SCPN Control — Neuro-symbolic Stochastic Petri Net controller for plasma control
Project description
scpn-control is a standalone neuro-symbolic control engine that compiles Stochastic Petri Nets into spiking neural network controllers with formal verification guarantees. Extracted from scpn-fusion-core — 48 source modules, 50 test files, 701 tests, 5 Rust crates, 13 CI jobs.
11.9 µs P50 control loop — faster than any open-source fusion code, competitive with the DIII-D PCS (4–10 kHz physics loops). With
sc-neurocoreinstalled, the SNN compiler usesVectorizedSCLayer+ Rust backend for 512× real-time spiking neural network execution. See competitive analysis for full benchmarks.
Quick Start
pip install -e "."
scpn-control demo --steps 1000
scpn-control benchmark --n-bench 5000
Documentation and Tutorials
- Documentation site: https://anulum.github.io/scpn-control/
- Local docs index:
docs/index.md - Benchmark guide:
docs/benchmarks.md - Notebook tutorials:
examples/neuro_symbolic_control_demo.ipynbexamples/q10_breakeven_demo.ipynbexamples/snn_compiler_walkthrough.ipynbexamples/paper27_phase_dynamics_demo.ipynb— Knm/UPDE + ζ sin(Ψ−θ)examples/snn_pac_closed_loop_demo.ipynb— SNN-PAC-Kuramoto closed loopexamples/streamlit_ws_client.py— live WebSocket phase sync dashboard
Build docs locally:
python -m pip install mkdocs
mkdocs serve
Execute all notebooks:
python -m pip install -e ".[viz]" jupyter nbconvert
jupyter nbconvert --to notebook --execute --output-dir artifacts/notebook-exec examples/q10_breakeven_demo.ipynb
jupyter nbconvert --to notebook --execute --output-dir artifacts/notebook-exec examples/snn_compiler_walkthrough.ipynb
Optional notebook (requires sc_neurocore available in environment):
jupyter nbconvert --to notebook --execute --output-dir artifacts/notebook-exec examples/neuro_symbolic_control_demo.ipynb
Features
- Petri Net to SNN compilation -- Translates Stochastic Petri Nets into spiking neural network controllers with LIF neurons and bitstream encoding
- Formal verification -- Contract-based pre/post-condition checking on all control observations and actions
- Sub-millisecond latency -- <1ms control loop with optional Rust-accelerated kernels
- Rust acceleration -- PyO3 bindings for SCPN activation, marking update, Boris integration, SNN pools, and MPC
- Multiple controller types -- PID, MPC, H-infinity, SNN, neuro-cybernetic dual R+Z
- Grad-Shafranov solver -- Free-boundary equilibrium solver with L-mode/H-mode profile support
- Digital twin integration -- Real-time telemetry ingest, closed-loop simulation, and flight simulator
- RMSE validation -- CI-gated regression testing against DIII-D and SPARC experimental reference data
- Disruption prediction -- ML-based predictor with SPI mitigation and halo/RE physics
Architecture
src/scpn_control/
+-- scpn/ # Petri net -> SNN compiler
| +-- structure.py # StochasticPetriNet graph builder
| +-- compiler.py # FusionCompiler -> CompiledNet (LIF + bitstream)
| +-- contracts.py # ControlObservation, ControlAction, ControlTargets
| +-- controller.py # NeuroSymbolicController (main entry point)
+-- core/ # Solver + plant model (clean init, no import bombs)
| +-- fusion_kernel.py # Grad-Shafranov equilibrium solver
| +-- integrated_transport_solver.py # Multi-species transport
| +-- scaling_laws.py # IPB98y2 confinement scaling
| +-- eqdsk.py # GEQDSK/EQDSK file I/O
| +-- uncertainty.py # Monte Carlo UQ
+-- control/ # Controllers (optional deps guarded)
| +-- h_infinity_controller.py # H-inf robust control
| +-- fusion_sota_mpc.py # Model Predictive Control
| +-- disruption_predictor.py # ML disruption prediction
| +-- tokamak_digital_twin.py # Digital twin
| +-- tokamak_flight_sim.py # IsoFlux flight simulator
| +-- neuro_cybernetic_controller.py # Dual R+Z SNN
+-- phase/ # Paper 27 Knm/UPDE phase dynamics (NEW)
| +-- kuramoto.py # Kuramoto-Sakaguchi step + order parameter
| +-- knm.py # Paper 27 Knm coupling matrix builder
| +-- upde.py # UPDE multi-layer solver
| +-- lyapunov_guard.py # Sliding-window stability monitor
| +-- realtime_monitor.py # Tick-by-tick UPDE + TrajectoryRecorder
| +-- ws_phase_stream.py # Async WebSocket live stream server
+-- cli.py # Click CLI
scpn-control-rs/ # Rust workspace (5 crates)
+-- control-types/ # PlasmaState, EquilibriumConfig, ControlAction
+-- control-math/ # LIF neuron, Boris pusher, Kuramoto, upde_tick
+-- control-core/ # GS solver, transport, confinement scaling
+-- control-control/ # PID, MPC, H-inf, SNN controller
+-- control-python/ # PyO3 bindings (PyRealtimeMonitor, PySnnPool, ...)
tests/ # 701 tests (50 files)
+-- mock_diiid.py # Synthetic DIII-D shot generator (14-field NPZ)
+-- test_e2e_phase_diiid.py # E2E: shot-driven monitor + HDF5/NPZ export
+-- test_phase_kuramoto.py # 50 Kuramoto/UPDE/Guard/Monitor tests
+-- test_rust_realtime_parity.py # Rust PyRealtimeMonitor parity
+-- ... # 44 more test files
Paper 27 Phase Dynamics (Knm/UPDE Engine)
Implements the generalized Kuramoto-Sakaguchi mean-field model with exogenous
global field driver ζ sin(Ψ − θ), per arXiv:2004.06344 and SCPN Paper 27.
Modules: src/scpn_control/phase/ (7 files)
| Module | Purpose |
|---|---|
kuramoto.py |
Kuramoto-Sakaguchi step, order parameter R·e^{iΨ}, Lyapunov V/λ |
knm.py |
Paper 27 16×16 coupling matrix (exponential decay + calibration anchors) |
upde.py |
UPDE multi-layer solver with PAC gating |
lyapunov_guard.py |
Sliding-window stability monitor (mirrors DIRECTOR_AI CoherenceScorer) |
realtime_monitor.py |
Tick-by-tick UPDE + TrajectoryRecorder (HDF5/NPZ export) |
ws_phase_stream.py |
Async WebSocket server streaming R/V/λ per tick |
Rust acceleration: upde_tick() in control-math + PyRealtimeMonitor PyO3 binding.
Live phase sync convergence (GIF fallback):
500 ticks, 16 layers × 50 oscillators, ζ=0.5. R converges to 0.92, V→0, λ settles to −0.47 (stable). Generated by
tools/generate_phase_video.py.
WebSocket live stream:
# Terminal 1: start server (CLI)
scpn-control live --port 8765 --zeta 0.5
# Terminal 2: Streamlit WS client (live R/V/λ plots, guard status, control)
pip install -e ".[dashboard,ws]"
streamlit run examples/streamlit_ws_client.py
# Or embedded mode (server + client in one process)
streamlit run examples/streamlit_ws_client.py -- --embedded
E2E test with mock DIII-D shot data:
pytest tests/test_e2e_phase_diiid.py -v
Dependencies
| Required | Optional |
|---|---|
| numpy >= 1.24 | matplotlib (pip install -e ".[viz]") |
| scipy >= 1.10 | streamlit (pip install -e ".[dashboard]") |
| click >= 8.0 | torch (pip install -e ".[ml]") |
| sc-neurocore >= 3.8.0 | nengo (pip install -e ".[nengo]") |
h5py (pip install -e ".[hdf5]") |
|
websockets (pip install -e ".[ws]") |
CLI
scpn-control demo --scenario combined --steps 1000 # Closed-loop control demo
scpn-control benchmark --n-bench 5000 # PID vs SNN timing benchmark
scpn-control validate # RMSE validation dashboard
scpn-control live --port 8765 --zeta 0.5 # Real-time WS phase sync server
scpn-control hil-test --shots-dir ... # HIL test campaign
Benchmarks
Python micro-benchmark:
scpn-control benchmark --n-bench 5000 --json-out
Rust Criterion benchmarks:
cd scpn-control-rs
cargo bench --workspace
Benchmark docs: docs/benchmarks.md
Dashboard
pip install -e ".[dashboard]"
streamlit run dashboard/control_dashboard.py
Six tabs: Trajectory Viewer, RMSE Dashboard, Timing Benchmark, Shot Replay, Phase Sync Monitor (live R/V/λ plots), Benchmark Plots (interactive Vega).
Streamlit Cloud
Live dashboard: scpn-control.streamlit.app
The phase sync dashboard runs on Streamlit Cloud with embedded server mode
(no external WS server needed). Entry point: streamlit_app.py.
To deploy your own instance:
- Fork to your GitHub
- share.streamlit.io > New app > select
streamlit_app.py - Deploy (auto-starts embedded PhaseStreamServer)
Rust Acceleration
cd scpn-control-rs
cargo test --workspace
# Build Python bindings
cd crates/control-python
pip install maturin
maturin develop --release
cd ../../
# Verify
python -c "import importlib.util; from scpn_control.core._rust_compat import _rust_available; print(bool(importlib.util.find_spec('scpn_control_rs') and _rust_available()))"
The Rust backend provides PyO3 bindings for:
PyFusionKernel-- Grad-Shafranov solverPySnnPool/PySnnController-- Spiking neural network poolsPyMpcController-- Model Predictive ControlPyPlasma2D-- Digital twinPyTransportSolver-- Chang-Hinton + Sauter bootstrapPyRealtimeMonitor-- Multi-layer Kuramoto UPDE tick (phase dynamics)- SCPN kernels --
dense_activations,marking_update,sample_firing
Citation
@software{sotek2026scpncontrol,
title = {SCPN Control: Neuro-Symbolic Stochastic Petri Net Controller},
author = {Sotek, Miroslav and Reiprich, Michal},
year = {2026},
url = {https://github.com/anulum/scpn-control},
license = {AGPL-3.0-or-later}
}
Release and PyPI
Local publish script:
# Dry run (build + check, no upload)
python tools/publish.py --dry-run
# Publish to TestPyPI
python tools/publish.py --target testpypi
# Bump version + publish to PyPI
python tools/publish.py --bump minor --target pypi --confirm
CI workflow (tag-triggered trusted publishing):
git tag v0.2.0
git push --tags
# → .github/workflows/publish-pypi.yml runs automatically
Limitations
- Equilibrium solver: Fixed-boundary Grad-Shafranov only. Free-boundary with external coil currents is not implemented. No stellarator geometry.
- Transport: 1.5D flux-surface-averaged. No turbulence micro-instability models (TGLF/QuaLiKiz) — uses Chang-Hinton neoclassical + scaling-law anomalous.
- Validation scope: Benchmarked against analytic Solov'ev solutions and published DIII-D/SPARC equilibria (GEQDSK). No real MDSplus shot data yet.
- Disruption predictor: Synthetic training data only. Not validated on experimental disruption databases.
- Rust acceleration: Optional. Pure-Python fallback is complete but 5-10x slower for GS solve and Kuramoto steps at N > 1000.
- Deployment: Research-grade. Not hardened for real-time PCS integration. No ITER CODAC or EPICS interface.
Authors
- Miroslav Sotek — ANULUM CH & LI — ORCID
- Michal Reiprich — ANULUM CH & LI
License
- Concepts: Copyright 1996-2026
- Code: Copyright 2024-2026
- License: GNU AGPL v3
GNU Affero General Public License v3.0 — see LICENSE.
For commercial licensing inquiries, contact: protoscience@anulum.li
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file scpn_control-0.3.1.tar.gz.
File metadata
- Download URL: scpn_control-0.3.1.tar.gz
- Upload date:
- Size: 293.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
81d1f67e1270c9f8623c78d7a7c3a14fc0c1e037a426c5c61411c30d950c21f8
|
|
| MD5 |
31e0b9b99a8aed46a1fc51395bc6c879
|
|
| BLAKE2b-256 |
84532cec142454051428916b507ac2761683b47fe78df02d699dbec541bfb56e
|
Provenance
The following attestation bundles were made for scpn_control-0.3.1.tar.gz:
Publisher:
publish-pypi.yml on anulum/scpn-control
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
scpn_control-0.3.1.tar.gz -
Subject digest:
81d1f67e1270c9f8623c78d7a7c3a14fc0c1e037a426c5c61411c30d950c21f8 - Sigstore transparency entry: 1003618964
- Sigstore integration time:
-
Permalink:
anulum/scpn-control@dd9c9a2101fde24424654c8045ae4b408385958f -
Branch / Tag:
refs/tags/v0.3.1 - Owner: https://github.com/anulum
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@dd9c9a2101fde24424654c8045ae4b408385958f -
Trigger Event:
push
-
Statement type:
File details
Details for the file scpn_control-0.3.1-py3-none-any.whl.
File metadata
- Download URL: scpn_control-0.3.1-py3-none-any.whl
- Upload date:
- Size: 238.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c1aa6ed7559b53fbcf3e9bc6f3a2b93dc67d8581c040970291b3ccb67da8a9e4
|
|
| MD5 |
0a7f36309bb08f5dd5cfe4136aefb1a0
|
|
| BLAKE2b-256 |
9dc1a5760858d0da2073aa0be314c70527a75f23db14e33ab907bbc49154a5bc
|
Provenance
The following attestation bundles were made for scpn_control-0.3.1-py3-none-any.whl:
Publisher:
publish-pypi.yml on anulum/scpn-control
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
scpn_control-0.3.1-py3-none-any.whl -
Subject digest:
c1aa6ed7559b53fbcf3e9bc6f3a2b93dc67d8581c040970291b3ccb67da8a9e4 - Sigstore transparency entry: 1003618969
- Sigstore integration time:
-
Permalink:
anulum/scpn-control@dd9c9a2101fde24424654c8045ae4b408385958f -
Branch / Tag:
refs/tags/v0.3.1 - Owner: https://github.com/anulum
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@dd9c9a2101fde24424654c8045ae4b408385958f -
Trigger Event:
push
-
Statement type: