Catalog PyPI
Back to packageRELEASE DETAILS

3.0.0

PyPI

adcd

Anomaly-Driven Correction Discovery: Physics-Constrained Symbolic Regression for Evolutionary Scientific Discovery

discoveryjaxlearningmachinephysicsregressionscientificsymbolic
Published24 Jun 2026
Direct dependencies15
Transitive dependenciesNot calculated

README

Version 3.0.0 documentation

ADCD — Anomaly-Driven Correction Discovery

Physics-constrained symbolic regression that discovers correction terms — not equations from scratch. The same logic that led from Newton to Einstein, from Rayleigh–Jeans to Planck.

DOI License: MIT Python Support

Science rarely discovers from a blank slate — it corrects. ADCD automates the step between anomaly and theory correction: given a classical law and data that disagrees with it, it searches for the minimal physically-valid correction term $\Delta$ — passing every candidate through dimensional, asymptotic, and complexity gates before a single parameter is ever fit.


⚡ Key Features

  • Correction-First Paradigm — Starts from a known classical law, not a blank slate. Focuses the search space on the discrepancy $\Delta$ between theory and experiment.
  • Cascaded Physics Gates — AST complexity, dimensional homogeneity, transcendental guardrails, and asymptotic consistency (ARC) gates screen out unphysical candidates before running parameter-fitting.
  • JAX-Traced L-BFGS-B Optimizer — Highly optimized parameter-scaled differentiable fitting with multi-restart log-uniform initialization.
  • BIC Model Selection — Employs the Bayesian Information Criterion (BIC) to rank models, favoring simpler physical theories over overly complex numerical fits.
  • Residual Feature Intelligence — Extracts mathematical features (monotonicity, curvature, oscillation, decay) from residuals to bias proposal templates.
  • Phase 2: Multivariable Discovery — Buckingham Π group decomposition + per-variable Sequential ARC + variance-factorization separability detection for multi-input physical laws.
  • Real-World Validated — Successfully identifies correct structural classes on Mercury's perihelion (GR), Lamb Shift (QED), Muon g-2 (Schwinger), and Blackbody (Planck).

📦 Installation

Install the stable package from PyPI:

pip install adcd

Or install from source:

git clone https://github.com/apiprdt/PhysicsPaper.git
cd PhysicsPaper
pip install -e ".[dev]"

Verify your installation:

pytest tests/

💻 Quick Start

1. High-Level Scientific API

Running ADCD on predefined physics benchmarks is extremely simple:

import adcd

# 1. Load a pre-defined benchmark scenario (e.g. Relativistic Kinetic Energy)
scenarios = adcd.get_all_scenarios()
scenario = scenarios[0]

# 2. Run discovery in a single line!
result = adcd.discover_correction(scenario, max_iterations=5, proposer="mock")

# 3. View the best fit
print(f"Discovered correction: {result.best_expr}")       # θ₀ * (v/c)**2
print(f"LaTeX representation:  {result.export_latex()}")   # \theta_0 \left(\frac{v}{c}\right)^2
print(f"Parameters:            {result.best_theta}")
print(f"BIC Score:             {result.best_bic:.2f}")

# 4. Plot residuals
result.plot_residuals()

2. Custom Experimental Datasets

For custom datasets, use the adcd.fit function:

import numpy as np
import adcd

# Your custom data
x = np.linspace(1.0, 5.0, 100)
X = {"x": x}
y_classical = 2.0 * x
y_observed  = 2.0 * x + 0.5 * x**2   # True correction is 0.5 * x^2

# Run ADCD
result = adcd.fit(
    X=X,
    y_obs=y_observed,
    y_classical=y_classical,
    limit_variable="x",
    limit_direction="0",
    correction_mode="additive"
)

result.summary()

📊 Benchmark Results

Headline (primary claim): a mean structural recovery of 80.4% (±7.4%) across sixteen independent seeds (95% bootstrap CI [76.7%, 84.0%]). The reference seed=42 below is disclosed explicitly as the highest-performing seed (94.4%) — the mean, not the peak, is the claim. Full per-seed × per-noise breakdown ships in results/seed_distribution.json.

1. Multi-Seed Distribution (primary result, Mock Proposer)

Noise levelADCD mean (16 seeds)ADCD worst seedADCD best (seed=42)
0%86.8% (±9.8%)66.7% (6/9)100% (9/9)
1%81.2% (±14.6%)44.4% (4/9)100% (9/9)
5%77.1% (±10.0%)66.7% (6/9)88.9% (8/9)
10%76.4% (±12.3%)55.6% (5/9)88.9% (8/9)
Overall80.4% (±7.4%)69.4% (25/36)94.4% (34/36)

2. Reference-Seed Detail (seed=42, Mock Proposer)

