Note

This page renders committed notebook outputs. The Read the Docs build does not execute notebook code.

Comparing fitted, finite-map, formula-backed, and failed candidates#

Current surface: V0.29.

Purpose#

Compare candidate representations under one empirical validation vocabulary instead of assuming every discovered-looking object is trustworthy.

What you will learn#

  • How known finite maps, fitted polynomial generators, and formula-backed records differ.

  • How conclusion labels validated, partially_validated, and failed should be interpreted.

  • How direct/fallback evidence labels and wrong-span failures appear in reports.

Required extras#

Core install is enough.

Expected runtime#

Under 1 minute.

Out of scope#

No learned detector, no callable generator, no proof of symmetry, no KS runtime promotion.

These notebooks are tutorials, not API contracts. Example outputs are runtime summaries, not canonical paper artifacts.

[1]:
from pathlib import Path
import sys

ROOT = Path.cwd()
if not (ROOT / "pyproject.toml").exists():
    ROOT = ROOT.parent
if str(ROOT) not in sys.path:
    sys.path.insert(0, str(ROOT))
import numpy as np

from notebooks._tutorial_utils import confidence_card, plot_singular_values, print_cards, pretty_json
from pdelie import GeneratorFamily, InvariantMapSpec
from pdelie.data import generate_heat_1d_field_batch
from pdelie.reporting import summarize_formula_generator_family, summarize_generator_fit_diagnostics
from pdelie.residuals import HeatResidualEvaluator
from pdelie.symmetry import FormulaGeneratorFamily, fit_translation_generator, validate_symmetry_candidate

CONFIG = {"fit_epsilon": 1e-4, "finite_shift": float(np.pi / 4.0)}
CONFIG

[1]:
{'fit_epsilon': 0.0001, 'finite_shift': 0.7853981633974483}

1. Fit a polynomial translation generator#

[2]:
field = generate_heat_1d_field_batch(batch_size=4, num_times=33, num_points=64, seed=640)
evaluator = HeatResidualEvaluator()
fitted = fit_translation_generator(field, evaluator, epsilon=CONFIG["fit_epsilon"])
fit_summary = summarize_generator_fit_diagnostics(fitted)
plot_singular_values(fit_summary, title="Fitted generator design spectrum")
fit_summary

../_images/tutorials_04_discovered_vs_known_translation_generators_3_0.png
[2]:
{'summary_schema_version': '0.1',
 'summary_type': 'generator_fit_diagnostics',
 'parameterization': 'polynomial_translation_affine',
 'fit_mode': 'svd',
 'training_epsilon': 0.0001,
 'basis': ['1', 't', 'x', 'u'],
 'basis_delta_norms': {'1': 0.004296394298193215,
  't': 174.57692166784753,
  'x': 3567.3412985986092,
  'u': 126.76115865877486},
 'design_column_norms': {'1': 0.004296394298193215,
  't': 174.57692166784753,
  'x': 3567.3412985986092,
  'u': 126.76115865877486},
 'singular_values': [3567.342339962003,
  174.60620587941526,
  126.69149930872412,
  0.0038731770687536362],
 'condition_number': 921037.7621878132,
 'fit_residual': 0.0038731770687536362,
 'min_delta_basis': '1',
 'selected_coefficients': [0.9999999999415194,
  1.0381394087638847e-05,
  -7.176322837209081e-09,
  -3.0311445954099065e-06],
 'svd_coefficients': [0.9999999999415194,
  1.0381394087638847e-05,
  -7.176322837209081e-09,
  -3.0311445954099065e-06],
 'selected_span_distance': 1.0814861638697691e-05,
 'svd_span_distance': 1.0814861638697691e-05,
 'reference_fallback_used': False,
 'fallback_reason': None,
 'evidence_label': 'direct_svd_in_tolerance'}

2. Build alternative candidate representations#

The finite-map candidate is an InvariantMapSpec. The formula candidate stores safe JSON expression metadata, not executable code.

[3]:
spec = InvariantMapSpec(
    generator_metadata=fitted.to_dict(),
    construction_method="uniform_translation",
    parameters={"axis": "x", "shift": CONFIG["finite_shift"]},
    domain_validity="global",
    inverse_available=True,
    diagnostics={},
)
formula = FormulaGeneratorFamily(
    formula_generators=[
        {
            "name": "formula_translation",
            "components": {
                "tau": {"node": "const", "value": 0.0},
                "xi": {"node": "const", "value": 1.0},
                "phi": {"node": "const", "value": 0.0},
            },
        }
    ],
    finite_transform_spec=spec.to_dict(),
)
wrong = GeneratorFamily(
    parameterization=fitted.parameterization,
    coefficients=np.asarray([[0.0, 0.0, 1.0, 0.0]], dtype=float),
    basis_spec=fitted.basis_spec,
    normalization=fitted.normalization,
    diagnostics={},
)
print(pretty_json(summarize_formula_generator_family(formula)))

{
  "component_names": [
    "tau",
    "xi",
    "phi"
  ],
  "component_nodes": {
    "phi": [
      "const"
    ],
    "tau": [
      "const"
    ],
    "xi": [
      "const"
    ]
  },
  "diagnostics": {},
  "finite_transform_available": true,
  "finite_transform_construction_method": "uniform_translation",
  "formula_kinds": {
    "const": 3
  },
  "generator_count": 1,
  "generator_names": [
    "formula_translation"
  ],
  "parameterization": "formula_generator_family",
  "reciprocal_denominator_floor": 1e-12,
  "schema_version": "0.1",
  "summary_schema_version": "0.1",
  "summary_type": "formula_generator_family",
  "symbolic_references": [],
  "variables": [
    "t",
    "x",
    "u"
  ]
}

3. Validate every candidate under the same field and residual target#

[4]:
cases = {
    "fitted_generator_family": fitted,
    "finite_translation_spec": spec.to_dict(),
    "formula_with_finite_transform": formula,
    "wrong_span_generator": wrong,
}
reports = {
    name: validate_symmetry_candidate(
        field,
        candidate,
        residual_evaluator=evaluator,
        source_candidate_id=name,
    )
    for name, candidate in cases.items()
}
cards = [
    confidence_card(
        label=name,
        fit=fit_summary if name == "fitted_generator_family" else None,
        validation=report,
    )
    for name, report in reports.items()
]
print_cards(cards)

[
  {
    "candidate_kind": "generator_family",
    "condition_number": 921037.7621878132,
    "evidence_label": "direct_svd_in_tolerance",
    "fit_mode": "svd",
    "label": "fitted_generator_family",
    "reference_fallback_used": false,
    "selected_span_distance": 1.0814861638697691e-05,
    "singular_value_count": 4,
    "svd_span_distance": 1.0814861638697691e-05,
    "validation_conclusion": "validated"
  },
  {
    "candidate_kind": "invariant_map_spec",
    "label": "finite_translation_spec",
    "validation_conclusion": "validated"
  },
  {
    "candidate_kind": "formula_generator_family",
    "label": "formula_with_finite_transform",
    "validation_conclusion": "validated"
  },
  {
    "candidate_kind": "generator_family",
    "label": "wrong_span_generator",
    "validation_conclusion": "failed"
  }
]

4. Inspect failure as a first-class outcome#

A failed candidate is useful: it shows that validation is empirical and configured, not a rubber stamp.

[5]:
print(pretty_json({name: report["conclusion"] for name, report in reports.items()}))
print(pretty_json(reports["wrong_span_generator"], max_chars=3500))

{
  "finite_translation_spec": "validated",
  "fitted_generator_family": "validated",
  "formula_with_finite_transform": "validated",
  "wrong_span_generator": "failed"
}
{
  "candidate_kind": "generator_family",
  "candidate_summary": {
    "coefficient_shape": [
      1,
      4
    ],
    "coefficients": [
      [
        0.0,
        0.0,
        1.0,
        0.0
      ]
    ],
    "diagnostics": {},
    "fallback_reason": null,
    "fit_mode": null,
    "generator_names": null,
    "normalization": "l2_unit",
    "parameterization": "polynomial_translation_affine",
    "reference_fallback_used": null,
    "summary_schema_version": "0.1",
    "summary_type": "generator_family",
    "translation_span_distance": 1.4142135623730951
  },
  "check_reports": {
    "finite_transform_verification": {
      "report": {
        "classification": "failed",
        "diagnostics": {
          "batch_errors": [
            [
              0.003680206784620462,
              0.004729281486696321,
              0.0016744306242292603,
              0.0005985977258368695
            ],
            [
              0.01163783569982316,
              0.014955301194045612,
              0.005295014556513332,
              0.0018929322158421373
            ],
            [
              0.03680206784624526,
              0.04729281486700312,
              0.016744306242317295,
              0.005985977258370113
            ],
            [
              0.11637835699818891,
              0.14955301194040524,
              0.05295014556510434,
              0.018929322158419058
            ],
            [
              0.3680206784624749,
              0.4729281486700427,
              0.16744306242319326,
              0.05985977258370071
            ],
            [
              1.0969944869114534,
              1.268019583468842,
              0.6130436149426347,
              0.14249826325632717
            ],
            [
              2.261515580065275,
              0.8910920410809624,
              2.889891586564692,
              0.5750800053038561
            ]
          ],
          "heldout_initial_conditions": 4,
          "span_distance": 1.4142135623730951,
          "span_tolerance": 0.05,
          "transform_mode": "pointwise_translation"
        },
        "epsilon_values": [
          0.0001,
          0.00031622776601683794,
          0.001,
          0.0031622776601683794,
          0.01,
          0.03162277660168379,
          0.1
        ],
        "error_curve": [
          0.002677318704424861,
          0.008466425128168246,
          0.026773187044281277,
          0.08466425128164662,
          0.2677318704428341,
          0.8550190509270441,
          1.5763038105731186
        ],
        "first_epsilon": 0.0001,
        "first_error": 0.002677318704424861,
        "max_error": 1.5763038105731186,
        "norm": "relative_l2",
        "summary_schema_version": "0.1",
        "summary_type": "verification_report"
      },
      "required": true,
      "status": "failed",
      "threshold": "classification != 'failed'"
    },
    "schema": {
      "report": {
        "object": "GeneratorFamily"
      },
      "required": true,
      "status": "passed"
    }
  },
  "closure_required": true,
  "conclusion": "failed",
  "configured_validation_checks": [
    "schema",
    "finite_transform_verification"
  ],
  "empirical_interpretation": "configured_validation_not_mathematical_proof",
  "equation": null,
  "field_shape": [
    4,
    33,
    64,
    1
  ],
  "finite_transform_epsilons": [
    0.0001,
    0.00031622776601683794,
    0.001,
    0.0031622776601683794,
    0.01,
    0.0316227766016
... <truncated 524 chars>

Recap#

Different candidate types can be compared with one vocabulary: candidate_kind, configured checks, evidence labels, and validated / partially_validated / failed conclusions.

Common failure modes#

  • Fallback-backed evidence rather than direct residual-based fitting.

  • Wrong generator span despite valid schema.

  • Finite transform unavailable, producing only partial validation.

  • Formula-only finite evaluation without residual-preservation evidence.

  • Empirical validation being mistaken for proof.

Extension ideas#

  • Add a Fisher-KPP fitted generator as another candidate.

  • Compare reference-generator span diagnostics when a trusted reference exists.

  • Use the same report structure for outputs from an external symmetry method.

What to read/run next#

Run 05_closure_algebra_diagnostics.ipynb to separate algebra diagnostics from residual preservation.