Teleporting Simplicial Diffusion Layer / verify_and_report.py
Failed on benchmark
1import json
2import numpy as np
3from teleport_simplicial import (
4 cyclic_triangle_incidence, local_operator, teleport, nonprincipal_radius,
5 mfpt_to_target, run_experiment,
6)
7
8
9def main():
10 out = run_experiment(seed=7)
11 n = out['n']
12 A = cyclic_triangle_incidence(n)
13 P0 = local_operator(A, self_loop=0.1)
14 alphas = np.array([x[0] for x in out['spectral']])
15
16 # Structural checks: incidence has three faces per triangle and P is stochastic.
17 assert np.all(A.sum(axis=0) == 3)
18 assert np.allclose(P0.sum(axis=1), 1.0)
19 assert np.min(P0) >= 0
20
21 # Prediction 1: uniform teleportation gives rho(P_alpha)=rho(P0)*(1-alpha).
22 rho0 = out['rho0']
23 observed = np.array([x[1] for x in out['spectral']])
24 predicted = rho0 * (1 - alphas)
25 spectral_max_error = float(np.max(np.abs(observed - predicted)))
26 assert spectral_max_error < 1e-10
27
28 # Prediction 2: global teleportation monotonically reduces target MFPT.
29 mfpt = np.array([x[1] for x in out['mfpt']])
30 assert np.all(np.diff(mfpt) < 0)
31
32 # A direct mixing prediction: on any mean-zero eigenmode, m-step norm scales
33 # as [rho(P0)*(1-alpha)]^m. Numerically use the slowest eigenvector.
34 vals, vecs = np.linalg.eig(P0)
35 k = np.argsort(np.abs(vals - 1))[-1] # not used; select largest nonprincipal below
36 order = np.argsort(-np.abs(vals))
37 k = next(i for i in order if abs(vals[i] - 1) > 1e-8)
38 v = np.real(vecs[:, k]); v -= v.mean(); v /= np.linalg.norm(v)
39 m = 12
40 mixing_rows = []
41 for a in alphas:
42 P = teleport(P0, float(a))
43 actual = np.linalg.norm(np.linalg.matrix_power(P, m) @ v)
44 pred = (rho0 * (1-a)) ** m
45 mixing_rows.append([float(a), float(actual), float(pred)])
46 mixing_max_error = float(max(abs(x[1]-x[2]) for x in mixing_rows))
47 assert mixing_max_error < 1e-8
48
49 report = {
50 'spectral_prediction': {
51 'prediction': 'rho_alpha / rho_0 = 1-alpha',
52 'max_abs_error': spectral_max_error,
53 'rows_alpha_observed_predicted': [
54 [float(a), float(o), float(p)] for a, o, p in zip(alphas, observed, predicted)
55 ],
56 },
57 'mfpt_prediction': {
58 'prediction': 'mean MFPT to target decreases with alpha',
59 'rows_alpha_mean_mfpt': [[float(a), float(t)] for a, t in zip(alphas, mfpt)],
60 },
61 'mixing_prediction': {
62 'prediction': 'm-step slow-mode norm = [rho_0(1-alpha)]^m, m=12',
63 'max_abs_error': mixing_max_error,
64 'rows_alpha_observed_predicted': mixing_rows,
65 },
66 'classification': {
67 'prediction': 'teleportation can improve delayed global classification but oversmooths features',
68 'rows_alpha_accuracy_feature_std': out['classification'],
69 },
70 }
71 with open('results.json', 'w') as f:
72 json.dump(report, f, indent=2)
73 print(json.dumps(report, indent=2))
74
75
76if __name__ == '__main__':
77 main()