Skip to content

Quisim Troubleshooting Guide ​

Overview ​

This guide helps when a model does not do what you expect. It has two parts:

  • Part 1: Messages lists the errors and warnings Quisim shows, grouped by when they appear: while loading the model, while connecting blocks, while running and while reading results. For each message you find what it means, what usually causes it and how to fix it.
  • Part 2: Modeling pitfalls covers the harder cases: Quisim shows no message, but the results are wrong or surprising.

How to use the error list itself (colours, clicking, the fix buttons) is explained in the UI guide. Questions about the interface, such as my model does not start or nothing moves on the canvas, are answered in its Troubleshooting and FAQ. Blocks and their attributes are described in the API reference, the concepts in the handbook.

The code examples are short pieces of a model. Lines such as // leave0: further blocks of the model mean that you add the remaining blocks yourself.


Part 1: Messages ​

How to read a message ​

Every entry in the error list starts with the item it belongs to:

The entry starts withIt belongs toExample
line N column M:the code as a whole (the model could not be loaded)line 3 column 17: Queu is not a type
a block namethe label, else its type nameArrive: outlet is blocked at time 1234.5
Pipe from … to …a pipe, named by block id and socket labelPipe from arrive0.O to ?: 'to' not found
Wire from … to …a wire, named by block label and socket labelWire from Exp.V to Perform.D: to is fixed

A ? stands for a socket Quisim could not find. Because several blocks can share the same label (for example two blocks both called Arrive), hover over the entry to see which block is meant: it is highlighted on the canvas.

Red or yellow. Red entries are errors: a red error in the code means the model cannot be loaded, and a red error during a run stops the run. Yellow entries are warnings: the model keeps running, but probably not as you intended.

When entries go away. All entries are cleared whenever the model is reloaded from the code (Reload, Ctrl+D, or clicking outside the editor after typing). Warnings that name a time (… at time 1234.5) are cleared at the next Start clean. Warnings about a setting, such as the timeAverage warning, disappear as soon as you change that setting.

Where messages do not reach you. Quisim does not check attribute values that you write in the code. The Properties tab refuses invalid input (it turns red, see Changing a value), but Queue { id: queue0; capacity: -1 } typed into the code is accepted without a message. Mistakes inside the JavaScript of a Function or Explorer block do show up, see Running.

Tip: when the error list shows entries, the Explainer can explain them for your model.

In the entries below, variable parts are written in angle brackets, for example <t> for a time and <label> for a block label.

Loading a model ​

These errors appear when the code is applied: when you open a file or example, press Reload (Ctrl+D), or click outside the editor after typing. They are red and start with line N column M:. Click the entry to move the text cursor there. The model is not loaded until all of them are fixed; the canvas keeps showing the last model that loaded.

line N column M: Cannot assign to non-existent property "<name>" ​

  • Meaning: The block has no attribute called name.
  • Typical cause: A typo (capacty, Duration instead of duration), an attribute that belongs to another block type, or a model written for an older Quisim version.
  • Fix: Check the spelling against the block's Attributes table in the API reference. Attribute names are case-sensitive. To drive a value through a wire, use the connector name in a Wire, not in the block (see How to Read an Entry).

line N column M: Cannot assign to non-existent property "<old>", please use "<new>" instead ​

  • Meaning: The model uses an attribute name from an older Quisim version.
  • Fix: Click the Rename to "<new>" button on the entry. Quisim renames it in the code and reloads. The renamed attributes are:
Old nameNew nameBlock
initCodecontextFunction
haltLastOnCapacityDecreasehaltExcessPerform
warmupDurationwarmupWidthStatistics
batchDurationbatchWidthStatistics
timeBatchingtimeWidthsStatistics
valueinitValueNumberInput
resetOnRunStartclearBetweenReplicationsChart

line N column M: Cannot assign to non-existent property "renegeLastOnOverflow", it was replaced by "preemptive" and the evict outlet E ​

