Physics-Constrained Symbolic Regression for Evolutionary Scientific Discovery
Explore the Documentation »
Quick Start
·
Key Features
·
Benchmarks
·
Run in Colab
Science rarely discovers from a blank slate — it corrects.
ADCD automates the step between anomaly and theory correction, the same step that led from Newtonian gravity to General Relativity, from Dirac to QED, and from Rayleigh-Jeans to Planck.
-
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.
- Real-World Validated — Successfully identifies correct structural classes on Mercury's perihelion (GR), Lamb Shift (QED), Muon g-2 (Schwinger), and Blackbody (Planck).
Install the stable package from PyPI:
pip install adcdOr install from source:
git clone https://github.com/apiprdt/PhysicsPaper.git
cd PhysicsPaper
pip install -e ".[dev]"Verify your installation:
pytest tests/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()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()| Scenario | Tier | 0% Noise | 1% Noise | 5% Noise | 10% Noise |
|---|---|---|---|---|---|
| Relativistic KE | Textbook | ✓ | ✓ | ✓ | ✓ |
| Yukawa Gravity | Textbook | ✓ | ✓ | ✓ | ✓ |
| Anharmonic Spring | Textbook | ✓ | ✓ | ✓ | ✓ |
| Screened Coulomb | Cross-Domain | ✓ | ✓ | ✗ | ✗ |
| Net Radiation | Cross-Domain | ✓ | ✓ | ✓ | ✓ |
| Nonlinear Drag | Cross-Domain | ✓ | ✓ | ✓ | ✓ |
| Mystery-A (tanh²) | Synthetic | ✓ | ✓ | ✓ | ✓ |
| Mystery-B (sinc) | Synthetic | ✓ | ✓ | ✓ | ✓ |
| Mystery-C (log-quotient) | Synthetic | ✓ | ✓ | ✓ | ✓ |
| Overall | 100% | 100% | 88.9% | 88.9% |
| Method | 0% Noise | 1% Noise | 5% Noise | 10% Noise |
|---|---|---|---|---|
| ADCD (ours, seed=42) | 9/9 (100%) | 9/9 (100%) | 8/9 (88.9%) | 8/9 (88.9%) |
| PySR fair | 4/9 (44.4%) | 5/9 (55.6%) | 1/9 (11.1%) | 5/9 (55.6%) |
ADCD outperforms PySR by +77.8 percentage points at 5% noise.
Validation on historical anomalies using physical constants from JPL DE440, NIST, and CODATA:
| Physical Scenario | Discovered Correction | Converged | Class Match | NMSE |
|---|---|---|---|---|
| Mercury Perihelion (GR) | θ₀·vc² |
— | ✓ polynomial | 1.11e-05 |
| Hydrogen Lamb Shift (QED) | θ₀(n/θ₁)^(-θ₂) |
✓ | ✓ power_law | 1.82e-18 |
| Muon g-2 (Schwinger) | θ₀(α/π)^θ₁ |
✓ | ✓ polynomial | 7.94e-07 |
| Blackbody (Planck) | -1 + e^(-f/θ₁) |
— | ✓ exponential | 2.59e-02 |
PhysicsPaper/
├── src/adcd/ # Installable package
│ ├── __init__.py # Public API (fit, discover_correction)
│ ├── anomaly_scenarios.py # 9 standard + 3 blind benchmark scenarios
│ ├── arc_scorer.py # Asymptotic consistency gate (ARC)
│ ├── 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
│ ├── pipeline.py # Stage 1 filter cascade
│ ├── real_data_loader.py # Real-world data loading (JPL, NIST, CODATA)
│ └── result.py # CorrectionResult object
├── tests/ # 77 unit + integration tests
├── paper/ # LaTeX source (main.tex) + figures
├── run_correction_discovery.py # Benchmark runner
└── README.md # This file
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 = {2.1.3},
doi = {10.5281/zenodo.20534940},
url = {https://doi.org/10.5281/zenodo.20534940}
}This project was developed with assistance from Google DeepMind's Antigravity AI assistant. AI was used as a pair-programming and writing tool. All scientific content, experimental design decisions, and intellectual contributions are the author's own.
This project is licensed under the MIT License.
