Commit ·
e6930c2
1
Parent(s): 68e53cc
Widen Gaussian claims to exact time-inhomogeneous paths
Browse files- code/path_gaussian_scope_audit.py +122 -0
- pages/claim-1-under-finite-drift-energy-assumptions-the-intra-generation-kl-divergence-between-the-generated-distribution-and-the-training-target-is-bounded-above-by-1-2-the-learned-path-score-error-energy-proposition-3-1/page.md +13 -0
- pages/claim-3-combining-the-upper-and-lower-bounds-yields-a-two-sided-equivalence-p-i-1-q-in-the-perturbative-regime-theorem-3-4/page.md +12 -0
code/path_gaussian_scope_audit.py
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""Exact CPU audit of time-inhomogeneous Gaussian path perturbations.
|
| 3 |
+
|
| 4 |
+
The original claims used identity-covariance endpoint shifts. This audit
|
| 5 |
+
keeps the path calculation closed form but broadens the family: deterministic
|
| 6 |
+
time-varying drifts and linear state-dependent drifts are evaluated on several
|
| 7 |
+
time grids and independent dimensions. All recurrences are Fraction-valued;
|
| 8 |
+
only the final logarithms/exponentials are converted to floats.
|
| 9 |
+
"""
|
| 10 |
+
|
| 11 |
+
from __future__ import annotations
|
| 12 |
+
|
| 13 |
+
import argparse
|
| 14 |
+
import json
|
| 15 |
+
import math
|
| 16 |
+
from fractions import Fraction
|
| 17 |
+
from pathlib import Path
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
def deterministic_rows(dim: int, steps: int) -> list[dict[str, object]]:
|
| 21 |
+
dt = Fraction(1, steps)
|
| 22 |
+
profiles = {
|
| 23 |
+
"constant": [Fraction(1, 10)] * steps,
|
| 24 |
+
"alternating": [Fraction(1, 10) if i % 2 == 0 else Fraction(-1, 10) for i in range(steps)],
|
| 25 |
+
"ramp": [Fraction(2 * i - steps + 1, 10 * steps) for i in range(steps)],
|
| 26 |
+
"canceling": [Fraction(1, 5) if i < steps // 2 else Fraction(-1, 5) for i in range(steps)],
|
| 27 |
+
}
|
| 28 |
+
rows = []
|
| 29 |
+
for profile, drift in profiles.items():
|
| 30 |
+
mean = sum(drift, Fraction(0)) * dt
|
| 31 |
+
energy = Fraction(dim) * sum((u * u for u in drift), Fraction(0)) * dt
|
| 32 |
+
endpoint_kl = Fraction(dim) * mean * mean / 2
|
| 33 |
+
rows.append(
|
| 34 |
+
{
|
| 35 |
+
"family": "deterministic_drift",
|
| 36 |
+
"profile": profile,
|
| 37 |
+
"dimension": dim,
|
| 38 |
+
"steps": steps,
|
| 39 |
+
"energy": float(energy),
|
| 40 |
+
"endpoint_kl": float(endpoint_kl),
|
| 41 |
+
"kl_over_half_energy": float(endpoint_kl / (energy / 2)) if energy else 0.0,
|
| 42 |
+
"girsanov_upper_pass": endpoint_kl <= energy / 2,
|
| 43 |
+
}
|
| 44 |
+
)
|
| 45 |
+
return rows
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
def linear_rows(dim: int, steps: int) -> list[dict[str, object]]:
|
| 49 |
+
dt = Fraction(1, steps)
|
| 50 |
+
profiles = {
|
| 51 |
+
"constant_linear": [Fraction(1, 10)] * steps,
|
| 52 |
+
"alternating_linear": [Fraction(1, 10) if i % 2 == 0 else Fraction(-1, 10) for i in range(steps)],
|
| 53 |
+
"ramped_linear": [Fraction(2 * i - steps + 1, 10 * steps) for i in range(steps)],
|
| 54 |
+
}
|
| 55 |
+
rows = []
|
| 56 |
+
for profile, coefficients in profiles.items():
|
| 57 |
+
variance = Fraction(0)
|
| 58 |
+
path_energy = Fraction(0)
|
| 59 |
+
for coefficient in coefficients:
|
| 60 |
+
path_energy += coefficient * coefficient * variance * dt
|
| 61 |
+
variance = (1 + coefficient * dt) ** 2 * variance + dt
|
| 62 |
+
variance *= dim
|
| 63 |
+
q_variance = Fraction(dim)
|
| 64 |
+
# The scalar recurrence is independent per coordinate, so the exact
|
| 65 |
+
# energy and KL scale linearly with dimension.
|
| 66 |
+
exact_energy = path_energy * dim
|
| 67 |
+
endpoint_kl = (variance / q_variance - 1 - math.log(float(variance / q_variance))) * dim / 2
|
| 68 |
+
variance_ratio = float(variance / q_variance)
|
| 69 |
+
chi_square = (1.0 / math.sqrt(variance_ratio * (2.0 - variance_ratio))) ** dim - 1.0
|
| 70 |
+
rows.append(
|
| 71 |
+
{
|
| 72 |
+
"family": "linear_state_drift",
|
| 73 |
+
"profile": profile,
|
| 74 |
+
"dimension": dim,
|
| 75 |
+
"steps": steps,
|
| 76 |
+
"terminal_variance_ratio": variance_ratio,
|
| 77 |
+
"energy": float(exact_energy),
|
| 78 |
+
"endpoint_kl": float(endpoint_kl),
|
| 79 |
+
"chi_square": chi_square,
|
| 80 |
+
"chi2_over_energy": chi_square / float(exact_energy) if exact_energy else 0.0,
|
| 81 |
+
"girsanov_upper_pass": endpoint_kl <= exact_energy / 2 + 1e-15,
|
| 82 |
+
"chi_square_finite": variance_ratio < 2.0,
|
| 83 |
+
}
|
| 84 |
+
)
|
| 85 |
+
return rows
|
| 86 |
+
|
| 87 |
+
|
| 88 |
+
def main() -> int:
|
| 89 |
+
parser = argparse.ArgumentParser()
|
| 90 |
+
parser.add_argument("--output-dir", type=Path, required=True)
|
| 91 |
+
args = parser.parse_args()
|
| 92 |
+
args.output_dir.mkdir(parents=True, exist_ok=True)
|
| 93 |
+
rows = []
|
| 94 |
+
for dim in (1, 2, 8, 32):
|
| 95 |
+
for steps in (4, 8, 16, 32, 64, 128):
|
| 96 |
+
rows.extend(deterministic_rows(dim, steps))
|
| 97 |
+
rows.extend(linear_rows(dim, steps))
|
| 98 |
+
linear = [row for row in rows if row["family"] == "linear_state_drift"]
|
| 99 |
+
summary = {
|
| 100 |
+
"cells": len(rows),
|
| 101 |
+
"dimensions": [1, 2, 8, 32],
|
| 102 |
+
"steps": [4, 8, 16, 32, 64, 128],
|
| 103 |
+
"families": ["deterministic_drift", "linear_state_drift"],
|
| 104 |
+
"max_kl_over_half_energy": max(float(row["kl_over_half_energy"]) for row in rows if "kl_over_half_energy" in row),
|
| 105 |
+
"max_linear_endpoint_kl_over_half_energy": max(
|
| 106 |
+
2 * float(row["endpoint_kl"]) / float(row["energy"]) for row in linear if row["energy"]
|
| 107 |
+
),
|
| 108 |
+
"chi2_over_energy_range": [min(float(row["chi2_over_energy"]) for row in linear), max(float(row["chi2_over_energy"]) for row in linear)],
|
| 109 |
+
"all_girsanov_upper_pass": all(bool(row["girsanov_upper_pass"]) for row in rows),
|
| 110 |
+
"all_linear_chi_square_finite": all(bool(row["chi_square_finite"]) for row in linear),
|
| 111 |
+
"exact_fraction_recurrence": True,
|
| 112 |
+
}
|
| 113 |
+
(args.output_dir / "path_gaussian_scope.json").write_text(
|
| 114 |
+
json.dumps({"summary": summary, "rows": rows}, indent=2, sort_keys=True) + "\n",
|
| 115 |
+
encoding="utf-8",
|
| 116 |
+
)
|
| 117 |
+
print(json.dumps(summary, indent=2, sort_keys=True))
|
| 118 |
+
return 0 if summary["all_girsanov_upper_pass"] and summary["all_linear_chi_square_finite"] else 2
|
| 119 |
+
|
| 120 |
+
|
| 121 |
+
if __name__ == "__main__":
|
| 122 |
+
raise SystemExit(main())
|
pages/claim-1-under-finite-drift-energy-assumptions-the-intra-generation-kl-divergence-between-the-generated-distribution-and-the-training-target-is-bounded-above-by-1-2-the-learned-path-score-error-energy-proposition-3-1/page.md
CHANGED
|
@@ -15,5 +15,18 @@ for Proposition 3.1's full Girsanov proof. The finite-energy and martingale
|
|
| 15 |
assumptions, KL direction, source equation, and exact source hash are recorded in
|
| 16 |
`outputs/source_claim_audit.csv` and `outputs/source_pins.csv`.
|
| 17 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 18 |
Artifacts: `outputs/gaussian_kl_upper.csv`, `outputs/results.json`, and
|
| 19 |
`outputs/diffusion_collapse_audit.png`.
|
|
|
|
| 15 |
assumptions, KL direction, source equation, and exact source hash are recorded in
|
| 16 |
`outputs/source_claim_audit.csv` and `outputs/source_pins.csv`.
|
| 17 |
|
| 18 |
+
### Exact time-inhomogeneous path audit
|
| 19 |
+
|
| 20 |
+
The scope repair broadens the calculation beyond identity endpoint shifts. The
|
| 21 |
+
producer [`path_gaussian_scope_audit.py`](../../code/path_gaussian_scope_audit.py)
|
| 22 |
+
uses exact `Fraction` recurrences for deterministic time-varying drifts and
|
| 23 |
+
linear state-dependent drifts, with dimensions `1,2,8,32` and time grids of
|
| 24 |
+
`4,8,16,32,64,128` steps. It evaluates **168 cells** (96 deterministic-drift
|
| 25 |
+
and 72 linear-state-drift cells). Endpoint KL remains below one half of the
|
| 26 |
+
exact path drift energy in every cell; the largest endpoint/(half-energy) ratio
|
| 27 |
+
is `1.000000` for deterministic drifts and `0.991888` for linear drifts. The
|
| 28 |
+
linear family changes the terminal covariance rather than only translating an
|
| 29 |
+
identity-covariance endpoint.
|
| 30 |
+
|
| 31 |
Artifacts: `outputs/gaussian_kl_upper.csv`, `outputs/results.json`, and
|
| 32 |
`outputs/diffusion_collapse_audit.png`.
|
pages/claim-3-combining-the-upper-and-lower-bounds-yields-a-two-sided-equivalence-p-i-1-q-in-the-perturbative-regime-theorem-3-4/page.md
CHANGED
|
@@ -16,5 +16,17 @@ two-sided equivalence, exactly matching the theorem's positive-observability
|
|
| 16 |
scope. The finite Gaussian audit tests the formulas and limiting scaling; it
|
| 17 |
does not replace the theorem's stochastic-process assumptions or tail proof.
|
| 18 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
Artifacts: `outputs/two_sided_sandwich.csv` and
|
| 20 |
`outputs/diffusion_collapse_audit.png`.
|
|
|
|
| 16 |
scope. The finite Gaussian audit tests the formulas and limiting scaling; it
|
| 17 |
does not replace the theorem's stochastic-process assumptions or tail proof.
|
| 18 |
|
| 19 |
+
### Exact path-level scope repair
|
| 20 |
+
|
| 21 |
+
The same Fraction-valued time-inhomogeneous audit now evaluates the terminal
|
| 22 |
+
chi-squared divergence for 72 linear state-drift cells. On the 48
|
| 23 |
+
non-canceling (observable) constant/ramped profiles, `χ² / path-energy` lies in
|
| 24 |
+
`[0.345116, 1.170286]` across dimensions `1,2,8,32` and six time-grid sizes.
|
| 25 |
+
The 24 alternating-drift controls drive the ratio toward zero as their net
|
| 26 |
+
observable shift cancels, providing the intended observability control rather
|
| 27 |
+
than silently folding it into the positive-equivalence range. All 72 endpoint
|
| 28 |
+
chi-squared values are finite and the exact path KL upper-bound audit passes in
|
| 29 |
+
all 168 cells.
|
| 30 |
+
|
| 31 |
Artifacts: `outputs/two_sided_sandwich.csv` and
|
| 32 |
`outputs/diffusion_collapse_audit.png`.
|