Skip to content

chc.dynamics

Stability tier: stable.

Dynamics: the known mechanism, the learned residual, and their additive hybrid.

Dynamics

Bases: Protocol

A vector field f(t, x, u) -> dx/dt.

DampedOscillator

Bases: Module

Known 2-state linear system: a driven damped harmonic oscillator.

State x = [position, velocity], control u = [force]: ẍ + 2ζω ẋ + ω² x = u.

omega and zeta are kept as (dynamic) leaves so they can later be identified as physical parameters p rather than hard-coded.

LinearDynamics

Bases: Module

Known linear system ẋ = A x + B u; the exactly-integrable part used in splitting.

HybridDynamics

Bases: Module

f(x, u, t) = f_known(x, u, t) + r_θ(x, u, t).

The residual carries only the unknown part. With a ZeroResidual this reduces exactly to the known dynamics.

Fitting the residual by prediction error (chc.train) makes its control channel the observational response, which is the wrong object under a confounded logging policy; chc.dynamics_id.fit_causal_residual is the identified alternative, restricted to a control-affine residual.

DrivenDynamics

Bases: Module

f(t, x, u) + G w(t): a plant pushed by exogenous drivers whose path the plan can see.

levels[k] is the drivers' value at t = start + k * dt, and between two points they move linearly -- a first-order hold. A zero-order hold would not do: RK4's last stage of step k is the first of step k + 1, both at t = (k + 1) * dt, so no function of t alone can hold one level through a step. Past either end the nearest segment is extended, so a plan longer than the forecast extrapolates it; a horizon-step plan wants horizon + 1 levels.

The term reads neither x nor u. It moves the drift and never the control channel, so what is priced on the channel -- the barrier's gamma*, the tube's model error -- is left alone, and the forecast enters the barrier's drift term at every step.

drivers(t)

The drivers at time t, linear between the two grid points around it.