Quodsi Docs

State

A state is a value the model remembers. Use one when what happens next depends on something that happened earlier.

What it is

A state is a named, typed value. Think of a patient's acuity, a part's rework count, or a running total of orders. If you've used attributes or variables elsewhere, states do the same job. You define each state once, on the Model editor's States tab.

The question it helps answer

Does the work behave differently depending on what it is or what's happened to it? Urgent cases jumping the queue, parts that fail twice being scrapped, and orders of different sizes all need a value that travels with the work.

How it behaves

Component Type sets who holds the value. It's the most important choice you make for a state, because each type behaves differently.

Component TypeWho owns the valueWhen it's createdWhat can change itWhat can read it
entityEach entity has its own copy. Every entity type gets every entity state.When the entity is created, at Initial Value.A generator's States tab, a schedule row, Assign State, a Delay, a connector, and Split, Create and Join for the new entity. The change lands on the entity running that step.Conditions, Expressions, Queue Ranking and Match State.
modelOne value, shared by the whole model.At the start of each replication.All of the places above, from any entity.Conditions and Expressions, and the States option in animation. Queue Ranking and Match State can't read it.
activityEach activity has its own copy.At the start of each replication.Assign State or a Delay on an activity. The change lands on that activity's own copy.Nothing in the model. Only your results show it.
resourceEach resource has its own copy.At the start of each replication.A change on any of the places above, where you pick which resource it lands on.Nothing in the model. Only your results show it.
The State list in a change shows every state, but not every state works everywhere. An activity state can't be changed from a connector, a generator, a schedule row, or Split, Create and Join, because none of those can say which activity to change. Validation stops the model until you remove the change.

Data types

Data Type sets what a state can hold and what you can do with it.

Data TypeDefault Initial ValueOperationsExpressionComparisons
number0assign, sample, add, subtract, multiply, divideYesequal, not_equal, greater_than, greater_equal, less_than, less_equal
stringBlankassignNoequal, not_equal. Text must match exactly, including capitals.
booleanfalseassign, sampleYesequal, not_equal
categoryThe first value in the listassign, sampleNoequal, not_equal

A number state has no minimum or maximum, and it can go negative. It keeps fractions, so adding 0.5 to 0 gives 0.5. A category state can only hold a value from its list.

Changing a state

A change picks a State, an Operation, and a value. You can add changes in these places:

Changes run in the order listed, and each sees the one before. Set qty to 7, then set total to qty * 2, and total is 14.

OperationWorks onWhat it does
assignAll data typesSets the value.
add, subtract, multiplynumberDoes the arithmetic on the current value.
dividenumberDivides the current value. Dividing by 0 stops the run, with a message naming the step, the state and the time. The form and validation both accept it, because a value can reach 0 during the run.
samplenumber, boolean, categoryDraws a new value at random each time the step runs. Use it for "30% of patients are urgent".

Reading a state

Queue Ranking and Match State read the entity's own states. A condition reads an entity state or a model state, and so does an Expression. A condition on an activity or resource state is refused, because validation stops the model first.

Conditions on a model state

A model state is one value for the whole model, so a condition can use it as a switch that every entity sees. This works in all three places a condition appears: a connector's State Condition, an action's State Condition (Only if… in Recipe) and a Branch action.

When the warm-up ends

Each replication starts every state fresh at its Initial Value. At the end of a warm-up, a state's statistics restart from the value it holds. The value itself stays, so routing and queues carry on as they were.

For model, activity and resource states, tick Reset value at warm-up end to also put the value back to Initial Value. In a test with a model state adding 1 every 6 minutes, a 2-hour run and a 1-hour warm-up, the final value was 20 without the reset and 10 with it. The reset itself doesn't count as a change. Use it for running tallies. If a state drives a condition, the reset changes what entities read after the warm-up: they see the starting value again, not the value the run had set.

Entity states never reset. An entity in flight keeps its value, and its statistics count from the end of the warm-up. An entity that left before then is left out. With no warm-up, the reset does nothing.

In your results

