Part of World Models Handbook
Differentiable simulators, graph networks, neural ODEs, and operator learning add physical structure to world models for efficient data use and planning.
Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.
Article links
Make inline references clickable
Structured Simulators and Neural Operators
Suppose you are building a world model for a floating robot arm in a turbulent fluid. An unconstrained sequence model might learn to predict the next frame from video, but it may require substantial task data, can fail under distribution shift, and provides no architectural guarantee of momentum conservation or finite-speed propagation. Regularities such as angular-momentum balance and delayed pressure-wave propagation must then be inferred from observations. If you can instead encode rigid-body equations for the arm, Navier–Stokes equations for the fluid, and their coupling, valid structure can improve data efficiency, extrapolation, and interpretability. The tradeoff is that an authored model cannot represent an omitted effect by itself. Classical solvers may expose analytic, automatic, adjoint, or finite-difference sensitivities, but a solver that provides only forward outputs does not directly supply the derivatives needed for learning and planning.
This chapter is about the middle ground. We study four families of methods that inject physical structure into world models while keeping them learnable:
- Differentiable simulators: hand-built physics engines whose outputs can be backpropagated through, so the same machinery that trains neural networks can identify parameters and optimize plans. The physics is authored by hand; learning touches the parameters, the plans, and any neural components bolted on top.
- Graph-based physical models: learned dynamics whose architecture mirrors the fact that physical influence is local and relational, built from interactions between neighboring entities. The existence of an interaction law is assumed; its form is learned.
- Neural differential equations: neural networks that define a continuous-time vector field, so learned dynamics can be integrated, analyzed, and constrained with the tools of dynamical systems. The existence of smooth continuous-time flow is assumed; the flow itself is learned.
- Operator learning: neural architectures whose inputs and outputs are entire fields, learning maps from functions to functions for PDE-governed worlds like fluids, weather, and heat. The function-space character of the problem is assumed; the solution operator is learned.
These four families form a spectrum from "physics written by hand, learning only parameters" to "physics learned end to end, structure only in the architecture." Each step along that spectrum trades one kind of prior knowledge for another: the differentiable simulator assumes the equations, the graph model assumes locality and shared interaction laws, the neural ODE assumes a sufficiently regular continuous-time flow, and the operator network represents fields while still encoding architectural priors such as bases, kernels, geometry, and local or nonlocal coupling. Where you sit on that spectrum is one of the most consequential design decisions in a physical world model, and the right answer depends on how much data you have, how well you know the physics, and whether the model will be used to predict or to act. A model that only needs to forecast can tolerate structural compromises that a model used for planning cannot, because a planner can exploit inaccuracies that are reachable under its actions and favorable to its objective; not every inconsistency is reachable or useful.
Why Structure Belongs in a World Model
Throughout Part I we argued that a world model is a learned surrogate for the environment's transition dynamics. Part III showed that the representation of state matters enormously: object-centric and relational state (Part III, Chapter 5) made latents more controllable and composable. This chapter makes the complementary point about the dynamics: the function that advances state through time can itself carry structure, and that structure is a form of prior knowledge you can spend instead of data. The two ideas compose rather than compete. A well-structured state makes the transition easier to learn; a well-structured transition makes the state representation's structure pay off, because compositional state is only useful if the dynamics respect that composition. An object-centric latent whose dynamics are a dense matrix over the flattened vector quietly destroys the decomposition the representation worked so hard to find.
The physical world has strong regularities that a generic function approximator must rediscover from scratch, and each of these regularities, once stated, suggests a family of architectures:
- Locality: many hyperbolic systems and explicitly local interactions propagate influence through neighboring regions at finite speed. Sound takes time to travel, and a disturbance at one end of a beam is not felt at the other until material waves carry it there. This motivates graph architectures with local message passing. The scope matters: diffusion has nonzero mathematical influence at arbitrary distance for positive time, and elliptic solution maps can depend globally on boundary data even when their differential operators are local.
- Relationality: many forces arise from interactions between pairs of entities, with the same law applied to each pair. Gravity applies the same pairwise law everywhere; its force depends on the bodies' masses and relative displacement, not arbitrary identities. This is what licenses sharing one learned interaction function across all entity pairs.
- Continuity and smoothness: states evolve along trajectories, not in arbitrary jumps, at least away from impacts and contacts. This is what licenses differential-equation models and integration as the mechanism of prediction.
- Conservation: in a closed, unforced system, conserved quantities such as mass, momentum, and energy restrict the space of plausible futures. Boundaries, forcing, dissipation, and exchanges with the environment introduce balance terms, so an apparent gain or loss must be interpreted with the system boundary made explicit.
When you hard-code these regularities, the model is reliable only where the encoded physics is valid. Learning without them offers more flexibility but may require more data and may generalize poorly. The methods in this chapter let you learn within a structured hypothesis space, so the data can focus on what you do not know. This is the same economy that shaped the identifiability discussion in Part II: valid structural assumptions shrink the hypothesis space and can reduce the observations needed for identification and improve generalization.
One caution before we begin, because it echoes a theme from Part I: a structured model that predicts well in open loop is not automatically a good model for control. Structure improves the trajectories a model produces, but planning exercises the model differently than prediction does: it pushes the model along action sequences it was never evaluated on, multiplies small errors over long horizons, and depends on gradients that can be wrong even when predictions look right. We will return to this distinction repeatedly, and it becomes central when these models drive planning in Part VII.
Differentiable Simulators
A simulator is a world model you wrote yourself. It takes a state and an action and produces a next state through hand-coded physics:
where:
- , : the state and the action at time
- : the next state produced by the hand-coded physics
- : the hand-coded transition function that advances the state one step
- : the physical parameters, collecting masses, lengths, friction coefficients, stiffnesses
The distinction between the structure of and the values of is the whole design. The structure encodes your physical understanding: which forces act, how they compose, what integration scheme advances the state. The parameters encode what you do not know precisely: the true mass of the payload, the actual coefficient of friction on the table, the real stiffness of a contact. Many legacy or externally wrapped simulators expose only forward outputs, even though classical sensitivity machinery may exist. A differentiable simulator additionally exposes derivatives of the implemented computation through analytic, automatic, implicit, adjoint, or custom derivative rules. For the rollout above, the quantities of interest are the following partial derivatives:
where:
- : the rollout horizon, the number of simulation steps taken from the initial state
- : the simulator state after steps, the output whose sensitivity we compute
- : how the final state changes with each physical parameter
- : how the final state changes with the initial condition
- : how the final state changes with the entire sequence of actions applied over the rollout
Each of these three gradients powers a different capability. The parameter gradient drives system identification, the initial-condition gradient drives sensitivity analysis and state estimation, and the action gradient drives trajectory optimization. One derivative mechanism enables all three, which makes differentiability valuable for a world model.
A physics engine or solver implementation that exposes derivatives of its implemented outputs (states, contacts, sensor readings) with respect to inputs, parameters, and initial conditions, using analytic, automatic, implicit, adjoint, or custom derivative rules.
Why does this matter? Three reasons dominate.
System identification becomes gradient descent. Part II, Chapter 3 treated system identification as an optimization problem and surveyed gradient-free and linear methods. Those methods are workhorses, but they can scale poorly with dimension and nonlinear dynamics. When the simulator is differentiable, identification of reduces to minimizing a loss by backpropagation. The method avoids choosing parameter updates from forward evaluations alone; each iteration still simulates the trajectory, compares it with data, backpropagates through the rollout, and updates the parameters. The gradient combines information from each step of the rollout.
Planning becomes gradient descent. If you can differentiate the accumulated reward or a target cost through the rollout, you can optimize an action sequence directly. This is the modern descendant of shooting methods from classical optimal control (Part II, Chapter 4), and we will do exactly this in the worked example. Automatic differentiation replaces much of the system-specific derivative transcription with loss.backward(), provided every operation on the executed path has a valid derivative. The resulting gradient is exact for the implemented computation, not necessarily for omitted or idealized physics.
Learning can wrap around the simulator. Gradients flowing through simulation let you fit residual neural networks on top of physics, fit simulator parameters jointly with policy parameters, or backpropagate a learned perception module into a physical model. This pattern appears in some hybrid differentiable-simulation pipelines: the simulator supplies a structured backbone, while learned components model residual effects and end-to-end derivatives coordinate the trainable pieces. It is one design option for sim-to-real work, not a description of every sim-to-real pipeline.
How gradients flow through a rollout
The rollout is a deep computation graph: applying once is one layer, so a horizon- rollout is a -layer network. Everything you know about training deep networks applies, with the twist that the layers are physics steps and the depth is dictated by the horizon you care about, not by an architecture choice. There are two standard ways to get gradients through it.
Unrolled backpropagation treats the whole trajectory as a feedforward graph and applies reverse-mode autodiff. This is what torch.autograd does automatically. It is exact and simple, and because reverse-mode autodiff computes the gradient of a scalar loss with respect to all inputs in a single backward pass whose cost is comparable to the forward pass, it is remarkably efficient per unit of information. Its weakness is memory: without checkpointing or recomputation, it stores intermediate states and memory grows linearly with . For a long rollout of a high-dimensional state, memory can become the binding constraint, depending on state size, per-step compute, hardware, and the checkpointing or recomputation strategy.
The adjoint method avoids storing the trajectory by solving an augmented system backward in time. For continuous dynamics and a terminal cost , which measures the terminal state, define the adjoint state by
where:
- : the adjoint state, a costate variable that accumulates sensitivity information as it is integrated backward in time from to
- : the Jacobian of the vector field with respect to the state, evaluated along the forward trajectory
- : the terminal condition, equal to the gradient of the terminal cost with respect to the final state
and then the gradient is an integral along the backward pass:
where:
- : the gradient of the terminal cost with respect to the parameters
- : the adjoint state (transposed), propagated backward from to along the reverse integration
- : the Jacobian of the vector field with respect to the parameters
- The integral runs from down to because the adjoint system is solved backward in time; the minus sign comes from that reversed direction of integration
The intuition behind the adjoint state is worth pausing on: answers the question "if you perturb the state slightly at time , how does the final cost change?" It starts at holding exactly the cost's sensitivity to the terminal state, and as it integrates backward, each step multiplies it by the transpose Jacobian of the dynamics, which converts sensitivity one step later into sensitivity one step earlier. The parameter gradient then follows by accumulating, along the backward sweep, how each parameter perturbation at each moment feeds into that running sensitivity. In the ideal continuous-adjoint formulation, storage can be independent of the number of accepted steps when the trajectory can be reconstructed. Practical implementations retain solver workspace or checkpoints and trade storage for recomputation. There is a pleasing unity here: discrete unrolled backpropagation is in fact an adjoint method for the discretized system; the distinction is practical, not fundamental. Which side wins depends on state dimension, horizon, numerical stability, and whether the integrator can reconstruct or restart the trajectory reliably.
Where differentiability breaks
Physics is not everywhere smooth, and this is the central engineering difficulty. The clean calculus of the previous section assumes is differentiable, and the most interesting parts of physical interaction are precisely where it is not.
- Contacts and impacts create hybrid maps whose event activation, timing, contact set, and normal can change non-smoothly with state or parameters. Within a fixed impact mode, a restitution map such as is linear and continuous in the incoming normal velocity; the derivative difficulty comes from switching between modes and moving event times.
- Friction and stiction involve complementarity conditions (either the object sticks with force below a threshold, or it slips with force at the threshold), which are non-smooth by nature. The switch between sticking and slipping is a set-valued force law, and set-valued maps have no single Jacobian at the switching surface.
- Chaotic dynamics amplify perturbations along unstable directions approximately as over the regime where linearization applies. After several Lyapunov times, long-horizon prediction and gradient-based optimization can become badly conditioned. The derivative can still be mathematically correct; the problem is that it describes extreme sensitivity to initial conditions, parameters, and numerical error.
Practical responses depend on the engine and contact pipeline. Some differentiable simulators use compliant or softened contact, while others differentiate constraint, convex, or position-based formulations; frameworks such as DiffTaichi and Warp support more than one simulator formulation. Any surrogate changes the relationship between the implemented gradient and ideal rigid-contact physics. Against chaotic sensitivity, practitioners often differentiate over shorter windows and re-fit or re-plan frequently, exactly the receding-horizon pattern we will see in the worked example. An adjoint changes memory and computation, not the underlying sensitivity.
We can isolate one mechanism by computing parameter sensitivity in two linear systems. One transition contracts perturbations and the other amplifies them. This is not a chaos experiment; it shows how repeated Jacobian products can make an additive parameter sensitivity saturate or grow with rollout length.
import numpy as np
rng_grad = np.random.default_rng(7)
## Two 2D systems: A_stable has eigenvalues of modulus < 1; A_unstable amplifies.
A_stable = np.array([[0.95, 0.1], [-0.1, 0.9]])
A_unstable = np.array([[1.05, 0.1], [-0.1, 1.02]])
## Fixed parameter entering the dynamics linearly, so d x_T / d theta is the
## composition of the per-step Jacobians times a constant direction.
b_dir = np.array([0.3, -0.2])
horizons = np.arange(1, 61)
grad_stable = np.zeros(len(horizons))
grad_unstable = np.zeros(len(horizons))
for i, T in enumerate(horizons):
g = np.zeros_like(b_dir)
gs = np.zeros_like(b_dir)
for _ in range(T):
g = A_unstable @ g + b_dir
gs = A_stable @ gs + b_dir
grad_unstable[i] = np.linalg.norm(g)
grad_stable[i] = np.linalg.norm(gs)
## Reference exponential fits for the annotation: log-gradient slope per step.
slope_unstable = np.polyfit(horizons, np.log(grad_unstable + 1e-12), 1)[0]
slope_stable = np.polyfit(horizons, np.log(grad_stable + 1e-12), 1)[0]
Let us build a minimal differentiable simulator and use it for identification. The system is a damped pendulum with gravity unknown:
where:
- : the pendulum angle, the configuration we observe
- : the angular velocity, the rate of change of the angle
- : the gravitational acceleration, the unknown parameter to be identified
- : the pendulum length, assumed known
- : the linear damping coefficient, assumed known
integrated with semi-implicit Euler steps. Updating velocity first and then position generally behaves better than explicit Euler for oscillatory mechanics. The undamped conservative update is symplectic; the damping term makes the full map dissipative rather than symplectic. Because every step is built from differentiable torch operations, autodiff gives us directly.
import numpy as np
import torch
torch.manual_seed(0)
L, c, dt = 1.0, 0.15, 0.02
g_true = 9.81
theta0, omega0 = 1.2, 0.0
def simulate_pendulum(g, T=200):
"""Semi-implicit Euler rollout of a damped pendulum."""
theta = g.new_tensor(float(theta0))
omega = g.new_tensor(float(omega0))
traj = [theta]
for _ in range(T):
alpha = -(g / L) * torch.sin(theta) - c * omega
omega = omega + dt * alpha
theta = theta + dt * omega
traj.append(theta)
return torch.stack(traj)Before trusting autodiff through a 50-step rollout, we check one local derivative against finite differences. This is a useful habit: a mismatch can reveal a bug that affects the chosen input, output, and perturbation direction. Agreement is narrower evidence. It does not validate unvisited branches, every parameter or state direction, or the physical model itself.
g_try = torch.tensor(9.0, dtype=torch.float64, requires_grad=True)
final = simulate_pendulum(g_try, T=50)[-1]
final.backward()
grad_autodiff = g_try.grad.item()
eps = 1e-5
up = simulate_pendulum(torch.tensor(9.0 + eps, dtype=torch.float64), T=50)[
-1
].item()
down = simulate_pendulum(torch.tensor(9.0 - eps, dtype=torch.float64), T=50)[
-1
].item()
grad_finite = (up - down) / (2 * eps)Autodiff gradient of final angle wrt g: -0.063487 Finite-difference gradient: -0.063487
The two values agree to several digits, which is what we want for this local check. It supports the derivative of the final angle with respect to at the chosen input after fifty composed steps; it does not certify every gradient path through the simulator. Now the identification task: simulate with the true , corrupt the angles with measurement noise, and recover by gradient descent through the simulator. This is gradient-based system identification, and it is the direct differentiable-simulator answer to the methods of Part II, Chapter 3. Where those chapters treated the simulator as a forward map to be probed, here the simulator is itself the differentiable objective, and the data does the rest.
rng = np.random.default_rng(0)
with torch.no_grad():
true_traj = simulate_pendulum(torch.tensor(g_true), T=200).numpy()
obs = true_traj + 0.01 * rng.standard_normal(true_traj.shape)
obs_t = torch.tensor(obs)
g_hat = torch.tensor(6.0, requires_grad=True)
opt = torch.optim.Adam([g_hat], lr=0.05)
losses = []
for step in range(300):
opt.zero_grad()
pred = simulate_pendulum(g_hat, T=200)
loss = torch.mean((pred - obs_t) ** 2)
loss.backward()
opt.step()
losses.append(loss.item())
g_est = g_hat.item()Estimated gravity: 9.809 (true: 9.810) Final training MSE: 9.21e-05
The estimate lands close to the true value despite the noise. Two things are worth noticing. First, the loss is the full-trajectory matching error, so gradients flow through 200 compositional steps: unrolled backpropagation in its simplest form. For this small scalar-parameter example, storing the trajectory is inexpensive; larger states or longer horizons may favor checkpointing or an adjoint. Second, this worked because the pendulum is smooth and well conditioned over the chosen horizon. For a chaotic system, useful responses include shorter training windows, frequent state feedback, regularization, or methods designed for chaotic sensitivities. An adjoint can reduce memory use, and clipping can bound an update, but neither restores the information lost to long-horizon chaotic sensitivity.
g_grid = np.linspace(4.0, 16.0, 121)
landscape = np.zeros_like(g_grid)
for i, gv in enumerate(g_grid):
with torch.no_grad():
lg = torch.mean(
(simulate_pendulum(torch.tensor(float(gv)), T=200) - obs_t) ** 2
)
landscape[i] = lg.item()