ScenarioTier0% Noise1% Noise5% Noise10% Noise
Relativistic KETextbook✓✓✓✓
Yukawa GravityTextbook✓✓✓✓
Anharmonic SpringTextbook✓✓✓✓
Screened CoulombCross-Domain✓✓✗✗
Net RadiationCross-Domain✓✓✓✓
Nonlinear DragCross-Domain✓✓✓✓
Mystery-A (tanh²)Synthetic✓✓✓✓
Mystery-B (sinc)Synthetic✓✓✓✓
Mystery-C (log-quotient)Synthetic✓✓✓✓
Overall100%100%88.9%88.9%

3. PySR Comparison (same residual, 5% noise — the structural-selection test)

The gap is seed-independent: even ADCD's worst of 16 seeds beats PySR fair, and PySR with doubled budget cannot reach ADCD's worst seed.

Method (5% noise)0%1%5%10%
ADCD (ours, seed=42)9/9 (100%)9/9 (100%)8/9 (88.9%)8/9 (88.9%)
ADCD multi-seed mean86.8%81.2%77.1%76.4%
ADCD worst of 16 seeds66.7%44.4%66.7%55.6%
PySR fair (100 iter, 60s)4/9 (44.4%)5/9 (55.6%)1/9 (11.1%)5/9 (55.6%)
PySR generous (2× budget)4/9 (44.4%)4/9 (44.4%)5/9 (55.6%)2/9 (22.2%)

At 5% noise the gap is +66.0 points (ADCD multi-seed mean 77.1% vs PySR fair 11.1%). Doubling PySR's budget (generous, 55.6%) does not close it — and that doubled-budget figure still sits below ADCD's worst of 16 seeds (66.7%). PySR was run once per (scenario, noise); ADCD across 16 seeds. PySR non-monotonic under noise; ADCD stable.

3. Phase 2: Multivariable Benchmark

ScenarioVariablesADCD SolvedNotes
Yukawa Mass-Ratiom, M, r, r₀✓Π groups: m/M, r/r₀
Turbulent Dragv, ρ, A, C_D✓Separable multiplicative
Coupled Oscillatork, m, Ω, ω₀✗Mixed functional form
Van der Waals MVa, b, P, V, T✗Requires 3rd Π group
Overall2/4 (50%)Baseline: 0/4

4. Real-World Physical Constants

Validation on historical anomalies using physical constants from JPL DE440, NIST, and CODATA:

Physical ScenarioDiscovered CorrectionConvergedClass MatchNMSE
Mercury Perihelion (GR)θ₀·vc²—✓ polynomial1.11e-05
Hydrogen Lamb Shift (QED)θ₀(n/θ₁)^(-θ₂)✓✓ power_law1.82e-18
Muon g-2 (Schwinger)θ₀(α/π)^θ₁✓✓ polynomial7.94e-07
Blackbody (Planck)-1 + e^(-f/θ₁)—✓ exponential2.59e-02

📁 Project Structure

adcd-v3.0.0/
├── src/adcd/                       # Installable package
│   ├── __init__.py                 # Public API (fit, discover_correction)
│   ├── anomaly_scenarios.py        # 9 standard + 3 blind + 4 multivariable scenarios
│   ├── arc_scorer.py               # Asymptotic consistency gate (ARC)
│   ├── buckingham_pi.py            # [Phase 2] Buckingham Π group engine
│   ├── coarse_evaluator.py         # Coarse numerical pre-filter
│   ├── correction_orchestrator.py  # Main multi-iteration discovery loop
│   ├── dimensional_checker.py      # Dimensional homogeneity + transcendental gate
│   ├── jax_optimizer.py            # JAX L-BFGS-B optimizer
│   ├── llm_proposer.py             # Mock + Gemini + OpenAI proposers
│   ├── metrics.py                  # NMSE, BIC, structural classification
│   ├── multivar_orchestrator.py    # [Phase 2] Multivariable correction pipeline
│   ├── pipeline.py                 # Stage 1 filter cascade
│   ├── real_data_loader.py         # Real-world data loading (JPL, NIST, CODATA)
│   ├── residual_factorizer_v2.py   # [Phase 2] Variance-decomposition separability
│   ├── result.py                   # CorrectionResult object
│   └── sequential_arc.py           # [Phase 2] Per-variable Sequential ARC checker
├── tests/                          # Unit + integration tests
├── paper/                          # LaTeX source (main.tex) + figures
├── data/                           # Input datasets (SPARC, cosmic chronometers, growth rate)
├── scripts/                         # Table generation and verification scripts
├── run_correction_discovery.py     # Benchmark runner
└── README.md                       # This file

📖 Citing This Work

If you use ADCD in your research, please cite:

