simweave 0.4.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.
- simweave-0.4.0/MANIFEST.in +51 -0
- simweave-0.4.0/PKG-INFO +304 -0
- simweave-0.4.0/README.md +255 -0
- simweave-0.4.0/pyproject.toml +71 -0
- simweave-0.4.0/requirements-dev.txt +7 -0
- simweave-0.4.0/requirements.txt +3 -0
- simweave-0.4.0/setup.cfg +4 -0
- simweave-0.4.0/src/simweave/__init__.py +198 -0
- simweave-0.4.0/src/simweave/agents/__init__.py +23 -0
- simweave-0.4.0/src/simweave/agents/agent.py +161 -0
- simweave-0.4.0/src/simweave/agents/compass.py +48 -0
- simweave-0.4.0/src/simweave/agents/routing.py +113 -0
- simweave-0.4.0/src/simweave/continuous/__init__.py +31 -0
- simweave-0.4.0/src/simweave/continuous/solver.py +237 -0
- simweave-0.4.0/src/simweave/continuous/systems/__init__.py +14 -0
- simweave-0.4.0/src/simweave/continuous/systems/mass_spring_damper.py +43 -0
- simweave-0.4.0/src/simweave/continuous/systems/pendulum.py +49 -0
- simweave-0.4.0/src/simweave/continuous/systems/quarter_car.py +59 -0
- simweave-0.4.0/src/simweave/continuous/systems/rlc.py +44 -0
- simweave-0.4.0/src/simweave/continuous/systems/thermal.py +127 -0
- simweave-0.4.0/src/simweave/core/__init__.py +18 -0
- simweave-0.4.0/src/simweave/core/clock.py +64 -0
- simweave-0.4.0/src/simweave/core/entity.py +74 -0
- simweave-0.4.0/src/simweave/core/environment.py +121 -0
- simweave-0.4.0/src/simweave/core/logging.py +41 -0
- simweave-0.4.0/src/simweave/core/scheduler.py +85 -0
- simweave-0.4.0/src/simweave/currency/__init__.py +64 -0
- simweave-0.4.0/src/simweave/currency/codes.py +257 -0
- simweave-0.4.0/src/simweave/currency/format.py +92 -0
- simweave-0.4.0/src/simweave/currency/fx.py +126 -0
- simweave-0.4.0/src/simweave/currency/money.py +328 -0
- simweave-0.4.0/src/simweave/discrete/__init__.py +28 -0
- simweave-0.4.0/src/simweave/discrete/properties.py +113 -0
- simweave-0.4.0/src/simweave/discrete/queues.py +317 -0
- simweave-0.4.0/src/simweave/discrete/resources.py +89 -0
- simweave-0.4.0/src/simweave/discrete/services.py +228 -0
- simweave-0.4.0/src/simweave/mc/__init__.py +5 -0
- simweave-0.4.0/src/simweave/mc/runner.py +151 -0
- simweave-0.4.0/src/simweave/spatial/__init__.py +5 -0
- simweave-0.4.0/src/simweave/spatial/graph.py +147 -0
- simweave-0.4.0/src/simweave/supplychain/__init__.py +9 -0
- simweave-0.4.0/src/simweave/supplychain/inventory.py +77 -0
- simweave-0.4.0/src/simweave/supplychain/optimization.py +197 -0
- simweave-0.4.0/src/simweave/supplychain/warehouse.py +153 -0
- simweave-0.4.0/src/simweave/units/__init__.py +25 -0
- simweave-0.4.0/src/simweave/units/si.py +213 -0
- simweave-0.4.0/src/simweave/viz/__init__.py +77 -0
- simweave-0.4.0/src/simweave/viz/_plotly.py +35 -0
- simweave-0.4.0/src/simweave/viz/plots.py +618 -0
- simweave-0.4.0/src/simweave/viz/recorders.py +172 -0
- simweave-0.4.0/src/simweave/viz/themes.py +187 -0
- simweave-0.4.0/src/simweave.egg-info/PKG-INFO +304 -0
- simweave-0.4.0/src/simweave.egg-info/SOURCES.txt +54 -0
- simweave-0.4.0/src/simweave.egg-info/dependency_links.txt +1 -0
- simweave-0.4.0/src/simweave.egg-info/requires.txt +50 -0
- simweave-0.4.0/src/simweave.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Controls what setuptools ships in the source distribution (sdist).
|
|
2
|
+
# The wheel is narrower still (only src/simweave/**/*.py) and governed by
|
|
3
|
+
# [tool.setuptools] in pyproject.toml.
|
|
4
|
+
#
|
|
5
|
+
# Rule of thumb: the sdist should contain everything needed to rebuild
|
|
6
|
+
# the wheel from a clean checkout, and NOTHING that's internal dev
|
|
7
|
+
# documentation, scratchpads, or editor/tool metadata.
|
|
8
|
+
|
|
9
|
+
# --- include the essentials ------------------------------------------------
|
|
10
|
+
include README.md
|
|
11
|
+
include LICENSE
|
|
12
|
+
include pyproject.toml
|
|
13
|
+
include requirements.txt
|
|
14
|
+
include requirements-dev.txt
|
|
15
|
+
|
|
16
|
+
# Package sources only; no tests, no demos in the sdist.
|
|
17
|
+
recursive-include src *.py
|
|
18
|
+
|
|
19
|
+
# --- exclude internal design / integration docs ---------------------------
|
|
20
|
+
# These are for contributors and for the EdgeWeave repo, not end users of
|
|
21
|
+
# the PyPI package.
|
|
22
|
+
exclude PACKAGING.md
|
|
23
|
+
exclude CURRENCY_DESIGN.md
|
|
24
|
+
exclude SIMWEAVE_API.md
|
|
25
|
+
exclude EdgeWeave.md
|
|
26
|
+
exclude VIZ_DESIGN.md
|
|
27
|
+
|
|
28
|
+
# --- exclude repo-level directories that don't belong in the sdist --------
|
|
29
|
+
prune .github
|
|
30
|
+
prune .claude
|
|
31
|
+
prune .idea
|
|
32
|
+
prune .vscode
|
|
33
|
+
prune archive
|
|
34
|
+
prune demos
|
|
35
|
+
prune docs
|
|
36
|
+
prune tests
|
|
37
|
+
|
|
38
|
+
# --- exclude common editor / tool metadata anywhere in the tree -----------
|
|
39
|
+
global-exclude .DS_Store
|
|
40
|
+
global-exclude Thumbs.db
|
|
41
|
+
global-exclude .claude*
|
|
42
|
+
global-exclude .cursor*
|
|
43
|
+
global-exclude CLAUDE.md
|
|
44
|
+
global-exclude .ruff_cache
|
|
45
|
+
global-exclude .mypy_cache
|
|
46
|
+
global-exclude .pytest_cache
|
|
47
|
+
global-exclude __pycache__
|
|
48
|
+
global-exclude *.py[co]
|
|
49
|
+
global-exclude *.log
|
|
50
|
+
global-exclude *.swp
|
|
51
|
+
global-exclude *~
|
simweave-0.4.0/PKG-INFO
ADDED
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: simweave
|
|
3
|
+
Version: 0.4.0
|
|
4
|
+
Summary: SimWeave: a hybrid discrete/continuous simulation engine with currency, units, agents, supply chains, and Monte Carlo.
|
|
5
|
+
Author: Stuart
|
|
6
|
+
License: MIT
|
|
7
|
+
Requires-Python: >=3.10
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
Requires-Dist: numpy>=1.23
|
|
10
|
+
Provides-Extra: optim
|
|
11
|
+
Requires-Dist: scipy>=1.10; extra == "optim"
|
|
12
|
+
Provides-Extra: plot
|
|
13
|
+
Requires-Dist: matplotlib>=3.7; extra == "plot"
|
|
14
|
+
Provides-Extra: viz
|
|
15
|
+
Requires-Dist: plotly>=5.18; extra == "viz"
|
|
16
|
+
Provides-Extra: graph
|
|
17
|
+
Requires-Dist: networkx>=3.0; extra == "graph"
|
|
18
|
+
Provides-Extra: geo
|
|
19
|
+
Requires-Dist: osmnx>=1.8; extra == "geo"
|
|
20
|
+
Requires-Dist: networkx>=3.0; extra == "geo"
|
|
21
|
+
Provides-Extra: fast
|
|
22
|
+
Requires-Dist: numba>=0.58; extra == "fast"
|
|
23
|
+
Provides-Extra: intl
|
|
24
|
+
Requires-Dist: babel>=2.14; extra == "intl"
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
27
|
+
Requires-Dist: pytest-cov>=4.1; extra == "dev"
|
|
28
|
+
Requires-Dist: scipy>=1.10; extra == "dev"
|
|
29
|
+
Requires-Dist: networkx>=3.0; extra == "dev"
|
|
30
|
+
Requires-Dist: babel>=2.14; extra == "dev"
|
|
31
|
+
Requires-Dist: plotly>=5.18; extra == "dev"
|
|
32
|
+
Provides-Extra: docs
|
|
33
|
+
Requires-Dist: mkdocs>=1.6; extra == "docs"
|
|
34
|
+
Requires-Dist: mkdocs-material>=9.5; extra == "docs"
|
|
35
|
+
Requires-Dist: mkdocstrings[python]>=0.25; extra == "docs"
|
|
36
|
+
Requires-Dist: mkdocs-include-markdown-plugin>=6.2; extra == "docs"
|
|
37
|
+
Requires-Dist: mkdocs-gen-files>=0.5; extra == "docs"
|
|
38
|
+
Requires-Dist: plotly>=5.18; extra == "docs"
|
|
39
|
+
Requires-Dist: networkx>=3.0; extra == "docs"
|
|
40
|
+
Requires-Dist: scipy>=1.10; extra == "docs"
|
|
41
|
+
Requires-Dist: babel>=2.14; extra == "docs"
|
|
42
|
+
Provides-Extra: all
|
|
43
|
+
Requires-Dist: scipy>=1.10; extra == "all"
|
|
44
|
+
Requires-Dist: matplotlib>=3.7; extra == "all"
|
|
45
|
+
Requires-Dist: plotly>=5.18; extra == "all"
|
|
46
|
+
Requires-Dist: networkx>=3.0; extra == "all"
|
|
47
|
+
Requires-Dist: numba>=0.58; extra == "all"
|
|
48
|
+
Requires-Dist: babel>=2.14; extra == "all"
|
|
49
|
+
|
|
50
|
+
# SimWeave — a hybrid discrete/continuous simulation engine
|
|
51
|
+
[](https://github.com/Notabot123/simweave/actions/workflows/ci.yml)
|
|
52
|
+
|
|
53
|
+
`simweave` (PyPI: [`simweave`](https://pypi.org/project/simweave/)) is a
|
|
54
|
+
lightweight Python simulation library built around an **atomic-clock
|
|
55
|
+
core** with an **optional heap-based event queue** layered on top. It is
|
|
56
|
+
designed for Monte Carlo studies where reproducibility and vectorised
|
|
57
|
+
aggregation across replicates matter as much as per-event precision.
|
|
58
|
+
|
|
59
|
+
Sister project: [EdgeWeave](https://github.com/) — desktop frontend that
|
|
60
|
+
generates and runs SimWeave scenarios.
|
|
61
|
+
|
|
62
|
+
## Design philosophy
|
|
63
|
+
|
|
64
|
+
### 1. Atomic clock, with an event queue when you need it
|
|
65
|
+
|
|
66
|
+
The heart of the engine is `simweave.core.environment.SimEnvironment`. It
|
|
67
|
+
owns a `Clock` (fixed `dt`), an `EventQueue` (heapq) for sparse future
|
|
68
|
+
callbacks, and a list of `Process` objects ticked every step.
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
for t in clock:
|
|
72
|
+
event_queue.fire_due(t, env) # scheduler-driven work
|
|
73
|
+
for proc in processes:
|
|
74
|
+
proc.tick(dt, env) # atomic-clock-driven work
|
|
75
|
+
clock.advance(dt)
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Fixed-step ticking gives Monte Carlo a shared time grid so `N` replicates
|
|
79
|
+
aggregate cleanly along a single axis. For scenarios where nothing
|
|
80
|
+
happens for long stretches — a factory idle overnight, an agent waiting
|
|
81
|
+
for a part — the environment supports `skip_idle_gaps=True` which
|
|
82
|
+
fast-forwards to the next scheduled event when every process reports
|
|
83
|
+
`has_work(env) == False`. That gives DEVS-like efficiency when demand is
|
|
84
|
+
sparse without losing the atomic time grid when it's not.
|
|
85
|
+
|
|
86
|
+
### 2. Minimal dependencies
|
|
87
|
+
|
|
88
|
+
Only `numpy` is a hard dependency. Everything else is optional:
|
|
89
|
+
|
|
90
|
+
| Extra | Used for | Install |
|
|
91
|
+
|--------------------|----------------------------------------------------------|--------------------------------------|
|
|
92
|
+
| `simweave[optim]` | scipy — DE optimiser, Poisson CDF | `pip install simweave[optim]` |
|
|
93
|
+
| `simweave[graph]` | networkx — interop with external graphs | `pip install simweave[graph]` |
|
|
94
|
+
| `simweave[geo]` | osmnx — OSM map ingestion | `pip install simweave[geo]` |
|
|
95
|
+
| `simweave[plot]` | matplotlib — bring-your-own static plotting | `pip install simweave[plot]` |
|
|
96
|
+
| `simweave[viz]` | plotly — first-class viz module (`simweave.viz`) | `pip install simweave[viz]` |
|
|
97
|
+
| `simweave[intl]` | babel — locale-aware money formatting | `pip install simweave[intl]` |
|
|
98
|
+
| `simweave[fast]` | numba — opt-in JIT for MC inner loops | `pip install simweave[fast]` |
|
|
99
|
+
| `simweave[dev]` | pytest / mypy / plus the optional libs needed for tests | `pip install simweave[dev]` |
|
|
100
|
+
| `simweave[all]` | everything above | `pip install simweave[all]` |
|
|
101
|
+
|
|
102
|
+
`numpy` stays in core because vectorised inventory / Monte Carlo maths
|
|
103
|
+
benefits dramatically from it. Queues still use `collections.deque` for
|
|
104
|
+
O(1) push/pop at both ends.
|
|
105
|
+
|
|
106
|
+
### 3. Modular, but not split into separate libraries
|
|
107
|
+
|
|
108
|
+
The submodules compose through the shared `Entity` base class:
|
|
109
|
+
|
|
110
|
+
```
|
|
111
|
+
simweave/
|
|
112
|
+
core/ Clock, EventQueue, Entity, SimEnvironment
|
|
113
|
+
units/ SI exponent-tagged units (preserved from the original)
|
|
114
|
+
discrete/ Queue, PriorityQueue, Service, ArrivalGenerator, Resource, ResourcePool
|
|
115
|
+
continuous/ DynamicSystem, RK4/Euler, ContinuousProcess (hybrid)
|
|
116
|
+
spatial/ Graph + A*-friendly adj_view adapter, grid_graph helper
|
|
117
|
+
agents/ Compass, routing.a_star, Agent (Entity subclass)
|
|
118
|
+
supplychain/ InventoryItems, Warehouse, steady-state optimisation
|
|
119
|
+
mc/ run_monte_carlo, run_batched_mc
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
A hybrid sim that moves a pallet (Agent) through a service line (Service
|
|
123
|
+
chain) while a mass-spring-damper physics model logs vibration under
|
|
124
|
+
load is completely natural in one package; forcing the user to import
|
|
125
|
+
three separate libraries to do it would be the wrong trade.
|
|
126
|
+
|
|
127
|
+
## Installation
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
git clone https://github.com/Notabot123/simweave
|
|
131
|
+
cd simweave
|
|
132
|
+
python -m venv .venv && source .venv/bin/activate # or .venv\Scripts\activate on Windows
|
|
133
|
+
pip install -e .[dev] # editable install with test deps
|
|
134
|
+
pytest # should show green
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Worked examples
|
|
138
|
+
|
|
139
|
+
Sixteen runnable scripts live under [`demos/`](demos/):
|
|
140
|
+
|
|
141
|
+
**Discrete-event / agents / Monte Carlo**
|
|
142
|
+
1. `01_simple_queue.py` — M/M/1 queue, Little's law diagnostics
|
|
143
|
+
2. `02_chained_services.py` — three-stage production line with blocking
|
|
144
|
+
3. `03_resource_pool.py` — bounded concurrency via a physician pool
|
|
145
|
+
4. `04_supply_chain_basic.py` — two-echelon SKU inventory with daily demand
|
|
146
|
+
5. `05_supply_chain_optimise.py` — Poisson + DE reorder-point optimisation
|
|
147
|
+
6. `06_agent_astar.py` — two agents A*-routing on a grid
|
|
148
|
+
7. `07_monte_carlo.py` — serial vs threads vs processes vs batched numpy
|
|
149
|
+
8. `08_hybrid_continuous_discrete.py` — queue coupled to an MSD
|
|
150
|
+
|
|
151
|
+
**Continuous dynamical systems** (added for teaching use)
|
|
152
|
+
|
|
153
|
+
9. `09_mass_spring_damper.py` — under-, critical-, over-damped responses
|
|
154
|
+
10. `10_quarter_car.py` — 2-DOF suspension over a speed bump, three damper setups
|
|
155
|
+
11. `11_series_rlc.py` — RLC step and resonant drive, reports ω₀, ζ, Q
|
|
156
|
+
12. `12_thermal_system.py` — single-body RC thermal + CPU/heatsink two-mass model
|
|
157
|
+
|
|
158
|
+
**Currency, visualisation, units, optimisation**
|
|
159
|
+
|
|
160
|
+
13. `13_money_cashflow.py` — `Money`, FX conversion, locale-aware formatting
|
|
161
|
+
14. `14_viz_tour.py` — every `simweave.viz` plot helper end-to-end, with HTML index
|
|
162
|
+
15. `15_units_dimensional.py` — SI-units algebra (`Distance / TimeUnit → Velocity`)
|
|
163
|
+
16. `16_inventory_optimisation.py` — recover demand rate from a sim, then optimise reorder points
|
|
164
|
+
|
|
165
|
+
Run any of them directly, e.g. `python demos/01_simple_queue.py` from
|
|
166
|
+
the repo root. The two-digit prefix is just an ordering hint; the
|
|
167
|
+
scripts have no dependency on each other. A small `demos/_bootstrap.py`
|
|
168
|
+
shim adds `src/` to `sys.path` if the package isn't installed; with
|
|
169
|
+
`pip install -e .` in place, the shim becomes a no-op.
|
|
170
|
+
|
|
171
|
+
## Monte Carlo performance: picking the right strategy
|
|
172
|
+
|
|
173
|
+
Monte Carlo scaling on a modern laptop looks like this, ordered by
|
|
174
|
+
expected speedup on compute-bound simulations:
|
|
175
|
+
|
|
176
|
+
| Strategy | When to reach for it | Typical speedup vs serial |
|
|
177
|
+
|--------------------------------|---------------------------------------------------------------------|----------------------------|
|
|
178
|
+
| `run_batched_mc` (numpy) | You can express the full population as arrays on a shared time grid | 10–100× on vector ops |
|
|
179
|
+
| `executor="processes"` | Replicates are independent, GIL-bound compute | ~N-cores× |
|
|
180
|
+
| `numba` JIT on hot loops | Handful of inner functions dominate profile | 3–30× on those functions |
|
|
181
|
+
| Cython (or C extension) | Truly maxing out a known-stable hot path | 2–5× over numba |
|
|
182
|
+
| `executor="threads"` | I/O-bound scenarios (DB hits, REST calls between replicates) | N-workers× |
|
|
183
|
+
| Python 3.13 free-threading | As above, but for compute, once libs stabilise | N-cores× |
|
|
184
|
+
|
|
185
|
+
### My recommended ordering
|
|
186
|
+
|
|
187
|
+
1. **Profile first.** `python -m cProfile demo.py` usually reveals that
|
|
188
|
+
90% of time is in one or two functions. Optimise those, not the
|
|
189
|
+
scheduler.
|
|
190
|
+
2. **Vectorise with numpy where possible.** `run_batched_mc` takes a
|
|
191
|
+
`(n_runs, ...)` step function. Any MC where the per-replicate state
|
|
192
|
+
is small and the dynamics are linear-algebraic is a win here. The
|
|
193
|
+
coin-flip toy in `demos/07_monte_carlo.py` runs 10,000 replicates in
|
|
194
|
+
milliseconds this way.
|
|
195
|
+
3. **Then reach for `processes`.** `ProcessPoolExecutor` sidesteps the
|
|
196
|
+
GIL without you writing any parallel code. The pickling overhead is
|
|
197
|
+
negligible when each replicate runs for ≥ a second. This is the best
|
|
198
|
+
default for a "complicated simulation" that can't be vectorised.
|
|
199
|
+
4. **Then numba.** `@njit` on the inner tick loop often adds 3–30× on
|
|
200
|
+
the hot path. Numba plays nicely with numpy arrays and compiles on
|
|
201
|
+
first call. Prefer it to Cython unless you already have a Cython
|
|
202
|
+
toolchain and need C-level interop — Cython's compile-and-link dance
|
|
203
|
+
is overkill for 95% of cases.
|
|
204
|
+
5. **Cython only as a last resort.** If you're building a PyPI wheel
|
|
205
|
+
and every ms counts, Cython can squeeze more out. In practice you
|
|
206
|
+
then have to ship platform-specific wheels, which doubles the CI
|
|
207
|
+
pipeline. Numba's JIT-at-import sidesteps that.
|
|
208
|
+
6. **Threads for IO.** The moment your replicate talks to a database,
|
|
209
|
+
an HTTP endpoint, or the filesystem, `executor="threads"` wins
|
|
210
|
+
because while one thread waits on a syscall another runs. On the
|
|
211
|
+
3.13 free-threading build threads will also help compute; treat it
|
|
212
|
+
as a near-term option rather than a today option.
|
|
213
|
+
|
|
214
|
+
### Seeding and reproducibility
|
|
215
|
+
|
|
216
|
+
Every Monte Carlo run receives a seed. `run_monte_carlo` materialises
|
|
217
|
+
`list(seeds or range(n_runs))` up front and stamps each replicate with
|
|
218
|
+
its own `np.random.Generator`, so results are deterministic per seed.
|
|
219
|
+
That determinism holds even when replicates are farmed across processes
|
|
220
|
+
— every worker sees the same integer seed.
|
|
221
|
+
|
|
222
|
+
## Packaging, CI, and releases
|
|
223
|
+
|
|
224
|
+
Continuous integration runs on every push and PR — see `.github/workflows/ci.yml`.
|
|
225
|
+
It matrixes `pytest --cov=simweave` across Python 3.10–3.13 on ubuntu / macos /
|
|
226
|
+
windows, runs `ruff` and `mypy`, and builds both `sdist` and `wheel` with
|
|
227
|
+
`python -m build`. Artefacts are uploaded on every green build and can be
|
|
228
|
+
downloaded from the Actions UI for local testing.
|
|
229
|
+
|
|
230
|
+
`release.yml` publishes on tag push:
|
|
231
|
+
|
|
232
|
+
- Tags matching a stable semver shape (`v0.1.0`, `v0.2.0`, `v1.0.0`) →
|
|
233
|
+
**PyPI**.
|
|
234
|
+
- Tags with a pre-release suffix (`v0.1.0rc1`, `v0.1.0a2`, `v0.1.0-beta`) →
|
|
235
|
+
**TestPyPI**.
|
|
236
|
+
- Both use PyPA's trusted publishing (OIDC). No API tokens in GitHub
|
|
237
|
+
secrets — configure once per project on pypi.org / test.pypi.org.
|
|
238
|
+
|
|
239
|
+
See [`PACKAGING.md`](PACKAGING.md) for the full release checklist and
|
|
240
|
+
recommended strategy (pure-Python wheels today; numba for hot paths
|
|
241
|
+
before Cython).
|
|
242
|
+
|
|
243
|
+
## Public API reference
|
|
244
|
+
|
|
245
|
+
[`SIMWEAVE_API.md`](SIMWEAVE_API.md) is a drop-in reference suitable for
|
|
246
|
+
copying into a consuming app's repo (e.g. EdgeWeave). It documents the
|
|
247
|
+
top-level imports, the continuous-dynamics protocol for plug-in systems,
|
|
248
|
+
and a code-generation template to follow.
|
|
249
|
+
|
|
250
|
+
## Integration with EdgeWeave
|
|
251
|
+
|
|
252
|
+
[`EdgeWeave.md`](EdgeWeave.md) describes the flow-based low-code app
|
|
253
|
+
that `simweave` is designed to feed. The boundary between the two is
|
|
254
|
+
intentionally thin:
|
|
255
|
+
|
|
256
|
+
- **simweave → EdgeWeave as `@node`s.** Any `simweave` entity with a
|
|
257
|
+
`tick(dt, env)` signature is trivially wrappable as an EdgeWeave node.
|
|
258
|
+
An `ArrivalGenerator` becomes a "Source" node; a `Service` becomes a
|
|
259
|
+
"Process" node; a `Queue` becomes a "Buffer" node. Inputs and outputs
|
|
260
|
+
flow as entity references along drawflow wires.
|
|
261
|
+
- **simweave stays headless.** No GUI, no fastapi dependency. EdgeWeave
|
|
262
|
+
imports `simweave` and constructs the environment; `simweave` never
|
|
263
|
+
imports EdgeWeave. This keeps `simweave` useful as a standalone library
|
|
264
|
+
and as a published pypi package.
|
|
265
|
+
- **Performance path.** If EdgeWeave wants to JIT hot inner loops,
|
|
266
|
+
enable `simweave[fast]` and let numba do the work — the simulation
|
|
267
|
+
graph stays pure Python while the tight numeric kernels compile
|
|
268
|
+
down. Cython only enters the picture if the EdgeWeave team decides to
|
|
269
|
+
ship prebuilt C extensions for the inner loops, which would be a
|
|
270
|
+
follow-on optimisation rather than a day-one requirement.
|
|
271
|
+
- **Serialisation.** Every entity already lives in a dataclass or has
|
|
272
|
+
a short `__init__` signature, so a `to_dict()` / `from_dict()`
|
|
273
|
+
round-trip is a small follow-up when EdgeWeave needs to serialise a
|
|
274
|
+
flow graph.
|
|
275
|
+
|
|
276
|
+
## Project layout
|
|
277
|
+
|
|
278
|
+
```
|
|
279
|
+
sim_engine/
|
|
280
|
+
src/simweave/ # the package (src layout)
|
|
281
|
+
tests/ # pytest suite (83 tests, scipy-dependent ones skip gracefully)
|
|
282
|
+
demos/ # worked examples (see above)
|
|
283
|
+
archive/ # legacy code kept for reference, safe to delete later
|
|
284
|
+
pyproject.toml
|
|
285
|
+
requirements.txt
|
|
286
|
+
requirements-dev.txt
|
|
287
|
+
EdgeWeave.md # integration notes for the flow-based front-end
|
|
288
|
+
README.md
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
## Next steps on the roadmap
|
|
292
|
+
|
|
293
|
+
- **True sim-based optimisation.** `cost_optimise_stock_sim` already
|
|
294
|
+
wraps a user callback; a future step is an adaptive surrogate model
|
|
295
|
+
(kriging / BO) so each evaluation doesn't need a full MC sweep.
|
|
296
|
+
- **DEVS-style segment.** When `skip_idle_gaps=True` covers most of the
|
|
297
|
+
gains of a pure event-queue system, a thin DEVS-style adapter on top
|
|
298
|
+
of the event queue would give users who prefer generator-style code
|
|
299
|
+
(à la SimPy) an entry point without forking the kernel.
|
|
300
|
+
- **Graph-agnostic spatial layer.** `adj_view` already handles simweave
|
|
301
|
+
Graph, dict-of-dict, and networkx; next is an osmnx adapter so
|
|
302
|
+
`simweave[geo]` lets agents route on real road networks without
|
|
303
|
+
baking osmnx into the core.
|
|
304
|
+
- **Numba hot paths.** The A* inner loop and the warehouse vecto
|
simweave-0.4.0/README.md
ADDED
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
# SimWeave — a hybrid discrete/continuous simulation engine
|
|
2
|
+
[](https://github.com/Notabot123/simweave/actions/workflows/ci.yml)
|
|
3
|
+
|
|
4
|
+
`simweave` (PyPI: [`simweave`](https://pypi.org/project/simweave/)) is a
|
|
5
|
+
lightweight Python simulation library built around an **atomic-clock
|
|
6
|
+
core** with an **optional heap-based event queue** layered on top. It is
|
|
7
|
+
designed for Monte Carlo studies where reproducibility and vectorised
|
|
8
|
+
aggregation across replicates matter as much as per-event precision.
|
|
9
|
+
|
|
10
|
+
Sister project: [EdgeWeave](https://github.com/) — desktop frontend that
|
|
11
|
+
generates and runs SimWeave scenarios.
|
|
12
|
+
|
|
13
|
+
## Design philosophy
|
|
14
|
+
|
|
15
|
+
### 1. Atomic clock, with an event queue when you need it
|
|
16
|
+
|
|
17
|
+
The heart of the engine is `simweave.core.environment.SimEnvironment`. It
|
|
18
|
+
owns a `Clock` (fixed `dt`), an `EventQueue` (heapq) for sparse future
|
|
19
|
+
callbacks, and a list of `Process` objects ticked every step.
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
for t in clock:
|
|
23
|
+
event_queue.fire_due(t, env) # scheduler-driven work
|
|
24
|
+
for proc in processes:
|
|
25
|
+
proc.tick(dt, env) # atomic-clock-driven work
|
|
26
|
+
clock.advance(dt)
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Fixed-step ticking gives Monte Carlo a shared time grid so `N` replicates
|
|
30
|
+
aggregate cleanly along a single axis. For scenarios where nothing
|
|
31
|
+
happens for long stretches — a factory idle overnight, an agent waiting
|
|
32
|
+
for a part — the environment supports `skip_idle_gaps=True` which
|
|
33
|
+
fast-forwards to the next scheduled event when every process reports
|
|
34
|
+
`has_work(env) == False`. That gives DEVS-like efficiency when demand is
|
|
35
|
+
sparse without losing the atomic time grid when it's not.
|
|
36
|
+
|
|
37
|
+
### 2. Minimal dependencies
|
|
38
|
+
|
|
39
|
+
Only `numpy` is a hard dependency. Everything else is optional:
|
|
40
|
+
|
|
41
|
+
| Extra | Used for | Install |
|
|
42
|
+
|--------------------|----------------------------------------------------------|--------------------------------------|
|
|
43
|
+
| `simweave[optim]` | scipy — DE optimiser, Poisson CDF | `pip install simweave[optim]` |
|
|
44
|
+
| `simweave[graph]` | networkx — interop with external graphs | `pip install simweave[graph]` |
|
|
45
|
+
| `simweave[geo]` | osmnx — OSM map ingestion | `pip install simweave[geo]` |
|
|
46
|
+
| `simweave[plot]` | matplotlib — bring-your-own static plotting | `pip install simweave[plot]` |
|
|
47
|
+
| `simweave[viz]` | plotly — first-class viz module (`simweave.viz`) | `pip install simweave[viz]` |
|
|
48
|
+
| `simweave[intl]` | babel — locale-aware money formatting | `pip install simweave[intl]` |
|
|
49
|
+
| `simweave[fast]` | numba — opt-in JIT for MC inner loops | `pip install simweave[fast]` |
|
|
50
|
+
| `simweave[dev]` | pytest / mypy / plus the optional libs needed for tests | `pip install simweave[dev]` |
|
|
51
|
+
| `simweave[all]` | everything above | `pip install simweave[all]` |
|
|
52
|
+
|
|
53
|
+
`numpy` stays in core because vectorised inventory / Monte Carlo maths
|
|
54
|
+
benefits dramatically from it. Queues still use `collections.deque` for
|
|
55
|
+
O(1) push/pop at both ends.
|
|
56
|
+
|
|
57
|
+
### 3. Modular, but not split into separate libraries
|
|
58
|
+
|
|
59
|
+
The submodules compose through the shared `Entity` base class:
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
simweave/
|
|
63
|
+
core/ Clock, EventQueue, Entity, SimEnvironment
|
|
64
|
+
units/ SI exponent-tagged units (preserved from the original)
|
|
65
|
+
discrete/ Queue, PriorityQueue, Service, ArrivalGenerator, Resource, ResourcePool
|
|
66
|
+
continuous/ DynamicSystem, RK4/Euler, ContinuousProcess (hybrid)
|
|
67
|
+
spatial/ Graph + A*-friendly adj_view adapter, grid_graph helper
|
|
68
|
+
agents/ Compass, routing.a_star, Agent (Entity subclass)
|
|
69
|
+
supplychain/ InventoryItems, Warehouse, steady-state optimisation
|
|
70
|
+
mc/ run_monte_carlo, run_batched_mc
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
A hybrid sim that moves a pallet (Agent) through a service line (Service
|
|
74
|
+
chain) while a mass-spring-damper physics model logs vibration under
|
|
75
|
+
load is completely natural in one package; forcing the user to import
|
|
76
|
+
three separate libraries to do it would be the wrong trade.
|
|
77
|
+
|
|
78
|
+
## Installation
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
git clone https://github.com/Notabot123/simweave
|
|
82
|
+
cd simweave
|
|
83
|
+
python -m venv .venv && source .venv/bin/activate # or .venv\Scripts\activate on Windows
|
|
84
|
+
pip install -e .[dev] # editable install with test deps
|
|
85
|
+
pytest # should show green
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Worked examples
|
|
89
|
+
|
|
90
|
+
Sixteen runnable scripts live under [`demos/`](demos/):
|
|
91
|
+
|
|
92
|
+
**Discrete-event / agents / Monte Carlo**
|
|
93
|
+
1. `01_simple_queue.py` — M/M/1 queue, Little's law diagnostics
|
|
94
|
+
2. `02_chained_services.py` — three-stage production line with blocking
|
|
95
|
+
3. `03_resource_pool.py` — bounded concurrency via a physician pool
|
|
96
|
+
4. `04_supply_chain_basic.py` — two-echelon SKU inventory with daily demand
|
|
97
|
+
5. `05_supply_chain_optimise.py` — Poisson + DE reorder-point optimisation
|
|
98
|
+
6. `06_agent_astar.py` — two agents A*-routing on a grid
|
|
99
|
+
7. `07_monte_carlo.py` — serial vs threads vs processes vs batched numpy
|
|
100
|
+
8. `08_hybrid_continuous_discrete.py` — queue coupled to an MSD
|
|
101
|
+
|
|
102
|
+
**Continuous dynamical systems** (added for teaching use)
|
|
103
|
+
|
|
104
|
+
9. `09_mass_spring_damper.py` — under-, critical-, over-damped responses
|
|
105
|
+
10. `10_quarter_car.py` — 2-DOF suspension over a speed bump, three damper setups
|
|
106
|
+
11. `11_series_rlc.py` — RLC step and resonant drive, reports ω₀, ζ, Q
|
|
107
|
+
12. `12_thermal_system.py` — single-body RC thermal + CPU/heatsink two-mass model
|
|
108
|
+
|
|
109
|
+
**Currency, visualisation, units, optimisation**
|
|
110
|
+
|
|
111
|
+
13. `13_money_cashflow.py` — `Money`, FX conversion, locale-aware formatting
|
|
112
|
+
14. `14_viz_tour.py` — every `simweave.viz` plot helper end-to-end, with HTML index
|
|
113
|
+
15. `15_units_dimensional.py` — SI-units algebra (`Distance / TimeUnit → Velocity`)
|
|
114
|
+
16. `16_inventory_optimisation.py` — recover demand rate from a sim, then optimise reorder points
|
|
115
|
+
|
|
116
|
+
Run any of them directly, e.g. `python demos/01_simple_queue.py` from
|
|
117
|
+
the repo root. The two-digit prefix is just an ordering hint; the
|
|
118
|
+
scripts have no dependency on each other. A small `demos/_bootstrap.py`
|
|
119
|
+
shim adds `src/` to `sys.path` if the package isn't installed; with
|
|
120
|
+
`pip install -e .` in place, the shim becomes a no-op.
|
|
121
|
+
|
|
122
|
+
## Monte Carlo performance: picking the right strategy
|
|
123
|
+
|
|
124
|
+
Monte Carlo scaling on a modern laptop looks like this, ordered by
|
|
125
|
+
expected speedup on compute-bound simulations:
|
|
126
|
+
|
|
127
|
+
| Strategy | When to reach for it | Typical speedup vs serial |
|
|
128
|
+
|--------------------------------|---------------------------------------------------------------------|----------------------------|
|
|
129
|
+
| `run_batched_mc` (numpy) | You can express the full population as arrays on a shared time grid | 10–100× on vector ops |
|
|
130
|
+
| `executor="processes"` | Replicates are independent, GIL-bound compute | ~N-cores× |
|
|
131
|
+
| `numba` JIT on hot loops | Handful of inner functions dominate profile | 3–30× on those functions |
|
|
132
|
+
| Cython (or C extension) | Truly maxing out a known-stable hot path | 2–5× over numba |
|
|
133
|
+
| `executor="threads"` | I/O-bound scenarios (DB hits, REST calls between replicates) | N-workers× |
|
|
134
|
+
| Python 3.13 free-threading | As above, but for compute, once libs stabilise | N-cores× |
|
|
135
|
+
|
|
136
|
+
### My recommended ordering
|
|
137
|
+
|
|
138
|
+
1. **Profile first.** `python -m cProfile demo.py` usually reveals that
|
|
139
|
+
90% of time is in one or two functions. Optimise those, not the
|
|
140
|
+
scheduler.
|
|
141
|
+
2. **Vectorise with numpy where possible.** `run_batched_mc` takes a
|
|
142
|
+
`(n_runs, ...)` step function. Any MC where the per-replicate state
|
|
143
|
+
is small and the dynamics are linear-algebraic is a win here. The
|
|
144
|
+
coin-flip toy in `demos/07_monte_carlo.py` runs 10,000 replicates in
|
|
145
|
+
milliseconds this way.
|
|
146
|
+
3. **Then reach for `processes`.** `ProcessPoolExecutor` sidesteps the
|
|
147
|
+
GIL without you writing any parallel code. The pickling overhead is
|
|
148
|
+
negligible when each replicate runs for ≥ a second. This is the best
|
|
149
|
+
default for a "complicated simulation" that can't be vectorised.
|
|
150
|
+
4. **Then numba.** `@njit` on the inner tick loop often adds 3–30× on
|
|
151
|
+
the hot path. Numba plays nicely with numpy arrays and compiles on
|
|
152
|
+
first call. Prefer it to Cython unless you already have a Cython
|
|
153
|
+
toolchain and need C-level interop — Cython's compile-and-link dance
|
|
154
|
+
is overkill for 95% of cases.
|
|
155
|
+
5. **Cython only as a last resort.** If you're building a PyPI wheel
|
|
156
|
+
and every ms counts, Cython can squeeze more out. In practice you
|
|
157
|
+
then have to ship platform-specific wheels, which doubles the CI
|
|
158
|
+
pipeline. Numba's JIT-at-import sidesteps that.
|
|
159
|
+
6. **Threads for IO.** The moment your replicate talks to a database,
|
|
160
|
+
an HTTP endpoint, or the filesystem, `executor="threads"` wins
|
|
161
|
+
because while one thread waits on a syscall another runs. On the
|
|
162
|
+
3.13 free-threading build threads will also help compute; treat it
|
|
163
|
+
as a near-term option rather than a today option.
|
|
164
|
+
|
|
165
|
+
### Seeding and reproducibility
|
|
166
|
+
|
|
167
|
+
Every Monte Carlo run receives a seed. `run_monte_carlo` materialises
|
|
168
|
+
`list(seeds or range(n_runs))` up front and stamps each replicate with
|
|
169
|
+
its own `np.random.Generator`, so results are deterministic per seed.
|
|
170
|
+
That determinism holds even when replicates are farmed across processes
|
|
171
|
+
— every worker sees the same integer seed.
|
|
172
|
+
|
|
173
|
+
## Packaging, CI, and releases
|
|
174
|
+
|
|
175
|
+
Continuous integration runs on every push and PR — see `.github/workflows/ci.yml`.
|
|
176
|
+
It matrixes `pytest --cov=simweave` across Python 3.10–3.13 on ubuntu / macos /
|
|
177
|
+
windows, runs `ruff` and `mypy`, and builds both `sdist` and `wheel` with
|
|
178
|
+
`python -m build`. Artefacts are uploaded on every green build and can be
|
|
179
|
+
downloaded from the Actions UI for local testing.
|
|
180
|
+
|
|
181
|
+
`release.yml` publishes on tag push:
|
|
182
|
+
|
|
183
|
+
- Tags matching a stable semver shape (`v0.1.0`, `v0.2.0`, `v1.0.0`) →
|
|
184
|
+
**PyPI**.
|
|
185
|
+
- Tags with a pre-release suffix (`v0.1.0rc1`, `v0.1.0a2`, `v0.1.0-beta`) →
|
|
186
|
+
**TestPyPI**.
|
|
187
|
+
- Both use PyPA's trusted publishing (OIDC). No API tokens in GitHub
|
|
188
|
+
secrets — configure once per project on pypi.org / test.pypi.org.
|
|
189
|
+
|
|
190
|
+
See [`PACKAGING.md`](PACKAGING.md) for the full release checklist and
|
|
191
|
+
recommended strategy (pure-Python wheels today; numba for hot paths
|
|
192
|
+
before Cython).
|
|
193
|
+
|
|
194
|
+
## Public API reference
|
|
195
|
+
|
|
196
|
+
[`SIMWEAVE_API.md`](SIMWEAVE_API.md) is a drop-in reference suitable for
|
|
197
|
+
copying into a consuming app's repo (e.g. EdgeWeave). It documents the
|
|
198
|
+
top-level imports, the continuous-dynamics protocol for plug-in systems,
|
|
199
|
+
and a code-generation template to follow.
|
|
200
|
+
|
|
201
|
+
## Integration with EdgeWeave
|
|
202
|
+
|
|
203
|
+
[`EdgeWeave.md`](EdgeWeave.md) describes the flow-based low-code app
|
|
204
|
+
that `simweave` is designed to feed. The boundary between the two is
|
|
205
|
+
intentionally thin:
|
|
206
|
+
|
|
207
|
+
- **simweave → EdgeWeave as `@node`s.** Any `simweave` entity with a
|
|
208
|
+
`tick(dt, env)` signature is trivially wrappable as an EdgeWeave node.
|
|
209
|
+
An `ArrivalGenerator` becomes a "Source" node; a `Service` becomes a
|
|
210
|
+
"Process" node; a `Queue` becomes a "Buffer" node. Inputs and outputs
|
|
211
|
+
flow as entity references along drawflow wires.
|
|
212
|
+
- **simweave stays headless.** No GUI, no fastapi dependency. EdgeWeave
|
|
213
|
+
imports `simweave` and constructs the environment; `simweave` never
|
|
214
|
+
imports EdgeWeave. This keeps `simweave` useful as a standalone library
|
|
215
|
+
and as a published pypi package.
|
|
216
|
+
- **Performance path.** If EdgeWeave wants to JIT hot inner loops,
|
|
217
|
+
enable `simweave[fast]` and let numba do the work — the simulation
|
|
218
|
+
graph stays pure Python while the tight numeric kernels compile
|
|
219
|
+
down. Cython only enters the picture if the EdgeWeave team decides to
|
|
220
|
+
ship prebuilt C extensions for the inner loops, which would be a
|
|
221
|
+
follow-on optimisation rather than a day-one requirement.
|
|
222
|
+
- **Serialisation.** Every entity already lives in a dataclass or has
|
|
223
|
+
a short `__init__` signature, so a `to_dict()` / `from_dict()`
|
|
224
|
+
round-trip is a small follow-up when EdgeWeave needs to serialise a
|
|
225
|
+
flow graph.
|
|
226
|
+
|
|
227
|
+
## Project layout
|
|
228
|
+
|
|
229
|
+
```
|
|
230
|
+
sim_engine/
|
|
231
|
+
src/simweave/ # the package (src layout)
|
|
232
|
+
tests/ # pytest suite (83 tests, scipy-dependent ones skip gracefully)
|
|
233
|
+
demos/ # worked examples (see above)
|
|
234
|
+
archive/ # legacy code kept for reference, safe to delete later
|
|
235
|
+
pyproject.toml
|
|
236
|
+
requirements.txt
|
|
237
|
+
requirements-dev.txt
|
|
238
|
+
EdgeWeave.md # integration notes for the flow-based front-end
|
|
239
|
+
README.md
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
## Next steps on the roadmap
|
|
243
|
+
|
|
244
|
+
- **True sim-based optimisation.** `cost_optimise_stock_sim` already
|
|
245
|
+
wraps a user callback; a future step is an adaptive surrogate model
|
|
246
|
+
(kriging / BO) so each evaluation doesn't need a full MC sweep.
|
|
247
|
+
- **DEVS-style segment.** When `skip_idle_gaps=True` covers most of the
|
|
248
|
+
gains of a pure event-queue system, a thin DEVS-style adapter on top
|
|
249
|
+
of the event queue would give users who prefer generator-style code
|
|
250
|
+
(à la SimPy) an entry point without forking the kernel.
|
|
251
|
+
- **Graph-agnostic spatial layer.** `adj_view` already handles simweave
|
|
252
|
+
Graph, dict-of-dict, and networkx; next is an osmnx adapter so
|
|
253
|
+
`simweave[geo]` lets agents route on real road networks without
|
|
254
|
+
baking osmnx into the core.
|
|
255
|
+
- **Numba hot paths.** The A* inner loop and the warehouse vecto
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "simweave"
|
|
7
|
+
version = "0.4.0"
|
|
8
|
+
description = "SimWeave: a hybrid discrete/continuous simulation engine with currency, units, agents, supply chains, and Monte Carlo."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [{ name = "Stuart" }]
|
|
13
|
+
dependencies = [
|
|
14
|
+
"numpy>=1.23",
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
[project.optional-dependencies]
|
|
18
|
+
optim = ["scipy>=1.10"]
|
|
19
|
+
plot = ["matplotlib>=3.7"]
|
|
20
|
+
viz = ["plotly>=5.18"]
|
|
21
|
+
graph = ["networkx>=3.0"]
|
|
22
|
+
geo = ["osmnx>=1.8", "networkx>=3.0"]
|
|
23
|
+
fast = ["numba>=0.58"]
|
|
24
|
+
intl = ["babel>=2.14"]
|
|
25
|
+
dev = [
|
|
26
|
+
"pytest>=8.0",
|
|
27
|
+
"pytest-cov>=4.1",
|
|
28
|
+
"scipy>=1.10",
|
|
29
|
+
"networkx>=3.0",
|
|
30
|
+
"babel>=2.14",
|
|
31
|
+
"plotly>=5.18",
|
|
32
|
+
]
|
|
33
|
+
docs = [
|
|
34
|
+
"mkdocs>=1.6",
|
|
35
|
+
"mkdocs-material>=9.5",
|
|
36
|
+
"mkdocstrings[python]>=0.25",
|
|
37
|
+
"mkdocs-include-markdown-plugin>=6.2",
|
|
38
|
+
"mkdocs-gen-files>=0.5",
|
|
39
|
+
# Match the runtime deps mkdocstrings needs to actually import simweave
|
|
40
|
+
# so the auto-generated API pages render the full surface.
|
|
41
|
+
"plotly>=5.18",
|
|
42
|
+
"networkx>=3.0",
|
|
43
|
+
"scipy>=1.10",
|
|
44
|
+
"babel>=2.14",
|
|
45
|
+
]
|
|
46
|
+
all = [
|
|
47
|
+
"scipy>=1.10",
|
|
48
|
+
"matplotlib>=3.7",
|
|
49
|
+
"plotly>=5.18",
|
|
50
|
+
"networkx>=3.0",
|
|
51
|
+
"numba>=0.58",
|
|
52
|
+
"babel>=2.14",
|
|
53
|
+
]
|
|
54
|
+
|
|
55
|
+
[tool.setuptools]
|
|
56
|
+
# Keep the wheel lean: only Python sources under src/simweave go in.
|
|
57
|
+
# README/LICENSE/pyproject are included automatically as distribution metadata.
|
|
58
|
+
include-package-data = false
|
|
59
|
+
|
|
60
|
+
[tool.setuptools.packages.find]
|
|
61
|
+
where = ["src"]
|
|
62
|
+
|
|
63
|
+
[tool.setuptools.package-data]
|
|
64
|
+
# If we ever need to ship data files inside the package, list them here
|
|
65
|
+
# explicitly. Leaving empty keeps the wheel to *.py only.
|
|
66
|
+
simweave = []
|
|
67
|
+
|
|
68
|
+
[tool.pytest.ini_options]
|
|
69
|
+
testpaths = ["tests"]
|
|
70
|
+
pythonpath = ["src"]
|
|
71
|
+
addopts = "-q"
|