The landscape is smooth and has a single clear sampled basin around the true value. Within at spacing 0.1, the scan shows no comparably low sampled alternative, but it does not certify a global optimum outside that interval or between samples. Missing physics can leave systematic residual error or distort the parameter landscape; whether this appears as a floor, a flat direction, or local minima depends on the data, loss, and compensating parameters. Inspecting the loss landscape and residual behavior is therefore useful evidence for identification, but not a proof that the model class is correct.
Graph-Based Physical Models
Differentiable simulators assume you know the equations. Graph-based physical models assume something much weaker: you know that the system is a network of local interactions. You do not know the force law, the material model, or even in detail what the entities are; you only know that influence is local, that it happens between pairs, and that the same rule applies everywhere. This is the dynamics-side twin of the object-centric representations from Part III, Chapter 5. There we argued that state should be decomposed into objects and relations; here we build the transition function out of the same decomposition. The payoff of matching the two is that the representation and the dynamics now agree about what the world is made of, and learning can happen in the natural coordinates of the problem.
The canonical particle example is the Graph Network Simulator (GNS) of Sanchez-Gonzalez and colleagues (2020). MeshGraphNets, introduced separately by Pfaff and colleagues, applies related graph machinery to mesh-based simulation. In these systems the "objects" are particles or mesh nodes, the edges connect spatial neighbors, and learned updates stand in for parts of a hand-designed simulator. The inductive bias has three parts:
- State is a set of nodes, each carrying local information (position, velocity history, material properties).
- Interactions are edges, and the dynamics of a node depend on its neighbors through learned message-passing functions, not on a global flattened vector.
- The update predicts a derivative (typically acceleration), which is integrated with a fixed physical scheme such as semi-implicit Euler.
The third part deserves emphasis because it imports a useful kinematic structure. Predicting acceleration and integrating it enforces a second-order update from acceleration to velocity to position. It does not by itself enforce Newton's second law, momentum conservation, or force symmetry; those require additional parameterization or constraints. A model that predicts positions directly has no comparable integration scaffold.
A message-passing round looks like
where:
- : the feature vector (for example, position and velocity history) of node before the update
- : the feature vector of neighboring node
- : the edge features carrying relative geometry between the pair, for example
- : the message sent from node to node , computed by the learned interaction network
- : the sum of all incoming messages to node , aggregating its neighborhood
- : the learned update network that combines a node's own features with its aggregated messages
- : the updated node features after one round of message passing
Here and are small neural networks, carries relative geometry (for example ), and the sum aggregates all incoming messages. Two design details carry most of the physical weight. First, if all positional inputs enter through relative displacement rather than absolute position, translating the whole system leaves the interaction input unchanged. Other features, such as masses, material types, or relative velocities, may still affect the interaction. Second, summation matches additive force composition when messages are parameterized as pairwise force contributions; it does not alone enforce antisymmetry or conservation. Stacking rounds lets information travel hops per step for a fixed graph.
An architectural constraint that encodes the hypothesis "the dynamics decompose into interactions between entities, with the same interaction law shared across entities." Graph networks are the standard carrier of this bias for physical worlds.
The payoff of this bias shows up in two places. First, sample efficiency: the model must learn one interaction law rather than a separate rule for every configuration of the system. A pair of neighboring particles observed in one corner of the domain constrains the same function that governs particles elsewhere, so every pair observation in the training data informs the single shared law. Second, size and shape transfer: a model trained on a chain of 8 masses can drive a chain of 12, because nothing in its parameters is tied to the number 8. The learned function takes a pair of features and returns a message; it neither knows nor cares how many such pairs exist. A fixed-width dense model over a flattened state does not natively accept another entity count; supporting size variation requires padding or masking, a maximum-size parameterization, shared structure, or architectural redesign.
Let us demonstrate the core mechanism in its simplest possible form. We will simulate a chain of masses connected by springs with an unknown rest length, assume we know only that (a) forces are pairwise between neighbors, (b) the same law applies to every pair, and (c) damping is linear and known, and then recover from observed motion by linear regression. This strips the message-passing machinery down to its identifiable core: what survives when you remove the neural networks is the hypothesis "one shared pairwise law," and that hypothesis alone is enough to make the problem solvable from modest data.
import numpy as np
rng = np.random.default_rng(1)
k_spring, L0, b_damp, m = 2.0, 1.0, 0.3, 1.0
dt_chain, steps_chain = 0.01, 400
def simulate_chain(x0, v0, steps=steps_chain):
"""Semi-implicit Euler for a free chain with neighbor springs and damping."""
n = len(x0)
x, v = x0.copy(), v0.copy()
xs = np.zeros((steps + 1, n))
vs = np.zeros_like(xs)
acc = np.zeros_like(xs)
xs[0], vs[0] = x, v
for t in range(steps):
pair_force = k_spring * (x[1:] - x[:-1] - L0) # on left mass from right
a = np.zeros(n)
a[:-1] += pair_force
a[1:] -= pair_force
a -= b_damp * v
v = v + dt_chain * a
x = x + dt_chain * v
xs[t + 1], vs[t + 1], acc[t] = x, v, a
return xs, vs, accWe generate training trajectories with random initial conditions. The regression below sees only the two end masses, where the net spring force equals one pairwise force. This restriction exposes an identifiability property rather than taking a shortcut.
n_train_traj, n_masses = 40, 8
train_data = []
for _ in range(n_train_traj):
x0 = np.linspace(0, (n_masses - 1) * L0, n_masses) + rng.normal(
0, 0.15, n_masses
)
v0 = rng.normal(0, 0.3, n_masses)
train_data.append(simulate_chain(x0, v0))Here is the subtle point. At a single instant, the acceleration equation for an interior mass determines only the difference of the two pairwise forces. Any component of that is constant in cancels from those instantaneous interior equations. If observations contain only such equations, any law of the form fits them equally well: the constant is a gauge freedom. Boundary equations break this symmetry because an end mass has only one neighboring force; a periodic chain with only pairwise differences retains it. Longer trajectories do not remove the offset by themselves when every observed acceleration still depends only on force differences, although additional boundary, constitutive, or force measurements can. Learning interaction laws from motion capture often has flavors of this problem: collective motion underdetermines individual forces unless boundary observations, contact events, direct force measurements, or a prior pins them down. Full GNS models bypass explicit force-law identification by supervising accelerations from relative inputs, but that does not make latent messages or physical forces uniquely identifiable. The underdetermination belongs to the inverse problem and can persist inside the architecture.
D_list, F_list = [], []
for xs, vs, acc in train_data:
n_rows = acc.shape[0] - 1 # terminal acceleration was not evaluated
d0 = xs[:-1, 1] - xs[:-1, 0] + rng.normal(0, 0.01, n_rows)
f0 = m * (acc[:-1, 0] + b_damp * vs[:-1, 0]) # phi(d0)
dL = xs[:-1, -1] - xs[:-1, -2] + rng.normal(0, 0.01, n_rows)
fL = m * (acc[:-1, -1] + b_damp * vs[:-1, -1]) # -phi(dL)
D_list += [d0, dL]
F_list += [f0, -fL]
D = np.concatenate(D_list)[:, None]
F = np.concatenate(F_list)
coef = np.linalg.lstsq(np.column_stack([D, np.ones_like(D)]), F, rcond=None)[0]
w1, w0 = float(coef[0]), float(coef[1])Learned interaction law: phi(d) = 1.992 * d + -1.992 True interaction law: phi(d) = 2.000 * d + -2.000
The regression recovers both the slope (stiffness) and the intercept (which encodes the rest length) from end-mass observations, up to the injected separation noise. Here is the mass separation, so vanishes at and has intercept at , a fully compressed ideal spring. The learned law absorbs that offset automatically. Now the transfer test. We roll the learned pairwise law forward with the same semi-implicit integrator on a held-out chain of 8 masses and on a chain of 12 masses, using no size-specific learned parameters.
def rollout_learned(x0, v0, w1, w0, steps=steps_chain):
"""Integrate the chain using the learned pairwise law phi(d) = w1*d + w0."""
n = len(x0)
x, v = x0.copy(), v0.copy()
xs = np.zeros((steps + 1, n))
xs[0] = x
for t in range(steps):
d = x[1:] - x[:-1]
f_pair = w1 * d + w0
a = np.zeros(n)
a[:-1] += f_pair
a[1:] -= f_pair
a -= b_damp * v
v = v + dt_chain * a
x = x + dt_chain * v
xs[t + 1] = x
return xs
x0a = np.linspace(0, 7 * L0, 8) + rng.normal(0, 0.15, 8)
v0a = rng.normal(0, 0.3, 8)
xs_true8, _, _ = simulate_chain(x0a, v0a)
xs_pred8 = rollout_learned(x0a, v0a, w1, w0)
rms8 = np.sqrt(np.mean((xs_pred8 - xs_true8) ** 2, axis=1))
x0b = np.linspace(0, 11 * L0, 12) + rng.normal(0, 0.15, 12)
v0b = rng.normal(0, 0.3, 12)
xs_true12, _, _ = simulate_chain(x0b, v0b)
xs_pred12 = rollout_learned(x0b, v0b, w1, w0)
rms12 = np.sqrt(np.mean((xs_pred12 - xs_true12) ** 2, axis=1))
snap_t = 200 # snapshot time index for the trajectory comparison

The learned law rolls out with tiny error on both tested chain sizes. Because the same local law applies at both sizes, data from 8-mass chains transfers to this matched 12-mass case. Transfer to other sizes still depends on coverage of the relevant local configurations and dynamics. The error curves also illustrate compounding rollout error: small per-step mismatches accumulate over the horizon. Full GNS models retain shared local updates while replacing this linear regression with neural message passing. Their learned interactions remain trustworthy only where training data or structural constraints support them.
Neural Differential Equations
Both previous approaches keep an explicit integrator and learn either parameters or a force law. Neural differential equations go one step further back: the learned object is the vector field. There is no hand-written equation and no assumed interaction structure; there is only the commitment that state evolves as a continuous-time flow, and a neural network is installed as the right-hand side of the flow equation. A neural ODE (Chen and colleagues, 2018) defines state evolution by
where:
- : the state of the system at continuous time
- : a neural network, with parameters , that defines the time derivative of the state
Trajectories are produced by a compatible ODE solver, and the model's job is to learn the right-hand side from data. The change of perspective is subtle but consequential: in a differentiable simulator the integrator is an implementation detail of your physics, while here the integrator is a generic engine and the entire modeling content lives in the vector field. The commitment is that state evolution can be represented by a sufficiently regular continuous-time vector field; the regularity needed for existence, uniqueness, and differentiability depends on the model and solver.
A continuous-time dynamical system whose vector field is a neural network. Gradients are computed either by backpropagating through solver steps or with an adjoint method. Ideal continuous-adjoint storage can be independent of the number of accepted steps when the trajectory is reconstructible; practical implementations may retain workspace or checkpoints.
The connection to the adjoint method is especially clean. The continuous-adjoint formulation can avoid storing every accepted solver step by reconstructing or recomputing the trajectory during the backward solve. Its idealized memory cost is independent of the number of stored steps, excluding solver workspace and checkpoints, but numerical error and backward instability can make its gradients differ from differentiating the actual discrete solver. The appropriate choice is therefore implementation- and problem-dependent.
What does continuous time buy you, concretely?
- Decoupling the model from the integrator. Because the learned object is a vector field rather than a discrete map, it can be evaluated with another compatible solver or time grid. Accuracy and stability can still change with the solver, tolerance, and sampling regime, so deployment at a new resolution requires validation rather than an assumption of invariance.
- Irregular sampling. Observation times need not be uniform. The solver simply integrates between whatever times data arrives, which is awkward for fixed-window discrete models and natural here. This connects directly to the temporal state and memory questions of Part III, Chapter 4. Real sensors do not tick at metronomic intervals, and a model class that treats the timestamps as part of the problem rather than a nuisance is materially better suited to them.
- Dynamical-systems tools. You can compute fixed points, Jacobians, Lyapunov exponents, or conservation properties of , and you can constrain it: divergence-free fields for incompressible flow, Hamiltonian structure for conservative systems (the Hamiltonian and Lagrangian neural network line of work). This is a two-way street: the tools analyze what was learned, and the constraints shape what can be learned. An exact autonomous Hamiltonian vector field conserves its Hamiltonian along the continuous flow, but a numerical rollout can still drift unless the integrator and step-size regime preserve the relevant structure accurately.
The main training design choice is one-step supervision versus unrolled supervision, and it is the same open-loop-versus-compounding issue we have flagged before. Supervising to match at every pair of adjacent states is easy and stable, but it is exactly the one-step trap from our discussion of rollout error: tiny one-step biases integrate into large trajectory biases. A vector field that is locally correct to within a percent can still point systematically off-trajectory, and over a hundred integration steps those small angular errors push the solution onto a path the true system never visits. Training through short unrolled segments pushes the model toward trajectories that stay on track, and is usually worth the extra cost.
Let us learn a Van der Pol oscillator from a single trajectory. Its dynamics,
where:
- : the two state variables, position-like and velocity-like respectively
- : the nonlinearity parameter; with the system exhibits a self-sustained limit cycle, and here
- : the state-dependent damping term, which removes energy for large and injects energy near the origin, producing the limit cycle
produce a self-sustained limit cycle: trajectories spiral out from near the origin and settle onto a closed loop. The Van der Pol system is a demanding target for exactly the reason it is a good test: its long-term behavior is a geometric object, a closed attracting loop, and reproducing it requires getting the energy balance right everywhere around the cycle, not just on average. A learned vector field that injects slightly too much energy will spiral outward forever; one that removes slightly too much will collapse to the origin. The learned model sees only states, never the equations.
import numpy as np
mu_vdp, dt_ode = 1.5, 0.05
def vdp_rhs(z):
return np.array([z[1], mu_vdp * (1.0 - z[0] ** 2) * z[1] - z[0]])
def rk4_np(f, z, h):
k1 = f(z)
k2 = f(z + 0.5 * h * k1)
k3 = f(z + 0.5 * h * k2)
k4 = f(z + h * k3)
return z + (h / 6.0) * (k1 + 2 * k2 + 2 * k3 + k4)
z = np.array([1.0, 1.0]) # start off the limit cycle
traj = [z.copy()]
for _ in range(2000):
z = rk4_np(vdp_rhs, z, dt_ode)
traj.append(z.copy())
vdp_traj = np.array(traj)The model is a small MLP defining the vector field. Training unrolls 8 RK4 steps from a batch of starting states and penalizes the mismatch at every step, so gradients flow through the integrator. The unrolling length of 8 is itself a design decision: long enough that compounding errors are visible to the loss, short enough that gradients remain well conditioned. We supervise at every step of the segment rather than only the terminal step, which anchors the trajectory while still letting later steps correct compounding drift.
import torch
import torch.nn as nn
torch.manual_seed(0)
f_node = nn.Sequential(
nn.Linear(2, 64),
nn.Tanh(),
nn.Linear(64, 64),
nn.Tanh(),
nn.Linear(64, 2),
)
for p in f_node.parameters():
nn.init.normal_(p, std=0.1)
def rk4_torch(f, z, h):
k1 = f(z)
k2 = f(z + 0.5 * h * k1)
k3 = f(z + 0.5 * h * k2)
k4 = f(z + h * k3)
return z + (h / 6.0) * (k1 + 2 * k2 + 2 * k3 + k4)
seg_len = 8
starts = np.random.default_rng(3).integers(
0, len(vdp_traj) - seg_len - 1, size=512
)
seg_data = torch.tensor(
np.stack([vdp_traj[s : s + seg_len + 1] for s in starts]),
dtype=torch.float32,
)
opt = torch.optim.Adam(f_node.parameters(), lr=1e-2)
node_losses = []
for step in range(600):
batch = seg_data[torch.randint(0, seg_data.shape[0], (64,))]
zb = batch[:, 0]
loss = 0.0
for t in range(seg_len):
zb = rk4_torch(f_node, zb, dt_ode)
loss = loss + torch.mean((zb - batch[:, t + 1]) ** 2)
opt.zero_grad()
loss.backward()
opt.step()
node_losses.append(loss.item() / seg_len)Then we roll the learned vector field out for the full 100 seconds from the same initial condition and see whether it reproduces the limit cycle. This is a much harder test than the training loss suggests: 100 seconds is 2000 integrator steps, roughly 250 times the unrolled training length. It tests long-horizon consistency along and near the visited trajectory, not global recovery of the vector field.
with torch.no_grad():
zt = torch.tensor([[1.0, 1.0]])
learned_traj = [zt]
for _ in range(2000):
zt = rk4_torch(f_node, zt, dt_ode)
learned_traj.append(zt)
learned_rollout = torch.cat(learned_traj).numpy()
print(f"Final segment training loss: {node_losses[-1]:.2e}")

