Skip to content

Reference models

Models whose answer is known exactly, from a formula found in the textbooks of the subject, beside what the engine gives when it runs them. Every model here is one of the bundled models, so each line can be repeated with one command.

Case Method Model Quantity Exact Naga 95% interval Exact inside Replications Seed
M/M/1 queue Discrete-event single_server mean number waiting 3.2 3.26 3.05 to 3.48 yes 20 0
M/M/2 queue (Erlang C) Discrete-event two_teller_set mean number waiting 1.93 1.94 1.81 to 2.07 yes 20 0
M/G/1 queue (Pollaczek-Khinchine) Discrete-event single_server_general mean number waiting 1.9 1.88 1.78 to 1.98 yes 20 0
Open Jackson network Discrete-event job_shop_jackson mean time in the shop 8.38 8.37 7.95 to 8.79 yes 10 0
Logistic growth System dynamics sd_population population at t = 25 600 600 no randomness equal 1 0
Bass diffusion System dynamics sd_bass_diffusion adopters at t = 10 835 835 no randomness equal 1 0
SIR epidemic System dynamics sd_sir peak number infected 404 404 no randomness equal 1 0
Busy/idle cycle Agent-based agents_server_utilization share of the time busy 0.444 0.447 0.442 to 0.451 yes 10 0
SIR epidemic of agents Agent-based agents_sir_agents final number recovered 1,790 1,780 1,760 to 1,790 yes 20 0
Tank, average level Rate-based tank_fill_and_drain time-average level 57 57 no randomness equal 1 0
Tank, overflow Rate-based tank_fill_and_drain quantity spilled 80 80 no randomness equal 1 0

How to read it

Exact is the formula's value, computed from the parameters in the model file. Naga is the mean over the replications of a run made when this page was generated, and the interval is its 95% Student-t confidence interval over those replications. Numbers are printed at three significant digits; "inside" is decided before rounding.

A 95% interval misses the true value one time in twenty by chance. 6 lines here have an interval, so a "no" somewhere in the table is expected for about one seed in 4, with nothing wrong. Where a line has no interval, the model has no randomness and the two numbers are compared as printed.

The intervals are a few percent wide because the runs are kept to a few seconds each. An interval narrows with the square root of the simulated time: give a command below a longer --run-length or more --replications to see it close in on the exact value.

tools/gen_engine_docs.py makes the runs and writes this page; no number on it is typed. A test derives each value a second way (the Markov chain summed state by state, or the differential equation integrated numerically), repeats each run, and fails when the exact value is outside the interval or when a line here is not what the run gives.

The cases

M/M/1 queue

Single server (M/M/1) (single_server), mean number waiting: the KPI resource/Server/Queue Length Avg.

Exact: Lq = rho^2 / (1 - rho), rho = lambda / mu.

naga run single_server --replications 20 --run-length 10500 --warmup 500

M/M/2 queue (Erlang C)

Two tellers (resource set) (two_teller_set), mean number waiting: the KPI resource/Tellers/Queue Length Avg.

Exact: Lq = p0 a^c rho / (c! (1 - rho)^2), a = lambda / mu, rho = a / c, 1 / p0 = sum over n < c of a^n / n! + a^c / (c! (1 - rho)).

naga run two_teller_set --replications 20 --run-length 5500 --warmup 500

M/G/1 queue (Pollaczek-Khinchine)

Single server, general service times (M/G/1) (single_server_general), mean number waiting: the KPI resource/Server/Queue Length Avg.

Exact: Lq = lambda^2 E[S^2] / (2 (1 - rho)), rho = lambda E[S].

naga run single_server_general

Open Jackson network

Job shop (Jackson network) (job_shop_jackson), mean time in the shop: the KPI system/Avg Throughput Time.

Exact: W = sum of L_i / gamma: station i an M/M/c queue at the rate lambda_i of the traffic equations lambda_i = gamma_i + sum over j of lambda_j p_ji, L_i = Lq_i + lambda_i / mu_i.

naga run job_shop_jackson --replications 10 --run-length 6500 --warmup 500

Logistic growth

Population (logistic) (sd_population), population at t = 25: the KPI level/population_1/SD Population/Final.

Exact: P(t) = K / (1 + (K / P0 - 1) exp(-r t)).

naga run sd_population --run-length 25

Bass diffusion

Bass diffusion (sd_bass_diffusion), adopters at t = 10: the KPI level/bass_diffusion_1/SD Adopters/Final.

Exact: A(t) = m (1 - exp(-(p + q) t)) / (1 + (q / p) exp(-(p + q) t)).

naga run sd_bass_diffusion --run-length 10

SIR epidemic

SIR epidemic (sd_sir), peak number infected: the KPI level/sir_1/SD Infected/Max.

Exact: I_max = N - rho (1 + ln(S0 / rho)), rho = gamma N / beta.

naga run sd_sir

Busy/idle cycle

Server busy/idle cycle (agents) (agents_server_utilization), share of the time busy: the KPI agent/server_utilization_1/Servers/Busy/Avg Count.

Exact: lambda / (lambda + mu).

naga run agents_server_utilization --replications 10

SIR epidemic of agents

SIR epidemic (agents) (agents_sir_agents), final number recovered: the KPI agent/sir_agents_1/SIR People/R/Final.

Exact: the mean of N - S when the last infected agent recovers, summed over every path of the Markov chain: from (S, I) the next event is an infection with probability beta S / (beta S + gamma N), else a recovery.

naga run agents_sir_agents --replications 20 --run-length 300

Tank, average level

Tank: fill, overflow and run dry (tank_fill_and_drain), time-average level: the KPI level/Tank/Average.

Exact: the area under three straight lines (rise to full, full, fall to empty) over the run.

naga run tank_fill_and_drain

Tank, overflow

Tank: fill, overflow and run dry (tank_fill_and_drain), quantity spilled: the KPI level/Tank/Spilled.

Exact: (fill - draw) x the time the tank is full while the pump runs.

The same run as the line above.

What this does not show

Agreement on these cases says the engine's clock, queues, random streams, integrators and statistics are right where a formula can check them. It says nothing about a model that has no formula, which is most models: for those, see Model assertions and Experiments.