(also for the older name renegeOnOverflow)

  • Meaning: The model uses the Queue attribute that let a newcomer at a full queue displace the entity served last through outlet R. This is now the attribute preemptive, and pushed-out entities leave through their own outlet E (outEvict).
  • Fix: Click Replace by "preemptive". If the value was true, Quisim writes preemptive: true and adds, for every pipe from <queue>.outRenege, a pipe from <queue>.outEvict to the same target. If the Queue has no renege duration (neither set nor wired), the pipe is moved from R to E instead of copied. If the value was false, or the block is an Unpack, the attribute is just removed. To fix it by hand, do the same in the code. To also evict after a capacity drop, add evictExcess: true yourself. See Queue for how eviction works now.

line N column M: Invalid property assignment: "value" is a read-only property ​

  • Meaning: This appears for NumberInput { value: … }. The current value of a NumberInput is read-only; its starting value is initValue.
  • Fix: Click Rename to "initValue", or write NumberInput { id: numberInput0; initValue: 5 }. See NumberInput.

line N column M: <Type> is not a type ​

  • Meaning: There is no block type with this name.
  • Typical cause: A typo (Queu, queue; type names start with a capital letter), or a block from a newer Quisim version.
  • Fix: Use a type name from the Contents of the API reference.

line N column M: Expected token `}' (or `;', `,') ​

  • Meaning: The code is not well-formed, so Quisim cannot read it at all.
  • Typical causes:
    • a missing closing brace: Queue { id: queue0 (the line number may point to the end of the code),
    • attributes separated by a comma instead of a semicolon: Queue { id: queue0, capacity: 5 },
    • a unit after a number: Perform { id: perform0; duration: 5 min }. Quisim time has no units, see Time Units,
    • an unclosed string or comment.
  • Fix: Every block is written Type { key: value; key: value } on its own line. See The Modeling Language.

line N column M: id is not unique ​

  • Meaning: Two blocks have the same id.
  • Typical cause: Copying a block and pasting it with plain Paste.
  • Fix: Rename one of them, and update the pipes and wires that should refer to it. Paste with unique names (Ctrl+Alt+V) avoids the problem, see Copy and paste.

line N column M: IDs cannot start with an uppercase letter / IDs must contain only letters, numbers, and underscores ​

  • Meaning: The id is not a valid name.
  • Fix: Start with a lower-case letter or _ and use only letters, digits and _: queue_1, not Queue1 or queue-1. See the type Id.

line N column M: Invalid property assignment: number expected (or boolean expected, color expected) ​

  • Meaning: The value has the wrong kind.
  • Typical causes: A number in quotes (capacity: "5"), a truth value in quotes (ascending: "false"), or a colour name Qt does not know (color: "blau").
  • Fix: Write numbers and true/false without quotes. Write colours as "#ff8800" or an English colour name. See Attribute Types.

line N column M: Property value set multiple times ​

  • Meaning: The same attribute appears twice in one block, for example Queue { id: queue0; capacity: 5; capacity: 6 }.
  • Fix: Delete one of them.

line N column M: Cannot assign primitives to lists ​

  • Meaning: A value was assigned to an indexed socket inside a block, for example Statistics { parameters[0]: 5 }.
  • Fix: Indexed sockets are connected with a Wire, never set inside the braces. To feed a constant, use a Number block and a wire.

line N column M: Required property to was not initialized (or from) ​

  • Meaning: A Pipe or Wire lacks its to: (or from:) part.
  • Fix: Every connector needs both: Pipe { from: queue0.outlet; to: perform0.inlet }. See Connectors.
  • Note: The line and column of this message refer to Quisim's own definition of the Pipe or Wire, not to your code. Look for the connector without to: or from: yourself.

Connecting blocks ​

These yellow warnings appear when the model is loaded, one for each pipe or wire that could not be connected. The rest of the model still loads and runs, but without that connection. They stay in the list until the model is reloaded.

Pipe from <block.socket> to ?: 'to' not found / Pipe from ? to <block.socket>: from not found ​

  • Meaning: The pipe could not find one of its ends, so it was left out.
  • Typical causes:
    • The block id is misspelled or the block was deleted: to: leave1.inlet when the block is called leave0.
    • The socket name is wrong or belongs to a wire: from: arrive0.measureNumPassed (a measure) in a Pipe.
    • The index is too large: from: decide0.outlets[2] with the default numOutlets: 2 (indices start at 0).
  • Fix: Check the id and the socket name in the block's Entity inputs/outputs table. For indexed sockets, raise numOutlets, numInlets or numConnectors first, see Indexed connectors. Entities that reach the unconnected outlet are blocked, so a second warning such as outlet is blocked usually follows.

Wire from <block.socket> to ?: to not found / Wire from ? to <block.socket>: from not found ​

  • Meaning: The wire could not find one of its ends, so it was left out. The value is not transmitted.
  • Typical causes: As for pipes, plus the most common one: wiring to statistics0.parameters[1] while the Statistics block still has numParameters: 1.
  • Fix: Check the id and the connector name (measure… for from, parameter… or parameters[i] for to). Raise numParameters or numMeasures before using a further index.

Wire from <block.socket> to <block.socket>: to is fixed ​

  • Meaning: The target attribute is also set as a constant in the block, so the wire is ignored. The constant wins.
  • Typical cause: Perform { id: perform0; duration: 50 } together with Wire { from: rnd1.measureRandomVariate; to: perform0.parameterDuration }. The service time stays 50 and the random block is not used.
  • Fix: Remove the constant from the block (or click the lock icon in the Properties tab). Use either a constant or a wire, see How to Read an Entry.

Pipe from <set.O> to <get.I>: Connecting Set and Get blocks without intermediate step: Get will read previous attribute value. Consider adding a Perfom block in between. ​

  • Meaning: A Set block is piped directly into a Get block for the same attribute. The Get block reads the attribute while the entity is being offered to it, before the Set block has written the new value. So Get sees the old value (or nothing, if the attribute was never set).
  • Fix: Put a block in between, for example a Queue or a Perform with duration: 0. See Set and Get.

Error creating Pipe: from block has no id. (also to block, and Wire) ​

  • Meaning: You drew a connection on the canvas to a block that has no id in the code, so the connection cannot be written.
  • Fix: Give the block an id in the code (Queue { id: queue1 }), then connect again.

Rare: 'from' is not an Outlet, 'to' is not an Inlet, from is not a Valout, to is not a Valin. In practice a pipe between wrong socket types shows as not found (above). The fix is the same: pipes connect entity sockets, wires connect data sockets.

Queue or Perform: outlet E is not piped / E is piped, but no job or entity will leave through it ​

  • Meaning: A yellow warning when the model is loaded.
    • Queue with evictExcess or preemptive but no pipe from E (outEvict): a queue cannot halt anyone, so no entity will be evicted; the Queue behaves as if both were off.
    • Queue with a pipe from E but neither evictExcess nor preemptive, or Perform with a pipe from E but neither haltExcess nor preemptive: nothing ever makes an entity excess, so E never carries one.
    • A Perform with haltExcess or preemptive and no pipe from E gets no warning: its excess jobs are halted and resume later.
  • Fix: For a Queue set a trigger together with the pipe: Queue { id: queue0; evictExcess: true } (capacity drops) or preemptive: true (arrivals at a full queue), plus Pipe { from: queue0.outEvict; to: … }. For a Perform set haltExcess or preemptive, or remove the pipe. Outlet E is shown on the canvas as soon as a trigger or the pipe is present. See Queue and Perform.

Running a model ​

Arrive: outlet is blocked at time <t> ​

  • Meaning: At time tt an Arrive block created a new entity, but its previous entity had not left yet, because no block behind it accepted it. The arrival is held back until the outlet is free, and the next inter-arrival time only starts then. This message is repeated for each blockage, so you may see many entries.
  • Typical causes:
    • No Queue in front of a busy Perform block (Arrive → Perform). See Arrive → Perform: why a Queue is needed in Getting Started.
    • A Queue with a limited capacity that is full, or capacity: 0.
    • A Decide block that selects no outlet (selectedOutlet −1, not wired, or too large), see pitfall: Decide index.
    • An outlet further down with no pipe at all.
  • Fix: Put a Queue in front of the block that is busy. If losing or rejecting customers is part of your system (a full waiting room), model it explicitly, for example with a Decide on the queue length. Do not just ignore the warning: the arrival rate in your model is then lower than the one you specified, see pitfall: blocked entities.

Arrive: duration is NaN ​

  • Meaning: Red error, the run stops. The inter-arrival time is not a number.
  • Typical cause: duration: NaN written in the Arrive block.
  • Fix: Give a number, or wire a random block to parameterDuration. Note that a wire delivering NaN does not produce this error; the Arrive block then silently stops creating entities, see pitfall: NaN on a duration wire.

Lineup: outlet <id>.O<i> is blocked at time <t> ​

  • Meaning: The Lineup block had collected its entities, but at the moment of sending one of the targets could not take its entity.
  • Fix: Put a Queue behind each Lineup outlet. See Lineup.

Provide: blockage at time <t> and Pack: overflow at time <t> ​

Both are rare. Provide reports that a new entity was due while the previous one was still waiting. Pack reports that a packet holds more entities than its capacity, which can happen when the capacity is lowered by a wire during packing. See Provide and Pack.

Function: <JavaScript error> ​

  • Meaning: The JavaScript in the code, context or init attribute of a Function block failed. The text is the JavaScript error, for example:
    • Parse error: the code is not valid JavaScript (M[0]=P[0]+). No line number is given.
    • ReferenceError: foo is not defined: a name that does not exist, often a misspelled function (math.sqrt instead of Math.sqrt) or a variable that should have been defined in context.
    • TypeError: …: for example reading a property of undefined.
  • Fix: Correct the code in the Properties tab (text button opens a larger box). Separate statements with ;. Remember that P and M start at index 0. See Function. Errors during a run are repeated each time the function is evaluated.

Function: M must be an array of length <n> ​

  • Meaning: The code wrote more measures than the block has. M[1]=… with the default numMeasures: 1 is one too many.
  • Fix: Raise numMeasures, or write only to M[0] … M[numMeasures−1]. The values of this evaluation are discarded.

Aggregate: <JavaScript error> and Explorer: <JavaScript error> ​

The same as for Function. The code of an Aggregate uses A and V (A+=V), not P and M. The code of an Explorer needs yield to start each run.

Reading results ​

Statistics: timeAverage is not set, but P[<i>] is wired with an outlet recommending time averaging ​

Also shown by Histogram and EnsemblePlot.

  • Meaning: Input P[i] receives a level that holds over time, such as a queue length (queue0.measureLoad) or the number of busy servers (perform0.measureLoad). Its plain arithmetic mean is wrong, because it ignores how long each value held.
  • Fix: Set timeAverage: true on this block. If the same block also receives per-entity values such as waiting times, which need timeAverage: false, use two Statistics blocks. See Which mean? and pitfall: wrong kind of mean.

Statistics: cumulative is not set, but P[<i>] is wired with an outlet recommending cumulative ​

  • Meaning: Input P[i] receives a running count, such as arrive0.measureNumPassed. Averaging a count that only grows gives a meaningless number (roughly half the final count).
  • Fix: Set cumulative: true to report the increase over the run, in a Statistics block of its own. See Statistics.

Statistics: Both batchWidth and numBatches are set in count-batching mode; batchWidth wins, numBatches is ignored ​

  • Meaning: With timeWidths: false, batchWidth (records per batch) and numBatches both define the batches. Quisim uses batchWidth.
  • Fix: Set only one of them. Leave batchWidth at NaN to derive it from numBatches.

Statistics: warmupMSER is set but warmupWidth is nonzero; the MSER suggestion will be ignored ​

  • Meaning: The automatic warm-up (MSER-5) only works while warmupWidth is 0. You set both.
  • Fix: Either set warmupWidth: 0 to let MSER choose, or turn warmupMSER off and keep your own warm-up.
  • Meaning: You clicked the button that opens the data in an online R or Python notebook, but there is too much data to fit into a web link.
  • Fix: Follow the advice in the message: use the Copy … as CSV/TSV menu entry instead and paste the data into your own tool, or shorten the run or use fewer replications.

Starting, signing in and the Explainer ​

These messages do not appear in the error list but in the start screen, the sign-in dialog or the Explainer. The UI guide explains the dialogs.

MessageWhat to do
resource loading error / please check the internet connection. (also resource loading error, ret=<code>, resources loading error reply)The release version loads its interface from quisim.com. Check the internet connection and start Quisim again.
resources registration errorThe downloaded interface could not be used. Start Quisim again; if it persists, download the current version from quisim.com.
Port <n> is already in use, most likely by another copy of Quisim. …Close the other Quisim window, then click Try again.
Could not open a browser. Open this address manually: <url>Copy the address into your browser.
Token request failed: …, Could not reach the sign-in server: …, Could not reach quisim.com: …Network problem. Check the connection and click Try again.
Sign-in was answered by an unexpected request (state mismatch). …, The identity token was not valid (…). …, The sign-in server returned no access token.Click Try again. If it repeats, check that your computer's date and time are correct.
This session is no longer authorised. Please sign in again.Sign in again. Your model stays open.
Thank you for using Quisim. This version is outdated. …Download the current version from quisim.com.
Explainer: AI server cannot be reachedTry again later. A long wait while the status says connecting is normal, see the FAQ.

Part 2: Modeling pitfalls ​

In these cases Quisim shows no message, or only a warning that is easy to overlook, but the numbers are not what you intended. Each pitfall has the symptom, the reason and a fix. The numbers quoted come from runs of the small example models shown.

A general rule first: before trusting results, verify the model against a case you can compute, such as M/M/1, see Verification checklist.

Pipe priority: the pipe written last is tried first ​

Symptom. One outlet is piped to two blocks, for example a Queue feeding two machines. You expect the first machine to be used first, but all entities go to the second one.

Why. The declaration order in code matters. When several pipes leave the same outlet, the entity is offered to them in reverse order of the code: the pipe defined last is tried first. Only if that target is blocked is the entity offered to the next one. The same holds for several pipes into the same inlet, and for wires. Hover a pipe to see its priority number (1 is tried first).

animationanimation
Model codeOpen in Quisim
qml
Arrive { id: arrive0; duration:500 }
Perform { id: perform0; label:'Perform 0' }
Perform { id: perform1; label:'Perform 1' }
Pipe { from: arrive0.outlet; to: perform0.inlet }   // tried second
Pipe { from: arrive0.outlet; to: perform1.inlet }   // written last: tried first

In a run of 10 000 time units, machine B served all 1000 entities and machine A none. With the two pipe lines swapped, machine A served all of them.

Fix. Order the pipes deliberately: write the preferred target last. Use Move up / Move down (Ctrl+Up / Ctrl+Down) in the editor toolbar to reorder a line. If the choice should be random or rule-based, use a Decide block instead. See Pipe and Entity Handover Protocol.

Decide re-draws a random choice when the outlet is blocked ​

Symptom. A Decide block driven by RandomUniform { lower: 0; upper: 2 } should split entities 50/50, but one branch gets far more than half.

Why. Decide reads its selected outlet S every time an entity is offered to it. If the chosen outlet is blocked (for example a busy Perform block without a queue), the entity waits, and when it is offered again, a new random number is drawn. Entities therefore drift towards the branch that is free, and the split follows the capacity of the branches, not your probabilities.

diagramdiagram

Over 100 000 time units the fast branch received 9015 entities and the slow one 967, although each should get about half of the 10 001.

Fix. Give every Decide outlet a Queue, so that the selected outlet is never blocked:

diagramdiagram

With the queues, the split was 5028 to 4973, as intended (and the slow queue grew, as it should). If instead the choice is meant to depend on which server is free (for example joining the shortest queue), model that rule explicitly, for example with a Function block.

Decide and Select: truncated index, -1, and out-of-range numbers ​

Symptom. Entities get stuck in front of a Decide block, or go to an unexpected outlet. The only message is an outlet is blocked warning further upstream.

Why.

  • The default selectedOutlet is −1, which selects no outlet. A Decide block without a wire into parameterSelectedOutlet blocks every entity.
  • Any number without a matching outlet also selects none: 2 with numOutlets: 2 (the outlets are 0 and 1), or -1.5.
  • Fractions are cut off towards zero: 1.7 selects outlet 1, 0.9 selects outlet 0, and −0.5 selects outlet 0, not −1.
  • NaN or an unset value selects none. This happens when a Get block reads an attribute that the entity does not have, for example because of a misspelled attribute name.

The same rules apply to selectedInlet of the Select block.

diagramdiagram

Fix. Wire a value that is exactly a valid index, 0 … numOutlets−1. For a probability split use RandomUniform { lower: 0; upper: numOutlets; floor:true }. For setting individual probabilities, it is preferable to use the RandomDiscrete block. For more complicated rules, use a Function block with code like M[0] = P[0] < 0.3 ? 0 : 1. When routing on an attribute, check the attribute name in the Set and Get blocks (it is case-sensitive). See Decide.

Blocked entities change the arrival process ​

Symptom. Fewer entities arrive than the inter-arrival time suggests, and server utilization comes out too low. The error list shows outlet is blocked warnings.

Why. An outlet with no free path holds its entity. The block that holds it cannot pass on further entities, so the blockage travels upstream. At an Arrive block, the next inter-arrival time only starts when the blocked entity has left, so arrivals are delayed, not queued. At a Perform block, a finished entity that cannot leave still occupies capacity, so the server looks busy while it is in fact idle.

In an M/M/1 setting (mean inter-arrival time 100, mean service time 80, 10 000 time units), the model without a Queue let 80 entities arrive; with a Queue in front of the Perform block, 91 arrived.

Fix. Put a Queue in front of every block that can be busy. Treat every blocked warning as a modeling error unless blocking is part of the real system (for example a machine that must wait until the next station is free). See Arrive → Perform: why a Queue is needed in Getting Started.

Negative durations are rounded up to 0 ​

Symptom. A service time drawn from RandomNormal { mean: 1; stddev: 5 } gives a mean time in the Perform block far above 1.

Why. Durations cannot be negative. Arrive, Perform, Queue (renegeDuration) and Sampler use 0 instead of a negative value. With a normal distribution whose standard deviation is large compared with its mean, many draws are negative, become 0, and the mean of the durations actually used rises. In the example the sojourn time in an unlimited Perform block averaged 2.52 (theory for max⁡(0,X)\max(0, X): 2.53), not 1.

A duration of exactly 0 at an Arrive block is worse: the Arrive block then creates an unlimited number of entities at the same instant, simulated time never advances and the run does not finish.

Fix. Use a distribution that is never negative for durations: RandomExponential, RandomGamma, RandomWeibull, RandomLognormal. If a normal distribution is really what you need, truncate it with lower: 0 and check its measureExpectedValue (EV), which includes the limits. Never give an Arrive block a duration of 0.

NaN on a duration wire means "never" ​

Symptom. An Arrive block creates one entity and then stops, or an entity enters a Perform block and never comes out. No message.

Why. When a wire delivers NaN or no value at all, the block treats the input as not set and uses Infinity: the next arrival never happens, the activity never ends. Typical sources are a Function block whose input is not wired (P[0] is then NaN, so M[0]=P[0]*2 is NaN), or a Get block reading an attribute the entity does not carry.

diagramdiagram

Fix. Wire every input of a Function block, or set a default in the code: M[0] = isNaN(P[0]) ? 100 : P[0]*2. Hover the sockets during a paused run to check the values, see Reading values on the canvas.

Blocks without a wire use fixed defaults ​

Symptom. The model runs, but nothing looks random, or there is one server where you expected many.

Why. An unwired Arrive or Perform block uses a constant duration of 1000 time units. A Perform block has a capacity of 1 unless you set it. A model without a Steering block runs for 10 000 time units with one replication.

Fix. Wire a random block to every duration that should vary, and set capacity and the Steering block explicitly. Check the Default column in the API reference for each block you use.

RandomLognormal: mean is not the average ​

Symptom. With RandomLognormal { mean: 100; stddev: 0.5 } the model produces astronomically large durations; nothing seems to happen after the first entity.

Why. mean and stddev are the parameters μ\mu and σ\sigma of the underlying normal distribution, on the log scale. The median of the variates is exp⁡(μ)\exp(\mu) and their average is exp⁡(μ+σ2/2)\exp(\mu + \sigma^2/2). For μ=100\mu = 100 the average is about 3⋅10433 \cdot 10^{43}.

Fix. For a desired average mm and log-scale σ\sigma, set μ=ln⁡(m)−σ2/2\mu = \ln(m) - \sigma^2/2. For an average of 100 with σ=0.5\sigma = 0.5: μ=ln⁡(100)−0.125≈4.48\mu = \ln(100) - 0.125 \approx 4.48. Check the result with the block's expectedValue measure (EV), which showed 99.98 for these values; simulated inter-arrival times averaged 101.5.

diagramdiagram

μ\mu may be negative (an average below 1). This works in the code, but the Properties tab does not accept a negative mean.

Statistics: confidence is the tail probability α ​

Symptom. You set confidence: 0.95 to get a 95% interval, and the interval is suspiciously narrow. The column header shows ±5%.

Why. confidence is α\alpha, the probability outside the interval. The interval covers 1 − confidence. With 0.95 you get a 5% interval, which is almost a point.

Fix. Use confidence: 0.05 for a 95% interval (the default) and 0.01 for 99%. See Reading the confidence interval.

Wrong kind of mean: timeAverage and cumulative ​

Symptom. The mean queue length is too high (or too low), or a count comes out as roughly half of what you counted.

Why. A level such as a queue length must be time-weighted; a plain average over the moments when it changed counts short and long stretches equally. A counter such as measureNumPassed must be reported as an increase, not averaged. timeAverage and cumulative apply to the whole Statistics block, so inputs that need different settings cannot share one block. Quisim warns in the error list (see Reading results), but the run goes on.

For the M/M/1 queue with ρ=0.8\rho = 0.8 (theory: mean queue length 3.2), 40 replications with warm-up gave 3.27 ± 1.09 time-weighted, but 4.21 ± 1.04 without timeAverage.

Fix. One Statistics block per kind of measure.

The table in Which mean? lists the right setting for each common measure. A Meter count is reset by its reset input, so with cumulative it only gives the right increase if no reset happens during the run.

Warm-up bias: the model starts empty ​

Symptom. In a study of long-run (steady-state) behaviour, the mean queue length or waiting time is clearly below the theoretical value, especially for short runs.

Why. Every run starts with an empty, idle system. The first part of the run, the warm-up, has shorter queues than the steady state and pulls the mean down. The busier the system, the longer the warm-up lasts.

M/M/1 with ρ=0.8\rho = 0.8, mean queue length, 40 replications each (theory: 3.2):

Run lengthWarm-up removedResult
2 000none1.20 ± 0.40 (interval misses 3.2)
20 000none2.69 ± 0.75
20 0008 0003.27 ± 1.09

Fix. Decide first whether your study is terminating (a natural end, such as a working day: keep the start, no warm-up removal) or non-terminating, see Terminating vs. non-terminating. For a non-terminating study, find the warm-up with an EnsemblePlot over at least 5 replications, or let warmupMSER: true choose it, then cut it off with warmupWidth and run much longer than the warm-up.

warmupWidth is a simulation time (unless timeWidths: false), so it must be smaller than the Steering duration.

Too few replications ​

Symptom. The Statistics block shows no interval at all, or an interval so wide that it says nothing.

Why. A confidence interval needs several independent observations of the mean: replications, or batches within one run. One replication with numBatches: 1 gives no interval. With few replications the tt factor is large and the variance estimate unreliable. The radius shrinks only like 1/m1/\sqrt{m}: halving it needs four times as many replications.

Same M/M/1 model as above (20 000 time units, warm-up 8 000): 3 replications gave 2.67 ± 3.46, 40 replications gave 3.27 ± 1.09.

Fix. Use at least 10 replications for a first estimate, then increase until the interval is narrow enough for your question. Set them in the Steering block (R), see Steering. For one long run, numBatches gives batch means instead. To compare two designs, use common random numbers rather than just more replications.

Time units and animation speed ​

Symptom. The animation is far too fast or painfully slow, the run ends after a few customers, or a renege time seems to have no effect.

Why. Quisim time has no unit. All durations, the Steering duration, warmupWidth and batchWidth are in the same model time units, whatever you decide they mean. Only the animation speed V of the Steering block refers to the real clock: it is model time units per millisecond. With the default speed 1, an 8-hour shift modeled in seconds (duration 28 800) plays for about 29 seconds; the same shift modeled in hours (duration 8) is over in 8 milliseconds. The default Steering duration of 10 000 suits models in seconds or minutes; for a model in hours it means more than a year.

Fix. Choose one unit per model, write it in a Note, and convert all inputs to it (a mean service time of 2 minutes is 120 in a model in seconds). Set the Steering duration in that unit. Adjust the speed V only for the animation; it does not change any result. See Time Units.

Setting the Steering duration to Infinity runs until no events are left. A model with an Arrive block always has a next arrival, so such a run never ends by itself.

Seeds: adjacent seeds share random numbers ​

Symptom. Results of different replications or blocks are more alike than they should be, or changing one part of the model changes random numbers everywhere.

Why. A random block with a seed ss uses the seed s+rs + r in replication rr (0, 1, 2, …). Two blocks with neighbouring seeds, such as 5 and 6, therefore produce the same numbers one replication apart: block 5 in replication 1 equals block 6 in replication 0. Blocks with seed 0 (the default) share the global random stream, so a change in how often one of them draws shifts the numbers of all others. The edition number does not enter the seed: all editions reuse the same random numbers.

In a test, an Arrive block driven by seed 5 had 95 arrivals in replication 1, exactly as many as the one driven by seed 6 in replication 0.

Fix. Give every random block its own seed, spaced far apart: 1000, 2000, 3000, … (more than the number of replications). Within one comparison, use the same seed for the corresponding blocks of both variants, see Getting CRN right. Set the global seed (S) of the Steering block to make the whole run reproducible.

A random block that nothing reads produces nothing ​

Symptom. A random block wired only to a Statistics block, a Chart or a Histogram shows no values.

Why. Random blocks draw a new number only when a block asks for one, for example an Arrive block reading its next inter-arrival time. Report blocks only listen; they do not ask.

Fix. Wire the random block to the block that uses it (Arrive, Perform, Decide …) and additionally to the report block. The report block then records every number that is drawn. To check a distribution on its own, drive an Arrive block with it and record the values, or read the measureExpectedValue (EV) and measureExpectedStdDev (ESD) measures.

Other things to know ​

  • Unwired Function inputs are NaN. M[0]=P[0]+P[1] with only P[0] wired gives NaN, silently. See NaN on a duration wire.
  • Values are taken when the entity arrives. A Perform duration and a Queue renege duration are read when the entity enters the block. Changing the input later does not affect entities already inside.
  • Lowering a capacity during a run removes nobody by default (soft cap): a Perform lets the entities in service finish as planned, a Queue just accepts nothing until it has drained below the new capacity. Set haltExcess (Perform: excess jobs leave through E if it is piped and open, else they are halted) or evictExcess (Queue, with a pipe from E) to act on the excess, see Queue and Perform.
  • Line jockeying with capacity = other load + 0 moves an entity back and forth forever without time advancing; use + 1, see Line jockeying.
  • Changing a NumberInput during a run affects the running model at once, but the next run starts from initValue again unless you press Enter. See Changing inputs during a run.
  • One value per run: for the final value of a measure that only grows, such as measureLastTime (the makespan) or a counter, set quantile: 1 on the Statistics block. Wiring steering0.measureFinished into the Statistics block's active input is an outdated pattern that records nothing: a Statistics block only records values that arrive while it is active, and measureFinished turns it on only after the run has ended, when no more values arrive.
  • A Queue without a pipe on its outlet collects entities forever, with no warning (the default capacity is unlimited).