Each state with Collect statistics on gets a row in the results. They cover the time after any warm-up, across replications. Add a card from the States group on a dashboard, such as Final, Max or Min. In a study, the Tradeoff View can plot them too.

ResultShown forWhat it means
Number of changesAll data typesHow often the value changed. Setting a state to the value it already holds doesn't count. For an entity state, it's the average per entity.
Final valuenumberThe value at the end of the run. For an entity state, it's the average across entities, each at the moment it left or at the end of the run.
Time-weighted averagenumberThe average value over time. For an entity state, an entity that held a value longer counts for more.
Lowest value, Highest valuenumberThe extremes reached. The Initial Value counts only if the state held it for some time, so a value a generator sets at creation replaces it. After a warm-up, the value at the end of the warm-up counts.
Most common valuecategoryThe value held for the most time.
Percent of time truebooleanThe share of time the state was true, from 0 to 100.

A string state shows only its number of changes. Entity states report one row per entity type, so you can compare a state across types. Activity and resource states report one row for each activity or resource, even one that never changed it. Model states report one row, named Model.

Changing a starting value in a what-if

A what-if can change a state's Initial Value, and you can make it a lever. This lets you ask "what if the mix, the mode or the starting stock were different?" without editing the state.

A value reached for no time still counts as a Lowest or Highest value: going to 20 and straight to 10 at the same moment shows a Highest value of 20. A category value never held isn't listed, not even at 0%. If every entity leaves before the warm-up ends, its entity state has no row, because no entity was there to measure. A divide leaves a decimal behind, so 6 divided by 2 then plus 1 holds 4.0, not 4. It reads the same in results.

A number state holds only numbers, so true or false is refused, as is a sample on a string state, because there's no distribution of text.

Properties

What you can edit depends on the complexity view. A view only changes what you can edit, never what runs.

WhereLowest view
States tab on the Model editorIntermediate
States tab on a generatorIntermediate
Assign State action, and State Modifications on a DelayIntermediate
State Condition on an actionIntermediate
State Condition routing, On departure and On arrivalIntermediate
Queue RankingAdvanced
Split, Create and Join actionsAdvanced
Schedule rows on a generatorAdvanced

States tab

With nothing selected on your diagram, open the Model editor and choose States. The tab says: State variables track custom numeric or text values on simulation objects. Use them for conditional routing, tracking entity attributes, or counting occurrences. Boolean and category states work too.

PropertyWhere to find itWhat it does
FilterTop of the tab.Shows All Components, or one type, such as entity Only. It also sets the Component Type a new state starts with.
Add StateTop of the tab.Opens the form. With no states yet, the tab says No states defined yet. Click "Add State" to create your first.
State rowThe list.Shows the name, Component Type, Data Type and initial value, such as initial: 0.
EditPencil on the row.Opens the same form. See Changing a state later.
DeleteTrash icon on the row.Opens a box under the row. See Deleting a state.

Add State form

Add State opens this form. The pencil opens the same form, headed Edit State.

PropertyWhere to find itWhat it does
NameForm.Required. Starts with a letter or underscore, then letters, digits and underscores only, so no spaces. Capitals matter. The form shows Name is required, or Name must start with a letter or underscore and contain only letters, digits, and underscores. Names must be unique across the whole model, whatever the Component Type, or you'll see Another state named "x" already exists.
Component TypeForm.model, entity, resource or activity. Starts on the filter's type, or model when the filter shows all.
Data TypeForm.number, string, boolean or category. Default number. Changing it resets Initial Value to that type's default. Leaving category clears Category Values.
Category ValuesForm. category only.The allowed values, one per row, with spaces trimmed and blank rows ignored. At least 2, or you'll see CATEGORY type requires at least 2 values (e.g. "low, high"). All different, or duplicates are marked and you'll see CATEGORY values must be unique. + Add value or Enter on the last row adds a row. Pasting a comma-separated list splits it into rows. The × removes a row, and it's disabled at 2 rows.
Initial ValueForm.The value at the start. A box for number, which treats blank as 0 and has no limits. A box for string. true or false for boolean. A list for category, showing (no values) until you've added some. If you remove the value it's set to, it moves to the first in the list.
DescriptionForm.Optional note. Shows only in this form. The run doesn't use it.
Collect statisticsForm.Default on. When off, the state has no row in your results, and the animation's States option doesn't follow its changes. The value still changes, and conditions and Expressions still read it.
Reset value at warm-up endForm. Not for entity states.Default off. See When the warm-up ends. The form says: The history always restarts at the end of the warm-up; tick this to also put the value back to its initial value — for running tallies, not for flags that drive routing. An entity state saved with it ticked shows it ticked and disabled, because it has no effect.

