Object-Centric and Relational Worlds › Worked Example: A Spring Lattice, Message by Message

Michael BrenndoerferJune 17, 20264 min read
World Models HandbookAll chapters
Part 3 of 12Representing Agents and Worlds
Chapter 17Object-Centric and Relational Worlds › Worked Example: A Spring Lattice, Message by Message
Reading section 7 of 11 · Worked Example: A Spring Lattice, Message by Message · 4 minSection 7 of 11 · 4 min

Book contents

Section 7 of 11 · 4 min read

Object-Centric and Relational Worlds › Worked Example: A Spring Lattice, Message by MessageOne section · Sections in this chapter7 / 11 ↓
Reading tools Definitions & inline links

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

Let's make message passing concrete with the smallest possible physical system: two unit masses connected by one spring with stiffness k=6k = 6 and rest length L0=1L_0 = 1, moving along a line with damping c=0.6c = 0.6. Small enough to do by hand, rich enough to exercise every stage of the recipe: an edge function, an aggregation, a node update, and an integration step. At some instant, with xix_i the position of mass ii and viv_i its velocity:

x1=0,x2=1.2,v1=v2=0.3.x_1 = 0, \quad x_2 = 1.2, \quad v_1 = v_2 = 0.3.

The worked physical system has one undirected relation. We will display its equal-and-opposite forces as two directed effects. That representation allows both effects to be carried, but a generic learned directed-edge MLP does not enforce Newton's third law unless antisymmetry is built into the parameterization or one pair force is applied with opposite signs.

Edge messages. The signed scalar spring law is k(r−L0)k(r-L_0); its magnitude is k∣r−L0∣k|r-L_0|, with direction supplied separately. Here r=1.2r=1.2, so the stretch is 0.20.2 and the magnitude is 1.21.2. The physical force on mass 1 points toward mass 2, so ε2→1=+1.2\varepsilon_{2\to1}=+1.2, while the paired force is ε1→2=−1.2\varepsilon_{1\to2}=-1.2. A learned edge function can use relative position and rest length to approximate this vector law without absolute positions. Exact action-reaction symmetry still requires an antisymmetric construction; otherwise data-sparse regimes are one risk among several sources of approximation error.

Aggregation. Each mass has exactly one neighbor, so mˉ1=1.2\bar{m}_1=1.2 and mˉ2=−1.2\bar{m}_2=-1.2. In a larger lattice, aggregation forms the vector sum of attached spring forces. For two equal, co-directed contributions, averaging would return half of the correct sum; in general, directions and magnitudes differ and may cancel.

Node update. The node function combines the aggregated force with damping: ai=mˉi−c via_i = \bar{m}_i - c\,v_i, where aia_i is the acceleration of mass ii (with unit masses, net force and acceleration are numerically equal). With v=0.3v = 0.3 for both masses:

a1=mˉ1−c v1=1.2−0.6×0.3=1.2−0.18=1.02,a2=mˉ2−c v2=−1.2−0.6×0.3=−1.2−0.18=−1.38.\begin{aligned} a_1 &= \bar{m}_1 - c\,v_1 = 1.2 - 0.6 \times 0.3 = 1.2 - 0.18 = 1.02, \\ a_2 &= \bar{m}_2 - c\,v_2 = -1.2 - 0.6 \times 0.3 = -1.2 - 0.18 = -1.38. \end{aligned}

One semi-implicit Euler step with Δt=0.02\Delta t = 0.02, updating velocity first with vi′=vi+Δt aiv_i' = v_i + \Delta t\, a_i and then position with xi′=xi+Δt vi′x_i' = x_i + \Delta t\, v_i', gives v1′=0.3+0.02×1.02=0.3204v_1' = 0.3 + 0.02 \times 1.02 = 0.3204 and v2′=0.3+0.02×(−1.38)=0.2724v_2' = 0.3 + 0.02 \times (-1.38) = 0.2724. The separation becomes

x2′−x1′=(1.2+0.02×0.2724)−(0.02×0.3204)(semi-implicit Euler updates, with x1=0)=1.205448−0.006408(evaluate the two new positions)=1.19904≈1.199,\begin{aligned} x_2' - x_1' &= (1.2 + 0.02 \times 0.2724) - (0.02 \times 0.3204) && \text{(semi-implicit Euler updates, with } x_1 = 0 \text{)} \\ &= 1.205448 - 0.006408 && \text{(evaluate the two new positions)} \\ &= 1.19904 \approx 1.199, \end{aligned}

which is down from 1.21.2: the stretched spring is pulling the masses together, with damping bleeding energy.

The edge function in this example is a straight line in the separation, which makes its job easy to picture.

In[6]:
Code
import numpy as np

K_SPRING = 6.0
L0 = 1.0
separations = np.linspace(0.4, 1.8, 200)
forces = K_SPRING * (separations - L0)
r_now = 1.2
f_now = K_SPRING * (r_now - L0)
Out[7]:
Visualization
Line of spring force versus separation with a marked operating point.
Signed scalar spring force k(r-L0) versus separation for stiffness 6 and rest length 1. The dot marks separation 1.2, where the scalar is 1.2; negative values denote compression.

This curve is one one-dimensional, fixed-parameter slice of the learned relation. The two-dimensional model below receives relative position, relative velocity, and rest length and must learn a direction-dependent vector message across that larger input space.

For a fixed-size joint state (x1,x2,v1,v2)(x_1,x_2,v_1,v_2), a generic MLP can learn relative differences and symmetry, but does not obtain them by construction. A different object count changes a fixed-width interface unless the design adds padding, masks, sharing, or set-equivariant modules. Message passing supplies shared local computation and permutation-compatible aggregation directly. The following code tests that inductive bias against an edge-free per-object baseline.