skills/simpy/references/cli-guide.md
Verified 2026-07-23 for skill version 1.1 and SimPy 4.1.2.
The scripts implement one transparent finite-horizon exponential arrival/exponential service multi-server queue. They are examples and diagnostics, not a generic model execution platform.
All scripts:
--help when SimPy is absent, so options remain inspectable before
installation;NaN/infinity, unknown keys, and
oversized inputs;allow_nan=False);0600;--force is supplied.Run from the repository root after the pinned install:
uv pip install "simpy==4.1.2"
Commands that execute a simulation gate SimPy through a shared dependency loader. If it is absent, they exit without a traceback and print the pinned installation command above. Configuration validation and artifact summarization remain usable without SimPy.
Every field is optional; defaults are shown:
{
"analysis_mode": "terminating",
"base_seed": 20260723,
"horizon": 480.0,
"max_entities": 10000,
"max_events": 200000,
"mean_interarrival": 4.0,
"mean_service": 6.0,
"queue_capacity": 20,
"servers": 2,
"warm_up": 0.0
}
Semantics:
servers simultaneous slots and at most queue_capacity waiting
entities;servers + queue_capacity admitted entities is rejected;horizon;Bounds:
0 < horizon <= 1,000,000;1 <= servers <= 10,000;0 <= queue_capacity <= 100,000;1 <= max_entities <= 100,000;10 <= max_events <= 1,000,000;2^63 - 1.For analysis_mode="terminating", warm_up must be zero. For
analysis_mode="steady_state", warm-up must be positive and less than horizon.
This validates consistency only; it does not establish that steady state was
reached.
python skills/simpy/scripts/basic_simulation_template.py --help
python skills/simpy/scripts/basic_simulation_template.py
python skills/simpy/scripts/basic_simulation_template.py \
--config queue.json --output run.json
--replication INDEX selects deterministic derived arrival/service seeds. It does
not itself create a confidence interval.
Library use:
from basic_simulation_template import QueueConfig, run_simulation
config = QueueConfig.from_mapping({"horizon": 120, "servers": 3})
report = run_simulation(config, replication=0)
python skills/simpy/scripts/bounded_queue_scenario.py \
--config queue.json \
--output scenario.json \
--trace-output trace.jsonl \
--trace-max-records 50000
The trace is capped and contains no event repr:
{
"event_id": 0,
"event_type": "Initialize",
"priority": 0,
"queue_size_before": 1,
"time": 0.0
}
The .jsonl file has one compact object per line. A trace can truncate while the
bounded simulation completes; the report discloses trace.truncated.
{
"confidence": 0.95,
"model": {
"analysis_mode": "terminating",
"base_seed": 20260723,
"horizon": 480,
"max_entities": 10000,
"max_events": 200000,
"mean_interarrival": 4,
"mean_service": 6,
"queue_capacity": 20,
"servers": 2,
"warm_up": 0
},
"replications": 20
}
Additional experiment bounds:
replications * max_events <= 5,000,000;replications * max_entities <= 2,000,000.python skills/simpy/scripts/replication_runner.py --help
python skills/simpy/scripts/replication_runner.py \
--config experiment.json --output intervals.json
The runner makes a two-sided Student-t interval from independent replication-level estimates. A metric undefined in any run is marked unavailable instead of dropping that run. It never constructs a CI from individual customers within one run.
The seed manifest uses stable BLAKE2b derivation for separate arrival/service RNG
objects. This is deterministic stream separation for the bundled example, not a
formal proof of independent substreams. See simulation-methodology.md.
Validation performs no simulation:
python skills/simpy/scripts/validate_simulation_config.py queue.json
python skills/simpy/scripts/validate_simulation_config.py \
experiment.json --schema replication
Schemas are queue, replication, or auto. Auto identifies the replication
schema by any top-level model, replications, or confidence key. There are no
custom model names, module paths, class names, predicates, or callable fields.
Unknown keys such as the following are rejected:
{
"plugin": "package.module",
"python": "print('run me')"
}
Summarize a trace without importing or executing its originating model:
python skills/simpy/scripts/event_trace_summary.py trace.jsonl
Summarize ResourceMonitor CSV:
python skills/simpy/scripts/resource_monitor.py \
--samples resource.csv --output monitor.json
python skills/simpy/scripts/event_trace_summary.py resource.csv
Accepted trace fields are exactly:
event_id, event_type, priority, queue_size_before, time.
Accepted resource CSV fields are exactly:
time, event, count, queue_length, utilization.
The summarizer checks event trace order by (time, priority, event_id) and computes
resource time averages by carrying each state left-continuously to the next sample.
It does not infer queue semantics from arbitrary column names.
from resource_monitor import EventTraceRecorder, ResourceMonitor
monitor = ResourceMonitor(env, server, "server")
trace = EventTraceRecorder(env, max_records=10_000)
env.run(until=100)
trace.detach()
monitor.finalize(at=100)
print(monitor.summary(start=20, end=100))
monitor.export_csv("resource.csv")
trace.export_jsonl("trace.jsonl")
The monitor patches one resource instance. Do not attach multiple wrappers to the
same resource. Its queue timing and private-API caveats are in monitoring.md.
Expected validation failures use argparse errors and nonzero exit status:
An event-budget error is a failed/incomplete simulation, not a valid censored result. Increase a cap only after diagnosing why it was reached.
PYTHONDONTWRITEBYTECODE=1 uv run --isolated --no-project \
--python 3.13 --with "simpy==4.1.2" \
python -m unittest discover -s skills/simpy/tests -v
Tests cover scheduler boundaries, deterministic ties, Conditions, all resource families, preemption causes, monitor time weighting, trace round-trip, config/path safety, hard limits, seed determinism, and Student-t calculations.