@software{erdita2026adcd,
  author    = {Erdita, Muhammad Afif},
  title     = {{Anomaly-Driven Correction Discovery (ADCD): Physics-Constrained
                Symbolic Regression for Evolutionary Scientific Discovery}},
  year      = {2026},
  publisher = {Zenodo},
  version   = {3.0.0},
  doi       = {10.5281/zenodo.20534940},
  url       = {https://doi.org/10.5281/zenodo.20534940}
}

🔬 Reproducibility

Every quantitative claim in this project is reproducible from committed scripts. No number is hand-typed.

# Regenerate the 9-scenario benchmark (seed=42)
python run_correction_discovery.py

# Multi-seed study (16 seeds × 9 scenarios × 4 noise levels)
python run_reproducibility.py

# Build the per-seed × per-noise anti-cherry-pick artifact
python scripts/generate_seed_distribution.py    # → results/seed_distribution.json

# Guard: fails loudly if any headline number drifts
python scripts/verify_paper_claims.py

# SPARC MOND robustness study
python -m adcd.experiments.sparc_robustness

The full test suite must pass before any release:

pytest tests/ -q

📄 License

This project is licensed under the MIT License.

Downloads & popularity

Awaiting observations

No metric observations yet

Download counts and popularity will appear here as the collector receives them.

Declared dependencies 15

Native requirements
15 direct targetsNot calculated transitive count
Package / targetRequirementRelationship
numpy
Environment
{
  "extras": "",
  "marker": null,
  "requires_python": ">=3.10",
  "evaluation": "NOT_EVALUATED"
}
numpy>=1.24runtime
scipy
Environment
{
  "extras": "",
  "marker": null,
  "requires_python": ">=3.10",
  "evaluation": "NOT_EVALUATED"
}
scipy>=1.11runtime
sympy
Environment
{
  "extras": "",
  "marker": null,
  "requires_python": ">=3.10",
  "evaluation": "NOT_EVALUATED"
}
sympy>=1.12runtime
jax
Environment
{
  "extras": "",
  "marker": null,
  "requires_python": ">=3.10",
  "evaluation": "NOT_EVALUATED"
}
jax>=0.4.20runtime
jaxlib
Environment
{
  "extras": "",
  "marker": null,
  "requires_python": ">=3.10",
  "evaluation": "NOT_EVALUATED"
}
jaxlib>=0.4.20runtime
matplotlib
Environment
{
  "extras": "",
  "marker": null,
  "requires_python": ">=3.10",
  "evaluation": "NOT_EVALUATED"
}
matplotlib>=3.7runtime
scikit-learn
Environment
{
  "extras": "",
  "marker": null,
  "requires_python": ">=3.10",
  "evaluation": "NOT_EVALUATED"
}
scikit-learn>=1.3runtime
pandas
Environment
{
  "extras": "",
  "marker": null,
  "requires_python": ">=3.10",
  "evaluation": "NOT_EVALUATED"
}
pandas>=1.5runtime
pytest
Environment
{
  "extras": "",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.10",
  "evaluation": "NOT_EVALUATED"
}
pytest>=7.4; extra == "dev"runtime
pytest-cov
Environment
{
  "extras": "",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.10",
  "evaluation": "NOT_EVALUATED"
}
pytest-cov>=4.1; extra == "dev"runtime
flake8
Environment
{
  "extras": "",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.10",
  "evaluation": "NOT_EVALUATED"
}
flake8>=6.1; extra == "dev"runtime
black
Environment
{
  "extras": "",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.10",
  "evaluation": "NOT_EVALUATED"
}
black>=23.0; extra == "dev"runtime
google-generativeai
Environment
{
  "extras": "",
  "marker": "extra == \"llm\"",
  "requires_python": ">=3.10",
  "evaluation": "NOT_EVALUATED"
}
google-generativeai>=0.3; extra == "llm"runtime
pysr
Environment
{
  "extras": "",
  "marker": "extra == \"benchmark\"",
  "requires_python": ">=3.10",
  "evaluation": "NOT_EVALUATED"
}
pysr>=1.5; extra == "benchmark"runtime
adcd
Environment
{
  "extras": "benchmark,dev,llm",
  "marker": "extra == \"all\"",
  "requires_python": ">=3.10",
  "evaluation": "NOT_EVALUATED"
}
adcd[benchmark,dev,llm]; extra == "all"runtime

Distribution files

2 collected
adcd-3.0.0-py3-none-any.whl

bdist_wheel · 147.39 KB · Python py3

Source file
adcd-3.0.0.tar.gz

sdist · 165.73 KB · Python source

Source file

Repository

PENDING
apiprdt/physicspaper

Shared repository data · GitHub

License detected in repository
Not collected

Metadata history

Meaningful changes
Current collected state Current

Observed since 20 Oct, 19:14 UTC

No superseded metadata states collected. Unchanged observations do not create new revisions.

Record identity

package_version:4b8377609221a21763b78a1e4efa23b64fb6b7fca56fdc13eee58a3ea444fb5b

Other collected versions

View all collected versions →