In the Intermediate view, the form also shows a Lever tick for a model or entity state that a what-if can change. See State starting values as levers.

Validation also warns about a state named now, abs, min, max or round. It works everywhere except inside an Expression. Words such as if, class and not have the same limit, with no warning until an Expression uses them.

Add State Modification form

Add modification opens this form from any of the places above. It's disabled with no states in the model. The list then shows each change, with edit and delete buttons.

PropertyWhere to find itWhat it does
StateForm.The state to change, listed with its type, such as qty (entity · number). Every state in the model is listed. Starts on the first. Changing it resets the value.
ResourceForm. Resource states only.Which resource the change lands on. Each resource has its own copy of the state. You must pick one before saving. If you later delete that resource, the change stays and shows it as missing, and the model won't run until you pick another or remove the change. In the Recipe view this is the on choice in the sentence, which starts on the first resource.
OperationForm.The operations that state's Data Type allows. Default assign. A sample saved on a string state by an older model stays listed, disabled, and blocks saving until you choose assign.
Value or ExpressionForm. number and boolean only, not for sample.Choose Value to type a literal, or Expression to calculate one each time the step runs. See Expressions. Default Value.
ValueForm.Matches the Data Type: a box for number, a box for string, true or false, or a list of category values. A blank number box counts as 0. A category state starts on its first value.
Sample distributionForm. sample only.Where the random value comes from. See Sample fields.

Assign State also has a Recipe view, with sentences such as Increase qty by 1. See Activity. Recipe has no Expression or sample. Those show there, and open through edit in Classic.

Sample fields

PropertyWhere to find itWhat it does
Distributionnumber states.Constant, Uniform, Normal, Triangular or Exponential. Default Constant, with Value 0. Each choice starts with its own values, shown below. The units are whatever your state means.
Min, MaxUniform, starting at 0 and 1.Uniform: min must be ≤ max.
Mean, StdNormal, starting at 0 and 1.Normal: std must be > 0. A Normal draw can be negative.
Min, Mode, MaxTriangular, starting at 0, 0.5 and 1.Triangular: min ≤ mode ≤ max.
ScaleExponential, starting at 1.Exponential: scale must be > 0.
P(true)boolean states.The chance of true, from 0 to 1, with P(false) below it. The box shows 0.5, but nothing is set yet, so the form shows p must be between 0 and 1 until you change the box.
Probabilitiescategory states.One box per value, from 0 to 1, with its percentage. A new sample starts with every value on the same share. The sum must reach 1, to within 0.000001, and the form shows Probabilities must sum to 1.000 (currently 0.900) until it does. Normalize scales your numbers to total 1. Equalize gives every value the same share.

Expressions

Enter a formula in Expression value, such as qty * unit_price. It gives a list of readable states as you type. On add, subtract, multiply or divide, the result is the amount: adding qty * 2 with qty at 4 adds 8.

Under the box it says: Operators: + - * / , comparisons (chainable: 0 < qty < 10), and/or/not, A if cond else B. Functions: abs(), max(), min(), now(), round(). Reference a state by typing its name.

The form checks as you type, and won't save with an error, such as Unknown state 'x', Expression mixes incompatible types, or Expression produces boolean, but 'qty' is number. Validation checks it again. A few names get past the form, such as a state called class, and validation then stops the model.

State Condition fields

Actions and connectors share this editor. On an action, open the State Condition section, or Only if… in Recipe. It reads State Condition (active) once set. An action that fails its test is skipped. For connectors, see State Condition fields.