The learned rollout traces a loop close to the visited limit cycle. From segments of one clean simulated trajectory, this run learns a vector field whose long rollout visually approximates the oscillation. The figure does not by itself establish global vector-field recovery or precise amplitude and period errors. Two failure modes are worth knowing about before you rely on this pattern in earnest.
Stiffness. If the true dynamics have fast transients relative to the slow behavior of interest, explicit solvers need tiny steps, and training through them is expensive. The problem is not merely slow training: an adaptive solver may take very different numbers of internal steps for nearby inputs, which makes the training landscape itself jagged. Recognizing stiffness and switching to implicit solvers is a real skill, and the adjoint method helps because it does not need to store the fine-grained forward trajectory.
Drift and non-conservation. Nothing in the architecture prevents the learned vector field from slowly spiraling inward or outward where the true system conserves energy. The Van der Pol example survives this because the limit cycle is attracting, so small energy errors are corrected by the dynamics themselves; a conservative system with no attractor gives the learned model nowhere to hide, and unbounded drift accumulates. Structural variants address this: Hamiltonian and Lagrangian neural networks build conservation into the parameterization, and augmented neural ODEs add extra dimensions so the model can express trajectories that a fixed-dimensional field cannot fit without distortion. Uncertainty about where the model is trustworthy, rather than a single confident trajectory, is the deeper fix, and that is the subject of the next chapter.
Neural ODEs are also a conceptual bridge to Part V. Residual recurrent state updates can sometimes be interpreted as discretizations of continuous-time latent dynamics, with an encoder mapping observations into that state. Recurrent state-space models in general are broader: they may be gated, stochastic, discontinuous, noninvertible, or otherwise not embeddable in a same-dimensional ODE flow.
Operator Learning for Fields and PDEs
Everything so far concerns systems represented with finite-dimensional state. Continuum fields, such as fluid velocity, material temperature, or ocean pressure, are functions governed by partial differential equations. A numerical discretization with 10 million unknowns is a large finite-dimensional ODE or DAE approximation of that continuum problem. A fixed-grid architecture may couple its learned representation to one resolution or geometry, while convolutional, graph, interpolation, multigrid, and operator constructions can share parameters across compatible discretizations. Whether they transfer depends on coordinates, normalization, geometry handling, numerical resolution, and the training distribution.
Operator learning reframes the learning target. For a PDE with solution , the object of interest is often not one trajectory but the solution operator: the map
which takes an entire initial condition to the entire solution at time . A neural operator is designed to approximate this function-space map from sampled representations. Appropriately constructed operators can share parameters across discretizations and sometimes evaluate zero-shot at new resolutions. That capability is not automatic: standard FFT-based FNOs assume regular grids, while new geometries need compatible coordinates, meshes, or geometry-aware variants and remain distribution-dependent.
The use of one learned parameterization across compatible discretizations of the same underlying function-space problem. A well-designed method should converge toward a consistent continuum operator as adequately resolved meshes are refined; it need not have equal accuracy on arbitrary grids, geometries, or resolutions.
Two foundational architectures illustrate different answers to the question "how does a network eat a function?"
DeepONet (Lu and colleagues, 2019) factorizes the output function evaluation as a learned inner product:
where:
- : the operator output at the query location for the input function
- : the -th coefficient the branch network produces from the entire input function
- : the -th feature the trunk network produces at the query location
- : the number of coefficient-feature pairs, which sets the expressiveness of the factorization
A branch network encodes sampled values of the input function into coefficients , and a trunk network encodes each supported query location into features . Their dot product lets one trained model evaluate new query points within the represented domain, subject to the sensor layout and training distribution. The factorization resembles a learned basis expansion: the trunk provides basis-like spatial functions and the branch provides input-dependent coefficients. Universal approximation results apply under compactness and continuity assumptions; they are existence results, not finite-data generalization guarantees.
The Fourier Neural Operator (FNO, Li and colleagues, 2020) builds the nonlocality into a single layer. Its core is the spectral convolution:
where:
- : the input field (for example, the feature values on the grid at the current layer)
- : the Fourier transform, mapping the field to its frequency modes
- : a learnable complex weight applied to each frequency mode, with the highest modes truncated
- : the inverse Fourier transform, mapping the weighted modes back to the grid
- : the output of the spectral convolution at grid location
Here is the Fourier transform, is a learnable complex weight applied to each frequency mode (with the highest modes truncated), and transforms back. Multiplication by a learned in frequency space is a convolution on the grid, and unlike a local CNN kernel it can couple every point to every other point in one operation. This global path is useful for solution operators with nonlocal dependencies, including positive-time diffusion on the periodic domain used below; not every PDE or forecast horizon requires all-to-all influence. A full FNO stacks several layers of the form
where:
- : the layer- feature value at grid location
- : a local linear map applied pointwise at each location
- : the global spectral path from the previous equation, coupling every location to every other
- : a pointwise nonlinearity applied after summing the local and global paths
The layer combines the global spectral path with a local linear path and a pointwise nonlinearity. Nonlinear PDEs couple modes, while a purely linear spectral map remains confined to linear transformations regardless of depth. The pointwise nonlinearity lets successive spectral layers compose nonlinear operators.
Why is the spectral view so natural for PDEs? Because many linear PDE solution operators are diagonal in the Fourier basis. The heat equation on a periodic domain multiplies each wavenumber- Fourier coefficient by . A spectral architecture can represent this multiplier exactly on its retained modes; an architecture that looks at one grid point at a time cannot express the full map for arbitrary fields, because depends on the entire initial profile. When you choose an architecture for a field-valued world, you decide which dependency structures are available to the model.
Weather forecasting provides large-scale examples. In their 2022--2023 evaluations, FourCastNet, based on an adaptive Fourier operator, matched then-current IFS performance on selected short-lead variables, while GraphCast, a multimesh graph model, beat then-current HRES on most specified verification targets. These were benchmark-, lead-time-, hardware-, and baseline-specific results rather than universal dominance. FourCastNet reported a week-long forecast in under two seconds on its stated accelerator setup; GraphCast reported a ten-day forecast in under 60 seconds on a TPU. Both timings describe inference and exclude training and operational pipeline costs.
Let us see the argument play out on the heat equation. We generate discrete spectral solutions, then train two models on the same data: a minimal spectral operator and a pointwise MLP that sees only at each location. The spectral architecture can represent the heat multiplier on its retained modes; modes above its cutoff are present but strongly attenuated in the targets. Both models use the same data and number of training steps. The spectral model has 2,073 trainable real parameters and the pointwise MLP has 4,353, so this comparison isolates the dependency structure more clearly than it isolates parameter count.
import numpy as np
rng = np.random.default_rng(5)
N_grid, nu_heat, T_final = 256, 0.1, 1.0
k_modes = np.arange(N_grid // 2 + 1)
def make_heat_sample():
"""Random smooth initial condition and its exact heat-equation solution at T."""
c0 = rng.normal(size=len(k_modes)) + 1j * rng.normal(size=len(k_modes))
c0 = c0 / (1.0 + k_modes**2) ** 1.2
c0[0] = 0.0
u0 = np.fft.irfft(c0, n=N_grid)
uT = np.fft.irfft(c0 * np.exp(-nu_heat * k_modes**2 * T_final), n=N_grid)
return u0, uT
n_train, n_test = 200, 50
train_u0 = np.zeros((n_train, N_grid))
train_uT = np.zeros((n_train, N_grid))
test_u0 = np.zeros((n_test, N_grid))
test_uT = np.zeros((n_test, N_grid))
for i in range(n_train):
train_u0[i], train_uT[i] = make_heat_sample()
for i in range(n_test):
test_u0[i], test_uT[i] = make_heat_sample()The spectral model lifts each grid value to a small feature width, applies a learnable complex weight per retained Fourier mode, and projects back. The random initial conditions contain nonzero coefficients above mode 15, but heat evolution suppresses them strongly at . The model can represent the exact heat multiplier on the retained modes and approximate the full target closely; the cutoff remains a real modeling choice rather than an exact support boundary.
import torch
import torch.nn as nn
torch.manual_seed(0)
class SpectralOperator(nn.Module):
"""Minimal FNO-style layer: lift, learned per-mode weights, project."""
def __init__(self, modes=16, width=8):
super().__init__()
self.modes = modes
self.lift = nn.Linear(1, width)
self.W = nn.Parameter(0.05 * torch.randn(modes, width, width, 2))
self.proj = nn.Linear(width, 1)
def forward(self, u): # u: (batch, N_grid)
h = self.lift(u.unsqueeze(-1)) # (batch, N, width)
h_ft = torch.fft.rfft(h, dim=1) # (batch, N//2+1, width)
out_ft = torch.zeros_like(h_ft)
Wc = torch.complex(self.W[..., 0], self.W[..., 1])
out_ft[:, : self.modes] = torch.einsum(
"bkm,kmo->bko", h_ft[:, : self.modes], Wc
)
h = torch.fft.irfft(out_ft, n=u.shape[-1], dim=1)
return self.proj(h).squeeze(-1)
train_u0_t = torch.tensor(train_u0, dtype=torch.float32)
train_uT_t = torch.tensor(train_uT, dtype=torch.float32)
spectral_model = SpectralOperator(modes=16, width=8)
opt = torch.optim.Adam(spectral_model.parameters(), lr=5e-3)
spectral_losses = []
for step in range(1000):
pred = spectral_model(train_u0_t)
loss = torch.mean((pred - train_uT_t) ** 2)
opt.zero_grad()
loss.backward()
opt.step()
spectral_losses.append(loss.item())The pointwise baseline has more parameters but the wrong dependency structure: its output at can depend only on its input at . Watch what that does to the error.
pointwise_model = nn.Sequential(
nn.Linear(1, 64),
nn.GELU(),
nn.Linear(64, 64),
nn.GELU(),
nn.Linear(64, 1),
)
opt = torch.optim.Adam(pointwise_model.parameters(), lr=5e-3)
pointwise_losses = []
for step in range(1000):
pred = pointwise_model(train_u0_t.unsqueeze(-1)).squeeze(-1)
loss = torch.mean((pred - train_uT_t) ** 2)
opt.zero_grad()
loss.backward()
opt.step()
pointwise_losses.append(loss.item())def rel_l2(model, u0, uT, pointwise=False):
u0_t = torch.tensor(u0, dtype=torch.float32)
uT_t = torch.tensor(uT, dtype=torch.float32)
with torch.no_grad():
x_in = u0_t.unsqueeze(-1) if pointwise else u0_t
pred = model(x_in).squeeze(-1)
err = torch.mean((pred - uT_t) ** 2, dim=1)
ref = torch.mean(uT_t**2, dim=1)
return torch.sqrt(err / ref).mean().item()
err_spectral = rel_l2(spectral_model, test_u0, test_uT)
err_pointwise = rel_l2(pointwise_model, test_u0, test_uT, pointwise=True)
with torch.no_grad():
spec_pred = spectral_model(
torch.tensor(test_u0[:1], dtype=torch.float32)
).numpy()[0]
pw_pred = (
pointwise_model(
torch.tensor(test_u0[:1], dtype=torch.float32).unsqueeze(-1)
)
.squeeze(-1)
.numpy()[0]
)
spectra_u0 = np.abs(np.fft.rfft(test_u0[0]))
spectra_uT = np.abs(np.fft.rfft(test_uT[0]))Test relative L2 error, spectral operator: 0.0011 Test relative L2 error, pointwise MLP: 0.2292


The contrast is stark. The spectral operator tracks the target closely, while the larger pointwise MLP does not. The failure is an expressiveness problem imposed by the dependency structure: no function of the single number can equal a value that depends on the entire field for arbitrary initial conditions. Diffusion damps high wavenumbers, so by time the output at one point is a weighted average of values across the periodic domain. A pointwise map has no mechanism for that averaging. This fixed-grid experiment isolates nonlocal representability; it does not test transfer to another resolution or geometry.
Worked Example: Planning Through a Differentiable Simulator
Everything above was about prediction quality. This worked example turns a structured model toward decision-making, which is where world models earn their keep, and it demonstrates the difference between open-loop prediction and closed-loop usefulness that runs through this book. The example is intentionally simple, because its purpose is not to showcase a hard control problem but to expose, in a setting where the answer is known, exactly what differentiability contributes to planning and exactly where the resulting plans are fragile.
The task: a damped pendulum starts at angle and we want the final angle near after 2.4 seconds, using a bounded torque . We use normalized units with effective moment of inertia , so torque enters the angular acceleration as ; otherwise the dynamics contain . We know the physics exactly, so the differentiable simulator is the world model, and the plan is simply a sequence of torques found by gradient descent through the rollout:
where:
- : the sequence of torque actions being optimized, the decision variables of the problem
- : the pendulum angle after steps under the chosen action sequence, which we want near zero
- : the effort weight penalizing control energy, set to in the experiment below
- : the mean squared normalized torque over the horizon, discouraging aggressive actuation
- : the differentiable simulator dynamics as a constraint on every step
- : the torque bound, with enforced via a tanh squashing in the implementation
This is a shooting method from Part II, Chapter 4, with autodiff replacing hand-derived adjoints. The constraint is handled implicitly: rather than enforcing the dynamics as constraints in a constrained optimizer, we simulate them forward and optimize only over the action sequence, which is what "shooting" means. The dynamics are satisfied by construction inside the simulator; the price is that the parameterization of the decision variables, a flat sequence of torques, gives the optimizer no mechanism to correct early mistakes except through the actions themselves.
import numpy as np
import torch
torch.manual_seed(0)
theta_start, omega_start = 1.2, 0.0
n_ctrl = 120
u_max = 2.0
def simulate_controlled(u_seq):
theta = torch.tensor(float(theta_start))
omega = torch.tensor(float(omega_start))
traj = [theta]
for ut in u_seq:
alpha = -(g_true / L) * torch.sin(theta) - c * omega + ut
omega = omega + dt * alpha
theta = theta + dt * omega
traj.append(theta)
return torch.stack(traj)
traj_before = simulate_controlled(torch.zeros(n_ctrl)).detach().numpy()
u_param = torch.zeros(n_ctrl, requires_grad=True)
opt = torch.optim.Adam([u_param], lr=0.05)
ctrl_losses = []
for step in range(500):
u = u_max * torch.tanh(u_param) # bounded torque via squashing
traj = simulate_controlled(u)
loss = traj[-1] ** 2 + 0.01 * torch.mean(u**2)
opt.zero_grad()
loss.backward()
opt.step()
ctrl_losses.append(loss.item())
with torch.no_grad():
traj_after = simulate_controlled(u_max * torch.tanh(u_param)).numpy()
theta_before_final = traj_before[-1]
theta_after_final = traj_after[-1]
omega_before = np.gradient(traj_before, dt)
omega_after = np.gradient(traj_after, dt)
times_ctrl = np.arange(n_ctrl + 1) * dtFinal angle, no control: 0.777 rad Final angle, optimized: 0.023 rad Approx. final angular velocity: -2.159 rad/s Final cost, optimized: 0.0155


Gradient descent through the simulator finds a torque sequence that reaches the target angle at the terminal time. The pendulum is still moving, because the objective penalizes terminal angle but not terminal angular velocity or dwell time. Notice what made the optimization work: differentiability of the implemented physics supplied action sensitivities, differentiability through time composed them across 120 steps, and differentiable squashing enforced the torque bound at every iterate. These gradients are correct for the implemented model; mismatch between that model and reality can still mislead the planner.
This plan is open loop: we optimized one torque sequence against the model and executed it. If the real pendulum's friction differed from the model's, or a nudge arrived mid-swing, the plan would drift and the realized terminal error would differ from the prediction. The plan is most fragile where the optimized trajectory passes through sensitive regions of state space, yet a single deterministic rollout does not identify those regions. The standard remedies are to re-plan from the measured state every few steps (receding-horizon control, developed in Part VII) and to model residual uncertainty explicitly. Re-planning replaces one long plan with a chain of shorter optimizations at the cost of solving a problem at each control step. A model accurate enough to optimize through is not automatically safe to trust for the full horizon. This open-loop-versus-closed-loop gap is a central evaluation criterion for the architectures in Part V.
Choosing the Right Structure
The four families form a design spectrum, and the choice among them is driven by what you know, what you have, and what the model is for. Reading the table by columns is instructive: the "hand-designed" column generally shrinks as you move down, while the "sweet spot" column tracks how much physics you can commit to in advance. The data-hunger labels are qualitative heuristics, not controlled cross-family measurements; they depend on the task, target error, architecture, data quality, and evaluation regime.
| Family | What is hand-designed | What is learned | Data hunger | Sweet spot |
|---|---|---|---|---|
| Differentiable simulator | Equations, integrator | Parameters, plans, residuals | Very low | Known physics, unknown constants, control |
| Graph-based models | Locality, pairwise sums, integrator | Interaction laws | Low to moderate | Many interacting objects or particles |
| Neural ODEs | Integrator, state dimension | Full vector field | Moderate | Smooth continuous-time processes, irregular data |
| Operator learning | Function-space architecture | Solution operator | Moderate to high | Fields and PDEs, multi-resolution deployment |
A few rules of thumb distilled from the chapter:
- Differentiate what you know, learn what you do not. If the equations are right up to parameters, use a differentiable simulator and fit the parameters. If only the interaction structure is known, learn inside a graph model. Reserve learning capacity for unknown components. Every valid equation you supply is one less relation the data must identify.
- Match the architecture's bias to the physics' structure. Pairwise locality calls for graphs, temporal smoothness calls for differential equations, and spatial nonlocality calls for operators. A mismatched bias can waste capacity or exclude the target dependency entirely, as the pointwise heat baseline demonstrates.
- Prefer hypothesis classes that contain the target dependency structure and can approximate the dynamics to the fidelity the task requires. The pointwise MLP failed the heat equation not for lack of width but because it had no pathway for cross-location dependence. Extra width cannot repair a missing dependency pathway.
- Hybrid physics-plus-residual models are useful when core physics is trustworthy and systematic residual effects are learnable. Physics-informed neural networks likewise add differential-equation residuals and boundary or initial-condition information to the objective, although some variants enforce conditions directly. A persistent, validated residual can flag where a mechanistic model disagrees with data, but attributing it to missing physics requires ruling out observation noise, state-estimation bias, discretization error, parameter error, distribution shift, and failed optimization.
Limitations and Impact
The deepest limitation of every method in this chapter is that structure is a wager on where the model will be used. A differentiable simulator is accurate only inside the regime its equations describe; a graph network's learned interaction law assumes coverage of relevant pair configurations; an operator trained on one family of initial conditions may degrade outside it. Agents that optimize through these models can find the seams. A policy may exploit compliant contact in ways a real robot cannot, while an operator-based planner may seek inputs where prediction error flatters its objective. Structure narrows the space of plausible failures, but it does not eliminate model exploitation. Part XII returns to these reliability questions.
The second systemic limitation concerns evaluation. These families are often evaluated on held-out predictive error---trajectory or rollout error for dynamical models, and field or function error for operator models---but predictive error alone does not establish usefulness for control. As we saw in the worked example, open-loop accuracy and closed-loop usefulness can come apart. A simulator whose parameters are slightly wrong may produce visually indistinguishable trajectories while inverting the sign of a gradient that planning depends on; a graph model with excellent one-step accuracy may drift over horizons that matter for a task. Structured models earn their complexity budget only when the structure they encode is the structure the decision problem exercises, and evaluating that requires task-level protocols, not just predictive-error metrics. In practice this means evaluating plans executed under model mismatch, not just predictions compared to data, and it means reporting where in state space the model is trustworthy, not just how wrong it is on average.
The impact of these methods has been substantial. Differentiable simulators connect system identification, optimal control, and deep learning. Graph simulators have shown that learned local updates can model particle and mesh systems, and GraphCast-style models scale relational structure to planetary forecasting. Neural differential equations connect learned dynamics to dynamical-systems analysis, while operator learning targets reusable PDE solution maps. Each capability remains conditional on the encoded structure, numerical method, data regime, and deployment distribution.
One more frontier remains deliberately open in this chapter. Every model here produced a deterministic prediction. Physical prediction is uncertain because chaotic dynamics amplify initial-state uncertainty, contact conditions and parameters are imperfectly known or variable, and sensors are noisy; only some of these mechanisms are intrinsically stochastic. Representing aleatoric, epistemic, and observation uncertainty changes both training objectives and how a planner should consume predictions. A predictive distribution can support risk-aware decisions, provided it is calibrated in the relevant state-action region. That is the subject of the next chapter on stochasticity and uncertainty.
Summary
- Structured simulators inject physical knowledge at different points: equations (differentiable simulators), interaction topology (graph models), temporal structure (neural ODEs), or function-space structure (operators). Choosing the injection point is a core world-model design decision, because it fixes what the data must teach and what the architecture guarantees for free.
- Differentiable simulators turn identification and planning into gradient-based optimization, with unrolled backpropagation trading memory for simplicity and adjoints trading storage for recomputation or backward integration. Contact formulations are engine-specific, and chaotic sensitivity often motivates shorter differentiation and replanning horizons.
- Graph-based physical models encode locality and shared pairwise interaction laws. Parameter sharing can improve sample efficiency, while the spring-chain experiment demonstrates transfer from the matched 8-mass training setup to a 12-mass test. Interior motion only constrains differences of pairwise forces, so boundary information or priors are needed to pin down an absolute law. Learned interactions remain limited by their training distribution.
- Neural ODEs learn the vector field itself, decoupling the model from the integrator and enabling dynamical-systems analysis. Unrolled training mitigates one-step-to-trajectory drift; conservation requires structural commitments, and stiff systems demand solver sophistication.
- Operator learning targets maps between function spaces. Spectral architectures can represent nonlocal operators that pointwise models cannot. Compatible neural-operator designs may share parameters across discretizations, but the fixed-grid heat experiment tests nonlocal representability, not cross-grid transfer.
- Structure trades data for assumptions. Valid priors can reduce data needs and improve extrapolation within their regime, while incorrect priors can fail sharply. Hybrid residuals are useful corrections and potential diagnostics, but a large residual is not uniquely attributable to missing physics.
- Prediction quality is not decision quality. Gradients through a model can optimize plans that the same model's open-loop errors will break; receding-horizon re-planning and explicit uncertainty modeling are the standard responses, and uncertainty is where the next chapter begins.
Quiz
Ready to test your understanding? Take this quick quiz to reinforce what you've learned about structured simulators and neural operators.
Structured Simulators and Neural Operators
Reference
Citation details
Cite or share this article.
Continue with the full handbook
This chapter is part of World Models Handbook. Use the handbook page to browse the complete table of contents and continue reading in sequence.
Explore World Models HandbookStay up to date
Get articles, book updates, and news delivered to your inbox.
No spam, unsubscribe anytime.
Join the community
Sign in to remove popups, track your reading progress, and join the discussion.

Comments
No comments yet. Be the first to share your thoughts!