{"id":45889943,"url":"https://github.com/anulum/scpn-control","last_synced_at":"2026-05-24T06:00:56.358Z","repository":{"id":339399112,"uuid":"1161708293","full_name":"anulum/scpn-control","owner":"anulum","description":"SCPN Control — Neuro-Symbolic Stochastic Petri Net Controller for Tokamak Plasma Control","archived":false,"fork":false,"pushed_at":"2026-05-18T01:10:38.000Z","size":24573,"stargazers_count":0,"open_issues_count":3,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-18T02:18:49.540Z","etag":null,"topics":["control-systems","digital-twin","formal-verification","fusion","fusion-energy","grad-shafranov","kuramoto","neuro-symbolic","petri-net","plasma-control","plasma-physics","pyo3","python","rust","spiking-neural-network","tokamak"],"latest_commit_sha":null,"homepage":"https://anulum.li/scpn-control/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/anulum.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":"CITATION.cff","codeowners":".github/CODEOWNERS","security":"SECURITY.md","support":"SUPPORT.md","governance":"GOVERNANCE.md","roadmap":"ROADMAP.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":".zenodo.json","notice":"NOTICE.md","maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":"anulum","custom":["https://buy.stripe.com/4gM00kbiMdjAberaYz5J601","https://www.paypal.com/donate?hosted_button_id=4X5F6DNT934HY"]}},"created_at":"2026-02-19T12:28:06.000Z","updated_at":"2026-05-18T00:57:37.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/anulum/scpn-control","commit_stats":null,"previous_names":["anulum/scpn-control"],"tags_count":32,"template":false,"template_full_name":null,"purl":"pkg:github/anulum/scpn-control","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anulum%2Fscpn-control","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anulum%2Fscpn-control/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anulum%2Fscpn-control/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anulum%2Fscpn-control/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/anulum","download_url":"https://codeload.github.com/anulum/scpn-control/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anulum%2Fscpn-control/sbom","scorecard":{"id":1244612,"data":{"date":"2026-03-09T23:39:33Z","repo":{"name":"github.com/anulum/scpn-control","commit":"13b428e776660c037281d369a5701a4b3f0e60e2"},"scorecard":{"version":"v5.3.0","commit":"c22063e786c11f9dd714d777a687ff7c4599b600"},"score":5.6,"checks":[{"name":"Security-Policy","score":10,"reason":"security policy file detected","details":["Info: security policy file detected: SECURITY.md:1","Info: Found linked content: SECURITY.md:1","Info: Found disclosure, vulnerability, and/or timelines in security policy: SECURITY.md:1","Info: Found text in security policy: SECURITY.md:1"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#security-policy"}},{"name":"Dependency-Update-Tool","score":10,"reason":"update tool detected","details":["Info: detected update tool: Dependabot: .github/dependabot.yml:1"],"documentation":{"short":"Determines if the project uses a dependency update tool.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#dependency-update-tool"}},{"name":"Maintained","score":0,"reason":"project was created within the last 90 days. Please review its contents carefully","details":["Warn: Repository was created within the last 90 days."],"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#dangerous-workflow"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#binary-artifacts"}},{"name":"Code-Review","score":0,"reason":"Found 0/29 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#code-review"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Info: jobLevel 'contents' permission set to 'read': .github/workflows/scorecard.yml:22","Info: found token with 'none' permissions: .github/workflows/ci.yml:1","Warn: topLevel 'security-events' permission set to 'write': .github/workflows/codeql.yml:16","Info: topLevel 'contents' permission set to 'read': .github/workflows/docs-pages.yml:18","Info: found token with 'none' permissions: .github/workflows/pre-commit.yml:1","Info: found token with 'none' permissions: .github/workflows/publish-pypi.yml:1","Warn: topLevel 'contents' permission set to 'write': .github/workflows/release.yml:11","Info: found token with 'none' permissions: .github/workflows/scorecard.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#token-permissions"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#cii-best-practices"}},{"name":"Packaging","score":10,"reason":"packaging workflow detected","details":["Info: Project packages its releases by way of GitHub Actions.: .github/workflows/publish-pypi.yml:46"],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#packaging"}},{"name":"Pinned-Dependencies","score":4,"reason":"dependency not pinned by hash detected -- score normalized to 4","details":["Warn: containerImage not pinned by hash: Dockerfile:6: pin your Docker image by updating python:3.12-slim to python:3.12-slim@sha256:ccc7089399c8bb65dd1fb3ed6d55efa538a3f5e7fca3f5988ac3b5b87e593bf0","Warn: containerImage not pinned by hash: Dockerfile:23: pin your Docker image by updating python:3.12-slim to python:3.12-slim@sha256:ccc7089399c8bb65dd1fb3ed6d55efa538a3f5e7fca3f5988ac3b5b87e593bf0","Warn: downloadThenRun not pinned by hash: Dockerfile:8-11","Warn: pipCommand not pinned by hash: Dockerfile:18-20","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:295","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:296","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:315","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:352","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:353","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:183","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:184","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:193","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:35","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:36","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:106","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:107","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:127","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:128","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:143","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:144","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:239","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:240","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:330","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:69","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:70","Warn: pipCommand not pinned by hash: .github/workflows/docs-pages.yml:40","Warn: pipCommand not pinned by hash: .github/workflows/docs-pages.yml:41","Warn: pipCommand not pinned by hash: .github/workflows/publish-pypi.yml:37","Warn: pipCommand not pinned by hash: .github/workflows/publish-pypi.yml:38","Warn: pipCommand not pinned by hash: .github/workflows/release.yml:31","Info:  53 out of  53 GitHub-owned GitHubAction dependencies pinned","Info:  13 out of  13 third-party GitHubAction dependencies pinned","Info:   0 out of   1 downloadThenRun dependencies pinned","Info:   1 out of  28 pipCommand dependencies pinned","Info:   0 out of   2 containerImage dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#pinned-dependencies"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#signed-releases"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#fuzzing"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#vulnerabilities"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'main'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#branch-protection"}},{"name":"SAST","score":10,"reason":"SAST tool is run on all commits","details":["Info: SAST configuration detected: CodeQL","Info: all commits (1) are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#sast"}},{"name":"License","score":9,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Warn: project license file does not contain an FSF or OSI license."],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#license"}},{"name":"CI-Tests","score":10,"reason":"1 out of 1 merged PRs checked by a CI test -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project runs tests before pull requests are merged.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#ci-tests"}},{"name":"Contributors","score":0,"reason":"project has 0 contributing companies or organizations -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project has a set of contributors from multiple organizations (e.g., companies).","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#contributors"}}]},"last_synced_at":"2026-03-10T00:52:45.142Z","repository_id":339399112,"created_at":"2026-03-10T00:52:45.142Z","updated_at":"2026-03-10T00:52:45.142Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33423284,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-23T22:14:44.296Z","status":"online","status_checked_at":"2026-05-24T02:00:06.296Z","response_time":57,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["control-systems","digital-twin","formal-verification","fusion","fusion-energy","grad-shafranov","kuramoto","neuro-symbolic","petri-net","plasma-control","plasma-physics","pyo3","python","rust","spiking-neural-network","tokamak"],"created_at":"2026-02-27T17:27:47.350Z","updated_at":"2026-05-24T06:00:56.329Z","avatar_url":"https://github.com/anulum.png","language":"Python","funding_links":["https://github.com/sponsors/anulum","https://buy.stripe.com/4gM00kbiMdjAberaYz5J601","https://www.paypal.com/donate?hosted_button_id=4X5F6DNT934HY"],"categories":[],"sub_categories":[],"readme":"\u003c!-- SPDX-License-Identifier: AGPL-3.0-or-later --\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/scpn_control_header.png\" alt=\"SCPN-CONTROL — Formal Stochastic Petri Net Engine\" width=\"100%\"\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/anulum/scpn-control/actions\"\u003e\u003cimg src=\"https://github.com/anulum/scpn-control/actions/workflows/ci.yml/badge.svg\" alt=\"CI\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/anulum/scpn-control/actions/workflows/docs-pages.yml\"\u003e\u003cimg src=\"https://github.com/anulum/scpn-control/actions/workflows/docs-pages.yml/badge.svg\" alt=\"Docs Pages\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://pypi.org/project/scpn-control/\"\u003e\u003cimg src=\"https://img.shields.io/pypi/v/scpn-control\" alt=\"PyPI version\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://pypi.org/project/scpn-control/\"\u003e\u003cimg src=\"https://img.shields.io/pypi/pyversions/scpn-control\" alt=\"Python versions\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://pepy.tech/project/scpn-control\"\u003e\u003cimg src=\"https://static.pepy.tech/badge/scpn-control\" alt=\"All-time downloads\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://scpn-control.streamlit.app\"\u003e\u003cimg src=\"https://static.streamlit.io/badges/streamlit_badge_black_white.svg\" alt=\"Open in Streamlit\"\u003e\u003c/a\u003e\n  \u003ca href=\"LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/badge/license-AGPL--3.0-blue.svg\" alt=\"License: AGPL-3.0-or-later\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://www.bestpractices.dev/projects/12176\"\u003e\u003cimg src=\"https://www.bestpractices.dev/projects/12176/badge\" alt=\"OpenSSF Best Practices\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://orcid.org/0009-0009-3560-0851\"\u003e\u003cimg src=\"https://img.shields.io/badge/ORCID-0009--0009--3560--0851-green.svg\" alt=\"ORCID\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://arxiv.org/abs/2004.06344\"\u003e\u003cimg src=\"https://img.shields.io/badge/arXiv-2004.06344-b31b1b.svg\" alt=\"arXiv\"\u003e\u003c/a\u003e\n  \u003ca href=\"docs/REVIEWER_PAPER27_INTEGRATION.pdf\"\u003e\u003cimg src=\"https://img.shields.io/badge/Paper_27-PDF-informational.svg\" alt=\"Paper 27 PDF\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://codecov.io/gh/anulum/scpn-control\"\u003e\u003cimg src=\"https://codecov.io/gh/anulum/scpn-control/branch/main/graph/badge.svg\" alt=\"codecov\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://doi.org/10.5281/zenodo.18804939\"\u003e\u003cimg src=\"https://zenodo.org/badge/DOI/10.5281/zenodo.18804939.svg\" alt=\"DOI\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://buy.stripe.com/4gM00kbiMdjAberaYz5J601\"\u003e\u003cimg src=\"https://img.shields.io/badge/sponsor-Stripe-635bff.svg\" alt=\"Sponsor\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n---\n\n**scpn-control** is a standalone neuro-symbolic control engine that compiles\nStochastic Petri Nets into spiking neural network controllers with\ncontract-based pre/post-condition checking. Extracted from\n[scpn-fusion-core](https://github.com/anulum/scpn-fusion-core) — 134 Python\nsource modules, 264 test files, **3,700+ collected Python tests**, 5 Rust crates, and a 20-job CI matrix.\nFive-tier gyrokinetic transport: critical-gradient, QLKNN surrogate, native linear eigenvalue, native TGLF-equivalent (SAT0/SAT1/SAT2), nonlinear δf GK (5D Vlasov, JAX-accelerable).\n\n\u003e **11.9 µs P50 kernel step** (Criterion-verified, GitHub Actions ubuntu-latest).\n\u003e This is a bare Rust kernel call, not a complete control cycle.\n\u003e See [competitive analysis](docs/competitive_analysis.md) for full benchmarks\n\u003e and [Limitations](#limitations) for honest scope.\n\u003e\n\u003e **Status: Alpha / Research.** Not a production PCS. No real tokamak\n\u003e deployment. Public physics claims are limited to checksum-gated repository\n\u003e reference artefacts, published GEQDSK files, and explicitly bounded synthetic\n\u003e or non-facility domains.\n\n## Capability Inventory\n\n\u003c!-- capability-snapshot:start --\u003e\n\u003c!-- SPDX-License-Identifier: AGPL-3.0-or-later --\u003e\n\u003c!-- Commercial license available --\u003e\n\u003c!-- © Concepts 1996–2026 Miroslav Šotek. All rights reserved. --\u003e\n\u003c!-- © Code 2020–2026 Miroslav Šotek. All rights reserved. --\u003e\n\u003c!-- ORCID: 0009-0009-3560-0851 --\u003e\n\u003c!-- Contact: www.anulum.li | protoscience@anulum.li --\u003e\n\u003c!-- SCPN Control — Generated Capability Snapshot --\u003e\n\u003c!-- Embedded in README.md between capability-snapshot markers. --\u003e\n\n**Capability Inventory**\n\n| Surface | Count |\n| --- | ---: |\n| Package version | 0.19.2 |\n| Python requirement | \u003e=3.10 |\n| Project scripts | 2 |\n| Public API exports | 15 |\n| Python control/physics modules | 128 |\n| Python public classes | 394 |\n| Rust source files | 50 |\n| Rust PyO3 exports | 27 |\n| Validation scripts | 38 |\n| Optional extras | 16 |\n| Python test files | 269 |\n| Public documentation pages | 31 |\n| GitHub Actions workflows | 8 |\n\n**Evidence roots:** `src/scpn_control/{core,control,phase,scpn}`, `scpn-control-rs/crates`, `validation`, `tests`, `docs`, and `.github/workflows`.\n\nRefresh with `python tools/capability_manifest.py`; enforce with `python tools/capability_manifest.py --check`.\n\u003c!-- capability-snapshot:end --\u003e\n\n## Quick Start\n\n```bash\npip install scpn-control                        # core (numpy, scipy, click)\npip install \"scpn-control[dashboard,ws]\"        # + Streamlit dashboard + WebSocket\nscpn-control demo --steps 1000\nscpn-control benchmark --n-bench 5000\n```\n\nFor development (editable install):\n\n```bash\ngit clone https://github.com/anulum/scpn-control.git\ncd scpn-control\npip install -e \".[dev]\"\n```\n\n### Python in 30 Seconds\n\n```python\nfrom scpn_control.core.jax_gs_solver import jax_gs_solve\npsi = jax_gs_solve(NR=33, NZ=33, Ip_target=1e6, n_picard=40, n_jacobi=100)\n\nfrom scpn_control.scpn.structure import StochasticPetriNet\nfrom scpn_control.scpn.compiler import FusionCompiler\nnet = StochasticPetriNet()\nnet.add_place(\"idle\", initial_tokens=1.0)\nnet.add_place(\"heating\"); net.add_transition(\"ignite\")\nnet.add_arc(\"idle\", \"ignite\"); net.add_arc(\"ignite\", \"heating\")\nnet.compile()\nartifact = FusionCompiler().compile(net)  # SPN -\u003e SNN\n```\n\nFull walkthrough: `python examples/quickstart.py`\n\n## Documentation and Tutorials\n\n- Documentation site: https://anulum.github.io/scpn-control/\n- Local docs index: `docs/index.md`\n- Benchmark guide: `docs/benchmarks.md`\n- Notebook tutorials:\n  - `examples/neuro_symbolic_control_demo.ipynb`\n  - `examples/q10_breakeven_demo.ipynb`\n  - `examples/snn_compiler_walkthrough.ipynb`\n  - `examples/paper27_phase_dynamics_demo.ipynb` — Knm/UPDE + ζ sin(Ψ−θ)\n  - `examples/snn_pac_closed_loop_demo.ipynb` — SNN-PAC-Kuramoto closed loop\n  - `examples/streamlit_ws_client.py` — live WebSocket phase sync dashboard\n\nBuild docs locally:\n\n```bash\npython -m pip install mkdocs\nmkdocs serve\n```\n\nExecute all notebooks:\n\n```bash\npython -m pip install \"scpn-control[viz]\" jupyter nbconvert\njupyter nbconvert --to notebook --execute --output-dir artifacts/notebook-exec examples/q10_breakeven_demo.ipynb\njupyter nbconvert --to notebook --execute --output-dir artifacts/notebook-exec examples/snn_compiler_walkthrough.ipynb\n```\n\nOptional notebook (requires `sc_neurocore` available in environment):\n\n```bash\njupyter nbconvert --to notebook --execute --output-dir artifacts/notebook-exec examples/neuro_symbolic_control_demo.ipynb\n```\n\n## Features\n\n- **Petri Net to SNN compilation** -- Translates Stochastic Petri Nets into spiking neural network controllers with LIF neurons and bitstream encoding\n- **Contract checking** -- Runtime pre/post-condition assertions on control observations and actions (not theorem-proved formal verification)\n- **Sub-millisecond latency** -- \u003c1ms control loop with optional Rust-accelerated kernels\n- **Rust acceleration** -- PyO3 bindings for SCPN activation, marking update, Boris integration, SNN pools, and MPC\n- **10 controller types** -- PID, MPC, NMPC, H-infinity, mu-synthesis, gain-scheduled, sliding-mode, fault-tolerant, SNN, PPO reinforcement learning\n- **Grad-Shafranov solver** -- Fixed + free-boundary equilibrium solver with L/H-mode profiles, JAX-differentiable (`jax.grad` through full Picard solve)\n- **Frontier physics** -- Nonlinear δf gyrokinetic solver (5D Vlasov, JAX-accelerable), native TGLF-equivalent (SAT0/SAT1/SAT2, no Fortran binary), kinetic electron species, Sugama collision operator (particle/momentum/energy conservation), electromagnetic A_∥ via Ampere's law (KBM/MTM capable), Dimits-shift scan machinery requiring post-audit revalidation, ballooning connection BC (kx shift), Rosenbluth-Hinton zonal Krook damping, 62× JAX GPU speedup, ballooning eigenvalue solver, sawtooth Kadomtsev model, NTM dynamics, current diffusion/drive, SOL two-point model\n- **MHD stability** -- Five independent criteria: Mercier interchange, ballooning, Kruskal-Shafranov kink, Troyon beta limit, NTM seeding\n- **JAX autodiff** -- Thomas solver, Crank-Nicolson transport, neural equilibrium, GS solver — all JIT-compiled and GPU-compatible\n- **PPO agent** -- 500K-step cloud-trained RL controller (reward 143.7 vs MPC 58.1 vs PID −912.3), 3-seed reproducible\n- **Neural transport** -- QLKNN-10D trained MLP with auto-discovered weights\n- **Scenario management** -- Integrated scenario simulator (transport + current diffusion + sawteeth + NTM + SOL), scenario scheduler, ITER/NSTX-U presets\n- **Digital twin integration** -- Real-time telemetry ingest, closed-loop simulation, real-time EFIT, and flight simulator\n- **RMSE validation** -- CI-gated regression testing against DIII-D reference artefacts and published SPARC GEQDSK files\n- **Disruption prediction** -- ML-based predictor with SPI mitigation and halo/RE physics\n- **Robust control** -- H-infinity DARE synthesis, bounded static mu-analysis, fault-tolerant degraded-mode operation, shape controller with boundary Jacobian\n\n## Architecture\n\n```\nsrc/scpn_control/\n+-- scpn/              # Petri net -\u003e SNN compiler\n|   +-- structure.py   #   StochasticPetriNet graph builder\n|   +-- compiler.py    #   FusionCompiler -\u003e CompiledNet (LIF + bitstream)\n|   +-- contracts.py   #   ControlObservation, ControlAction, ControlTargets\n|   +-- controller.py  #   NeuroSymbolicController (main entry point)\n+-- core/              # Physics solvers + plant models (67 modules)\n|   +-- fusion_kernel.py           # Grad-Shafranov equilibrium (fixed + free boundary)\n|   +-- integrated_transport_solver.py  # Multi-species transport PDE\n|   +-- gyrokinetic_transport.py   # Quasilinear TGLF-10 (ITG/TEM/ETG)\n|   +-- ballooning_solver.py       # s-alpha ballooning eigenvalue ODE\n|   +-- sawtooth.py                # Kadomtsev crash + Porcelli trigger\n|   +-- ntm_dynamics.py            # Modified Rutherford NTM + ECCD stabilization\n|   +-- current_diffusion.py       # Parallel current evolution PDE\n|   +-- current_drive.py           # ECCD, NBI, LHCD deposition models\n|   +-- sol_model.py               # Two-point SOL + Eich heat-flux width\n|   +-- rzip_model.py              # Linearised vertical stability (RZIp)\n|   +-- integrated_scenario.py     # Full scenario simulator (ITER/NSTX-U presets)\n|   +-- stability_mhd.py           # 5 MHD stability criteria\n|   +-- scaling_laws.py            # IPB98y2 confinement scaling\n|   +-- neural_transport.py        # QLKNN-10D trained surrogate\n|   +-- neural_equilibrium.py      # PCA+MLP GS surrogate (1000x speedup)\n|   +-- ...                        # 14 more (eqdsk, uncertainty, pedestal, ...)\n+-- control/           # Controllers (42 modules, optional deps guarded)\n|   +-- h_infinity_controller.py   # H-inf robust control (DARE)\n|   +-- mu_synthesis.py            # Static D-scaled structured singular value bound\n|   +-- nmpc_controller.py         # Nonlinear MPC (SQP, 20-step horizon)\n|   +-- gain_scheduled_controller.py  # PID scheduled on operating regime\n|   +-- sliding_mode_vertical.py   # Sliding-mode vertical stabilizer\n|   +-- fault_tolerant_control.py  # Fault detection + degraded-mode operation\n|   +-- shape_controller.py        # Plasma shape via boundary Jacobian\n|   +-- safe_rl_controller.py      # PPO + MHD constraint checker\n|   +-- scenario_scheduler.py      # Shot timeline + actuator scheduling\n|   +-- realtime_efit.py           # Streaming equilibrium reconstruction\n|   +-- control_benchmark_suite.py # Standardised benchmark scenarios\n|   +-- disruption_predictor.py    # ML disruption prediction + SPI\n|   +-- tokamak_digital_twin.py    # Digital twin\n|   +-- ...                        # 24 more (MPC, flight sim, HIL, ...)\n+-- phase/             # Paper 27 Knm/UPDE phase dynamics (9 modules)\n|   +-- kuramoto.py    #   Kuramoto-Sakaguchi step + order parameter\n|   +-- knm.py         #   Paper 27 Knm coupling matrix builder\n|   +-- upde.py        #   UPDE multi-layer solver\n|   +-- lyapunov_guard.py          # Sliding-window stability monitor\n|   +-- realtime_monitor.py        # Tick-by-tick UPDE + TrajectoryRecorder\n|   +-- ws_phase_stream.py         # Async WebSocket live stream server\n+-- cli.py             # Click CLI\n\nscpn-control-rs/       # Rust workspace (5 crates)\n+-- control-types/     # PlasmaState, EquilibriumConfig, ControlAction\n+-- control-math/      # LIF neuron, Boris pusher, Kuramoto, upde_tick\n+-- control-core/      # GS solver, transport, confinement scaling\n+-- control-control/   # PID, MPC, H-inf, SNN controller\n+-- control-python/    # PyO3 bindings (PyRealtimeMonitor, PySnnPool, ...)\n\ntests/                 # 3,700+ collected Python tests\n+-- mock_diiid.py      # Synthetic DIII-D shot generator (NOT real MDSplus data)\n+-- test_e2e_phase_diiid.py  # E2E: shot-driven monitor + HDF5/NPZ export\n+-- test_phase_kuramoto.py   # 50 Kuramoto/UPDE/Guard/Monitor tests\n+-- test_rust_realtime_parity.py  # Rust PyRealtimeMonitor parity\n+-- ...                # 170+ more test files\n```\n\n## Paper 27 Phase Dynamics (Knm/UPDE Engine)\n\nImplements the generalized Kuramoto-Sakaguchi mean-field model with exogenous\nglobal field driver `ζ sin(Ψ − θ)`, per arXiv:2004.06344 and SCPN Paper 27.\n\n**Modules:** `src/scpn_control/phase/` (9 modules)\n\n| Module | Purpose |\n|--------|---------|\n| `kuramoto.py` | Kuramoto-Sakaguchi step, order parameter R·e^{iΨ}, Lyapunov V/λ |\n| `knm.py` | Paper 27 16×16 coupling matrix (exponential decay + calibration anchors) |\n| `upde.py` | UPDE multi-layer solver with PAC gating |\n| `lyapunov_guard.py` | Sliding-window stability monitor (mirrors DIRECTOR_AI CoherenceScorer) |\n| `realtime_monitor.py` | Tick-by-tick UPDE + TrajectoryRecorder (HDF5/NPZ export) |\n| `ws_phase_stream.py` | Async WebSocket server streaming R/V/λ per tick |\n\n**Rust acceleration:** `upde_tick()` in `control-math` + `PyRealtimeMonitor` PyO3 binding.\n\n**Live phase sync convergence** ([GIF fallback](docs/phase_sync_live.gif)):\n\n\u003cp align=\"center\"\u003e\n  \u003cvideo src=\"docs/phase_sync_live.mp4\" autoplay loop muted playsinline width=\"100%\"\u003e\n    \u003cimg src=\"docs/phase_sync_live.gif\" alt=\"Phase Sync Convergence — 16 layers × 50 osc, ζ=0.5\" width=\"100%\"\u003e\n  \u003c/video\u003e\n\u003c/p\u003e\n\n\u003e 500 ticks, 16 layers × 50 oscillators, ζ=0.5. R converges to 0.92,\n\u003e V→0, λ settles to −0.47 (stable). Generated by `tools/generate_phase_video.py`.\n\n**WebSocket live stream:**\n\n```bash\n# Terminal 1: start server (CLI)\nscpn-control live --port 8765 --zeta 0.5\n\n# Terminal 2: Streamlit WS client (live R/V/λ plots, guard status, control)\npip install \"scpn-control[dashboard,ws]\"\nstreamlit run examples/streamlit_ws_client.py\n\n# Or embedded mode (server + client in one process)\nstreamlit run examples/streamlit_ws_client.py -- --embedded\n```\n\n**E2E test with mock DIII-D shot data:**\n\n```bash\npytest tests/test_e2e_phase_diiid.py -v\n```\n\n## Dependencies\n\n| Required | Optional |\n|----------|----------|\n| numpy \u003e= 1.24 | sc-neurocore \u003e= 3.8.0 (`pip install \"scpn-control[neuro]\"`) |\n| scipy \u003e= 1.10 | matplotlib (`pip install \"scpn-control[viz]\"`) |\n| click \u003e= 8.0 | streamlit (`pip install \"scpn-control[dashboard]\"`) |\n| | torch (`pip install \"scpn-control[ml]\"`) |\n| | ~~nengo~~ (removed — pure LIF+NEF engine, no external dependency) |\n| | h5py (`pip install \"scpn-control[hdf5]\"`) |\n| | websockets (`pip install \"scpn-control[ws]\"`) |\n\n## CLI\n\n```bash\nscpn-control demo --scenario combined --steps 1000   # Closed-loop control demo\nscpn-control benchmark --n-bench 5000                 # PID vs SNN timing benchmark\nscpn-control validate                                 # RMSE validation dashboard\nscpn-control live --port 8765 --zeta 0.5              # Real-time WS phase sync server\nscpn-control hil-test --shots-dir ...                 # HIL test campaign\n```\n\n## Benchmarks\n\nPython micro-benchmark:\n\n```bash\nscpn-control benchmark --n-bench 5000 --json-out\n```\n\nRust Criterion benchmarks:\n\n```bash\ncd scpn-control-rs\ncargo bench --workspace\n```\n\nBenchmark docs: `docs/benchmarks.md`\n\n## Dashboard\n\n```bash\npip install \"scpn-control[dashboard]\"\nstreamlit run dashboard/control_dashboard.py\n```\n\nSix tabs: Trajectory Viewer, RMSE Dashboard, Timing Benchmark, Shot Replay,\nPhase Sync Monitor (live R/V/λ plots), Benchmark Plots (interactive Vega).\n\n### Streamlit Cloud\n\n**Live dashboard:** [scpn-control.streamlit.app](https://scpn-control.streamlit.app)\n\nThe phase sync dashboard runs on Streamlit Cloud with embedded server mode\n(no external WS server needed). Entry point: `streamlit_app.py`.\n\nTo deploy your own instance:\n1. Fork to your GitHub\n2. [share.streamlit.io](https://share.streamlit.io) \u003e New app \u003e select `streamlit_app.py`\n3. Deploy (auto-starts embedded PhaseStreamServer)\n\n## Rust Acceleration\n\n```bash\ncd scpn-control-rs\ncargo test --workspace\n\n# Build Python bindings\ncd crates/control-python\npip install maturin\nmaturin develop --release\ncd ../../\n\n# Verify\npython -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()))\"\n```\n\nThe Rust backend provides PyO3 bindings for:\n- `PyFusionKernel` -- Grad-Shafranov solver\n- `PySnnPool` / `PySnnController` -- Spiking neural network pools\n- `PyMpcController` -- Model Predictive Control\n- `PyPlasma2D` -- Digital twin\n- `PyTransportSolver` -- Chang-Hinton + Sauter bootstrap\n- `PyRealtimeMonitor` -- Multi-layer Kuramoto UPDE tick (phase dynamics)\n- SCPN kernels -- `dense_activations`, `marking_update`, `sample_firing`\n\n## Citation\n\n```bibtex\n@software{sotek2026scpncontrol,\n  title   = {SCPN Control: Neuro-Symbolic Stochastic Petri Net Controller},\n  author  = {Sotek, Miroslav and Reiprich, Michal},\n  year    = {2026},\n  url     = {https://github.com/anulum/scpn-control},\n  license = {AGPL-3.0-or-later}\n}\n```\n\n## Release and PyPI\n\n**Local publish script:**\n\n```bash\n# Dry run (build + check, no upload)\npython tools/publish.py --dry-run\n\n# Publish to TestPyPI\npython tools/publish.py --target testpypi\n\n# Bump version + publish to PyPI\npython tools/publish.py --bump minor --target pypi --confirm\n```\n\n**CI workflow** (tag-triggered trusted publishing):\n\n```bash\ngit tag v0.2.0\ngit push --tags\n# → .github/workflows/publish-pypi.yml runs automatically\n```\n\n## Limitations \u0026 Honest Scope\n\n\u003e These are not future roadmap items — they are current architectural\n\u003e constraints that users must understand.\n\n- **No facility deployment**: DIII-D replay evidence is limited to immutable\n  repository reference artefacts with manifest checksums. Synthetic fixtures\n  remain for CI plumbing only, not public physics evidence. No live MDSplus,\n  no experimental control-room replay, and no real-world validation.\n- **No peer-reviewed fusion publication**: Paper 27 (arXiv:2004.06344) is\n  unpublished in a fusion journal. No external citations.\n- **Not a production PCS**: Alpha-stage research software. No ITER CODAC,\n  no EPICS interface, no safety certification, no real hardware deployment.\n- **\"Formal verification\" is contract checking**: Runtime pre/post-condition\n  assertions, not theorem-proved guarantees (no Coq/Lean/TLA+).\n- **Benchmark comparisons are not apples-to-apples**: The 11.9 µs number is a\n  bare Rust kernel step. DIII-D PCS timings include I/O, diagnostics, and\n  actuator commands. A fair comparison requires equivalent end-to-end\n  measurement on comparable hardware.\n- **Equilibrium solver**: Two variants exist: stable fixed-boundary GS, plus an\n  experimental free-boundary external-coil scaffold. The free-boundary path is\n  not yet sufficient for full shape control, X-point geometry, or divertor\n  configuration. No stellarator geometry.\n- **Transport**: 1.5D flux-surface-averaged with five tiers from critical-gradient\n  to nonlinear δf GK. Native TGLF-equivalent (no Fortran binary) and nonlinear\n  solver produce physically meaningful transport, but are not yet cross-validated\n  against production TGLF or GENE on identical equilibria.\n- **Disruption predictor**: Synthetic training data only. Not validated on\n  experimental disruption databases.\n- **No GPU equilibrium**: P-EFIT is faster on GPU hardware. JAX neural equilibrium\n  runs on GPU if available but is not cross-validated against P-EFIT.\n- **Rust acceleration**: Optional. Pure-Python fallback is complete but 5-10x\n  slower for GS solve and Kuramoto steps at N \u003e 1000.\n\n## Support the Project\n\n**scpn-control** is open-source (AGPL-3.0-or-later | commercial license available).\nFunding goes to compute, validation data, and development time.\n\n| | | |\n|---|---|---|\n| [Sponsor via Stripe](https://buy.stripe.com/4gM00kbiMdjAberaYz5J601) | [Donate via PayPal](https://www.paypal.com/donate?hosted_button_id=4X5F6DNT934HY) | [Pay via TWINT](https://go.twint.ch/1/e/tw?tw=acq.lJTAypb8SL2s8vPg7fL0ubi2C220ajOH0BEQn1aKfEJIiIakLpt8jlEv8XdQ9tCp.) |\n\n**Crypto:** BTC `bc1qg48gdmrjrjumn6fqltvt0cf0w6nvs0wggy37zd` ·\nETH `0xd9b07F617bEff4aC9CAdC2a13Dd631B1980905FF` ·\nLTC `ltc1q886tmvtlnj86kmg2urd8f5td3lmfh32xtpdrut`\n\n**Bank:** CHF IBAN CH14 8080 8002 1898 7544 1 · EUR IBAN CH66 8080 8002 8173 6061 8 · BIC RAIFCH22\n\nFull tier details (Pro, Academic, Enterprise, Sponsorships): [docs/pricing.md](docs/pricing.md)\n\n## Authors\n\n- **Miroslav Sotek** — ANULUM CH \u0026 LI — [ORCID](https://orcid.org/0009-0009-3560-0851)\n- **** — ANULUM CH \u0026 LI\n\n## License\n\n- Concepts: Copyright 1996-2026\n- Code: Copyright 2024-2026\n- License: AGPL-3.0-or-later\n\nCommercial licensing available — contact protoscience@anulum.li.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fanulum%2Fscpn-control","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fanulum%2Fscpn-control","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fanulum%2Fscpn-control/lists"}