Rust/WASM Discrete Event Simulation engine for Russian Railway (РЖД) locomotive crew operations.
Replaces legacy TypeScript SPA (stats.syntog.ru v3.0) with 50–100× performance gains.
┌─────────────────────────────────────────────────┐
│ TypeScript Host │
│ (Vite + React / CLI) │
├──────────────────────┬──────────────────────────┤
│ rzd-wasm (WASM) │ rzd-cli (native) │
│ wasm-bindgen glue │ clap-based runner │
├──────────────────────┴──────────────────────────┤
│ rzd-core │
│ ┌────────┬───────┬──────┬──────┬────────────┐ │
│ │ Engine │Events │Crew │Loco │ Statistics │ │
│ ├────────┼───────┼──────┼──────┼────────────┤ │
│ │Network │Export │TU-3 │PRNG │ Violations │ │
│ └────────┴───────┴──────┴──────┴────────────┘ │
└─────────────────────────────────────────────────┘
The engine uses synthetic railway scenarios only. From a checkout with Rust installed:
cargo check --all-targets
cargo run -p rzd-cli -- --help
cargo run -p rzd-cli -- validate --network data/networks/synthetic_one_road_88_05.jsonFor the browser visualization and a reproducible demo walkthrough, see the visualization runbook. Repository rules are documented in CONTRIBUTING.md, SECURITY.md, and the documentation index.
# Run all tests
cargo test --all-targets
# Check no warnings
cargo clippy --all-targets -- -D warnings
# Run CLI
cargo run -p rzd-cli
# Run with reproducible scripted disruptions
cargo run -p rzd-cli -- run --network data/networks/northern.json --crews 8 --locos 4 --days 2 --format bundle --inject data/injection/sample_fault_windows.json
# Run from declarative scenario JSON
cargo run -p rzd-cli -- run --network data/networks/synthetic_one_road_88_05.json --scenario data/scenarios/one_road_shoulder_b.json --format summary
# Emit a structured event trace for deterministic forensic/debug analysis
cargo run -p rzd-cli -- run --network data/networks/synthetic_one_road_88_05.json --scenario data/scenarios/one_road_shoulder_a.json --format trace
# Validate the one-road synthetic benchmark network (88_05)
cargo run -p rzd-cli -- validate --network data/networks/synthetic_one_road_88_05.json
# Generate a one-road synthetic month aligned to shoulders A/B/C
cargo run -p rzd-cli -- generate --network data/networks/synthetic_one_road_88_05.json --crews 18 --locos 12 --days 30 --seed 20260708
# Replay a short deterministic disruption scenario on the same road
cargo run -p rzd-cli -- run --network data/networks/synthetic_one_road_88_05.json --crews 12 --locos 12 --days 2 --seed 42 --format bundle --inject data/injection/sample_fault_windows.json
# Emit a reproducible benchmark report for the synthetic road
cargo run -p rzd-cli -- benchmark --network data/networks/synthetic_one_road_88_05.json --profile one-road-demo
cargo run -p rzd-cli -- benchmark --network data/networks/synthetic_one_road_88_05.json --profile one-road-month
cargo run -p rzd-cli -- benchmark --network data/networks/synthetic_one_road_88_05.json --profile one-road-stress
cargo run -p rzd-cli -- benchmark --network data/networks/synthetic_one_road_88_05.json --profile one-road-shoulder-a
cargo run -p rzd-cli -- benchmark --network data/networks/synthetic_one_road_88_05.json --profile one-road-shoulder-b
cargo run -p rzd-cli -- benchmark --network data/networks/synthetic_one_road_88_05.json --profile one-road-shoulder-c
cargo run -p rzd-cli -- benchmark --network data/networks/synthetic_one_road_88_05.json --profile one-road-competition
cargo run -p rzd-cli -- benchmark --network data/networks/synthetic_one_road_88_05.json --profile one-road-rzd-scale
# Emit a repeated benchmark suite across profiles
cargo run -p rzd-cli -- benchmark-suite --network data/networks/synthetic_one_road_88_05.json --profiles all --repeats 3
cargo run -p rzd-cli -- benchmark-suite --network data/networks/synthetic_one_road_88_05.json --profiles one-road-competition --repeats 2
cargo run -p rzd-cli -- benchmark-suite --network data/networks/synthetic_one_road_88_05.json --profiles one-road-rzd-scale --repeats 1
# Emit a contest-ready bundle directory with hashes and manifest
cargo run -p rzd-cli -- benchmark-bundle --network data/networks/synthetic_one_road_88_05.json --profile one-road-competition --output-dir out/one-road-competition-bundle
cargo run -p rzd-cli -- benchmark-bundle --network data/networks/synthetic_one_road_88_05.json --profile one-road-rzd-scale --output-dir out/one-road-rzd-scale-bundle
# Build a full scale packet with competition, rzd-scale, comparison, and leaderboard
cargo run -p rzd-cli -- scale-packet --network data/networks/synthetic_one_road_88_05.json --output-dir out/scale-packet
# Compare two bundle directories
cargo run -p rzd-cli -- compare-bundles --baseline-dir out/run-a --current-dir out/run-b --output-dir out/comparison
# Compare two trace files directly
cargo run -p rzd-cli -- compare-traces --baseline-trace out/run-a/event_trace.ndjson --current-trace out/run-b/event_trace.ndjson --output-dir out/trace-comparison
# Build an aggregate leaderboard from comparison outputs
cargo run -p rzd-cli -- comparison-leaderboard --input-dir out/comparisons-root --output-dir out/leaderboard
# Save and resume a synthetic-road checkpoint
cargo run -p rzd-cli -- checkpoint --network data/networks/synthetic_one_road_88_05.json --crews 24 --locos 12 --days 5 --seed 20260708 --checkpoint-minute 300 --output checkpoint_88_05.json
cargo run -p rzd-cli -- resume --snapshot checkpoint_88_05.json --until-minute 7200 --format summary
# Build WASM
cd crates/rzd-wasm && wasm-pack build --target web| File | Description |
|---|---|
data/networks/northern.json |
Northern Railway topology: 35 stations, 38 segments, 10 legs |
data/networks/synthetic_one_road_88_05.json |
Synthetic one-road benchmark package: 35 stations, 38 segments, 10 legs, 3 operating shoulders (A/B/C) |
data/networks/northern_constants.json |
Loco series, norms, failure/event types |
data/scenarios/one_road_month.json |
Declarative baseline one-road month scenario |
data/scenarios/one_road_shoulder_*.json |
Declarative shoulder-scoped one-road month scenarios |
synthetic_one_road_88_05.json is the external-safe demo network for one synthetic road.
- No real station names or depot names
- One road with three comparable operating shoulders:
A-West,B-Central,C-East - Mixed electric / dual / diesel traction zones
- Sized to resemble a single-road monthly package such as
88_05 - Intended for replayable demos, synthetic violation generation, and future large-scale benchmarks
Benchmark profiles currently available through rzd-cli benchmark:
one-road-demo— short deterministic run with scripted disruptionsone-road-month— baseline one-road synthetic monthone-road-stress— denser same-road stress profile for throughput checksone-road-shoulder-a— western shoulder month (SD-1,SD-2,TD-72; legsLEG-01..03)one-road-shoulder-b— central shoulder month (SD-3,SD-5,TD-74,SD-7; legsLEG-04..06,LEG-10)one-road-shoulder-c— eastern shoulder month (TD-71,TD-75,TD-77; legsLEG-07..09)one-road-competition— competition-scale synthetic month with deterministic burst injection of500,000manual violations on the same one-road networkone-road-rzd-scale— heavier synthetic one-road month with750,000manual violations and denser crew/loco load, intended as a stress step beyond the contest profile
Declarative scenario JSON examples currently available in data/scenarios/:
one_road_month.jsonone_road_shoulder_a.jsonone_road_shoulder_b.jsonone_road_shoulder_c.json
These scenario files now use the versioned contract schema
rzd-des-scenario/v1. The CLI still accepts legacy bare ScenarioConfig
JSON for backward compatibility, but the versioned wrapper is the preferred
long-term replay and exchange format.
Measured evidence on 2026-07-08:
one-road-competitionprocessed523,900events and produced500,157violations onsynthetic_one_road_88_05.jsonone-road-rzd-scaleprocessed783,726events and produced750,168violations onsynthetic_one_road_88_05.json- the single-run benchmark completed in about
11.6son the current workstation - the
one-road-rzd-scalesimulation run completed in about19.1son the current workstation - repeated suite runs (
repeats=2) preserved one unique business signature while wall-clock timing varied - benchmark export rendering on the same run produced:
violations_ndjson:500,157lines,128,518,655bytes, about27.5srender timeCED JSON:5,018,424lines,143,442,164bytes, about153.7srender timeTU-3 TSV:1,502lines,536,366bytes, about0.23srender time
- benchmark export rendering on
one-road-rzd-scaleproduced:violations_ndjson:750,168lines,192,758,779bytes, about42.3srender timeCED JSON:7,526,594lines,215,132,167bytes, about48.8srender timeevent_trace.ndjson:783,726lines,221,448,020bytes, about51.1srender timeTU-3 TSV:2,203lines,784,916bytes, about0.37srender time
- after indexing violations by
crew_idinside CED export on2026-07-08, the sameCED JSONartifact dropped to about26.9srender time on the competition profile while preserving identical outward bytes and lines benchmark-bundlenow emits a reproducible directory containingreport.json,manifest.json,tu3.tsv,ced.json, andviolations.ndjsonbenchmark-bundlenow also emitsevent_trace.ndjson, a structured processed-event history for deterministic forensic comparison- the bundle manifest records SHA-256, bytes, and line counts for each outward artifact
- bundle comparison now evaluates the event trace artifact together with the other outward files via the shared manifest workflow
- bundle comparison now also reports shoulder-aware deltas, so drift across
A-West,B-Central, andC-Eastcan be inspected directly instead of inferred from aggregate totals benchmark-bundlealso emitsSUMMARY.md, a human-readable competition summary with key metrics, export sizes, render times, and the deterministic business signaturebenchmark-bundlealso emits standalonereport.html, an offline demo view for external reviewers that opens directly from the bundle directorybenchmark-bundlealso emitsJUDGING_PACKET.md, a concise contest-facing packet with the problem statement, scale metrics, artifact inventory, and reproducibility notescompare-bundlesemitscomparison.json,comparison.md, andcomparison.htmlfor baseline-vs-current evidence across two benchmark bundle directoriescompare-tracesemitstrace_comparison.json,trace_comparison.md, andtrace_comparison.htmlfor direct event-trace forensic comparison- comparison output now distinguishes
fully_equivalent,timing_only_drift,business_equivalent_only, andbusiness_drift, so regressions can be separated from harmless timing noise - trace comparison now also reports
trace_signatures_match,trace_event_count_delta, atrace_divergence_class, and the first divergence point when traces differ comparison-leaderboardemits aggregateleaderboard.json,leaderboard.md, andleaderboard.htmlacross multiple comparison artifactsscale-packetemits a ready-to-review directory containing competition and RZD-scale bundles plus their comparison, leaderboard, a top-levelSCALE_PACKET.md,SCALE_PACKET.html,MANIFEST_SCALE.json,packet_summary.json, andpacket_summary.tsv
Benchmark suite surface currently available through rzd-cli:
benchmark-suite— repeated runs across one or more profiles with aggregate latency and throughput statistics- each run now emits a stable
business_signaturebuilt from business results instead of wall-clock fields - suite reports now include a
determinismsection withunique_business_signaturesandbusiness_outputs_stable_across_repeats - on
2026-07-08,synthetic_one_road_88_05.jsonvalidated stable business outputs across repeats forone-road-demo,one-road-month, andone-road-stress; suite variance was limited to wall-clock timing one-road-competitionis intentionally explicit rather than part of--profiles all, so large competition-scale runs stay opt-inone-road-rzd-scaleis also intentionally opt-in and excluded from--profiles all, so the heaviest synthetic-road runs remain deliberate
Checkpoint surface currently available through rzd-cli:
checkpoint— run until a target minute and saverzd-des-engine-snapshot/v1resume— restore snapshot JSON and continue the run to a new minute boundary- on
2026-07-08, a checkpoint boundary bug that dropped the first post-checkpoint event was fixed; JSON snapshot roundtrip resume now matches the full synthetic-road run business results in automated tests
- DES engine — 24 event kinds, BinaryHeap priority queue, deterministic (Mulberry32 PRNG)
- Crew state machine — 11 states with validated transitions per Приказ Минтранса №339
- Violation checks — overtime, rest, night shift, acceptance delay, voltage sag
- CED export — competition format for
ced.syntog.ru(ЦЭД) - Replay bundle export — versioned JSON bundle with network, scenario, and run results for deterministic reruns
- Structured event trace — versioned
rzd-des-event-trace/v1export for deterministic forensic analysis and replay debugging - Scripted disruption injection — versioned JSON plan for waits, failures, voltage sag windows, and manual violations
- Engine snapshot contract — versioned JSON-safe engine state snapshot with restore of serialized runtime state and validated business-parity resume coverage on the synthetic road
- TU-3 export — 73-column TSV with BOM for Excel
- WASM integration — full JS interop via wasm-bindgen
- Statistics — Welford online mean/variance, time-weighted averages, histograms
<500 ms for 100,000 events with 100+ stations and 50+ legs.
Phase 1 (Core Hardening) — in progress. See CHANGELOG and Issues.
Supporting architecture notes: