simulsi 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. simulsi-0.2.0/.gitignore +30 -0
  2. simulsi-0.2.0/CHANGELOG.md +78 -0
  3. simulsi-0.2.0/LICENSE +21 -0
  4. simulsi-0.2.0/NOTICE +11 -0
  5. simulsi-0.2.0/PKG-INFO +206 -0
  6. simulsi-0.2.0/README.md +151 -0
  7. simulsi-0.2.0/benchmarks/README.md +59 -0
  8. simulsi-0.2.0/docs/architecture.md +163 -0
  9. simulsi-0.2.0/docs/cli.md +115 -0
  10. simulsi-0.2.0/docs/concepts.md +339 -0
  11. simulsi-0.2.0/docs/examples.md +93 -0
  12. simulsi-0.2.0/docs/experiments.md +266 -0
  13. simulsi-0.2.0/docs/extending.md +144 -0
  14. simulsi-0.2.0/docs/faq.md +100 -0
  15. simulsi-0.2.0/docs/getting-started.md +135 -0
  16. simulsi-0.2.0/docs/index.md +35 -0
  17. simulsi-0.2.0/docs/research.md +93 -0
  18. simulsi-0.2.0/docs/visualization.md +112 -0
  19. simulsi-0.2.0/pyproject.toml +130 -0
  20. simulsi-0.2.0/src/simulsi/__init__.py +70 -0
  21. simulsi-0.2.0/src/simulsi/__main__.py +5 -0
  22. simulsi-0.2.0/src/simulsi/_version.py +1 -0
  23. simulsi-0.2.0/src/simulsi/analysis/__init__.py +24 -0
  24. simulsi-0.2.0/src/simulsi/analysis/comparison.py +154 -0
  25. simulsi-0.2.0/src/simulsi/analysis/report.py +46 -0
  26. simulsi-0.2.0/src/simulsi/analysis/sensitivity.py +387 -0
  27. simulsi-0.2.0/src/simulsi/benchmarks.py +128 -0
  28. simulsi-0.2.0/src/simulsi/cli/__init__.py +3 -0
  29. simulsi-0.2.0/src/simulsi/cli/main.py +486 -0
  30. simulsi-0.2.0/src/simulsi/cli/templates.py +96 -0
  31. simulsi-0.2.0/src/simulsi/config/__init__.py +19 -0
  32. simulsi-0.2.0/src/simulsi/config/schema.py +263 -0
  33. simulsi-0.2.0/src/simulsi/core/__init__.py +13 -0
  34. simulsi-0.2.0/src/simulsi/core/checkpoint.py +159 -0
  35. simulsi-0.2.0/src/simulsi/core/clock.py +87 -0
  36. simulsi-0.2.0/src/simulsi/core/model.py +441 -0
  37. simulsi-0.2.0/src/simulsi/core/simulation.py +670 -0
  38. simulsi-0.2.0/src/simulsi/core/trace.py +79 -0
  39. simulsi-0.2.0/src/simulsi/cost/__init__.py +3 -0
  40. simulsi-0.2.0/src/simulsi/cost/model.py +193 -0
  41. simulsi-0.2.0/src/simulsi/entities/__init__.py +3 -0
  42. simulsi-0.2.0/src/simulsi/entities/entity.py +120 -0
  43. simulsi-0.2.0/src/simulsi/errors.py +50 -0
  44. simulsi-0.2.0/src/simulsi/events/__init__.py +3 -0
  45. simulsi-0.2.0/src/simulsi/events/event.py +221 -0
  46. simulsi-0.2.0/src/simulsi/experiments/__init__.py +17 -0
  47. simulsi-0.2.0/src/simulsi/experiments/experiment.py +548 -0
  48. simulsi-0.2.0/src/simulsi/experiments/montecarlo.py +261 -0
  49. simulsi-0.2.0/src/simulsi/experiments/provenance.py +61 -0
  50. simulsi-0.2.0/src/simulsi/introspection/__init__.py +21 -0
  51. simulsi-0.2.0/src/simulsi/introspection/graph.py +210 -0
  52. simulsi-0.2.0/src/simulsi/metrics/__init__.py +3 -0
  53. simulsi-0.2.0/src/simulsi/metrics/collectors.py +348 -0
  54. simulsi-0.2.0/src/simulsi/models/__init__.py +3 -0
  55. simulsi-0.2.0/src/simulsi/models/queueing.py +73 -0
  56. simulsi-0.2.0/src/simulsi/optimization/__init__.py +3 -0
  57. simulsi-0.2.0/src/simulsi/optimization/objective.py +131 -0
  58. simulsi-0.2.0/src/simulsi/processes/__init__.py +31 -0
  59. simulsi-0.2.0/src/simulsi/processes/disruption.py +165 -0
  60. simulsi-0.2.0/src/simulsi/processes/process.py +346 -0
  61. simulsi-0.2.0/src/simulsi/py.typed +0 -0
  62. simulsi-0.2.0/src/simulsi/queues/__init__.py +4 -0
  63. simulsi-0.2.0/src/simulsi/queues/discipline.py +99 -0
  64. simulsi-0.2.0/src/simulsi/queues/queue.py +256 -0
  65. simulsi-0.2.0/src/simulsi/randomness/__init__.py +47 -0
  66. simulsi-0.2.0/src/simulsi/randomness/distributions.py +449 -0
  67. simulsi-0.2.0/src/simulsi/randomness/stream.py +117 -0
  68. simulsi-0.2.0/src/simulsi/resources/__init__.py +3 -0
  69. simulsi-0.2.0/src/simulsi/resources/resource.py +519 -0
  70. simulsi-0.2.0/src/simulsi/scenarios/__init__.py +10 -0
  71. simulsi-0.2.0/src/simulsi/scenarios/scenario.py +132 -0
  72. simulsi-0.2.0/src/simulsi/serialization/__init__.py +23 -0
  73. simulsi-0.2.0/src/simulsi/serialization/io.py +128 -0
  74. simulsi-0.2.0/src/simulsi/statistics/__init__.py +37 -0
  75. simulsi-0.2.0/src/simulsi/statistics/core.py +418 -0
  76. simulsi-0.2.0/src/simulsi/validation/__init__.py +3 -0
  77. simulsi-0.2.0/src/simulsi/validation/validate.py +168 -0
  78. simulsi-0.2.0/src/simulsi/visualization/__init__.py +27 -0
  79. simulsi-0.2.0/src/simulsi/visualization/plots.py +423 -0
  80. simulsi-0.2.0/src/simulsi/web/__init__.py +1 -0
  81. simulsi-0.2.0/src/simulsi/web/server.py +338 -0
  82. simulsi-0.2.0/src/simulsi/web/static/assets/index-CNMcVqxw.css +2 -0
  83. simulsi-0.2.0/src/simulsi/web/static/assets/index-DDtrYZla.js +9 -0
  84. simulsi-0.2.0/src/simulsi/web/static/index.html +13 -0
  85. simulsi-0.2.0/tests/cli/test_cli.py +244 -0
  86. simulsi-0.2.0/tests/docs/test_docs.py +62 -0
  87. simulsi-0.2.0/tests/integration/test_analysis_features.py +366 -0
  88. simulsi-0.2.0/tests/integration/test_examples.py +52 -0
  89. simulsi-0.2.0/tests/integration/test_experiments.py +221 -0
  90. simulsi-0.2.0/tests/integration/test_visualization.py +71 -0
  91. simulsi-0.2.0/tests/integration/test_web_server.py +151 -0
  92. simulsi-0.2.0/tests/performance/test_performance.py +33 -0
  93. simulsi-0.2.0/tests/property/test_invariants.py +181 -0
  94. simulsi-0.2.0/tests/statistical/test_queueing_theory.py +66 -0
  95. simulsi-0.2.0/tests/unit/test_checkpoint.py +90 -0
  96. simulsi-0.2.0/tests/unit/test_entities.py +71 -0
  97. simulsi-0.2.0/tests/unit/test_events.py +173 -0
  98. simulsi-0.2.0/tests/unit/test_metrics.py +79 -0
  99. simulsi-0.2.0/tests/unit/test_model.py +122 -0
  100. simulsi-0.2.0/tests/unit/test_montecarlo_and_engine_extras.py +122 -0
  101. simulsi-0.2.0/tests/unit/test_processes.py +181 -0
  102. simulsi-0.2.0/tests/unit/test_queues.py +103 -0
  103. simulsi-0.2.0/tests/unit/test_randomness.py +169 -0
  104. simulsi-0.2.0/tests/unit/test_resources.py +316 -0
  105. simulsi-0.2.0/tests/unit/test_statistics.py +123 -0
  106. simulsi-0.2.0/web/README.md +41 -0
