Kronos Fusion Energy commited on
Commit ·
2573a5a
1
Parent(s): 102af5d
Refresh to v0.3.0 (39 codes); clean package + docs (drop stale cache dump and deposit tooling)
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- .gitattributes +0 -35
- .pytest_cache/.gitignore +0 -2
- .pytest_cache/CACHEDIR.TAG +0 -4
- .pytest_cache/README.md +0 -8
- .pytest_cache/v/cache/lastfailed +0 -3
- .pytest_cache/v/cache/nodeids +0 -12
- .zenodo.json +4 -4
- BENCHMARKS.md +25 -21
- CITATION.cff +2 -2
- CODES.md +16 -0
- benchmarks/benchmarks.json +427 -16
- benchmarks/run_all.py +25 -0
- codemeta.json +2 -2
- kronos_ml/members/__init__.py +2 -0
- kronos_ml/members/advanced.py +133 -0
- kronos_ml/members/foundation.py +333 -0
- kronos_ml/members/quantum.py +8 -7
- kronos_ml/members/quantum_v3.py +286 -0
- kronos_ml/quantum_backend.py +3 -2
- publish/LIVE_RECORDS.md +0 -36
- publish/MANIFEST.sha256 +0 -41
- publish/PROVENANCE.md +0 -42
- publish/PUBLISH_RUNBOOK.md +0 -158
- publish/_deposit_common.py +0 -68
- publish/_percode.py +0 -256
- publish/_percode_summary.json +0 -42
- publish/_scaffolding_summary.json +0 -40
- publish/dataverse_draft.py +0 -105
- publish/dataverse_publish_all.py +0 -59
- publish/figshare_draft.py +0 -119
- publish/figshare_publish_all.py +0 -47
- publish/ia_upload_all.py +0 -47
- publish/kronos-ml-v0.1.0-source.zip +0 -3
- publish/osf_draft.py +0 -71
- publish/osf_publish_all.py +0 -47
- publish/records/kairos/CITATION.cff +0 -13
- publish/records/kairos/LICENSE +0 -189
- publish/records/kairos/MANIFEST.sha256 +0 -7
- publish/records/kairos/benchmark.json +0 -19
- publish/records/kairos/card.md +0 -13
- publish/records/kairos/kairos.py +0 -57
- publish/records/kairos/metadata.json +0 -65
- publish/records/kbench/CITATION.cff +0 -13
- publish/records/kbench/LICENSE +0 -189
- publish/records/kbench/MANIFEST.sha256 +0 -7
- publish/records/kbench/benchmark.json +0 -44
- publish/records/kbench/card.md +0 -13
- publish/records/kbench/kbench.py +0 -54
- publish/records/kbench/metadata.json +0 -65
- publish/records/kbreed/CITATION.cff +0 -13
.gitattributes
DELETED
|
@@ -1,35 +0,0 @@
|
|
| 1 |
-
*.7z filter=lfs diff=lfs merge=lfs -text
|
| 2 |
-
*.arrow filter=lfs diff=lfs merge=lfs -text
|
| 3 |
-
*.bin filter=lfs diff=lfs merge=lfs -text
|
| 4 |
-
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
| 5 |
-
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
| 6 |
-
*.ftz filter=lfs diff=lfs merge=lfs -text
|
| 7 |
-
*.gz filter=lfs diff=lfs merge=lfs -text
|
| 8 |
-
*.h5 filter=lfs diff=lfs merge=lfs -text
|
| 9 |
-
*.joblib filter=lfs diff=lfs merge=lfs -text
|
| 10 |
-
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
| 11 |
-
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
| 12 |
-
*.model filter=lfs diff=lfs merge=lfs -text
|
| 13 |
-
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
| 14 |
-
*.npy filter=lfs diff=lfs merge=lfs -text
|
| 15 |
-
*.npz filter=lfs diff=lfs merge=lfs -text
|
| 16 |
-
*.onnx filter=lfs diff=lfs merge=lfs -text
|
| 17 |
-
*.ot filter=lfs diff=lfs merge=lfs -text
|
| 18 |
-
*.parquet filter=lfs diff=lfs merge=lfs -text
|
| 19 |
-
*.pb filter=lfs diff=lfs merge=lfs -text
|
| 20 |
-
*.pickle filter=lfs diff=lfs merge=lfs -text
|
| 21 |
-
*.pkl filter=lfs diff=lfs merge=lfs -text
|
| 22 |
-
*.pt filter=lfs diff=lfs merge=lfs -text
|
| 23 |
-
*.pth filter=lfs diff=lfs merge=lfs -text
|
| 24 |
-
*.rar filter=lfs diff=lfs merge=lfs -text
|
| 25 |
-
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
| 26 |
-
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
| 27 |
-
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
| 28 |
-
*.tar filter=lfs diff=lfs merge=lfs -text
|
| 29 |
-
*.tflite filter=lfs diff=lfs merge=lfs -text
|
| 30 |
-
*.tgz filter=lfs diff=lfs merge=lfs -text
|
| 31 |
-
*.wasm filter=lfs diff=lfs merge=lfs -text
|
| 32 |
-
*.xz filter=lfs diff=lfs merge=lfs -text
|
| 33 |
-
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
-
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
-
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.pytest_cache/.gitignore
DELETED
|
@@ -1,2 +0,0 @@
|
|
| 1 |
-
# Created by pytest automatically.
|
| 2 |
-
*
|
|
|
|
|
|
|
|
|
.pytest_cache/CACHEDIR.TAG
DELETED
|
@@ -1,4 +0,0 @@
|
|
| 1 |
-
Signature: 8a477f597d28d172789f06886806bc55
|
| 2 |
-
# This file is a cache directory tag created by pytest.
|
| 3 |
-
# For information about cache directory tags, see:
|
| 4 |
-
# https://bford.info/cachedir/spec.html
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.pytest_cache/README.md
DELETED
|
@@ -1,8 +0,0 @@
|
|
| 1 |
-
# pytest cache directory #
|
| 2 |
-
|
| 3 |
-
This directory contains data from the pytest's cache plugin,
|
| 4 |
-
which provides the `--lf` and `--ff` options, as well as the `cache` fixture.
|
| 5 |
-
|
| 6 |
-
**Do not** commit this to version control.
|
| 7 |
-
|
| 8 |
-
See [the docs](https://docs.pytest.org/en/stable/how-to/cache.html) for more information.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.pytest_cache/v/cache/lastfailed
DELETED
|
@@ -1,3 +0,0 @@
|
|
| 1 |
-
{
|
| 2 |
-
"tests/test_contract.py::test_registry_has_thirty": true
|
| 3 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
.pytest_cache/v/cache/nodeids
DELETED
|
@@ -1,12 +0,0 @@
|
|
| 1 |
-
[
|
| 2 |
-
"tests/test_contract.py::test_contract_returns_prediction",
|
| 3 |
-
"tests/test_contract.py::test_every_code_has_provenance_and_status",
|
| 4 |
-
"tests/test_contract.py::test_kecon_financial_firewall",
|
| 5 |
-
"tests/test_contract.py::test_kgate_clamps_and_fails_closed",
|
| 6 |
-
"tests/test_contract.py::test_kyro_reproduces_training_point",
|
| 7 |
-
"tests/test_contract.py::test_metrics_calibration",
|
| 8 |
-
"tests/test_contract.py::test_registry",
|
| 9 |
-
"tests/test_contract.py::test_registry_has_thirty",
|
| 10 |
-
"tests/test_contract.py::test_roadmap_codes_raise",
|
| 11 |
-
"tests/test_contract.py::test_tagged_provenance_requires_retired_by"
|
| 12 |
-
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.zenodo.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
| 1 |
{
|
| 2 |
-
"title": "KODEX: the Kronos Family of Codes (AI/ML fusion surrogate suite) v0.
|
| 3 |
"upload_type": "software",
|
| 4 |
"language": "eng",
|
| 5 |
-
"version": "0.
|
| 6 |
-
"publication_date": "2026-09-
|
| 7 |
"creators": [
|
| 8 |
{
|
| 9 |
"name": "Ford, P. I.",
|
|
@@ -193,5 +193,5 @@
|
|
| 193 |
}
|
| 194 |
],
|
| 195 |
"notes": "Draft-first deposit. Provenance chain: code -> benchmark -> on-disk data -> CGYRO/register/AI+Quantum DOI. See PROVENANCE.md and MANIFEST.sha256.",
|
| 196 |
-
"description": "<p><strong>KODEX — the Kronos Family of Codes.</strong> A benchmarked suite of AI/ML surrogate models that stand in for expensive fusion physics (CGYRO-class gyrokinetics, neutronics, equilibrium, control) with calibrated uncertainty and an abstention gate. One contract across the fleet: <code>predict(x) → (y, uncertainty, in_domain)</code>. Built on and tracing to the Kronos research corpus.</p><p>This release publishes the <strong>
|
| 197 |
}
|
|
|
|
| 1 |
{
|
| 2 |
+
"title": "KODEX: the Kronos Family of Codes (AI/ML fusion surrogate suite) v0.3.0",
|
| 3 |
"upload_type": "software",
|
| 4 |
"language": "eng",
|
| 5 |
+
"version": "0.3.0",
|
| 6 |
+
"publication_date": "2026-09-29",
|
| 7 |
"creators": [
|
| 8 |
{
|
| 9 |
"name": "Ford, P. I.",
|
|
|
|
| 193 |
}
|
| 194 |
],
|
| 195 |
"notes": "Draft-first deposit. Provenance chain: code -> benchmark -> on-disk data -> CGYRO/register/AI+Quantum DOI. See PROVENANCE.md and MANIFEST.sha256.",
|
| 196 |
+
"description": "<p><strong>KODEX — the Kronos Family of Codes.</strong> A benchmarked suite of AI/ML surrogate models that stand in for expensive fusion physics (CGYRO-class gyrokinetics, neutronics, equilibrium, control) with calibrated uncertainty and an abstention gate. One contract across the fleet: <code>predict(x) → (y, uncertainty, in_domain)</code>. Built on and tracing to the Kronos research corpus.</p><p>This release publishes the full <strong>39 BUILT</strong> codes (package + real benchmark + docs), including the v0.3.0 additions KMIND (whole-device foundation surrogate), KSCOUT (multi-fidelity campaign manager), and the quantum members KMIT (error mitigation) and KLINQ (linear solver).</p><p>Honest cards are kept intact: CGYRO-anchored surrogates use the mu=400 representative-mass turbulence map; the quantum members (KQUBIT/KQROSS/KSENSE) report validated null/negative results (no quantum advantage claimed); KWARD's disruption labels are heuristic (Ip current-quench, not physicist-verified) and its headline independent-precursor AUC (0.975) uses only n=1 Mirnov + P_rad; KECON is a generic-LCOE financial firewall carrying no Kronos economic numbers; the newer quantum members (KMIT, KLINQ) are real NISQ-era tools with no claimed advantage — quantum's meaningful role in fusion is post-~2036.</p><p>Documentation: <a href=\"https://kronosfusionenergy.com/kodex\">https://kronosfusionenergy.com/kodex</a> · source: <a href=\"https://github.com/KronosFE/kronos-ml\">https://github.com/KronosFE/kronos-ml</a>.</p>"
|
| 197 |
}
|
BENCHMARKS.md
CHANGED
|
@@ -6,16 +6,16 @@ are kept, not hidden. Nothing here is published until go-live.
|
|
| 6 |
|
| 7 |
| # | Code | Status | Headline benchmark |
|
| 8 |
|--|--|--|--|
|
| 9 |
-
| 01 | **KAIROS** | BUILT | MPC tracking 0.0461 (<5%); Exp-B **0 escapes / 150,000**;
|
| 10 |
| 02 | **KFLOW** | BUILT | GNN RMSE@k8 0.0844 vs naive 0.1721 (beats naive; AC-18 0.05 bar **MISSED**, kept) |
|
| 11 |
| 03 | **KGATE** | BUILT | model-free clamp: **0 escapes / 150,000 steps** |
|
| 12 |
| 04 | **KHALO** | BUILT | sourced ECE 0.0327 +/- 0.0136 / cov90 0.888 +/- 0.034; live GP ECE 0.0771 |
|
| 13 |
| 05 | **KMAT** | BUILT | DFT-validated CHGNet screen, 8 candidates |
|
| 14 |
| 06 | **KOIL** | BUILT | live strain surrogate rel-L2 0.0038; sourced 0.24% @0.15 ms, quench AUC 0.9998 |
|
| 15 |
-
| 07 | **KORE** | BUILT | learned NN equilibrium: rel-L2 0.0035 vs analytic,
|
| 16 |
| 08 | **KQUBIT** | BUILT | **REAL VQE** (PennyLane): recovers H2 ground state to 0.0002 mHa on default; runs on real QC hardware — no advantage yet |
|
| 17 |
| 09 | **KWARD** | BUILT | real-device AUC 0.98 (591 MAST shots), ECE 0.0349; **independent-precursor AUC 0.975** (n=1 Mirnov + P_rad ONLY, label-independent); labels heuristic (Ip-quench) |
|
| 18 |
-
| 10 | **KYRO** | BUILT | complete 16/16 map (12 turbulent / 4 quiet (16/16 complete)); turbulent/quiet **16/16 correct**, R²=0.858 / cov90=0.875; **0.
|
| 19 |
| 11 | **KBREED** | BUILT | TBR surrogate R²=1.0 vs neutronics engine; nominal net TBR 0.742; OpenMC = auto fidelity upgrade |
|
| 20 |
| 12 | **KBURN** | BUILT | dispatch surrogate R²=1.0 (fuel mix → captured power); +22% dynamic |
|
| 21 |
| 13 | **KEYE** | BUILT | virtual-sensor fault detection 0.767 at FAR 0.0 |
|
|
@@ -23,23 +23,27 @@ are kept, not hidden. Nothing here is published until go-live.
|
|
| 23 |
| 15 | **KFUSE** | BUILT | multi-fidelity: RMSE 1.481→1.05 (R²=0.787); 3rd fidelity = real-mass gold (deferred) |
|
| 24 |
| 16 | **KHEAT** | BUILT | heating/current-drive surrogate: driven-current I_cd **R²=0.949** over 3888 configs (reduced CD; RF/NBI ray-tracing = upgrade) |
|
| 25 |
| 17 | **KISO** | BUILT | servo R²=0.723 + **medical-isotope yield** from real FENDL-3.2 σ(E) (6 isotopes, Mo-99/Tc-99m flagship) |
|
| 26 |
-
| 18 | **
|
| 27 |
-
| 19 | **
|
| 28 |
-
| 20 | **
|
| 29 |
-
| 21 | **
|
| 30 |
-
| 22 | **
|
| 31 |
-
| 23 | **
|
| 32 |
-
| 24 | **
|
| 33 |
-
| 25 | **
|
| 34 |
-
| 26 | **
|
| 35 |
-
| 27 | **
|
| 36 |
-
| 28 | **
|
| 37 |
-
| 29 | **
|
| 38 |
-
| 30 | **
|
| 39 |
-
| 31 | **
|
| 40 |
-
| 32 | **
|
| 41 |
-
| 33 | **
|
| 42 |
-
| 34 | **
|
| 43 |
-
| 35 | **
|
|
|
|
|
|
|
|
|
|
|
|
|
| 44 |
|
| 45 |
_Regenerate: `PYTHONPATH=<kronos-ml>:<kronos-toolkit> python benchmarks/run_all.py`._
|
|
|
|
| 6 |
|
| 7 |
| # | Code | Status | Headline benchmark |
|
| 8 |
|--|--|--|--|
|
| 9 |
+
| 01 | **KAIROS** | BUILT | MPC tracking 0.0461 (<5%); Exp-B **0 escapes / 150,000**; 77.8 µs/step |
|
| 10 |
| 02 | **KFLOW** | BUILT | GNN RMSE@k8 0.0844 vs naive 0.1721 (beats naive; AC-18 0.05 bar **MISSED**, kept) |
|
| 11 |
| 03 | **KGATE** | BUILT | model-free clamp: **0 escapes / 150,000 steps** |
|
| 12 |
| 04 | **KHALO** | BUILT | sourced ECE 0.0327 +/- 0.0136 / cov90 0.888 +/- 0.034; live GP ECE 0.0771 |
|
| 13 |
| 05 | **KMAT** | BUILT | DFT-validated CHGNet screen, 8 candidates |
|
| 14 |
| 06 | **KOIL** | BUILT | live strain surrogate rel-L2 0.0038; sourced 0.24% @0.15 ms, quench AUC 0.9998 |
|
| 15 |
+
| 07 | **KORE** | BUILT | learned NN equilibrium: rel-L2 0.0035 vs analytic, 0.318 ms/field; sourced FNO 2.5% vs 1% bar |
|
| 16 |
| 08 | **KQUBIT** | BUILT | **REAL VQE** (PennyLane): recovers H2 ground state to 0.0002 mHa on default; runs on real QC hardware — no advantage yet |
|
| 17 |
| 09 | **KWARD** | BUILT | real-device AUC 0.98 (591 MAST shots), ECE 0.0349; **independent-precursor AUC 0.975** (n=1 Mirnov + P_rad ONLY, label-independent); labels heuristic (Ip-quench) |
|
| 18 |
+
| 10 | **KYRO** | BUILT | complete 16/16 map (12 turbulent / 4 quiet (16/16 complete)); turbulent/quiet **16/16 correct**, R²=0.858 / cov90=0.875; **0.257 ms vs 2.89 GPU-h/pt** (μ=400) |
|
| 19 |
| 11 | **KBREED** | BUILT | TBR surrogate R²=1.0 vs neutronics engine; nominal net TBR 0.742; OpenMC = auto fidelity upgrade |
|
| 20 |
| 12 | **KBURN** | BUILT | dispatch surrogate R²=1.0 (fuel mix → captured power); +22% dynamic |
|
| 21 |
| 13 | **KEYE** | BUILT | virtual-sensor fault detection 0.767 at FAR 0.0 |
|
|
|
|
| 23 |
| 15 | **KFUSE** | BUILT | multi-fidelity: RMSE 1.481→1.05 (R²=0.787); 3rd fidelity = real-mass gold (deferred) |
|
| 24 |
| 16 | **KHEAT** | BUILT | heating/current-drive surrogate: driven-current I_cd **R²=0.949** over 3888 configs (reduced CD; RF/NBI ray-tracing = upgrade) |
|
| 25 |
| 17 | **KISO** | BUILT | servo R²=0.723 + **medical-isotope yield** from real FENDL-3.2 σ(E) (6 isotopes, Mo-99/Tc-99m flagship) |
|
| 26 |
+
| 18 | **KMIT** | BUILT | **REAL error mitigation**: ZNE cuts H2 energy error 44.38→5.029 mHa (0.887 removed); readout TV 0.1472→0.0 — real NISQ tool today, role post-~2036 |
|
| 27 |
+
| 19 | **KPATH** | BUILT | MPC-imitation controller R²=0.879 over 6 axes |
|
| 28 |
+
| 20 | **KQERN** | BUILT | **REAL quantum kernel**: MAST-disruption AUC 0.919 vs classical 0.929 (ties — honest null); runnable on real QC hardware |
|
| 29 |
+
| 21 | **KQROSS** | BUILT | **REAL FT resource estimator**: classical↔quantum crossover ~N=50 needs ~6e+04 physical qubits, roadmap ~2032 — no FT advantage this decade |
|
| 30 |
+
| 22 | **KSENSE** | BUILT | **REAL quantum metrology** (GHZ, PennyLane): ideal Heisenberg 4.0× vs dephased 2.05× ≈ SQL 2.01× — dephasing erases the advantage (honest null) |
|
| 31 |
+
| 23 | **KTENSOR** | BUILT | SVD/MPS ROM of the real CGYRO flux DB: **effective rank ~2.93 of 4 — modestly compressible, NOT strongly low-rank** (honest characterization; classical, no quantum advantage) |
|
| 32 |
+
| 24 | **KBENCH** | BUILT | open fusion-ML benchmark suite: **3 citable tasks** (CGYRO turbulence, MAST disruption, flux ROM) with real data + KODEX baselines |
|
| 33 |
+
| 25 | **KDRIVE** | BUILT | RL policy (cross-entropy): tracking **0.0551** vs naive 0.1225, twin-in-the-loop |
|
| 34 |
+
| 26 | **KDYN** | BUILT | **REAL Trotter quantum dynamics**: 1st-order error 1.34637→0.03381 over steps (~1/n); runs on real QC hardware — honest cost curve, no advantage yet |
|
| 35 |
+
| 27 | **KECON** | BUILT | generic LCOE calculator + breakdown — **FINANCIAL FIREWALL (no Kronos numbers)** |
|
| 36 |
+
| 28 | **KEDGE** | BUILT | divertor edge surrogate: heat-flux→target-temp **R²=1.0**, CuCrZr limit q~13.5 MW/m² (reduced 0-D; SOLPS/EIRENE = upgrade) |
|
| 37 |
+
| 29 | **KFORGE** | BUILT | inverse-design chained KYRO+KORE → **found a quiet operating point** (a/L_T=2.228, shear=1.511, Q_tot≈0.0) |
|
| 38 |
+
| 30 | **KFUEL** | BUILT | fuel-cycle balance: self-sufficient=True, doubling 5.17 yr (illustrative TBR) |
|
| 39 |
+
| 31 | **KGEN** | BUILT | generative (PCA latent, dim 8); samples plausible equilibrium fields (diffusion = roadmap) |
|
| 40 |
+
| 32 | **KLAW** | BUILT | equation discovery: 7 terms, R²=0.903 — **rediscovered the critical-gradient onset** from the CGYRO map |
|
| 41 |
+
| 33 | **KLINQ** | BUILT | **REAL quantum linear solver** (VQLS): 4×4 reduced-MHD solve fidelity 1.0 vs classical (rel-resid 0.0); FT-HHL ~4e+04 phys qubits — no advantage, role post-~2036 |
|
| 42 |
+
| 34 | **KMIND** | BUILT | **foundation model**: one shared trunk across 4 domains (66958 params); transfer vs matched single-task — pos ['equil'], neg none, neutral ['state', 'disrupt'] (transport data-starved) — honest multi-task result |
|
| 43 |
+
| 35 | **KPILOT** | BUILT | fleet router: plain-language query → the right code (LLM agent = roadmap upgrade) |
|
| 44 |
+
| 36 | **KQOPT** | BUILT | **REAL QAOA optimizer**: 1.0 of optimum on a design QUBO (6 qubits); plug in your QUBO, run on real QC hardware — no speedup yet |
|
| 45 |
+
| 37 | **KRAD** | BUILT | impurity-seeding radiation evaluator: 3 impurities (Ar, N, Ne); least core dilution = Ar |
|
| 46 |
+
| 38 | **KSCOUT** | BUILT | **multi-fidelity campaign**: tight 15.0 GPU-h over 16 hotspots → mean confidence ρ 0.638 vs 0.281 all-μ=400 (2.27×); triage-then-escalate |
|
| 47 |
+
| 39 | **KSEEK** | BUILT | active-learning: proposes next CGYRO run (a/L_T=2.225, shear=0.58); LOO std-vs-error corr -0.283 (honest: weak on 16 pts) |
|
| 48 |
|
| 49 |
_Regenerate: `PYTHONPATH=<kronos-ml>:<kronos-toolkit> python benchmarks/run_all.py`._
|
CITATION.cff
CHANGED
|
@@ -1,8 +1,8 @@
|
|
| 1 |
cff-version: 1.2.0
|
| 2 |
message: "If you use KODEX, please cite it as below."
|
| 3 |
title: "KODEX: the Kronos Family of Codes (AI/ML fusion surrogate suite)"
|
| 4 |
-
version: "0.
|
| 5 |
-
date-released: "2026-09-
|
| 6 |
license: Apache-2.0
|
| 7 |
repository-code: "https://github.com/KronosFE/kronos-ml"
|
| 8 |
url: "https://kronosfusionenergy.com/kodex"
|
|
|
|
| 1 |
cff-version: 1.2.0
|
| 2 |
message: "If you use KODEX, please cite it as below."
|
| 3 |
title: "KODEX: the Kronos Family of Codes (AI/ML fusion surrogate suite)"
|
| 4 |
+
version: "0.3.0"
|
| 5 |
+
date-released: "2026-09-29"
|
| 6 |
license: Apache-2.0
|
| 7 |
repository-code: "https://github.com/KronosFE/kronos-ml"
|
| 8 |
url: "https://kronosfusionenergy.com/kodex"
|
CODES.md
CHANGED
|
@@ -94,6 +94,10 @@ tensor-network / low-rank (MPS-style SVD) ROM of the real CGYRO A1e flux databas
|
|
| 94 |
**REAL quantum kernel** (PennyLane) — embeds real MAST disruption features into a quantum feature map and classifies on the fidelity kernel; runs on a simulator now, real QC hardware pluggable. MAST-disruption AUC **0.919** vs classical RBF 0.929 (ties — a validated null); a real, runnable quantum-ML pipeline on real fusion data.
|
| 95 |
*provenance SIM · retired_by **fault-tolerant quantum hardware (not available this decade)** · gates KX-L3.*
|
| 96 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 97 |
## Phase 3 — cutting-edge + capstones
|
| 98 |
|
| 99 |
### KDRIVE — RL-control `[BUILT]`
|
|
@@ -148,3 +152,15 @@ active-learning acquisition — proposes the next most-informative CGYRO run fro
|
|
| 148 |
open, citable fusion-ML benchmark suite — 3 tasks (CGYRO turbulence, MAST disruption, flux ROM) with real on-disk data, fixed reproducible splits, metrics, and KODEX baselines to beat. A community leaderboard starting point, not a private result; honest that it's small by mainstream-ML standards (pilot fusion-ML benchmarks).
|
| 149 |
*provenance n/a · retired_by **community-standard fusion-ML benchmarks**.*
|
| 150 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 94 |
**REAL quantum kernel** (PennyLane) — embeds real MAST disruption features into a quantum feature map and classifies on the fidelity kernel; runs on a simulator now, real QC hardware pluggable. MAST-disruption AUC **0.919** vs classical RBF 0.929 (ties — a validated null); a real, runnable quantum-ML pipeline on real fusion data.
|
| 95 |
*provenance SIM · retired_by **fault-tolerant quantum hardware (not available this decade)** · gates KX-L3.*
|
| 96 |
|
| 97 |
+
### KMIT — QMITIGATION `[BUILT]` ✦v0.3
|
| 98 |
+
**REAL quantum error mitigation** — zero-noise extrapolation (ZNE, global unitary folding) + inverse-confusion readout-error mitigation applied to the real KQUBIT H₂ VQE circuit (PennyLane default.mixed; sim now, real hardware pluggable). ZNE removes ~89% of the noise-induced energy error (44.4 → 5.0 mHa); readout mitigation cuts the measurement TV distance to ~0. Mitigation is the genuine NISQ tool TODAY — it recovers signal from noise, not a speedup. Honest: quantum's meaningful role in fusion is post-~2036.
|
| 99 |
+
*provenance SIM · retired_by **fault-tolerant quantum hardware (not available this decade)** · gates KX-L3.*
|
| 100 |
+
|
| 101 |
## Phase 3 — cutting-edge + capstones
|
| 102 |
|
| 103 |
### KDRIVE — RL-control `[BUILT]`
|
|
|
|
| 152 |
open, citable fusion-ML benchmark suite — 3 tasks (CGYRO turbulence, MAST disruption, flux ROM) with real on-disk data, fixed reproducible splits, metrics, and KODEX baselines to beat. A community leaderboard starting point, not a private result; honest that it's small by mainstream-ML standards (pilot fusion-ML benchmarks).
|
| 153 |
*provenance n/a · retired_by **community-standard fusion-ML benchmarks**.*
|
| 154 |
|
| 155 |
+
### KMIND — FOUNDATION `[BUILT]` ✦v0.3
|
| 156 |
+
**whole-device foundation surrogate** — ONE shared-trunk multi-task neural net (per-domain input adapters → a shared plasma-state trunk → per-domain heads, ~67k params) trained JOINTLY across transport (KYRO), equilibrium (KORE), state (KFLOW) and disruption (KWARD) on the data those specialists use. Benchmarked head-by-head against a MATCHED single-task baseline on the same split: on the well-populated domains the shared representation shows **no negative transfer** (equilibrium slight positive, state/disruption neutral); transport is **data-starved (16 pts) and reported, not hidden**. MC-dropout uncertainty; per-domain trust gate (physical box for transport/equil, Mahalanobis for state/disrupt). The honest question a foundation model must answer — does one shared representation help or hurt each task? — answered with matched baselines.
|
| 157 |
+
*provenance SIM · retired_by **a device-scale multi-task foundation model on real multi-diagnostic data** · gates BR-L2-A1e, AC-16, AC-18, AC-20.*
|
| 158 |
+
|
| 159 |
+
### KLINQ — QLINSOLVE `[BUILT]` ✦v0.3
|
| 160 |
+
**REAL quantum linear solver** — a variational quantum linear solver (VQLS) prepares the solution of a 4×4 reduced-MHD (discrete-Laplacian, SPD) linear system with a real quantum circuit (PennyLane; sim now, hardware pluggable), recovering the classical solution at fidelity ~1.0. Bundled with an honest fault-tolerant HHL resource estimate: a fusion-scale (N~1e6) sparse solve needs ~4e4 physical qubits — no advantage at real scale. Honest: quantum's meaningful role in fusion is post-~2036.
|
| 161 |
+
*provenance SIM · retired_by **fault-tolerant quantum hardware (not available this decade)** · gates KX-L3.*
|
| 162 |
+
|
| 163 |
+
### KSCOUT — MF-CAMPAIGN `[BUILT]` ✦v0.3
|
| 164 |
+
**multi-fidelity Bayesian-optimization campaign manager** — extends KSEEK from a single next-point to a budget-constrained campaign that chooses which operating point AND which fidelity (reduced twin / μ=400 CGYRO / real-mass gold) to run next. Triage-then-escalate: cheap twin on every uncertain hotspot, escalate the most-uncertain to μ=400, reserve real-mass gold. Under a tight GPU-hour budget it reaches ~2.3× the mean truth-confidence of a naive all-μ=400 plan (which exhausts the budget and leaves most hotspots unexamined). Honest: fidelity correlations are assumptions (gold not yet run); GPU-hours only, no cost figures.
|
| 165 |
+
*provenance SIM · retired_by **the full multi-fidelity CGYRO campaign (twin + μ=400 + real-mass gold)** · gates BR-L2-A1e.*
|
| 166 |
+
|
benchmarks/benchmarks.json
CHANGED
|
@@ -27,7 +27,7 @@
|
|
| 27 |
"escapes": 0,
|
| 28 |
"catch_rate": 1.0
|
| 29 |
},
|
| 30 |
-
"live_mpc_step_us":
|
| 31 |
"sourced": {
|
| 32 |
"file": "track5_control/clamp_activation_stats.csv",
|
| 33 |
"headline": "0 escapes / 150k steps / 3000 injected (AC-25); tracking <5%"
|
|
@@ -178,7 +178,7 @@
|
|
| 178 |
"gates": [
|
| 179 |
"KX-L3"
|
| 180 |
],
|
| 181 |
-
"note": "REAL quantum dynamics \u2014 Trotterized time-evolution of a transverse-field Ising 'kinetic' Hamiltonian (PennyLane); the honest 1/n_steps cost curve for simulating plasma-like dynamics on a quantum computer. Runs on a simulator now, hardware pluggable",
|
| 182 |
"available": true
|
| 183 |
},
|
| 184 |
"benchmark": {
|
|
@@ -200,7 +200,7 @@
|
|
| 200 |
"active_backend": "default",
|
| 201 |
"ran_on_real_hardware": false,
|
| 202 |
"how_to_use_real_qc": "set KODEX_QC_BACKEND=ibm and KODEX_QC_TOKEN=<your IBM Quantum token> to run this exact circuit on real quantum hardware",
|
| 203 |
-
"honest_timeline": "fault-tolerant quantum ADVANTAGE for fusion kernels is ~8-10 yr out; this tooling makes the TESTING real and runnable TODAY, same code path"
|
| 204 |
},
|
| 205 |
"verdict": "REAL Trotterized quantum dynamics: 1st-order error falls 1.34637 -> 0.03381 from 1 to 32 steps (~1/n) \u2014 the honest cost curve for simulating plasma-like Hamiltonian dynamics on a quantum computer. Runs on real hardware with KODEX_QC_BACKEND=ibm. No advantage at this size; a real, testable pipeline."
|
| 206 |
},
|
|
@@ -613,6 +613,70 @@
|
|
| 613 |
"note": "compact closure discovered from the 16/16 CGYRO map"
|
| 614 |
}
|
| 615 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 616 |
"KMAT": {
|
| 617 |
"card": {
|
| 618 |
"name": "KMAT",
|
|
@@ -649,6 +713,161 @@
|
|
| 649 |
"note": "alloy screen BUILT; dpa/lifetime roadmap inside KMAT"
|
| 650 |
}
|
| 651 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 652 |
"KOIL": {
|
| 653 |
"card": {
|
| 654 |
"name": "KOIL",
|
|
@@ -701,7 +920,7 @@
|
|
| 701 |
"live_learned_surrogate": {
|
| 702 |
"rel_l2_vs_analytic": 0.0035,
|
| 703 |
"ensemble_cov90": 0.778,
|
| 704 |
-
"infer_ms":
|
| 705 |
"grid": "16x16",
|
| 706 |
"n_heldout": 120
|
| 707 |
},
|
|
@@ -768,7 +987,7 @@
|
|
| 768 |
"gates": [
|
| 769 |
"KX-L3"
|
| 770 |
],
|
| 771 |
-
"note": "REAL quantum-kernel classifier \u2014 embeds real MAST disruption features into a quantum feature map and classifies on the fidelity kernel (PennyLane); runs on a simulator now, real hardware pluggable. Honest: ties the classical kernel \u2014 a validated no-advantage result, but a real, runnable quantum-ML pipeline",
|
| 772 |
"available": true
|
| 773 |
},
|
| 774 |
"benchmark": {
|
|
@@ -792,7 +1011,7 @@
|
|
| 792 |
"active_backend": "default",
|
| 793 |
"ran_on_real_hardware": false,
|
| 794 |
"how_to_use_real_qc": "set KODEX_QC_BACKEND=ibm and KODEX_QC_TOKEN=<your IBM Quantum token> to run this exact circuit on real quantum hardware",
|
| 795 |
-
"honest_timeline": "fault-tolerant quantum ADVANTAGE for fusion kernels is ~8-10 yr out; this tooling makes the TESTING real and runnable TODAY, same code path"
|
| 796 |
},
|
| 797 |
"verdict": "REAL quantum kernel classifies MAST disruptions at AUC 0.919 vs classical RBF 0.929 (Delta -0.010) \u2014 no advantage: a validated null, but a REAL runnable quantum-ML pipeline on real fusion data. Runs on hardware with KODEX_QC_BACKEND=ibm.",
|
| 798 |
"caveats": [
|
|
@@ -817,7 +1036,7 @@
|
|
| 817 |
"gates": [
|
| 818 |
"KX-L3"
|
| 819 |
],
|
| 820 |
-
"note": "REAL QAOA quantum optimizer \u2014 solves a combinatorial design QUBO on an actual quantum circuit (PennyLane); runs on a simulator now, real hardware pluggable, and you can plug in your own QUBO. Honest: standard ~0.7-1.0 approx ratio, no speedup at this size (
|
| 821 |
"available": true
|
| 822 |
},
|
| 823 |
"benchmark": {
|
|
@@ -842,7 +1061,7 @@
|
|
| 842 |
"active_backend": "default",
|
| 843 |
"ran_on_real_hardware": false,
|
| 844 |
"how_to_use_real_qc": "set KODEX_QC_BACKEND=ibm and KODEX_QC_TOKEN=<your IBM Quantum token> to run this exact circuit on real quantum hardware",
|
| 845 |
-
"honest_timeline": "fault-tolerant quantum ADVANTAGE for fusion kernels is ~8-10 yr out; this tooling makes the TESTING real and runnable TODAY, same code path"
|
| 846 |
},
|
| 847 |
"verdict": "REAL QAOA reaches 100% of the brute-force optimum (cut 6/6, p=2, 6 qubits) on the default backend \u2014 a working quantum optimizer, runnable on hardware with KODEX_QC_BACKEND=ibm. HONEST: no speedup vs classical at this size; advantage is ~8-10 yr out."
|
| 848 |
},
|
|
@@ -864,7 +1083,7 @@
|
|
| 864 |
"AC-43",
|
| 865 |
"BR-SX-08"
|
| 866 |
],
|
| 867 |
-
"note": "REAL fault-tolerant resource estimator \u2014 computes the classical<->quantum crossover N, the surface-code physical-qubit overhead, and the logical-qubit roadmap year for a fusion electronic-structure kernel (order-of-magnitude, literature-scaled). Verdict: no FT advantage this decade \u2014 the machine does not exist yet",
|
| 868 |
"available": true
|
| 869 |
},
|
| 870 |
"benchmark": {
|
|
@@ -899,7 +1118,7 @@
|
|
| 899 |
"AC-44",
|
| 900 |
"KX-L3-A4"
|
| 901 |
],
|
| 902 |
-
"note": "REAL variational quantum eigensolver (VQE) for a molecular Hamiltonian \u2014 a runnable quantum program (PennyLane): executes on a simulator now and on real quantum hardware when you plug in a backend. Honest: no quantum advantage yet (~8-10 yr out); the tooling + testing are real TODAY",
|
| 903 |
"available": true
|
| 904 |
},
|
| 905 |
"benchmark": {
|
|
@@ -926,7 +1145,7 @@
|
|
| 926 |
"active_backend": "default",
|
| 927 |
"ran_on_real_hardware": false,
|
| 928 |
"how_to_use_real_qc": "set KODEX_QC_BACKEND=ibm and KODEX_QC_TOKEN=<your IBM Quantum token> to run this exact circuit on real quantum hardware",
|
| 929 |
-
"honest_timeline": "fault-tolerant quantum ADVANTAGE for fusion kernels is ~8-10 yr out; this tooling makes the TESTING real and runnable TODAY, same code path"
|
| 930 |
},
|
| 931 |
"verdict": "REAL VQE recovers the H2 ground state to 0.0002 mHa on the default backend (within 1.6 mHa chemical accuracy). Runs on real quantum hardware when you set KODEX_QC_BACKEND=ibm. HONEST: no quantum advantage this decade \u2014 the value now is a real, testable quantum pipeline, not a speedup."
|
| 932 |
},
|
|
@@ -968,6 +1187,198 @@
|
|
| 968 |
"caveat": "small seeding scan (few impurities); reduced 0-D radiation model"
|
| 969 |
}
|
| 970 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 971 |
"KSEEK": {
|
| 972 |
"card": {
|
| 973 |
"name": "KSEEK",
|
|
@@ -1022,7 +1433,7 @@
|
|
| 1022 |
"gates": [
|
| 1023 |
"HX-29"
|
| 1024 |
],
|
| 1025 |
-
"note": "REAL quantum-metrology evaluation (PennyLane mixed-state) \u2014 GHZ interferometry: ideal gives Heisenberg (gain ~ N) scaling, but realistic dephasing (NV/SQUID/SERF reality) collapses it back to the standard quantum limit (~sqrt(N)). Honest null where fusion disruptions live",
|
| 1026 |
"available": true
|
| 1027 |
},
|
| 1028 |
"benchmark": {
|
|
@@ -1091,7 +1502,7 @@
|
|
| 1091 |
"active_backend": "default",
|
| 1092 |
"ran_on_real_hardware": false,
|
| 1093 |
"how_to_use_real_qc": "set KODEX_QC_BACKEND=ibm and KODEX_QC_TOKEN=<your IBM Quantum token> to run this exact circuit on real quantum hardware",
|
| 1094 |
-
"honest_timeline": "fault-tolerant quantum ADVANTAGE for fusion kernels is ~8-10 yr out; this tooling makes the TESTING real and runnable TODAY, same code path"
|
| 1095 |
},
|
| 1096 |
"verdict": "REAL quantum-metrology computation: over N=2->8 the ideal GHZ gain grows 4.0x (Heisenberg ~ N), but with per-qubit dephasing (p=0.2) the dephased GHZ grows only 2.05x \u2014 essentially the SQL rate (2.01x, ~sqrt(N)). Dephasing ERASES the Heisenberg *scaling* to a bounded constant (gain turns over near N~9). HONEST NULL: no quantum-sensing advantage for fusion disruptions this decade \u2014 but a real, runnable metrology tool."
|
| 1097 |
},
|
|
@@ -1112,7 +1523,7 @@
|
|
| 1112 |
"gates": [
|
| 1113 |
"KX-L3"
|
| 1114 |
],
|
| 1115 |
-
"note": "tensor-network / low-rank ROM compression of the real CGYRO A1e flux database (classical MPS-style SVD; a many-body method and bridge to quantum kernels \u2014 NO quantum-advantage claim)",
|
| 1116 |
"available": true
|
| 1117 |
},
|
| 1118 |
"benchmark": {
|
|
@@ -1263,9 +1674,9 @@
|
|
| 1263 |
"map": "12 turbulent / 4 quiet (16/16 complete)"
|
| 1264 |
},
|
| 1265 |
"speed": {
|
| 1266 |
-
"surrogate_ms_per_point": 0.
|
| 1267 |
"cgyro_gpu_h_per_point_measured": 2.89,
|
| 1268 |
-
"speedup_x_vs_cgyro": "
|
| 1269 |
"speedup_note": "ms inference vs GPU-hours for the CONVERGED flux value",
|
| 1270 |
"fidelity": "representative mu=400; real-mass gold deferred"
|
| 1271 |
},
|
|
|
|
| 27 |
"escapes": 0,
|
| 28 |
"catch_rate": 1.0
|
| 29 |
},
|
| 30 |
+
"live_mpc_step_us": 77.8,
|
| 31 |
"sourced": {
|
| 32 |
"file": "track5_control/clamp_activation_stats.csv",
|
| 33 |
"headline": "0 escapes / 150k steps / 3000 injected (AC-25); tracking <5%"
|
|
|
|
| 178 |
"gates": [
|
| 179 |
"KX-L3"
|
| 180 |
],
|
| 181 |
+
"note": "REAL quantum dynamics \u2014 Trotterized time-evolution of a transverse-field Ising 'kinetic' Hamiltonian (PennyLane); the honest 1/n_steps cost curve for simulating plasma-like dynamics on a quantum computer. Runs on a simulator now, hardware pluggable; quantum's role in fusion is post-~2036",
|
| 182 |
"available": true
|
| 183 |
},
|
| 184 |
"benchmark": {
|
|
|
|
| 200 |
"active_backend": "default",
|
| 201 |
"ran_on_real_hardware": false,
|
| 202 |
"how_to_use_real_qc": "set KODEX_QC_BACKEND=ibm and KODEX_QC_TOKEN=<your IBM Quantum token> to run this exact circuit on real quantum hardware",
|
| 203 |
+
"honest_timeline": "fault-tolerant quantum ADVANTAGE for fusion kernels is ~8-10 yr out \u2014 a meaningful role in fusion only after ~2036; this tooling makes the TESTING real and runnable TODAY, same code path"
|
| 204 |
},
|
| 205 |
"verdict": "REAL Trotterized quantum dynamics: 1st-order error falls 1.34637 -> 0.03381 from 1 to 32 steps (~1/n) \u2014 the honest cost curve for simulating plasma-like Hamiltonian dynamics on a quantum computer. Runs on real hardware with KODEX_QC_BACKEND=ibm. No advantage at this size; a real, testable pipeline."
|
| 206 |
},
|
|
|
|
| 613 |
"note": "compact closure discovered from the 16/16 CGYRO map"
|
| 614 |
}
|
| 615 |
},
|
| 616 |
+
"KLINQ": {
|
| 617 |
+
"card": {
|
| 618 |
+
"name": "KLINQ",
|
| 619 |
+
"function": "QLINSOLVE",
|
| 620 |
+
"status": "BUILT",
|
| 621 |
+
"phase": 3,
|
| 622 |
+
"provenance": "SIM",
|
| 623 |
+
"retired_by": "fault-tolerant quantum hardware (not available this decade)",
|
| 624 |
+
"gates": [
|
| 625 |
+
"KX-L3"
|
| 626 |
+
],
|
| 627 |
+
"note": "REAL quantum linear solver \u2014 a variational quantum linear solver (VQLS) prepares the solution of a small reduced-MHD linear system with a real quantum circuit (sim now, hardware pluggable), plus an honest fault-tolerant HHL resource estimate. No advantage at real scale; quantum's role in fusion is post-~2036",
|
| 628 |
+
"available": true
|
| 629 |
+
},
|
| 630 |
+
"benchmark": {
|
| 631 |
+
"member": "KLINQ",
|
| 632 |
+
"live_quantum_linear_solver": {
|
| 633 |
+
"problem": "solve A x = b for a 4x4 reduced-MHD Laplacian (SPD) with a real quantum circuit",
|
| 634 |
+
"method": "variational quantum linear solver (VQLS), global overlap cost, Powell optimization",
|
| 635 |
+
"framework": "PennyLane (sim now; Hadamard-test cost on real hardware, pluggable)",
|
| 636 |
+
"N": 4,
|
| 637 |
+
"n_qubits": 2,
|
| 638 |
+
"cost_final": 0.0,
|
| 639 |
+
"solution_fidelity_vs_classical": 1.0,
|
| 640 |
+
"residual_rel": 0.0,
|
| 641 |
+
"x_quantum": [
|
| 642 |
+
0.8,
|
| 643 |
+
0.6,
|
| 644 |
+
0.4,
|
| 645 |
+
0.2
|
| 646 |
+
],
|
| 647 |
+
"x_classical": [
|
| 648 |
+
0.8,
|
| 649 |
+
0.6,
|
| 650 |
+
0.4,
|
| 651 |
+
0.2
|
| 652 |
+
],
|
| 653 |
+
"ft_hhl_resource_estimate": {
|
| 654 |
+
"assumed_system": "N~1e+06 sparse SPD (reduced-MHD grid), kappa~1e+03",
|
| 655 |
+
"logical_qubits_needed": 31,
|
| 656 |
+
"physical_qubits_needed": "~4e+04",
|
| 657 |
+
"surface_code_phys_per_logical": 1250,
|
| 658 |
+
"roadmap_year_reach_logical": 2031,
|
| 659 |
+
"hardware_today": "~1e2-1e3 physical qubits, no error-corrected logical qubits",
|
| 660 |
+
"caveats": [
|
| 661 |
+
"HHL needs fault tolerance + sparse, well-conditioned A + efficient state prep, and returns |x> (aggregate readout), not the full vector",
|
| 662 |
+
"no fusion HHL advantage this decade \u2014 meaningful role post-~2036"
|
| 663 |
+
]
|
| 664 |
+
},
|
| 665 |
+
"backend": {
|
| 666 |
+
"active_backend": "default",
|
| 667 |
+
"ran_on_real_hardware": false,
|
| 668 |
+
"how_to_use_real_qc": "set KODEX_QC_BACKEND=ibm and KODEX_QC_TOKEN=<your IBM Quantum token> to run this exact circuit on real quantum hardware",
|
| 669 |
+
"honest_timeline": "fault-tolerant quantum ADVANTAGE for fusion kernels is ~8-10 yr out \u2014 a meaningful role in fusion only after ~2036; this tooling makes the TESTING real and runnable TODAY, same code path"
|
| 670 |
+
},
|
| 671 |
+
"verdict": "REAL variational quantum linear solver recovers the 4x4 reduced-MHD solve at solution fidelity 1.0 vs classical (rel-residual 0.0) \u2014 a runnable quantum linear solver TODAY. The fault-tolerant HHL route for a fusion-scale (N~1e6) solve needs ~31 logical -> ~4e+04 physical qubits (roadmap ~2031). HONEST: no advantage at real scale; quantum's meaningful role in fusion is post-~2036. Runs on hardware with KODEX_QC_BACKEND=ibm."
|
| 672 |
+
},
|
| 673 |
+
"caveats": [
|
| 674 |
+
"no quantum advantage \u2014 quantum's role in fusion is post-~2036",
|
| 675 |
+
"VQLS residual is read from the simulator here; on hardware it needs Hadamard tests and its cost landscape can have barren plateaus at scale",
|
| 676 |
+
"the 4x4 system is a toy; classical solves it instantly \u2014 the point is a real, honest, hardware-ready quantum pipeline, not a speedup"
|
| 677 |
+
]
|
| 678 |
+
}
|
| 679 |
+
},
|
| 680 |
"KMAT": {
|
| 681 |
"card": {
|
| 682 |
"name": "KMAT",
|
|
|
|
| 713 |
"note": "alloy screen BUILT; dpa/lifetime roadmap inside KMAT"
|
| 714 |
}
|
| 715 |
},
|
| 716 |
+
"KMIND": {
|
| 717 |
+
"card": {
|
| 718 |
+
"name": "KMIND",
|
| 719 |
+
"function": "FOUNDATION",
|
| 720 |
+
"status": "BUILT",
|
| 721 |
+
"phase": 3,
|
| 722 |
+
"provenance": "SIM",
|
| 723 |
+
"retired_by": "a device-scale multi-task foundation model on real multi-diagnostic data",
|
| 724 |
+
"gates": [
|
| 725 |
+
"BR-L2-A1e",
|
| 726 |
+
"AC-16",
|
| 727 |
+
"AC-18",
|
| 728 |
+
"AC-20"
|
| 729 |
+
],
|
| 730 |
+
"note": "whole-device foundation surrogate \u2014 one shared-trunk multi-task net across transport / equilibrium / state / disruption, trained jointly; reports shared-representation transfer honestly (incl. negative transfer)",
|
| 731 |
+
"available": true
|
| 732 |
+
},
|
| 733 |
+
"benchmark": {
|
| 734 |
+
"member": "KMIND",
|
| 735 |
+
"live_foundation": {
|
| 736 |
+
"architecture": "per-domain adapter (->32) + shared trunk (2x128, dropout 0.1) + per-domain head; 4 domains, joint training 300 steps",
|
| 737 |
+
"domains": [
|
| 738 |
+
"transport",
|
| 739 |
+
"equil",
|
| 740 |
+
"state",
|
| 741 |
+
"disrupt"
|
| 742 |
+
],
|
| 743 |
+
"params": 66958,
|
| 744 |
+
"transfer_vs_single_task": {
|
| 745 |
+
"transport": {
|
| 746 |
+
"metric": "r2_log_Qtot",
|
| 747 |
+
"multitask": 0.577,
|
| 748 |
+
"single_task_baseline": 0.571,
|
| 749 |
+
"delta": 0.006,
|
| 750 |
+
"transfer": "data_starved",
|
| 751 |
+
"n_train": 12,
|
| 752 |
+
"n_test": 4
|
| 753 |
+
},
|
| 754 |
+
"equil": {
|
| 755 |
+
"metric": "rel_l2_field",
|
| 756 |
+
"multitask": 0.009,
|
| 757 |
+
"single_task_baseline": 0.0117,
|
| 758 |
+
"delta": -0.0027,
|
| 759 |
+
"transfer": "positive",
|
| 760 |
+
"n_train": 600,
|
| 761 |
+
"n_test": 200
|
| 762 |
+
},
|
| 763 |
+
"state": {
|
| 764 |
+
"metric": "norm_rmse",
|
| 765 |
+
"multitask": 0.0239,
|
| 766 |
+
"single_task_baseline": 0.0224,
|
| 767 |
+
"delta": 0.0015,
|
| 768 |
+
"transfer": "neutral",
|
| 769 |
+
"n_train": 1500,
|
| 770 |
+
"n_test": 500
|
| 771 |
+
},
|
| 772 |
+
"disrupt": {
|
| 773 |
+
"metric": "roc_auc",
|
| 774 |
+
"multitask": 0.99,
|
| 775 |
+
"single_task_baseline": 0.993,
|
| 776 |
+
"delta": -0.003,
|
| 777 |
+
"transfer": "neutral",
|
| 778 |
+
"n_train": 443,
|
| 779 |
+
"n_test": 148
|
| 780 |
+
}
|
| 781 |
+
},
|
| 782 |
+
"positive_transfer_domains": [
|
| 783 |
+
"equil"
|
| 784 |
+
],
|
| 785 |
+
"negative_transfer_domains": [],
|
| 786 |
+
"neutral_transfer_domains": [
|
| 787 |
+
"state",
|
| 788 |
+
"disrupt"
|
| 789 |
+
],
|
| 790 |
+
"data_starved_domains": [
|
| 791 |
+
"transport"
|
| 792 |
+
],
|
| 793 |
+
"mc_dropout_predict_ms": 4.05,
|
| 794 |
+
"backend": "CPU, torch, MC-dropout UQ",
|
| 795 |
+
"verdict": "One shared trunk across 4 fusion domains, benchmarked head-by-head against a MATCHED single-task baseline on the same split. On the well-populated domains the shared representation is positive ['equil'], negative none, neutral ['state', 'disrupt'] \u2014 no negative transfer. ['transport'] is data-starved (16 pts) and not judged held-out. Trained on real on-disk data (CGYRO map / analytic equilibria / twin sensor snapshots / MAST shots) \u2014 an honest multi-task result, not a blanket win."
|
| 796 |
+
},
|
| 797 |
+
"caveats": [
|
| 798 |
+
"transport has only ~16 points, so its head is data-starved and high-variance (a real limit, reported not hidden)",
|
| 799 |
+
"uncertainty is an MC-dropout epistemic proxy, not a calibrated conformal interval",
|
| 800 |
+
"equilibrium targets are the analytic Solov'ev family (as in KORE); state targets are the analytic-twin sensor snapshots (as in KFLOW)"
|
| 801 |
+
]
|
| 802 |
+
}
|
| 803 |
+
},
|
| 804 |
+
"KMIT": {
|
| 805 |
+
"card": {
|
| 806 |
+
"name": "KMIT",
|
| 807 |
+
"function": "QMITIGATION",
|
| 808 |
+
"status": "BUILT",
|
| 809 |
+
"phase": 2,
|
| 810 |
+
"provenance": "SIM",
|
| 811 |
+
"retired_by": "fault-tolerant quantum hardware (not available this decade)",
|
| 812 |
+
"gates": [
|
| 813 |
+
"KX-L3"
|
| 814 |
+
],
|
| 815 |
+
"note": "REAL quantum error mitigation \u2014 zero-noise extrapolation (ZNE, unitary folding) + readout-error mitigation on a real fusion quantum circuit (the KQUBIT H2 VQE state). Mitigation is the genuine NISQ tool TODAY; it recovers signal from noise, not a speedup. Quantum's role in fusion is post-~2036",
|
| 816 |
+
"available": true
|
| 817 |
+
},
|
| 818 |
+
"benchmark": {
|
| 819 |
+
"member": "KMIT",
|
| 820 |
+
"live_error_mitigation": {
|
| 821 |
+
"problem": "mitigate a noisy H2 VQE expectation (the real KQUBIT circuit)",
|
| 822 |
+
"framework": "PennyLane default.mixed; ZNE via global unitary folding + linear extrapolation",
|
| 823 |
+
"zne": {
|
| 824 |
+
"exact_energy_Ha": -1.857275,
|
| 825 |
+
"ideal_noiseless_Ha": -1.857275,
|
| 826 |
+
"noisy_Ha": -1.812895,
|
| 827 |
+
"zne_mitigated_Ha": -1.852246,
|
| 828 |
+
"noise_scales_lambda": [
|
| 829 |
+
1.0,
|
| 830 |
+
3.0,
|
| 831 |
+
5.0
|
| 832 |
+
],
|
| 833 |
+
"energies_vs_lambda": [
|
| 834 |
+
-1.812895,
|
| 835 |
+
-1.725694,
|
| 836 |
+
-1.648692
|
| 837 |
+
],
|
| 838 |
+
"error_noisy_mHa": 44.38,
|
| 839 |
+
"error_zne_mHa": 5.029,
|
| 840 |
+
"error_reduction_frac": 0.887,
|
| 841 |
+
"depolarizing_p": 0.04,
|
| 842 |
+
"backend": {
|
| 843 |
+
"active_backend": "default",
|
| 844 |
+
"ran_on_real_hardware": false,
|
| 845 |
+
"how_to_use_real_qc": "set KODEX_QC_BACKEND=ibm and KODEX_QC_TOKEN=<your IBM Quantum token> to run this exact circuit on real quantum hardware",
|
| 846 |
+
"honest_timeline": "fault-tolerant quantum ADVANTAGE for fusion kernels is ~8-10 yr out \u2014 a meaningful role in fusion only after ~2036; this tooling makes the TESTING real and runnable TODAY, same code path"
|
| 847 |
+
}
|
| 848 |
+
},
|
| 849 |
+
"readout_mitigation": {
|
| 850 |
+
"readout_bitflip_p": 0.08,
|
| 851 |
+
"tv_distance_noisy": 0.1472,
|
| 852 |
+
"tv_distance_mitigated": 0.0,
|
| 853 |
+
"tv_reduction_frac": 1.0,
|
| 854 |
+
"method": "inverse confusion-matrix (linear) readout correction"
|
| 855 |
+
},
|
| 856 |
+
"backend": {
|
| 857 |
+
"active_backend": "default",
|
| 858 |
+
"ran_on_real_hardware": false,
|
| 859 |
+
"how_to_use_real_qc": "set KODEX_QC_BACKEND=ibm and KODEX_QC_TOKEN=<your IBM Quantum token> to run this exact circuit on real quantum hardware",
|
| 860 |
+
"honest_timeline": "fault-tolerant quantum ADVANTAGE for fusion kernels is ~8-10 yr out \u2014 a meaningful role in fusion only after ~2036; this tooling makes the TESTING real and runnable TODAY, same code path"
|
| 861 |
+
},
|
| 862 |
+
"verdict": "REAL error mitigation on a fusion quantum circuit: ZNE cuts the noisy-energy error 44.38 -> 5.029 mHa (89% of the error removed) and inverse-confusion readout correction cuts the measurement TV distance 0.1472 -> 0.0 (100%). Mitigation is the REAL NISQ tool today \u2014 it recovers signal from noise. HONEST: it is NOT a speedup; quantum's meaningful role in fusion is post-~2036, and mitigation cost grows with noise. Runs on real hardware with KODEX_QC_BACKEND=ibm."
|
| 863 |
+
},
|
| 864 |
+
"caveats": [
|
| 865 |
+
"no quantum advantage \u2014 quantum's role in fusion is post-~2036",
|
| 866 |
+
"ZNE assumes a smooth noise->observable relation; it extrapolates, it does not eliminate noise, and its overhead grows as noise grows",
|
| 867 |
+
"readout mitigation uses a known confusion matrix; on hardware you must calibrate it"
|
| 868 |
+
]
|
| 869 |
+
}
|
| 870 |
+
},
|
| 871 |
"KOIL": {
|
| 872 |
"card": {
|
| 873 |
"name": "KOIL",
|
|
|
|
| 920 |
"live_learned_surrogate": {
|
| 921 |
"rel_l2_vs_analytic": 0.0035,
|
| 922 |
"ensemble_cov90": 0.778,
|
| 923 |
+
"infer_ms": 0.318,
|
| 924 |
"grid": "16x16",
|
| 925 |
"n_heldout": 120
|
| 926 |
},
|
|
|
|
| 987 |
"gates": [
|
| 988 |
"KX-L3"
|
| 989 |
],
|
| 990 |
+
"note": "REAL quantum-kernel classifier \u2014 embeds real MAST disruption features into a quantum feature map and classifies on the fidelity kernel (PennyLane); runs on a simulator now, real hardware pluggable. Honest: ties the classical kernel \u2014 a validated no-advantage result, but a real, runnable quantum-ML pipeline; role in fusion post-~2036",
|
| 991 |
"available": true
|
| 992 |
},
|
| 993 |
"benchmark": {
|
|
|
|
| 1011 |
"active_backend": "default",
|
| 1012 |
"ran_on_real_hardware": false,
|
| 1013 |
"how_to_use_real_qc": "set KODEX_QC_BACKEND=ibm and KODEX_QC_TOKEN=<your IBM Quantum token> to run this exact circuit on real quantum hardware",
|
| 1014 |
+
"honest_timeline": "fault-tolerant quantum ADVANTAGE for fusion kernels is ~8-10 yr out \u2014 a meaningful role in fusion only after ~2036; this tooling makes the TESTING real and runnable TODAY, same code path"
|
| 1015 |
},
|
| 1016 |
"verdict": "REAL quantum kernel classifies MAST disruptions at AUC 0.919 vs classical RBF 0.929 (Delta -0.010) \u2014 no advantage: a validated null, but a REAL runnable quantum-ML pipeline on real fusion data. Runs on hardware with KODEX_QC_BACKEND=ibm.",
|
| 1017 |
"caveats": [
|
|
|
|
| 1036 |
"gates": [
|
| 1037 |
"KX-L3"
|
| 1038 |
],
|
| 1039 |
+
"note": "REAL QAOA quantum optimizer \u2014 solves a combinatorial design QUBO on an actual quantum circuit (PennyLane); runs on a simulator now, real hardware pluggable, and you can plug in your own QUBO. Honest: standard ~0.7-1.0 approx ratio, no speedup at this size (advantage post-~2036)",
|
| 1040 |
"available": true
|
| 1041 |
},
|
| 1042 |
"benchmark": {
|
|
|
|
| 1061 |
"active_backend": "default",
|
| 1062 |
"ran_on_real_hardware": false,
|
| 1063 |
"how_to_use_real_qc": "set KODEX_QC_BACKEND=ibm and KODEX_QC_TOKEN=<your IBM Quantum token> to run this exact circuit on real quantum hardware",
|
| 1064 |
+
"honest_timeline": "fault-tolerant quantum ADVANTAGE for fusion kernels is ~8-10 yr out \u2014 a meaningful role in fusion only after ~2036; this tooling makes the TESTING real and runnable TODAY, same code path"
|
| 1065 |
},
|
| 1066 |
"verdict": "REAL QAOA reaches 100% of the brute-force optimum (cut 6/6, p=2, 6 qubits) on the default backend \u2014 a working quantum optimizer, runnable on hardware with KODEX_QC_BACKEND=ibm. HONEST: no speedup vs classical at this size; advantage is ~8-10 yr out."
|
| 1067 |
},
|
|
|
|
| 1083 |
"AC-43",
|
| 1084 |
"BR-SX-08"
|
| 1085 |
],
|
| 1086 |
+
"note": "REAL fault-tolerant resource estimator \u2014 computes the classical<->quantum crossover N, the surface-code physical-qubit overhead, and the logical-qubit roadmap year for a fusion electronic-structure kernel (order-of-magnitude, literature-scaled). Verdict: no FT advantage this decade \u2014 the machine does not exist yet; meaningful role post-~2036",
|
| 1087 |
"available": true
|
| 1088 |
},
|
| 1089 |
"benchmark": {
|
|
|
|
| 1118 |
"AC-44",
|
| 1119 |
"KX-L3-A4"
|
| 1120 |
],
|
| 1121 |
+
"note": "REAL variational quantum eigensolver (VQE) for a molecular Hamiltonian \u2014 a runnable quantum program (PennyLane): executes on a simulator now and on real quantum hardware when you plug in a backend. Honest: no quantum advantage yet (~8-10 yr out); the tooling + testing are real TODAY \u2014 quantum's role in fusion is post-~2036",
|
| 1122 |
"available": true
|
| 1123 |
},
|
| 1124 |
"benchmark": {
|
|
|
|
| 1145 |
"active_backend": "default",
|
| 1146 |
"ran_on_real_hardware": false,
|
| 1147 |
"how_to_use_real_qc": "set KODEX_QC_BACKEND=ibm and KODEX_QC_TOKEN=<your IBM Quantum token> to run this exact circuit on real quantum hardware",
|
| 1148 |
+
"honest_timeline": "fault-tolerant quantum ADVANTAGE for fusion kernels is ~8-10 yr out \u2014 a meaningful role in fusion only after ~2036; this tooling makes the TESTING real and runnable TODAY, same code path"
|
| 1149 |
},
|
| 1150 |
"verdict": "REAL VQE recovers the H2 ground state to 0.0002 mHa on the default backend (within 1.6 mHa chemical accuracy). Runs on real quantum hardware when you set KODEX_QC_BACKEND=ibm. HONEST: no quantum advantage this decade \u2014 the value now is a real, testable quantum pipeline, not a speedup."
|
| 1151 |
},
|
|
|
|
| 1187 |
"caveat": "small seeding scan (few impurities); reduced 0-D radiation model"
|
| 1188 |
}
|
| 1189 |
},
|
| 1190 |
+
"KSCOUT": {
|
| 1191 |
+
"card": {
|
| 1192 |
+
"name": "KSCOUT",
|
| 1193 |
+
"function": "MF-CAMPAIGN",
|
| 1194 |
+
"status": "BUILT",
|
| 1195 |
+
"phase": 3,
|
| 1196 |
+
"provenance": "SIM",
|
| 1197 |
+
"retired_by": "the full multi-fidelity CGYRO campaign (twin + mu=400 + real-mass gold)",
|
| 1198 |
+
"gates": [
|
| 1199 |
+
"BR-L2-A1e"
|
| 1200 |
+
],
|
| 1201 |
+
"note": "multi-fidelity Bayesian-optimization campaign manager \u2014 extends KSEEK: chooses which operating point AND which fidelity (reduced twin / mu=400 CGYRO / real-mass gold) to run next, greedily maximizing truth-weighted information per GPU-hour under a budget",
|
| 1202 |
+
"available": true
|
| 1203 |
+
},
|
| 1204 |
+
"benchmark": {
|
| 1205 |
+
"member": "KSCOUT",
|
| 1206 |
+
"live_mf_campaign": {
|
| 1207 |
+
"source": "KYRO GP over the completed 16-pt CGYRO A1e map",
|
| 1208 |
+
"budget_gpu_h": 15.0,
|
| 1209 |
+
"target_hotspots": 16,
|
| 1210 |
+
"policy": "twin-triage every hotspot, escalate most-uncertain to mu=400, reserve gold",
|
| 1211 |
+
"fidelities": {
|
| 1212 |
+
"twin": {
|
| 1213 |
+
"gpu_h": 0.0,
|
| 1214 |
+
"rho": 0.55,
|
| 1215 |
+
"desc": "reduced analytic twin (near-free triage)"
|
| 1216 |
+
},
|
| 1217 |
+
"cgyro_mu400": {
|
| 1218 |
+
"gpu_h": 2.89,
|
| 1219 |
+
"rho": 0.9,
|
| 1220 |
+
"desc": "CGYRO representative mu=400 (measured GPU-h)"
|
| 1221 |
+
},
|
| 1222 |
+
"gold_mu3672": {
|
| 1223 |
+
"gpu_h": 28.9,
|
| 1224 |
+
"rho": 1.0,
|
| 1225 |
+
"desc": "CGYRO real-mass gold (est. ~10x mu=400; not yet run)"
|
| 1226 |
+
}
|
| 1227 |
+
},
|
| 1228 |
+
"multi_fidelity_plan": [
|
| 1229 |
+
{
|
| 1230 |
+
"a_LT": 3.25,
|
| 1231 |
+
"shear": 1.4,
|
| 1232 |
+
"fidelity": "cgyro_mu400",
|
| 1233 |
+
"gpu_h": 2.99,
|
| 1234 |
+
"gp_std": 0.5041,
|
| 1235 |
+
"truth_confidence_rho": 0.9
|
| 1236 |
+
},
|
| 1237 |
+
{
|
| 1238 |
+
"a_LT": 2.25,
|
| 1239 |
+
"shear": 1.4,
|
| 1240 |
+
"fidelity": "cgyro_mu400",
|
| 1241 |
+
"gpu_h": 2.99,
|
| 1242 |
+
"gp_std": 0.5041,
|
| 1243 |
+
"truth_confidence_rho": 0.9
|
| 1244 |
+
},
|
| 1245 |
+
{
|
| 1246 |
+
"a_LT": 3.25,
|
| 1247 |
+
"shear": 0.6,
|
| 1248 |
+
"fidelity": "cgyro_mu400",
|
| 1249 |
+
"gpu_h": 2.99,
|
| 1250 |
+
"gp_std": 0.5041,
|
| 1251 |
+
"truth_confidence_rho": 0.9
|
| 1252 |
+
},
|
| 1253 |
+
{
|
| 1254 |
+
"a_LT": 2.25,
|
| 1255 |
+
"shear": 0.6,
|
| 1256 |
+
"fidelity": "cgyro_mu400",
|
| 1257 |
+
"gpu_h": 2.99,
|
| 1258 |
+
"gp_std": 0.5041,
|
| 1259 |
+
"truth_confidence_rho": 0.9
|
| 1260 |
+
},
|
| 1261 |
+
{
|
| 1262 |
+
"a_LT": 3.25,
|
| 1263 |
+
"shear": 1.0,
|
| 1264 |
+
"fidelity": "twin",
|
| 1265 |
+
"gpu_h": 0.1,
|
| 1266 |
+
"gp_std": 0.4831,
|
| 1267 |
+
"truth_confidence_rho": 0.55
|
| 1268 |
+
},
|
| 1269 |
+
{
|
| 1270 |
+
"a_LT": 2.25,
|
| 1271 |
+
"shear": 1.0,
|
| 1272 |
+
"fidelity": "twin",
|
| 1273 |
+
"gpu_h": 0.1,
|
| 1274 |
+
"gp_std": 0.4831,
|
| 1275 |
+
"truth_confidence_rho": 0.55
|
| 1276 |
+
},
|
| 1277 |
+
{
|
| 1278 |
+
"a_LT": 2.75,
|
| 1279 |
+
"shear": 0.6,
|
| 1280 |
+
"fidelity": "twin",
|
| 1281 |
+
"gpu_h": 0.1,
|
| 1282 |
+
"gp_std": 0.4831,
|
| 1283 |
+
"truth_confidence_rho": 0.55
|
| 1284 |
+
},
|
| 1285 |
+
{
|
| 1286 |
+
"a_LT": 2.75,
|
| 1287 |
+
"shear": 1.4,
|
| 1288 |
+
"fidelity": "twin",
|
| 1289 |
+
"gpu_h": 0.1,
|
| 1290 |
+
"gp_std": 0.4831,
|
| 1291 |
+
"truth_confidence_rho": 0.55
|
| 1292 |
+
},
|
| 1293 |
+
{
|
| 1294 |
+
"a_LT": 2.75,
|
| 1295 |
+
"shear": 1.0,
|
| 1296 |
+
"fidelity": "twin",
|
| 1297 |
+
"gpu_h": 0.1,
|
| 1298 |
+
"gp_std": 0.4623,
|
| 1299 |
+
"truth_confidence_rho": 0.55
|
| 1300 |
+
},
|
| 1301 |
+
{
|
| 1302 |
+
"a_LT": 2.25,
|
| 1303 |
+
"shear": 0.4,
|
| 1304 |
+
"fidelity": "twin",
|
| 1305 |
+
"gpu_h": 0.1,
|
| 1306 |
+
"gp_std": 0.3838,
|
| 1307 |
+
"truth_confidence_rho": 0.55
|
| 1308 |
+
},
|
| 1309 |
+
{
|
| 1310 |
+
"a_LT": 2.25,
|
| 1311 |
+
"shear": 1.6,
|
| 1312 |
+
"fidelity": "twin",
|
| 1313 |
+
"gpu_h": 0.1,
|
| 1314 |
+
"gp_std": 0.3838,
|
| 1315 |
+
"truth_confidence_rho": 0.55
|
| 1316 |
+
},
|
| 1317 |
+
{
|
| 1318 |
+
"a_LT": 3.25,
|
| 1319 |
+
"shear": 1.6,
|
| 1320 |
+
"fidelity": "twin",
|
| 1321 |
+
"gpu_h": 0.1,
|
| 1322 |
+
"gp_std": 0.3838,
|
| 1323 |
+
"truth_confidence_rho": 0.55
|
| 1324 |
+
},
|
| 1325 |
+
{
|
| 1326 |
+
"a_LT": 3.25,
|
| 1327 |
+
"shear": 0.4,
|
| 1328 |
+
"fidelity": "twin",
|
| 1329 |
+
"gpu_h": 0.1,
|
| 1330 |
+
"gp_std": 0.3838,
|
| 1331 |
+
"truth_confidence_rho": 0.55
|
| 1332 |
+
},
|
| 1333 |
+
{
|
| 1334 |
+
"a_LT": 2.0,
|
| 1335 |
+
"shear": 1.4,
|
| 1336 |
+
"fidelity": "twin",
|
| 1337 |
+
"gpu_h": 0.1,
|
| 1338 |
+
"gp_std": 0.3838,
|
| 1339 |
+
"truth_confidence_rho": 0.55
|
| 1340 |
+
},
|
| 1341 |
+
{
|
| 1342 |
+
"a_LT": 3.5,
|
| 1343 |
+
"shear": 1.4,
|
| 1344 |
+
"fidelity": "twin",
|
| 1345 |
+
"gpu_h": 0.1,
|
| 1346 |
+
"gp_std": 0.3838,
|
| 1347 |
+
"truth_confidence_rho": 0.55
|
| 1348 |
+
},
|
| 1349 |
+
{
|
| 1350 |
+
"a_LT": 2.0,
|
| 1351 |
+
"shear": 0.6,
|
| 1352 |
+
"fidelity": "twin",
|
| 1353 |
+
"gpu_h": 0.1,
|
| 1354 |
+
"gp_std": 0.3838,
|
| 1355 |
+
"truth_confidence_rho": 0.55
|
| 1356 |
+
}
|
| 1357 |
+
],
|
| 1358 |
+
"mf_runs": 16,
|
| 1359 |
+
"mf_gpu_h_used": 13.56,
|
| 1360 |
+
"mf_runs_by_fidelity": {
|
| 1361 |
+
"twin": 12,
|
| 1362 |
+
"cgyro_mu400": 4,
|
| 1363 |
+
"gold_mu3672": 0
|
| 1364 |
+
},
|
| 1365 |
+
"mf_mean_confidence_rho": 0.638,
|
| 1366 |
+
"baseline_all_mu400": {
|
| 1367 |
+
"n_runs": 5,
|
| 1368 |
+
"gpu_h_used": 14.95,
|
| 1369 |
+
"mean_confidence_rho": 0.281,
|
| 1370 |
+
"unvisited_hotspots": 11
|
| 1371 |
+
},
|
| 1372 |
+
"mf_confidence_gain_x_vs_all_mu400": 2.27,
|
| 1373 |
+
"verdict": "Under a tight 15.0 GPU-h budget across 16 uncertain operating points, the multi-fidelity policy triages ALL 16 with cheap twin runs and escalates 4 to mu=400 (0 to real-mass gold), reaching mean truth-confidence rho 0.638 \u2014 vs 0.281 for a naive all-mu=400 plan that exhausts the budget after 5 points and leaves 11 hotspots unexamined (2.27x). A real cost-aware campaign manager: look everywhere cheaply, spend the expensive fidelity where KYRO is least sure."
|
| 1374 |
+
},
|
| 1375 |
+
"caveats": [
|
| 1376 |
+
"the per-fidelity rho (correlation-with-truth) values are ASSUMPTIONS \u2014 the real-mass gold has not been run \u2014 so this is a planning heuristic, not a measured speedup; the advantage holds only while budget < hotspots x mu=400 cost",
|
| 1377 |
+
"GP std comes from only 16 points (directional, like KSEEK)",
|
| 1378 |
+
"GPU-hours only; no compute-cost figures (product-econ rule)"
|
| 1379 |
+
]
|
| 1380 |
+
}
|
| 1381 |
+
},
|
| 1382 |
"KSEEK": {
|
| 1383 |
"card": {
|
| 1384 |
"name": "KSEEK",
|
|
|
|
| 1433 |
"gates": [
|
| 1434 |
"HX-29"
|
| 1435 |
],
|
| 1436 |
+
"note": "REAL quantum-metrology evaluation (PennyLane mixed-state) \u2014 GHZ interferometry: ideal gives Heisenberg (gain ~ N) scaling, but realistic dephasing (NV/SQUID/SERF reality) collapses it back to the standard quantum limit (~sqrt(N)). Honest null where fusion disruptions live; quantum's role in fusion is post-~2036",
|
| 1437 |
"available": true
|
| 1438 |
},
|
| 1439 |
"benchmark": {
|
|
|
|
| 1502 |
"active_backend": "default",
|
| 1503 |
"ran_on_real_hardware": false,
|
| 1504 |
"how_to_use_real_qc": "set KODEX_QC_BACKEND=ibm and KODEX_QC_TOKEN=<your IBM Quantum token> to run this exact circuit on real quantum hardware",
|
| 1505 |
+
"honest_timeline": "fault-tolerant quantum ADVANTAGE for fusion kernels is ~8-10 yr out \u2014 a meaningful role in fusion only after ~2036; this tooling makes the TESTING real and runnable TODAY, same code path"
|
| 1506 |
},
|
| 1507 |
"verdict": "REAL quantum-metrology computation: over N=2->8 the ideal GHZ gain grows 4.0x (Heisenberg ~ N), but with per-qubit dephasing (p=0.2) the dephased GHZ grows only 2.05x \u2014 essentially the SQL rate (2.01x, ~sqrt(N)). Dephasing ERASES the Heisenberg *scaling* to a bounded constant (gain turns over near N~9). HONEST NULL: no quantum-sensing advantage for fusion disruptions this decade \u2014 but a real, runnable metrology tool."
|
| 1508 |
},
|
|
|
|
| 1523 |
"gates": [
|
| 1524 |
"KX-L3"
|
| 1525 |
],
|
| 1526 |
+
"note": "tensor-network / low-rank ROM compression of the real CGYRO A1e flux database (classical MPS-style SVD; a many-body method and bridge to quantum kernels \u2014 NO quantum-advantage claim; quantum's role in fusion is post-~2036)",
|
| 1527 |
"available": true
|
| 1528 |
},
|
| 1529 |
"benchmark": {
|
|
|
|
| 1674 |
"map": "12 turbulent / 4 quiet (16/16 complete)"
|
| 1675 |
},
|
| 1676 |
"speed": {
|
| 1677 |
+
"surrogate_ms_per_point": 0.257,
|
| 1678 |
"cgyro_gpu_h_per_point_measured": 2.89,
|
| 1679 |
+
"speedup_x_vs_cgyro": "4.1e+07",
|
| 1680 |
"speedup_note": "ms inference vs GPU-hours for the CONVERGED flux value",
|
| 1681 |
"fidelity": "representative mu=400; real-mass gold deferred"
|
| 1682 |
},
|
benchmarks/run_all.py
CHANGED
|
@@ -181,6 +181,31 @@ def _headline(name, b):
|
|
| 181 |
r = b.get("live_impurity_seeding", {})
|
| 182 |
return (f"impurity-seeding radiation evaluator: {r.get('n_impurities')} impurities "
|
| 183 |
f"({', '.join(r.get('impurities', []))}); least core dilution = {r.get('least_core_dilution_impurity')}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 184 |
return b.get("note", b.get("headline", "roadmap"))
|
| 185 |
|
| 186 |
|
|
|
|
| 181 |
r = b.get("live_impurity_seeding", {})
|
| 182 |
return (f"impurity-seeding radiation evaluator: {r.get('n_impurities')} impurities "
|
| 183 |
f"({', '.join(r.get('impurities', []))}); least core dilution = {r.get('least_core_dilution_impurity')}")
|
| 184 |
+
if name == "KMIND":
|
| 185 |
+
lf = b.get("live_foundation", {})
|
| 186 |
+
pos = lf.get("positive_transfer_domains", []); neg = lf.get("negative_transfer_domains", [])
|
| 187 |
+
neu = lf.get("neutral_transfer_domains", []); st = lf.get("data_starved_domains", [])
|
| 188 |
+
return (f"**foundation model**: one shared trunk across {len(lf.get('domains', []))} domains "
|
| 189 |
+
f"({lf.get('params', '?')} params); transfer vs matched single-task — pos {pos or 'none'}, "
|
| 190 |
+
f"neg {neg or 'none'}, neutral {neu or 'none'}"
|
| 191 |
+
+ (" (transport data-starved)" if st else "") + " — honest multi-task result")
|
| 192 |
+
if name == "KMIT":
|
| 193 |
+
m = b.get("live_error_mitigation", {}); z = m.get("zne", {}); ro = m.get("readout_mitigation", {})
|
| 194 |
+
return (f"**REAL error mitigation**: ZNE cuts H2 energy error {z.get('error_noisy_mHa')}→"
|
| 195 |
+
f"{z.get('error_zne_mHa')} mHa ({z.get('error_reduction_frac')} removed); readout TV "
|
| 196 |
+
f"{ro.get('tv_distance_noisy')}→{ro.get('tv_distance_mitigated')} — real NISQ tool today, "
|
| 197 |
+
f"role post-~2036")
|
| 198 |
+
if name == "KLINQ":
|
| 199 |
+
q = b.get("live_quantum_linear_solver", {}); hhl = q.get("ft_hhl_resource_estimate", {})
|
| 200 |
+
return (f"**REAL quantum linear solver** (VQLS): 4×4 reduced-MHD solve fidelity "
|
| 201 |
+
f"{q.get('solution_fidelity_vs_classical')} vs classical (rel-resid {q.get('residual_rel')}); "
|
| 202 |
+
f"FT-HHL {hhl.get('physical_qubits_needed')} phys qubits — no advantage, role post-~2036")
|
| 203 |
+
if name == "KSCOUT":
|
| 204 |
+
c = b.get("live_mf_campaign", {}); base = c.get("baseline_all_mu400", {})
|
| 205 |
+
return (f"**multi-fidelity campaign**: tight {c.get('budget_gpu_h')} GPU-h over "
|
| 206 |
+
f"{c.get('target_hotspots')} hotspots → mean confidence ρ {c.get('mf_mean_confidence_rho')} "
|
| 207 |
+
f"vs {base.get('mean_confidence_rho')} all-μ=400 "
|
| 208 |
+
f"({c.get('mf_confidence_gain_x_vs_all_mu400')}×); triage-then-escalate")
|
| 209 |
return b.get("note", b.get("headline", "roadmap"))
|
| 210 |
|
| 211 |
|
codemeta.json
CHANGED
|
@@ -2,8 +2,8 @@
|
|
| 2 |
"@context": "https://doi.org/10.5063/schema/codemeta-2.0",
|
| 3 |
"@type": "SoftwareSourceCode",
|
| 4 |
"name": "KODEX: the Kronos Family of Codes",
|
| 5 |
-
"version": "0.
|
| 6 |
-
"dateModified": "2026-09-
|
| 7 |
"license": "https://spdx.org/licenses/Apache-2.0",
|
| 8 |
"codeRepository": "https://github.com/KronosFE/kronos-ml",
|
| 9 |
"url": "https://kronosfusionenergy.com/kodex",
|
|
|
|
| 2 |
"@context": "https://doi.org/10.5063/schema/codemeta-2.0",
|
| 3 |
"@type": "SoftwareSourceCode",
|
| 4 |
"name": "KODEX: the Kronos Family of Codes",
|
| 5 |
+
"version": "0.3.0",
|
| 6 |
+
"dateModified": "2026-09-29",
|
| 7 |
"license": "https://spdx.org/licenses/Apache-2.0",
|
| 8 |
"codeRepository": "https://github.com/KronosFE/kronos-ml",
|
| 9 |
"url": "https://kronosfusionenergy.com/kodex",
|
kronos_ml/members/__init__.py
CHANGED
|
@@ -16,3 +16,5 @@ from . import advanced # noqa: F401 KLAW, KDRIVE, KGEN, KFUEL
|
|
| 16 |
from . import capstone # noqa: F401 KFORGE, KPILOT
|
| 17 |
from . import neutronics # noqa: F401 KBREED, KFLUX
|
| 18 |
from . import roadmap # noqa: F401 KHEAT, KEDGE, KRAD, KECON
|
|
|
|
|
|
|
|
|
| 16 |
from . import capstone # noqa: F401 KFORGE, KPILOT
|
| 17 |
from . import neutronics # noqa: F401 KBREED, KFLUX
|
| 18 |
from . import roadmap # noqa: F401 KHEAT, KEDGE, KRAD, KECON
|
| 19 |
+
from . import foundation # noqa: F401 KMIND (v0.3.0)
|
| 20 |
+
from . import quantum_v3 # noqa: F401 KMIT, KLINQ (v0.3.0)
|
kronos_ml/members/advanced.py
CHANGED
|
@@ -358,3 +358,136 @@ class KBENCH(Surrogate):
|
|
| 358 |
"ROM) with real on-disk data + reproducible KODEX baselines — a community "
|
| 359 |
"leaderboard starting point, not a private result")},
|
| 360 |
"caveat": "small by mainstream-ML standards (CGYRO = 16 pts); honest pilot fusion-ML benchmarks"}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 358 |
"ROM) with real on-disk data + reproducible KODEX baselines — a community "
|
| 359 |
"leaderboard starting point, not a private result")},
|
| 360 |
"caveat": "small by mainstream-ML standards (CGYRO = 16 pts); honest pilot fusion-ML benchmarks"}
|
| 361 |
+
|
| 362 |
+
|
| 363 |
+
# ------------------------------------------------------------------ KSCOUT
|
| 364 |
+
@register
|
| 365 |
+
class KSCOUT(Surrogate):
|
| 366 |
+
name = "KSCOUT"; function = "MF-CAMPAIGN"; phase = 3; status = "BUILT"
|
| 367 |
+
provenance = "SIM"
|
| 368 |
+
retired_by = "the full multi-fidelity CGYRO campaign (twin + mu=400 + real-mass gold)"
|
| 369 |
+
real_codes = ("multi-fidelity Bayesian optimization", "cost-aware acquisition")
|
| 370 |
+
gates = ("BR-L2-A1e",)
|
| 371 |
+
note = ("multi-fidelity Bayesian-optimization campaign manager — extends KSEEK: chooses which "
|
| 372 |
+
"operating point AND which fidelity (reduced twin / mu=400 CGYRO / real-mass gold) to "
|
| 373 |
+
"run next, greedily maximizing truth-weighted information per GPU-hour under a budget")
|
| 374 |
+
|
| 375 |
+
_BOX = ((2.0, 3.5), (0.4, 1.6)) # a_LT, shear (matches KYRO / KSEEK)
|
| 376 |
+
_C0 = 0.10 # fixed per-run setup overhead (GPU-h equiv.)
|
| 377 |
+
_HOTSPOTS = 16 # target uncertain locations for a campaign
|
| 378 |
+
# honest fidelity model: measured mu=400 cost; twin ~free; gold ~10x mu=400 (estimate, not yet run).
|
| 379 |
+
# rho = ASSUMED correlation-with-truth per fidelity (gold=1 by definition); labelled as assumptions.
|
| 380 |
+
_FIDELITIES = {
|
| 381 |
+
"twin": {"gpu_h": 0.0, "rho": 0.55, "desc": "reduced analytic twin (near-free triage)"},
|
| 382 |
+
"cgyro_mu400": {"gpu_h": 2.89, "rho": 0.90, "desc": "CGYRO representative mu=400 (measured GPU-h)"},
|
| 383 |
+
"gold_mu3672": {"gpu_h": 28.9, "rho": 1.00, "desc": "CGYRO real-mass gold (est. ~10x mu=400; not yet run)"},
|
| 384 |
+
}
|
| 385 |
+
|
| 386 |
+
def _grid(self, n=31):
|
| 387 |
+
a = np.linspace(*self._BOX[0], n); s = np.linspace(*self._BOX[1], n)
|
| 388 |
+
A, S = np.meshgrid(a, s)
|
| 389 |
+
return np.c_[A.ravel(), S.ravel()]
|
| 390 |
+
|
| 391 |
+
def _hotspots(self, n_hotspots, min_sep=0.16):
|
| 392 |
+
"""The n most-uncertain operating points (KYRO GP std), min-separated + away from data."""
|
| 393 |
+
gp = get("KYRO")._fit()
|
| 394 |
+
G = self._grid()
|
| 395 |
+
_, std = gp.predict(G); std = np.asarray(std).ravel()
|
| 396 |
+
Xtr = data.cgyro_flux_map_final()[["a_LT", "shear"]].to_numpy(float)
|
| 397 |
+
span = np.array([self._BOX[0][1] - self._BOX[0][0], self._BOX[1][1] - self._BOX[1][0]])
|
| 398 |
+
picks = []
|
| 399 |
+
for idx in np.argsort(-std):
|
| 400 |
+
g = G[idx]
|
| 401 |
+
d_tr = np.linalg.norm((g - Xtr) / span, axis=1).min()
|
| 402 |
+
d_ch = min([np.linalg.norm((g - c[0]) / span) for c in picks], default=9.0)
|
| 403 |
+
if min(d_tr, d_ch) < min_sep:
|
| 404 |
+
continue
|
| 405 |
+
picks.append((g, float(std[idx])))
|
| 406 |
+
if len(picks) >= n_hotspots:
|
| 407 |
+
break
|
| 408 |
+
return picks
|
| 409 |
+
|
| 410 |
+
def _cost(self, fid):
|
| 411 |
+
return self._FIDELITIES[fid]["gpu_h"] + self._C0
|
| 412 |
+
|
| 413 |
+
def _plan(self, budget, n_hotspots=None):
|
| 414 |
+
"""Triage-and-escalate: twin-triage every hotspot, then escalate the most-uncertain to
|
| 415 |
+
mu=400, then the single most-critical to real-mass gold — all within the GPU-h budget."""
|
| 416 |
+
n_hotspots = n_hotspots or self._HOTSPOTS
|
| 417 |
+
hs = self._hotspots(n_hotspots) # sorted by std desc
|
| 418 |
+
c_t, c_m, c_g = (self._cost("twin"), self._cost("cgyro_mu400"), self._cost("gold_mu3672"))
|
| 419 |
+
tiers = [None] * len(hs); used = 0.0
|
| 420 |
+
# tier 1 — cheap twin triage on as many hotspots as the budget allows (highest std first)
|
| 421 |
+
for i in range(len(hs)):
|
| 422 |
+
if used + c_t <= budget + 1e-9:
|
| 423 |
+
tiers[i] = "twin"; used += c_t
|
| 424 |
+
# tier 2 — escalate the single most-uncertain to real-mass gold if affordable
|
| 425 |
+
if tiers and tiers[0] == "twin" and used + c_g <= budget + 1e-9:
|
| 426 |
+
tiers[0] = "gold_mu3672"; used += c_g
|
| 427 |
+
# tier 3 — escalate the next most-uncertain to mu=400 while budget remains
|
| 428 |
+
for i in range(len(hs)):
|
| 429 |
+
if tiers[i] == "twin" and used + c_m <= budget + 1e-9:
|
| 430 |
+
tiers[i] = "cgyro_mu400"; used += c_m
|
| 431 |
+
plan = []
|
| 432 |
+
for (g, s), tier in zip(hs, tiers):
|
| 433 |
+
if tier is None:
|
| 434 |
+
continue
|
| 435 |
+
plan.append({"a_LT": round(float(g[0]), 3), "shear": round(float(g[1]), 3),
|
| 436 |
+
"fidelity": tier, "gpu_h": round(self._cost(tier), 2),
|
| 437 |
+
"gp_std": round(float(s), 4),
|
| 438 |
+
"truth_confidence_rho": self._FIDELITIES[tier]["rho"]})
|
| 439 |
+
return plan, round(used, 2), hs
|
| 440 |
+
|
| 441 |
+
def _mean_confidence(self, plan, n_hotspots):
|
| 442 |
+
"""Mean truth-confidence (rho) achieved across ALL target hotspots (unvisited = 0)."""
|
| 443 |
+
return round(sum(p["truth_confidence_rho"] for p in plan) / n_hotspots, 3)
|
| 444 |
+
|
| 445 |
+
def _baseline_all_mu400(self, budget, n_hotspots):
|
| 446 |
+
"""Naive baseline: spend the whole budget at mu=400 on the highest-std hotspots."""
|
| 447 |
+
c_m = self._cost("cgyro_mu400")
|
| 448 |
+
n = min(n_hotspots, int((budget + 1e-9) // c_m))
|
| 449 |
+
return {"n_runs": n, "gpu_h_used": round(n * c_m, 2),
|
| 450 |
+
"mean_confidence_rho": round(n * self._FIDELITIES["cgyro_mu400"]["rho"] / n_hotspots, 3),
|
| 451 |
+
"unvisited_hotspots": n_hotspots - n}
|
| 452 |
+
|
| 453 |
+
def _predict(self, x):
|
| 454 |
+
"""x = GPU-hour budget (float) -> the recommended multi-fidelity campaign plan."""
|
| 455 |
+
budget = float(np.ravel(np.asarray(x, float))[0]) if x is not None else 15.0
|
| 456 |
+
plan, used, _ = self._plan(budget)
|
| 457 |
+
by_fid = {f: sum(1 for p in plan if p["fidelity"] == f) for f in self._FIDELITIES}
|
| 458 |
+
return Prediction(plan, None, True,
|
| 459 |
+
note=f"multi-fidelity campaign: {len(plan)} runs {by_fid}, {used} GPU-h of {budget}")
|
| 460 |
+
|
| 461 |
+
def benchmark(self):
|
| 462 |
+
budget = 15.0 # tight budget: mu=400 can't cover every hotspot
|
| 463 |
+
n = self._HOTSPOTS
|
| 464 |
+
plan, used, hs = self._plan(budget, n)
|
| 465 |
+
by_fid = {f: sum(1 for p in plan if p["fidelity"] == f) for f in self._FIDELITIES}
|
| 466 |
+
mf_conf = self._mean_confidence(plan, n)
|
| 467 |
+
base = self._baseline_all_mu400(budget, n)
|
| 468 |
+
ratio = round(mf_conf / base["mean_confidence_rho"], 2) if base["mean_confidence_rho"] > 1e-9 else None
|
| 469 |
+
return {"member": self.name,
|
| 470 |
+
"live_mf_campaign": {
|
| 471 |
+
"source": "KYRO GP over the completed 16-pt CGYRO A1e map",
|
| 472 |
+
"budget_gpu_h": budget, "target_hotspots": n,
|
| 473 |
+
"policy": "twin-triage every hotspot, escalate most-uncertain to mu=400, reserve gold",
|
| 474 |
+
"fidelities": {k: {kk: v[kk] for kk in ("gpu_h", "rho", "desc")}
|
| 475 |
+
for k, v in self._FIDELITIES.items()},
|
| 476 |
+
"multi_fidelity_plan": plan,
|
| 477 |
+
"mf_runs": len(plan), "mf_gpu_h_used": used, "mf_runs_by_fidelity": by_fid,
|
| 478 |
+
"mf_mean_confidence_rho": mf_conf,
|
| 479 |
+
"baseline_all_mu400": base,
|
| 480 |
+
"mf_confidence_gain_x_vs_all_mu400": ratio,
|
| 481 |
+
"verdict": (f"Under a tight {budget} GPU-h budget across {n} uncertain operating points, the "
|
| 482 |
+
f"multi-fidelity policy triages ALL {n} with cheap twin runs and escalates "
|
| 483 |
+
f"{by_fid['cgyro_mu400']} to mu=400 ({by_fid['gold_mu3672']} to real-mass gold), "
|
| 484 |
+
f"reaching mean truth-confidence rho {mf_conf} — vs {base['mean_confidence_rho']} "
|
| 485 |
+
f"for a naive all-mu=400 plan that exhausts the budget after {base['n_runs']} "
|
| 486 |
+
f"points and leaves {base['unvisited_hotspots']} hotspots unexamined ({ratio}x). "
|
| 487 |
+
f"A real cost-aware campaign manager: look everywhere cheaply, spend the "
|
| 488 |
+
f"expensive fidelity where KYRO is least sure.")},
|
| 489 |
+
"caveats": ["the per-fidelity rho (correlation-with-truth) values are ASSUMPTIONS — the "
|
| 490 |
+
"real-mass gold has not been run — so this is a planning heuristic, not a "
|
| 491 |
+
"measured speedup; the advantage holds only while budget < hotspots x mu=400 cost",
|
| 492 |
+
"GP std comes from only 16 points (directional, like KSEEK)",
|
| 493 |
+
"GPU-hours only; no compute-cost figures (product-econ rule)"]}
|
kronos_ml/members/foundation.py
ADDED
|
@@ -0,0 +1,333 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""KMIND — whole-device foundation surrogate (shared-trunk multi-task model).
|
| 2 |
+
|
| 3 |
+
ONE shared plasma-state trunk feeds four domain heads — transport (KYRO),
|
| 4 |
+
equilibrium (KORE), state (KFLOW) and disruption (KWARD) — trained JOINTLY on the
|
| 5 |
+
on-disk data those specialists use. Per-domain input adapters project each
|
| 6 |
+
domain's heterogeneous inputs into a common embedding; the shared trunk learns a
|
| 7 |
+
representation every head reads; per-domain heads emit the domain output.
|
| 8 |
+
|
| 9 |
+
The honest question a foundation model has to answer: does forcing four fusion
|
| 10 |
+
sub-problems through ONE shared representation help or hurt each of them vs a
|
| 11 |
+
matched single-task specialist? `benchmark()` trains the multi-task model AND a
|
| 12 |
+
matched single-task baseline per domain on the SAME split and reports the
|
| 13 |
+
transfer — positive OR negative — in each domain's own metric. No hype: a shared
|
| 14 |
+
representation that hurts a task is reported as hurting it.
|
| 15 |
+
|
| 16 |
+
CPU-only, deterministic (fixed seed), torch (lazy import). Uncertainty is an
|
| 17 |
+
MC-dropout epistemic proxy; the per-domain in_domain gate is a Mahalanobis
|
| 18 |
+
distance to that domain's training inputs.
|
| 19 |
+
"""
|
| 20 |
+
from __future__ import annotations
|
| 21 |
+
|
| 22 |
+
import time
|
| 23 |
+
import numpy as np
|
| 24 |
+
|
| 25 |
+
from .. import register, get
|
| 26 |
+
from ..base import Surrogate, Prediction
|
| 27 |
+
from .. import uq, metrics, data
|
| 28 |
+
from .._torch import torch
|
| 29 |
+
from .equil import _field, _A, _K, _D
|
| 30 |
+
|
| 31 |
+
_D_EMB = 32 # shared embedding width (adapter output)
|
| 32 |
+
_H = 128 # shared trunk width
|
| 33 |
+
_DROP = 0.1 # dropout (also the MC-dropout head)
|
| 34 |
+
_STEPS = 300 # joint / baseline training steps (same for fairness)
|
| 35 |
+
_BATCH = 64
|
| 36 |
+
_MC = 30 # MC-dropout passes for predictive std
|
| 37 |
+
_DOMAINS = ("transport", "equil", "state", "disrupt")
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
# ---- per-domain data builders (all read-only, on-disk) -------------------
|
| 41 |
+
|
| 42 |
+
def _transport_xy():
|
| 43 |
+
df = data.cgyro_flux_map_final()
|
| 44 |
+
X = df[["a_LT", "shear"]].to_numpy(float)
|
| 45 |
+
y = np.log10(np.clip(df.Q_tot.to_numpy(float), 0, None) + 1e-4).reshape(-1, 1)
|
| 46 |
+
return X, y
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
def _equil_xy(n=800, seed=uq.SEED):
|
| 50 |
+
rng = np.random.default_rng(seed)
|
| 51 |
+
P = np.c_[rng.uniform(*_A, n), rng.uniform(*_K, n), rng.uniform(*_D, n)]
|
| 52 |
+
Y = np.array([_field(*p) for p in P], float)
|
| 53 |
+
return P.astype(float), Y
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
def _state_xy(n=2000, seed=uq.SEED):
|
| 57 |
+
z = data.gnn_snapshots()
|
| 58 |
+
Xobs = np.nan_to_num(np.asarray(z["Xn_obs"], float))
|
| 59 |
+
Yclean = np.nan_to_num(np.asarray(z["Xn_clean"], float))
|
| 60 |
+
if len(Xobs) > n: # deterministic subsample for speed
|
| 61 |
+
idx = np.random.default_rng(seed).choice(len(Xobs), n, replace=False)
|
| 62 |
+
Xobs, Yclean = Xobs[idx], Yclean[idx]
|
| 63 |
+
return Xobs, Yclean
|
| 64 |
+
|
| 65 |
+
|
| 66 |
+
def _disrupt_xy():
|
| 67 |
+
X, y, _ = get("KWARD")._real_features()
|
| 68 |
+
return np.asarray(X, float), np.asarray(y, int).reshape(-1, 1)
|
| 69 |
+
|
| 70 |
+
|
| 71 |
+
_BUILDERS = {"transport": _transport_xy, "equil": _equil_xy,
|
| 72 |
+
"state": _state_xy, "disrupt": _disrupt_xy}
|
| 73 |
+
_KIND = {"transport": "reg", "equil": "reg", "state": "reg", "disrupt": "cls"}
|
| 74 |
+
# physical in-domain boxes for the low-D parametric domains (match KYRO / KORE);
|
| 75 |
+
# the high-D domains (state, disrupt) use a Mahalanobis gate on training inputs
|
| 76 |
+
_BOX = {"transport": ((2.0, 3.5), (0.4, 1.6)),
|
| 77 |
+
"equil": ((0.8, 1.2), (1.5, 2.5), (-0.5, 0.5))}
|
| 78 |
+
|
| 79 |
+
|
| 80 |
+
def _spec(name, test_frac=0.25, seed=uq.SEED):
|
| 81 |
+
"""Build a domain spec: standardized train/test tensors + inversion stats + gate."""
|
| 82 |
+
X, Y = _BUILDERS[name]()
|
| 83 |
+
n = len(X)
|
| 84 |
+
rng = np.random.default_rng(seed + hash(name) % 1000)
|
| 85 |
+
perm = rng.permutation(n)
|
| 86 |
+
nte = max(2, int(round(test_frac * n)))
|
| 87 |
+
te, tr = perm[:nte], perm[nte:]
|
| 88 |
+
Xtr, Xte, Ytr, Yte = X[tr], X[te], Y[tr], Y[te]
|
| 89 |
+
xmu, xsd = Xtr.mean(0), Xtr.std(0) + 1e-8
|
| 90 |
+
kind = _KIND[name]
|
| 91 |
+
if kind == "reg":
|
| 92 |
+
ymu, ysd = Ytr.mean(0), Ytr.std(0) + 1e-8
|
| 93 |
+
else:
|
| 94 |
+
ymu, ysd = np.zeros(Y.shape[1]), np.ones(Y.shape[1]) # raw {0,1} labels
|
| 95 |
+
gate = None if name in _BOX else uq.MahalanobisGate(0.05).fit(Xtr)
|
| 96 |
+
return {"name": name, "kind": kind, "in_dim": X.shape[1], "out_dim": Y.shape[1],
|
| 97 |
+
"Xtr": Xtr, "Xte": Xte, "Ytr": Ytr, "Yte": Yte,
|
| 98 |
+
"xmu": xmu, "xsd": xsd, "ymu": ymu, "ysd": ysd, "gate": gate, "n": n}
|
| 99 |
+
|
| 100 |
+
|
| 101 |
+
def _in_domain(sp, x_raw):
|
| 102 |
+
"""Per-domain trust gate, queried on RAW inputs: a physical box for the low-D
|
| 103 |
+
parametric domains (transport/equil), Mahalanobis distance for the rest."""
|
| 104 |
+
x = np.asarray(x_raw, float).ravel()
|
| 105 |
+
if sp["name"] in _BOX:
|
| 106 |
+
b = _BOX[sp["name"]]
|
| 107 |
+
return bool(len(x) >= len(b) and all(lo <= x[i] <= hi for i, (lo, hi) in enumerate(b)))
|
| 108 |
+
return bool(sp["gate"].in_domain(x.reshape(1, -1)))
|
| 109 |
+
|
| 110 |
+
|
| 111 |
+
def _stdx(sp, X):
|
| 112 |
+
return ((np.atleast_2d(np.asarray(X, float)) - sp["xmu"]) / sp["xsd"]).astype("float32")
|
| 113 |
+
|
| 114 |
+
|
| 115 |
+
def _stdy(sp, Y):
|
| 116 |
+
return ((np.asarray(Y, float) - sp["ymu"]) / sp["ysd"]).astype("float32")
|
| 117 |
+
|
| 118 |
+
|
| 119 |
+
def _invy(sp, Yn):
|
| 120 |
+
return np.asarray(Yn, float) * sp["ysd"] + sp["ymu"]
|
| 121 |
+
|
| 122 |
+
|
| 123 |
+
# ---- the shared-trunk multi-task network ---------------------------------
|
| 124 |
+
|
| 125 |
+
def _build_net(specs, seed=uq.SEED):
|
| 126 |
+
t = torch(); t.set_num_threads(1); t.manual_seed(seed) # single-thread -> reproducible
|
| 127 |
+
nn = t.nn
|
| 128 |
+
|
| 129 |
+
class MultiTask(nn.Module):
|
| 130 |
+
def __init__(self):
|
| 131 |
+
super().__init__()
|
| 132 |
+
self.adapters = nn.ModuleDict({
|
| 133 |
+
s["name"]: nn.Sequential(nn.Linear(s["in_dim"], _D_EMB), nn.SiLU())
|
| 134 |
+
for s in specs})
|
| 135 |
+
self.trunk = nn.Sequential(
|
| 136 |
+
nn.Linear(_D_EMB, _H), nn.SiLU(), nn.Dropout(_DROP),
|
| 137 |
+
nn.Linear(_H, _H), nn.SiLU(), nn.Dropout(_DROP))
|
| 138 |
+
self.heads = nn.ModuleDict({
|
| 139 |
+
s["name"]: nn.Linear(_H, s["out_dim"]) for s in specs})
|
| 140 |
+
|
| 141 |
+
def forward(self, name, x):
|
| 142 |
+
return self.heads[name](self.trunk(self.adapters[name](x)))
|
| 143 |
+
|
| 144 |
+
return MultiTask()
|
| 145 |
+
|
| 146 |
+
|
| 147 |
+
def _train(net, specs, steps=_STEPS, seed=uq.SEED):
|
| 148 |
+
t = torch(); nn = t.nn
|
| 149 |
+
opt = t.optim.Adam(net.parameters(), lr=3e-3)
|
| 150 |
+
mse = nn.MSELoss(); bce = nn.BCEWithLogitsLoss()
|
| 151 |
+
rng = np.random.default_rng(seed)
|
| 152 |
+
# pre-tensor the standardized train sets
|
| 153 |
+
packs = []
|
| 154 |
+
for sp in specs:
|
| 155 |
+
Xn = t.tensor(_stdx(sp, sp["Xtr"]))
|
| 156 |
+
Yn = t.tensor(_stdy(sp, sp["Ytr"]))
|
| 157 |
+
packs.append((sp, Xn, Yn))
|
| 158 |
+
net.train()
|
| 159 |
+
for _ in range(steps):
|
| 160 |
+
opt.zero_grad(); loss = 0.0
|
| 161 |
+
for sp, Xn, Yn in packs:
|
| 162 |
+
m = len(Xn); b = min(_BATCH, m)
|
| 163 |
+
idx = t.tensor(rng.choice(m, b, replace=False))
|
| 164 |
+
out = net(sp["name"], Xn[idx])
|
| 165 |
+
loss = loss + (bce(out, Yn[idx]) if sp["kind"] == "cls"
|
| 166 |
+
else mse(out, Yn[idx]))
|
| 167 |
+
loss.backward(); opt.step()
|
| 168 |
+
net.eval()
|
| 169 |
+
return net
|
| 170 |
+
|
| 171 |
+
|
| 172 |
+
def _mc_forward(net, name, Xn, kind, passes=_MC):
|
| 173 |
+
"""MC-dropout: keep dropout ON, run several passes -> (mean, std)."""
|
| 174 |
+
t = torch()
|
| 175 |
+
net.train() # dropout active
|
| 176 |
+
outs = []
|
| 177 |
+
with t.no_grad():
|
| 178 |
+
for _ in range(passes):
|
| 179 |
+
o = net(name, t.tensor(np.asarray(Xn, "float32"))).numpy()
|
| 180 |
+
outs.append(_sigmoid(o) if kind == "cls" else o)
|
| 181 |
+
net.eval()
|
| 182 |
+
outs = np.array(outs)
|
| 183 |
+
return outs.mean(0), outs.std(0)
|
| 184 |
+
|
| 185 |
+
|
| 186 |
+
def _sigmoid(z):
|
| 187 |
+
return 1.0 / (1.0 + np.exp(-np.clip(z, -30, 30)))
|
| 188 |
+
|
| 189 |
+
|
| 190 |
+
def _domain_metric(sp, pred_std_mean):
|
| 191 |
+
"""Score the (standardized) prediction against the held-out truth in the
|
| 192 |
+
domain's OWN metric. pred_std_mean is the standardized-space mean output."""
|
| 193 |
+
kind = sp["kind"]; Yte = sp["Yte"]
|
| 194 |
+
if kind == "cls":
|
| 195 |
+
from sklearn.metrics import roc_auc_score
|
| 196 |
+
p = _sigmoid(pred_std_mean).ravel()
|
| 197 |
+
auc = float(roc_auc_score(Yte.ravel(), p)) if len(np.unique(Yte)) > 1 else float("nan")
|
| 198 |
+
return {"metric": "roc_auc", "value": round(auc, 3), "higher_better": True}
|
| 199 |
+
pred = _invy(sp, pred_std_mean)
|
| 200 |
+
if sp["name"] == "transport":
|
| 201 |
+
return {"metric": "r2_log_Qtot", "value": round(metrics.r2(Yte.ravel(), pred.ravel()), 3),
|
| 202 |
+
"higher_better": True}
|
| 203 |
+
if sp["name"] == "equil":
|
| 204 |
+
rl2 = float(np.mean([metrics.rel_l2(Yte[i], pred[i]) for i in range(len(Yte))]))
|
| 205 |
+
return {"metric": "rel_l2_field", "value": round(rl2, 4), "higher_better": False}
|
| 206 |
+
# state: range-normalized RMSE (KFLOW convention)
|
| 207 |
+
rng = sp["Ytr"].max(0) - sp["Ytr"].min(0) + 1e-9
|
| 208 |
+
nrmse = float(np.sqrt(np.mean(((pred - Yte) / rng) ** 2)))
|
| 209 |
+
return {"metric": "norm_rmse", "value": round(nrmse, 4), "higher_better": False}
|
| 210 |
+
|
| 211 |
+
|
| 212 |
+
@register
|
| 213 |
+
class KMIND(Surrogate):
|
| 214 |
+
name = "KMIND"; function = "FOUNDATION"; phase = 3; status = "BUILT"
|
| 215 |
+
provenance = "SIM"
|
| 216 |
+
retired_by = "a device-scale multi-task foundation model on real multi-diagnostic data"
|
| 217 |
+
real_codes = ("multi-task representation learning", "KYRO", "KORE", "KFLOW", "KWARD")
|
| 218 |
+
gates = ("BR-L2-A1e", "AC-16", "AC-18", "AC-20")
|
| 219 |
+
note = ("whole-device foundation surrogate — one shared-trunk multi-task net across "
|
| 220 |
+
"transport / equilibrium / state / disruption, trained jointly; reports "
|
| 221 |
+
"shared-representation transfer honestly (incl. negative transfer)")
|
| 222 |
+
|
| 223 |
+
def __init__(self):
|
| 224 |
+
self._net = None; self._specs = None
|
| 225 |
+
|
| 226 |
+
def _fit(self):
|
| 227 |
+
if self._net is None:
|
| 228 |
+
self._specs = [_spec(n) for n in _DOMAINS]
|
| 229 |
+
self._net = _train(_build_net(self._specs), self._specs)
|
| 230 |
+
return self._net, self._specs
|
| 231 |
+
|
| 232 |
+
def _sp(self, name):
|
| 233 |
+
_, specs = self._fit()
|
| 234 |
+
for sp in specs:
|
| 235 |
+
if sp["name"] == name:
|
| 236 |
+
return sp
|
| 237 |
+
raise KeyError(name)
|
| 238 |
+
|
| 239 |
+
def _predict(self, x):
|
| 240 |
+
"""x = (domain, input) or {"domain": name, "x": input}, domain in
|
| 241 |
+
{transport, equil, state, disrupt}. -> Prediction(y, MC-dropout std, in_domain)."""
|
| 242 |
+
if isinstance(x, dict):
|
| 243 |
+
name, xi = x.get("domain"), x.get("x")
|
| 244 |
+
elif isinstance(x, (tuple, list)) and len(x) == 2 and x[0] in _DOMAINS:
|
| 245 |
+
name, xi = x
|
| 246 |
+
else:
|
| 247 |
+
raise ValueError("KMIND expects (domain, input) or {'domain','x'}; "
|
| 248 |
+
f"domain in {list(_DOMAINS)}")
|
| 249 |
+
net, _ = self._fit(); sp = self._sp(name)
|
| 250 |
+
Xn = _stdx(sp, xi)
|
| 251 |
+
mean, std = _mc_forward(net, name, Xn, sp["kind"])
|
| 252 |
+
if sp["kind"] == "cls":
|
| 253 |
+
y = float(mean.ravel()[0]); unc = float(std.ravel()[0])
|
| 254 |
+
note = f"{name} head: disruption probability {y:.3f} (MC-dropout std {unc:.3f})"
|
| 255 |
+
else:
|
| 256 |
+
inv_mean = _invy(sp, mean)[0]; inv_std = (std * sp["ysd"])[0]
|
| 257 |
+
y = float(inv_mean) if sp["out_dim"] == 1 else inv_mean
|
| 258 |
+
unc = float(np.mean(inv_std)) if sp["out_dim"] > 1 else float(inv_std)
|
| 259 |
+
tgt = "log10 Q_tot" if name == "transport" else ("psi field" if name == "equil"
|
| 260 |
+
else "clean sensor state")
|
| 261 |
+
note = f"{name} head via shared trunk -> {tgt} (MC-dropout epistemic std)"
|
| 262 |
+
return Prediction(y, unc, _in_domain(sp, xi), note=note)
|
| 263 |
+
|
| 264 |
+
def benchmark(self):
|
| 265 |
+
net, specs = self._fit()
|
| 266 |
+
# multi-task test predictions per domain (deterministic mean, dropout off)
|
| 267 |
+
t = torch()
|
| 268 |
+
multi = {}
|
| 269 |
+
with t.no_grad():
|
| 270 |
+
for sp in specs:
|
| 271 |
+
out = net(sp["name"], t.tensor(_stdx(sp, sp["Xte"]))).numpy()
|
| 272 |
+
multi[sp["name"]] = _domain_metric(sp, out)
|
| 273 |
+
# matched single-task baselines: same architecture (adapter+trunk+head),
|
| 274 |
+
# SAME split + steps, trained on that ONE domain only
|
| 275 |
+
_MIN_TEST = 10 # below this, held-out metric is too noisy to judge
|
| 276 |
+
transfer = {}
|
| 277 |
+
for sp in specs:
|
| 278 |
+
base_net = _train(_build_net([sp]), [sp])
|
| 279 |
+
with t.no_grad():
|
| 280 |
+
bo = base_net(sp["name"], t.tensor(_stdx(sp, sp["Xte"]))).numpy()
|
| 281 |
+
base_m = _domain_metric(sp, bo)
|
| 282 |
+
mm = multi[sp["name"]]
|
| 283 |
+
n_test = int(len(sp["Xte"]))
|
| 284 |
+
delta = round(mm["value"] - base_m["value"], 4)
|
| 285 |
+
if n_test < _MIN_TEST:
|
| 286 |
+
direction = "data_starved" # e.g. transport: 16 pts total, held-out R2 unreliable
|
| 287 |
+
else:
|
| 288 |
+
better = ((mm["value"] > base_m["value"]) if mm["higher_better"]
|
| 289 |
+
else (mm["value"] < base_m["value"]))
|
| 290 |
+
eps = 0.01 if mm["higher_better"] else 0.002
|
| 291 |
+
direction = ("positive" if (better and abs(delta) > eps)
|
| 292 |
+
else "negative" if (not better and abs(delta) > eps) else "neutral")
|
| 293 |
+
transfer[sp["name"]] = {
|
| 294 |
+
"metric": mm["metric"], "multitask": mm["value"],
|
| 295 |
+
"single_task_baseline": base_m["value"], "delta": delta,
|
| 296 |
+
"transfer": direction, "n_train": int(sp["n"] - n_test), "n_test": n_test}
|
| 297 |
+
pos = [d for d, v in transfer.items() if v["transfer"] == "positive"]
|
| 298 |
+
neg = [d for d, v in transfer.items() if v["transfer"] == "negative"]
|
| 299 |
+
neu = [d for d, v in transfer.items() if v["transfer"] == "neutral"]
|
| 300 |
+
starved = [d for d, v in transfer.items() if v["transfer"] == "data_starved"]
|
| 301 |
+
t0 = time.perf_counter()
|
| 302 |
+
for _ in range(50):
|
| 303 |
+
self._predict(("transport", [3.0, 1.0]))
|
| 304 |
+
ms = (time.perf_counter() - t0) / 50 * 1e3
|
| 305 |
+
return {"member": self.name,
|
| 306 |
+
"live_foundation": {
|
| 307 |
+
"architecture": (f"per-domain adapter (->{_D_EMB}) + shared trunk "
|
| 308 |
+
f"(2x{_H}, dropout {_DROP}) + per-domain head; {len(specs)} domains, "
|
| 309 |
+
f"joint training {_STEPS} steps"),
|
| 310 |
+
"domains": list(_DOMAINS),
|
| 311 |
+
"params": int(sum(p.numel() for p in net.parameters())),
|
| 312 |
+
"transfer_vs_single_task": transfer,
|
| 313 |
+
"positive_transfer_domains": pos,
|
| 314 |
+
"negative_transfer_domains": neg,
|
| 315 |
+
"neutral_transfer_domains": neu,
|
| 316 |
+
"data_starved_domains": starved,
|
| 317 |
+
"mc_dropout_predict_ms": round(ms, 2),
|
| 318 |
+
"backend": "CPU, torch, MC-dropout UQ",
|
| 319 |
+
"verdict": (f"One shared trunk across {len(specs)} fusion domains, benchmarked head-by-head "
|
| 320 |
+
f"against a MATCHED single-task baseline on the same split. On the well-populated "
|
| 321 |
+
f"domains the shared representation is positive {pos or 'none'}, negative "
|
| 322 |
+
f"{neg or 'none'}, neutral {neu or 'none'} — "
|
| 323 |
+
f"{'no negative transfer' if not neg else 'some negative transfer'}. "
|
| 324 |
+
+ (f"{starved} is data-starved "
|
| 325 |
+
f"({transfer[starved[0]]['n_train'] + transfer[starved[0]]['n_test']} pts) "
|
| 326 |
+
f"and not judged held-out. " if starved else "")
|
| 327 |
+
+ f"Trained on real on-disk data (CGYRO map / analytic equilibria / twin "
|
| 328 |
+
f"sensor snapshots / MAST shots) — an honest multi-task result, not a blanket win.")},
|
| 329 |
+
"caveats": ["transport has only ~16 points, so its head is data-starved and high-variance "
|
| 330 |
+
"(a real limit, reported not hidden)",
|
| 331 |
+
"uncertainty is an MC-dropout epistemic proxy, not a calibrated conformal interval",
|
| 332 |
+
"equilibrium targets are the analytic Solov'ev family (as in KORE); state targets "
|
| 333 |
+
"are the analytic-twin sensor snapshots (as in KFLOW)"]}
|
kronos_ml/members/quantum.py
CHANGED
|
@@ -27,7 +27,7 @@ class KQUBIT(Surrogate):
|
|
| 27 |
note = ("REAL variational quantum eigensolver (VQE) for a molecular Hamiltonian — a "
|
| 28 |
"runnable quantum program (PennyLane): executes on a simulator now and on real "
|
| 29 |
"quantum hardware when you plug in a backend. Honest: no quantum advantage yet "
|
| 30 |
-
"(~8-10 yr out); the tooling + testing are real TODAY")
|
| 31 |
|
| 32 |
# H2 molecular Hamiltonian, 2-qubit parity-reduced (standard Qiskit/IBM textbook coeffs, Ha)
|
| 33 |
_COEFFS = (-1.052373245772859, 0.39793742484318045, -0.39793742484318045,
|
|
@@ -137,7 +137,7 @@ class KQROSS(Surrogate):
|
|
| 137 |
note = ("REAL fault-tolerant resource estimator — computes the classical<->quantum crossover N, "
|
| 138 |
"the surface-code physical-qubit overhead, and the logical-qubit roadmap year for a fusion "
|
| 139 |
"electronic-structure kernel (order-of-magnitude, literature-scaled). Verdict: no FT "
|
| 140 |
-
"advantage this decade — the machine does not exist yet")
|
| 141 |
|
| 142 |
# order-of-magnitude scaling model (literature-scaled; illustrative, honestly labelled)
|
| 143 |
_D = 25 # surface-code distance
|
|
@@ -207,7 +207,7 @@ class KSENSE(Surrogate):
|
|
| 207 |
note = ("REAL quantum-metrology evaluation (PennyLane mixed-state) — GHZ interferometry: ideal "
|
| 208 |
"gives Heisenberg (gain ~ N) scaling, but realistic dephasing (NV/SQUID/SERF reality) "
|
| 209 |
"collapses it back to the standard quantum limit (~sqrt(N)). Honest null where fusion "
|
| 210 |
-
"disruptions live")
|
| 211 |
|
| 212 |
_P = 0.2 # per-qubit dephasing (realistic sensor decoherence)
|
| 213 |
|
|
@@ -284,7 +284,7 @@ class KTENSOR(Surrogate):
|
|
| 284 |
gates = ("KX-L3",)
|
| 285 |
note = ("tensor-network / low-rank ROM compression of the real CGYRO A1e flux "
|
| 286 |
"database (classical MPS-style SVD; a many-body method and bridge to "
|
| 287 |
-
"quantum kernels — NO quantum-advantage claim)")
|
| 288 |
|
| 289 |
_COLS = ("a_LT", "shear", "Q_i", "Q_e") # operating grid + saturated fluxes
|
| 290 |
|
|
@@ -395,7 +395,7 @@ class KQERN(Surrogate):
|
|
| 395 |
note = ("REAL quantum-kernel classifier — embeds real MAST disruption features into a "
|
| 396 |
"quantum feature map and classifies on the fidelity kernel (PennyLane); runs on a "
|
| 397 |
"simulator now, real hardware pluggable. Honest: ties the classical kernel — a "
|
| 398 |
-
"validated no-advantage result, but a real, runnable quantum-ML pipeline")
|
| 399 |
|
| 400 |
_N = 64
|
| 401 |
_FEATS = (0, 6, 7, 8) # ip_mean, beta_n, li, q95 (subset of KWARD's real features)
|
|
@@ -490,7 +490,7 @@ class KQOPT(Surrogate):
|
|
| 490 |
note = ("REAL QAOA quantum optimizer — solves a combinatorial design QUBO on an actual "
|
| 491 |
"quantum circuit (PennyLane); runs on a simulator now, real hardware pluggable, and "
|
| 492 |
"you can plug in your own QUBO. Honest: standard ~0.7-1.0 approx ratio, no speedup "
|
| 493 |
-
"at this size (
|
| 494 |
|
| 495 |
# a fixed 6-node design QUBO (illustrative MaxCut-style configuration problem)
|
| 496 |
_EDGES = ((0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 0), (0, 2), (3, 5))
|
|
@@ -586,7 +586,8 @@ class KDYN(Surrogate):
|
|
| 586 |
gates = ("KX-L3",)
|
| 587 |
note = ("REAL quantum dynamics — Trotterized time-evolution of a transverse-field Ising "
|
| 588 |
"'kinetic' Hamiltonian (PennyLane); the honest 1/n_steps cost curve for simulating "
|
| 589 |
-
"plasma-like dynamics on a quantum computer. Runs on a simulator now, hardware pluggable"
|
|
|
|
| 590 |
|
| 591 |
_NQ = 3; _J = 1.0; _HX = 0.8; _T = 1.0
|
| 592 |
|
|
|
|
| 27 |
note = ("REAL variational quantum eigensolver (VQE) for a molecular Hamiltonian — a "
|
| 28 |
"runnable quantum program (PennyLane): executes on a simulator now and on real "
|
| 29 |
"quantum hardware when you plug in a backend. Honest: no quantum advantage yet "
|
| 30 |
+
"(~8-10 yr out); the tooling + testing are real TODAY — quantum's role in fusion is post-~2036")
|
| 31 |
|
| 32 |
# H2 molecular Hamiltonian, 2-qubit parity-reduced (standard Qiskit/IBM textbook coeffs, Ha)
|
| 33 |
_COEFFS = (-1.052373245772859, 0.39793742484318045, -0.39793742484318045,
|
|
|
|
| 137 |
note = ("REAL fault-tolerant resource estimator — computes the classical<->quantum crossover N, "
|
| 138 |
"the surface-code physical-qubit overhead, and the logical-qubit roadmap year for a fusion "
|
| 139 |
"electronic-structure kernel (order-of-magnitude, literature-scaled). Verdict: no FT "
|
| 140 |
+
"advantage this decade — the machine does not exist yet; meaningful role post-~2036")
|
| 141 |
|
| 142 |
# order-of-magnitude scaling model (literature-scaled; illustrative, honestly labelled)
|
| 143 |
_D = 25 # surface-code distance
|
|
|
|
| 207 |
note = ("REAL quantum-metrology evaluation (PennyLane mixed-state) — GHZ interferometry: ideal "
|
| 208 |
"gives Heisenberg (gain ~ N) scaling, but realistic dephasing (NV/SQUID/SERF reality) "
|
| 209 |
"collapses it back to the standard quantum limit (~sqrt(N)). Honest null where fusion "
|
| 210 |
+
"disruptions live; quantum's role in fusion is post-~2036")
|
| 211 |
|
| 212 |
_P = 0.2 # per-qubit dephasing (realistic sensor decoherence)
|
| 213 |
|
|
|
|
| 284 |
gates = ("KX-L3",)
|
| 285 |
note = ("tensor-network / low-rank ROM compression of the real CGYRO A1e flux "
|
| 286 |
"database (classical MPS-style SVD; a many-body method and bridge to "
|
| 287 |
+
"quantum kernels — NO quantum-advantage claim; quantum's role in fusion is post-~2036)")
|
| 288 |
|
| 289 |
_COLS = ("a_LT", "shear", "Q_i", "Q_e") # operating grid + saturated fluxes
|
| 290 |
|
|
|
|
| 395 |
note = ("REAL quantum-kernel classifier — embeds real MAST disruption features into a "
|
| 396 |
"quantum feature map and classifies on the fidelity kernel (PennyLane); runs on a "
|
| 397 |
"simulator now, real hardware pluggable. Honest: ties the classical kernel — a "
|
| 398 |
+
"validated no-advantage result, but a real, runnable quantum-ML pipeline; role in fusion post-~2036")
|
| 399 |
|
| 400 |
_N = 64
|
| 401 |
_FEATS = (0, 6, 7, 8) # ip_mean, beta_n, li, q95 (subset of KWARD's real features)
|
|
|
|
| 490 |
note = ("REAL QAOA quantum optimizer — solves a combinatorial design QUBO on an actual "
|
| 491 |
"quantum circuit (PennyLane); runs on a simulator now, real hardware pluggable, and "
|
| 492 |
"you can plug in your own QUBO. Honest: standard ~0.7-1.0 approx ratio, no speedup "
|
| 493 |
+
"at this size (advantage post-~2036)")
|
| 494 |
|
| 495 |
# a fixed 6-node design QUBO (illustrative MaxCut-style configuration problem)
|
| 496 |
_EDGES = ((0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 0), (0, 2), (3, 5))
|
|
|
|
| 586 |
gates = ("KX-L3",)
|
| 587 |
note = ("REAL quantum dynamics — Trotterized time-evolution of a transverse-field Ising "
|
| 588 |
"'kinetic' Hamiltonian (PennyLane); the honest 1/n_steps cost curve for simulating "
|
| 589 |
+
"plasma-like dynamics on a quantum computer. Runs on a simulator now, hardware pluggable; "
|
| 590 |
+
"quantum's role in fusion is post-~2036")
|
| 591 |
|
| 592 |
_NQ = 3; _J = 1.0; _HX = 0.8; _T = 1.0
|
| 593 |
|
kronos_ml/members/quantum_v3.py
ADDED
|
@@ -0,0 +1,286 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""KODEX v0.3.0 quantum additions — honest, runnable-today NISQ tooling.
|
| 2 |
+
|
| 3 |
+
KMIT — quantum ERROR MITIGATION: zero-noise extrapolation (ZNE) + readout-error
|
| 4 |
+
mitigation applied to a real fusion quantum circuit (the KQUBIT H2 VQE
|
| 5 |
+
state). Mitigation is the technique NISQ practitioners actually run
|
| 6 |
+
today — it claws signal back out of noise; it is NOT a speedup.
|
| 7 |
+
KLINQ — quantum LINEAR SOLVER: a variational quantum linear solver (VQLS) that
|
| 8 |
+
prepares the solution of a small reduced-MHD linear system with a real
|
| 9 |
+
quantum circuit, plus an honest fault-tolerant HHL resource estimate.
|
| 10 |
+
|
| 11 |
+
Framing (founder, 2026-09-19): we see quantum computing taking a meaningful role
|
| 12 |
+
in fusion only AFTER ~2036 — the tooling and testing are real and runnable TODAY
|
| 13 |
+
(here, on a simulator now and on real hardware via KODEX_QC_BACKEND=ibm), the
|
| 14 |
+
advantage is not.
|
| 15 |
+
"""
|
| 16 |
+
from __future__ import annotations
|
| 17 |
+
|
| 18 |
+
import numpy as np
|
| 19 |
+
|
| 20 |
+
from .. import register, get
|
| 21 |
+
from ..base import Surrogate, Prediction
|
| 22 |
+
from .. import quantum_backend as qc
|
| 23 |
+
|
| 24 |
+
_QC_ROLE_YEAR = 2036 # honest: quantum's meaningful role in fusion is post-~2036
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
# ============================================================ KMIT
|
| 28 |
+
@register
|
| 29 |
+
class KMIT(Surrogate):
|
| 30 |
+
name = "KMIT"; function = "QMITIGATION"; phase = 2; status = "BUILT"
|
| 31 |
+
provenance = "SIM"
|
| 32 |
+
retired_by = "fault-tolerant quantum hardware (not available this decade)"
|
| 33 |
+
real_codes = ("zero-noise extrapolation", "readout-error mitigation", "PennyLane")
|
| 34 |
+
gates = ("KX-L3",)
|
| 35 |
+
note = ("REAL quantum error mitigation — zero-noise extrapolation (ZNE, unitary "
|
| 36 |
+
"folding) + readout-error mitigation on a real fusion quantum circuit "
|
| 37 |
+
"(the KQUBIT H2 VQE state). Mitigation is the genuine NISQ tool TODAY; it "
|
| 38 |
+
f"recovers signal from noise, not a speedup. Quantum's role in fusion is "
|
| 39 |
+
f"post-~{_QC_ROLE_YEAR}")
|
| 40 |
+
|
| 41 |
+
_P = 0.04 # per-qubit depolarizing rate (NISQ-ish)
|
| 42 |
+
_READOUT = 0.08 # per-qubit readout bit-flip probability
|
| 43 |
+
|
| 44 |
+
# ---- ZNE on the KQUBIT H2 VQE circuit ----
|
| 45 |
+
def _zne(self):
|
| 46 |
+
import pennylane as qml
|
| 47 |
+
kq = get("KQUBIT"); kq._run_vqe()
|
| 48 |
+
params, H = kq._vqe_params, kq._hamiltonian()
|
| 49 |
+
ansatz = kq._ansatz
|
| 50 |
+
exact = kq._vqe["exact_energy_Ha"]
|
| 51 |
+
|
| 52 |
+
dev_clean = qml.device("default.qubit", wires=2)
|
| 53 |
+
|
| 54 |
+
@qml.qnode(dev_clean)
|
| 55 |
+
def ideal():
|
| 56 |
+
ansatz(params)
|
| 57 |
+
return qml.expval(H)
|
| 58 |
+
e_ideal = float(ideal()) # noiseless expval at the VQE params
|
| 59 |
+
|
| 60 |
+
dev = qml.device("default.mixed", wires=2)
|
| 61 |
+
|
| 62 |
+
def _noise():
|
| 63 |
+
for w in (0, 1):
|
| 64 |
+
qml.DepolarizingChannel(self._P, wires=w)
|
| 65 |
+
|
| 66 |
+
@qml.qnode(dev)
|
| 67 |
+
def folded(k):
|
| 68 |
+
"""Global unitary folding: ansatz (adjoint.ansatz)^k -> logical ansatz,
|
| 69 |
+
noise scale lambda = 2k+1."""
|
| 70 |
+
ansatz(params); _noise()
|
| 71 |
+
for _ in range(k):
|
| 72 |
+
qml.adjoint(ansatz)(params); _noise()
|
| 73 |
+
ansatz(params); _noise()
|
| 74 |
+
return qml.expval(H)
|
| 75 |
+
|
| 76 |
+
lambdas = np.array([1, 3, 5], float) # k = 0, 1, 2
|
| 77 |
+
energies = np.array([float(folded(int((lam - 1) / 2))) for lam in lambdas])
|
| 78 |
+
# linear ZNE extrapolation to zero noise
|
| 79 |
+
slope, intercept = np.polyfit(lambdas, energies, 1)
|
| 80 |
+
e_noisy = float(energies[0])
|
| 81 |
+
e_zne = float(intercept)
|
| 82 |
+
err_noisy = abs(e_noisy - e_ideal)
|
| 83 |
+
err_zne = abs(e_zne - e_ideal)
|
| 84 |
+
reduction = (err_noisy - err_zne) / err_noisy if err_noisy > 1e-9 else 0.0
|
| 85 |
+
return {"exact_energy_Ha": round(exact, 6),
|
| 86 |
+
"ideal_noiseless_Ha": round(e_ideal, 6),
|
| 87 |
+
"noisy_Ha": round(e_noisy, 6),
|
| 88 |
+
"zne_mitigated_Ha": round(e_zne, 6),
|
| 89 |
+
"noise_scales_lambda": lambdas.tolist(),
|
| 90 |
+
"energies_vs_lambda": [round(float(e), 6) for e in energies],
|
| 91 |
+
"error_noisy_mHa": round(err_noisy * 1e3, 3),
|
| 92 |
+
"error_zne_mHa": round(err_zne * 1e3, 3),
|
| 93 |
+
"error_reduction_frac": round(float(reduction), 3),
|
| 94 |
+
"depolarizing_p": self._P, "backend": qc.backend_note()}
|
| 95 |
+
|
| 96 |
+
# ---- readout-error mitigation on a Bell distribution ----
|
| 97 |
+
def _readout_mitigation(self):
|
| 98 |
+
r = self._READOUT
|
| 99 |
+
ideal = np.array([0.5, 0.0, 0.0, 0.5]) # Bell |Phi+> probs
|
| 100 |
+
M1 = np.array([[1 - r, r], [r, 1 - r]]) # per-qubit readout confusion
|
| 101 |
+
M = np.kron(M1, M1)
|
| 102 |
+
noisy = M @ ideal
|
| 103 |
+
mitig = np.linalg.solve(M, noisy)
|
| 104 |
+
mitig = np.clip(mitig, 0, None); mitig = mitig / mitig.sum()
|
| 105 |
+
tv = lambda a, b: float(0.5 * np.abs(a - b).sum())
|
| 106 |
+
tv_noisy, tv_mit = tv(noisy, ideal), tv(mitig, ideal)
|
| 107 |
+
return {"readout_bitflip_p": r,
|
| 108 |
+
"tv_distance_noisy": round(tv_noisy, 4),
|
| 109 |
+
"tv_distance_mitigated": round(tv_mit, 4),
|
| 110 |
+
"tv_reduction_frac": round((tv_noisy - tv_mit) / tv_noisy, 3) if tv_noisy > 1e-9 else 0.0,
|
| 111 |
+
"method": "inverse confusion-matrix (linear) readout correction"}
|
| 112 |
+
|
| 113 |
+
def _predict(self, x):
|
| 114 |
+
"""x = per-qubit depolarizing rate p (float) -> ZNE-mitigated H2 energy at that noise."""
|
| 115 |
+
if x is not None:
|
| 116 |
+
try:
|
| 117 |
+
self._P = float(np.ravel(np.asarray(x, float))[0])
|
| 118 |
+
except Exception:
|
| 119 |
+
pass
|
| 120 |
+
z = self._zne()
|
| 121 |
+
return Prediction(z["zne_mitigated_Ha"], z["error_zne_mHa"], True,
|
| 122 |
+
note=(f"ZNE-mitigated H2 energy {z['zne_mitigated_Ha']} Ha "
|
| 123 |
+
f"(noisy err {z['error_noisy_mHa']} -> {z['error_zne_mHa']} mHa); "
|
| 124 |
+
f"backend={z['backend']['active_backend']}"))
|
| 125 |
+
|
| 126 |
+
def benchmark(self):
|
| 127 |
+
z = self._zne(); ro = self._readout_mitigation()
|
| 128 |
+
return {"member": self.name,
|
| 129 |
+
"live_error_mitigation": {
|
| 130 |
+
"problem": "mitigate a noisy H2 VQE expectation (the real KQUBIT circuit)",
|
| 131 |
+
"framework": "PennyLane default.mixed; ZNE via global unitary folding + linear extrapolation",
|
| 132 |
+
"zne": z, "readout_mitigation": ro,
|
| 133 |
+
"backend": z["backend"],
|
| 134 |
+
"verdict": (f"REAL error mitigation on a fusion quantum circuit: ZNE cuts the noisy-energy "
|
| 135 |
+
f"error {z['error_noisy_mHa']} -> {z['error_zne_mHa']} mHa "
|
| 136 |
+
f"({z['error_reduction_frac']:.0%} of the error removed) and inverse-confusion "
|
| 137 |
+
f"readout correction cuts the measurement TV distance "
|
| 138 |
+
f"{ro['tv_distance_noisy']} -> {ro['tv_distance_mitigated']} "
|
| 139 |
+
f"({ro['tv_reduction_frac']:.0%}). Mitigation is the REAL NISQ tool today — it "
|
| 140 |
+
f"recovers signal from noise. HONEST: it is NOT a speedup; quantum's meaningful "
|
| 141 |
+
f"role in fusion is post-~{_QC_ROLE_YEAR}, and mitigation cost grows with noise. "
|
| 142 |
+
f"Runs on real hardware with KODEX_QC_BACKEND=ibm.")},
|
| 143 |
+
"caveats": [f"no quantum advantage — quantum's role in fusion is post-~{_QC_ROLE_YEAR}",
|
| 144 |
+
"ZNE assumes a smooth noise->observable relation; it extrapolates, it does not "
|
| 145 |
+
"eliminate noise, and its overhead grows as noise grows",
|
| 146 |
+
"readout mitigation uses a known confusion matrix; on hardware you must calibrate it"]}
|
| 147 |
+
|
| 148 |
+
|
| 149 |
+
# ============================================================ KLINQ
|
| 150 |
+
@register
|
| 151 |
+
class KLINQ(Surrogate):
|
| 152 |
+
name = "KLINQ"; function = "QLINSOLVE"; phase = 3; status = "BUILT"
|
| 153 |
+
provenance = "SIM"
|
| 154 |
+
retired_by = "fault-tolerant quantum hardware (not available this decade)"
|
| 155 |
+
real_codes = ("variational quantum linear solver", "HHL resource estimate", "PennyLane")
|
| 156 |
+
gates = ("KX-L3",)
|
| 157 |
+
note = ("REAL quantum linear solver — a variational quantum linear solver (VQLS) prepares the "
|
| 158 |
+
"solution of a small reduced-MHD linear system with a real quantum circuit (sim now, "
|
| 159 |
+
"hardware pluggable), plus an honest fault-tolerant HHL resource estimate. No advantage "
|
| 160 |
+
f"at real scale; quantum's role in fusion is post-~{_QC_ROLE_YEAR}")
|
| 161 |
+
|
| 162 |
+
_NQ = 2 # N = 4 linear system
|
| 163 |
+
_N = 4
|
| 164 |
+
|
| 165 |
+
def _system(self, b=None):
|
| 166 |
+
"""A small SPD reduced-MHD operator: 1-D discrete Laplacian (tridiagonal),
|
| 167 |
+
the shape a linearized force-balance / diffusion solve takes."""
|
| 168 |
+
A = (np.diag([2.0] * self._N) + np.diag([-1.0] * (self._N - 1), 1)
|
| 169 |
+
+ np.diag([-1.0] * (self._N - 1), -1))
|
| 170 |
+
if b is None:
|
| 171 |
+
b = np.array([1.0, 0.0, 0.0, 0.0])
|
| 172 |
+
b = np.asarray(b, float).ravel()[: self._N]
|
| 173 |
+
b = b / (np.linalg.norm(b) + 1e-12)
|
| 174 |
+
return A, b
|
| 175 |
+
|
| 176 |
+
def _ansatz_state(self, theta, dev):
|
| 177 |
+
import pennylane as qml
|
| 178 |
+
|
| 179 |
+
@qml.qnode(dev)
|
| 180 |
+
def state(t):
|
| 181 |
+
# 2-layer hardware-efficient ansatz on 2 qubits
|
| 182 |
+
qml.RY(t[0], 0); qml.RY(t[1], 1)
|
| 183 |
+
qml.CNOT([0, 1])
|
| 184 |
+
qml.RY(t[2], 0); qml.RY(t[3], 1)
|
| 185 |
+
qml.CNOT([1, 0])
|
| 186 |
+
qml.RY(t[4], 0); qml.RY(t[5], 1)
|
| 187 |
+
return qml.state()
|
| 188 |
+
return np.real(np.asarray(state(theta))) # SPD system -> real solution
|
| 189 |
+
|
| 190 |
+
def _solve(self, b=None):
|
| 191 |
+
if getattr(self, "_res", None) is not None and b is None:
|
| 192 |
+
return self._res
|
| 193 |
+
import pennylane as qml
|
| 194 |
+
from scipy.optimize import minimize
|
| 195 |
+
from .. import uq
|
| 196 |
+
A, bvec = self._system(b)
|
| 197 |
+
dev = qc.get_device(wires=self._NQ)
|
| 198 |
+
|
| 199 |
+
def cost(theta):
|
| 200 |
+
x = self._ansatz_state(theta, dev)
|
| 201 |
+
Ax = A @ x
|
| 202 |
+
nAx = np.linalg.norm(Ax) + 1e-12
|
| 203 |
+
overlap = float(bvec @ (Ax / nAx)) # want A|x> parallel to |b>
|
| 204 |
+
return 1.0 - overlap ** 2 # global VQLS cost
|
| 205 |
+
|
| 206 |
+
rng = np.random.default_rng(uq.SEED)
|
| 207 |
+
best = None
|
| 208 |
+
for _ in range(4): # a few restarts for robustness
|
| 209 |
+
t0 = rng.uniform(0, 2 * np.pi, 6)
|
| 210 |
+
r = minimize(cost, t0, method="Powell",
|
| 211 |
+
options={"maxiter": 4000, "xtol": 1e-8, "ftol": 1e-10})
|
| 212 |
+
if best is None or r.fun < best.fun:
|
| 213 |
+
best = r
|
| 214 |
+
theta = best.x
|
| 215 |
+
x_q = self._ansatz_state(theta, dev)
|
| 216 |
+
# VQLS solves up to scale & sign: fix by projecting onto the classical solution direction
|
| 217 |
+
x_cl = np.linalg.solve(A, bvec)
|
| 218 |
+
x_q_dir = x_q / (np.linalg.norm(x_q) + 1e-12)
|
| 219 |
+
x_cl_dir = x_cl / (np.linalg.norm(x_cl) + 1e-12)
|
| 220 |
+
if x_q_dir @ x_cl_dir < 0:
|
| 221 |
+
x_q_dir = -x_q_dir
|
| 222 |
+
fidelity = float((x_q_dir @ x_cl_dir) ** 2) # state fidelity of the solutions
|
| 223 |
+
# rescale quantum direction to the true magnitude for a usable x
|
| 224 |
+
alpha = float((A @ x_q_dir) @ bvec) / float((A @ x_q_dir) @ (A @ x_q_dir) + 1e-12)
|
| 225 |
+
x_q_scaled = alpha * x_q_dir
|
| 226 |
+
resid = float(np.linalg.norm(A @ x_q_scaled - bvec) / (np.linalg.norm(bvec) + 1e-12))
|
| 227 |
+
res = {"N": self._N, "n_qubits": self._NQ, "cost_final": round(float(best.fun), 6),
|
| 228 |
+
"solution_fidelity_vs_classical": round(fidelity, 4),
|
| 229 |
+
"residual_rel": round(resid, 4),
|
| 230 |
+
"x_quantum": [round(float(v), 4) for v in x_q_scaled],
|
| 231 |
+
"x_classical": [round(float(v), 4) for v in x_cl],
|
| 232 |
+
"backend": qc.backend_note()}
|
| 233 |
+
if b is None:
|
| 234 |
+
self._res = res
|
| 235 |
+
return res
|
| 236 |
+
|
| 237 |
+
# ---- honest fault-tolerant HHL resource estimate (KQROSS-style) ----
|
| 238 |
+
def _hhl_estimate(self, N=1_000_000, kappa=1e3, precision_bits=10):
|
| 239 |
+
"""Order-of-magnitude FT-HHL cost for a fusion-scale sparse linear solve."""
|
| 240 |
+
n_logical = int(np.ceil(np.log2(N))) + precision_bits + 1 # system + clock + ancilla
|
| 241 |
+
phys_per_logical = 2 * 25 * 25 # surface code d=25 (~1250)
|
| 242 |
+
phys = n_logical * phys_per_logical
|
| 243 |
+
# HHL ~ O(kappa/eps) calls; classical CG ~ O(sqrt(kappa)) matvecs — quantum needs
|
| 244 |
+
# sparse, well-conditioned, and only reads out an aggregate, else state-prep/readout kill it
|
| 245 |
+
roadmap_year = 2027 + 3.0 * np.log10(max(n_logical, 1) / 1.0) # ~10x logical / 3 yr from ~1 in 2027
|
| 246 |
+
return {"assumed_system": f"N~{N:.0e} sparse SPD (reduced-MHD grid), kappa~{kappa:.0e}",
|
| 247 |
+
"logical_qubits_needed": n_logical,
|
| 248 |
+
"physical_qubits_needed": f"~{phys:.0e}",
|
| 249 |
+
"surface_code_phys_per_logical": phys_per_logical,
|
| 250 |
+
"roadmap_year_reach_logical": int(round(roadmap_year)),
|
| 251 |
+
"hardware_today": "~1e2-1e3 physical qubits, no error-corrected logical qubits",
|
| 252 |
+
"caveats": ["HHL needs fault tolerance + sparse, well-conditioned A + efficient state "
|
| 253 |
+
"prep, and returns |x> (aggregate readout), not the full vector",
|
| 254 |
+
f"no fusion HHL advantage this decade — meaningful role post-~{_QC_ROLE_YEAR}"]}
|
| 255 |
+
|
| 256 |
+
def _predict(self, x):
|
| 257 |
+
"""x = right-hand-side vector b (len<=4) or None -> quantum solution x of A x = b."""
|
| 258 |
+
r = self._solve(None if x is None else x)
|
| 259 |
+
return Prediction(r["x_quantum"], r["residual_rel"], True,
|
| 260 |
+
note=(f"VQLS solution (fidelity {r['solution_fidelity_vs_classical']} vs classical, "
|
| 261 |
+
f"rel-residual {r['residual_rel']}); backend={r['backend']['active_backend']}"))
|
| 262 |
+
|
| 263 |
+
def benchmark(self):
|
| 264 |
+
r = self._solve()
|
| 265 |
+
hhl = self._hhl_estimate()
|
| 266 |
+
return {"member": self.name,
|
| 267 |
+
"live_quantum_linear_solver": {
|
| 268 |
+
"problem": "solve A x = b for a 4x4 reduced-MHD Laplacian (SPD) with a real quantum circuit",
|
| 269 |
+
"method": "variational quantum linear solver (VQLS), global overlap cost, Powell optimization",
|
| 270 |
+
"framework": "PennyLane (sim now; Hadamard-test cost on real hardware, pluggable)",
|
| 271 |
+
**{k: r[k] for k in ("N", "n_qubits", "cost_final", "solution_fidelity_vs_classical",
|
| 272 |
+
"residual_rel", "x_quantum", "x_classical")},
|
| 273 |
+
"ft_hhl_resource_estimate": hhl, "backend": r["backend"],
|
| 274 |
+
"verdict": (f"REAL variational quantum linear solver recovers the 4x4 reduced-MHD solve at "
|
| 275 |
+
f"solution fidelity {r['solution_fidelity_vs_classical']} vs classical "
|
| 276 |
+
f"(rel-residual {r['residual_rel']}) — a runnable quantum linear solver TODAY. "
|
| 277 |
+
f"The fault-tolerant HHL route for a fusion-scale (N~1e6) solve needs "
|
| 278 |
+
f"~{hhl['logical_qubits_needed']} logical -> {hhl['physical_qubits_needed']} "
|
| 279 |
+
f"physical qubits (roadmap ~{hhl['roadmap_year_reach_logical']}). HONEST: no "
|
| 280 |
+
f"advantage at real scale; quantum's meaningful role in fusion is "
|
| 281 |
+
f"post-~{_QC_ROLE_YEAR}. Runs on hardware with KODEX_QC_BACKEND=ibm.")},
|
| 282 |
+
"caveats": [f"no quantum advantage — quantum's role in fusion is post-~{_QC_ROLE_YEAR}",
|
| 283 |
+
"VQLS residual is read from the simulator here; on hardware it needs Hadamard "
|
| 284 |
+
"tests and its cost landscape can have barren plateaus at scale",
|
| 285 |
+
"the 4x4 system is a toy; classical solves it instantly — the point is a real, "
|
| 286 |
+
"honest, hardware-ready quantum pipeline, not a speedup"]}
|
kronos_ml/quantum_backend.py
CHANGED
|
@@ -62,6 +62,7 @@ def backend_note() -> dict:
|
|
| 62 |
"ran_on_real_hardware": real,
|
| 63 |
"how_to_use_real_qc": ("set KODEX_QC_BACKEND=ibm and KODEX_QC_TOKEN=<your IBM Quantum "
|
| 64 |
"token> to run this exact circuit on real quantum hardware"),
|
| 65 |
-
"honest_timeline": ("fault-tolerant quantum ADVANTAGE for fusion kernels is ~8-10 yr out
|
| 66 |
-
"
|
|
|
|
| 67 |
}
|
|
|
|
| 62 |
"ran_on_real_hardware": real,
|
| 63 |
"how_to_use_real_qc": ("set KODEX_QC_BACKEND=ibm and KODEX_QC_TOKEN=<your IBM Quantum "
|
| 64 |
"token> to run this exact circuit on real quantum hardware"),
|
| 65 |
+
"honest_timeline": ("fault-tolerant quantum ADVANTAGE for fusion kernels is ~8-10 yr out — a "
|
| 66 |
+
"meaningful role in fusion only after ~2036; this tooling makes the TESTING "
|
| 67 |
+
"real and runnable TODAY, same code path"),
|
| 68 |
}
|
publish/LIVE_RECORDS.md
DELETED
|
@@ -1,36 +0,0 @@
|
|
| 1 |
-
# KODEX — live deposit records (per code)
|
| 2 |
-
|
| 3 |
-
Status 2026-09-10: **Zenodo, OSF, Figshare = published** (26 each). **Harvard Dataverse = 25 submitted for curator review** (DOIs reserved; publish on Harvard approval) — **KLAW (doi:10.7910/DVN/ANAFXK) still to submit**. GitHub / PyPI / Hugging Face / Internet Archive = pending.
|
| 4 |
-
|
| 5 |
-
Author: Ford, P. I. · ORCID 0000-0003-0395-1752 · Kronos Fusion Energy · Apache-2.0. Each record's homepage = kronosfusionenergy.com/kodex/<code>.
|
| 6 |
-
|
| 7 |
-
| Code | Zenodo DOI | Figshare DOI | Dataverse DOI (in review) | OSF |
|
| 8 |
-
|--|--|--|--|--|
|
| 9 |
-
| **KAIROS** | 10.5281/zenodo.22694265 | 10.6084/m9.figshare.33553966 | 10.7910/DVN/GOZGCM | [db6uh](https://osf.io/db6uh/) |
|
| 10 |
-
| **KBREED** | 10.5281/zenodo.22694267 | 10.6084/m9.figshare.33559312 | 10.7910/DVN/OPJHP3 | [2m3ce](https://osf.io/2m3ce/) |
|
| 11 |
-
| **KBURN** | 10.5281/zenodo.22694269 | 10.6084/m9.figshare.33559324 | 10.7910/DVN/ITN6JZ | [8e6fn](https://osf.io/8e6fn/) |
|
| 12 |
-
| **KDRIVE** | 10.5281/zenodo.22694271 | 10.6084/m9.figshare.33559333 | 10.7910/DVN/YKKLQ7 | [xhkuy](https://osf.io/xhkuy/) |
|
| 13 |
-
| **KECON** | 10.5281/zenodo.22694273 | 10.6084/m9.figshare.33559345 | 10.7910/DVN/WBHQ7S | [b5qmx](https://osf.io/b5qmx/) |
|
| 14 |
-
| **KEYE** | 10.5281/zenodo.22694279 | 10.6084/m9.figshare.33559357 | 10.7910/DVN/5UILC8 | [5qzp4](https://osf.io/5qzp4/) |
|
| 15 |
-
| **KFLOW** | 10.5281/zenodo.22694283 | 10.6084/m9.figshare.33559369 | 10.7910/DVN/XUXC7B | [hjrzb](https://osf.io/hjrzb/) |
|
| 16 |
-
| **KFLUX** | 10.5281/zenodo.22694287 | 10.6084/m9.figshare.33559378 | 10.7910/DVN/3F0NCW | [fmjc2](https://osf.io/fmjc2/) |
|
| 17 |
-
| **KFORGE** | 10.5281/zenodo.22694289 | 10.6084/m9.figshare.33559390 | 10.7910/DVN/OVOVVN | [5zg6j](https://osf.io/5zg6j/) |
|
| 18 |
-
| **KFUEL** | 10.5281/zenodo.22694291 | 10.6084/m9.figshare.33559402 | 10.7910/DVN/89A8GS | [xuz8a](https://osf.io/xuz8a/) |
|
| 19 |
-
| **KFUSE** | 10.5281/zenodo.22694294 | 10.6084/m9.figshare.33559414 | 10.7910/DVN/SMA2OP | [exhkc](https://osf.io/exhkc/) |
|
| 20 |
-
| **KGATE** | 10.5281/zenodo.22694297 | 10.6084/m9.figshare.33559423 | 10.7910/DVN/2CKPZH | [mbu37](https://osf.io/mbu37/) |
|
| 21 |
-
| **KGEN** | 10.5281/zenodo.22694307 | 10.6084/m9.figshare.33559435 | 10.7910/DVN/OCTF8U | [svbwq](https://osf.io/svbwq/) |
|
| 22 |
-
| **KHALO** | 10.5281/zenodo.22694309 | 10.6084/m9.figshare.33559447 | 10.7910/DVN/V5YM23 | [ne89y](https://osf.io/ne89y/) |
|
| 23 |
-
| **KISO** | 10.5281/zenodo.22694311 | 10.6084/m9.figshare.33559459 | 10.7910/DVN/ELXAEY | [hjqek](https://osf.io/hjqek/) |
|
| 24 |
-
| **KLAW** | 10.5281/zenodo.22694315 | 10.6084/m9.figshare.33559468 | 10.7910/DVN/ANAFXK | [kfp4t](https://osf.io/kfp4t/) |
|
| 25 |
-
| **KMAT** | 10.5281/zenodo.22694319 | 10.6084/m9.figshare.33559480 | 10.7910/DVN/IJG9FT | [y4j2p](https://osf.io/y4j2p/) |
|
| 26 |
-
| **KOIL** | 10.5281/zenodo.22694323 | 10.6084/m9.figshare.33559492 | 10.7910/DVN/N5WLNR | [2rb68](https://osf.io/2rb68/) |
|
| 27 |
-
| **KORE** | 10.5281/zenodo.22694327 | 10.6084/m9.figshare.33559504 | 10.7910/DVN/DCFLOI | [sxm5v](https://osf.io/sxm5v/) |
|
| 28 |
-
| **KPATH** | 10.5281/zenodo.22694329 | 10.6084/m9.figshare.33559513 | 10.7910/DVN/8QIUD4 | [fbcyw](https://osf.io/fbcyw/) |
|
| 29 |
-
| **KPILOT** | 10.5281/zenodo.22694331 | 10.6084/m9.figshare.33559525 | 10.7910/DVN/EYD6FZ | [aqxe8](https://osf.io/aqxe8/) |
|
| 30 |
-
| **KQROSS** | 10.5281/zenodo.22694333 | 10.6084/m9.figshare.33559537 | 10.7910/DVN/IIDBCF | [zp82a](https://osf.io/zp82a/) |
|
| 31 |
-
| **KQUBIT** | 10.5281/zenodo.22694336 | 10.6084/m9.figshare.33559546 | 10.7910/DVN/2BC8BL | [eqr9z](https://osf.io/eqr9z/) |
|
| 32 |
-
| **KSENSE** | 10.5281/zenodo.22694338 | 10.6084/m9.figshare.33559558 | 10.7910/DVN/5LQJAF | [psr8h](https://osf.io/psr8h/) |
|
| 33 |
-
| **KWARD** | 10.5281/zenodo.22694342 | 10.6084/m9.figshare.33559570 | 10.7910/DVN/VPYXHS | [ugfpr](https://osf.io/ugfpr/) |
|
| 34 |
-
| **KYRO** | 10.5281/zenodo.22694348 | 10.6084/m9.figshare.33559582 | 10.7910/DVN/2YQQOX | [5m6vu](https://osf.io/5m6vu/) |
|
| 35 |
-
|
| 36 |
-
_Generated from publish/state/*.json. Zenodo/Figshare DOIs are permanent; Dataverse DOIs activate when Harvard curators approve the review submissions._
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
publish/MANIFEST.sha256
DELETED
|
@@ -1,41 +0,0 @@
|
|
| 1 |
-
# KODEX SHA-256 manifest (v0.1.0, 2026-09-10)
|
| 2 |
-
|
| 3 |
-
2ac66d4d7d4a89054d47e15215b9d6eca8e527503763b9b05c85b65160f5d8ec .gitignore
|
| 4 |
-
8695a176b58590a0bbc6b7ede1c0ce4a270c54115aa06777e1462bfebe86bd1a .zenodo.json
|
| 5 |
-
b1ee5fa8a901a64265186e58788f420b94c37151a61144a3c24ed37d782325e3 BENCHMARKS.md
|
| 6 |
-
9bb42b66491b72e95cfc26b4139c767ec7eda643d479061183c65af55db56d44 CITATION.cff
|
| 7 |
-
889dc088a39f3b908cc627dcbd09e252a75abea42f716f664eafcf7d8b7ff578 CODES.md
|
| 8 |
-
16f411de9a68f30ea8f05572c7a2aebe8cd923acec35bb55441b1a92861ce7c2 FAMILY.md
|
| 9 |
-
ae87ebecd1f321a19799e21f6fe25e4a74261f16c91e6cb6cc248e6197dcf838 LICENSE
|
| 10 |
-
faf6dbd85a3cd3b9879201b7470e7ba858ae560108b7c984ec33809081d51a3d README.md
|
| 11 |
-
8d2e3d7856756d03007be14187b5dd5bf10e22160e9f04103015141c04643d42 benchmarks/benchmarks.json
|
| 12 |
-
361ef1108dc3ea2c4d6499b47ea4617a528a53bef4254abafdb889568a2772d3 benchmarks/run_all.py
|
| 13 |
-
5e138e573eeaaaf7a5c2b0c74570adbf7cb132058f2c8c2dd7c25e3c18a4d77f checkpoints/kore_mlp_seed0.pt
|
| 14 |
-
a251c80fc84f2c46be0a8aa822bc5a3619c32019627d0d35001531d0b5d3be19 checkpoints/kore_mlp_seed1.pt
|
| 15 |
-
525cecaf99600dd7ccddb1d25a84fa216ab71739d73c39b62bb04d1e434bfd76 checkpoints/kore_mlp_seed2.pt
|
| 16 |
-
6e5136d13e3e0b8335d146e65dce940b54e38e0e6a7bfe1fbdb3af8ea8483d88 codemeta.json
|
| 17 |
-
162d8a2ba10cead49dd9be7276dc7c57177f151f174d1ea623ad1f65fce2d43a demo.ipynb
|
| 18 |
-
b4233195b725817a61d1801f7c744159486076bae1c3bb9fd7d0e9ab9070f3dd kronos_ml/__init__.py
|
| 19 |
-
835650847427eb59f9240a6bbcd1db4ec739eacef974aa0200944bbe3348043e kronos_ml/_torch.py
|
| 20 |
-
c094cca7d3393317f8e412f41211b073be1701560b8c2923f84ab1e0bf770753 kronos_ml/base.py
|
| 21 |
-
510bf0fe2c2ce159dec25629ad903e3b0de1e97fdc2621b80efce87e4d6c33a7 kronos_ml/data.py
|
| 22 |
-
5d34c8aec99f9f7c5e6f62cb3b02b1aafeb311bb94d38f880d9ae6de63e51733 kronos_ml/members/__init__.py
|
| 23 |
-
e5b88836b177c757a4f2db0925eac364ad12abe8c18038e14be9432286c03e61 kronos_ml/members/advanced.py
|
| 24 |
-
f87aaf941a7ee00200f18bd35d68880e5365d62aa48bb029ab64e0091f16888e kronos_ml/members/capstone.py
|
| 25 |
-
2b1d273280c16b1771cf1fd745aa558b967d9dac0684eb722dfdc867812fe9d1 kronos_ml/members/control.py
|
| 26 |
-
5c340f9813497f5382b3a5324b76311b216f5696c9d8f3b2d0fb8f7491d7f671 kronos_ml/members/disrupt.py
|
| 27 |
-
3f881fef3d4b8b255907c3adda0c3936b335c4aadb51e7a566bf4095bd058c29 kronos_ml/members/equil.py
|
| 28 |
-
56d7f4b0b4072224772e3a59f1642ef4e5f5afaf70575636775a73a891f6e0d3 kronos_ml/members/fusion.py
|
| 29 |
-
a8639ff450bb27a42771a2251ee852291ecaf09c4a1795cfc790ce67a84b808e kronos_ml/members/magnet.py
|
| 30 |
-
9265df980412b82ef2185fb3d143c93780f4da76fda72fa4b6b010b6ae06b3de kronos_ml/members/materials.py
|
| 31 |
-
f843996eeaa949e470ecce22713e5505649ce9fc1a7f5a6cdfca425a2ded09dc kronos_ml/members/neutronics.py
|
| 32 |
-
2708133806780dce88184fa19c03b3760f207788c78d9e8edddcecd35f991e5e kronos_ml/members/plant.py
|
| 33 |
-
ad05706b4f588e413b1314ebe7b3069c57a21ccf040d6fb762eb731aeda41584 kronos_ml/members/quantum.py
|
| 34 |
-
c9b921c1131b95831366c0197663b486ea1c9a302b119ef3880249d6c897c7bf kronos_ml/members/roadmap.py
|
| 35 |
-
75c01157cea0ab64f6a3458d76e69fa2be386fd5e4c6168d6e08d41e46a53c15 kronos_ml/members/spine.py
|
| 36 |
-
eca2a363d02653b4fbe5e68df2ca41ecb5c277fd66fea22694681d648ecf7f64 kronos_ml/members/state.py
|
| 37 |
-
f6466e59e49482d4423fb0415e3a7e4377eada9d2544a734a23a82974730e60f kronos_ml/members/transport.py
|
| 38 |
-
508a45df51b194c435bfdd2d79658bff66bb77913a0ea66cea40116a7867266a kronos_ml/metrics.py
|
| 39 |
-
578e86ef6f3faa7cce6682541d6cedb52c7f652d187085088dc3a4e8ccd4b5db kronos_ml/uq.py
|
| 40 |
-
0f1af657ccf7539ab9dbbc2dd5408afa08085670d9c896bd5e95cbb4352124ec pyproject.toml
|
| 41 |
-
54516950a748b00bc0992388ae3ae1a3fda3739307e7f2b651670896fb30c823 tests/test_contract.py
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
publish/PROVENANCE.md
DELETED
|
@@ -1,42 +0,0 @@
|
|
| 1 |
-
# KODEX provenance & traceability (v0.1.0, 2026-09-10)
|
| 2 |
-
|
| 3 |
-
Each BUILT code traces: **code -> real benchmark -> on-disk data/method -> Kronos corpus DOI -> /kodex page.**
|
| 4 |
-
|
| 5 |
-
| # | Code | Ph | Provenance | Real source/method | Corpus anchor | Page |
|
| 6 |
-
|--|--|--|--|--|--|--|
|
| 7 |
-
| 01 | **KAIROS** | 1 | TWIN | receding-horizon MPC | references:10.5281/zenodo.21842371; references:10.5281/zenodo.22645689 | kairos |
|
| 8 |
-
| 02 | **KBREED** | 2 | SIM | openmc | references:10.5281/zenodo.22645689 | kbreed |
|
| 9 |
-
| 03 | **KBURN** | 2 | TWIN | plant systems model | references:10.5281/zenodo.21842371; references:10.5281/zenodo.22645689 | kburn |
|
| 10 |
-
| 04 | **KDRIVE** | 3 | TWIN | reinforcement learning | references:10.5281/zenodo.21842371; references:10.5281/zenodo.22645689 | kdrive |
|
| 11 |
-
| 05 | **KECON** | 3 | n/a | open LCOE methodology | references:10.5281/zenodo.21842371; references:10.5281/zenodo.22645689 | kecon |
|
| 12 |
-
| 06 | **KEYE** | 2 | SIM | sensor fusion, signal validation | references:10.5281/zenodo.21842371; references:10.5281/zenodo.22645689 | keye |
|
| 13 |
-
| 07 | **KFLOW** | 1 | SIM | message-passing GNN | references:10.5281/zenodo.21842371; references:10.5281/zenodo.22645689 | kflow |
|
| 14 |
-
| 08 | **KFLUX** | 2 | SIM | openmc | references:10.5281/zenodo.22645689 | kflux |
|
| 15 |
-
| 09 | **KFORGE** | 3 | CGYRO-urep | differential evolution over the fleet | isDerivedFrom:10.5281/zenodo.22136279 | kforge |
|
| 16 |
-
| 10 | **KFUEL** | 3 | SIM | fuel-cycle systems model | references:10.5281/zenodo.21842371; references:10.5281/zenodo.22645689 | kfuel |
|
| 17 |
-
| 11 | **KFUSE** | 2 | CGYRO-urep | multi-fidelity GP, CGYRO | isDerivedFrom:10.5281/zenodo.22136279 | kfuse |
|
| 18 |
-
| 12 | **KGATE** | 1 | TWIN | CBF certificate, hardware failsafe | references:10.5281/zenodo.21842371; references:10.5281/zenodo.22645689 | kgate |
|
| 19 |
-
| 13 | **KGEN** | 3 | ANALYTIC | generative model | references:10.5281/zenodo.21842371; references:10.5281/zenodo.22645689 | kgen |
|
| 20 |
-
| 14 | **KHALO** | 1 | SIM | deep-ensemble, conformal | references:10.5281/zenodo.21842371; references:10.5281/zenodo.22645689 | khalo |
|
| 21 |
-
| 15 | **KISO** | 2 | SIM | isotope PI servo, FENDL-3.2 activation | references:10.5281/zenodo.22645689; isDerivedFrom:https://www-nds.iaea.org/fendl/ | kiso |
|
| 22 |
-
| 16 | **KLAW** | 3 | CGYRO-urep | sparse regression / SINDy | isDerivedFrom:10.5281/zenodo.22136279 | klaw |
|
| 23 |
-
| 17 | **KMAT** | 1 | SIM | CHGNet, DFT | references:10.5281/zenodo.21842371; references:10.5281/zenodo.22645689 | kmat |
|
| 24 |
-
| 18 | **KOIL** | 1 | SIM | finite-element stress solve | references:10.5281/zenodo.21842371; references:10.5281/zenodo.22645689 | koil |
|
| 25 |
-
| 19 | **KORE** | 1 | ANALYTIC | Grad-Shafranov FD solver | references:10.5281/zenodo.21842371; references:10.5281/zenodo.22645689 | kore |
|
| 26 |
-
| 20 | **KPATH** | 2 | TWIN | MPC scenario optimizer | references:10.5281/zenodo.21842371; references:10.5281/zenodo.22645689 | kpath |
|
| 27 |
-
| 21 | **KPILOT** | 3 | n/a | fleet router / tool dispatcher | references:10.5281/zenodo.21842371; references:10.5281/zenodo.22645689 | kpilot |
|
| 28 |
-
| 22 | **KQROSS** | 2 | SIM | FT resource estimation | isDerivedFrom:10.5281/zenodo.21842371 | kqross |
|
| 29 |
-
| 23 | **KQUBIT** | 1 | SIM | VQE, quantum chemistry | isDerivedFrom:10.5281/zenodo.21842371 | kqubit |
|
| 30 |
-
| 24 | **KSENSE** | 2 | SIM | NV/SQUID/SERF magnetometry | isDerivedFrom:10.5281/zenodo.21842371 | ksense |
|
| 31 |
-
| 25 | **KWARD** | 1 | REAL-ANCHOR | real MAST shots (FAIR-MAST) | isDerivedFrom:https://mastapp.site; references:10.5281/zenodo.22645689 | kward |
|
| 32 |
-
| 26 | **KYRO** | 1 | CGYRO-urep | cgyro, gene, gs2, tglf | isDerivedFrom:10.5281/zenodo.22136279 | kyro |
|
| 33 |
-
|
| 34 |
-
## Held as ROADMAP (4)
|
| 35 |
-
|
| 36 |
-
- **KEDGE** (ROADMAP, phase 3) — divertor / SOL / edge heat-flux transport surrogate
|
| 37 |
-
- **KHEAT** (PARTIAL, phase 2) — RF / NBI heating & current-drive actuator-response surrogate
|
| 38 |
-
- **KRAD** (ROADMAP, phase 3) — impurity seeding / radiation / divertor-detachment control
|
| 39 |
-
- **KTENSOR** (PARTIAL, phase 2) — tensor-network simulation & compression — a classical many-body method and a bridge to quantum for kernel problems
|
| 40 |
-
|
| 41 |
-
Anchor DOIs: CGYRO `10.5281/zenodo.22136279` · Register `10.5281/zenodo.22645689` · AI+Quantum `10.5281/zenodo.21842371` · toolkit https://github.com/KronosFE/kronos-toolkit
|
| 42 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
publish/PUBLISH_RUNBOOK.md
DELETED
|
@@ -1,158 +0,0 @@
|
|
| 1 |
-
# KODEX — publish runbook (PER-CODE, DRAFT-FIRST)
|
| 2 |
-
|
| 3 |
-
**Release:** KODEX v0.1.0 — the Kronos Family of Codes.
|
| 4 |
-
**Model:** **26 per-code records** on each data repository (Zenodo / OSF / Figshare / Harvard Dataverse /
|
| 5 |
-
Internet Archive) — each BUILT code gets its own record + DOI. **GitHub = ONE repo** (`kronos-ml`, 26
|
| 6 |
-
modules). **PyPI = ONE package** (`kronos-ml`, 26 importable codes). **Held as ROADMAP (not published):**
|
| 7 |
-
KHEAT, KTENSOR, KEDGE, KRAD.
|
| 8 |
-
**Author on every record:** Ford, P. I. · ORCID `0000-0003-0395-1752` · Kronos Fusion Energy · Apache-2.0.
|
| 9 |
-
|
| 10 |
-
> **Draft-first, two-step per data venue.** Step 1 `*_draft.py` creates all 26 records as **private/
|
| 11 |
-
> unpublished** and uploads each code's files — nothing is public. Step 2 `*_publish_all.py` is a **dry run
|
| 12 |
-
> by default** and publishes only with an explicit **`--yes`** — that `--yes` is your single deliberate
|
| 13 |
-
> authorization for that venue's 26. The draft scripts NEVER publish; the publish scripts do nothing
|
| 14 |
-
> without `--yes`. (Internet Archive is one step — items are public on upload — so `ia_upload_all.py`
|
| 15 |
-
> requires `--yes` and IS the publish.)
|
| 16 |
-
|
| 17 |
-
Per-code metadata lives in `publish/records/<code>/metadata.json`; each record's homepage is
|
| 18 |
-
`kronosfusionenergy.com/kodex/<code>`, with its physics-source + the shared Kronos anchors
|
| 19 |
-
(register `10.5281/zenodo.22645689`, CGYRO `10.5281/zenodo.22136279`, AI+Quantum `10.5281/zenodo.21842371`,
|
| 20 |
-
toolkit) as related-identifiers, honest card preserved. Per-code attach set: `<code>.py` (source excerpt),
|
| 21 |
-
`benchmark.json`, `card.md`, `CITATION.cff`, `LICENSE`, `MANIFEST.sha256`. The repo-root `.zenodo.json`,
|
| 22 |
-
`CITATION.cff`, `codemeta.json` describe the **GitHub/PyPI package** (the one-repo/one-package side).
|
| 23 |
-
|
| 24 |
-
## Token map
|
| 25 |
-
|
| 26 |
-
| Venue | Credential | Env var | Status |
|
| 27 |
-
|---|---|---|---|
|
| 28 |
-
| GitHub | SSH key | — | ✅ ready |
|
| 29 |
-
| Zenodo | token `deposit:write` | `ZENODO_TOKEN` | ✅ ready |
|
| 30 |
-
| OSF | token `osf.full_write` | `OSF_TOKEN` | ✅ ready |
|
| 31 |
-
| Figshare | personal token | `FIGSHARE_TOKEN` | ✅ ready |
|
| 32 |
-
| Internet Archive | `ia configure` (S3 keys) | — | ✅ ready |
|
| 33 |
-
| Harvard Dataverse | API token (115-paper/books token) | `DATAVERSE_TOKEN` + `DATAVERSE_CONTACT_EMAIL` | ⏳ token needed |
|
| 34 |
-
| PyPI | API token | `TWINE_PASSWORD` (`TWINE_USERNAME=__token__`) | ⏳ fast-follow |
|
| 35 |
-
| Hugging Face | write token | `HF_TOKEN` | ⏳ fast-follow |
|
| 36 |
-
|
| 37 |
-
## Preflight (once)
|
| 38 |
-
|
| 39 |
-
```bash
|
| 40 |
-
cd "/Users/pford/Desktop/Kronos Fusion Energy/04 - IT INFRASTRUCTURE/07 - IT Infrastructure & Code Repos/Code Repos (live)/kronos-ml"
|
| 41 |
-
PY=~/kronos-hpc-build/ml311_venv/bin/python
|
| 42 |
-
$PY -m pytest tests/ -q # expect 9 passed
|
| 43 |
-
$PY publish/_percode.py # (re)builds publish/records/<code>/ for all 26 (resume-safe)
|
| 44 |
-
```
|
| 45 |
-
|
| 46 |
-
> ⚠ **numpy pin:** this venv must keep **numpy<2** (torch 2.2.2 needs it; numpy 2.x breaks KORE). If a
|
| 47 |
-
> tool ever pulls numpy 2.x back in, run `$PY -m pip install "numpy==1.26.4"` before benchmarking.
|
| 48 |
-
|
| 49 |
-
---
|
| 50 |
-
|
| 51 |
-
## 1) GitHub — ONE repo (git@github.com:KronosFE/kronos-ml.git)
|
| 52 |
-
|
| 53 |
-
```bash
|
| 54 |
-
git init -b main
|
| 55 |
-
git add .
|
| 56 |
-
git commit -m "KODEX v0.1.0 — Kronos Family of Codes (26 BUILT surrogates)"
|
| 57 |
-
git tag -a v0.1.0 -m "KODEX v0.1.0"
|
| 58 |
-
# create the repo PRIVATE on GitHub, then:
|
| 59 |
-
git remote add origin git@github.com:KronosFE/kronos-ml.git
|
| 60 |
-
git push -u origin main --tags
|
| 61 |
-
# → review; when ready, make public + draft a Release from tag v0.1.0.
|
| 62 |
-
# Do NOT enable the GitHub↔Zenodo webhook (we deposit Zenodo per-code below).
|
| 63 |
-
```
|
| 64 |
-
|
| 65 |
-
## 2) Zenodo — 26 per-code records
|
| 66 |
-
|
| 67 |
-
```bash
|
| 68 |
-
export ZENODO_TOKEN=... # rehearse first: export ZENODO_BASE=https://sandbox.zenodo.org
|
| 69 |
-
$PY publish/zenodo_draft.py # creates 26 DRAFTS (resume-safe), nothing public
|
| 70 |
-
$PY publish/zenodo_publish_all.py # DRY RUN — lists the 26 drafts
|
| 71 |
-
$PY publish/zenodo_publish_all.py --yes # ← your one authorization: publishes all 26, mints DOIs
|
| 72 |
-
```
|
| 73 |
-
|
| 74 |
-
## 3) OSF — 26 private projects → public
|
| 75 |
-
|
| 76 |
-
```bash
|
| 77 |
-
export OSF_TOKEN=...
|
| 78 |
-
$PY publish/osf_draft.py # 26 PRIVATE projects
|
| 79 |
-
$PY publish/osf_publish_all.py # DRY RUN
|
| 80 |
-
$PY publish/osf_publish_all.py --yes # ← make all 26 public
|
| 81 |
-
```
|
| 82 |
-
|
| 83 |
-
## 4) Figshare — 26 draft articles → published
|
| 84 |
-
|
| 85 |
-
```bash
|
| 86 |
-
export FIGSHARE_TOKEN=...
|
| 87 |
-
$PY publish/figshare_draft.py # 26 DRAFT articles (DOIs reserved, not published)
|
| 88 |
-
$PY publish/figshare_publish_all.py # DRY RUN
|
| 89 |
-
$PY publish/figshare_publish_all.py --yes
|
| 90 |
-
```
|
| 91 |
-
|
| 92 |
-
## 5) Harvard Dataverse — 26 datasets (published by CURATORS, not by --yes)
|
| 93 |
-
|
| 94 |
-
STATUS 2026-09-10: the 26 drafts are created; **25 were submitted for Harvard curator review**
|
| 95 |
-
(`review:true` in state) and publish when a Harvard **curator approves** — NOT via a depositor
|
| 96 |
-
`--yes`. `dataverse_publish_all.py` now refuses to `:publish` review-queued datasets (a direct
|
| 97 |
-
publish on an In-Review dataset errors), so `--yes` is a no-op for the 25. Two open items before
|
| 98 |
-
curators approve (the published version is immutable):
|
| 99 |
-
|
| 100 |
-
1. **KLAW** (`doi:10.7910/DVN/ANAFXK`) was NOT submitted for review — submit it so it isn't stranded:
|
| 101 |
-
```bash
|
| 102 |
-
export DATAVERSE_TOKEN=...
|
| 103 |
-
curl -H "X-Dataverse-key:$DATAVERSE_TOKEN" -X POST \
|
| 104 |
-
"https://dataverse.harvard.edu/api/datasets/:persistentId/submitForReview?persistentId=doi:10.7910/DVN/ANAFXK"
|
| 105 |
-
# then set "review": true for KLAW in publish/state/dataverse_drafts.json
|
| 106 |
-
```
|
| 107 |
-
2. **License field**: the drafts carry no dataset-level license, so Harvard will publish them as
|
| 108 |
-
**CC0** unless Apache-2.0 is set. Check + set before approval:
|
| 109 |
-
```bash
|
| 110 |
-
curl -s -H "X-Dataverse-key:$DATAVERSE_TOKEN" https://dataverse.harvard.edu/api/licenses | grep -i apache
|
| 111 |
-
# if Apache-2.0 is installed, set it on each draft version (API) before curator approval;
|
| 112 |
-
# otherwise the Apache-2.0 statement in the description + bundled LICENSE stand, and you accept CC0.
|
| 113 |
-
```
|
| 114 |
-
(Re-running `dataverse_draft.py` is safe — it skips the 26 already-created datasets.)
|
| 115 |
-
|
| 116 |
-
## 6) Internet Archive — 26 items (public on upload; one step)
|
| 117 |
-
|
| 118 |
-
```bash
|
| 119 |
-
ia configure # once, with your IA S3 keys
|
| 120 |
-
$PY publish/ia_upload_all.py # DRY RUN — lists the 26 item identifiers
|
| 121 |
-
$PY publish/ia_upload_all.py --yes # ← uploads 26 items (PUBLIC immediately)
|
| 122 |
-
```
|
| 123 |
-
|
| 124 |
-
---
|
| 125 |
-
|
| 126 |
-
## Fast-follow (when the tokens land)
|
| 127 |
-
|
| 128 |
-
### PyPI — ONE package
|
| 129 |
-
```bash
|
| 130 |
-
$PY -m build
|
| 131 |
-
export TWINE_USERNAME=__token__ TWINE_PASSWORD=pypi-...
|
| 132 |
-
$PY -m twine upload --repository testpypi dist/* # rehearse first
|
| 133 |
-
$PY -m twine upload dist/*
|
| 134 |
-
```
|
| 135 |
-
|
| 136 |
-
### Hugging Face — per-code model repos (or one)
|
| 137 |
-
```bash
|
| 138 |
-
export HF_TOKEN=...
|
| 139 |
-
$PY -m pip install -q huggingface_hub
|
| 140 |
-
# one suite repo:
|
| 141 |
-
huggingface-cli upload KronosFE/kronos-ml . . --repo-type=model --token "$HF_TOKEN"
|
| 142 |
-
# (per-code repos KronosFE/kodex-<code> can be scripted the same way if preferred)
|
| 143 |
-
```
|
| 144 |
-
|
| 145 |
-
---
|
| 146 |
-
|
| 147 |
-
## Rollback (discard drafts — nothing was public)
|
| 148 |
-
- **Zenodo / Figshare / Dataverse:** delete the unpublished drafts in each UI (or via each API).
|
| 149 |
-
- **OSF:** projects are private until `--yes`; delete in the UI.
|
| 150 |
-
- **GitHub:** repo stays private until you flip it.
|
| 151 |
-
- **Internet Archive:** items are public on upload — only run `--yes` when you're sure; ask IA support to
|
| 152 |
-
dark an item if needed.
|
| 153 |
-
- Re-running any `*_draft.py` is safe: it skips codes already in `publish/state/<venue>_drafts.json`.
|
| 154 |
-
|
| 155 |
-
## Provenance recorded in every record
|
| 156 |
-
code → real benchmark (`benchmark.json`) → on-disk data/method → Kronos corpus DOI → `/kodex/<code>` page.
|
| 157 |
-
Honest cards intact: μ=400 representative-mass (CGYRO codes); validated null result (quantum codes);
|
| 158 |
-
KWARD heuristic labels + independent-precursor AUC 0.975 (n=1 Mirnov + P_rad only); KECON financial firewall.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
publish/_deposit_common.py
DELETED
|
@@ -1,68 +0,0 @@
|
|
| 1 |
-
"""Shared helpers for the KODEX draft-first deposits.
|
| 2 |
-
|
| 3 |
-
Builds a clean release archive and defines the attach list + metadata. Imported by
|
| 4 |
-
zenodo_draft.py / osf_draft.py / figshare_draft.py. NONE of those scripts ever call
|
| 5 |
-
a venue's publish/complete endpoint — they create a DRAFT and upload files, then
|
| 6 |
-
print the draft URL for the founder to review and publish herself.
|
| 7 |
-
"""
|
| 8 |
-
from __future__ import annotations
|
| 9 |
-
import json, os, zipfile
|
| 10 |
-
from pathlib import Path
|
| 11 |
-
|
| 12 |
-
REPO = Path(__file__).resolve().parent.parent
|
| 13 |
-
PUB = REPO / "publish"
|
| 14 |
-
VERSION = json.load(open(PUB / "_scaffolding_summary.json"))["version"]
|
| 15 |
-
ARCHIVE = PUB / f"kronos-ml-v{VERSION}-source.zip"
|
| 16 |
-
|
| 17 |
-
# individual human-readable artifacts attached alongside the source archive
|
| 18 |
-
DOCS = ["README.md", "FAMILY.md", "CODES.md", "BENCHMARKS.md", "benchmarks/benchmarks.json",
|
| 19 |
-
"demo.ipynb", "CITATION.cff", "LICENSE", "codemeta.json", ".zenodo.json",
|
| 20 |
-
"publish/PROVENANCE.md", "publish/MANIFEST.sha256"]
|
| 21 |
-
|
| 22 |
-
_SKIP_DIRS = {"__pycache__", ".git", ".ipynb_checkpoints", ".pytest_cache", "dist"}
|
| 23 |
-
_SKIP_SUFFIX = {".pyc", ".pyo"}
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
def build_archive() -> Path:
|
| 27 |
-
"""Zip the whole package (source + tests + docs + manifest), minus cruft."""
|
| 28 |
-
with zipfile.ZipFile(ARCHIVE, "w", zipfile.ZIP_DEFLATED) as z:
|
| 29 |
-
for root, dirs, files in os.walk(REPO):
|
| 30 |
-
dirs[:] = [d for d in dirs if d not in _SKIP_DIRS]
|
| 31 |
-
for fn in files:
|
| 32 |
-
p = Path(root) / fn
|
| 33 |
-
if p.suffix in _SKIP_SUFFIX or p == ARCHIVE:
|
| 34 |
-
continue
|
| 35 |
-
if p.name.endswith(".parquet"):
|
| 36 |
-
continue
|
| 37 |
-
z.write(p, p.relative_to(REPO))
|
| 38 |
-
return ARCHIVE
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
def attach_paths() -> list[Path]:
|
| 42 |
-
"""Full attach set: the source archive + the individual docs f7 asked for."""
|
| 43 |
-
out = [build_archive()]
|
| 44 |
-
for rel in DOCS:
|
| 45 |
-
p = REPO / rel
|
| 46 |
-
if p.exists():
|
| 47 |
-
out.append(p)
|
| 48 |
-
return out
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
def zenodo_metadata() -> dict:
|
| 52 |
-
return json.load(open(REPO / ".zenodo.json"))
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
def require_env(var: str) -> str:
|
| 56 |
-
v = os.environ.get(var)
|
| 57 |
-
if not v:
|
| 58 |
-
raise SystemExit(f"[STOP] environment variable {var} is not set. "
|
| 59 |
-
f"Export your token first (see PUBLISH_RUNBOOK.md).")
|
| 60 |
-
return v
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
if __name__ == "__main__":
|
| 64 |
-
paths = attach_paths()
|
| 65 |
-
print(f"archive: {ARCHIVE.name}")
|
| 66 |
-
print(f"attach set ({len(paths)} files):")
|
| 67 |
-
for p in paths:
|
| 68 |
-
print(f" {p.relative_to(REPO)} ({p.stat().st_size:,} B)")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
publish/_percode.py
DELETED
|
@@ -1,256 +0,0 @@
|
|
| 1 |
-
"""Per-code deposit engine for KODEX (26 BUILT codes -> 26 records per data venue).
|
| 2 |
-
|
| 3 |
-
Generates publish/records/<kname>/ (metadata + per-code attach set) and provides the
|
| 4 |
-
shared helpers the venue scripts use to loop. State (created draft ids/DOIs) is written
|
| 5 |
-
to publish/state/<venue>_drafts.json so a run can resume and the batch-publish step
|
| 6 |
-
knows exactly what to act on.
|
| 7 |
-
|
| 8 |
-
DRAFT-FIRST: nothing here publishes. The *_draft.py scripts create drafts; the separate
|
| 9 |
-
*_publish_all.py scripts publish only drafts listed in the state file, only with --yes.
|
| 10 |
-
"""
|
| 11 |
-
from __future__ import annotations
|
| 12 |
-
import hashlib, html, inspect, json, os, random, re, shutil, sys, time
|
| 13 |
-
from datetime import date
|
| 14 |
-
from pathlib import Path
|
| 15 |
-
|
| 16 |
-
_RETRY_CODES = {403, 408, 425, 429, 500, 502, 503, 504}
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
def http_retry(fn, *, tries=6, base=0.8, label=""):
|
| 20 |
-
"""Call fn() -> requests.Response; retry transient/rate-limit codes with expo backoff.
|
| 21 |
-
Returns the final Response (caller still checks .ok / raises). 2xx returns immediately."""
|
| 22 |
-
r = None
|
| 23 |
-
for i in range(tries):
|
| 24 |
-
r = fn()
|
| 25 |
-
if 200 <= r.status_code < 300 or r.status_code not in _RETRY_CODES or i == tries - 1:
|
| 26 |
-
return r
|
| 27 |
-
wait = base * (2 ** i) + random.random() * 0.4
|
| 28 |
-
sys.stderr.write(f" [retry] {label} {r.status_code}; sleep {wait:.1f}s ({i+1}/{tries})\n")
|
| 29 |
-
time.sleep(wait)
|
| 30 |
-
return r
|
| 31 |
-
|
| 32 |
-
REPO = Path(__file__).resolve().parent.parent
|
| 33 |
-
PUB = REPO / "publish"
|
| 34 |
-
REC_ROOT = PUB / "records"
|
| 35 |
-
STATE_ROOT = PUB / "state"
|
| 36 |
-
sys.path.insert(0, str(REPO)); sys.path.insert(0, str(REPO.parent / "kronos-toolkit"))
|
| 37 |
-
os.environ.setdefault("PYTHONWARNINGS", "ignore")
|
| 38 |
-
import warnings; warnings.filterwarnings("ignore")
|
| 39 |
-
import kronos_ml as K
|
| 40 |
-
|
| 41 |
-
TODAY = date.today().isoformat()
|
| 42 |
-
VERSION = K.__version__
|
| 43 |
-
ORCID = "0000-0003-0395-1752"
|
| 44 |
-
AFFIL = "Kronos Fusion Energy"
|
| 45 |
-
KODEX = "https://kronosfusionenergy.com/kodex"
|
| 46 |
-
REPO_URL = "https://github.com/KronosFE/kronos-ml"
|
| 47 |
-
TOOLKIT_URL = "https://github.com/KronosFE/kronos-toolkit"
|
| 48 |
-
LICENSE = "Apache-2.0"
|
| 49 |
-
|
| 50 |
-
DOI_REGISTER = "10.5281/zenodo.22645689"
|
| 51 |
-
DOI_CGYRO = "10.5281/zenodo.22136279"
|
| 52 |
-
DOI_AIQ = "10.5281/zenodo.21842371"
|
| 53 |
-
|
| 54 |
-
KEYWORDS_BASE = ["fusion energy", "spherical tokamak", "D-3He", "AI/ML surrogate model",
|
| 55 |
-
"uncertainty quantification", "digital twin", "Kronos Fusion Energy"]
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
def built():
|
| 59 |
-
"""The codes a publish run acts on: every BUILT code, unless KODEX_PUBLISH_ONLY
|
| 60 |
-
restricts it to an explicit allow-list (comma/space-separated code names).
|
| 61 |
-
|
| 62 |
-
The allow-list is how an operator deposits a deliberate SUBSET (e.g. only the
|
| 63 |
-
v0.2.0 additions) without touching the rest of the fleet — it does NOT change any
|
| 64 |
-
code's real status, so the package stays honest. Unset = all BUILT (default). A
|
| 65 |
-
named code that is not currently BUILT is a hard error, so a typo can never
|
| 66 |
-
silently narrow (or widen) the set.
|
| 67 |
-
"""
|
| 68 |
-
names = sorted(n for n in K.list_surrogates() if K.get(n).status == "BUILT")
|
| 69 |
-
only = os.environ.get("KODEX_PUBLISH_ONLY", "").strip()
|
| 70 |
-
if only:
|
| 71 |
-
want = {c.strip().upper() for c in re.split(r"[,\s]+", only) if c.strip()}
|
| 72 |
-
unknown = want - set(names)
|
| 73 |
-
if unknown:
|
| 74 |
-
raise SystemExit(f"[STOP] KODEX_PUBLISH_ONLY names not in the BUILT set: "
|
| 75 |
-
f"{sorted(unknown)} (BUILT: {names})")
|
| 76 |
-
names = [n for n in names if n in want]
|
| 77 |
-
sys.stderr.write(f"[scope] KODEX_PUBLISH_ONLY -> {len(names)} codes: {names}\n")
|
| 78 |
-
return names
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
def physics_source(s):
|
| 82 |
-
"""(relation, identifier, note) list tracing a code to its real physics source."""
|
| 83 |
-
p = (s.provenance or "").upper()
|
| 84 |
-
if "CGYRO" in p:
|
| 85 |
-
return [("isDerivedFrom", DOI_CGYRO, "CGYRO A1e nonlinear-kinetic turbulence map (mu=400)")]
|
| 86 |
-
if p == "REAL-ANCHOR":
|
| 87 |
-
return [("isDerivedFrom", "https://mastapp.site", "FAIR-MAST real-device data (UKAEA)")]
|
| 88 |
-
if s.name in ("KQUBIT", "KQROSS", "KSENSE", "KTENSOR"):
|
| 89 |
-
return [("isDerivedFrom", DOI_AIQ, "Kronos AI + Quantum deposit")]
|
| 90 |
-
if s.name in ("KBREED", "KFLUX"):
|
| 91 |
-
return [("references", DOI_REGISTER, "De-Risking Register neutronics gates")]
|
| 92 |
-
if s.name == "KISO":
|
| 93 |
-
return [("isDerivedFrom", "https://www-nds.iaea.org/fendl/", "FENDL-3.2 activation data (IAEA)"),
|
| 94 |
-
("references", DOI_REGISTER, "De-Risking Register")]
|
| 95 |
-
return [("references", DOI_AIQ, "Kronos AI + Quantum corpus")]
|
| 96 |
-
|
| 97 |
-
|
| 98 |
-
def _headline(name, b):
|
| 99 |
-
try:
|
| 100 |
-
from benchmarks.run_all import _headline as hl
|
| 101 |
-
return hl(name, b)
|
| 102 |
-
except Exception:
|
| 103 |
-
return (b or {}).get("note", "")
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
def record_meta(name, b=None):
|
| 107 |
-
s = K.get(name); kn = name.lower()
|
| 108 |
-
if b is None:
|
| 109 |
-
b = s.benchmark()
|
| 110 |
-
page = f"{KODEX}/{kn}"
|
| 111 |
-
src = physics_source(s)
|
| 112 |
-
related = [{"relation": "isDocumentedBy", "identifier": page, "resource_type": "publication-other"},
|
| 113 |
-
{"relation": "isPartOf", "identifier": KODEX, "resource_type": "publication-other"},
|
| 114 |
-
{"relation": "isSupplementTo", "identifier": REPO_URL, "resource_type": "software"},
|
| 115 |
-
{"relation": "references", "identifier": DOI_REGISTER, "resource_type": "publication"},
|
| 116 |
-
{"relation": "isCompiledBy", "identifier": TOOLKIT_URL, "resource_type": "software"}]
|
| 117 |
-
for rel, ident, _ in src:
|
| 118 |
-
rtype = "dataset" if ident.startswith("10.") or "mast" in ident or "fendl" in ident else "other"
|
| 119 |
-
related.append({"relation": rel, "identifier": ident, "resource_type": rtype})
|
| 120 |
-
# dedupe by (relation, identifier), keeping first (e.g. register DOI appended by both
|
| 121 |
-
# the base list and physics_source for KBREED/KFLUX/KISO)
|
| 122 |
-
_seen, _ded = set(), []
|
| 123 |
-
for r in related:
|
| 124 |
-
k = (r["relation"], r["identifier"])
|
| 125 |
-
if k not in _seen:
|
| 126 |
-
_seen.add(k); _ded.append(r)
|
| 127 |
-
related = _ded
|
| 128 |
-
desc = (f"<p><strong>KODEX — {name}</strong> ({s.function}). {(s.note or '').strip()}</p>"
|
| 129 |
-
f"<p><strong>Benchmark:</strong> {_headline(name, b)}</p>"
|
| 130 |
-
f"<p>Part of KODEX, the Kronos Family of Codes — a benchmarked AI/ML fusion "
|
| 131 |
-
f"surrogate suite with calibrated uncertainty and an abstention gate "
|
| 132 |
-
f"(<code>predict(x) → (y, uncertainty, in_domain)</code>). Provenance: "
|
| 133 |
-
f"{'; '.join(f'{r} {i}' for r, i, _ in src)}. Home: <a href=\"{page}\">{page}</a> · "
|
| 134 |
-
f"suite: <a href=\"{REPO_URL}\">{REPO_URL}</a>. Licensed under Apache-2.0. "
|
| 135 |
-
f"Honest card preserved verbatim.</p>")
|
| 136 |
-
# plaintext variant for venues whose description field does NOT render HTML (OSF)
|
| 137 |
-
desc_plain = html.unescape(re.sub(r"<[^>]+>", "", desc)).strip()
|
| 138 |
-
return {
|
| 139 |
-
"kname": name, "page": page,
|
| 140 |
-
"title": f"KODEX — {name}: {s.function}",
|
| 141 |
-
"version": VERSION, "publication_date": TODAY, "language": "eng",
|
| 142 |
-
"upload_type": "software",
|
| 143 |
-
"creators": [{"name": "Ford, P. I.", "orcid": ORCID, "affiliation": AFFIL}],
|
| 144 |
-
"license": {"id": LICENSE},
|
| 145 |
-
"keywords": KEYWORDS_BASE + [s.function, f"KODEX:{name}"],
|
| 146 |
-
"related_identifiers": related,
|
| 147 |
-
"description": desc,
|
| 148 |
-
"description_plain": desc_plain,
|
| 149 |
-
"notes": (f"Draft-first per-code deposit. Full package: {REPO_URL}. "
|
| 150 |
-
f"Provenance chain in card.md + MANIFEST.sha256."),
|
| 151 |
-
}
|
| 152 |
-
|
| 153 |
-
|
| 154 |
-
def _sha(p):
|
| 155 |
-
h = hashlib.sha256()
|
| 156 |
-
with open(p, "rb") as f:
|
| 157 |
-
for c in iter(lambda: f.read(1 << 16), b""):
|
| 158 |
-
h.update(c)
|
| 159 |
-
return h.hexdigest()
|
| 160 |
-
|
| 161 |
-
|
| 162 |
-
def build_records():
|
| 163 |
-
REC_ROOT.mkdir(parents=True, exist_ok=True)
|
| 164 |
-
STATE_ROOT.mkdir(parents=True, exist_ok=True)
|
| 165 |
-
names = built()
|
| 166 |
-
for name in names:
|
| 167 |
-
d = REC_ROOT / name.lower()
|
| 168 |
-
if (d / "metadata.json").exists() and (d / "MANIFEST.sha256").exists():
|
| 169 |
-
continue # resume: already generated
|
| 170 |
-
s = K.get(name); kn = name.lower()
|
| 171 |
-
b = s.benchmark() # compute ONCE, reuse
|
| 172 |
-
d.mkdir(exist_ok=True)
|
| 173 |
-
# 1) source excerpt (the class), readable
|
| 174 |
-
try:
|
| 175 |
-
src_code = inspect.getsource(type(s))
|
| 176 |
-
except Exception:
|
| 177 |
-
src_code = f"# source not extractable for {name}\n"
|
| 178 |
-
(d / f"{kn}.py").write_text(
|
| 179 |
-
f'"""KODEX {name} — source excerpt (class). Full runnable package: {REPO_URL}"""\n\n'
|
| 180 |
-
+ src_code)
|
| 181 |
-
# 2) benchmark
|
| 182 |
-
(d / "benchmark.json").write_text(json.dumps(b, default=str, indent=2) + "\n")
|
| 183 |
-
# 3) card
|
| 184 |
-
c = s.card()
|
| 185 |
-
(d / "card.md").write_text(
|
| 186 |
-
f"# KODEX {name} — card\n\n"
|
| 187 |
-
+ "\n".join(f"- **{k}:** {v}" for k, v in c.items()) + "\n\n"
|
| 188 |
-
+ f"Benchmark headline: {_headline(name, b)}\n")
|
| 189 |
-
# 4) per-code CITATION.cff
|
| 190 |
-
(d / "CITATION.cff").write_text("\n".join([
|
| 191 |
-
"cff-version: 1.2.0",
|
| 192 |
-
f"title: \"KODEX — {name}: {s.function} (Kronos Family of Codes)\"",
|
| 193 |
-
f"version: \"{VERSION}\"", f"date-released: \"{TODAY}\"",
|
| 194 |
-
f"license: {LICENSE}", f"url: \"{KODEX}/{kn}\"",
|
| 195 |
-
f"repository-code: \"{REPO_URL}\"", "type: software", "authors:",
|
| 196 |
-
" - family-names: Ford", " given-names: \"P. I.\"",
|
| 197 |
-
f" orcid: \"https://orcid.org/{ORCID}\"", f" affiliation: \"{AFFIL}\"",
|
| 198 |
-
]) + "\n")
|
| 199 |
-
# 5) LICENSE
|
| 200 |
-
shutil.copyfile(REPO / "LICENSE", d / "LICENSE")
|
| 201 |
-
# 6) metadata
|
| 202 |
-
(d / "metadata.json").write_text(json.dumps(record_meta(name, b), indent=2) + "\n")
|
| 203 |
-
# 7) manifest
|
| 204 |
-
files = [p for p in sorted(d.iterdir()) if p.name != "MANIFEST.sha256"]
|
| 205 |
-
(d / "MANIFEST.sha256").write_text(
|
| 206 |
-
f"# KODEX {name} SHA-256 ({VERSION}, {TODAY})\n"
|
| 207 |
-
+ "\n".join(f"{_sha(p)} {p.name}" for p in files) + "\n")
|
| 208 |
-
(PUB / "_percode_summary.json").write_text(json.dumps(
|
| 209 |
-
{"version": VERSION, "date": TODAY, "n_records": len(names), "codes": names}, indent=2) + "\n")
|
| 210 |
-
return names
|
| 211 |
-
|
| 212 |
-
|
| 213 |
-
def record_dir(kname):
|
| 214 |
-
return REC_ROOT / kname.lower()
|
| 215 |
-
|
| 216 |
-
|
| 217 |
-
def attach_paths(kname):
|
| 218 |
-
d = record_dir(kname)
|
| 219 |
-
# metadata.json is included so the uploaded file set exactly equals the set the
|
| 220 |
-
# MANIFEST.sha256 hashes (sha256sum -c then verifies clean; -c skips the un-self-listed manifest)
|
| 221 |
-
order = [f"{kname.lower()}.py", "benchmark.json", "card.md",
|
| 222 |
-
"CITATION.cff", "LICENSE", "metadata.json", "MANIFEST.sha256"]
|
| 223 |
-
return [d / f for f in order if (d / f).exists()]
|
| 224 |
-
|
| 225 |
-
|
| 226 |
-
def load_meta(kname):
|
| 227 |
-
return json.loads((record_dir(kname) / "metadata.json").read_text())
|
| 228 |
-
|
| 229 |
-
|
| 230 |
-
def state_path(venue):
|
| 231 |
-
return STATE_ROOT / f"{venue}_drafts.json"
|
| 232 |
-
|
| 233 |
-
|
| 234 |
-
def read_state(venue):
|
| 235 |
-
p = state_path(venue)
|
| 236 |
-
return json.loads(p.read_text()) if p.exists() else {}
|
| 237 |
-
|
| 238 |
-
|
| 239 |
-
def write_state(venue, st):
|
| 240 |
-
STATE_ROOT.mkdir(parents=True, exist_ok=True)
|
| 241 |
-
state_path(venue).write_text(json.dumps(st, indent=2) + "\n")
|
| 242 |
-
|
| 243 |
-
|
| 244 |
-
def require_env(var):
|
| 245 |
-
v = os.environ.get(var)
|
| 246 |
-
if not v:
|
| 247 |
-
raise SystemExit(f"[STOP] environment variable {var} is not set (see PUBLISH_RUNBOOK.md).")
|
| 248 |
-
return v
|
| 249 |
-
|
| 250 |
-
|
| 251 |
-
if __name__ == "__main__":
|
| 252 |
-
names = build_records()
|
| 253 |
-
print(f"built {len(names)} per-code records under publish/records/:")
|
| 254 |
-
for n in names:
|
| 255 |
-
ap = attach_paths(n)
|
| 256 |
-
print(f" {n.lower():9s} {len(ap)} files, meta title={load_meta(n)['title']!r}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
publish/_percode_summary.json
DELETED
|
@@ -1,42 +0,0 @@
|
|
| 1 |
-
{
|
| 2 |
-
"version": "0.2.0",
|
| 3 |
-
"date": "2026-09-11",
|
| 4 |
-
"n_records": 35,
|
| 5 |
-
"codes": [
|
| 6 |
-
"KAIROS",
|
| 7 |
-
"KBENCH",
|
| 8 |
-
"KBREED",
|
| 9 |
-
"KBURN",
|
| 10 |
-
"KDRIVE",
|
| 11 |
-
"KDYN",
|
| 12 |
-
"KECON",
|
| 13 |
-
"KEDGE",
|
| 14 |
-
"KEYE",
|
| 15 |
-
"KFLOW",
|
| 16 |
-
"KFLUX",
|
| 17 |
-
"KFORGE",
|
| 18 |
-
"KFUEL",
|
| 19 |
-
"KFUSE",
|
| 20 |
-
"KGATE",
|
| 21 |
-
"KGEN",
|
| 22 |
-
"KHALO",
|
| 23 |
-
"KHEAT",
|
| 24 |
-
"KISO",
|
| 25 |
-
"KLAW",
|
| 26 |
-
"KMAT",
|
| 27 |
-
"KOIL",
|
| 28 |
-
"KORE",
|
| 29 |
-
"KPATH",
|
| 30 |
-
"KPILOT",
|
| 31 |
-
"KQERN",
|
| 32 |
-
"KQOPT",
|
| 33 |
-
"KQROSS",
|
| 34 |
-
"KQUBIT",
|
| 35 |
-
"KRAD",
|
| 36 |
-
"KSEEK",
|
| 37 |
-
"KSENSE",
|
| 38 |
-
"KTENSOR",
|
| 39 |
-
"KWARD",
|
| 40 |
-
"KYRO"
|
| 41 |
-
]
|
| 42 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
publish/_scaffolding_summary.json
DELETED
|
@@ -1,40 +0,0 @@
|
|
| 1 |
-
{
|
| 2 |
-
"version": "0.1.0",
|
| 3 |
-
"date": "2026-09-10",
|
| 4 |
-
"built": [
|
| 5 |
-
"KAIROS",
|
| 6 |
-
"KBREED",
|
| 7 |
-
"KBURN",
|
| 8 |
-
"KDRIVE",
|
| 9 |
-
"KECON",
|
| 10 |
-
"KEYE",
|
| 11 |
-
"KFLOW",
|
| 12 |
-
"KFLUX",
|
| 13 |
-
"KFORGE",
|
| 14 |
-
"KFUEL",
|
| 15 |
-
"KFUSE",
|
| 16 |
-
"KGATE",
|
| 17 |
-
"KGEN",
|
| 18 |
-
"KHALO",
|
| 19 |
-
"KISO",
|
| 20 |
-
"KLAW",
|
| 21 |
-
"KMAT",
|
| 22 |
-
"KOIL",
|
| 23 |
-
"KORE",
|
| 24 |
-
"KPATH",
|
| 25 |
-
"KPILOT",
|
| 26 |
-
"KQROSS",
|
| 27 |
-
"KQUBIT",
|
| 28 |
-
"KSENSE",
|
| 29 |
-
"KWARD",
|
| 30 |
-
"KYRO"
|
| 31 |
-
],
|
| 32 |
-
"n_built": 26,
|
| 33 |
-
"held": [
|
| 34 |
-
"KEDGE",
|
| 35 |
-
"KHEAT",
|
| 36 |
-
"KRAD",
|
| 37 |
-
"KTENSOR"
|
| 38 |
-
],
|
| 39 |
-
"n_files_hashed": 39
|
| 40 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
publish/dataverse_draft.py
DELETED
|
@@ -1,105 +0,0 @@
|
|
| 1 |
-
#!/usr/bin/env python
|
| 2 |
-
"""Create 26 DRAFT Harvard Dataverse datasets (one per BUILT KODEX code) in the
|
| 3 |
-
kronos-fusion-energy collection.
|
| 4 |
-
|
| 5 |
-
DRAFT-FIRST: Dataverse datasets are created UNPUBLISHED. Never calls the publish
|
| 6 |
-
action. Resume-safe via publish/state/dataverse_drafts.json (pid recorded the moment
|
| 7 |
-
the dataset is created). Prints the API error body on failure so a 400 names its field.
|
| 8 |
-
After review, run dataverse_publish_all.py --yes.
|
| 9 |
-
|
| 10 |
-
export DATAVERSE_TOKEN=...
|
| 11 |
-
export DATAVERSE_CONTACT_EMAIL=... # shown PUBLICLY — use a public-safe address
|
| 12 |
-
# optional: DATAVERSE_COLLECTION=kronos-fusion-energy DATAVERSE_BASE=https://dataverse.harvard.edu
|
| 13 |
-
python publish/dataverse_draft.py
|
| 14 |
-
"""
|
| 15 |
-
from __future__ import annotations
|
| 16 |
-
import os, sys
|
| 17 |
-
import requests
|
| 18 |
-
from _percode import built, attach_paths, load_meta, read_state, write_state, require_env, ORCID
|
| 19 |
-
|
| 20 |
-
BASE = os.environ.get("DATAVERSE_BASE", "https://dataverse.harvard.edu").rstrip("/")
|
| 21 |
-
COLLECTION = os.environ.get("DATAVERSE_COLLECTION", "kronos-fusion-energy")
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
def _prim(name, value, multiple=False, cls="primitive"):
|
| 25 |
-
return {"typeName": name, "multiple": multiple, "typeClass": cls, "value": value}
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
def _dataset_json(m, contact_email):
|
| 29 |
-
author = {"authorName": _prim("authorName", "Ford, P. I."),
|
| 30 |
-
"authorAffiliation": _prim("authorAffiliation", "Kronos Fusion Energy"),
|
| 31 |
-
"authorIdentifierScheme": {"typeName": "authorIdentifierScheme", "multiple": False,
|
| 32 |
-
"typeClass": "controlledVocabulary", "value": "ORCID"},
|
| 33 |
-
"authorIdentifier": _prim("authorIdentifier", ORCID)}
|
| 34 |
-
contact = {"datasetContactName": _prim("datasetContactName", "Ford, P. I."),
|
| 35 |
-
"datasetContactAffiliation": _prim("datasetContactAffiliation", "Kronos Fusion Energy"),
|
| 36 |
-
"datasetContactEmail": _prim("datasetContactEmail", contact_email)}
|
| 37 |
-
desc = {"dsDescriptionValue": _prim("dsDescriptionValue", m["description"])}
|
| 38 |
-
kws = [{"keywordValue": _prim("keywordValue", k)} for k in m["keywords"]]
|
| 39 |
-
# only well-formed DOI publications (bare-URL entries live in the description instead)
|
| 40 |
-
pubs = []
|
| 41 |
-
for r in m["related_identifiers"]:
|
| 42 |
-
ident = r["identifier"]
|
| 43 |
-
if ident.startswith("10."):
|
| 44 |
-
pubs.append({"publicationIDType": {"typeName": "publicationIDType", "multiple": False,
|
| 45 |
-
"typeClass": "controlledVocabulary", "value": "doi"},
|
| 46 |
-
"publicationIDNumber": _prim("publicationIDNumber", ident),
|
| 47 |
-
"publicationURL": _prim("publicationURL", f"https://doi.org/{ident}")})
|
| 48 |
-
fields = [_prim("title", m["title"]),
|
| 49 |
-
_prim("author", [author], True, "compound"),
|
| 50 |
-
_prim("datasetContact", [contact], True, "compound"),
|
| 51 |
-
_prim("dsDescription", [desc], True, "compound"),
|
| 52 |
-
_prim("subject", ["Physics"], True, "controlledVocabulary"),
|
| 53 |
-
_prim("keyword", kws, True, "compound")]
|
| 54 |
-
if pubs:
|
| 55 |
-
fields.append(_prim("publication", pubs, True, "compound"))
|
| 56 |
-
# Harvard's license picker has no Apache-2.0, and a license-less dataset defaults to CC0.
|
| 57 |
-
# So set Custom Terms of Use = Apache-2.0 text (per f7's live run) to override the CC0 default.
|
| 58 |
-
apache_terms = ("Licensed under the Apache License, Version 2.0 "
|
| 59 |
-
"(http://www.apache.org/licenses/LICENSE-2.0). The full license text is in the "
|
| 60 |
-
"bundled LICENSE file; citation metadata in CITATION.cff.")
|
| 61 |
-
return {"datasetVersion": {"termsOfUse": apache_terms,
|
| 62 |
-
"metadataBlocks": {"citation": {"fields": fields}}}}
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
def main():
|
| 66 |
-
token = require_env("DATAVERSE_TOKEN")
|
| 67 |
-
contact = os.environ.get("DATAVERSE_CONTACT_EMAIL")
|
| 68 |
-
if not contact:
|
| 69 |
-
raise SystemExit("[STOP] set DATAVERSE_CONTACT_EMAIL (public on the record) first.")
|
| 70 |
-
h = {"X-Dataverse-key": token}
|
| 71 |
-
s = requests.Session()
|
| 72 |
-
state = read_state("dataverse")
|
| 73 |
-
names = built()
|
| 74 |
-
for i, name in enumerate(names, 1):
|
| 75 |
-
rec = state.get(name, {})
|
| 76 |
-
if rec.get("done"):
|
| 77 |
-
print(f"[dataverse] ({i}/{len(names)}) {name}: complete (skip)"); continue
|
| 78 |
-
m = load_meta(name)
|
| 79 |
-
pid = rec.get("pid")
|
| 80 |
-
if not pid:
|
| 81 |
-
r = s.post(f"{BASE}/api/dataverses/{COLLECTION}/datasets", headers=h,
|
| 82 |
-
json=_dataset_json(m, contact))
|
| 83 |
-
if not r.ok:
|
| 84 |
-
print(f"[dataverse] {name}: create FAILED {r.status_code}: {r.text[:500]}")
|
| 85 |
-
return 1
|
| 86 |
-
pid = r.json()["data"].get("persistentId")
|
| 87 |
-
state[name] = {"pid": pid,
|
| 88 |
-
"url": f"{BASE}/dataset.xhtml?persistentId={pid}&version=DRAFT"}
|
| 89 |
-
write_state("dataverse", state)
|
| 90 |
-
for path in attach_paths(name):
|
| 91 |
-
with open(path, "rb") as fh:
|
| 92 |
-
r = s.post(f"{BASE}/api/datasets/:persistentId/add", headers=h,
|
| 93 |
-
params={"persistentId": pid}, files={"file": (path.name, fh)})
|
| 94 |
-
if not r.ok and "duplicate" not in r.text.lower() and "exists" not in r.text.lower():
|
| 95 |
-
print(f"[dataverse] {name}/{path.name}: add FAILED {r.status_code}: {r.text[:300]}")
|
| 96 |
-
return 1
|
| 97 |
-
state[name]["done"] = True
|
| 98 |
-
write_state("dataverse", state)
|
| 99 |
-
print(f"[dataverse] ({i}/{len(names)}) {name}: DRAFT {pid}")
|
| 100 |
-
print(f"\n[dataverse] {sum(1 for r in state.values() if r.get('done'))} drafts (NONE published). Then:")
|
| 101 |
-
print(" python publish/dataverse_publish_all.py --yes")
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
if __name__ == "__main__":
|
| 105 |
-
sys.exit(main())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
publish/dataverse_publish_all.py
DELETED
|
@@ -1,59 +0,0 @@
|
|
| 1 |
-
#!/usr/bin/env python
|
| 2 |
-
"""Publish the 26 per-code Harvard Dataverse DRAFTS created by dataverse_draft.py.
|
| 3 |
-
|
| 4 |
-
IRREVERSIBLE STEP. DRY RUN by default; publishes (major version) only with --yes,
|
| 5 |
-
only the datasets recorded in publish/state/dataverse_drafts.json.
|
| 6 |
-
|
| 7 |
-
export DATAVERSE_TOKEN=...
|
| 8 |
-
python publish/dataverse_publish_all.py # dry run
|
| 9 |
-
python publish/dataverse_publish_all.py --yes # publish
|
| 10 |
-
"""
|
| 11 |
-
from __future__ import annotations
|
| 12 |
-
import argparse, os, sys
|
| 13 |
-
import requests
|
| 14 |
-
from _percode import read_state, write_state, require_env
|
| 15 |
-
|
| 16 |
-
BASE = os.environ.get("DATAVERSE_BASE", "https://dataverse.harvard.edu").rstrip("/")
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
def main():
|
| 20 |
-
ap = argparse.ArgumentParser()
|
| 21 |
-
ap.add_argument("--yes", action="store_true")
|
| 22 |
-
args = ap.parse_args()
|
| 23 |
-
state = read_state("dataverse")
|
| 24 |
-
# records submitted for Harvard CURATOR review (review:true) are published by the
|
| 25 |
-
# curators on approval, NOT by a depositor :publish call (which errors on an In-Review
|
| 26 |
-
# dataset). Only ever direct-publish records that are NOT in the review queue.
|
| 27 |
-
in_review = {n: r for n, r in state.items() if r.get("review") and not r.get("published")}
|
| 28 |
-
pending = {n: r for n, r in state.items()
|
| 29 |
-
if r.get("pid") and not r.get("published") and not r.get("review")}
|
| 30 |
-
if in_review:
|
| 31 |
-
print(f"[dataverse] {len(in_review)} dataset(s) are in Harvard curator review — "
|
| 32 |
-
f"published on curator APPROVAL, not here. Skipping: {', '.join(sorted(in_review))}")
|
| 33 |
-
if not pending:
|
| 34 |
-
print("[dataverse] no directly-publishable drafts (all are curator-review or already "
|
| 35 |
-
"published). Nothing to do — await Harvard curators."); return
|
| 36 |
-
print(f"[dataverse] {len(pending)} NON-review draft(s) directly publishable on {BASE}:")
|
| 37 |
-
for n, r in pending.items():
|
| 38 |
-
print(f" {n:9s} {r['pid']}")
|
| 39 |
-
if not args.yes:
|
| 40 |
-
print("\n[dataverse] DRY RUN — nothing published. Re-run with --yes.")
|
| 41 |
-
return
|
| 42 |
-
h = {"X-Dataverse-key": require_env("DATAVERSE_TOKEN")}
|
| 43 |
-
s = requests.Session()
|
| 44 |
-
ok = 0
|
| 45 |
-
for n, r in pending.items():
|
| 46 |
-
resp = s.post(f"{BASE}/api/datasets/:persistentId/actions/:publish",
|
| 47 |
-
headers=h, params={"persistentId": r["pid"], "type": "major"})
|
| 48 |
-
if not resp.ok: # don't let one failure abort the batch
|
| 49 |
-
print(f"[dataverse] {n}: publish FAILED {resp.status_code}: {resp.text[:200]}")
|
| 50 |
-
continue
|
| 51 |
-
r["published"] = True
|
| 52 |
-
write_state("dataverse", state)
|
| 53 |
-
ok += 1
|
| 54 |
-
print(f"[dataverse] PUBLISHED {n}: {r['pid']}")
|
| 55 |
-
print(f"\n[dataverse] published {ok}/{len(pending)} non-review records.")
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
if __name__ == "__main__":
|
| 59 |
-
sys.exit(main())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
publish/figshare_draft.py
DELETED
|
@@ -1,119 +0,0 @@
|
|
| 1 |
-
#!/usr/bin/env python
|
| 2 |
-
"""Create 26 DRAFT Figshare articles (one per BUILT KODEX code).
|
| 3 |
-
|
| 4 |
-
DRAFT-FIRST: never calls /publish. Creates private articles, reserves DOIs (a
|
| 5 |
-
reservation is not a publication), uploads each code's attach set via the multipart
|
| 6 |
-
flow. Resume-safe via publish/state/figshare_drafts.json (article id recorded the
|
| 7 |
-
moment it is created, so a mid-upload failure never orphans it). After review, run
|
| 8 |
-
figshare_publish_all.py --yes.
|
| 9 |
-
|
| 10 |
-
export FIGSHARE_TOKEN=...
|
| 11 |
-
python publish/figshare_draft.py
|
| 12 |
-
"""
|
| 13 |
-
from __future__ import annotations
|
| 14 |
-
import hashlib, sys
|
| 15 |
-
import requests
|
| 16 |
-
from _percode import built, attach_paths, load_meta, read_state, write_state, require_env
|
| 17 |
-
|
| 18 |
-
API = "https://api.figshare.com/v2"
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
def _md5(path):
|
| 22 |
-
h = hashlib.md5()
|
| 23 |
-
with open(path, "rb") as f:
|
| 24 |
-
for c in iter(lambda: f.read(1 << 16), b""):
|
| 25 |
-
h.update(c)
|
| 26 |
-
return h.hexdigest()
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
def _refs(meta):
|
| 30 |
-
"""Figshare 'references' must be valid URLs — DOIs -> https://doi.org/..., keep only
|
| 31 |
-
http(s), dedupe, preserve order."""
|
| 32 |
-
out, seen = [], set()
|
| 33 |
-
for r in meta["related_identifiers"]:
|
| 34 |
-
ident = r["identifier"].strip()
|
| 35 |
-
url = f"https://doi.org/{ident}" if ident.startswith("10.") else ident
|
| 36 |
-
if url.startswith("http") and url not in seen:
|
| 37 |
-
seen.add(url); out.append(url)
|
| 38 |
-
return out
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
def _tags(meta):
|
| 42 |
-
"""Figshare tags: each >= 3 chars; keep it modest."""
|
| 43 |
-
out, seen = [], set()
|
| 44 |
-
for k in meta["keywords"]:
|
| 45 |
-
k = k.strip()
|
| 46 |
-
if len(k) >= 3 and k.lower() not in seen:
|
| 47 |
-
seen.add(k.lower()); out.append(k)
|
| 48 |
-
return out[:10]
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
def _existing_files(s, h, article_id):
|
| 52 |
-
try:
|
| 53 |
-
r = s.get(f"{API}/account/articles/{article_id}/files", headers=h)
|
| 54 |
-
return {f["name"] for f in r.json()} if r.ok else set()
|
| 55 |
-
except Exception:
|
| 56 |
-
return set()
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
def _upload(s, h, article_id, path):
|
| 60 |
-
size = path.stat().st_size
|
| 61 |
-
r = s.post(f"{API}/account/articles/{article_id}/files", headers=h,
|
| 62 |
-
json={"name": path.name, "md5": _md5(path), "size": size}); r.raise_for_status()
|
| 63 |
-
file_url = r.json()["location"]
|
| 64 |
-
info = s.get(file_url, headers=h).json()
|
| 65 |
-
up = s.get(info["upload_url"], headers=h).json()
|
| 66 |
-
with open(path, "rb") as fh:
|
| 67 |
-
for part in up["parts"]:
|
| 68 |
-
fh.seek(part["startOffset"])
|
| 69 |
-
chunk = fh.read(part["endOffset"] - part["startOffset"] + 1)
|
| 70 |
-
s.put(f"{info['upload_url']}/{part['partNo']}", headers=h, data=chunk).raise_for_status()
|
| 71 |
-
s.post(file_url, headers=h).raise_for_status()
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
def main():
|
| 75 |
-
token = require_env("FIGSHARE_TOKEN")
|
| 76 |
-
h = {"Authorization": f"token {token}"}
|
| 77 |
-
s = requests.Session()
|
| 78 |
-
state = read_state("figshare")
|
| 79 |
-
names = built()
|
| 80 |
-
for i, name in enumerate(names, 1):
|
| 81 |
-
rec = state.get(name, {})
|
| 82 |
-
if rec.get("done"):
|
| 83 |
-
print(f"[figshare] ({i}/{len(names)}) {name}: complete (skip)"); continue
|
| 84 |
-
m = load_meta(name)
|
| 85 |
-
aid = rec.get("id")
|
| 86 |
-
if not aid:
|
| 87 |
-
body = {"title": m["title"], "description": m["description"],
|
| 88 |
-
"defined_type": "software", "tags": _tags(m), "references": _refs(m),
|
| 89 |
-
# explicit author (ORCID is linked via the uploading Figshare account)
|
| 90 |
-
"authors": [{"name": "Ford, P. I."}],
|
| 91 |
-
# LEAF categories only — parent 29152 is not assignable (per f7's live run)
|
| 92 |
-
"categories": [30202, 29173, 26836]}
|
| 93 |
-
r = s.post(f"{API}/account/articles", headers=h, json=body)
|
| 94 |
-
if not r.ok:
|
| 95 |
-
print(f"[figshare] {name}: create FAILED {r.status_code}: {r.text[:400]}")
|
| 96 |
-
print(f" body.tags={body['tags']}")
|
| 97 |
-
print(f" body.references={body['references']}")
|
| 98 |
-
return 1
|
| 99 |
-
aid = int(r.json()["location"].rstrip("/").split("/")[-1])
|
| 100 |
-
state[name] = {"id": aid, "url": f"https://figshare.com/account/articles/{aid}"}
|
| 101 |
-
write_state("figshare", state)
|
| 102 |
-
try:
|
| 103 |
-
s.post(f"{API}/account/articles/{aid}/reserve_doi", headers=h).raise_for_status()
|
| 104 |
-
except Exception:
|
| 105 |
-
pass
|
| 106 |
-
have = _existing_files(s, h, aid)
|
| 107 |
-
for path in attach_paths(name):
|
| 108 |
-
if path.name in have:
|
| 109 |
-
continue # already uploaded (resumed) -> idempotent
|
| 110 |
-
_upload(s, h, aid, path)
|
| 111 |
-
state[name]["done"] = True
|
| 112 |
-
write_state("figshare", state)
|
| 113 |
-
print(f"[figshare] ({i}/{len(names)}) {name}: DRAFT {aid}")
|
| 114 |
-
print(f"\n[figshare] {sum(1 for r in state.values() if r.get('done'))} drafts (NONE published). Then:")
|
| 115 |
-
print(" python publish/figshare_publish_all.py --yes")
|
| 116 |
-
|
| 117 |
-
|
| 118 |
-
if __name__ == "__main__":
|
| 119 |
-
sys.exit(main())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
publish/figshare_publish_all.py
DELETED
|
@@ -1,47 +0,0 @@
|
|
| 1 |
-
#!/usr/bin/env python
|
| 2 |
-
"""Publish the 26 per-code Figshare DRAFTS created by figshare_draft.py.
|
| 3 |
-
|
| 4 |
-
IRREVERSIBLE STEP. DRY RUN by default; publishes only with --yes, only the articles
|
| 5 |
-
recorded in publish/state/figshare_drafts.json.
|
| 6 |
-
|
| 7 |
-
export FIGSHARE_TOKEN=...
|
| 8 |
-
python publish/figshare_publish_all.py # dry run
|
| 9 |
-
python publish/figshare_publish_all.py --yes # publish
|
| 10 |
-
"""
|
| 11 |
-
from __future__ import annotations
|
| 12 |
-
import argparse, sys
|
| 13 |
-
import requests
|
| 14 |
-
from _percode import read_state, write_state, require_env
|
| 15 |
-
|
| 16 |
-
API = "https://api.figshare.com/v2"
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
def main():
|
| 20 |
-
ap = argparse.ArgumentParser()
|
| 21 |
-
ap.add_argument("--yes", action="store_true")
|
| 22 |
-
args = ap.parse_args()
|
| 23 |
-
state = read_state("figshare")
|
| 24 |
-
pending = {n: r for n, r in state.items() if r.get("id") and not r.get("published")}
|
| 25 |
-
if not pending:
|
| 26 |
-
print("[figshare] no unpublished drafts in state (run figshare_draft.py first)."); return
|
| 27 |
-
print(f"[figshare] {len(pending)} draft(s) to publish:")
|
| 28 |
-
for n, r in pending.items():
|
| 29 |
-
print(f" {n:9s} id={r['id']}")
|
| 30 |
-
if not args.yes:
|
| 31 |
-
print("\n[figshare] DRY RUN — nothing published. Re-run with --yes.")
|
| 32 |
-
return
|
| 33 |
-
h = {"Authorization": f"token {require_env('FIGSHARE_TOKEN')}"}
|
| 34 |
-
s = requests.Session()
|
| 35 |
-
for n, r in pending.items():
|
| 36 |
-
resp = s.post(f"{API}/account/articles/{r['id']}/publish", headers=h)
|
| 37 |
-
resp.raise_for_status()
|
| 38 |
-
loc = resp.json().get("location", "")
|
| 39 |
-
r["published"] = True
|
| 40 |
-
r["public_url"] = loc
|
| 41 |
-
write_state("figshare", state)
|
| 42 |
-
print(f"[figshare] PUBLISHED {n}: {loc}")
|
| 43 |
-
print(f"\n[figshare] published {len(pending)} records.")
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
if __name__ == "__main__":
|
| 47 |
-
sys.exit(main())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
publish/ia_upload_all.py
DELETED
|
@@ -1,47 +0,0 @@
|
|
| 1 |
-
#!/usr/bin/env python
|
| 2 |
-
"""Upload the 26 per-code KODEX records to the Internet Archive (one item per code).
|
| 3 |
-
|
| 4 |
-
NOTE: Internet Archive items become PUBLIC on upload — there is no private-draft state —
|
| 5 |
-
so this IS the publish step for IA. DRY RUN by default; uploads only with --yes.
|
| 6 |
-
Requires the `ia` CLI configured (`ia configure` with your S3 keys) once.
|
| 7 |
-
|
| 8 |
-
python publish/ia_upload_all.py # dry run (lists items + files)
|
| 9 |
-
python publish/ia_upload_all.py --yes # upload (public)
|
| 10 |
-
"""
|
| 11 |
-
from __future__ import annotations
|
| 12 |
-
import argparse, subprocess, sys
|
| 13 |
-
from _percode import built, attach_paths, load_meta, VERSION
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
def main():
|
| 17 |
-
ap = argparse.ArgumentParser()
|
| 18 |
-
ap.add_argument("--yes", action="store_true")
|
| 19 |
-
args = ap.parse_args()
|
| 20 |
-
names = built()
|
| 21 |
-
print(f"[ia] {len(names)} items to upload (identifier = kronos-ml-kodex-<code>-v{VERSION}):")
|
| 22 |
-
plans = []
|
| 23 |
-
for name in names:
|
| 24 |
-
m = load_meta(name)
|
| 25 |
-
ident = f"kronos-ml-kodex-{name.lower()}-v{VERSION}"
|
| 26 |
-
files = [str(p) for p in attach_paths(name)]
|
| 27 |
-
plans.append((ident, m, files))
|
| 28 |
-
print(f" {ident} ({len(files)} files)")
|
| 29 |
-
if not args.yes:
|
| 30 |
-
print("\n[ia] DRY RUN — nothing uploaded. Re-run with --yes (items go PUBLIC on upload).")
|
| 31 |
-
return
|
| 32 |
-
for ident, m, files in plans:
|
| 33 |
-
cmd = ["ia", "upload", ident, *files,
|
| 34 |
-
f"--metadata=title:{m['title']}",
|
| 35 |
-
"--metadata=creator:Ford, P. I.",
|
| 36 |
-
"--metadata=licenseurl:https://spdx.org/licenses/Apache-2.0",
|
| 37 |
-
f"--metadata=external-identifier:{m['page']}",
|
| 38 |
-
"--metadata=subject:fusion; spherical tokamak; AI/ML surrogate; Kronos Fusion Energy"]
|
| 39 |
-
r = subprocess.run(cmd)
|
| 40 |
-
if r.returncode != 0:
|
| 41 |
-
print(f"[ia] FAILED {ident} (rc={r.returncode})"); return r.returncode
|
| 42 |
-
print(f"[ia] uploaded https://archive.org/details/{ident}")
|
| 43 |
-
print(f"\n[ia] uploaded {len(plans)} items.")
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
if __name__ == "__main__":
|
| 47 |
-
sys.exit(main())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
publish/kronos-ml-v0.1.0-source.zip
DELETED
|
@@ -1,3 +0,0 @@
|
|
| 1 |
-
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:cc14cfb661fae0b28ebb757796c563cf9517ee3bf444e97d314cd377b4b94b21
|
| 3 |
-
size 652545
|
|
|
|
|
|
|
|
|
|
|
|
publish/osf_draft.py
DELETED
|
@@ -1,71 +0,0 @@
|
|
| 1 |
-
#!/usr/bin/env python
|
| 2 |
-
"""Create 26 PRIVATE OSF projects (one per BUILT KODEX code).
|
| 3 |
-
|
| 4 |
-
DRAFT-FIRST: each project is created private (public=false) and never made public here.
|
| 5 |
-
Resume-safe via publish/state/osf_drafts.json. Throttled + retried against OSF's
|
| 6 |
-
rate-limiting (403/429). After review, run osf_publish_all.py --yes.
|
| 7 |
-
|
| 8 |
-
export OSF_TOKEN=...
|
| 9 |
-
python publish/osf_draft.py
|
| 10 |
-
"""
|
| 11 |
-
from __future__ import annotations
|
| 12 |
-
import sys, time
|
| 13 |
-
import requests
|
| 14 |
-
from _percode import (built, attach_paths, load_meta, read_state, write_state,
|
| 15 |
-
require_env, http_retry)
|
| 16 |
-
|
| 17 |
-
API = "https://api.osf.io/v2"
|
| 18 |
-
WB = "https://files.osf.io/v1"
|
| 19 |
-
PACE_FILE = 0.6 # seconds between file uploads
|
| 20 |
-
PACE_PROJECT = 1.2 # seconds between projects
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
def main():
|
| 24 |
-
token = require_env("OSF_TOKEN")
|
| 25 |
-
h = {"Authorization": f"Bearer {token}"}
|
| 26 |
-
hj = {**h, "Content-Type": "application/vnd.api+json"}
|
| 27 |
-
s = requests.Session()
|
| 28 |
-
state = read_state("osf")
|
| 29 |
-
names = built()
|
| 30 |
-
for i, name in enumerate(names, 1):
|
| 31 |
-
rec = state.get(name, {})
|
| 32 |
-
node = rec.get("id")
|
| 33 |
-
if rec.get("done"):
|
| 34 |
-
print(f"[osf] ({i}/{len(names)}) {name}: complete (skip)"); continue
|
| 35 |
-
m = load_meta(name)
|
| 36 |
-
if not node: # create the project (retry rate-limits)
|
| 37 |
-
payload = {"data": {"type": "nodes", "attributes": {
|
| 38 |
-
"title": m["title"], "category": "software",
|
| 39 |
-
# OSF renders the description as PLAIN TEXT (no HTML) -> use the stripped variant
|
| 40 |
-
"description": m.get("description_plain", m["description"]),
|
| 41 |
-
"public": False, "tags": m["keywords"][:25]}}}
|
| 42 |
-
r = http_retry(lambda: s.post(f"{API}/nodes/", headers=hj, json=payload),
|
| 43 |
-
label=f"osf-create {name}")
|
| 44 |
-
if not r.ok:
|
| 45 |
-
print(f"[osf] {name}: create FAILED {r.status_code}: {r.text[:300]}"); return 1
|
| 46 |
-
node = r.json()["data"]["id"]
|
| 47 |
-
state[name] = {"id": node, "url": f"https://osf.io/{node}/"}
|
| 48 |
-
write_state("osf", state)
|
| 49 |
-
time.sleep(PACE_PROJECT)
|
| 50 |
-
# upload files (throttled; 409 = already there = fine)
|
| 51 |
-
for path in attach_paths(name):
|
| 52 |
-
def _put():
|
| 53 |
-
with open(path, "rb") as fh:
|
| 54 |
-
return s.put(f"{WB}/resources/{node}/providers/osfstorage/", headers=h,
|
| 55 |
-
params={"kind": "file", "name": path.name}, data=fh)
|
| 56 |
-
r = http_retry(_put, label=f"osf-upload {name}/{path.name}")
|
| 57 |
-
if r.status_code == 409:
|
| 58 |
-
pass # file already exists (resumed) -> treat as done
|
| 59 |
-
elif not r.ok:
|
| 60 |
-
print(f"[osf] {name}/{path.name}: upload FAILED {r.status_code}: {r.text[:200]}")
|
| 61 |
-
return 1
|
| 62 |
-
time.sleep(PACE_FILE)
|
| 63 |
-
state[name]["done"] = True
|
| 64 |
-
write_state("osf", state)
|
| 65 |
-
print(f"[osf] ({i}/{len(names)}) {name}: PRIVATE {node} ({len(attach_paths(name))} files)")
|
| 66 |
-
print(f"\n[osf] {sum(1 for r in state.values() if r.get('done'))} private projects (NONE public). Then:")
|
| 67 |
-
print(" python publish/osf_publish_all.py --yes")
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
if __name__ == "__main__":
|
| 71 |
-
sys.exit(main())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
publish/osf_publish_all.py
DELETED
|
@@ -1,47 +0,0 @@
|
|
| 1 |
-
#!/usr/bin/env python
|
| 2 |
-
"""Make the 26 per-code OSF projects PUBLIC (created private by osf_draft.py).
|
| 3 |
-
|
| 4 |
-
IRREVERSIBLE STEP. DRY RUN by default; flips projects to public only with --yes,
|
| 5 |
-
and only those recorded in publish/state/osf_drafts.json.
|
| 6 |
-
|
| 7 |
-
export OSF_TOKEN=...
|
| 8 |
-
python publish/osf_publish_all.py # dry run
|
| 9 |
-
python publish/osf_publish_all.py --yes # make public
|
| 10 |
-
"""
|
| 11 |
-
from __future__ import annotations
|
| 12 |
-
import argparse, sys
|
| 13 |
-
import requests
|
| 14 |
-
from _percode import read_state, write_state, require_env
|
| 15 |
-
|
| 16 |
-
API = "https://api.osf.io/v2"
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
def main():
|
| 20 |
-
ap = argparse.ArgumentParser()
|
| 21 |
-
ap.add_argument("--yes", action="store_true")
|
| 22 |
-
args = ap.parse_args()
|
| 23 |
-
state = read_state("osf")
|
| 24 |
-
pending = {n: r for n, r in state.items() if r.get("id") and not r.get("public")}
|
| 25 |
-
if not pending:
|
| 26 |
-
print("[osf] no private projects in state (run osf_draft.py first)."); return
|
| 27 |
-
print(f"[osf] {len(pending)} project(s) to make public:")
|
| 28 |
-
for n, r in pending.items():
|
| 29 |
-
print(f" {n:9s} {r.get('url','')}")
|
| 30 |
-
if not args.yes:
|
| 31 |
-
print("\n[osf] DRY RUN — nothing made public. Re-run with --yes.")
|
| 32 |
-
return
|
| 33 |
-
hj = {"Authorization": f"Bearer {require_env('OSF_TOKEN')}",
|
| 34 |
-
"Content-Type": "application/vnd.api+json"}
|
| 35 |
-
s = requests.Session()
|
| 36 |
-
for n, r in pending.items():
|
| 37 |
-
payload = {"data": {"type": "nodes", "id": r["id"], "attributes": {"public": True}}}
|
| 38 |
-
resp = s.patch(f"{API}/nodes/{r['id']}/", headers=hj, json=payload)
|
| 39 |
-
resp.raise_for_status()
|
| 40 |
-
r["public"] = True
|
| 41 |
-
write_state("osf", state)
|
| 42 |
-
print(f"[osf] PUBLIC {n}: {r.get('url')}")
|
| 43 |
-
print(f"\n[osf] made {len(pending)} projects public.")
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
if __name__ == "__main__":
|
| 47 |
-
sys.exit(main())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
publish/records/kairos/CITATION.cff
DELETED
|
@@ -1,13 +0,0 @@
|
|
| 1 |
-
cff-version: 1.2.0
|
| 2 |
-
title: "KODEX — KAIROS: CONTROL (Kronos Family of Codes)"
|
| 3 |
-
version: "0.2.0"
|
| 4 |
-
date-released: "2026-09-11"
|
| 5 |
-
license: Apache-2.0
|
| 6 |
-
url: "https://kronosfusionenergy.com/kodex/kairos"
|
| 7 |
-
repository-code: "https://github.com/KronosFE/kronos-ml"
|
| 8 |
-
type: software
|
| 9 |
-
authors:
|
| 10 |
-
- family-names: Ford
|
| 11 |
-
given-names: "P. I."
|
| 12 |
-
orcid: "https://orcid.org/0000-0003-0395-1752"
|
| 13 |
-
affiliation: "Kronos Fusion Energy"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
publish/records/kairos/LICENSE
DELETED
|
@@ -1,189 +0,0 @@
|
|
| 1 |
-
Apache License
|
| 2 |
-
Version 2.0, January 2004
|
| 3 |
-
http://www.apache.org/licenses/
|
| 4 |
-
|
| 5 |
-
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
| 6 |
-
|
| 7 |
-
1. Definitions.
|
| 8 |
-
|
| 9 |
-
"License" shall mean the terms and conditions for use, reproduction,
|
| 10 |
-
and distribution as defined by Sections 1 through 9 of this document.
|
| 11 |
-
|
| 12 |
-
"Licensor" shall mean the copyright owner or entity authorized by
|
| 13 |
-
the copyright owner that is granting the License.
|
| 14 |
-
|
| 15 |
-
"Legal Entity" shall mean the union of the acting entity and all
|
| 16 |
-
other entities that control, are controlled by, or are under common
|
| 17 |
-
control with that entity. For the purposes of this definition,
|
| 18 |
-
"control" means (i) the power, direct or indirect, to cause the
|
| 19 |
-
direction or management of such entity, whether by contract or
|
| 20 |
-
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
| 21 |
-
outstanding shares, or (iii) beneficial ownership of such entity.
|
| 22 |
-
|
| 23 |
-
"You" (or "Your") shall mean an individual or Legal Entity
|
| 24 |
-
exercising permissions granted by this License.
|
| 25 |
-
|
| 26 |
-
"Source" form shall mean the preferred form for making modifications,
|
| 27 |
-
including but not limited to software source code, documentation
|
| 28 |
-
source, and configuration files.
|
| 29 |
-
|
| 30 |
-
"Object" form shall mean any form resulting from mechanical
|
| 31 |
-
transformation or translation of a Source form, including but not
|
| 32 |
-
limited to compiled object code, generated documentation, and
|
| 33 |
-
conversions to other media types.
|
| 34 |
-
|
| 35 |
-
"Work" shall mean the work of authorship, whether in Source or
|
| 36 |
-
Object form, made available under the License, as indicated by a
|
| 37 |
-
copyright notice that is included in or attached to the work.
|
| 38 |
-
|
| 39 |
-
"Derivative Works" shall mean any work, whether in Source or Object
|
| 40 |
-
form, that is based on (or derived from) the Work and for which the
|
| 41 |
-
editorial revisions, annotations, elaborations, or other modifications
|
| 42 |
-
represent, as a whole, an original work of authorship. For the purposes
|
| 43 |
-
of this License, Derivative Works shall not include works that remain
|
| 44 |
-
separable from, or merely link (or bind by name) to the interfaces of,
|
| 45 |
-
the Work and Derivative Works thereof.
|
| 46 |
-
|
| 47 |
-
"Contribution" shall mean any work of authorship, including the
|
| 48 |
-
original version of the Work and any modifications or additions
|
| 49 |
-
to that Work or Derivative Works thereof, that is intentionally
|
| 50 |
-
submitted to Licensor for inclusion in the Work by the copyright owner
|
| 51 |
-
or by an individual or Legal Entity authorized to submit on behalf of
|
| 52 |
-
the copyright owner. For the purposes of this definition, "submitted"
|
| 53 |
-
means any form of electronic, verbal, or written communication sent
|
| 54 |
-
to the Licensor or its representatives, including but not limited to
|
| 55 |
-
communication on electronic mailing lists, source code control systems,
|
| 56 |
-
and issue tracking systems that are managed by, or on behalf of, the
|
| 57 |
-
Licensor for the purpose of discussing and improving the Work, but
|
| 58 |
-
excluding communication that is conspicuously marked or otherwise
|
| 59 |
-
designated in writing by the copyright owner as "Not a Contribution."
|
| 60 |
-
|
| 61 |
-
"Contributor" shall mean Licensor and any individual or Legal Entity
|
| 62 |
-
on behalf of whom a Contribution has been received by Licensor and
|
| 63 |
-
subsequently incorporated within the Work.
|
| 64 |
-
|
| 65 |
-
2. Grant of Copyright License. Subject to the terms and conditions of
|
| 66 |
-
this License, each Contributor hereby grants to You a perpetual,
|
| 67 |
-
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
| 68 |
-
copyright license to reproduce, prepare Derivative Works of,
|
| 69 |
-
publicly display, publicly perform, sublicense, and distribute the
|
| 70 |
-
Work and such Derivative Works in Source or Object form.
|
| 71 |
-
|
| 72 |
-
3. Grant of Patent License. Subject to the terms and conditions of
|
| 73 |
-
this License, each Contributor hereby grants to You a perpetual,
|
| 74 |
-
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
| 75 |
-
(except as stated in this section) patent license to make, have made,
|
| 76 |
-
use, offer to sell, sell, import, and otherwise transfer the Work,
|
| 77 |
-
where such license applies only to those patent claims licensable
|
| 78 |
-
by such Contributor that are necessarily infringed by their
|
| 79 |
-
Contribution(s) alone or by combination of their Contribution(s)
|
| 80 |
-
with the Work to which such Contribution(s) was submitted. If You
|
| 81 |
-
institute patent litigation against any entity (including a
|
| 82 |
-
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
| 83 |
-
or a Contribution incorporated within the Work constitutes direct
|
| 84 |
-
or contributory patent infringement, then any patent licenses
|
| 85 |
-
granted to You under this License for that Work shall terminate
|
| 86 |
-
as of the date such litigation is filed.
|
| 87 |
-
|
| 88 |
-
4. Redistribution. You may reproduce and distribute copies of the
|
| 89 |
-
Work or Derivative Works thereof in any medium, with or without
|
| 90 |
-
modifications, and in Source or Object form, provided that You
|
| 91 |
-
meet the following conditions:
|
| 92 |
-
|
| 93 |
-
(a) You must give any other recipients of the Work or Derivative
|
| 94 |
-
Works a copy of this License; and
|
| 95 |
-
|
| 96 |
-
(b) You must cause any modified files to carry prominent notices
|
| 97 |
-
stating that You changed the files; and
|
| 98 |
-
|
| 99 |
-
(c) You must retain, in the Source form of any Derivative Works
|
| 100 |
-
that You distribute, all copyright, patent, trademark, and
|
| 101 |
-
attribution notices from the Source form of the Work,
|
| 102 |
-
excluding those notices that do not pertain to any part of
|
| 103 |
-
the Derivative Works; and
|
| 104 |
-
|
| 105 |
-
(d) If the Work includes a "NOTICE" text file as part of its
|
| 106 |
-
distribution, then any Derivative Works that You distribute must
|
| 107 |
-
include a readable copy of the attribution notices contained
|
| 108 |
-
within such NOTICE file, excluding those notices that do not
|
| 109 |
-
pertain to any part of the Derivative Works.
|
| 110 |
-
|
| 111 |
-
You may add Your own copyright statement to Your modifications and
|
| 112 |
-
may provide additional or different license terms and conditions
|
| 113 |
-
for use, reproduction, or distribution of Your modifications, or
|
| 114 |
-
for any such Derivative Works as a whole, provided Your use,
|
| 115 |
-
reproduction, and distribution of the Work otherwise complies with
|
| 116 |
-
the conditions stated in this License.
|
| 117 |
-
|
| 118 |
-
5. Submission of Contributions. Unless You explicitly state otherwise,
|
| 119 |
-
any Contribution intentionally submitted for inclusion in the Work
|
| 120 |
-
by You to the Licensor shall be under the terms and conditions of
|
| 121 |
-
this License, without any additional terms or conditions.
|
| 122 |
-
Notwithstanding the above, nothing herein shall supersede or modify
|
| 123 |
-
the terms of any separate license agreement you may have executed
|
| 124 |
-
with Licensor regarding such Contributions.
|
| 125 |
-
|
| 126 |
-
6. Trademarks. This License does not grant permission to use the trade
|
| 127 |
-
names, trademarks, service marks, or product names of the Licensor,
|
| 128 |
-
except as required for reasonable and customary use in describing the
|
| 129 |
-
origin of the Work and reproducing the content of the NOTICE file.
|
| 130 |
-
|
| 131 |
-
7. Disclaimer of Warranty. Unless required by applicable law or
|
| 132 |
-
agreed to in writing, Licensor provides the Work (and each
|
| 133 |
-
Contributor provides its Contributions) on an "AS IS" BASIS,
|
| 134 |
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
| 135 |
-
implied, including, without limitation, any warranties or conditions
|
| 136 |
-
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
| 137 |
-
PARTICULAR PURPOSE. You are solely responsible for determining the
|
| 138 |
-
appropriateness of using or redistributing the Work and assume any
|
| 139 |
-
risks associated with Your exercise of permissions under this License.
|
| 140 |
-
|
| 141 |
-
8. Limitation of Liability. In no event and under no legal theory,
|
| 142 |
-
whether in tort (including negligence), contract, or otherwise,
|
| 143 |
-
unless required by applicable law (such as deliberate and grossly
|
| 144 |
-
negligent acts) or agreed to in writing, shall any Contributor be
|
| 145 |
-
liable to You for damages, including any direct, indirect, special,
|
| 146 |
-
incidental, or consequential damages of any character arising as a
|
| 147 |
-
result of this License or out of the use or inability to use the
|
| 148 |
-
Work (including but not limited to damages for loss of goodwill,
|
| 149 |
-
work stoppage, computer failure or malfunction, or any and all
|
| 150 |
-
other commercial damages or losses), even if such Contributor
|
| 151 |
-
has been advised of the possibility of such damages.
|
| 152 |
-
|
| 153 |
-
9. Accepting Warranty or Additional Liability. While redistributing
|
| 154 |
-
the Work or Derivative Works thereof, You may choose to offer,
|
| 155 |
-
and charge a fee for, acceptance of support, warranty, indemnity,
|
| 156 |
-
or other liability obligations and/or rights consistent with this
|
| 157 |
-
License. However, in accepting such obligations, You may act only
|
| 158 |
-
on Your own behalf and on Your sole responsibility, not on behalf
|
| 159 |
-
of any other Contributor, and only if You agree to indemnify,
|
| 160 |
-
defend, and hold each Contributor harmless for any liability
|
| 161 |
-
incurred by, or claims asserted against, such Contributor by reason
|
| 162 |
-
of your accepting any such warranty or additional liability.
|
| 163 |
-
|
| 164 |
-
END OF TERMS AND CONDITIONS
|
| 165 |
-
|
| 166 |
-
APPENDIX: How to apply the Apache License to your work.
|
| 167 |
-
|
| 168 |
-
To apply the Apache License to your work, attach the following
|
| 169 |
-
boilerplate notice, with the fields enclosed by brackets "[]"
|
| 170 |
-
replaced with your own identifying information. (Don't include
|
| 171 |
-
the brackets!) The text should be enclosed in the appropriate
|
| 172 |
-
comment syntax for the file format. We also recommend that a
|
| 173 |
-
file or class name and description of purpose be included on the
|
| 174 |
-
same "printed page" as the copyright notice for easier
|
| 175 |
-
identification within third-party archives.
|
| 176 |
-
|
| 177 |
-
Copyright 2026 Kronos Fusion Energy
|
| 178 |
-
|
| 179 |
-
Licensed under the Apache License, Version 2.0 (the "License");
|
| 180 |
-
you may not use this file except in compliance with the License.
|
| 181 |
-
You may obtain a copy of the License at
|
| 182 |
-
|
| 183 |
-
http://www.apache.org/licenses/LICENSE-2.0
|
| 184 |
-
|
| 185 |
-
Unless required by applicable law or agreed to in writing, software
|
| 186 |
-
distributed under the License is distributed on an "AS IS" BASIS,
|
| 187 |
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 188 |
-
See the License for the specific language governing permissions and
|
| 189 |
-
limitations under the License.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
publish/records/kairos/MANIFEST.sha256
DELETED
|
@@ -1,7 +0,0 @@
|
|
| 1 |
-
# KODEX KAIROS SHA-256 (0.2.0, 2026-09-11)
|
| 2 |
-
d334149c67e6fab06da1157e5cd47129d2bf4e738754afeb20176b6bacb89d54 CITATION.cff
|
| 3 |
-
ae87ebecd1f321a19799e21f6fe25e4a74261f16c91e6cb6cc248e6197dcf838 LICENSE
|
| 4 |
-
4519abc8cba84d5ba68e5e0cc5faef0dac4094a970a6a4a39f993abcfc4931be benchmark.json
|
| 5 |
-
f99514c0fb9ad18571bfafcdd8579f51323285a65c66f90140d91cb781a58243 card.md
|
| 6 |
-
203323e21eb15172090486e0fdde9367a3c13b7e1fb3d66d5b280108b7f15f32 kairos.py
|
| 7 |
-
85ff663bac08f45a66d216dbbed1bf62143b7fa0943192c6f6e91f4ca3cf4c47 metadata.json
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
publish/records/kairos/benchmark.json
DELETED
|
@@ -1,19 +0,0 @@
|
|
| 1 |
-
{
|
| 2 |
-
"member": "KAIROS",
|
| 3 |
-
"live_tracking_rms_frac": 0.0461,
|
| 4 |
-
"live_expB_model_failure": {
|
| 5 |
-
"adversaries": [
|
| 6 |
-
"drift",
|
| 7 |
-
"edge_seeker",
|
| 8 |
-
"nan_garbage"
|
| 9 |
-
],
|
| 10 |
-
"steps": 150000,
|
| 11 |
-
"escapes": 0,
|
| 12 |
-
"catch_rate": 1.0
|
| 13 |
-
},
|
| 14 |
-
"live_mpc_step_us": 96.1,
|
| 15 |
-
"sourced": {
|
| 16 |
-
"file": "track5_control/clamp_activation_stats.csv",
|
| 17 |
-
"headline": "0 escapes / 150k steps / 3000 injected (AC-25); tracking <5%"
|
| 18 |
-
}
|
| 19 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
publish/records/kairos/card.md
DELETED
|
@@ -1,13 +0,0 @@
|
|
| 1 |
-
# KODEX KAIROS — card
|
| 2 |
-
|
| 3 |
-
- **name:** KAIROS
|
| 4 |
-
- **function:** CONTROL
|
| 5 |
-
- **status:** BUILT
|
| 6 |
-
- **phase:** 1
|
| 7 |
-
- **provenance:** TWIN
|
| 8 |
-
- **retired_by:** validated real-time plant controller (device-in-the-loop)
|
| 9 |
-
- **gates:** ['AC-24', 'AC-25']
|
| 10 |
-
- **note:** real-time closed-loop MPC control (analytic finite-horizon QP); supplies the model-free L4 clamp that KGATE enforces
|
| 11 |
-
- **available:** True
|
| 12 |
-
|
| 13 |
-
Benchmark headline: MPC tracking 0.0461 (<5%); Exp-B **0 escapes / 150,000**; 96.1 µs/step
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
publish/records/kairos/kairos.py
DELETED
|
@@ -1,57 +0,0 @@
|
|
| 1 |
-
"""KODEX KAIROS — source excerpt (class). Full runnable package: https://github.com/KronosFE/kronos-ml"""
|
| 2 |
-
|
| 3 |
-
@register
|
| 4 |
-
class KAIROS(Surrogate):
|
| 5 |
-
name = "KAIROS"; function = "CONTROL"; phase = 1; status = "BUILT"
|
| 6 |
-
provenance = "TWIN"
|
| 7 |
-
retired_by = "validated real-time plant controller (device-in-the-loop)"
|
| 8 |
-
real_codes = ("receding-horizon MPC",)
|
| 9 |
-
gates = ("AC-24", "AC-25")
|
| 10 |
-
note = ("real-time closed-loop MPC control (analytic finite-horizon QP); "
|
| 11 |
-
"supplies the model-free L4 clamp that KGATE enforces")
|
| 12 |
-
|
| 13 |
-
def _predict(self, x):
|
| 14 |
-
"""x = (state6, ref6) -> next command from the MPC, clamped by KGATE."""
|
| 15 |
-
state, ref = x
|
| 16 |
-
u = _mpc(state, ref)
|
| 17 |
-
safe, ok = get("KGATE").clamp(u)
|
| 18 |
-
in_dom = bool(np.allclose(safe, u, atol=1e-6))
|
| 19 |
-
return Prediction(safe, None, in_dom,
|
| 20 |
-
note="MPC step, clamped" if not in_dom else "MPC step, in envelope")
|
| 21 |
-
|
| 22 |
-
def benchmark(self):
|
| 23 |
-
rng = np.random.default_rng(uq.SEED)
|
| 24 |
-
clamp = get("KGATE").clamp
|
| 25 |
-
# (1) closed-loop tracking: drive from a start state to a setpoint
|
| 26 |
-
ref = np.array([2.2, 0.3, 3.0, 1.0, 0.2, 30.0])
|
| 27 |
-
x = np.array([2.0, 0.0, 2.0, 0.5, 0.1, 20.0])
|
| 28 |
-
for _ in range(200):
|
| 29 |
-
safe, _ = clamp(_mpc(x, ref)); x = _plant_step(x, safe, rng)
|
| 30 |
-
rng_scale = np.array([1, 1, 4.2, 3, 0.4, 47.21])
|
| 31 |
-
track_rms = float(np.sqrt(np.mean(((x - ref) / rng_scale) ** 2)))
|
| 32 |
-
# (2) Exp-B: broken controllers emit unsafe commands; clamp must catch all
|
| 33 |
-
from .spine import _LO, _HI
|
| 34 |
-
adversaries = {
|
| 35 |
-
"drift": lambda: _HI * (1 + 0.5 * rng.random(6)),
|
| 36 |
-
"edge_seeker": lambda: _HI + 5,
|
| 37 |
-
"nan_garbage": lambda: np.where(rng.random(6) < 0.3, np.nan, _HI * 3),
|
| 38 |
-
}
|
| 39 |
-
escapes = 0; steps = 0
|
| 40 |
-
for _, gen in adversaries.items():
|
| 41 |
-
for _ in range(50_000):
|
| 42 |
-
safe, _ = clamp(gen()); steps += 1
|
| 43 |
-
if not (np.all(safe >= _LO - 1e-9) and np.all(safe <= _HI + 1e-9)):
|
| 44 |
-
escapes += 1
|
| 45 |
-
# (3) real latency of an MPC step + clamp
|
| 46 |
-
t0 = time.perf_counter()
|
| 47 |
-
for _ in range(2000):
|
| 48 |
-
clamp(_mpc(x, ref))
|
| 49 |
-
us = (time.perf_counter() - t0) / 2000 * 1e6
|
| 50 |
-
return {"member": self.name,
|
| 51 |
-
"live_tracking_rms_frac": round(track_rms, 4),
|
| 52 |
-
"live_expB_model_failure": {"adversaries": list(adversaries),
|
| 53 |
-
"steps": steps, "escapes": escapes,
|
| 54 |
-
"catch_rate": 1.0 - escapes / steps},
|
| 55 |
-
"live_mpc_step_us": round(us, 1),
|
| 56 |
-
"sourced": {"file": "track5_control/clamp_activation_stats.csv",
|
| 57 |
-
"headline": "0 escapes / 150k steps / 3000 injected (AC-25); tracking <5%"}}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
publish/records/kairos/metadata.json
DELETED
|
@@ -1,65 +0,0 @@
|
|
| 1 |
-
{
|
| 2 |
-
"kname": "KAIROS",
|
| 3 |
-
"page": "https://kronosfusionenergy.com/kodex/kairos",
|
| 4 |
-
"title": "KODEX \u2014 KAIROS: CONTROL",
|
| 5 |
-
"version": "0.2.0",
|
| 6 |
-
"publication_date": "2026-09-11",
|
| 7 |
-
"language": "eng",
|
| 8 |
-
"upload_type": "software",
|
| 9 |
-
"creators": [
|
| 10 |
-
{
|
| 11 |
-
"name": "Ford, P. I.",
|
| 12 |
-
"orcid": "0000-0003-0395-1752",
|
| 13 |
-
"affiliation": "Kronos Fusion Energy"
|
| 14 |
-
}
|
| 15 |
-
],
|
| 16 |
-
"license": {
|
| 17 |
-
"id": "Apache-2.0"
|
| 18 |
-
},
|
| 19 |
-
"keywords": [
|
| 20 |
-
"fusion energy",
|
| 21 |
-
"spherical tokamak",
|
| 22 |
-
"D-3He",
|
| 23 |
-
"AI/ML surrogate model",
|
| 24 |
-
"uncertainty quantification",
|
| 25 |
-
"digital twin",
|
| 26 |
-
"Kronos Fusion Energy",
|
| 27 |
-
"CONTROL",
|
| 28 |
-
"KODEX:KAIROS"
|
| 29 |
-
],
|
| 30 |
-
"related_identifiers": [
|
| 31 |
-
{
|
| 32 |
-
"relation": "isDocumentedBy",
|
| 33 |
-
"identifier": "https://kronosfusionenergy.com/kodex/kairos",
|
| 34 |
-
"resource_type": "publication-other"
|
| 35 |
-
},
|
| 36 |
-
{
|
| 37 |
-
"relation": "isPartOf",
|
| 38 |
-
"identifier": "https://kronosfusionenergy.com/kodex",
|
| 39 |
-
"resource_type": "publication-other"
|
| 40 |
-
},
|
| 41 |
-
{
|
| 42 |
-
"relation": "isSupplementTo",
|
| 43 |
-
"identifier": "https://github.com/KronosFE/kronos-ml",
|
| 44 |
-
"resource_type": "software"
|
| 45 |
-
},
|
| 46 |
-
{
|
| 47 |
-
"relation": "references",
|
| 48 |
-
"identifier": "10.5281/zenodo.22645689",
|
| 49 |
-
"resource_type": "publication"
|
| 50 |
-
},
|
| 51 |
-
{
|
| 52 |
-
"relation": "isCompiledBy",
|
| 53 |
-
"identifier": "https://github.com/KronosFE/kronos-toolkit",
|
| 54 |
-
"resource_type": "software"
|
| 55 |
-
},
|
| 56 |
-
{
|
| 57 |
-
"relation": "references",
|
| 58 |
-
"identifier": "10.5281/zenodo.21842371",
|
| 59 |
-
"resource_type": "dataset"
|
| 60 |
-
}
|
| 61 |
-
],
|
| 62 |
-
"description": "<p><strong>KODEX — KAIROS</strong> (CONTROL). real-time closed-loop MPC control (analytic finite-horizon QP); supplies the model-free L4 clamp that KGATE enforces</p><p><strong>Benchmark:</strong> MPC tracking 0.0461 (<5%); Exp-B **0 escapes / 150,000**; 96.1 \u00b5s/step</p><p>Part of KODEX, the Kronos Family of Codes — a benchmarked AI/ML fusion surrogate suite with calibrated uncertainty and an abstention gate (<code>predict(x) → (y, uncertainty, in_domain)</code>). Provenance: references 10.5281/zenodo.21842371. Home: <a href=\"https://kronosfusionenergy.com/kodex/kairos\">https://kronosfusionenergy.com/kodex/kairos</a> · suite: <a href=\"https://github.com/KronosFE/kronos-ml\">https://github.com/KronosFE/kronos-ml</a>. Licensed under Apache-2.0. Honest card preserved verbatim.</p>",
|
| 63 |
-
"description_plain": "KODEX \u2014 KAIROS (CONTROL). real-time closed-loop MPC control (analytic finite-horizon QP); supplies the model-free L4 clamp that KGATE enforcesBenchmark: MPC tracking 0.0461 (Part of KODEX, the Kronos Family of Codes \u2014 a benchmarked AI/ML fusion surrogate suite with calibrated uncertainty and an abstention gate (predict(x) \u2192 (y, uncertainty, in_domain)). Provenance: references 10.5281/zenodo.21842371. Home: https://kronosfusionenergy.com/kodex/kairos \u00b7 suite: https://github.com/KronosFE/kronos-ml. Licensed under Apache-2.0. Honest card preserved verbatim.",
|
| 64 |
-
"notes": "Draft-first per-code deposit. Full package (all 26 codes): https://github.com/KronosFE/kronos-ml. Provenance chain in card.md + MANIFEST.sha256."
|
| 65 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
publish/records/kbench/CITATION.cff
DELETED
|
@@ -1,13 +0,0 @@
|
|
| 1 |
-
cff-version: 1.2.0
|
| 2 |
-
title: "KODEX — KBENCH: BENCHMARK (Kronos Family of Codes)"
|
| 3 |
-
version: "0.2.0"
|
| 4 |
-
date-released: "2026-09-11"
|
| 5 |
-
license: Apache-2.0
|
| 6 |
-
url: "https://kronosfusionenergy.com/kodex/kbench"
|
| 7 |
-
repository-code: "https://github.com/KronosFE/kronos-ml"
|
| 8 |
-
type: software
|
| 9 |
-
authors:
|
| 10 |
-
- family-names: Ford
|
| 11 |
-
given-names: "P. I."
|
| 12 |
-
orcid: "https://orcid.org/0000-0003-0395-1752"
|
| 13 |
-
affiliation: "Kronos Fusion Energy"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
publish/records/kbench/LICENSE
DELETED
|
@@ -1,189 +0,0 @@
|
|
| 1 |
-
Apache License
|
| 2 |
-
Version 2.0, January 2004
|
| 3 |
-
http://www.apache.org/licenses/
|
| 4 |
-
|
| 5 |
-
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
| 6 |
-
|
| 7 |
-
1. Definitions.
|
| 8 |
-
|
| 9 |
-
"License" shall mean the terms and conditions for use, reproduction,
|
| 10 |
-
and distribution as defined by Sections 1 through 9 of this document.
|
| 11 |
-
|
| 12 |
-
"Licensor" shall mean the copyright owner or entity authorized by
|
| 13 |
-
the copyright owner that is granting the License.
|
| 14 |
-
|
| 15 |
-
"Legal Entity" shall mean the union of the acting entity and all
|
| 16 |
-
other entities that control, are controlled by, or are under common
|
| 17 |
-
control with that entity. For the purposes of this definition,
|
| 18 |
-
"control" means (i) the power, direct or indirect, to cause the
|
| 19 |
-
direction or management of such entity, whether by contract or
|
| 20 |
-
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
| 21 |
-
outstanding shares, or (iii) beneficial ownership of such entity.
|
| 22 |
-
|
| 23 |
-
"You" (or "Your") shall mean an individual or Legal Entity
|
| 24 |
-
exercising permissions granted by this License.
|
| 25 |
-
|
| 26 |
-
"Source" form shall mean the preferred form for making modifications,
|
| 27 |
-
including but not limited to software source code, documentation
|
| 28 |
-
source, and configuration files.
|
| 29 |
-
|
| 30 |
-
"Object" form shall mean any form resulting from mechanical
|
| 31 |
-
transformation or translation of a Source form, including but not
|
| 32 |
-
limited to compiled object code, generated documentation, and
|
| 33 |
-
conversions to other media types.
|
| 34 |
-
|
| 35 |
-
"Work" shall mean the work of authorship, whether in Source or
|
| 36 |
-
Object form, made available under the License, as indicated by a
|
| 37 |
-
copyright notice that is included in or attached to the work.
|
| 38 |
-
|
| 39 |
-
"Derivative Works" shall mean any work, whether in Source or Object
|
| 40 |
-
form, that is based on (or derived from) the Work and for which the
|
| 41 |
-
editorial revisions, annotations, elaborations, or other modifications
|
| 42 |
-
represent, as a whole, an original work of authorship. For the purposes
|
| 43 |
-
of this License, Derivative Works shall not include works that remain
|
| 44 |
-
separable from, or merely link (or bind by name) to the interfaces of,
|
| 45 |
-
the Work and Derivative Works thereof.
|
| 46 |
-
|
| 47 |
-
"Contribution" shall mean any work of authorship, including the
|
| 48 |
-
original version of the Work and any modifications or additions
|
| 49 |
-
to that Work or Derivative Works thereof, that is intentionally
|
| 50 |
-
submitted to Licensor for inclusion in the Work by the copyright owner
|
| 51 |
-
or by an individual or Legal Entity authorized to submit on behalf of
|
| 52 |
-
the copyright owner. For the purposes of this definition, "submitted"
|
| 53 |
-
means any form of electronic, verbal, or written communication sent
|
| 54 |
-
to the Licensor or its representatives, including but not limited to
|
| 55 |
-
communication on electronic mailing lists, source code control systems,
|
| 56 |
-
and issue tracking systems that are managed by, or on behalf of, the
|
| 57 |
-
Licensor for the purpose of discussing and improving the Work, but
|
| 58 |
-
excluding communication that is conspicuously marked or otherwise
|
| 59 |
-
designated in writing by the copyright owner as "Not a Contribution."
|
| 60 |
-
|
| 61 |
-
"Contributor" shall mean Licensor and any individual or Legal Entity
|
| 62 |
-
on behalf of whom a Contribution has been received by Licensor and
|
| 63 |
-
subsequently incorporated within the Work.
|
| 64 |
-
|
| 65 |
-
2. Grant of Copyright License. Subject to the terms and conditions of
|
| 66 |
-
this License, each Contributor hereby grants to You a perpetual,
|
| 67 |
-
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
| 68 |
-
copyright license to reproduce, prepare Derivative Works of,
|
| 69 |
-
publicly display, publicly perform, sublicense, and distribute the
|
| 70 |
-
Work and such Derivative Works in Source or Object form.
|
| 71 |
-
|
| 72 |
-
3. Grant of Patent License. Subject to the terms and conditions of
|
| 73 |
-
this License, each Contributor hereby grants to You a perpetual,
|
| 74 |
-
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
| 75 |
-
(except as stated in this section) patent license to make, have made,
|
| 76 |
-
use, offer to sell, sell, import, and otherwise transfer the Work,
|
| 77 |
-
where such license applies only to those patent claims licensable
|
| 78 |
-
by such Contributor that are necessarily infringed by their
|
| 79 |
-
Contribution(s) alone or by combination of their Contribution(s)
|
| 80 |
-
with the Work to which such Contribution(s) was submitted. If You
|
| 81 |
-
institute patent litigation against any entity (including a
|
| 82 |
-
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
| 83 |
-
or a Contribution incorporated within the Work constitutes direct
|
| 84 |
-
or contributory patent infringement, then any patent licenses
|
| 85 |
-
granted to You under this License for that Work shall terminate
|
| 86 |
-
as of the date such litigation is filed.
|
| 87 |
-
|
| 88 |
-
4. Redistribution. You may reproduce and distribute copies of the
|
| 89 |
-
Work or Derivative Works thereof in any medium, with or without
|
| 90 |
-
modifications, and in Source or Object form, provided that You
|
| 91 |
-
meet the following conditions:
|
| 92 |
-
|
| 93 |
-
(a) You must give any other recipients of the Work or Derivative
|
| 94 |
-
Works a copy of this License; and
|
| 95 |
-
|
| 96 |
-
(b) You must cause any modified files to carry prominent notices
|
| 97 |
-
stating that You changed the files; and
|
| 98 |
-
|
| 99 |
-
(c) You must retain, in the Source form of any Derivative Works
|
| 100 |
-
that You distribute, all copyright, patent, trademark, and
|
| 101 |
-
attribution notices from the Source form of the Work,
|
| 102 |
-
excluding those notices that do not pertain to any part of
|
| 103 |
-
the Derivative Works; and
|
| 104 |
-
|
| 105 |
-
(d) If the Work includes a "NOTICE" text file as part of its
|
| 106 |
-
distribution, then any Derivative Works that You distribute must
|
| 107 |
-
include a readable copy of the attribution notices contained
|
| 108 |
-
within such NOTICE file, excluding those notices that do not
|
| 109 |
-
pertain to any part of the Derivative Works.
|
| 110 |
-
|
| 111 |
-
You may add Your own copyright statement to Your modifications and
|
| 112 |
-
may provide additional or different license terms and conditions
|
| 113 |
-
for use, reproduction, or distribution of Your modifications, or
|
| 114 |
-
for any such Derivative Works as a whole, provided Your use,
|
| 115 |
-
reproduction, and distribution of the Work otherwise complies with
|
| 116 |
-
the conditions stated in this License.
|
| 117 |
-
|
| 118 |
-
5. Submission of Contributions. Unless You explicitly state otherwise,
|
| 119 |
-
any Contribution intentionally submitted for inclusion in the Work
|
| 120 |
-
by You to the Licensor shall be under the terms and conditions of
|
| 121 |
-
this License, without any additional terms or conditions.
|
| 122 |
-
Notwithstanding the above, nothing herein shall supersede or modify
|
| 123 |
-
the terms of any separate license agreement you may have executed
|
| 124 |
-
with Licensor regarding such Contributions.
|
| 125 |
-
|
| 126 |
-
6. Trademarks. This License does not grant permission to use the trade
|
| 127 |
-
names, trademarks, service marks, or product names of the Licensor,
|
| 128 |
-
except as required for reasonable and customary use in describing the
|
| 129 |
-
origin of the Work and reproducing the content of the NOTICE file.
|
| 130 |
-
|
| 131 |
-
7. Disclaimer of Warranty. Unless required by applicable law or
|
| 132 |
-
agreed to in writing, Licensor provides the Work (and each
|
| 133 |
-
Contributor provides its Contributions) on an "AS IS" BASIS,
|
| 134 |
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
| 135 |
-
implied, including, without limitation, any warranties or conditions
|
| 136 |
-
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
| 137 |
-
PARTICULAR PURPOSE. You are solely responsible for determining the
|
| 138 |
-
appropriateness of using or redistributing the Work and assume any
|
| 139 |
-
risks associated with Your exercise of permissions under this License.
|
| 140 |
-
|
| 141 |
-
8. Limitation of Liability. In no event and under no legal theory,
|
| 142 |
-
whether in tort (including negligence), contract, or otherwise,
|
| 143 |
-
unless required by applicable law (such as deliberate and grossly
|
| 144 |
-
negligent acts) or agreed to in writing, shall any Contributor be
|
| 145 |
-
liable to You for damages, including any direct, indirect, special,
|
| 146 |
-
incidental, or consequential damages of any character arising as a
|
| 147 |
-
result of this License or out of the use or inability to use the
|
| 148 |
-
Work (including but not limited to damages for loss of goodwill,
|
| 149 |
-
work stoppage, computer failure or malfunction, or any and all
|
| 150 |
-
other commercial damages or losses), even if such Contributor
|
| 151 |
-
has been advised of the possibility of such damages.
|
| 152 |
-
|
| 153 |
-
9. Accepting Warranty or Additional Liability. While redistributing
|
| 154 |
-
the Work or Derivative Works thereof, You may choose to offer,
|
| 155 |
-
and charge a fee for, acceptance of support, warranty, indemnity,
|
| 156 |
-
or other liability obligations and/or rights consistent with this
|
| 157 |
-
License. However, in accepting such obligations, You may act only
|
| 158 |
-
on Your own behalf and on Your sole responsibility, not on behalf
|
| 159 |
-
of any other Contributor, and only if You agree to indemnify,
|
| 160 |
-
defend, and hold each Contributor harmless for any liability
|
| 161 |
-
incurred by, or claims asserted against, such Contributor by reason
|
| 162 |
-
of your accepting any such warranty or additional liability.
|
| 163 |
-
|
| 164 |
-
END OF TERMS AND CONDITIONS
|
| 165 |
-
|
| 166 |
-
APPENDIX: How to apply the Apache License to your work.
|
| 167 |
-
|
| 168 |
-
To apply the Apache License to your work, attach the following
|
| 169 |
-
boilerplate notice, with the fields enclosed by brackets "[]"
|
| 170 |
-
replaced with your own identifying information. (Don't include
|
| 171 |
-
the brackets!) The text should be enclosed in the appropriate
|
| 172 |
-
comment syntax for the file format. We also recommend that a
|
| 173 |
-
file or class name and description of purpose be included on the
|
| 174 |
-
same "printed page" as the copyright notice for easier
|
| 175 |
-
identification within third-party archives.
|
| 176 |
-
|
| 177 |
-
Copyright 2026 Kronos Fusion Energy
|
| 178 |
-
|
| 179 |
-
Licensed under the Apache License, Version 2.0 (the "License");
|
| 180 |
-
you may not use this file except in compliance with the License.
|
| 181 |
-
You may obtain a copy of the License at
|
| 182 |
-
|
| 183 |
-
http://www.apache.org/licenses/LICENSE-2.0
|
| 184 |
-
|
| 185 |
-
Unless required by applicable law or agreed to in writing, software
|
| 186 |
-
distributed under the License is distributed on an "AS IS" BASIS,
|
| 187 |
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 188 |
-
See the License for the specific language governing permissions and
|
| 189 |
-
limitations under the License.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
publish/records/kbench/MANIFEST.sha256
DELETED
|
@@ -1,7 +0,0 @@
|
|
| 1 |
-
# KODEX KBENCH SHA-256 (0.2.0, 2026-09-11)
|
| 2 |
-
cecfe7657f26a4b4af96f4257070e8769c4c9266748d8717f4ceeb3fbba00e83 CITATION.cff
|
| 3 |
-
ae87ebecd1f321a19799e21f6fe25e4a74261f16c91e6cb6cc248e6197dcf838 LICENSE
|
| 4 |
-
1f532ca6a582bc0e639f3490dc421c799f583766a8639863078d00ff3ef66f75 benchmark.json
|
| 5 |
-
65f7c48c499563e291bf9230ac6098dcee186eaf437e97b43b41a640638fa972 card.md
|
| 6 |
-
4d0e21b1012d27a9f9a2bb6cccb937530a8efe1ed02b6b9d5cc569ac8ad42c91 kbench.py
|
| 7 |
-
e62bf7f72ba3ffda7478ade5c404e054bb0e77d9a42be30352ef1952673934a4 metadata.json
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
publish/records/kbench/benchmark.json
DELETED
|
@@ -1,44 +0,0 @@
|
|
| 1 |
-
{
|
| 2 |
-
"member": "KBENCH",
|
| 3 |
-
"live_benchmark_suite": {
|
| 4 |
-
"n_tasks": 3,
|
| 5 |
-
"tasks": {
|
| 6 |
-
"cgyro-turbulence-flux": {
|
| 7 |
-
"inputs": [
|
| 8 |
-
"a_LT",
|
| 9 |
-
"shear"
|
| 10 |
-
],
|
| 11 |
-
"target": "log10 Q_tot (regression) + turbulent/quiet (classification)",
|
| 12 |
-
"n_samples": 16,
|
| 13 |
-
"metric": "R2 (regression) / leave-one-out accuracy (classification)",
|
| 14 |
-
"loader": "kronos_ml.data.cgyro_flux_map_final()",
|
| 15 |
-
"baseline_code": "KYRO",
|
| 16 |
-
"baseline_score": "R2 ~0.86, turbulent/quiet 16/16",
|
| 17 |
-
"note": "real CGYRO A1e saturated-flux (mu=400 representative)"
|
| 18 |
-
},
|
| 19 |
-
"mast-disruption": {
|
| 20 |
-
"inputs": "physics features (Ip family + EFIT + n=1 Mirnov / P_rad)",
|
| 21 |
-
"target": "disruptive (binary)",
|
| 22 |
-
"n_samples": 591,
|
| 23 |
-
"metric": "ROC-AUC (+ independent-precursor AUC)",
|
| 24 |
-
"loader": "kronos_ml.data.kward_real()",
|
| 25 |
-
"baseline_code": "KWARD",
|
| 26 |
-
"baseline_score": "AUC ~0.98, independent-precursor 0.975",
|
| 27 |
-
"note": "real MAST shots (FAIR-MAST); labels are heuristic Ip-quench"
|
| 28 |
-
},
|
| 29 |
-
"cgyro-rom-compressibility": {
|
| 30 |
-
"inputs": "flux-database matrix (points x [inputs, fluxes])",
|
| 31 |
-
"target": "rel-L2 reconstruction error vs retained bond dimension",
|
| 32 |
-
"n_samples": 16,
|
| 33 |
-
"metric": "rel-L2 vs rank",
|
| 34 |
-
"loader": "kronos_ml.data.cgyro_flux_map_final()",
|
| 35 |
-
"baseline_code": "KTENSOR",
|
| 36 |
-
"baseline_score": "effective rank 2.93/4 (not strongly low-rank)",
|
| 37 |
-
"note": "honest ROM characterization"
|
| 38 |
-
}
|
| 39 |
-
},
|
| 40 |
-
"how_to_use": "load via each task's loader, use the fixed reproducible split, report the metric, and try to beat the named KODEX baseline_code",
|
| 41 |
-
"verdict": "3 open, citable fusion-ML tasks (CGYRO turbulence, MAST disruption, flux ROM) with real on-disk data + reproducible KODEX baselines \u2014 a community leaderboard starting point, not a private result"
|
| 42 |
-
},
|
| 43 |
-
"caveat": "small by mainstream-ML standards (CGYRO = 16 pts); honest pilot fusion-ML benchmarks"
|
| 44 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
publish/records/kbench/card.md
DELETED
|
@@ -1,13 +0,0 @@
|
|
| 1 |
-
# KODEX KBENCH — card
|
| 2 |
-
|
| 3 |
-
- **name:** KBENCH
|
| 4 |
-
- **function:** BENCHMARK
|
| 5 |
-
- **status:** BUILT
|
| 6 |
-
- **phase:** 3
|
| 7 |
-
- **provenance:** n/a
|
| 8 |
-
- **retired_by:** community-standard fusion-ML benchmarks
|
| 9 |
-
- **gates:** []
|
| 10 |
-
- **note:** open, citable ML benchmark suite for fusion — real CGYRO turbulence + MAST disruption tasks with fixed splits, metrics and KODEX baselines to beat. Bring your own model; move the community forward
|
| 11 |
-
- **available:** True
|
| 12 |
-
|
| 13 |
-
Benchmark headline: open fusion-ML benchmark suite: **3 citable tasks** (CGYRO turbulence, MAST disruption, flux ROM) with real data + KODEX baselines
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
publish/records/kbench/kbench.py
DELETED
|
@@ -1,54 +0,0 @@
|
|
| 1 |
-
"""KODEX KBENCH — source excerpt (class). Full runnable package: https://github.com/KronosFE/kronos-ml"""
|
| 2 |
-
|
| 3 |
-
@register
|
| 4 |
-
class KBENCH(Surrogate):
|
| 5 |
-
name = "KBENCH"; function = "BENCHMARK"; phase = 3; status = "BUILT"
|
| 6 |
-
provenance = "n/a"
|
| 7 |
-
retired_by = "community-standard fusion-ML benchmarks"
|
| 8 |
-
real_codes = ("open ML benchmark suite",)
|
| 9 |
-
gates = ()
|
| 10 |
-
note = ("open, citable ML benchmark suite for fusion — real CGYRO turbulence + MAST "
|
| 11 |
-
"disruption tasks with fixed splits, metrics and KODEX baselines to beat. Bring "
|
| 12 |
-
"your own model; move the community forward")
|
| 13 |
-
|
| 14 |
-
def tasks(self):
|
| 15 |
-
return {
|
| 16 |
-
"cgyro-turbulence-flux": {
|
| 17 |
-
"inputs": ["a_LT", "shear"],
|
| 18 |
-
"target": "log10 Q_tot (regression) + turbulent/quiet (classification)",
|
| 19 |
-
"n_samples": 16, "metric": "R2 (regression) / leave-one-out accuracy (classification)",
|
| 20 |
-
"loader": "kronos_ml.data.cgyro_flux_map_final()",
|
| 21 |
-
"baseline_code": "KYRO", "baseline_score": "R2 ~0.86, turbulent/quiet 16/16",
|
| 22 |
-
"note": "real CGYRO A1e saturated-flux (mu=400 representative)"},
|
| 23 |
-
"mast-disruption": {
|
| 24 |
-
"inputs": "physics features (Ip family + EFIT + n=1 Mirnov / P_rad)",
|
| 25 |
-
"target": "disruptive (binary)",
|
| 26 |
-
"n_samples": 591, "metric": "ROC-AUC (+ independent-precursor AUC)",
|
| 27 |
-
"loader": "kronos_ml.data.kward_real()",
|
| 28 |
-
"baseline_code": "KWARD", "baseline_score": "AUC ~0.98, independent-precursor 0.975",
|
| 29 |
-
"note": "real MAST shots (FAIR-MAST); labels are heuristic Ip-quench"},
|
| 30 |
-
"cgyro-rom-compressibility": {
|
| 31 |
-
"inputs": "flux-database matrix (points x [inputs, fluxes])",
|
| 32 |
-
"target": "rel-L2 reconstruction error vs retained bond dimension",
|
| 33 |
-
"n_samples": 16, "metric": "rel-L2 vs rank",
|
| 34 |
-
"loader": "kronos_ml.data.cgyro_flux_map_final()",
|
| 35 |
-
"baseline_code": "KTENSOR", "baseline_score": "effective rank 2.93/4 (not strongly low-rank)",
|
| 36 |
-
"note": "honest ROM characterization"},
|
| 37 |
-
}
|
| 38 |
-
|
| 39 |
-
def _predict(self, x):
|
| 40 |
-
t = self.tasks()
|
| 41 |
-
key = x if isinstance(x, str) and x in t else next(iter(t))
|
| 42 |
-
return Prediction(t[key], None, True, note=f"fusion-ML benchmark task spec: {key}")
|
| 43 |
-
|
| 44 |
-
def benchmark(self):
|
| 45 |
-
t = self.tasks()
|
| 46 |
-
return {"member": self.name,
|
| 47 |
-
"live_benchmark_suite": {
|
| 48 |
-
"n_tasks": len(t), "tasks": t,
|
| 49 |
-
"how_to_use": ("load via each task's loader, use the fixed reproducible split, report "
|
| 50 |
-
"the metric, and try to beat the named KODEX baseline_code"),
|
| 51 |
-
"verdict": ("3 open, citable fusion-ML tasks (CGYRO turbulence, MAST disruption, flux "
|
| 52 |
-
"ROM) with real on-disk data + reproducible KODEX baselines — a community "
|
| 53 |
-
"leaderboard starting point, not a private result")},
|
| 54 |
-
"caveat": "small by mainstream-ML standards (CGYRO = 16 pts); honest pilot fusion-ML benchmarks"}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
publish/records/kbench/metadata.json
DELETED
|
@@ -1,65 +0,0 @@
|
|
| 1 |
-
{
|
| 2 |
-
"kname": "KBENCH",
|
| 3 |
-
"page": "https://kronosfusionenergy.com/kodex/kbench",
|
| 4 |
-
"title": "KODEX \u2014 KBENCH: BENCHMARK",
|
| 5 |
-
"version": "0.2.0",
|
| 6 |
-
"publication_date": "2026-09-11",
|
| 7 |
-
"language": "eng",
|
| 8 |
-
"upload_type": "software",
|
| 9 |
-
"creators": [
|
| 10 |
-
{
|
| 11 |
-
"name": "Ford, P. I.",
|
| 12 |
-
"orcid": "0000-0003-0395-1752",
|
| 13 |
-
"affiliation": "Kronos Fusion Energy"
|
| 14 |
-
}
|
| 15 |
-
],
|
| 16 |
-
"license": {
|
| 17 |
-
"id": "Apache-2.0"
|
| 18 |
-
},
|
| 19 |
-
"keywords": [
|
| 20 |
-
"fusion energy",
|
| 21 |
-
"spherical tokamak",
|
| 22 |
-
"D-3He",
|
| 23 |
-
"AI/ML surrogate model",
|
| 24 |
-
"uncertainty quantification",
|
| 25 |
-
"digital twin",
|
| 26 |
-
"Kronos Fusion Energy",
|
| 27 |
-
"BENCHMARK",
|
| 28 |
-
"KODEX:KBENCH"
|
| 29 |
-
],
|
| 30 |
-
"related_identifiers": [
|
| 31 |
-
{
|
| 32 |
-
"relation": "isDocumentedBy",
|
| 33 |
-
"identifier": "https://kronosfusionenergy.com/kodex/kbench",
|
| 34 |
-
"resource_type": "publication-other"
|
| 35 |
-
},
|
| 36 |
-
{
|
| 37 |
-
"relation": "isPartOf",
|
| 38 |
-
"identifier": "https://kronosfusionenergy.com/kodex",
|
| 39 |
-
"resource_type": "publication-other"
|
| 40 |
-
},
|
| 41 |
-
{
|
| 42 |
-
"relation": "isSupplementTo",
|
| 43 |
-
"identifier": "https://github.com/KronosFE/kronos-ml",
|
| 44 |
-
"resource_type": "software"
|
| 45 |
-
},
|
| 46 |
-
{
|
| 47 |
-
"relation": "references",
|
| 48 |
-
"identifier": "10.5281/zenodo.22645689",
|
| 49 |
-
"resource_type": "publication"
|
| 50 |
-
},
|
| 51 |
-
{
|
| 52 |
-
"relation": "isCompiledBy",
|
| 53 |
-
"identifier": "https://github.com/KronosFE/kronos-toolkit",
|
| 54 |
-
"resource_type": "software"
|
| 55 |
-
},
|
| 56 |
-
{
|
| 57 |
-
"relation": "references",
|
| 58 |
-
"identifier": "10.5281/zenodo.21842371",
|
| 59 |
-
"resource_type": "dataset"
|
| 60 |
-
}
|
| 61 |
-
],
|
| 62 |
-
"description": "<p><strong>KODEX — KBENCH</strong> (BENCHMARK). open, citable ML benchmark suite for fusion \u2014 real CGYRO turbulence + MAST disruption tasks with fixed splits, metrics and KODEX baselines to beat. Bring your own model; move the community forward</p><p><strong>Benchmark:</strong> open fusion-ML benchmark suite: **3 citable tasks** (CGYRO turbulence, MAST disruption, flux ROM) with real data + KODEX baselines</p><p>Part of KODEX, the Kronos Family of Codes — a benchmarked AI/ML fusion surrogate suite with calibrated uncertainty and an abstention gate (<code>predict(x) → (y, uncertainty, in_domain)</code>). Provenance: references 10.5281/zenodo.21842371. Home: <a href=\"https://kronosfusionenergy.com/kodex/kbench\">https://kronosfusionenergy.com/kodex/kbench</a> · suite: <a href=\"https://github.com/KronosFE/kronos-ml\">https://github.com/KronosFE/kronos-ml</a>. Licensed under Apache-2.0. Honest card preserved verbatim.</p>",
|
| 63 |
-
"description_plain": "KODEX \u2014 KBENCH (BENCHMARK). open, citable ML benchmark suite for fusion \u2014 real CGYRO turbulence + MAST disruption tasks with fixed splits, metrics and KODEX baselines to beat. Bring your own model; move the community forwardBenchmark: open fusion-ML benchmark suite: **3 citable tasks** (CGYRO turbulence, MAST disruption, flux ROM) with real data + KODEX baselinesPart of KODEX, the Kronos Family of Codes \u2014 a benchmarked AI/ML fusion surrogate suite with calibrated uncertainty and an abstention gate (predict(x) \u2192 (y, uncertainty, in_domain)). Provenance: references 10.5281/zenodo.21842371. Home: https://kronosfusionenergy.com/kodex/kbench \u00b7 suite: https://github.com/KronosFE/kronos-ml. Licensed under Apache-2.0. Honest card preserved verbatim.",
|
| 64 |
-
"notes": "Draft-first per-code deposit. Full package: https://github.com/KronosFE/kronos-ml. Provenance chain in card.md + MANIFEST.sha256."
|
| 65 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
publish/records/kbreed/CITATION.cff
DELETED
|
@@ -1,13 +0,0 @@
|
|
| 1 |
-
cff-version: 1.2.0
|
| 2 |
-
title: "KODEX — KBREED: breeder (Kronos Family of Codes)"
|
| 3 |
-
version: "0.2.0"
|
| 4 |
-
date-released: "2026-09-11"
|
| 5 |
-
license: Apache-2.0
|
| 6 |
-
url: "https://kronosfusionenergy.com/kodex/kbreed"
|
| 7 |
-
repository-code: "https://github.com/KronosFE/kronos-ml"
|
| 8 |
-
type: software
|
| 9 |
-
authors:
|
| 10 |
-
- family-names: Ford
|
| 11 |
-
given-names: "P. I."
|
| 12 |
-
orcid: "https://orcid.org/0000-0003-0395-1752"
|
| 13 |
-
affiliation: "Kronos Fusion Energy"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|