Press Add state condition to start. It fills in the first entity state, or the first model state if there is no entity state, with equal and that state's default value, so check all three fields. With no states, the card says Define states first — switch to the States tab. With states but none on entities or the model, it says Define a State first.

PropertyWhere to find itWhat it does
StateEditor.Entity states are listed first, then model states, each with its scope and data type. A condition saved on an activity or resource state stays listed, disabled, with Conditions read an entity State or a model State, so this one would stop the run. Choose one of those. Validation stops the model until you do. A connector's condition only counts while its source routes by State Condition. Changing the state resets Value, and resets Comparison to equal if the new type doesn't offer it. A deleted state shows as (missing state: …).
ComparisonEditor.Every data type has equal and not_equal. Number states add greater_than, greater_equal, less_than and less_equal.
ValueEditor.What to compare against. A box for a number or text state, true or false, or a list of category values. A value no longer on the list shows as (missing value: …). The test still runs, with no warning: equal is never true and not_equal is always true. A category condition with no value shows (choose a value).
Clear conditionEditor.Removes the condition. The action then always runs.

Deleting a state

The trash icon opens a box headed Delete State: "qty"?, with Delete State and Cancel. It ends with This action cannot be undone. Here's what happens to what used the state.

What used the stateWhat the delete does
Changes to itRemoved, on generators, activities and connectors, including inside Branch and Loop.
A State Condition on an actionRemoved, so the action now always runs. On a Branch, the true path always runs. The box tells you how many Branches this affects, and validation warns about each one until you choose a new condition.
A State Condition on a connectorRemoved. That connector is then never taken. See Connector.
Queue RankingRemoved. The queue goes back to first come, first served.
Inherit States, Split Index State, Join Count StateCleared.
Match StateCleared. A Join needs one, so the model can't run until you choose another.
An Expression naming itLeft as it is. Validation stops the model until you fix it.
A schedule row with a value for itCleared from that row. The box tells you how many rows this affects.

The box counts the shapes it will change: 1 place — activities, generators, or connectors — uses this state directly and will be updated automatically. In Lucidchart it can't count shapes or Branches, so it says Activity and generator steps that use this state directly will have that reference removed automatically., and that an If-then step testing it always takes its true path.

It lists each Expression, with the state it sets, under 1 expression references this state inside a formula and cannot be fixed automatically:, and adds Edit these yourself first — the engine rejects a formula that names a state which no longer exists. You can still delete.

Changing a state later

Edit a state from its row. A new name carries through to everything that uses it. Other edits don't, so the form warns you before you change a type, and validation flags whatever no longer fits.

ChangeWhat happens
Rename itEverything follows the new name: changes, conditions, Queue Ranking, Expressions, schedule rows, Inherit States, Split Index State, Join Count State and Match State. The one exception is a script, which is free text. Update those yourself.
Change Data TypeExisting changes stay. Validation stops the model at any that no longer fit, such as an add on a state that's now text, and at Queue Ranking on a state that's no longer a number.
Change Component TypeExisting changes and conditions stay. Validation stops the model at a condition on a state that is no longer an entity or model state, and at a change that can't say which component it lands on.
Remove a category valueValidation stops the model at a change, sample or schedule row that uses it. Reopening a sample and saving drops the removed value. A condition testing it is never true, and nothing flags that.
Add a category valueValidation stops the model at a sample that doesn't list it. Reopen the sample and set the new value's share.

Example

In an emergency department, urgent patients should jump the queue. Add an entity state named acuity with Data Type number. Use one generator for urgent arrivals and one for routine arrivals. On each generator's States tab, add a modification that assigns acuity: 1 for urgent and 2 for routine. Then, in the Advanced view, set Queue Ranking on Triage to Serve by acuity, with Order set to Lowest value first. Your results now show how much the routine patients pay for that.

To count urgent arrivals as well, add a model state named urgent_count. On the urgent generator's States tab, add a second modification that adds 1 to it. Its Final value is the average count per replication. If your model has a warm-up, tick Reset value at warm-up end so the count covers the same window as the rest of your results.

Common mistakes

Related pages