Skip to content

Expression reference

core/expressions.py's grammar: a restricted-Python AST allow-list, never eval/exec.

Grammar

Category Allowed
Constants int, float, str, bool, None
Names entity, TNOW / now, true / false, submodel parameters, model variables
Attributes entity.<name>; self.<name> in an agent type's expressions (its attributes, self.state, self.id); AGENT("pop", i).<name>; no leading _. payload in a message transition's guard and actions
Operators + - * / // % **, unary + - not, and/or, comparisons, in/not in against a tuple or list literal, a if c else b, tuple and list literals
Calls the functions below, positional arguments only

Functions

Function Arguments Notes
ACOS 1 math.acos, radians
ACTIVE_INITIAL 2
AGENT 2 AGENT("pop", i): a reference to agent i (what entity.agent holds and a send takes); AGENT("pop", i).attr reads its attribute
ALIVE 1 ALIVE(ref): whether a stored agent reference (AGENT(...), entity.agent) still names its agent; using one whose agent was removed raises
ASIN 1 math.asin, radians
ATAN 1 math.atan, radians
ATAN2 2 ATAN2(y, x): math.atan2, radians in (-pi, pi]
AUX 1 auxiliary NAME, evaluated on read
AVAILABLE 1 capacity in force at resource NAME, seized units NOT deducted (free units: IDLE)
CELL_COUNT 1..3 CELL_COUNT("pop"[, dx, dy]): pop's agents in self's grid cell (or an offset from it), self included; 0 off a bounded grid
CONV 1
COS 1 math.cos, radians
COSH 1 math.cosh, radians
COUNT 1..4 COUNT("pop"[, "state"][, "attr", "value"]): a population's live agents, those in a state (O(1)), or those whose categorical attribute holds that category
DEG 1 radians to degrees
DELAY 1 output of delay NAME
DELAY1 2..3 DELAY1(x, tau[, init]): first-order material delay (init defaults to x at t0); needs simulation.sd
DELAY3 2..3 DELAY3(x, tau[, init]): third-order material delay (init defaults to x at t0); needs simulation.sd
DELAYN 3..4 DELAYN(x, tau, n[, init]): n-th order material delay, n a literal integer (init defaults to x at t0)
DELAYP 2..3 DELAYP(x, tau[, init]): x exactly tau later (pipeline); no grid needed
DISC 2..n value/prob pairs (>= 1 pair), probs must sum to 1
DISTANCE 2
EXPO 1 exponential(mean), sampled from the calling block's own rng
FLOW 1 FLOW("name"): the rate flow NAME moves right now, after saturation
FLOWSUM 1..2
FORECAST 3
FRACTION 2
IDLE 1 free units of resource NAME: nothing holds them now (AVAILABLE minus the seized)
IF 3 IF(c, a, b): a when c else b; only the branch taken is evaluated
INITIAL 1
IS_LINKED 1 IS_LINKED(ref): whether self is linked to that agent (directed: self -> it)
KNN_MEAN 3..4 KNN_MEAN("pop", "attr", k[, "state"]): attr's mean over the k nearest agents of pop to self (state-filtered first, ties by ascending index); 0 if none
KNN_SUM 3..4 KNN_SUM("pop", "attr", k[, "state"]): attr summed over the k nearest agents of pop to self (state-filtered first, ties by ascending index); 0 if none
LEVEL 1 LEVEL("name"): the current value of level NAME
LINKED 1..2 LINKED("pop"[, "state"]): how many agents self is linked to (pop is self's own population; directed: its out-links)
LINK_MEAN 1..2 LINK_MEAN("attr"[, "state"]): attr's mean over self's linked neighbours; 0 if none
LINK_SUM 1..2 LINK_SUM("attr"[, "state"]): attr summed over self's linked neighbours; 0 if none
MEAN 1..3 MEAN(x): SUM(x) divided by the element count (subscripts); MEAN("pop", "attr"[, "state"]): an attribute's mean over a population (in that state; 0 if none)
MODULO 2 MODULO(a, b): the remainder of a / b with the sign of a
MR 1 units currently scheduled at resource/set NAME (net of capacity-schedule/failure blockers)
NEAR 2..3 NEAR("pop", r[, "state"]): how many of pop's agents are within r of self (inclusive), self excluded when pop is self's own population
NEAREST 1..2 NEAREST("pop"[, "state"]): distance to the closest OTHER agent of pop (inf if there is none)
NEAR_HEADING 2..3
NEAR_MAX 3..4 NEAR_MAX("pop", "attr", r[, "state"]): attr's maximum over the agents NEAR counts; NaN if none
NEAR_MEAN 3..4 NEAR_MEAN("pop", "attr", r[, "state"]): attr's mean over the agents NEAR counts; 0 if none
NEAR_MIN 3..4 NEAR_MIN("pop", "attr", r[, "state"]): attr's minimum over the agents NEAR counts; NaN if none
NEAR_SUM 3..4 NEAR_SUM("pop", "attr", r[, "state"]): attr summed over the agents NEAR counts; 0 if none
NEIGHBOURS 1..2 NEIGHBOURS("pop"[, "state"]): pop's agents in the Moore/von Neumann cells around self's (own cell excluded)
NEIGHBOUR_MEAN 2..3 NEIGHBOUR_MEAN("pop", "attr"[, "state"]): attr's mean over the agents NEIGHBOURS counts; 0 if none
NEIGHBOUR_SUM 2..3 NEIGHBOUR_SUM("pop", "attr"[, "state"]): attr summed over the agents NEIGHBOURS counts; 0 if none
NOISE_NORMAL 4
NORM 2 normal(mean, sd), sampled from the calling block's own rng
NPV 4
NQ 1 entities waiting for resource/set NAME
NR 1 entities/units currently in service at resource/set NAME
NS 1 items currently in store NAME (a Hold/Batch/Match store, by block or store name)
PATCH 1..3 PATCH("name"[, dx, dy]): the patch value at self's grid cell (or an offset from it); 0 off a bounded grid
PI 0 PI(): 3.14159...
PROD 1
PULSE 3 PULSE(h, t0, w): h on [t0, t0 + w), else 0
RAD 1 degrees to radians: COS(RAD(self.heading))
RAMP 2..3 RAMP(s, t0[, t1]): s * (TNOW - t0) after t0, held after t1
RAND 0 uniform [0, 1), sampled from the calling block's own rng
SAMPLE_IF_TRUE 3
SIN 1 math.sin, radians
SINH 1 math.sinh, radians
SMOOTH 2..3 SMOOTH(x, tau[, init]): first-order information delay (init defaults to x at t0); needs simulation.sd
SMOOTH3 2..3 SMOOTH3(x, tau[, init]): third-order information delay (init defaults to x at t0); needs simulation.sd
SQRT 1 math.sqrt (the upper-case twin of sqrt)
STEP 2 STEP(h, t0): h from t0 on, else 0
SUM 1..3 SUM(x): x summed over every element its "[]" (or subrange "[North]") indexes run over (subscripts); SUM("pop", "attr"[, "state"]): an attribute summed over a population's agents (in that state)
TABLE 2..3 a value from the model's lookup table NAME, by 1 or 2 keys
TABLE_EXTRAPOLATE 2..3
TAN 1 math.tan, radians
TANH 1 math.tanh, radians
TREND 2..3
TRIA 3 triangular(low, mode, high), sampled from the calling block's own rng
TS 1..2 TS("name"[, t]): time-series input NAME now, or at time t
UNIF 2 uniform(low, high), sampled from the calling block's own rng
VAR 1 VAR("name"): model variable NAME, for a name a bare name cannot spell
VMAX 1
VMIN 1
XIDZ 2..3 XIDZ(a, b[, x]): a / b, or x (default 0) when b is 0
ZIDZ 2 ZIDZ(a, b): a / b, or 0 when b is 0
abs 1 plain Python
ceil 1 math.ceil
exp 1 math.exp
float 1 plain Python
floor 1 math.floor
int 1 plain Python
log 1..2 1-2 args, math.log
log10 1 math.log10
max 1..n variadic, plain Python
min 1..n variadic, plain Python
round 1..2 1-2 args, plain Python
sqrt 1 math.sqrt