States

A State is in effect an on/off switch. When the State is active, the model is in that state; when the State is inactive, the model is not in that state.

States are primarily useful when carrying out Agent Based Modeling. One or more sets of States may be placed in an agent to describe the current state of that agent. For instance, if you are modeling a population of individuals, you could have your agent definition contain a State representing whether or not an agent was a smoker. Similarly, you could have a State representing whether or not an agent was a female. For continuous variable (such as age) a Stock should be used; but for binary or dichotomous variables, a State is a more natural primitive.

States are not limited to agents, though. Anywhere a piece of your model needs to be switched on or off — a pump, a policy, a subsidy — a State can act as that switch, and other equations can read it.

A State is configured using its initial value equation. This equation may be a simple value such as: 1 or true for active, or 0 or false for inactive. The equation can also be a logical equation such as the following:

not true

Or a simple mathematical equation:

5*5 > 10

Or a formula that depends on other primitives. The model below is a tub of water: the Fill Flow adds water and the Drain Flow removes it. The Tap Open State is the switch that governs the filling. Fill is IfThenElse([Tap Open], 10, 0), so it runs at 10 a minute while the switch is on and drops to zero while it is off. The switch itself is a logical equation, [Water] < [Full Mark]: the tap starts open only if the tub starts below the full mark. Set Starting Level above 80 and the tap never opens, leaving the drain to empty the tub:

{ "engine": "SIMULATION_PACKAGE", "name": "A State as an On/Off Switch", "simulation": { "algorithm": "RK1", "time_start": 0, "time_length": 20, "time_step": 0.25, "time_units": "MINUTES" }, "elements": [ { "type": "VARIABLE", "name": "Starting Level", "behavior": { "value": "30" }, "display": { "interactive": true, "interactive_min": 0, "interactive_max": 100 } }, { "type": "VARIABLE", "name": "Full Mark", "behavior": { "value": "80" } }, { "type": "STOCK", "name": "Water", "behavior": { "initial_value": "[Starting Level]", "non_negative": true } }, { "type": "STATE", "name": "Tap Open", "behavior": { "initial_value": "[Water] < [Full Mark]" } }, { "type": "FLOW", "name": "Fill", "from": null, "to": "Water", "behavior": { "value": "IfThenElse([Tap Open], 10, 0)" } }, { "type": "FLOW", "name": "Drain", "from": "Water", "to": null, "behavior": { "value": "4", "non_negative": true } }, { "type": "LINK", "from": "Starting Level", "to": "Water" }, { "type": "LINK", "from": "Water", "to": "Tap Open" }, { "type": "LINK", "from": "Full Mark", "to": "Tap Open" }, { "type": "LINK", "from": "Tap Open", "to": "Fill" } ], "visualizations": [ { "name": "Water Level", "type": "TIME_SERIES", "elements": [ "Water", "Full Mark" ] }, { "name": "Tap Open", "type": "TIME_SERIES", "elements": [ "Tap Open" ] } ] }

The second chart shows the switch itself: whichever value it takes at the start, it holds for the whole run. A State's initial value equation is evaluated once, when the simulation begins, so with the tap open the tub keeps filling straight past the Full Mark and overflows. To flip a State part way through a run, you need a Transition.