@@ -0,0 +1,30 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ .eggs/
6
+ build/
7
+ dist/
8
+ .venv/
9
+ venv/
10
+ .pytest_cache/
11
+ .mypy_cache/
12
+ .ruff_cache/
13
+ .hypothesis/
14
+ .coverage
15
+ coverage.xml
16
+ htmlcov/
17
+
18
+ # SimulSI outputs are per-user
19
+ simulsi-results/
20
+ *.checkpoint.jsonl
21
+
22
+ # Node / web
23
+ node_modules/
24
+ web/frontend/dist/
25
+ src/simulsi/web/static/
26
+
27
+ # OS / editors
28
+ .DS_Store
29
+ .idea/
30
+ .vscode/
@@ -0,0 +1,78 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented here. The format follows
4
+ [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project uses
5
+ [Semantic Versioning](https://semver.org/).
6
+
7
+ ## [Unreleased]
8
+
9
+ ## [0.2.0] - 2026-10-02
10
+
11
+ ### Added
12
+
13
+ - Preemptive resources (`preemptive=True` with the priority discipline);
14
+ evicted processes receive `Interrupt(Preempted(...))`.
15
+ - Sobol first-order and total-effect sensitivity indices
16
+ (`simulsi.analysis.sobol_indices`) with bootstrap CIs, validated against
17
+ the Ishigami function.
18
+ - Checkpoints of running simulations (`sim.save_checkpoint`,
19
+ `Simulation.load_checkpoint`) restored by verified deterministic replay.
20
+ - PyPI publishing workflow (trusted publishing).
21
+
22
+ ### Fixed
23
+
24
+ - Hold times in event-log records were wrong for units granted at t = 0.
25
+
26
+ ## [0.1.0] - 2026-10-02
27
+
28
+ First public release.
29
+
30
+ ### Added
31
+
32
+ - Discrete-event engine: float clock with `timedelta`/`datetime` conversion,
33
+ heap-based event queue with deterministic `(time, priority, sequence)`
34
+ ordering, scheduling, rescheduling, cancellation, `run(until=...)`
35
+ that stops exactly at the horizon, snapshots and a structured event log
36
+ (JSON/CSV/Parquet export).
37
+ - Generator-based processes with timeouts, signals, `all_of`/`any_of`,
38
+ waiting on other processes, interrupts and error propagation.
39
+ - Resources with FIFO/LIFO/priority/custom disciplines, reneging,
40
+ capacity changes, downtime, automatic statistics; blocking queues.
41
+ - Entities with attributes, state history and time-in-system metrics.
42
+ - Seeded random streams (PCG64, named sub-streams via `SeedSequence`) and 12
43
+ distributions with validation and configuration specs.
44
+ - Metrics: tallies, time-weighted gauges, counters, histograms, warm-up reset.
45
+ - Models (`Model`, `@model`, `Parameter`), scenarios, full-factorial grids.
46
+ - Experiments with common random numbers, provenance (git commit,
47
+ environment), parallel workers, checkpoint/resume and JSON/CSV/Parquet
48
+ export.
49
+ - Monte Carlo (random and Latin hypercube sampling, vectorised models,
50
+ simulation models), statistics (t/bootstrap/Wilson intervals, replication
51
+ advice, convergence, batch means, paired and Welch differences), scenario
52
+ comparison, sensitivity analysis (OAT, finite differences, Pearson,
53
+ Spearman, SRC).
54
+ - Failure/recovery processes, scheduled disruptions, cost models and an
55
+ optimisation `Objective` adapter.
56
+ - Model validation (smoke run with deadlock / unreleased-resource / state
57
+ checks) and flow/state graph introspection (Mermaid, DOT).
58
+ - Optional matplotlib/Plotly visualisation.
59
+ - YAML experiment configuration (strict schema, safe loading, path checks)
60
+ and the `simulsi` CLI: `init`, `validate`, `run`, `experiment`, `analyze`,
61
+ `benchmark`, `visualize`, `ui`.
62
+ - Optional React + TypeScript dashboard (`simulsi ui`): load experiments,
63
+ view parameters and provenance, run models, compare scenarios, inspect
64
+ distributions and convergence, trace single runs (timeline, queues,
65
+ utilization) and export JSON/CSV. Served locally on 127.0.0.1.
66
+ - Six domain examples: bank, hospital, warehouse, manufacturing,
67
+ transportation, aviation - plus a minimal M/M/c example.
68
+ - Benchmark suite (`benchmarks/run_benchmarks.py`, `simulsi benchmark`) with
69
+ measured results, and performance regression tests.
70
+ - Documentation: user guide, architecture, research workflow, extension guide,
71
+ FAQ; documentation code blocks are executed by the test suite.
72
+
73
+ ### Known limitations
74
+
75
+ - No preemptive resources, continuous-time dynamics or single-run
76
+ checkpoint/restore (experiments are checkpointed per replication).
77
+ - Sensitivity analysis is local / correlation-based; no Sobol indices yet.
78
+ - Not yet published on PyPI; install from source.
simulsi-0.2.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Yash Jindal
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
simulsi-0.2.0/NOTICE ADDED
@@ -0,0 +1,11 @@
1
+ NOTICE
2
+ ======
3
+
4
+ This project is licensed under the MIT License (see LICENSE).
5
+
6
+ You are free to use, study, modify and build on this code, including
7
+ commercially. The MIT License requires that you keep the copyright notice
8
+ and license text with any substantial portion you reuse.
9
+
10
+ Nothing in this NOTICE modifies, restricts or adds conditions to the MIT
11
+ License. If the two ever appear to conflict, the LICENSE file governs.
simulsi-0.2.0/PKG-INFO ADDED
@@ -0,0 +1,206 @@
1
+ Metadata-Version: 2.5
2
+ Name: simulsi
3
+ Version: 0.2.0
4
+ Summary: A general-purpose, reproducible simulation and scenario experimentation framework for Python.
5
+ Project-URL: Homepage, https://github.com/Yashjindal11/simulsi
6
+ Project-URL: Documentation, https://github.com/Yashjindal11/simulsi/tree/main/docs
7
+ Project-URL: Issues, https://github.com/Yashjindal11/simulsi/issues
8
+ Author: Yash Jindal
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ License-File: NOTICE
12
+ Keywords: discrete-event-simulation,experiments,monte-carlo,operations-research,queueing,sensitivity-analysis,simulation
13
+ Classifier: Development Status :: 3 - Alpha
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Intended Audience :: Science/Research
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Scientific/Engineering
21
+ Classifier: Topic :: Scientific/Engineering :: Mathematics
22
+ Classifier: Typing :: Typed
23
+ Requires-Python: >=3.11
24
+ Requires-Dist: numpy>=1.26
25
+ Requires-Dist: pydantic>=2.6
26
+ Requires-Dist: pyyaml>=6.0
27
+ Requires-Dist: scipy>=1.11
28
+ Provides-Extra: all
29
+ Requires-Dist: matplotlib>=3.8; extra == 'all'
30
+ Requires-Dist: pandas>=2.1; extra == 'all'
31
+ Requires-Dist: plotly>=5.18; extra == 'all'
32
+ Requires-Dist: pyarrow>=14; extra == 'all'
33
+ Provides-Extra: dev
34
+ Requires-Dist: build>=1.2; extra == 'dev'
35
+ Requires-Dist: hypothesis>=6.100; extra == 'dev'
36
+ Requires-Dist: matplotlib>=3.8; extra == 'dev'
37
+ Requires-Dist: mypy>=1.10; extra == 'dev'
38
+ Requires-Dist: pandas>=2.1; extra == 'dev'
39
+ Requires-Dist: plotly>=5.18; extra == 'dev'
40
+ Requires-Dist: pyarrow>=14; extra == 'dev'
41
+ Requires-Dist: pytest-cov>=5.0; extra == 'dev'
42
+ Requires-Dist: pytest>=8.0; extra == 'dev'
43
+ Requires-Dist: ruff==0.16.10; extra == 'dev'
44
+ Requires-Dist: types-pyyaml; extra == 'dev'
45
+ Provides-Extra: pandas
46
+ Requires-Dist: pandas>=2.1; extra == 'pandas'
47
+ Provides-Extra: parquet
48
+ Requires-Dist: pandas>=2.1; extra == 'parquet'
49
+ Requires-Dist: pyarrow>=14; extra == 'parquet'
50
+ Provides-Extra: plotly
51
+ Requires-Dist: plotly>=5.18; extra == 'plotly'
52
+ Provides-Extra: viz
53
+ Requires-Dist: matplotlib>=3.8; extra == 'viz'
54
+ Description-Content-Type: text/markdown
55
+
56
+ # SimulSI
57
+
58
+ **Simulation Intelligence** - *Model the system. Simulate the future.*
59
+
60
+ SimulSI is a general-purpose, reproducible simulation and scenario
61
+ experimentation framework for Python. You describe a system - customers and
62
+ tellers, patients and doctors, jobs and machines, aircraft and gates, requests
63
+ and servers - as discrete-event processes; SimulSI runs it, measures it, and
64
+ helps you answer *what if?* with replications, confidence intervals, scenario
65
+ comparisons, Monte Carlo and sensitivity analysis.
66
+
67
+ ```python
68
+ from simulsi import Experiment, Scenario, Simulation, model
69
+ from simulsi.randomness import Exponential
70
+
71
+
72
+ @model(duration=480, parameters={"arrival_rate": 1.0, "tellers": 3})
73
+ def bank(sim: Simulation, p):
74
+ tellers = sim.resource("teller", capacity=p.tellers)
75
+ arrivals, service = sim.stream("arrivals"), sim.stream("service")
76
+
77
+ def customer(sim):
78
+ yield sim.request(tellers) # wait for a teller
79
+ yield Exponential(mean=2.6).sample(service) # being served
80
+ sim.release(tellers)
81
+
82
+ def source(sim):
83
+ while True:
84
+ yield Exponential(rate=p.arrival_rate).sample(arrivals)
85
+ sim.process(customer(sim))
86
+
87
+ sim.process(source(sim))
88
+
89
+
90
+ result = Experiment(
91
+ bank,
92
+ [Scenario("baseline"), Scenario("four_tellers", {"tellers": 4})],
93
+ replications=30,
94
+ seed=42,
95
+ ).run()
96
+ print(result.format_summary(["resource.teller.wait.mean", "resource.teller.utilization"]))
97
+ print(result.compare("baseline", metrics=["resource.teller.wait.mean"]).format())
98
+ ```
99
+
100
+ ## Why SimulSI?
101
+
102
+ Discrete-event engines tell you what happened in *one* run. Decisions need
103
+ more: how sure are we, which scenario is better, which input matters most, and
104
+ can someone else reproduce this? SimulSI is built **experiment-first**:
105
+
106
+ | | |
107
+ |---|---|
108
+ | **Reproducible by construction** | Every run is determined by its seed. Named random streams (`sim.stream("arrivals")`) are derived from the seed with NumPy's `SeedSequence`, so adding a resource never shifts another stream. Serial and parallel runs give identical numbers. |
109
+ | **Scenario comparison** | Scenarios share replication seeds (*common random numbers*) and comparisons use paired confidence intervals, which are usually much tighter than comparing independent runs. |
110
+ | **Statistics built in** | t and bootstrap CIs, Wilson intervals for probabilities, "have I run enough replications?" advice, convergence curves, batch means for long runs. |
111
+ | **Monte Carlo & sensitivity** | Propagate input uncertainty (random or Latin hypercube sampling, vectorised or per simulation run). One-at-a-time, finite-difference, correlation and standardised-regression sensitivity. |
112
+ | **Provenance** | Each experiment records id, model name/version, git commit, timestamp, seeds, parameters, runtime and environment. Results export to JSON, CSV and Parquet. |
113
+ | **Model introspection** | `snapshot()` of live state, structured event logs, observed flow graphs (arrival -> queue -> service -> departure), entity state machines, and model validation with a smoke run (unreleased resources, possible deadlocks, zero capacities, unreached states). |
114
+ | **Decision support** | Cost/revenue models on top of metrics; an `Objective` adapter that hands models to scipy.optimize, OR-Tools, evolutionary or Bayesian optimisers without depending on any of them. |
115
+ | **Local-first** | No LLMs, API keys, telemetry or network access. Core dependencies: NumPy, SciPy, pydantic, PyYAML. Plotting, pandas, Parquet and the web dashboard are optional. |
116
+
117
+ SimulSI is not a replacement for mature engines such as SimPy or Salabim, or
118
+ for commercial packages; see
119
+ [how SimulSI differs](docs/faq.md#how-does-simulsi-compare-with-other-tools).
120
+
121
+ ## Installation
122
+
123
+ SimulSI is not on PyPI yet; install from source (Python 3.11+):
124
+
125
+ ```bash
126
+ git clone https://github.com/Yashjindal11/simulsi.git && cd simulsi
127
+ python -m venv .venv
128
+ .venv/bin/pip install -e . # core
129
+ .venv/bin/pip install -e ".[viz]" # + matplotlib plots
130
+ .venv/bin/pip install -e ".[all]" # + pandas, Parquet, matplotlib, Plotly
131
+ .venv/bin/pip install -e ".[dev]" # everything needed to run the tests
132
+ ```
133
+
134
+ ## Command line
135
+
136
+ ```bash
137
+ simulsi init my-study # starter model.py + experiment.yaml
138
+ simulsi validate my-study/experiment.yaml # schema check + model smoke run
139
+ simulsi run examples/queue.py -p servers=3 # one replication, metrics table
140
+ simulsi experiment my-study/experiment.yaml # scenarios x replications, comparison, saved results
141
+ simulsi analyze my-study/results/service-desk --precision 0.05
142
+ simulsi visualize my-study/results/service-desk --out plots
143
+ simulsi benchmark # events/sec on this machine
144
+ simulsi ui my-study/results/service-desk # local dashboard on 127.0.0.1
145
+ ```
146
+
147
+ Experiments are described in YAML - data only, validated against a strict
148
+ schema:
149
+
150
+ ```yaml
151
+ model: model.py:service_desk
152
+ simulation: {seed: 42, duration: 480}
153
+ experiment: {replications: 30, workers: 4}
154
+ parameters: {arrival_rate: 0.9}
155
+ scenarios:
156
+ - {name: high_demand, parameters: {arrival_rate: 1.3}}
157
+ - {name: extra_server, parameters: {servers: 3}}
158
+ ```
159
+
160
+ ## Examples
161
+
162
+ | Example | Shows |
163
+ |---|---|
164
+ | [`queue.py`](examples/queue.py) | Minimal M/M/c model checked against Erlang C |
165
+ | [`bank_queue.py`](examples/bank_queue.py) | Reneging customers, staffing scenarios, replication advice |
166
+ | [`hospital.py`](examples/hospital.py) | Priority triage, several resources, service levels |
167
+ | [`warehouse.py`](examples/warehouse.py) | Time-varying demand, picking/packing buffers, backlog |
168
+ | [`manufacturing.py`](examples/manufacturing.py) | Breakdowns with a repair crew, blocking, cost model |
169
+ | [`transportation.py`](examples/transportation.py) | Shuttle loop, boarding capacity, left-behind passengers |
170
+ | [`aviation.py`](examples/aviation.py) | Synthetic airport gates, taxiway holds, tows, weather disruption |
171
+
172
+ ```bash
173
+ python examples/hospital.py
174
+ python scripts/run_examples.py # all of them, quick mode
175
+ ```
176
+
177
+ ## Documentation
178
+
179
+ - [Getting started](docs/getting-started.md) - installation, quickstart, first experiment
180
+ - [Core concepts](docs/concepts.md) - simulation, events, entities, resources, queues, processes, randomness, metrics, disruptions, validation, introspection
181
+ - [Experiments and analysis](docs/experiments.md) - scenarios, experiments, Monte Carlo, statistics, comparison, sensitivity, cost, optimisation
182
+ - [Visualization](docs/visualization.md) - plots and the web dashboard
183
+ - [CLI and configuration](docs/cli.md)
184
+ - [Architecture](docs/architecture.md) - design, module map, performance, limitations
185
+ - [Extending SimulSI](docs/extending.md)
186
+ - [Research workflow](docs/research.md) - reproducibility, provenance, statistical practice
187
+ - [Examples](docs/examples.md) - walkthroughs of the domain examples
188
+ - [FAQ](docs/faq.md) - including how SimulSI compares with other tools
189
+ - [Benchmarks](benchmarks/README.md) - measured numbers and how to reproduce them
190
+
191
+ ## Status
192
+
193
+ SimulSI is alpha software (0.x) and the API may still change. It is tested on
194
+ Python 3.11-3.13 (Linux, macOS, Windows in CI) with unit, property-based
195
+ (Hypothesis), statistical, integration, CLI and performance tests - including
196
+ checks of simulated M/M/c queues against closed-form Erlang-C results.
197
+
198
+ ## Contributing
199
+
200
+ Issues and pull requests are welcome - see [CONTRIBUTING.md](CONTRIBUTING.md)
201
+ and the [Code of Conduct](CODE_OF_CONDUCT.md). For security reports see
202
+ [SECURITY.md](SECURITY.md).
203
+
204
+ ## License
205
+
206
+ [MIT](LICENSE) © 2026 Yash Jindal
@@ -0,0 +1,151 @@
1
+ # SimulSI
2
+
3
+ **Simulation Intelligence** - *Model the system. Simulate the future.*
4
+
5
+ SimulSI is a general-purpose, reproducible simulation and scenario
6
+ experimentation framework for Python. You describe a system - customers and
7
+ tellers, patients and doctors, jobs and machines, aircraft and gates, requests
8
+ and servers - as discrete-event processes; SimulSI runs it, measures it, and
9
+ helps you answer *what if?* with replications, confidence intervals, scenario
10
+ comparisons, Monte Carlo and sensitivity analysis.
11
+
12
+ ```python
13
+ from simulsi import Experiment, Scenario, Simulation, model
14
+ from simulsi.randomness import Exponential
15
+
16
+
17
+ @model(duration=480, parameters={"arrival_rate": 1.0, "tellers": 3})
18
+ def bank(sim: Simulation, p):
19
+ tellers = sim.resource("teller", capacity=p.tellers)
20
+ arrivals, service = sim.stream("arrivals"), sim.stream("service")
21
+
22
+ def customer(sim):
23
+ yield sim.request(tellers) # wait for a teller
24
+ yield Exponential(mean=2.6).sample(service) # being served
25
+ sim.release(tellers)
26
+
27
+ def source(sim):
28
+ while True:
29
+ yield Exponential(rate=p.arrival_rate).sample(arrivals)
30
+ sim.process(customer(sim))
31
+
32
+ sim.process(source(sim))
33
+
34
+
35
+ result = Experiment(
36
+ bank,
37
+ [Scenario("baseline"), Scenario("four_tellers", {"tellers": 4})],
38
+ replications=30,
39
+ seed=42,
40
+ ).run()
41
+ print(result.format_summary(["resource.teller.wait.mean", "resource.teller.utilization"]))
42
+ print(result.compare("baseline", metrics=["resource.teller.wait.mean"]).format())
43
+ ```
44
+
45
+ ## Why SimulSI?
46
+
47
+ Discrete-event engines tell you what happened in *one* run. Decisions need
48
+ more: how sure are we, which scenario is better, which input matters most, and
49
+ can someone else reproduce this? SimulSI is built **experiment-first**:
50
+
51
+ | | |
52
+ |---|---|
53
+ | **Reproducible by construction** | Every run is determined by its seed. Named random streams (`sim.stream("arrivals")`) are derived from the seed with NumPy's `SeedSequence`, so adding a resource never shifts another stream. Serial and parallel runs give identical numbers. |
54
+ | **Scenario comparison** | Scenarios share replication seeds (*common random numbers*) and comparisons use paired confidence intervals, which are usually much tighter than comparing independent runs. |
55
+ | **Statistics built in** | t and bootstrap CIs, Wilson intervals for probabilities, "have I run enough replications?" advice, convergence curves, batch means for long runs. |
56
+ | **Monte Carlo & sensitivity** | Propagate input uncertainty (random or Latin hypercube sampling, vectorised or per simulation run). One-at-a-time, finite-difference, correlation and standardised-regression sensitivity. |
57
+ | **Provenance** | Each experiment records id, model name/version, git commit, timestamp, seeds, parameters, runtime and environment. Results export to JSON, CSV and Parquet. |
58
+ | **Model introspection** | `snapshot()` of live state, structured event logs, observed flow graphs (arrival -> queue -> service -> departure), entity state machines, and model validation with a smoke run (unreleased resources, possible deadlocks, zero capacities, unreached states). |
59
+ | **Decision support** | Cost/revenue models on top of metrics; an `Objective` adapter that hands models to scipy.optimize, OR-Tools, evolutionary or Bayesian optimisers without depending on any of them. |
60
+ | **Local-first** | No LLMs, API keys, telemetry or network access. Core dependencies: NumPy, SciPy, pydantic, PyYAML. Plotting, pandas, Parquet and the web dashboard are optional. |
61
+
62
+ SimulSI is not a replacement for mature engines such as SimPy or Salabim, or
63
+ for commercial packages; see
64
+ [how SimulSI differs](docs/faq.md#how-does-simulsi-compare-with-other-tools).
65
+
66
+ ## Installation
67
+
68
+ SimulSI is not on PyPI yet; install from source (Python 3.11+):
69
+
70
+ ```bash
71
+ git clone https://github.com/Yashjindal11/simulsi.git && cd simulsi
72
+ python -m venv .venv
73
+ .venv/bin/pip install -e . # core
74
+ .venv/bin/pip install -e ".[viz]" # + matplotlib plots
75
+ .venv/bin/pip install -e ".[all]" # + pandas, Parquet, matplotlib, Plotly
76
+ .venv/bin/pip install -e ".[dev]" # everything needed to run the tests
77
+ ```
78
+
79
+ ## Command line
80
+
81
+ ```bash
82
+ simulsi init my-study # starter model.py + experiment.yaml
83
+ simulsi validate my-study/experiment.yaml # schema check + model smoke run
84
+ simulsi run examples/queue.py -p servers=3 # one replication, metrics table
85
+ simulsi experiment my-study/experiment.yaml # scenarios x replications, comparison, saved results
86
+ simulsi analyze my-study/results/service-desk --precision 0.05
87
+ simulsi visualize my-study/results/service-desk --out plots
88
+ simulsi benchmark # events/sec on this machine
89
+ simulsi ui my-study/results/service-desk # local dashboard on 127.0.0.1
90
+ ```
91
+
92
+ Experiments are described in YAML - data only, validated against a strict
93
+ schema:
94
+
95
+ ```yaml
96
+ model: model.py:service_desk
97
+ simulation: {seed: 42, duration: 480}
98
+ experiment: {replications: 30, workers: 4}
99
+ parameters: {arrival_rate: 0.9}
100
+ scenarios:
101
+ - {name: high_demand, parameters: {arrival_rate: 1.3}}
102
+ - {name: extra_server, parameters: {servers: 3}}
103
+ ```
104
+
105
+ ## Examples
106
+
107
+ | Example | Shows |
108
+ |---|---|
109
+ | [`queue.py`](examples/queue.py) | Minimal M/M/c model checked against Erlang C |
110
+ | [`bank_queue.py`](examples/bank_queue.py) | Reneging customers, staffing scenarios, replication advice |
111
+ | [`hospital.py`](examples/hospital.py) | Priority triage, several resources, service levels |
112
+ | [`warehouse.py`](examples/warehouse.py) | Time-varying demand, picking/packing buffers, backlog |
113
+ | [`manufacturing.py`](examples/manufacturing.py) | Breakdowns with a repair crew, blocking, cost model |
114
+ | [`transportation.py`](examples/transportation.py) | Shuttle loop, boarding capacity, left-behind passengers |
115
+ | [`aviation.py`](examples/aviation.py) | Synthetic airport gates, taxiway holds, tows, weather disruption |
116
+
117
+ ```bash
118
+ python examples/hospital.py
119
+ python scripts/run_examples.py # all of them, quick mode
120
+ ```
121
+
122
+ ## Documentation
123
+
124
+ - [Getting started](docs/getting-started.md) - installation, quickstart, first experiment
125
+ - [Core concepts](docs/concepts.md) - simulation, events, entities, resources, queues, processes, randomness, metrics, disruptions, validation, introspection
126
+ - [Experiments and analysis](docs/experiments.md) - scenarios, experiments, Monte Carlo, statistics, comparison, sensitivity, cost, optimisation
127
+ - [Visualization](docs/visualization.md) - plots and the web dashboard
128
+ - [CLI and configuration](docs/cli.md)
129
+ - [Architecture](docs/architecture.md) - design, module map, performance, limitations
130
+ - [Extending SimulSI](docs/extending.md)
131
+ - [Research workflow](docs/research.md) - reproducibility, provenance, statistical practice
132
+ - [Examples](docs/examples.md) - walkthroughs of the domain examples
133
+ - [FAQ](docs/faq.md) - including how SimulSI compares with other tools
134
+ - [Benchmarks](benchmarks/README.md) - measured numbers and how to reproduce them
135
+
136
+ ## Status
137
+
138
+ SimulSI is alpha software (0.x) and the API may still change. It is tested on
139
+ Python 3.11-3.13 (Linux, macOS, Windows in CI) with unit, property-based
140
+ (Hypothesis), statistical, integration, CLI and performance tests - including
141
+ checks of simulated M/M/c queues against closed-form Erlang-C results.
142
+
143
+ ## Contributing
144
+
145
+ Issues and pull requests are welcome - see [CONTRIBUTING.md](CONTRIBUTING.md)
146
+ and the [Code of Conduct](CODE_OF_CONDUCT.md). For security reports see
147
+ [SECURITY.md](SECURITY.md).
148
+
149
+ ## License
150
+
151
+ [MIT](LICENSE) © 2026 Yash Jindal
@@ -0,0 +1,59 @@
1
+ # Benchmarks
2
+
3
+ ```bash
4
+ python benchmarks/run_benchmarks.py # full suite, ~1 minute
5
+ python benchmarks/run_benchmarks.py --quick # 10k / 100k only
6
+ simulsi benchmark # same measurements from the CLI
7
+ ```
8
+
9
+ The script writes [`results/latest.json`](results/latest.json) (raw numbers
10
+ plus the environment) and [`results/latest.md`](results/latest.md).
11
+
12
+ ## What is measured
13
+
14
+ | Benchmark | Description | Size means |
15
+ |---|---|---|
16
+ | `events` | Pure engine overhead: callback events in 100 interleaved chains with exponential delays (heap push/pop, clock, dispatch). | events |
17
+ | `processes` | An M/M/2 queue written with generator processes, a resource with contention, and metrics: about 3.85 events per customer. | customers |
18
+ | `experiment(workers=N)` | 16 replications of the built-in M/M/1 model (20,000 time units each), serial and in worker processes. | replications |
19
+ | `peak_memory_mb` | `tracemalloc` peak during a separate run (sizes up to 100k only, because tracing slows the run). | |
20
+
21
+ ## Results
22
+
23
+ Measured on 2026-10-02 on the development machine. These are single
24
+ measurements, not averages over repeated runs; expect some run-to-run
25
+ variation. Re-run the script on your hardware rather than relying on them.
26
+
27
+ - Python 3.12.15 (CPython), NumPy 2.5.3, SimulSI 0.1.0.dev0
28
+ - macOS 26.6.2 on Apple silicon (arm64), 10 logical CPUs
29
+
30
+ | name | size | events | seconds | events/s | peak MB |
31
+ |---|---:|---:|---:|---:|---:|
32
+ | events | 10,000 | 10,000 | 0.023 | 437,190 | 0.02 |
33
+ | events | 100,000 | 100,000 | 0.228 | 438,656 | 0.02 |
34
+ | events | 1,000,000 | 1,000,000 | 2.281 | 438,466 | - |
35
+ | processes | 10,000 | 38,501 | 0.154 | 250,000 | 0.31 |
36
+ | processes | 100,000 | 385,581 | 1.595 | 241,692 | 0.54 |
37
+ | processes | 1,000,000 | 3,850,935 | 16.34 | 235,737 | - |
38
+ | experiment (1 worker) | 16 | 1,119,489 | 4.59 | 244,072 | - |
39
+ | experiment (2 workers) | 16 | 1,119,489 | 3.82 | 293,357 | - |
40
+ | experiment (4 workers) | 16 | 1,119,489 | 3.40 | 329,285 | - |
41
+
42
+ ## Observations
43
+
44
+ * Throughput is flat from 10k to 1M events: the heap is O(log n) and
45
+ finished processes and timeouts are freed by reference counting. An
46
+ earlier version kept a reference cycle per timeout, so the cyclic garbage
47
+ collector slowed long runs by about 30%. That was found with this suite and
48
+ fixed.
49
+ * Memory stays small because statistics are incremental. Keeping raw
50
+ observations (`keep_values`), time series (`record_series`), entity
51
+ histories or an event log (`trace=True`) costs memory proportional to run
52
+ length.
53
+ * Parallel speed-up is modest here (about 1.35x with 4 workers): each
54
+ replication takes about 0.3 s, while starting a worker process with the
55
+ `spawn` method (macOS, Windows) and importing NumPy/SciPy costs about a
56
+ second. Longer replications parallelise better. Results are identical to
57
+ serial runs either way (tested).
58
+ * `tests/performance/test_performance.py` guards against regressions with
59
+ generous floors (about 10x below these numbers) and a linear-scaling check.