import json import random import sys from pathlib import Path import numpy as np import torch from torch import nn sys.path.insert(0, '/home/maxwelhelp/all/math2nn') from bench import train_model, evaluate, sweep_baseline, make_report, get_dataset as bench_get_dataset, all_track_names from tetra_elasticity_complex import D0, D1, D2 SEEDS = tuple(range(8)) GRID = [{'lr': 1e-3}, {'lr': 3e-3}, {'lr': 1e-2}] EPOCHS = 35 BATCH = 128 class SharedMLP(nn.Module): """Same learned architecture on both sides; only the fixed input map differs.""" def __init__(self, transform=None): super().__init__() self.transform = transform self.net = nn.Sequential(nn.Linear(D0.shape[0], 64), nn.ReLU(), nn.Linear(64, 64), nn.ReLU(), nn.Linear(64, 1)) def forward(self, x): if self.transform is not None: x = self.transform.to(x.device).to(x.dtype) @ x.unsqueeze(-1) x = x.squeeze(-1) return self.net(x) def tensors(ds): return {**ds, **{k: torch.as_tensor(ds[k], dtype=torch.float32) for k in ('xtr', 'ytr', 'xte', 'yte')}} def seed_all(seed): random.seed(seed) np.random.seed(seed) torch.manual_seed(seed) if torch.cuda.is_available(): torch.cuda.manual_seed_all(seed) def train_one(seed, cfg, idea=False, capture=False): seed_all(seed) ds = tensors(bench_get_dataset('tetra_elasticity_complex', seed, 400, 160)) # P = D1^T D1 is an edge-space map. It removes exact gradients because D1 D0=0. P = (D1.T @ D1).astype(np.float32) if idea else None model = SharedMLP(torch.tensor(P) if P is not None else None) net, metric, _ = train_model(model, ds, epochs=EPOCHS, lr=cfg['lr'], batch=BATCH, weight_decay=0.0, log=lambda *_: None) if net is None: return float('nan') if capture: with torch.no_grad(): u = np.random.default_rng(seed + 9000).normal(size=(160, 5)).astype(np.float32) dev = next(net.parameters()).device compatible = torch.as_tensor(u @ D0.T, dtype=torch.float32, device=dev) xt = ds['xte'].to(dev) observed = torch.sqrt(torch.mean((xt @ torch.tensor(D1.T, device=dev)) ** 2, dim=1)) pred_compat = net(compatible).squeeze(1).cpu().numpy() pred_test = net(xt).squeeze(1).cpu().numpy() return float(metric), {'compatible_pred_abs_mean': float(np.mean(np.abs(pred_compat))), 'test_pred_observed_corr': float(np.corrcoef(pred_test, observed.cpu().numpy())[0, 1]), 'test_pred_mean': float(np.mean(pred_test)), 'test_observed_mean': float(torch.mean(observed))} return float(metric) def make_train_fn(cfg, idea): return lambda seed: train_one(seed, cfg, idea=idea) def main(): assert 'tetra_elasticity_complex' in all_track_names(), all_track_names() # Cheap algebraic sanity checks required before training results are considered. r10 = float(np.linalg.norm(D1 @ D0) / (np.linalg.norm(D0) + 1e-12)) r21 = float(np.linalg.norm(D2 @ D1) / (np.linalg.norm(D1) + 1e-12)) rng = np.random.default_rng(123) leak_exact, leak_random = [], [] A = rng.normal(size=(D1.shape[0], D0.shape[0])).astype(np.float32) for _ in range(200): u = rng.normal(size=5).astype(np.float32) e = D0 @ u leak_exact.append(np.linalg.norm(D1 @ e) / (np.linalg.norm(e) + 1e-12)) leak_random.append(np.linalg.norm(A @ e) / (np.linalg.norm(e) + 1e-12)) algebra = {'relative_D1D0': r10, 'relative_D2D1': r21, 'compatible_leak_exact_mean': float(np.mean(leak_exact)), 'compatible_leak_unconstrained_mean': float(np.mean(leak_random))} print('algebra', json.dumps(algebra)) base = sweep_baseline(lambda cfg: make_train_fn(cfg, False), GRID, seeds=SEEDS[:4]) # sweep_baseline re-evaluates the selected baseline on all eight paired seeds. idea_runs = [] for cfg in GRID: res = evaluate(make_train_fn(cfg, True), seeds=SEEDS) idea_runs.append({'cfg': cfg, 'result': res}) best = min(idea_runs, key=lambda z: z['result']['mean']) idea = best['result'] sigvals = [train_one(s, best['cfg'], idea=True, capture=True)[1] for s in SEEDS] signature = { 'compatible_pred_abs_mean': float(np.mean([x['compatible_pred_abs_mean'] for x in sigvals])), 'observed_compatible_leakage': float(np.mean(leak_exact)), 'unconstrained_observed_leakage': float(np.mean(leak_random)), 'test_pred_observed_corr': float(np.mean([x['test_pred_observed_corr'] for x in sigvals])), 'test_pred_mean': float(np.mean([x['test_pred_mean'] for x in sigvals])), 'test_observed_mean': float(np.mean([x['test_observed_mean'] for x in sigvals])), 'confirmed': bool(r10 < 1e-6 and r21 < 1e-6 and np.mean(leak_exact) < 1e-6 and np.mean([x['compatible_pred_abs_mean'] for x in sigvals]) < 0.15) } report = make_report('tetra_elasticity_complex', 'mlp_tiny', base, idea, {'custom_track': {'name': 'tetra_elasticity_complex', 'file': 'tetra_elasticity_complex.py', 'domain': 'pde'}, 'algebra_sanity': algebra, 'idea_sweep': idea_runs, 'mechanism_signature': signature, 'protocol': {'epochs': EPOCHS, 'batch': BATCH, 'grid': GRID, 'paired_seeds': list(SEEDS), 'structural_match': 'PDE simplicial complex'}}) Path('bench_report.json').write_text(json.dumps(report, indent=2)) print(json.dumps(report, indent=2)) if __name__ == '__main__': main()