A first look at Quisim
Build your first queueing model, block by block
Quisim
What is Quisim?
A model is a network of blocks


Model codeOpen in Quisim
NumberInput { id: number0; initValue:125; label:"1/λ"; lower:1 }
NumberInput { id: number1; initValue:100; label:"1/µ"; lower:1 }
Wire { from: number0.measureValue; to: rnd0.parameterMean }
Wire { from: number1.measureValue; to: rnd1.parameterMean }
RandomExponential { id:rnd0 }
RandomExponential { id:rnd1 }
Wire { from:rnd0.measureRandomVariate; to:arrive0.parameterDuration }
Wire { from:rnd1.measureRandomVariate; to:perform0.parameterDuration }
Arrive { id:arrive0 }
Pipe { from:arrive0.outlet; to:queue0.inlet }
Queue { id:queue0 }
Pipe { from:queue0.outlet; to:perform0.inlet }
Perform { id:perform0 }
Pipe { from:perform0.outlet; to:leave0.inlet }
Leave { id:leave0 }
Wire { from: queue0.measureLoad; to: chart0.parameters[0] }
Statistics { id: statistics0; height:48; width:128; label:"Sojourn\ntime" }
Wire { from: leave0.measureSojourn; to: statistics0.parameters[0] }
Chart { id: chart0; height:66; width:384 }- Discrete-event simulation: the state changes only at events (an arrival, the end of a service); the clock jumps from one event to the next
- By the end of this session you will have built this model yourself. More: How a discrete-event simulation runs
The Quisim window
Canvas on the left, model code on the right: they are two views of the same model. See the UI guide.
How to follow along in the free demo
Hands on, in the browser
- Show the editor pane (pen icon). Examples tab: load a ready model. New: an empty canvas
- Blocks tab: click a block to add it; drag from socket to socket to draw a pipe or a wire
- Type values into the NumberInput fields, even while it runs (other properties are fixed in the demo)
- Animate (film icon) on, Start clean (Ctrl+Enter); Pause, Step; the Monitor tab shows the event list
- The demo kit: NumberInput, Arrive, Queue, Perform, Leave, 2 × RandomExponential, Chart, Statistics. Just enough for today
- Full version: open Model code under any picture and paste it into the editor instead
Times are in time units (milliseconds in the demo). Without a Steering block a run lasts 10 000, about 10 s of animation.
Blocks, sockets, pipes and wires
- Entity blocks move entities (Arrive, Queue, Perform, Leave); value blocks give numbers; report blocks show results
- Green entity sockets are joined by pipes: entities flow. Silver data sockets are joined by wires: numbers flow, from a measure (bottom right) to a parameter (bottom left)
More: Block Sockets, connecting blocks
Build along: your first queue
Build it: 1. Arrivals at a fixed pace
- New, then Blocks tab, Entity: click Arrive and Leave
- Drag Arrive's outlet O onto Leave's inlet I: a pipe
- Value: click NumberInput, type 100 into its field
- Drag its measure N onto Arrive's parameter D: a wire
- Animate on, Start clean
Model codeOpen in Quisim
NumberInput { id: number0; initValue:100; label:"D" }
Wire { from: number0.measureValue; to: arrive0.parameterDuration }
Arrive { id:arrive0 }
Pipe { from:arrive0.outlet; to:leave0.inlet }
Leave { id:leave0 }One entity every 100 time units. Arrive cannot store entities, so Leave takes each one away at once.
Predict: how many entities?
Question
The run lasts 10 000. How many entities reach Leave? How many events wait in the event list at any moment?
Run it: hover Leave's socket N: 101 entities, one at time 0 and then one every 100 up to time 10 000.
- Pause, open Monitor > Events, press Step: one entity event at a time, the next arrival, and the clock jumps by exactly 100
Build it: 2. Random arrivals
- Select the NumberInput, Delete component with connections (trash icon, Ctrl+Backspace)
- Random: click RandomExponential; wire its V onto Arrive's D
- Add a NumberInput, type 125: this is 1/λ
- Wire its N onto RandomExponential's mean µ
Model codeOpen in Quisim
NumberInput { id: number0; initValue:125; label:"1/λ" }
Wire { from: number0.measureValue; to: rnd0.parameterMean }
RandomExponential { id:rnd0; seed:11 }
Wire { from:rnd0.measureRandomVariate; to:arrive0.parameterDuration }
Arrive { id:arrive0 }
Pipe { from:arrive0.outlet; to:leave0.inlet }
Leave { id:leave0 }A new inter-arrival time is drawn for every entity, with mean 1/λ=125. This is the Arrive→Leave example.
Predict: same run twice?
Question
Press Start clean twice. Do you get the same number of entities both times? About how many?
Run it: about 10000/125=80, but a different count each time.
- Without a fixed seed, every start draws new random numbers. The pictures on these slides use fixed seeds, so your numbers will differ a little
- The random blocks also offer Uniform and Normal. For durations, prefer bounded distributions (min ≥ 0). More: Random Number Blocks
Build it: 3. A server
- Delete Leave (with connections)
- Add Perform; pipe Arrive O → Perform I
- Drag from Perform's O into the Blocks tab onto Leave's inlet: Leave is added, already connected
- Second RandomExponential: V → Perform's D
- New NumberInput, type 100 (1/μ), N → its µ


Model codeOpen in Quisim
NumberInput { id: number0; initValue:125; label:"1/λ" }
NumberInput { id: number1; initValue:100; label:"1/µ" }
Wire { from: number0.measureValue; to: rnd0.parameterMean }
Wire { from: number1.measureValue; to: rnd1.parameterMean }
RandomExponential { id:rnd0; seed:11 }
RandomExponential { id:rnd1; seed:22 }
Wire { from:rnd0.measureRandomVariate; to:arrive0.parameterDuration }
Wire { from:rnd1.measureRandomVariate; to:perform0.parameterDuration }
Arrive { id:arrive0 }
Pipe { from:arrive0.outlet; to:perform0.inlet }
Perform { id:perform0 }
Pipe { from:perform0.outlet; to:leave0.inlet }
Leave { id:leave0 }Predict: a server without a queue
Question
Arrivals every 125 on average, service takes 100 on average. Do still about 80 entities pass in 10 000?
Run it: clearly fewer (hover Leave's N): about 68 in the pictured run, where the arrivals alone gave 86. With Animate on, Arrive's outlet turns red: while Perform is busy, the new entity cannot leave Arrive, it is blocked, and the next inter-arrival time starts late.
Key insight
Without a queue, a busy server silently changes the arrival process you specified.
Build it: 4. A waiting line
- Delete Arrive (with connections)
- Add Queue; pipe Queue O → Perform I
- Drag from Queue's I into the Blocks tab onto Arrive's outlet: Arrive comes back connected
- Wire the first RandomExponential's V → Arrive's D again
Model codeOpen in Quisim
NumberInput { id: number0; initValue:125; label:"1/λ" }
NumberInput { id: number1; initValue:100; label:"1/µ" }
Wire { from: number0.measureValue; to: rnd0.parameterMean }
Wire { from: number1.measureValue; to: rnd1.parameterMean }
RandomExponential { id:rnd0; seed:11 }
RandomExponential { id:rnd1; seed:22 }
Wire { from:rnd0.measureRandomVariate; to:arrive0.parameterDuration }
Wire { from:rnd1.measureRandomVariate; to:perform0.parameterDuration }
Arrive { id:arrive0 }
Pipe { from:arrive0.outlet; to:queue0.inlet }
Queue { id:queue0 }
Pipe { from:queue0.outlet; to:perform0.inlet }
Perform { id:perform0 }
Pipe { from:perform0.outlet; to:leave0.inlet }
Leave { id:leave0 }Entities now wait in the Queue, Arrive is never blocked. This is the M/M/1 queue: Markov arrivals, Markov service, 1 server.
Build it: 5. Watch the queue
- Report: click Chart
- Wire Queue's measure L (its length) onto the Chart's P[0]
- Start clean, hover the Chart to read values


Model codeOpen in Quisim
NumberInput { id: number0; initValue:125; label:"1/λ" }
NumberInput { id: number1; initValue:100; label:"1/µ" }
Wire { from: number0.measureValue; to: rnd0.parameterMean }
Wire { from: number1.measureValue; to: rnd1.parameterMean }
RandomExponential { id:rnd0; seed:11 }
RandomExponential { id:rnd1; seed:22 }
Wire { from:rnd0.measureRandomVariate; to:arrive0.parameterDuration }
Wire { from:rnd1.measureRandomVariate; to:perform0.parameterDuration }
Arrive { id:arrive0 }
Pipe { from:arrive0.outlet; to:queue0.inlet }
Queue { id:queue0 }
Pipe { from:queue0.outlet; to:perform0.inlet }
Perform { id:perform0 }
Pipe { from:perform0.outlet; to:leave0.inlet }
Leave { id:leave0 }
Wire { from: queue0.measureLoad; to: chart0.parameters[0] }
Chart { id: chart0; height:66; width:384 }The queue length jumps up and down: long quiet spells, then sudden bursts.
Build it: 6. Measure the time in system
- Report: click Statistics
- Wire Leave's measure LS (sojourn time of the last entity) onto its P[0]
- Start clean: it shows the mean time in system W of the run


Model codeOpen in Quisim
NumberInput { id: number0; initValue:125; label:"1/λ"; lower:1 }
NumberInput { id: number1; initValue:100; label:"1/µ"; lower:1 }
Wire { from: number0.measureValue; to: rnd0.parameterMean }
Wire { from: number1.measureValue; to: rnd1.parameterMean }
RandomExponential { id:rnd0; seed:11 }
RandomExponential { id:rnd1; seed:22 }
Wire { from:rnd0.measureRandomVariate; to:arrive0.parameterDuration }
Wire { from:rnd1.measureRandomVariate; to:perform0.parameterDuration }
Arrive { id:arrive0 }
Pipe { from:arrive0.outlet; to:queue0.inlet }
Queue { id:queue0 }
Pipe { from:queue0.outlet; to:perform0.inlet }
Perform { id:perform0 }
Pipe { from:perform0.outlet; to:leave0.inlet }
Leave { id:leave0 }
Wire { from: queue0.measureLoad; to: chart0.parameters[0] }
Statistics { id: statistics0; height:48; width:128; label:"Sojourn\ntime" }
Wire { from: leave0.measureSojourn; to: statistics0.parameters[0] }
Chart { id: chart0; height:66; width:384 }Your model is now the M/M/1 example. Lost track? Load it from the Examples tab and carry on.
The M/M/1 queue in numbers
Your two NumberInputs set the two rates: λ=1/125, μ=1/100.
- Utilization ρ=λ/μ=100/125=0.8: the server is busy 80% of the time
- Theory: Nq=ρ2/(1−ρ)=3.2 waiting, waiting time Wq=400, time in system W=1/(μ−λ)=500
- Compare with your Statistics block: one run of 10 000 is short, so expect to be off by quite a bit
- The theory only holds for ρ<1. What happens beyond? Next slides
Your turn: step through the event list
M/M/1, Animate on, about 5 minutes
- Start clean, then Pause after a few seconds; open Monitor > Events
- Press Step ten times. For each step write down the clock time and the block that owned the event
- Answer: which blocks own events? Why is there never an event "entity joins the queue"? Does the clock advance in equal steps?
| Step | 1 | 2 | 3 | 4 | 5 | … |
|---|---|---|---|---|---|---|
| Time | ||||||
| Block |
More: The Monitor tab, Event List
Predict: a slightly slower server
Question
Set 1/µ from 100 to 120: service is 20% slower, ρ=0.96. How much longer is the time in system W?


Model codeOpen in Quisim
NumberInput { id: number0; initValue:125; label:"1/λ"; lower:1 }
NumberInput { id: number1; initValue:120; label:"1/µ"; lower:1 }
Wire { from: number0.measureValue; to: rnd0.parameterMean }
Wire { from: number1.measureValue; to: rnd1.parameterMean }
RandomExponential { id:rnd0; seed:11 }
RandomExponential { id:rnd1; seed:22 }
Wire { from:rnd0.measureRandomVariate; to:arrive0.parameterDuration }
Wire { from:rnd1.measureRandomVariate; to:perform0.parameterDuration }
Arrive { id:arrive0 }
Pipe { from:arrive0.outlet; to:queue0.inlet }
Queue { id:queue0 }
Pipe { from:queue0.outlet; to:perform0.inlet }
Perform { id:perform0 }
Pipe { from:perform0.outlet; to:leave0.inlet }
Leave { id:leave0 }
Wire { from: queue0.measureLoad; to: chart0.parameters[0] }
Statistics { id: statistics0; height:48; width:128; label:"Sojourn\ntime" }
Wire { from: leave0.measureSojourn; to: statistics0.parameters[0] }
Chart { id: chart0; height:66; width:384 }Run it: the queue climbs about twice as high (at most 15 instead of 8 in the pictured run), and W is about 1270 instead of about 520.
- Theory says W=1/(μ−λ)=3000, six times as long as at 100. A run of 10 000 starts with an empty queue and is far too short to get there: near ρ=1 the queue needs a long time to build up
Your turn: service time vs. time in system
Your M/M/1 (or the example), 1/λ = 125, about 10 minutes
For each 1/µ: type it in, Start clean (Animate off for speed), note the Statistics mean and the highest queue length on the Chart.
| 1/µ | 50 | 80 | 100 | 110 | 120 |
|---|---|---|---|---|---|
| ρ=(1/μ)/(1/λ) | 0.40 | 0.64 | 0.80 | 0.88 | 0.96 |
| Theory W | 83 | 222 | 500 | 917 | 3000 |
| Your W | |||||
| Max. queue |
- Plot W against ρ. At which ρ does your run start to miss the theory badly, and why?
Predict: a server that is too slow
Question
Set 1/µ = 150, longer than the mean time between arrivals. What does the Chart show?
Run it: the queue drifts upward for the whole run (to about 25 in a seeded test run) and every Start clean gives a very different W, from about 300 to over 2500 in our test runs. With ρ=150/125=1.2>1 there is no steady state: the longer the run, the longer the queue and the Statistics mean.
- Try 130 too (ρ=1.04): in a run of 10 000 it looks much like 120, because the queue grows by only about 3 entities per 10 000 on average
Key insight
Waiting time does not grow in proportion to load: near ρ=1 a little extra load makes the queue explode.
Replications and confidence intervals
The Statistics example


Model codeOpen in Quisim
NumberInput { id: number1; initValue:100; label:"1/µ\nservice time"; lower:1; height:58; width:96 }
NumberInput { id: number0; initValue:125; label:"1/λ\ninterarrival time"; lower:1; height:58; width:112 }
RandomExponential { id:rnd0 }
Wire { from: number0.measureValue; to: rnd0.parameterMean }
Wire { from: number1.measureValue; to: rnd1.parameterMean }
Wire { from:rnd0.measureRandomVariate; to:arrive0.parameterDuration }
Wire { from: number2.measureValue; to: perform0.parameterCapacity }
Wire { from:rnd0.measureRandomVariate; to:arrive0.parameterDuration }
Wire { from:rnd1.measureRandomVariate; to:perform0.parameterDuration }
NumberInput { id: numberinput1; initValue:10000; label:"Duration"; width:112; lower:1; upper:1000000 }
NumberInput { id: numberinput0; initValue:20; label:"Replications"; width:112; lower:1; upper:100 }
NumberInput { id: number2; initValue:1; label:"k servers"; lower:1 }
Wire { from: numberinput1.measureValue; to: steering0.parameterDuration }
Steering { id: steering0; duration:50000 }
Wire { from: numberinput0.measureValue; to: steering0.parameterReplications }
RandomExponential { id:rnd1 }
Arrive { id:arrive0 }
Pipe { from:arrive0.outlet; to:queue0.inlet }
Queue { id:queue0 }
Pipe { from:queue0.outlet; to:perform0.inlet }
Perform { id:perform0 }
Pipe { from:perform0.outlet; to:leave0.inlet }
Leave { id:leave0 }
Statistics { id: statistics0; timeAverage:true; numParameters:2; warmupWidth:5000; label:"Queue length\nService load"; height:192; width:152; x:646; y:245 }
Wire { from: queue0.measureLoad; to: statistics0.parameters[0] }
Wire { from: perform0.measureLoad; to: statistics0.parameters[1] }
Statistics { id: statistics2; warmupWidth:5000; label:"Sojourn time"; height:192; width:152; x:646; y:12 }
Statistics { id: statistics1; numParameters:2; warmupWidth:5000; label:"Waiting time\nService time"; height:192; width:152; x:470; y:245 }
Wire { from: queue0.measureWait; to: statistics1.parameters[0] }
Wire { from: rnd1.measureRandomVariate; to: statistics1.parameters[1] }
Wire { from: leave0.measureSojourn; to: statistics2.parameters[0] }Your M/M/1, plus a Steering block run 20 times (Replications). One row per run, then mean ± 95% radius. Compare with Nq=3.2, ρ=0.8, Wq=400, W=500.
Replications and the seed rule
One run is one possible outcome. Replications repeat it with new random numbers.
- Replication r reseeds every random stream with seed +r: different, yet reproducible
- Each run gives one average (e.g. the mean waiting time). Over m runs, report the overall average Θ^±δ, with δ=tm−1,α/2Sm2/m (Sm2: variance of the m averages)
- The radius shrinks like 1/m: four times the replications halve it
- Overlapping intervals do not show a significant difference
Your turn: how many replications?
Examples > Statistics, about 10 minutes
Animate off. Set Replications and Duration as in the table, Start clean, and copy the Sojourn time mean and its ± radius.
| Replications | 5 | 20 | 80 | 20 |
|---|---|---|---|---|
| Duration | 10 000 | 10 000 | 10 000 | 100 000 |
| Sojourn time W ± radius | ||||
| Contains 500? |
- Does 4 × the replications halve the radius? What does 10 × the duration do?
- Set 1/µ to 120 and repeat the first column: does the interval contain the theory value W=3000? Why not?
Key insight: replications
Key insight
A simulation result is an estimate: always report it with its confidence interval, and buy precision with more or longer runs.
- The first 5000 of every run are cut (
warmupWidth: 5000): the queue starts empty, which is not typical. More on this at the end
More servers: M/M/k
The M/M/k example


Model codeOpen in Quisim
NumberInput { id: number0; initValue:55; label:"1/λ"; lower:1 }
NumberInput { id: number1; initValue:500; label:"1/µ"; lower:1 }
Wire { from: number0.measureValue; to: rnd0.parameterMean }
Wire { from: number1.measureValue; to: rnd1.parameterMean }
RandomExponential { id:rnd0 }
RandomExponential { id:rnd1 }
Wire { from:rnd0.measureRandomVariate; to:arrive0.parameterDuration }
Wire { from:rnd1.measureRandomVariate; to:perform0.parameterDuration }
Arrive { id:arrive0 }
Pipe { from:arrive0.outlet; to:queue0.inlet }
Queue { id:queue0 }
Pipe { from:queue0.outlet; to:perform0.inlet }
NumberInput { id: number2; initValue:10; label:"Capacity"; lower:1 }
Wire { from: number2.measureValue; to: perform0.parameterCapacity }
Perform { id:perform0 }
Pipe { from:perform0.outlet; to:leave0.inlet }
Leave { id:leave0 }
Wire { from: queue0.measureLoad; to: chart0.parameters[0] }
Wire { from: perform0.measureLoad; to: chart0.parameters[1] }
Statistics { id: statistics0; height:48; width:128; label:"Sojourn\ntime" }
Wire { from: leave0.measureSojourn; to: statistics0.parameters[0] }
Chart { id: chart0; numParameters:2; height:66; width:384 }Capacity k=10: Perform serves up to 10 entities at once. ρ=λ/(kμ)=500/(10⋅55)=0.91. The Chart shows queue length and busy servers.
Predict: two servers fewer
Question
Open Examples > M/M/k and set Capacity from 10 to 8. What happens to the queue?


Model codeOpen in Quisim
NumberInput { id: number0; initValue:55; label:"1/λ"; lower:1 }
NumberInput { id: number1; initValue:500; label:"1/µ"; lower:1 }
Wire { from: number0.measureValue; to: rnd0.parameterMean }
Wire { from: number1.measureValue; to: rnd1.parameterMean }
RandomExponential { id:rnd0; seed:11 }
RandomExponential { id:rnd1; seed:22 }
Wire { from:rnd0.measureRandomVariate; to:arrive0.parameterDuration }
Wire { from:rnd1.measureRandomVariate; to:perform0.parameterDuration }
Arrive { id:arrive0 }
Pipe { from:arrive0.outlet; to:queue0.inlet }
Queue { id:queue0 }
Pipe { from:queue0.outlet; to:perform0.inlet }
NumberInput { id: number2; initValue:8; label:"Capacity"; lower:1 }
Wire { from: number2.measureValue; to: perform0.parameterCapacity }
Perform { id:perform0 }
Pipe { from:perform0.outlet; to:leave0.inlet }
Leave { id:leave0 }
Wire { from: queue0.measureLoad; to: chart0.parameters[0] }
Wire { from: perform0.measureLoad; to: chart0.parameters[1] }
Statistics { id: statistics0; height:48; width:128; label:"Sojourn\ntime" }
Wire { from: leave0.measureSojourn; to: statistics0.parameters[0] }
Chart { id: chart0; numParameters:2; height:66; width:384 }Run it: the 8 servers are busy almost all the time and the queue only grows, to about 30 at the end of the pictured run (W about 1340). With the same random numbers and 10 servers the queue ends empty and W is about 575. ρ=500/(8⋅55)=1.14>1: it needs k>500/55=9.1 servers.
Your turn: how many servers?
Examples > Erlang C, about 10 minutes
Set 1/λ = 55, 1/µ = 500, then each k servers below. Erlang C computes the theory, the model simulates it (20 replications). Record both.
| k servers | 10 | 11 | 12 | 14 |
|---|---|---|---|---|
| ρ | 0.91 | 0.83 | 0.76 | 0.65 |
| P(wait), theory | ||||
| W theory | ||||
| W simulated ± radius |
- Each server costs the same. Where does one more server stop paying off?
- Optional: k = 1 with 1/λ = 125, 1/µ = 100 is your M/M/1 again: do you get 500?
Key insight: servers
Key insight
The number of servers needed is set by the load λ/μ, but how long people wait is decided by the last one or two servers above it.
- At k=10 almost 70% of the customers wait, at k=12 fewer than 30%
What the full version adds
Steering: duration, replications, seed


Model codeOpen in Quisim
Steering { id: steering0; duration: 100000; replications: 10; seed: 1 }
RandomExponential { id: rnd0; mean: 125; seed: 88 }
RandomExponential { id: rnd1; mean: 100; seed: 143 }
Wire { from: rnd0.measureRandomVariate; to: arrive0.parameterDuration }
Wire { from: rnd1.measureRandomVariate; to: perform0.parameterDuration }
Arrive { id: arrive0 }
Pipe { from: arrive0.outlet; to: queue0.inlet }
Queue { id: queue0 }
Pipe { from: queue0.outlet; to: perform0.inlet }
Perform { id: perform0 }
Pipe { from: perform0.outlet; to: leave0.inlet }
Leave { id: leave0 }
Wire { from: queue0.measureLoad; to: stats0.parameters[0] }
Wire { from: perform0.measureLoad; to: stats0.parameters[1] }
Statistics { id: stats0; numParameters: 2; timeAverage: true; label: "Nq / ρ"; x: 520; y: 0 }
Wire { from: leave0.measureSojourn; to: statsW.parameters[0] }
Statistics { id: statsW; label: "W"; x: 760; y: 0 }- Every block and property is editable; Steering sets duration D, replications R, editions E, seed S, speed V
- A fixed seed makes every run reproducible; seed 0 on a random block draws from the Steering seed. Levels need
timeAverage: true
More: Running a simulation
Experiments: compare configurations


Model codeOpen in Quisim
// Edition 0: one fast server (mean 100). Edition 1: two slow servers (mean 200 each)
Steering { id: steering0; duration: 200000; replications: 10; editions: 2; seed: 1 }
Function { id: fnConfig; numMeasures: 2; label: "configuration"
code: "M[0] = [1, 2][P[0]] // servers
M[1] = [100, 200][P[0]] // mean service time" }
Wire { from: steering0.measureEdition; to: fnConfig.parameters[0] }
Wire { from: fnConfig.measures[0]; to: perform0.parameterCapacity }
Wire { from: fnConfig.measures[1]; to: rndB.parameterMean }
RandomExponential { id: rndA; mean: 125; seed: 11 }
Wire { from: rndA.measureRandomVariate; to: arrive0.parameterDuration }
Arrive { id: arrive0 }
Pipe { from: arrive0.outlet; to: queue0.inlet }
Queue { id: queue0 }
Pipe { from: queue0.outlet; to: perform0.inlet }
RandomExponential { id: rndB; seed: 22 }
Wire { from: rndB.measureRandomVariate; to: perform0.parameterDuration }
Perform { id: perform0 }
Pipe { from: perform0.outlet; to: leave0.inlet }
Leave { id: leave0 }
Statistics { id: stats0; numParameters: 2; label: "waiting time / time in system" }
Wire { from: queue0.measureWait; to: stats0.parameters[0] }
Wire { from: leave0.measureSojourn; to: stats0.parameters[1] }- Editions: the edition number EN drives a Function that sets each configuration; all editions share the seeds (common random numbers)
- Two slow servers: shorter wait (317 vs. 364), longer time in system (517 vs. 464). BrentOptimize and Explorer search parameters
More: compare configurations, find the best parameter, Experiment and Optimization Blocks
Warm-up: cut the start-up phase


Model codeOpen in Quisim
// M/M/1 (utilization 0.8) that starts with a backlog of 30 jobs: how long is the warm-up?
Steering { id: steering0; duration: 100000; replications: 10; seed: 1 }
Provide { id: provideBacklog }
Pipe { from: provideBacklog.outlet; to: meterBacklog.inlet }
Meter { id: meterBacklog; capacity: 30 } // 30 jobs already waiting at time 0
Pipe { from: meterBacklog.outlet; to: queue0.inlet }
RandomExponential { id: rndA; mean: 125; seed: 11 }
Wire { from: rndA.measureRandomVariate; to: arrive0.parameterDuration }
Arrive { id: arrive0 }
Pipe { from: arrive0.outlet; to: queue0.inlet }
Queue { id: queue0 }
Pipe { from: queue0.outlet; to: perform0.inlet }
RandomExponential { id: rndB; mean: 100; seed: 22 }
Wire { from: rndB.measureRandomVariate; to: perform0.parameterDuration }
Perform { id: perform0 }
Pipe { from: perform0.outlet; to: leave0.inlet }
Leave { id: leave0 }
EnsemblePlot { id: welch0; timeAverage: true; batchWidth: 1000; label: "Welch plot of queue length" }
Wire { from: queue0.measureLoad; to: welch0.parameters[0] }
Statistics { id: statsAll; timeAverage: true; label: "queue length, no warm-up removed" }
Wire { from: queue0.measureLoad; to: statsAll.parameters[0] }
Statistics { id: statsMser; timeAverage: true; warmupMSER: true; label: "queue length, MSER-5 warm-up" }
Wire { from: queue0.measureLoad; to: statsMser.parameters[0] }- Non-terminating systems: the EnsemblePlot (Welch plot) shows where the start-up ends;
warmupMSER: truecuts it. Queue length 2.8 ± 0.6 (theory 3.2) instead of 6.1 ± 1.4 - Terminating systems (a shift, a day) have a natural end: keep the whole run
More: Output Analysis, warm-up recipe
Where to go next
Where to go next
Keep exploring in the demo
Try Bypass, Capacity, Renege, Triage vs. No Triage, To Shorter, Sensitivity: each has NumberInputs to play with.
- UI guide: the window, canvas, run controls, report blocks
- Handbook: every block, first models, output analysis, testing
- Cookbook: short recipes for common modeling questions
- Examples: state diagrams, production, DoE, optimization
- Hospital case study and its slides: staffing an emergency department
- Block API Reference: all attributes, sockets and defaults