cli-guide.md
291 lines · skills/simpy/references/cli-guide.md at 5f2bc03
Most marks come from matching words in the file, so treat them as pointers.
Bundled CLI guide
Reviewed 2026-10-01 for skill version 1.6 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.
Raw lines 1 to 8Safety contract
All scripts:
- use only SimPy and the Python standard library;
- build
--helpwhen SimPy is absent, so options remain inspectable before installation; - make no network or external-service calls;
- accept only local regular files with fixed suffixes;
- reject URLs, symlinks, duplicate JSON keys,
NaN/infinity, unknown keys, and oversized inputs; - never evaluate configuration text, run user Python, resolve callables, or import plugins;
- enforce time, event, entity, queue, trace, and replication caps;
- emit strict deterministic JSON (
allow_nan=False); - write explicit outputs atomically with mode
0600; - refuse overwrite unless
--forceis 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. They also reject a different installed version because scheduler instrumentation is release-specific. Configuration validation and artifact summarization remain usable without SimPy.
Raw lines 9 to 38Queue configuration schema
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:
- arrival and service durations are exponential means in the declared model time unit;
- there are
serverssimultaneous slots and at mostqueue_capacitywaiting entities; - an arrival seeing
servers + queue_capacityadmitted entities is rejected; - arrivals and services use separate deterministic stream seeds;
- arrivals occur strictly before
horizon; - numeric horizon excludes ordinary events exactly at that time;
- completed-customer metrics exclude unfinished entities and disclose their count.
Bounds:
0 < horizon <= 1,000,000;1 <= servers <= 10,000;0 <= queue_capacity <= 100,000;- positive finite means no greater than 1,000,000;
1 <= max_entities <= 100,000;10 <= max_events <= 1,000,000;- base seed from 0 through
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.
Report schema 1.2 separates the measurement rules:
window_arrivalsandwindow_rejectedcount events in[warm_up, horizon);loss_probabilityis their ratio (null when there are no window arrivals).window_departurescounts all completions in that time window, including customers arriving before warm-up; throughput divides this byhorizon - warm_up.observed_completedand customer means use customers arriving at/after warm-up and completed before the horizon; unfinished customer paths are excluded.- Queue length and utilization are time-weighted over
[warm_up, horizon). - The original arrivals/admitted/rejected/completed counters span the full run.
event_processing.processedincludes the step whose callback stops the run.
These synthetic exponential inputs demonstrate event mechanics; they are not calibrated estimates of a real queue. Record the time unit and justify inputs before using scenario contrasts. The report records simpy_version and metric_windows.
Basic template
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)Raw lines 101 to 121Bounded queue scenario and trace
python skills/simpy/scripts/bounded_queue_scenario.py \
--config queue.json \
--output scenario.json \
--trace-output trace.jsonl \
--trace-max-records 50000The 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.
Replication configuration schema
{
"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:
- 2-1,000 replications; one-run confidence intervals are rejected;
- confidence strictly greater than 0.50 and at most 0.999;
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.jsonThe 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.
Configuration validator
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 replicationSchemas 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')"
}Raw lines 190 to 212Event/resource artifact summarizer
Summarize a trace without importing or executing its originating model:
python skills/simpy/scripts/event_trace_summary.py trace.jsonlGenerate the separate, fixed ResourceMonitor demonstration and its CSV, then summarize it (--samples is an output path, not an input):
python skills/simpy/scripts/resource_monitor.py \
--samples resource.csv --output monitor.json
python skills/simpy/scripts/event_trace_summary.py resource.csvAccepted 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 reports decreasing event times and computes resource time averages by carrying each post-transition state forward to the next sample. Same-time priority/event-ID decreases are valid when callbacks insert new urgent events; the processing trace alone cannot prove scheduler heap ordering. It does not infer queue semantics from arbitrary column names.
The replication runner consumes the replication JSON configuration and runs fresh model instances. It does not consume trace.jsonl or resource.csv. Each run provides one estimate per metric; the Student-t interval is across those estimates, not a separate confidence interval for each run.
Resource monitor library
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.
Exit behavior
Expected validation failures use argparse errors and nonzero exit status:
- malformed/unknown config;
- unsafe path or overwrite;
- event/entity/replication budget violation;
- event limit reached during the run;
- invalid trace/resource artifact.
An event-budget error is a failed/incomplete simulation, not a valid censored result. Increase a cap only after diagnosing why it was reached.
Raw lines 268 to 280Exact pinned tests
PYTHONDONTWRITEBYTECODE=1 uv run --isolated --no-project \
--python 3.13 --with "simpy==4.1.2" --with pytest \
python -m pytest tests/simpy -qTests 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.
Raw lines 281 to 291