Skip to content

Model Guide

Model

A Model declares the state variables, update blocks, and optional parameter grid for a simulation.

from gds_sim import Model, StateUpdateBlock

model = Model(
    initial_state={"x": 0.0},
    state_update_blocks=[StateUpdateBlock(variables={"x": update_x})],
    params={"rate": [0.1, 0.2]},
)

initial_state defines the complete state key set. Every variable updated by a state update function must already exist in initial_state; missing keys are rejected during model validation.

StateUpdateBlock

A block has two parts:

Field Purpose
policies Functions that read state and parameters, then emit signals
variables Functions that update one state variable each
def policy(state, params, **kw):
    return {"delta": params["rate"]}


def update_x(state, params, *, signal=None, **kw):
    signal = signal or {}
    return "x", state["x"] + signal["delta"]


block = StateUpdateBlock(
    policies={"p": policy},
    variables={"x": update_x},
)

Policy outputs are merged with dict.update(). If multiple policies emit the same signal key, the later policy value wins.

Function Signatures

Native gds-sim functions receive current state, current parameter subset, and keyword metadata:

policy(state, params, timestep=t, substep=s) -> dict
state_update(state, params, signal=signal, timestep=t, substep=s) -> tuple[str, Any]

State update functions return the state key and its new value. The engine creates a shallow copy of the state for each block and writes returned values into that new state.

cadCAD Compatibility

gds-sim also accepts cadCAD-style callables. Signature detection happens once when the model is created.

def cadcad_policy(params, substep, state_history, previous_state):
    return {"delta": params["rate"]}


def cadcad_suf(params, substep, state_history, previous_state, policy_input):
    return "x", previous_state["x"] + policy_input["delta"]

These are adapted to the native runtime signature before the hot loop starts.

Parameters

Model.params maps each parameter name to a list of values. The model expands those lists into cartesian-product subsets.

Model(
    initial_state={"x": 0},
    state_update_blocks=[StateUpdateBlock(variables={"x": update_x})],
    params={"a": [1, 2], "b": [10, 20]},
)

The simulation records the active combination as the subset metadata column.