"""Direct numerical contract for the resolution limit in Theorem 4.2. This module uses only deterministic quadrature. The discrete measures are positive midpoint rules that weakly converge to a positive continuous measure on [0, 1]. The continuous reference is computed independently with Gauss--Legendre quadrature at two orders. """ from __future__ import annotations import csv import hashlib import json import os import platform import subprocess import sys import time from pathlib import Path import numpy as np from numpy.polynomial.legendre import leggauss from scipy.spatial.distance import cdist ROOT = Path(__file__).resolve().parents[2] ARTIFACT_DIR = ROOT / ".openresearch" / "artifacts" / "claim_2" FIXED_COMMAND = "uv run python repro/src/verify.py" def _kernel(left: np.ndarray, right: np.ndarray, name: str, sigma: float) -> np.ndarray: distances = cdist(left[:, None], right[:, None], metric="euclidean") if name == "gaussian": return np.exp(-(distances**2) / (2.0 * sigma**2)) if name == "exponential": return np.exp(-distances / sigma) raise ValueError(f"unsupported kernel: {name}") def _density(points: np.ndarray, name: str) -> np.ndarray: if name == "uniform": return np.ones_like(points) if name == "affine": # Strictly positive on the closed domain and integrates to one. return 0.5 + points if name == "oscillatory": # Strict lower bound 0.55; integral is one. return 1.0 + 0.45 * np.cos(2.0 * np.pi * points) raise ValueError(f"unsupported density: {name}") def _signal(points: np.ndarray, name: str) -> np.ndarray: if name == "constant": return np.ones_like(points) if name == "linear": return points if name == "quadratic": return points**2 if name == "sin_2pi": return np.sin(2.0 * np.pi * points) if name == "cos_3pi": return np.cos(3.0 * np.pi * points) raise ValueError(f"unsupported signal: {name}") def _sinkhorn_scaling( points: np.ndarray, weights: np.ndarray, kernel_name: str, sigma: float, tolerance: float = 2e-14, max_iterations: int = 2_000, ) -> tuple[np.ndarray, int, float]: kernel = _kernel(points, points, kernel_name, sigma) scaling = np.ones(points.size, dtype=np.float64) residual = float("inf") for iteration in range(1, max_iterations + 1): denominator = kernel @ (weights * scaling) scaling = np.sqrt(scaling / np.maximum(denominator, 1e-300)) residual = float( np.max(np.abs(scaling * (kernel @ (weights * scaling)) - 1.0)) ) if residual < tolerance: return scaling, iteration, residual raise RuntimeError( f"Sinkhorn failed: kernel={kernel_name} n={points.size} residual={residual}" ) def _operator_on_probes( nodes: np.ndarray, weights: np.ndarray, scaling: np.ndarray, probes: np.ndarray, signal_name: str, kernel_name: str, sigma: float, ) -> tuple[np.ndarray, float]: cross_kernel = _kernel(probes, nodes, kernel_name, sigma) probe_denominator = cross_kernel @ (weights * scaling) probe_scaling = 1.0 / np.maximum(probe_denominator, 1e-300) values = probe_scaling * ( cross_kernel @ (weights * scaling * _signal(nodes, signal_name)) ) constant_residual = float( np.max( np.abs( probe_scaling * (cross_kernel @ (weights * scaling)) - np.ones(probes.size) ) ) ) return values, constant_residual def _midpoint_measure(n: int, density_name: str) -> tuple[np.ndarray, np.ndarray]: nodes = (np.arange(n, dtype=np.float64) + 0.5) / n weights = _density(nodes, density_name) / n # Normalization removes only finite quadrature error, preserves positivity, # and does not affect weak convergence. weights /= weights.sum() return nodes, weights def _quantile_measure(n: int, density_name: str) -> tuple[np.ndarray, np.ndarray]: probabilities = (np.arange(n, dtype=np.float64) + 0.5) / n if density_name == "uniform": nodes = probabilities elif density_name == "affine": # Invert F(x) = (x + x^2) / 2. nodes = 0.5 * (-1.0 + np.sqrt(1.0 + 8.0 * probabilities)) elif density_name == "oscillatory": # Invert F(x) = x + 0.45 sin(2 pi x)/(2 pi) by bisection. lower = np.zeros(n, dtype=np.float64) upper = np.ones(n, dtype=np.float64) for _ in range(60): middle = 0.5 * (lower + upper) cdf = middle + 0.45 * np.sin(2.0 * np.pi * middle) / ( 2.0 * np.pi ) lower = np.where(cdf < probabilities, middle, lower) upper = np.where(cdf >= probabilities, middle, upper) nodes = 0.5 * (lower + upper) else: raise ValueError(f"unsupported density: {density_name}") return nodes, np.full(n, 1.0 / n, dtype=np.float64) def _discrete_measure( n: int, density_name: str, discretization: str ) -> tuple[np.ndarray, np.ndarray]: if discretization == "midpoint": return _midpoint_measure(n, density_name) if discretization == "quantile": return _quantile_measure(n, density_name) raise ValueError(f"unsupported discretization: {discretization}") def _gauss_measure(order: int, density_name: str) -> tuple[np.ndarray, np.ndarray]: canonical_nodes, canonical_weights = leggauss(order) nodes = 0.5 * (canonical_nodes + 1.0) weights = 0.5 * canonical_weights * _density(nodes, density_name) weights /= weights.sum() return nodes, weights def _fit_slope(resolutions: list[int], errors: list[float]) -> float: safe = np.maximum(np.asarray(errors, dtype=np.float64), 1e-18) return float(np.polyfit(np.log(np.asarray(resolutions)), np.log(safe), 1)[0]) def _reference_outputs( order: int, density_name: str, kernel_name: str, sigma: float, signals: list[str], probes: np.ndarray, ) -> tuple[dict[str, np.ndarray], dict[str, float], int, float]: nodes, weights = _gauss_measure(order, density_name) scaling, iterations, residual = _sinkhorn_scaling( nodes, weights, kernel_name, sigma ) values: dict[str, np.ndarray] = {} constant_residuals: dict[str, float] = {} for signal_name in signals: values[signal_name], constant_residuals[signal_name] = _operator_on_probes( nodes, weights, scaling, probes, signal_name, kernel_name, sigma, ) return values, constant_residuals, iterations, residual def _git_sha() -> str: result = subprocess.run( ["git", "rev-parse", "HEAD"], cwd=ROOT, check=True, capture_output=True, text=True, ) return result.stdout.strip() def _sha256(path: Path) -> str: digest = hashlib.sha256() with path.open("rb") as handle: for block in iter(lambda: handle.read(1024 * 1024), b""): digest.update(block) return digest.hexdigest() def run_resolution_contract(config_path: Path | None = None) -> dict: start = time.perf_counter() if config_path is None: config_path = ROOT / "repro" / "config.json" config = json.loads(config_path.read_text(encoding="utf-8")) probes = np.linspace(0.0, 1.0, int(config["probe_count"])) resolutions = [int(value) for value in config["resolutions"]] reference_orders = [int(value) for value in config["reference_orders"]] signals = [str(value) for value in config["signals"]] cases: list[dict] = [] for density_name in config["densities"]: for discretization in config["discretizations"]: for kernel_spec in config["kernels"]: kernel_name = str(kernel_spec["name"]) sigma = float(kernel_spec["sigma"]) coarse_reference, coarse_constant, coarse_iterations, coarse_residual = ( _reference_outputs( reference_orders[0], density_name, kernel_name, sigma, signals, probes, ) ) fine_reference, fine_constant, fine_iterations, fine_residual = ( _reference_outputs( reference_orders[1], density_name, kernel_name, sigma, signals, probes, ) ) reference_stability = { signal_name: float( np.max( np.abs( coarse_reference[signal_name] - fine_reference[signal_name] ) ) ) for signal_name in signals } error_curves = {signal_name: [] for signal_name in signals} constant_residuals: list[float] = [] scaling_records: list[dict] = [] for n in resolutions: nodes, weights = _discrete_measure( n, density_name, discretization ) scaling, iterations, residual = _sinkhorn_scaling( nodes, weights, kernel_name, sigma ) scaling_records.append( { "n": n, "iterations": iterations, "node_residual": residual, "min_weight": float(weights.min()), "min_scaling": float(scaling.min()), } ) for signal_name in signals: values, constant_residual = _operator_on_probes( nodes, weights, scaling, probes, signal_name, kernel_name, sigma, ) error_curves[signal_name].append( float( np.max( np.abs( values - fine_reference[signal_name] ) ) ) ) constant_residuals.append(constant_residual) signal_records = [] for signal_name in signals: errors = error_curves[signal_name] signal_records.append( { "signal": signal_name, "uniform_errors": errors, "final_error": errors[-1], "reduction_ratio": errors[-1] / max(errors[0], 1e-300), "loglog_slope": _fit_slope(resolutions, errors), "reference_stability": reference_stability[ signal_name ], } ) cases.append( { "density": density_name, "discretization": discretization, "kernel": kernel_name, "sigma": sigma, "reference": { "orders": reference_orders, "coarse_iterations": coarse_iterations, "fine_iterations": fine_iterations, "coarse_node_residual": coarse_residual, "fine_node_residual": fine_residual, "max_constant_residual": max( list(coarse_constant.values()) + list(fine_constant.values()) ), }, "scalings": scaling_records, "max_probe_constant_residual": max( constant_residuals ), "signals": signal_records, } ) # This deliberately violates resolution increase: the same n=32 result is # repeated at every nominal t. It must not satisfy the convergence gates. negative_cases = [] for case in cases: negative_signals = [] for record in case["signals"]: repeated = [record["uniform_errors"][0]] * len(resolutions) negative_signals.append( { "signal": record["signal"], "uniform_errors": repeated, "final_error": repeated[-1], "reduction_ratio": 1.0, "loglog_slope": _fit_slope(resolutions, repeated), "reference_stability": record["reference_stability"], } ) negative_cases.append( { "density": case["density"], "discretization": case["discretization"], "kernel": case["kernel"], "sigma": case["sigma"], "reference": case["reference"], "max_probe_constant_residual": case[ "max_probe_constant_residual" ], "signals": negative_signals, } ) result = { "schema_version": 1, "claim": "Theorem 4.2 resolution convergence", "variant": config["resolution_variant"], "domain": "[0,1]", "resolutions": resolutions, "probe_count": int(config["probe_count"]), "fixed_command": FIXED_COMMAND, "seed": int(config["seed"]), "cases": cases, "negative_control": { "name": "fixed_resolution_relabelled_as_increasing", "expected_to_pass": False, "cases": negative_cases, }, "runtime_seconds": time.perf_counter() - start, } return result def write_artifacts(result: dict) -> None: ARTIFACT_DIR.mkdir(parents=True, exist_ok=True) raw_json = ARTIFACT_DIR / "raw_results.json" raw_json.write_text(json.dumps(result, indent=2) + "\n", encoding="utf-8") with (ARTIFACT_DIR / "raw_results.csv").open( "w", newline="", encoding="utf-8" ) as handle: writer = csv.DictWriter( handle, fieldnames=[ "variant", "density", "discretization", "kernel", "sigma", "signal", "n", "uniform_error", ], ) writer.writeheader() for case in result["cases"]: for record in case["signals"]: for n, error in zip(result["resolutions"], record["uniform_errors"]): writer.writerow( { "variant": result["variant"], "density": case["density"], "discretization": case["discretization"], "kernel": case["kernel"], "sigma": case["sigma"], "signal": record["signal"], "n": n, "uniform_error": f"{error:.17g}", } ) environment = { "git_sha": _git_sha(), "fixed_command": FIXED_COMMAND, "python": sys.version, "platform": platform.platform(), "processor": platform.processor(), "logical_cpu_count": os.cpu_count(), "numpy": np.__version__, "config_sha256": _sha256(ROOT / "repro" / "config.json"), "lock_sha256": _sha256(ROOT / "uv.lock"), "seed": result["seed"], "runtime_seconds": result["runtime_seconds"], } (ARTIFACT_DIR / "environment.json").write_text( json.dumps(environment, indent=2) + "\n", encoding="utf-8" ) def print_summary(result: dict) -> None: print("C2_RESOLUTION_VARIANT=" + str(result["variant"])) print("C2_FIXED_COMMAND=" + FIXED_COMMAND) print("C2_RESOLUTIONS=" + json.dumps(result["resolutions"])) for case in result["cases"]: for record in case["signals"]: print( "C2_RESULT " f"density={case['density']} discretization={case['discretization']} " f"kernel={case['kernel']} " f"sigma={case['sigma']:.6g} signal={record['signal']} " f"errors={json.dumps(record['uniform_errors'])} " f"ratio={record['reduction_ratio']:.8g} " f"slope={record['loglog_slope']:.8g} " f"ref_stability={record['reference_stability']:.8g}" ) print(f"C2_RUNTIME_SECONDS={result['runtime_seconds']:.6f}")