A deterministic, identifiability-aware framework for recovering algebraic corrections to known physical laws from noisy observational data.
Reproduce all three validated scenarios from the paper with one command.
Step 1 — Clone & install
git clone <repo-url>
cd PhysicsPaper
python -m venv .venv
source .venv/bin/activate # Linux / macOS
# .\.venv\Scripts\Activate.ps1 # Windows PowerShell
pip install -r requirements.txtStep 2 — Run the full validation
# Linux / macOS
export PYTHONPATH=src
python src/adcd/run_adcd_v3_validation_blind.py --top-k 5
# Windows PowerShell
$env:PYTHONPATH = "src"
python src\adcd\run_adcd_v3_validation_blind.py --top-k 5Step 3 — Read the output
Results print to stdout and are also saved automatically to run_outputs/adcd_v3_taxonomy_validation_report.json.
Expected summary:
═══════════════════════════════════════════════
ADCD v3 — Validation Summary
═══════════════════════════════════════════════
Scenario NMSE ΔBIC Verdict
───────────────────────────────────────────────
Screened Coulomb 2.77e-04 30.65 IDENTIFIABLE
Entropy Expansion 1.59e-02 14.70 IDENTIFIABLE
Time Dilation 4.12e-01 13.79 WITHHELD
═══════════════════════════════════════════════
Reproducibility: Results are byte-exact across runs (deterministic grammar enumeration + fixed seed). See REPRODUCIBILITY.md.
- How ADCD Works
- Installation (detailed)
- Python API
- Validated Results
- Repository Structure
- Reproducibility
- Limitations
- Citation & License
Core idea: Given a known classical law
The constraint
Classical law y_cl ─────┐
├─► Residual ──► Grammar ──► Gates ──► Optimizer ──► Pareto ──► Verdict
Observations y_obs ─────┘ (Δ = y_obs/y_cl - 1)
All corrections are expressed over five basis functions, each vanishing at
| Name | Physical archetype | |
|---|---|---|
D_lor |
Lorentz / special relativity | |
D_rat |
Rational poles | |
D_exp |
Exponential screening (Debye, Yukawa) | |
D_log |
Entropy, Van der Waals | |
D_sqrt_inv |
Inverse-root corrections |
| Step | Name | Criterion |
|---|---|---|
| 1 | Budget Disclosure | Search space size logged before results |
| 2 | Positive Control | Optimizer recovers structure within correct primitive family (NMSE < 0.05) |
| 3 | Ablation Control |
|
| 4 | Determinism Check | 3 independent runs produce byte-exact identical JSON output |
A scenario is IDENTIFIABLE only if all four steps pass. Otherwise it is WITHHELD — meaning the pipeline honestly reports insufficient evidence.
Requirements: Python 3.10+, CPU only (no GPU needed).
# Clone the repository
git clone <repo-url>
cd PhysicsPaper
# Create and activate a virtual environment
python -m venv .venv
source .venv/bin/activate # Linux / macOS
# .\.venv\Scripts\Activate.ps1 # Windows PowerShell
# Install dependencies (pinned to exact paper versions)
pip install -r requirements.txt
# Set the source path (required before any import or command)
export PYTHONPATH=src # Linux / macOS
# $env:PYTHONPATH = "src" # Windows PowerShellTo verify installation:
python -c "from adcd.pipeline import Stage1Pipeline; print('ADCD installed OK')"from adcd.anomaly_scenarios import get_all_scenarios
from adcd.run_adcd_v3_validation_blind import run_scenario_protocol
# Get all three paper scenarios
scenarios = get_all_scenarios()
sc = next(s for s in scenarios if s.name == "Screened Coulomb")
# Run the full 4-step blind protocol
results = run_scenario_protocol(sc, top_k=5)
print(results["verdict"]) # "IDENTIFIABLE"from adcd.anomaly_scenarios import AnomalyScenario
scenario = AnomalyScenario(
name="My Scenario",
tier="synthetic", # "textbook" | "synthetic" | "cross_domain"
domain="mechanics",
# Known classical baseline
classical_expr="0.5 * m * v**2",
classical_variables=["m", "v"],
classical_constants={"c": 2.99792458e8},
# Ground truth correction — withheld from pipeline, used only for evaluation
correction_type="multiplicative",
correction_expr="theta_0 * (v/c)**2",
correction_constants={"theta_0": 0.5},
# Physical metadata for the grammar and dimensional checker
anomaly_regime="high speeds v approaching c",
variables_with_units={"m": "kg", "v": "m/s", "c": "m/s"},
classical_limit_variable="v",
classical_limit_direction="0",
correction_class="rational", # "rational"|"logarithmic"|"exponential"|"power_law"
)
# Generate noisy observations
X, y_obs, y_classical, residual = scenario.generate_data(
n_points=200,
noise_level=0.01, # 1% Gaussian multiplicative noise
seed=42,
domain_max=0.3, # cap on the primary ratio (e.g. v/c ≤ 0.3)
)from adcd.pipeline import Stage1Pipeline
from adcd.grammar_proposer_v3 import GrammarProposerV3
from adcd.dimensional_checker import DimensionalChecker
from adcd.arc_scorer import ARCScorer, build_arc_regimes
from adcd.context import ProposalContext
# Build pipeline components
checker = DimensionalChecker()
arc = ARCScorer(regimes=build_arc_regimes())
context = ProposalContext.from_scenario(scenario)
# Enumerate candidates (fully blind — no ratio hints)
proposer = GrammarProposerV3()
candidates = proposer.propose(context)
print(f"Search space: {len(candidates)} candidates")
# Run all 5 physical gates
pipeline = Stage1Pipeline(checker, scenario)
survivors = pipeline.run(candidates, X, y_obs, y_classical)
print(f"Survived all gates: {len(survivors)} candidates")results = run_scenario_protocol(scenario, top_k=5)
print(f"Verdict: {results['verdict']}")
print(f"Top candidate: {results['blind_search']['top_candidate']}")
print(f"NMSE: {results['blind_search']['nmse']:.4e}")
print(f"BIC: {results['blind_search']['bic']:.2f}")
print(f"ΔBIC (ablation): {results['ablation_control']['bic_diff']:.2f}")
# Full Pareto front
for rank, c in enumerate(results['pareto_front'], 1):
print(f" Rank {rank} | BIC {c['bic']:>10.2f} | NMSE {c['nmse']:.3e} | {c['expr']}")Example output (Screened Coulomb):
Verdict: IDENTIFIABLE
Top candidate: theta_2 * (exp(-r/theta_0) - 1.0)
NMSE: 2.7722e-04
BIC: -1617.66
ΔBIC (ablation): 30.65
Rank 1 | BIC -1617.66 | NMSE 2.77e-04 | theta_2 * (exp(-r/theta_0) - 1.0)
Rank 2 | BIC -1612.93 | NMSE 2.76e-04 | theta_47 * (exp(-r/theta_0) - 1.0) * (...)
Dimensional Checker
from adcd.dimensional_checker import DimensionalChecker
import sympy as sp
checker = DimensionalChecker()
checker.registry["v"] = [1, 0, -1] # m/s → [L, M, T]
checker.registry["c"] = [1, 0, -1]
v, c = sp.symbols("v c")
is_ok, dims = checker.check_dimensionless(v**2 / c**2)
print(is_ok, dims) # True [0, 0, 0]ARC Scorer (Asymptotic Regime Check)
from adcd.arc_scorer import ARCScorer, build_arc_regimes
import sympy as sp
arc = ARCScorer(regimes=build_arc_regimes())
u = sp.Symbol("u")
print(arc.passes(u / (1 - u), limit_var=u, limit_val=0)) # True ✓ vanishes
print(arc.passes(sp.Rational(1, 2) + u, limit_var=u, limit_val=0)) # False ✗ non-zeroJAX Optimizer (standalone fit)
from adcd.jax_optimizer import JaxOptimizer
import sympy as sp, numpy as np
optimizer = JaxOptimizer(n_restarts=15)
expr = sp.sympify("theta_0 * (exp(-r / theta_1) - 1)")
params, nmse = optimizer.fit(expr, X={"r": r_data}, y=residual_data)
print(f"Fitted: {params}, NMSE: {nmse:.4e}")BIC & Identifiability Verdict
from adcd.identifiability import compute_bic, identifiability_verdict
bic = compute_bic(nmse=2.77e-4, n_params=2, n_points=200)
verdict = identifiability_verdict(delta_bic=30.65) # "IDENTIFIABLE" | "WITHHELD"
print(verdict)Three scenarios, seed = 42.
All numbers from a live JAX run on CPU — see run_outputs/.
| Scenario | Observation window | Rank-1 structure | ΔBIC | NMSE | Verdict |
|---|---|---|---|---|---|
| Screened Coulomb | 30.65 | 2.77 × 10⁻⁴ | IDENTIFIABLE | ||
| Entropy Expansion | 14.70 | 1.59 × 10⁻² | IDENTIFIABLE | ||
| Time Dilation | 13.79 | 4.12 × 10⁻¹ | WITHHELD |
Time Dilation: Lorentz structure is found at Rank 1 and ΔBIC > 10, but the positive control fails (NMSE = 0.41 > 0.05) within the historical
$v \le 0.3c$ window — meaning there is insufficient signal-to-noise for confident identification. The WITHHELD verdict is by design: the pipeline does not claim identifiability it cannot demonstrate.
PhysicsPaper/
├── src/adcd/ ← Core library
│ ├── run_adcd_v3_validation_blind.py ← Main entry point (4-step protocol)
│ ├── anomaly_scenarios.py ← AnomalyScenario dataclass + data generation
│ ├── pipeline.py ← 5-gate physical filter pipeline
│ ├── grammar_proposer_v3.py ← Deterministic candidate enumeration
│ ├── asymptotic_dictionary_proposer_v3.py ← Buckingham-Pi ratio derivation
│ ├── arc_scorer.py ← Gate 4: asymptotic limit check (ARC)
│ ├── dimensional_checker.py ← Gates 1–3: AST / units / transcendental
│ ├── coarse_evaluator.py ← Gate 5: NaN / inf pre-filter
│ ├── jax_optimizer.py ← Float64 JAX L-BFGS-B optimizer
│ ├── jax_precision_config.py ← JAX float64 precision enforcement
│ ├── bayesian_ranker.py ← BIC ranking and Pareto front builder
│ ├── identifiability.py ← ΔBIC computation and verdict logic
│ ├── metrics.py ← NMSE, symbolic + class match scoring
│ ├── constants.py ← CODATA 2018 physical constants
│ ├── context.py ← ProposalContext: scenario → grammar input
│ ├── quickfit.py ← Convenience single-fit wrapper
│ ├── budget_sweep.py ← Search-space budget analysis
│ ├── mode_detection.py ← Residual mode detection utilities
│ ├── residual_features.py ← Residual feature extraction
│ ├── real_data_loader.py ← Loader for external observational data
│ └── real_scenarios.py ← Non-synthetic scenario definitions
│
├── eval/ ← Evaluation & ablation scripts
│ ├── benchmark_runner.py
│ ├── ablation_extended.py
│ ├── independent_evaluator.py
│ └── compute_metrics.py
│
├── paper/ ← Paper source (LaTeX + figures)
│ ├── neurips_paper.tex ← Main manuscript
│ ├── neurips_2026.sty ← NeurIPS 2026 style file
│ ├── references.bib ← BibTeX bibliography
│ ├── fig1_recovery.pdf ← Figure 1: Correction recovery plots
│ ├── fig2_bic.pdf ← Figure 2: BIC identifiability
│ ├── fig3_parity.pdf ← Figure 3: Parity plots
│ └── generate_final_3_figures.py ← Figure generation script
│
├── run_outputs/ ← Validation reports (JSON)
├── data/ ← Reference datasets
├── tests/ ← Unit tests
│
├── reproduce_all.sh ← One-command full reproduction (Linux/macOS)
├── reproduce_all.ps1 ← One-command full reproduction (Windows)
├── requirements.txt ← Pinned dependencies
├── pyproject.toml ← Package metadata
└── REPRODUCIBILITY.md ← Full provenance chain
# Full reproduction — results saved to run_outputs/
export PYTHONPATH=src
python src/adcd/run_adcd_v3_validation_blind.py --top-k 5
# Or use the convenience script
bash reproduce_all.sh # Linux / macOS
# .\reproduce_all.ps1 # Windows PowerShellResults are byte-exact across runs because:
- Grammar enumeration is fully deterministic (no stochastic mutations)
- All random seeds are fixed (
seed=42throughout) - JAX computation graph is
jit-compiled on CPU withfloat64precision
For the full provenance chain — including a-priori AST budget justification and cross-run determinism verification — see REPRODUCIBILITY.md.
| Issue | Detail |
|---|---|
| Multiplicative corrections only | Grammar targets |
| Synthetic data | Validated on Gaussian noise with known structure. Extension to real observational data is future work. |
| Window-dependent verdicts | Identifiability depends on the observation regime. Results are specific to the stated domain bounds. |
| Charge / temperature dimensionless | The dimensional checker treats these as [0,0,0] by convention; ratios involving them need manual registry extension. |
| Positive-control threshold | Step 2 uses NMSE < 0.05. Scenarios with high inherent noise or very flat residuals may require threshold tuning. |
@inproceedings{adcd2026,
title = {Asymptotic Dictionary Correction Discovery: A Deterministic,
Identifiability-Aware Framework for Recovering Physical Corrections
from Observational Data},
author = {Anonymous Author(s)},
booktitle = {New in ML Workshop @ NeurIPS 2026},
year = {2026},
}Released under the MIT License — see LICENSE.