Simulation code and reproduction scripts for D-SCEOS, a gateway-injected peer-to-peer, operating-envelope-aware swarm-inspired control principle for flexibility sharing in cyber–physical energy systems.
This repository contains the core simulation code and the scripts that regenerate the reported numbers. It deliberately does not contain the manuscript sources, the figures as typeset, or the large raw trajectory archives: everything reported is regenerated from the code here.
Python 3.11+ and the pinned stack in requirements.txt:
numpy==2.4.4
scipy==1.17.1
pandas==3.0.2
matplotlib==3.10.8
pytest==9.1.1
pyflakes==3.4.0
cvxpy==1.9.2 # conic solver, needed only by the two cross-check scripts
Two dependency files are provided: requirements.txt (working set) and requirements-lock.txt
(every version pinned exactly, including test and lint tooling). Use the lock file to reproduce the
released numbers.
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txtThe numbers are byte-reproducible on this pinned pair of numpy/scipy. On a different BLAS/LAPACK
build the last digits of solver-sensitive means can move; the conclusions asserted by the validator
(orderings, win rates, confidence-interval signs, zero capacity violation, exact-gradient identity)
are checked in a stack-robust way and are not sensitive to that.
# 1. regression tests (fast, no simulation needed)
python -m pytest -q # 33 tests
# 2. full reproduction: runs every experiment, then validates fail-closed
python run_all.py --cold
# 3. or validate an existing set of artefacts on its own
python validate_results.pyrun_all.py --cold first deletes every artefact a run could be resumed from (Monte Carlo
*.partial.json checkpoints, stored trajectories, agent-loss outputs and provenance sidecars),
then executes the experiment manifest in dependency order and runs the validator. Plain --all
reuses any checkpoint it finds and is therefore not a cold reproduction. REPRODUCTION_LEVELS.md
defines three levels (smoke, artefact validation, cold regeneration) and states for each what it
does and does not establish. On Windows use python, not python3 -- see README_RUNNING.md.
On a fresh clone validate_results.py will fail by design until run_all.py has been executed:
the validator recomputes a benchmark from results/*/state_history.npz, and those trajectories are
generated, not shipped. This fail-closed behaviour is intentional — a missing artefact must never be
reported as a pass.
To see or run a subset:
python run_all.py --list # show the manifest
python run_all.py "Stress ladder" # run entries matching a substring| Path | Contents |
|---|---|
code/ |
controller core, safety filter, comparators, communication-graph configuration, unit catalogue, scenarios, simulation harness, runners, figure generators |
reruns/ |
one script per reported experiment |
run_all.py |
experiment manifest and orchestrator |
validate_results.py |
fail-closed validator of the released artefacts |
expected_results.json |
reference values the validator checks against |
test_*.py |
regression tests (exact-gradient identity, CLF derivation, graph reproduction, physical aggregate, communication units, source hygiene) |
*.json (root) |
authoritative result artefacts, regenerated by the scripts |
results/ |
generated trajectories and per-run outputs (created by run_all.py; only small JSON/CSV summaries are tracked) |
Key modules:
code/dsceos_controller.py— the D-SCEOS control law: dynamic aggregate estimation, the local optimization-guided gradient, and the local CLF/HOCBF-QCQP arbitration with its deterministic box–ball projection fallback.code/hocbf_safety_filter.py— the post-hoc HOCBF filter applied to the comparators.code/dsceos_validation.py— the simulation harness, the objective, and the centralized reference.code/graph_config.py— the single authoritative source of the communication-graph parameters. A regression test fails if any released path hardcodes them elsewhere.
# main realistic study (three scenarios x two fleet sizes)
python reruns/batch_realistic.py
# stress ladder (seven target-stress regimes)
python reruns/ladder_rerun.py
# paired Monte Carlo studies
python reruns/monte_carlo.py
# component ablation: each mechanism disabled in turn, scored on the fixed full objective
python reruns/ablation.py --configs N15_a,N60_a,N60_c
# independent-solver cross-check of the local QCQP (requires cvxpy/CLARABEL)
python reruns/qcqp_crosscheck_run.py --only ladder
# centralized reference solve: KKT residual, objective gap, full allocation error
python reruns/reference_kkt_diagnostics.py
# equal-effort comparator protocol with a bracketed step-size search
python reruns/comparator_protocol.py
# closed-loop sampling-time sensitivity at dt, dt/2, dt/4
python reruns/sampling_time_study.py
# distribution-free paired bootstrap with Holm-Bonferroni multiplicity control
python reruns/robust_inference.py
# dense-grid intersample check and objective-quadrature sensitivity
python reruns/intersample_check.py
python reruns/objective_indexing_check.py
# coordination graph held fixed while the communication overlay degrades
python reruns/graph_decoupling.py
# in-loop conic recompute of the main results (requires cvxpy)
python reruns/conic_recompute.pyRuntimes are minutes per experiment on a laptop; the Monte Carlo campaigns and the N=60
configurations are the slowest entries.
- Random seeds, graph parameters and unit catalogues are fixed in the code, so a given command reproduces the same numbers on the pinned stack.
results/trajectories are regenerated rather than tracked, so a clone stays small.- The wall-clock timings that appear in the reported profiles are machine-specific and are marked as such; they are not asserted by the validator.
MIT — see LICENSE. You may use, modify and redistribute this code, including
commercially, provided the copyright notice and the licence text are retained. The software is
provided without warranty.
Citation metadata is in CITATION.cff, which GitHub reads for its
"Cite this repository" button and which Zenodo uses when it archives a release. Before publishing,
fill in the repository URL and the ORCID, and once the article appears, uncomment the
preferred-citation block so that citations point at the paper rather than only at the software.