Reference
Base classes¶
The shared machinery (ParamSet, MetaStore, Trajectory,
SystemBase), the four family bases users subclass — ContinuousSystem
(ODEs), DelaySystem (DDEs), DiscreteMap (maps) and StochasticSystem
(diagonal-Itô SDEs) — and the System protocol the analysis toolkit is
written against.
ParamSet
¶
Bases: MutableMapping[str, Any]
Ordered, fixed-key parameter container.
Keys are frozen at construction time — you can change values but not add or
remove keys. Supports both dict-style (p["sigma"]) and attribute-style
(p.sigma) read/write.
| PARAMETER | DESCRIPTION |
|---|---|
data
|
Initial key→value mapping. All future writes must use existing keys.
TYPE:
|
| RAISES | DESCRIPTION |
|---|---|
AttributeError
|
On attribute-style read or write of an undeclared key
( |
KeyError
|
On item-style write of an undeclared key ( |
InvalidInputError
|
On any attempt to delete a key (the key set is frozen). |
Examples:
>>> p = ParamSet({"sigma": 10.0, "rho": 28.0})
>>> p.sigma
10.0
>>> p.sigma = 15.0
>>> p["sigma"]
15.0
>>> p.unknown = 5.0 # raises AttributeError
Source code in src/tsdynamics/families/base.py
as_tuple
¶
as_dict
¶
param_hash
¶
param_hash() -> int
Return a process-stable 64-bit integer hash of the current parameter values.
Uses MD5 over a JSON-serialised representation so the result is
reproducible across Python process restarts (unlike hash()).
The hash backs cache keys for per-system lowering / lambdify caches.
At 64 bits the birthday-paradox
collision probability reaches 50 % only around 2^32 ≈ 4·10⁹
distinct parameter sets, which is well beyond any realistic
parameter sweep. The previous 32-bit width hit the same threshold
at only 2^16 ≈ 65 000 sets, which a sufficiently large sweep
could plausibly reach — and a collision there would silently
return a compiled artifact built for a different parameter set.
Source code in src/tsdynamics/families/base.py
MetaStore
¶
Bases: MutableMapping[str, Any]
Append-with-history metadata store for computed results.
Behaves like a dict for everyday use (meta["lyapunov_spectrum"]
reads/writes the latest value), but every write is appended rather
than overwritten, so earlier results survive::
sys.meta.record("lyapunov_spectrum", spec, dt=0.1, final_time=200.0)
sys.meta["lyapunov_spectrum"] # latest value
sys.meta.history("lyapunov_spectrum") # every record, with context
Equality compares the latest values against a plain dict (or another
MetaStore), preserving sys.meta == {} style assertions.
Source code in src/tsdynamics/families/base.py
record
¶
Append value under key with optional context kwargs.
Each call stores a new record {"value", "context", "timestamp"} —
earlier records under the same key are preserved (retrievable with
:meth:history), and meta[key] returns the most recent value.
| PARAMETER | DESCRIPTION |
|---|---|
key
|
The result name (e.g.
TYPE:
|
value
|
The computed value to store.
TYPE:
|
**context
|
Free-form context recorded alongside the value (e.g.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Any
|
|
Source code in src/tsdynamics/families/base.py
history
¶
latest
¶
Trajectory
¶
The result of integrating or iterating a dynamical system.
Supports tuple-unpacking for backward compatibility::
t, y = system.integrate(final_time=100)
| ATTRIBUTE | DESCRIPTION |
|---|---|
t |
Time points (or step indices for discrete maps).
TYPE:
|
y |
State at each time point.
TYPE:
|
system |
Back-reference to the system that produced this trajectory.
TYPE:
|
meta |
Provenance: system name, params snapshot, solver, tolerances, ic.
TYPE:
|
Examples:
>>> traj = lor.integrate(final_time=100)
>>> traj.dim
3
>>> traj["x"] # named component (via the class's ``variables``)
array([...])
>>> traj.after(20.0) # drop transient
Trajectory(n_steps=..., dim=3, t=[20.0, 100.0])
>>> t, y = traj # tuple-unpack still works
Source code in src/tsdynamics/data/trajectory.py
variables
property
¶
Component names declared by the system (instance attr or class ClassVar).
component
¶
Return a single state component.
| PARAMETER | DESCRIPTION |
|---|---|
i
|
Component index, or component name when the system declares
|
| RETURNS | DESCRIPTION |
|---|---|
(ndarray, shape(T))
|
|
Source code in src/tsdynamics/data/trajectory.py
after
¶
after(t0: float) -> Trajectory
Drop the initial transient.
| PARAMETER | DESCRIPTION |
|---|---|
t0
|
Keep only time points
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Trajectory
|
|
Source code in src/tsdynamics/data/trajectory.py
to_plot_spec
¶
to_plot_spec(
kind: str | None = None,
*,
components: int
| str
| Sequence[int | str]
| None = None,
animate: bool | dict[str, Any] | Animation = False,
**kind_kw: Any,
) -> PlotSpec
Describe this trajectory as a backend-agnostic :class:PlotSpec.
This is the one front door for trajectory plotting — every common
view goes through here, so the parameterised viz.producers builders
stay an internal detail.
Auto-dispatch
With kind=None the semantic kind follows the number of selected
components (after applying components=): 1 → TIME_SERIES,
2 → PHASE_PORTRAIT_2D, 3 → PHASE_PORTRAIT_3D, and 4+ →
SPACETIME (a Lorenz-96-style field image, not a misleading
3-D portrait of the first three coordinates). A discrete-map orbit
draws with a SCATTER mark (a point sequence) rather than a line.
A Poincaré-section trajectory (carrying meta["plot_kind"] of
"poincare_section") is recognised and drawn as its in-plane
scatter.
Selecting components
components= picks what to draw — a name, an index, or a sequence
of them: components="x" (a single time series), components=
["y0", "y1", "y2"] (a 3-D portrait of three chosen channels). The
auto-dispatch then keys off how many you selected.
Overriding the kind
kind= forces any member of the closed
:class:~tsdynamics.viz.spec.PlotKind vocabulary — e.g.
kind="time_series" to overlay component-vs-time on a 3-D
trajectory, or kind="spacetime" to image it. The recipe
kind="delay" builds a delay-coordinate embedding x(t) vs
x(t - tau); pass tau (in time units) via **kind_kw.
Per-kind options (**kind_kw)
Options valid for one kind only are accepted as keywords rather than
cluttering the signature — tau (required for kind="delay",
converted from time units to samples via meta["dt"]),
color_by (time series / phase portraits — a named field
"time"/"speed"/"sagitta"/"curvature"/"acceleration"/
"arclength"/"index", a per-point array, or a callable
f(trajectory) -> array), transpose (spacetime). Passing one to
the wrong kind raises
:class:~tsdynamics.errors.InvalidParameterError.
The :mod:tsdynamics.viz import is local to this method (lazy), and the
spec carries no rendering code, so building a spec (or importing
:mod:tsdynamics) never imports matplotlib / Plotly.
| PARAMETER | DESCRIPTION |
|---|---|
kind
|
Override the auto-dispatched kind (a
TYPE:
|
components
|
Which state components to draw (names or indices).
TYPE:
|
animate
|
Turn the spec into a reveal animation. |
**kind_kw
|
Per-kind options (see above).
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
PlotSpec
|
|
Source code in src/tsdynamics/data/trajectory.py
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 | |
plot
¶
Render this trajectory via a visualization backend.
Sugar over :meth:to_plot_spec: the spec-shaping keywords (kind,
components, and the per-kind options tau / color_by /
transpose) are peeled off and passed to :meth:to_plot_spec; the
remaining keywords are inline spec tweaks (xlabel / yscale /
title / …) or backend keyword arguments (see
:meth:tsdynamics.viz.spec.Plottable.plot).
The viz package is imported lazily here (not at module scope) so plain
import tsdynamics never pulls it in — honouring the
no-backend-on-import contract. Raises
:class:~tsdynamics.viz.spec.VisualizationNotInstalled until a backend
is registered.
Source code in src/tsdynamics/data/trajectory.py
minmax
¶
standardize
¶
standardize() -> Trajectory
Return a copy with zero mean and unit standard deviation per component.
The applied transform is recorded in meta["standardized"].
Source code in src/tsdynamics/data/trajectory.py
neighbors
¶
Nearest trajectory points to query point(s) q.
Builds a KD-tree lazily on first call and caches it; subsequent queries are O(log T).
| PARAMETER | DESCRIPTION |
|---|---|
q
|
Query point(s). |
k
|
Number of neighbours per query point.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
(distances, indices)
|
As returned by :meth: |
Source code in src/tsdynamics/data/trajectory.py
set_distance
¶
Distance to another point set (Trajectory or array), as a set.
method is "centroid" (default), "hausdorff", or
"minimum" — see :func:tsdynamics.data.set_distance. The
matching primitive behind attractor deduplication and continuation.
Source code in src/tsdynamics/data/trajectory.py
SystemBase
¶
SystemBase(
params: dict[str, Any] | None = None,
ic: Any | None = None,
dim: int | None = None,
field_shape: tuple[int, ...] | None = None,
)
Bases: SystemPlottable
Abstract base class for all dynamical systems.
Provides:
- params — a :class:ParamSet holding the system's parameter values.
Attribute access on the system is transparently forwarded to params.
- dim — integer state-space dimension.
- ic — optional initial conditions array.
- meta — dict for storing computed metadata (Lyapunov spectra, etc.).
- copy() / with_params() for safe cloning.
- resolve_ic() for uniform IC resolution across subclasses.
Class-level declarations
Subclasses should declare at class level::
class Lorenz(ContinuousSystem):
params = {"sigma": 10.0, "rho": 28.0, "beta": 8/3}
dim = 3
Constructor overrides
Individual instances can override params and/or ic::
lor = Lorenz(params={"rho": 30.0}, ic=[1.0, 0.0, 0.0])
The constructor raises
:class:~tsdynamics.errors.InvalidParameterError (a ValueError
subclass) for any unknown parameter key, so a typo such as
params={"rhoo": 30.0} fails loudly instead of being silently ignored.
See Also
ParamSet : the fixed-key parameter container behind params.
MetaStore : the append-with-history store behind meta.
resolve_ic : the uniform initial-condition resolution helper.
Initialise a system from its class defaults plus instance overrides.
| PARAMETER | DESCRIPTION |
|---|---|
params
|
Per-instance parameter overrides. Every key must already exist in
the class-level :attr:
TYPE:
|
ic
|
Initial conditions. Stored on
TYPE:
|
dim
|
State-space dimension override for variable-dimension systems. Falls
back to the class-level :attr:
TYPE:
|
field_shape
|
Spatial grid shape override for a spatially-extended system (see
:attr:
TYPE:
|
| RAISES | DESCRIPTION |
|---|---|
InvalidParameterError
|
If |
Source code in src/tsdynamics/families/base.py
lyap
property
¶
lyap: Any
Lyapunov-exponent estimators bound to this system.
A cached :class:~tsdynamics.families._accessors.LyapunovAccessor
exposing .spectrum() / .maximal() / .from_data() — each
delegating to :func:tsdynamics.analysis.lyapunov_spectrum,
:func:~tsdynamics.analysis.max_lyapunov and
:func:~tsdynamics.analysis.lyapunov_from_data with this system bound.
chaos
property
¶
chaos: Any
Chaos indicators bound to this system.
A cached :class:~tsdynamics.families._accessors.ChaosAccessor exposing
.gali() / .expansion_entropy() / .zero_one() — delegating to
:func:tsdynamics.analysis.gali,
:func:~tsdynamics.analysis.expansion_entropy and
:func:~tsdynamics.analysis.zero_one_test.
dims
property
¶
dims: Any
Fractal-dimension estimators bound to this system.
A cached :class:~tsdynamics.families._accessors.DimensionsAccessor
(.correlation() / .generalized() / …) delegating to the
*_dimension free functions. These consume a point set; omitting the
data argument runs the system first (an implicit integration).
recurrence
property
¶
recurrence: Any
Recurrence-quantification estimators bound to this system.
A cached :class:~tsdynamics.families._accessors.RecurrenceAccessor
(.matrix() / .rqa() / .windowed()) delegating to
:func:tsdynamics.analysis.recurrence_matrix,
:func:~tsdynamics.analysis.rqa and
:func:~tsdynamics.analysis.windowed_rqa.
entropy
property
¶
entropy: Any
Entropy / complexity estimators bound to this system.
A cached :class:~tsdynamics.families._accessors.EntropyAccessor
(.permutation() / .sample() / …) delegating to the entropy free
functions. These consume a scalar series; omitting data runs the
system first.
surrogate
property
¶
surrogate: Any
Surrogate generators + nonlinearity tests bound to this system.
A cached :class:~tsdynamics.families._accessors.SurrogateAccessor
(.test() / .generate() / …) delegating to
:func:tsdynamics.analysis.surrogate_test,
:func:~tsdynamics.analysis.surrogates and the surrogate statistics.
copy
¶
copy() -> SystemBase
Return a deep copy with the same class, params, and ic.
The copy has its own independent params and meta stores, so
mutating the clone's parameters or recording metadata on it never
affects the original.
| RETURNS | DESCRIPTION |
|---|---|
SystemBase
|
A fresh instance of the same subclass with copied |
Source code in src/tsdynamics/families/base.py
with_params
¶
with_params(**overrides: Any) -> SystemBase
Return a new system with some parameters overridden.
Does not mutate self. Designed for parameter sweeps::
for rho in np.linspace(0, 50, 200):
traj = base_system.with_params(rho=rho).integrate(final_time=50)
| PARAMETER | DESCRIPTION |
|---|---|
**overrides
|
New parameter values. Keys must exist in
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
SystemBase
|
New instance of the same subclass. |
Source code in src/tsdynamics/families/base.py
resolve_ic
¶
Resolve initial conditions consistently.
Priority:
icargument (if provided)self.ic(set by a previous integration / iteration)type(self).default_ic(class-level default, if declared)- Random
U[0, 1)^dim
The resolved IC is stored in self.ic so subsequent calls without
an explicit ic reproduce the same initial state.
| PARAMETER | DESCRIPTION |
|---|---|
ic
|
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
(ndarray, shape(dim))
|
|
Source code in src/tsdynamics/families/base.py
fixed_points
¶
Find fixed points / equilibria of this system.
Delegates to :func:tsdynamics.analysis.fixed_points with this system
bound — returns the same list of
:class:~tsdynamics.analysis.FixedPoint.
Source code in src/tsdynamics/families/base.py
poincare
¶
poincare(
section: Any = None,
at: float = 0.0,
*,
plane: tuple[Any, ...] | None = None,
direction: int = +1,
**kwargs: Any,
) -> Any
Build a :class:~tsdynamics.derived.PoincareMap of this flow.
The friendly section= (a component index or name) + at= (the
crossing value) spelling is sugar over the wrapper's plane tuple; an
explicit plane=(normal, offset) may be passed instead for an
arbitrary-normal plane. Calling .run(...) (or .trajectory(...))
on the returned map collects crossings — the returned object is exactly
PoincareMap(self, plane, direction=...).
| PARAMETER | DESCRIPTION |
|---|---|
section
|
State component whose level set defines the section. A string is
resolved against the system's |
at
|
The crossing value for
TYPE:
|
plane
|
The raw
TYPE:
|
direction
|
Crossing direction (sign).
TYPE:
|
**kwargs
|
Forwarded to :class:
TYPE:
|
Source code in src/tsdynamics/families/base.py
stroboscope
¶
Build a :class:~tsdynamics.derived.StroboscopicMap of this forced flow.
When period is omitted the forcing period is inferred from the
system — from a forcing_period / drive_period hook (used
verbatim) or a drive_frequency / omega hook (taken as the
angular drive frequency, so the period is 2*pi / omega). The
catalogue's forced systems (e.g. :class:~tsdynamics.systems.Duffing,
whose autonomising phase obeys zdot = omega) follow the omega
convention, so ForcedDuffing().stroboscope() just works. Pass
period= to override the inference (or when no drive hook exists).
Equivalent to StroboscopicMap(self, period).
| PARAMETER | DESCRIPTION |
|---|---|
period
|
The forcing period. When
TYPE:
|
**kwargs
|
Forwarded to :class:
TYPE:
|
| RAISES | DESCRIPTION |
|---|---|
InvalidParameterError
|
When |
Source code in src/tsdynamics/families/base.py
tangent
¶
Build a :class:~tsdynamics.derived.TangentSystem (state plus k deviation vectors).
Equivalent to TangentSystem(self, k, ...) — the Lyapunov engine.
Source code in src/tsdynamics/families/base.py
project
¶
Build a :class:~tsdynamics.derived.ProjectedSystem onto components.
Accepts component indices or names (resolved against variables), as
positional arguments (self.project("x", "z")) or a single sequence
(self.project(["x", "z"])). Equivalent to
ProjectedSystem(self, components).
Source code in src/tsdynamics/families/base.py
ensemble
¶
Build an :class:~tsdynamics.derived.EnsembleSystem over states.
Equivalent to EnsembleSystem(self, states) — many copies stepped in
lockstep.
Source code in src/tsdynamics/families/base.py
ContinuousSystem
¶
ContinuousSystem(
params: dict[str, Any] | None = None,
ic: Any | None = None,
dim: int | None = None,
field_shape: tuple[int, ...] | None = None,
)
Bases: SystemBase, ABC
Base class for ODE-based dynamical systems, integrated on the engine.
Subclass contract
- Declare
params = {...}anddim = Nat class level. - Implement
_equationsas a@staticmethodreturning a length-dimsequence of SymEngine symbolic expressions. - Optionally mark integer or loop-structural parameters in
_structural_params— these are baked into the lowered tape rather than exposed as runtime control parameters.
Lowering
Each system is lowered once to an in-process IR tape with no warmup; the engine reads non-structural parameters live from the system on every run, so a parameter change never triggers a re-lowering.
Class-level attributes
_structural_params : frozenset[str]
Parameter names that appear as integer loop bounds or affect the
symbolic structure of _equations. These are baked in at compile
time. For most systems this is empty (the default).
Example — Lorenz96 uses ``N`` to build the list comprehension::
_structural_params = frozenset({"N"})
_default_method : str
Default integrator name (default "RK45").
Examples:
>>> lor = Lorenz()
>>> traj = lor.integrate(final_time=100, dt=0.01)
>>> t, y = traj # tuple-unpack
>>> lor.sigma = 15.0 # change param — zero recompile cost
>>> traj2 = lor.integrate(final_time=100)
Source code in src/tsdynamics/families/base.py
reinit
¶
reinit(
u: Any | None = None,
*,
t: float | None = None,
params: dict[str, Any] | None = None,
method: str | None = None,
rtol: float = 1e-06,
atol: float = 1e-09,
backend: str | None = None,
) -> None
(Re)start the incremental stepper from state u at time t.
| PARAMETER | DESCRIPTION |
|---|---|
u
|
Initial state (falls back to
TYPE:
|
t
|
Start time (default 0.0).
TYPE:
|
params
|
Parameter overrides applied (in place) before restarting.
TYPE:
|
method
|
Stepper configuration, as in :meth:
TYPE:
|
rtol
|
Stepper configuration, as in :meth:
TYPE:
|
atol
|
Stepper configuration, as in :meth:
TYPE:
|
backend
|
Stepper configuration, as in :meth:
TYPE:
|
Source code in src/tsdynamics/families/continuous.py
344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 | |
step
¶
Advance the system by dt (default 0.01) and return the new state.
The first call performs an implicit :meth:reinit. Parameter changes
made after reinit take effect on the next reinit, not on a
live stepper.
Notes
Each call advances exactly one dt from the live (state, t),
returning byte-for-byte the trajectory the released per-dt path
produced — there is no batching, so the numbers are unchanged for every
method, adaptive or fixed-step (streams WS-STEPBUF, WS-INVHOIST,
WS-STEPPER). The amortisation is durable: the first step after a
:meth:reinit builds an opaque resumable engine handle
(:class:tsdynamics._rust.OdeStepper, via
:func:~tsdynamics.engine.run.make_ode_stepper) that owns the built tape
evaluator + solver once and carries the live (u, t) across calls; every
later step is one :func:~tsdynamics.engine.run.step_advance on that
handle — the tape is never re-marshalled into the engine again. So a
constant-dt stepping loop (Poincaré refinement, basins over flows) skips
not only the solver-registry resolve, the implicit-Jacobian decision, the
output-grid build, provenance assembly and the :class:Trajectory wrap that
the full :meth:integrate entry point pays, but also the per-step tape
re-marshalling and tape rebuild the pre-handle stepping core paid. The
control-parameter vector is still read live each step, so the live-stepper
semantics are unchanged.
Why this stays answer-exact: the engine handle's advance(dt) re-seeds a
fresh solver and state for each dt segment (the adaptive controller is
re-seeded each step, exactly as the released per-dt integrate_dense
did), so the numbers are bit-for-bit identical to that path — verified in
the engine's own test. A batch-ahead variant that integrated a whole chunk
in one engine call was rejected (WS-STEPBUF): a chunked adaptive integration
is not equal to N single-dt integrations (the controller would carry
its step/error state across output nodes), which silently corrupted
sensitive consumers such as max_lyapunov. The durable handle amortises
the build/marshalling, never the numerics.
Source code in src/tsdynamics/families/continuous.py
434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 | |
state
¶
state() -> ndarray
Return a copy of the current state (implicit reinit if cold).
Source code in src/tsdynamics/families/continuous.py
set_state
¶
set_state(u: Any) -> None
Overwrite the current state without changing the current time.
Source code in src/tsdynamics/families/continuous.py
trajectory
¶
trajectory(
final_time: float = 100.0,
*,
dt: float = 0.02,
transient: float = 0.0,
**kwargs: Any,
) -> Trajectory
Protocol-uniform trajectory: integrate plus optional transient drop.
Source code in src/tsdynamics/families/continuous.py
jacobian_sym
¶
Return the symbolic Jacobian of _equations, differentiated by SymEngine.
Rows are d f_i / d y(j) for the current structural parameters;
non-structural parameters appear as symbols. Hand-written
_jacobian methods on system classes are never used at runtime —
this autogenerated form is the single source of truth (the test suite
cross-checks hand-written ones against it).
| RETURNS | DESCRIPTION |
|---|---|
list of ``dim`` rows, each a list of ``dim`` SymEngine expressions.
|
|
Source code in src/tsdynamics/families/continuous.py
jacobian
¶
Evaluate the (autogenerated) Jacobian numerically at state u.
| PARAMETER | DESCRIPTION |
|---|---|
u
|
State at which to evaluate.
TYPE:
|
t
|
Time (matters only for non-autonomous systems).
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
(ndarray, shape(dim, dim))
|
|
Source code in src/tsdynamics/families/continuous.py
run
¶
run(
final_time: float = 100.0,
dt: float = 0.02,
*,
events: Any = None,
**kwargs: Any,
) -> Trajectory
Produce a trajectory — the one canonical verb for every family.
run is the unified trajectory producer: it answers the same call for
flows, maps, DDEs and SDEs, dispatching on :attr:is_discrete. For a
continuous-time system (this family) it integrates the flow, so
run is a thin alias of :meth:integrate and forwards every keyword
to it unchanged.
| PARAMETER | DESCRIPTION |
|---|---|
final_time
|
End of the integration window. Default 100.0.
TYPE:
|
dt
|
Output sampling interval. The internal stepper is adaptive.
TYPE:
|
events
|
Detect events along the flow (a SciPy-shaped
TYPE:
|
**kwargs
|
Forwarded verbatim to :meth:
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Trajectory
|
Identical to :meth: |
See Also
integrate : The family-specific spelling (a permanent alias of run).
Examples:
>>> traj = Lorenz().run(final_time=100, dt=0.01)
>>> Henon().run(n=5000) # the same verb iterates a map
>>> sol = Lorenz().run(final_time=50, events=[("z", 27.0, "up")])
>>> sol.meta["t_events"][0].shape # times z=27 was crossed upward
(... ,)
Source code in src/tsdynamics/families/continuous.py
integrate
¶
integrate(
final_time: float = 100.0,
dt: float = 0.02,
*,
t0: float = 0.0,
ic: Any | None = None,
method: str | None = None,
rtol: float = 1e-06,
atol: float = 1e-09,
backend: str | None = None,
events: Any = None,
**integrator_kwargs: Any,
) -> Trajectory
Integrate the ODE and return a :class:~tsdynamics.families.Trajectory.
| PARAMETER | DESCRIPTION |
|---|---|
final_time
|
End of integration window. Default 100.0.
TYPE:
|
dt
|
Output sampling interval. The internal stepper is adaptive.
TYPE:
|
t0
|
Start time. Default 0.0. Allows warm restarts from a non-zero
time (the IC is interpreted as the state at
TYPE:
|
ic
|
Initial state at
TYPE:
|
method
|
Solver name, resolved by the solver registry (default
TYPE:
|
rtol
|
Solver tolerances (default 1e-6 / 1e-9).
TYPE:
|
atol
|
Solver tolerances (default 1e-6 / 1e-9).
TYPE:
|
backend
|
Where the ODE is integrated. Defaults to
TYPE:
|
events
|
Detect events along the flow (the SciPy-shaped
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Trajectory
|
Supports tuple-unpacking: |
Source code in src/tsdynamics/families/continuous.py
915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 | |
lyapunov_spectrum
¶
lyapunov_spectrum(
final_time: float = 200.0,
dt: float = 0.1,
*,
ic: Any | None = None,
n_exp: int | None = None,
burn_in: float = 50.0,
method: str | None = None,
rtol: float = 1e-06,
atol: float = 1e-09,
backend: str = "interp",
**integrator_kwargs: Any,
) -> ndarray
Estimate the Lyapunov spectrum of the flow.
Delegates to :class:~tsdynamics.derived.tangent.TangentSystem, the one
backend-neutral variational/Lyapunov engine shared across families: the
extended variational ODE (state ⊕ k tangent vectors) is integrated
on the chosen backend per dt-chunk and QR-reorthonormalised. The
Benettin time-averaging of the log-stretch rates follows the classical
construction of Benettin et al. [1]_.
Results are stored in self.meta['lyapunov_spectrum'].
| PARAMETER | DESCRIPTION |
|---|---|
final_time
|
Averaging window length after burn-in. Default 200.0.
TYPE:
|
dt
|
Sampling interval for local exponent accumulation. Default 0.1.
TYPE:
|
ic
|
Initial state. Falls back to
TYPE:
|
n_exp
|
Number of exponents. Defaults to
TYPE:
|
burn_in
|
Discard this much time before averaging. Default 50.0.
TYPE:
|
method
|
Integrator (default
TYPE:
|
rtol
|
Tolerances.
TYPE:
|
atol
|
Tolerances.
TYPE:
|
backend
|
Backend on which the extended variational ODE is integrated.
Defaults to
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
(ndarray, shape(n_exp))
|
Lyapunov exponents ordered from largest to smallest. |
| RAISES | DESCRIPTION |
|---|---|
InvalidParameterError
|
If |
References
.. [1] G. Benettin, L. Galgani, A. Giorgilli, and J.-M. Strelcyn, "Lyapunov characteristic exponents for smooth dynamical systems and for Hamiltonian systems; a method for computing all of them," Meccanica 15, 9-30 (1980).
Source code in src/tsdynamics/families/continuous.py
1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 | |
DelaySystem
¶
DelaySystem(
params: dict[str, Any] | None = None,
ic: Any | None = None,
dim: int | None = None,
field_shape: tuple[int, ...] | None = None,
)
Bases: SystemBase, ABC
Base class for delay differential systems (DDEs), integrated on the engine.
Subclass contract
- Declare
params = {...}anddim = N. - Implement
_equationsas a@staticmethodreturning a length-dimsequence of SymEngine symbolic expressions. Usey(i, t - tau)for delayed state access.
Lowering
Each system is lowered once to an in-process IR tape with no warmup. Delay values directly affect the history-buffer structure, so they are baked into the tape rather than read live like the other parameters; a delay change re-lowers, while ordinary parameters are read live with no re-lowering.
DDEs typically need looser tolerances than ODEs (start with rtol=atol=1e-3).
History
Pass a history callable h(s) → sequence defining the past for
s ≤ 0. If omitted, a constant past equal to ic is used.
.. note::
Provide a non-equilibrium history to avoid trivial Lyapunov exponents.
lyapunov_spectrum starts from a constant past, so the workaround is
to run integrate first with the desired history, then pass the
end-state as ic to lyapunov_spectrum.
Examples:
>>> mg = MackeyGlass()
>>> hist = lambda s: [1.0 + 0.1 * np.sin(0.2 * s)]
>>> traj = mg.integrate(final_time=500, history=hist)
>>> exps = mg.lyapunov_spectrum(n_exp=2, ic=traj.y[-1])
Source code in src/tsdynamics/families/base.py
reinit
¶
reinit(
u: Any | None = None,
*,
t: float | None = None,
params: dict[str, Any] | None = None,
rtol: float | None = None,
atol: float | None = None,
**kwargs: Any,
) -> None
(Re)start the incremental stepper from a constant past equal to u.
DDE state is a history function; the protocol restart uses a
constant past (the same convention as lyapunov_spectrum). For a
custom history, use :meth:integrate with history= and continue
from traj.y[-1].
Stepping is forward-only and re-integrates from the constant past on the
Rust DDE engine each call (the method of steps has no stateful one-step
restart), so it is correct but O(steps²) — use :meth:integrate for
a full trajectory.
Source code in src/tsdynamics/families/delay.py
step
¶
Advance by dt (default 0.1, forward-only) and return the new state.
Source code in src/tsdynamics/families/delay.py
set_state
¶
set_state(u: Any) -> None
Not available for DDEs — their state is a whole history function.
Source code in src/tsdynamics/families/delay.py
trajectory
¶
trajectory(
final_time: float = 100.0,
*,
dt: float = 0.02,
transient: float = 0.0,
**kwargs: Any,
) -> Trajectory
Protocol-uniform trajectory: integrate plus optional transient drop.
Source code in src/tsdynamics/families/delay.py
run
¶
run(
final_time: float = 100.0,
dt: float = 0.02,
**kwargs: Any,
) -> Trajectory
Produce a trajectory — the one canonical verb for every family.
run is the unified trajectory producer: it answers the same call for
flows, maps, DDEs and SDEs, dispatching on :attr:is_discrete. For a
delay system (this family) it integrates the DDE, so run is a thin
alias of :meth:integrate and forwards every keyword to it unchanged.
| PARAMETER | DESCRIPTION |
|---|---|
final_time
|
Integration end time. Default 100.0.
TYPE:
|
dt
|
Output sampling interval.
TYPE:
|
**kwargs
|
Forwarded verbatim to :meth:
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Trajectory
|
Identical to :meth: |
See Also
integrate : The family-specific spelling (a permanent alias of run).
Source code in src/tsdynamics/families/delay.py
integrate
¶
integrate(
final_time: float = 100.0,
dt: float = 0.02,
*,
ic: Any | None = None,
history: History = None,
rtol: float | None = None,
atol: float | None = None,
backend: str | None = None,
method: str = "rk45",
**kwargs: Any,
) -> Trajectory
Integrate the DDE and return a :class:~tsdynamics.families.Trajectory.
| PARAMETER | DESCRIPTION |
|---|---|
final_time
|
Integration end time. Default 100.0.
TYPE:
|
dt
|
Output sampling interval.
TYPE:
|
ic
|
Used for constant past when
TYPE:
|
history
|
TYPE:
|
rtol
|
Integration tolerances. DDEs typically need 1e-3; very tight tolerances can stall the solver.
TYPE:
|
atol
|
Integration tolerances. DDEs typically need 1e-3; very tight tolerances can stall the solver.
TYPE:
|
backend
|
Which engine integrates the DDE. Defaults to
TYPE:
|
method
|
The explicit kernel (
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Trajectory
|
|
Source code in src/tsdynamics/families/delay.py
lyapunov_spectrum
¶
lyapunov_spectrum(
final_time: float = 200.0,
dt: float = 0.1,
*,
ic: Any | None = None,
n_exp: int = 1,
burn_in: float = 50.0,
rtol: float | None = None,
atol: float | None = None,
backend: str | None = None,
**kwargs: Any,
) -> ndarray
Estimate the n_exp leading Lyapunov exponents of the delay system.
The engine estimator (stream E-DDE-LYAP, result stored in
self.meta['lyapunov_spectrum']) integrates the extended variational
DDE on the Rust engine with a function-space Benettin renormalisation
(:func:tsdynamics.families._dde_lyapunov.dde_lyapunov_spectrum):
backend="interp" / "jit". "reference" is rejected (the engine
has no pure-Python DDE integrator).
| PARAMETER | DESCRIPTION |
|---|---|
final_time
|
Averaging window after burn-in. Default 200.0.
TYPE:
|
dt
|
Sampling interval (should divide the maximum delay).
TYPE:
|
ic
|
Initial state. Provide the end-state of a prior
TYPE:
|
n_exp
|
Number of leading exponents to estimate. DDEs have infinitely many; choose consciously. Default 1.
TYPE:
|
burn_in
|
Discard interval. Default 50.0.
TYPE:
|
rtol
|
Integration tolerances. The engine path renormalises every delay
window and uses defaults of
TYPE:
|
atol
|
Integration tolerances. The engine path renormalises every delay
window and uses defaults of
TYPE:
|
backend
|
TYPE:
|
Notes
For best results, pass ic=traj.y[-1] from a prior integrate run —
this places the trajectory on the attractor and avoids trivial exponents
from equilibrium pasts.
| RETURNS | DESCRIPTION |
|---|---|
(ndarray, shape(n_exp))
|
|
Source code in src/tsdynamics/families/delay.py
444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 | |
DiscreteMap
¶
DiscreteMap(
params: dict[str, Any] | None = None,
ic: Any | None = None,
dim: int | None = None,
field_shape: tuple[int, ...] | None = None,
)
Bases: SystemBase
Base class for discrete maps iterated on the engine.
Subclass contract
- Declare
params = {...}anddim = N. - Implement
_stepand_jacobianas@staticmethodstatic methods. Parameters arrive as positional arguments in the order they appear in the class-levelparamsdict.
Iteration
iterate lowers _step to an in-process IR tape and runs the engine's
native map loop, with no warmup. The engine reads the current parameter
values live on every run, so a parameter change never triggers a
re-lowering.
Lyapunov spectrum
Computed in a single forward pass via QR decomposition of the Jacobian product — no redundant second iteration over the trajectory.
Examples:
>>> h = Henon()
>>> traj = h.iterate(steps=10_000)
>>> t_idx, X = traj # tuple-unpack
>>> exps = h.lyapunov_spectrum(steps=5_000)
>>> h_variant = h.with_params(a=1.2)
>>> traj2 = h_variant.iterate(steps=10_000)
Source code in src/tsdynamics/families/base.py
reinit
¶
reinit(
u: Any | None = None,
*,
t: float | None = None,
params: dict[str, Any] | None = None,
) -> None
(Re)start stepping from state u at iteration count t.
Source code in src/tsdynamics/families/discrete.py
step
¶
Advance n iterations and return the new state.
The first call performs an implicit :meth:reinit.
| PARAMETER | DESCRIPTION |
|---|---|
n_or_dt
|
Number of iterations to advance (default 1). Must be a positive whole number — a discrete map has no notion of a fractional step.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
(ndarray, shape(dim))
|
A copy of the state after |
| RAISES | DESCRIPTION |
|---|---|
InvalidParameterError
|
If |
ConvergenceError
|
If the orbit diverges to a non-finite state within the |
Source code in src/tsdynamics/families/discrete.py
trajectory
¶
trajectory(
steps: int = 1000, *, transient: int = 0, **kwargs: Any
) -> Trajectory
Protocol-uniform trajectory: iterate plus optional transient drop.
Source code in src/tsdynamics/families/discrete.py
run
¶
run(n: int = 1000, **kwargs: Any) -> Trajectory
Produce a trajectory — the one canonical verb for every family.
run is the unified trajectory producer: it answers the same call for
flows, maps, DDEs and SDEs, dispatching on :attr:is_discrete. For a
discrete map (this family) it iterates the map, so run is a thin
alias of :meth:iterate. The number of iterations is named n (the
canonical step-count keyword), forwarded to :meth:iterate as its
steps argument; every other keyword is forwarded unchanged.
| PARAMETER | DESCRIPTION |
|---|---|
n
|
Number of iterations. Default 1000.
TYPE:
|
**kwargs
|
Forwarded verbatim to :meth:
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Trajectory
|
Identical to :meth: |
See Also
iterate : The family-specific spelling (a permanent alias of run).
Examples:
Source code in src/tsdynamics/families/discrete.py
iterate
¶
iterate(
steps: int = 1000,
ic: Any | None = None,
max_retries: int = 10,
*,
backend: str | None = None,
) -> Trajectory
Iterate the map for steps steps on the engine.
| PARAMETER | DESCRIPTION |
|---|---|
steps
|
Number of iterations. Default 1000.
TYPE:
|
ic
|
Initial state. Falls back to
TYPE:
|
max_retries
|
Retry with a new random IC if divergence is detected (only when no
explicit
TYPE:
|
backend
|
Where the iteration runs. Defaults to
Every backend lowers
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Trajectory
|
|
| RAISES | DESCRIPTION |
|---|---|
ConvergenceError
|
If an explicit |
EngineNotAvailableError
|
If a Rust-engine backend ( |
TapeCompileError
|
If |
Source code in src/tsdynamics/families/discrete.py
350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 | |
lyapunov_spectrum
¶
lyapunov_spectrum(
steps: int = 5000,
ic: Any | None = None,
n_exp: int | None = None,
reortho_interval: int = 1,
*,
backend: str | None = None,
) -> ndarray
QR-based Lyapunov spectrum.
Delegates to :class:~tsdynamics.derived.tangent.TangentSystem, the one
backend-neutral variational/Lyapunov engine shared across families — a
single forward pass evaluating the Jacobian alongside the trajectory,
QR-reorthonormalising every reortho_interval steps, with a random-IC
retry on divergence.
On the compiled-engine backends ("interp" default / "jit") the whole
QR tangent-map iteration runs in one Rust kernel call
(:func:tsdynamics.engine.run.map_lyapunov) — no per-step Python→FFI
round-trip, so it is dramatically faster than the per-step NumPy loop.
backend="reference" (and any map whose _step will not lower to the
engine IR, or a wheel-free environment) runs the pure-Python QR loop — the
oracle the engine is validated against.
Results are stored in self.meta['lyapunov_spectrum'].
| PARAMETER | DESCRIPTION |
|---|---|
steps
|
Number of iterations. Default 5000.
TYPE:
|
ic
|
Initial state. Falls back to
TYPE:
|
n_exp
|
Number of exponents. Defaults to
TYPE:
|
reortho_interval
|
Reorthonormalise every this many steps. Default 1.
TYPE:
|
backend
|
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
(ndarray, shape(n_exp))
|
Lyapunov exponents ordered from largest to smallest. |
References
.. [1] G. Benettin, L. Galgani, A. Giorgilli, and J.-M. Strelcyn, "Lyapunov characteristic exponents for smooth dynamical systems and for Hamiltonian systems; a method for computing all of them," Meccanica 15, 9-30 (1980).
Source code in src/tsdynamics/families/discrete.py
StochasticSystem
¶
StochasticSystem(
params: dict[str, Any] | None = None,
ic: Any | None = None,
dim: int | None = None,
field_shape: tuple[int, ...] | None = None,
)
Bases: SystemBase, ABC
Base class for diagonal-Itô stochastic differential equations.
Subclass contract
- Declare
params = {...}anddim = Nat class level. -
Implement
_driftand_diffusionas@staticmethods, each returning a length-dimsequence of SymEngine symbolic expressions (usey(i)for componentiandtfor time — no NumPy, nomath, no Pythonif): -
_drift(y, t, **params)is the deterministic partf; -
_diffusion(y, t, **params)is the per-component diagonal noise coefficientg(sodX_k = f_k dt + g_k dW_k). -
Optionally mark integer / loop-structural parameters in
_structural_params(baked in at lowering time, like the ODE family).
Example
Geometric Brownian motion dX = μX dt + σX dW::
class GeometricBrownianMotion(StochasticSystem):
params = {"mu": 0.1, "sigma": 0.3}
dim = 1
variables = ("x",)
@staticmethod
def _drift(y, t, mu, sigma):
return [mu * y(0)]
@staticmethod
def _diffusion(y, t, mu, sigma):
return [sigma * y(0)]
gbm = GeometricBrownianMotion()
traj = gbm.integrate(final_time=1.0, dt=0.01, ic=[1.0], seed=0)
Notes
Integration uses a fixed step (the step is the noise scale √dt).
method selects "euler_maruyama" (default, order 0.5) or "milstein"
(order 1.0). Pass seed for a reproducible noise realisation; the resolved
seed is recorded in the trajectory's meta.
Source code in src/tsdynamics/families/base.py
reinit
¶
reinit(
u: Any | None = None,
*,
t: float | None = None,
params: dict[str, Any] | None = None,
method: str | None = None,
seed: int | None = None,
dt: float | None = None,
) -> None
(Re)start the incremental stepper from state u at time t.
| PARAMETER | DESCRIPTION |
|---|---|
u
|
Initial state (falls back to
TYPE:
|
t
|
Start time (default 0.0).
TYPE:
|
params
|
Parameter overrides applied (in place) before restarting.
TYPE:
|
method
|
TYPE:
|
seed
|
Seed for the noise stream (random if omitted) — set it for a reproducible path.
TYPE:
|
dt
|
Default step size for :meth:
TYPE:
|
Source code in src/tsdynamics/families/stochastic.py
step
¶
Advance by dt (default 0.01) and return the new state.
The first call performs an implicit :meth:reinit. Each call draws a
fresh diagonal Wiener increment from the stepper's seeded stream, so
repeated stepping traces one reproducible sample path.
Source code in src/tsdynamics/families/stochastic.py
set_state
¶
set_state(u: Any) -> None
Overwrite the current state without changing the current time.
Unlike a DDE (whose state is a whole history function), an SDE's state is
a single Markovian point, so set_state is well-defined.
Source code in src/tsdynamics/families/stochastic.py
trajectory
¶
trajectory(
final_time: float = 100.0,
*,
dt: float = 0.02,
transient: float = 0.0,
**kwargs: Any,
) -> Trajectory
Protocol-uniform trajectory: integrate plus optional transient drop.
Source code in src/tsdynamics/families/stochastic.py
run
¶
run(
final_time: float = 100.0,
dt: float = 0.02,
**kwargs: Any,
) -> Trajectory
Produce a trajectory — the one canonical verb for every family.
run is the unified trajectory producer: it answers the same call for
flows, maps, DDEs and SDEs, dispatching on :attr:is_discrete. For a
stochastic system (this family) it integrates the SDE, so run is a
thin alias of :meth:integrate and forwards every keyword to it
unchanged.
| PARAMETER | DESCRIPTION |
|---|---|
final_time
|
End of the integration window. Default 100.0.
TYPE:
|
dt
|
Fixed step size and output sampling interval (for an SDE the step is the noise scale).
TYPE:
|
**kwargs
|
Forwarded verbatim to :meth:
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Trajectory
|
Identical to :meth: |
See Also
integrate : The family-specific spelling (a permanent alias of run).
Source code in src/tsdynamics/families/stochastic.py
integrate
¶
integrate(
final_time: float = 100.0,
dt: float = 0.02,
*,
t0: float = 0.0,
ic: Any | None = None,
method: str | None = None,
seed: int | None = None,
backend: str | None = None,
) -> Trajectory
Integrate the SDE and return a :class:~tsdynamics.families.Trajectory.
| PARAMETER | DESCRIPTION |
|---|---|
final_time
|
End of the integration window.
TYPE:
|
dt
|
Fixed step size and output sampling interval — for an SDE the step
is the noise scale (each increment is drawn
TYPE:
|
t0
|
Start time (the IC is the state at
TYPE:
|
ic
|
Initial state. Falls back to
TYPE:
|
method
|
TYPE:
|
seed
|
Seed for the noise realisation (random if omitted). The resolved seed
is recorded in .. note::
TYPE:
|
backend
|
Defaults to
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Trajectory
|
Supports tuple-unpacking: |
Source code in src/tsdynamics/families/stochastic.py
505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 | |
ensemble
¶
ensemble(
ics: Any,
*,
final_time: float = 100.0,
dt: float = 0.02,
t0: float = 0.0,
method: str | None = None,
seed: int | None = None,
backend: str | None = None,
) -> ndarray
Integrate a batch of initial conditions and return their final states.
ics is (n, dim); each row is integrated from t0 to
final_time and its final state returned as a row of the (n, dim)
result. Trajectory i draws its noise from a stream seeded with
seed_for(seed, i) — depending only on the index — so the batch is
reproducible and matches the compiled engine's per-index seeding
(the parallel-equals-serial contract). A diverging trajectory yields a
row of NaN rather than aborting the batch.
.. note::
Because every trajectory is seeded by index, ensemble([ic], seed=s)
draws from seed_for(s, 0), which differs from the raw seed s
used by integrate(seed=s). The two calls therefore trace different
sample paths for the same s — by design (the index seeding is what
makes a batch reproducible and parallel-safe).
| PARAMETER | DESCRIPTION |
|---|---|
ics
|
The batch of initial conditions.
TYPE:
|
final_time
|
As in :meth:
TYPE:
|
dt
|
As in :meth:
TYPE:
|
t0
|
As in :meth:
TYPE:
|
method
|
As in :meth:
TYPE:
|
seed
|
As in :meth:
TYPE:
|
backend
|
Defaults to
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
(ndarray, shape(n, dim))
|
Final states (rows of |
Source code in src/tsdynamics/families/stochastic.py
598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 | |
System
¶
Bases: Protocol
Structural type for steppable dynamical systems.
is_discrete
property
¶
is_discrete: bool
True for iterated maps (and map-like wrappers such as Poincaré maps).
step
¶
Advance the system and return the new state.
The argument is the number of iterations for a discrete map and the time
increment dt for a continuous flow (each family supplies a sensible
default when None). Calling step on a fresh system performs an
implicit :meth:reinit first.
| RETURNS | DESCRIPTION |
|---|---|
ndarray
|
The state after advancing. |
Source code in src/tsdynamics/families/protocol.py
state
¶
state() -> ndarray
Return a copy of the current state vector.
Calling state on a fresh system performs an implicit :meth:reinit
first. The returned array is a copy, so mutating it never disturbs the
live stepper.
Source code in src/tsdynamics/families/protocol.py
set_state
¶
set_state(u: Any) -> None
Overwrite the current state.
Not available for delay systems — a DDE's state is a whole history
function, not a point, so its implementation raises
NotImplementedError; use :meth:reinit to restart from a constant
past instead.
Source code in src/tsdynamics/families/protocol.py
reinit
¶
reinit(
u: Any | None = None,
*,
t: float | None = None,
params: dict[str, Any] | None = None,
) -> None
Restart the stepper from state u at time t.
trajectory
¶
trajectory(*args: Any, **kwargs: Any) -> Trajectory
Produce a trajectory on a uniform output grid (the alias of :meth:run).
.. note::
run is the canonical trajectory-producer verb (see the module
docstring), but trajectory is the member the structural
protocol requires: every family and wrapper implements it, whereas a
few (WrappedSystem and the derived wrappers) expose only
trajectory — not run — so requiring run here would make
them fail isinstance(obj, System). Code written against
System should call trajectory; code holding a concrete flow
or map should prefer run.