diff options
| author | YurenHao0426 <Blackhao0426@gmail.com> | 2026-08-01 19:32:58 -0500 |
|---|---|---|
| committer | YurenHao0426 <Blackhao0426@gmail.com> | 2026-08-01 19:32:58 -0500 |
| commit | ef104fe4f07713bf11f266d2954b7446f176f8ae (patch) | |
| tree | 0ad9a26ca870bac83d3f509ec46be5b2f4048f9a /logs | |
| parent | de827a42e10ede662f4bd2893c4f8b6d54be45dc (diff) | |
Record the matching battery: fifteen solvers, one amplifier
Adds MATCHING_RESULTS.md. Entropic GW annealed and PATH both reach 0.961
on the reference field, above the 0.958 the project's own pipeline
reached after months, and neither had been run. GW reaches 0.881 on the
rank-8 field where GRAMPA reaches 0.076 -- which retires the morning's
rank-ladder conclusion, since that ladder was run entirely with GRAMPA
and GRAMPA degrades on clustered eigenvalues.
The hard instance yields to amplification rather than a better solver:
descent multiplies a partial answer by about four, so the job is to feed
it a start that is 10-20% correct rather than to replace it.
Co-Authored-By: Claude <noreply@anthropic.com>
Diffstat (limited to 'logs')
| -rw-r--r-- | logs/battery2.log | 6 | ||||
| -rw-r--r-- | logs/control.log | 4 | ||||
| -rw-r--r-- | logs/control_probe.py | 93 | ||||
| -rw-r--r-- | logs/fgw_alpha_control.log | 4 | ||||
| -rw-r--r-- | logs/fgw_alpha_lean.log | 71 | ||||
| -rw-r--r-- | logs/fgw_alpha_mech.log | 12 | ||||
| -rw-r--r-- | logs/lean.log | 71 | ||||
| -rw-r--r-- | logs/lean_probe.py | 84 | ||||
| -rw-r--r-- | logs/mech.log | 11 | ||||
| -rw-r--r-- | logs/mech.py | 51 | ||||
| -rw-r--r-- | logs/verify.py | 59 |
11 files changed, 466 insertions, 0 deletions
diff --git a/logs/battery2.log b/logs/battery2.log index bfde59c..a0b3a2a 100644 --- a/logs/battery2.log +++ b/logs/battery2.log @@ -22,3 +22,9 @@ GW kl-loss raw=0.2161 refined=0.2513 (0.1s) /home/yurenh2/.local/lib/python3.13/site-packages/ot/bregman/_sinkhorn.py:642: UserWarning: Warning: numerical errors at iteration 24 warnings.warn("Warning: numerical errors at iteration %d" % ii) + entropic GW deep anneal raw=0.0078 refined=0.0130 (554.8s) + semirelaxed GW raw=0.0156 refined=0.0443 (38.9s) + +=== synth-full-BOUND0.99 (N=256, chance=0.0039) + GW x12 restarts raw=0.3698 refined=0.3971 (12.3s) + GW kl-loss raw=0.0846 refined=0.0885 (13.9s) diff --git a/logs/control.log b/logs/control.log new file mode 100644 index 0000000..de41a42 --- /dev/null +++ b/logs/control.log @@ -0,0 +1,4 @@ +{"trial": 0, "cost": "tlb", "mode": "cold", "E_truth": 0.339629709924146, "blind_refined": 0.0234375, "blind_alpha": 1.0, "blind_E": 0.6228801020056084, "oracle_refined": 0.08203125, "curve": [0.0781, 0.0234, 0.0117, 0.0273, 0.0742, 0.0352, 0.0664, 0.0352, 0.082, 0.0, 0.0547, 0.0234]} +{"trial": 0, "cost": "tlb", "mode": "warm", "E_truth": 0.339629709924146, "blind_refined": 0.84765625, "blind_alpha": 0.2, "blind_E": 0.339629709924146, "oracle_refined": 0.84765625, "curve": [0.0781, 0.8281, 0.8477, 0.8398, 0.8398, 0.8398, 0.8398, 0.8398, 0.8398, 0.8398, 0.8398, 0.8398]} +{"trial": 0, "cost": "tlbperm", "mode": "cold", "E_truth": 0.339629709924146, "blind_refined": 0.02734375, "blind_alpha": 0.95, "blind_E": 0.6074469738905559, "oracle_refined": 0.078125, "curve": [0.0117, 0.0117, 0.043, 0.0781, 0.0078, 0.0352, 0.0156, 0.0156, 0.0039, 0.0078, 0.0273, 0.0234]} +{"trial": 0, "cost": "tlbperm", "mode": "warm", "E_truth": 0.339629709924146, "blind_refined": 0.03125, "blind_alpha": 1.0, "blind_E": 0.7038378812415739, "oracle_refined": 0.04296875, "curve": [0.0117, 0.043, 0.0234, 0.0234, 0.043, 0.0391, 0.0391, 0.0391, 0.0312, 0.0312, 0.0312, 0.0312]} diff --git a/logs/control_probe.py b/logs/control_probe.py new file mode 100644 index 0000000..170d731 --- /dev/null +++ b/logs/control_probe.py @@ -0,0 +1,93 @@ +"""Control: is the FGW warm-homotopy win driven by TLB *information*, or by any +linear term at all (generic symmetry-breaking)? Three linear costs: + + tlb -- the proposed distance-profile cost + tlbperm -- the same matrix with its columns randomly permuted: identical + value distribution, correspondence information destroyed + rand -- iid uniform noise cost + +Plus 3 trials, cold and warm sweeps, blind selection by E(P). +""" +from __future__ import annotations +import json, sys, time +sys.path.insert(0, "/home/yurenh2/emm") +import numpy as np, ot, torch +from scipy.optimize import linear_sum_assignment +from worldalign.synth_fast_gate import ClosedFormEnergy, fast_pair_descent +from worldalign.synth_triangle_gate import standardized + +DEV = torch.device("cuda:1") +ALPHAS = [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 0.95, 1.0] + + +def standardise(m): + mask = ~np.eye(len(m), dtype=bool); v = m[mask] + o = (m - v.mean()) / v.std(); np.fill_diagonal(o, 0.0); return o + + +def tlb(V, S): + n = len(V); a = np.sort(V, 1); b = np.sort(S, 1) + return (a * a).sum(1)[:, None] / n + (b * b).sum(1)[None, :] / n - 2 * (a @ b.T) / n + + +def main(): + path = "/home/yurenh2/emm/artifacts/synth_v1/omit_size.pt" + st = torch.load(path, map_location="cpu", weights_only=False) + V = standardise(st["visual_field"].double().numpy()) + T = standardise(st["text_field"].double().numpy()) + n = len(V); w = ot.unif(n) + rows = [] + for trial in range(3): + rng = np.random.default_rng(trial); hid = rng.permutation(n) + S = T[np.ix_(hid, hid)] + Vg = standardized(torch.from_numpy(V).to(DEV)).double() + Sg = standardized(torch.from_numpy(S).to(DEV)).double() + en = ClosedFormEnergy(Sg, Vg, 1.0, 0.0, 64) + et = float(en.energy(torch.from_numpy( + np.ascontiguousarray(np.argsort(hid))).to(DEV)[None])[0]) + + def acc(c): return float((hid[c] == np.arange(n)).mean()) + + def refine(c): + f = fast_pair_descent(Sg, Vg, + torch.from_numpy(np.ascontiguousarray(c)).to(DEV), + 600).cpu().numpy() + e = float(en.energy(torch.from_numpy(np.ascontiguousarray(f)).to(DEV)[None])[0]) + return e, acc(f) + + base = tlb(V, S) + shuf = np.random.default_rng(100 + trial).permutation(n) + variants = { + "tlb": base / base.max(), + "tlbperm": base[:, shuf] / base.max(), + "rand": np.random.default_rng(200 + trial).random((n, n)), + } + for vname, M in variants.items(): + for mode in ("cold", "warm"): + G = np.outer(w, w); recs = [] + for a in ALPHAS: + g0 = None if mode == "cold" else G + G2 = ot.gromov.fused_gromov_wasserstein( + M, V, S, w, w, "square_loss", alpha=a, G0=g0, + max_iter=200, tol_rel=1e-9) + if mode == "warm": + G = G2 + _, cols = linear_sum_assignment(-G2) + e, ar = refine(cols) + recs.append({"alpha": a, "raw": acc(cols), "refined": ar, "E": e}) + best = min(recs, key=lambda x: x["E"]) + row = {"trial": trial, "cost": vname, "mode": mode, + "E_truth": et, "blind_refined": best["refined"], + "blind_alpha": best["alpha"], "blind_E": best["E"], + "oracle_refined": max(x["refined"] for x in recs), + "curve": [round(x["refined"], 4) for x in recs]} + rows.append(row) + print(json.dumps(row), flush=True) + scratch = ("/tmp/claude-1273071/-home-yurenh2-emm/" + "bb97201d-d9b5-46e6-82fc-981d37e7ab98/scratchpad/") + json.dump(rows, open(scratch + "control.json", "w")) + print(json.dumps({"done": True})) + + +if __name__ == "__main__": + main() diff --git a/logs/fgw_alpha_control.log b/logs/fgw_alpha_control.log new file mode 100644 index 0000000..de41a42 --- /dev/null +++ b/logs/fgw_alpha_control.log @@ -0,0 +1,4 @@ +{"trial": 0, "cost": "tlb", "mode": "cold", "E_truth": 0.339629709924146, "blind_refined": 0.0234375, "blind_alpha": 1.0, "blind_E": 0.6228801020056084, "oracle_refined": 0.08203125, "curve": [0.0781, 0.0234, 0.0117, 0.0273, 0.0742, 0.0352, 0.0664, 0.0352, 0.082, 0.0, 0.0547, 0.0234]} +{"trial": 0, "cost": "tlb", "mode": "warm", "E_truth": 0.339629709924146, "blind_refined": 0.84765625, "blind_alpha": 0.2, "blind_E": 0.339629709924146, "oracle_refined": 0.84765625, "curve": [0.0781, 0.8281, 0.8477, 0.8398, 0.8398, 0.8398, 0.8398, 0.8398, 0.8398, 0.8398, 0.8398, 0.8398]} +{"trial": 0, "cost": "tlbperm", "mode": "cold", "E_truth": 0.339629709924146, "blind_refined": 0.02734375, "blind_alpha": 0.95, "blind_E": 0.6074469738905559, "oracle_refined": 0.078125, "curve": [0.0117, 0.0117, 0.043, 0.0781, 0.0078, 0.0352, 0.0156, 0.0156, 0.0039, 0.0078, 0.0273, 0.0234]} +{"trial": 0, "cost": "tlbperm", "mode": "warm", "E_truth": 0.339629709924146, "blind_refined": 0.03125, "blind_alpha": 1.0, "blind_E": 0.7038378812415739, "oracle_refined": 0.04296875, "curve": [0.0117, 0.043, 0.0234, 0.0234, 0.043, 0.0391, 0.0391, 0.0391, 0.0312, 0.0312, 0.0312, 0.0312]} diff --git a/logs/fgw_alpha_lean.log b/logs/fgw_alpha_lean.log new file mode 100644 index 0000000..0787289 --- /dev/null +++ b/logs/fgw_alpha_lean.log @@ -0,0 +1,71 @@ +# omit-size trial0 E_truth=0.3396 + cold a=0.0 raw=0.0625 ref=0.0781 E=0.6734 (8.4s) + cold a=0.2 raw=0.0117 ref=0.0117 E=0.6397 (9.5s) + cold a=0.4 raw=0.0703 ref=0.0742 E=0.6363 (2.8s) + cold a=0.6 raw=0.0586 ref=0.0664 E=0.6366 (1.2s) + cold a=0.75 raw=0.0508 ref=0.0430 E=0.6678 (5.7s) + cold a=0.85 raw=0.0312 ref=0.0234 E=0.6678 (1.6s) + cold a=0.88 raw=0.0586 ref=0.0508 E=0.6401 (2.4s) + cold a=0.9 raw=0.0000 ref=0.0000 E=0.6654 (2.2s) + cold a=0.92 raw=0.0352 ref=0.0312 E=0.7672 (0.5s) + cold a=0.94 raw=0.1680 ref=0.1875 E=0.6087 (0.5s) + cold a=0.95 raw=0.0625 ref=0.0547 E=0.6642 (2.1s) + cold a=0.96 raw=0.0664 ref=0.0664 E=0.6551 (0.3s) + cold a=0.97 raw=0.8203 ref=0.8203 E=0.3396 (0.4s) + cold a=0.98 raw=0.0039 ref=0.0039 E=0.6459 (1.0s) + cold a=0.99 raw=0.0156 ref=0.0156 E=0.6409 (1.0s) + cold a=1.0 raw=0.0195 ref=0.0234 E=0.6229 (0.7s) + == cold: blind-by-E refined=0.8203 (alpha=0.97), oracle-best=0.8203 + warm a=0.0 raw=0.0625 ref=0.0781 E=0.6734 (0.6s) + warm a=0.2 raw=0.8242 ref=0.8320 E=0.3396 (1.2s) + warm a=0.4 raw=0.8281 ref=0.8320 E=0.3396 (0.4s) + warm a=0.6 raw=0.8320 ref=0.8320 E=0.3396 (0.3s) + warm a=0.75 raw=0.8320 ref=0.8320 E=0.3396 (0.2s) + warm a=0.85 raw=0.8320 ref=0.8320 E=0.3396 FROZEN (0.1s) + warm a=0.88 raw=0.8320 ref=0.8320 E=0.3396 FROZEN (0.2s) + warm a=0.9 raw=0.8320 ref=0.8320 E=0.3396 FROZEN (0.2s) + warm a=0.92 raw=0.8320 ref=0.8320 E=0.3396 FROZEN (0.1s) + warm a=0.94 raw=0.8320 ref=0.8320 E=0.3396 FROZEN (0.1s) + warm a=0.95 raw=0.8320 ref=0.8320 E=0.3396 FROZEN (0.3s) + warm a=0.96 raw=0.8320 ref=0.8320 E=0.3396 FROZEN (0.2s) + warm a=0.97 raw=0.8320 ref=0.8320 E=0.3396 FROZEN (0.1s) + warm a=0.98 raw=0.8320 ref=0.8320 E=0.3396 FROZEN (0.3s) + warm a=0.99 raw=0.8320 ref=0.8320 E=0.3396 FROZEN (0.1s) + warm a=1.0 raw=0.8320 ref=0.8320 E=0.3396 FROZEN (0.0s) + == warm: blind-by-E refined=0.8320 (alpha=0.2), oracle-best=0.8320 +# synth-full trial0 E_truth=0.1430 + cold a=0.0 raw=0.2578 ref=0.8633 E=0.2199 (2.1s) + cold a=0.2 raw=0.9531 ref=0.9609 E=0.1425 (2.6s) + cold a=0.4 raw=0.9531 ref=0.9688 E=0.1425 (1.7s) + cold a=0.6 raw=0.9570 ref=0.9766 E=0.1425 (2.2s) + cold a=0.75 raw=0.9375 ref=0.9609 E=0.1425 (3.0s) + cold a=0.85 raw=0.9531 ref=0.9609 E=0.1425 (4.3s) + cold a=0.88 raw=0.9453 ref=0.9609 E=0.1425 (3.8s) + cold a=0.9 raw=0.9766 ref=0.9844 E=0.1425 (3.5s) + cold a=0.92 raw=0.9453 ref=0.9531 E=0.1425 (0.9s) + cold a=0.94 raw=0.9531 ref=0.9766 E=0.1425 (2.0s) + cold a=0.95 raw=0.9453 ref=0.9531 E=0.1425 (1.1s) + cold a=0.96 raw=0.9453 ref=0.9531 E=0.1425 (0.8s) + cold a=0.97 raw=0.9375 ref=0.9531 E=0.1425 (6.2s) + cold a=0.98 raw=0.3789 ref=0.3789 E=0.5018 (7.1s) + cold a=0.99 raw=0.4219 ref=0.4141 E=0.4734 (10.8s) + cold a=1.0 raw=0.3633 ref=0.3906 E=0.5082 (12.6s) + == cold: blind-by-E refined=0.9609 (alpha=0.2), oracle-best=0.9844 + warm a=0.0 raw=0.2578 ref=0.8633 E=0.2199 (4.5s) + warm a=0.2 raw=0.9375 ref=0.9453 E=0.1425 (1.9s) + warm a=0.4 raw=0.9375 ref=0.9453 E=0.1425 FROZEN (2.5s) + warm a=0.6 raw=0.9375 ref=0.9453 E=0.1425 FROZEN (0.3s) + warm a=0.75 raw=0.9375 ref=0.9453 E=0.1425 FROZEN (1.4s) + warm a=0.85 raw=0.9375 ref=0.9453 E=0.1425 FROZEN (0.9s) + warm a=0.88 raw=0.9375 ref=0.9453 E=0.1425 FROZEN (0.6s) + warm a=0.9 raw=0.9375 ref=0.9453 E=0.1425 FROZEN (0.8s) + warm a=0.92 raw=0.9375 ref=0.9453 E=0.1425 FROZEN (1.2s) + warm a=0.94 raw=0.9375 ref=0.9453 E=0.1425 FROZEN (0.8s) + warm a=0.95 raw=0.9375 ref=0.9453 E=0.1425 FROZEN (0.4s) + warm a=0.96 raw=0.9375 ref=0.9453 E=0.1425 FROZEN (0.6s) + warm a=0.97 raw=0.9375 ref=0.9453 E=0.1425 FROZEN (0.7s) + warm a=0.98 raw=0.9375 ref=0.9453 E=0.1425 FROZEN (0.4s) + warm a=0.99 raw=0.9375 ref=0.9453 E=0.1425 FROZEN (0.1s) + warm a=1.0 raw=0.9375 ref=0.9453 E=0.1425 FROZEN (0.2s) + == warm: blind-by-E refined=0.9453 (alpha=0.2), oracle-best=0.9453 +{"done": true} diff --git a/logs/fgw_alpha_mech.log b/logs/fgw_alpha_mech.log new file mode 100644 index 0000000..0c3f85f --- /dev/null +++ b/logs/fgw_alpha_mech.log @@ -0,0 +1,12 @@ +--- trial 0 E_truth=0.339630 + tlb-vertex start=0.0586 | 1 power step ->0.0312 (E=0.7114) | 5 steps ->0.1719 (E=0.6409) | warm FGW ->0.8555 (E=0.3396) + random-vertex start=0.0000 | 1 power step ->0.0312 (E=0.7279) | 5 steps ->0.0781 (E=0.6819) | warm FGW ->0.8125 (E=0.3396) + grampa-vertex start=0.0156 | 1 power step ->0.0938 (E=0.7821) | 5 steps ->0.0469 (E=0.7049) | warm FGW ->0.8203 (E=0.3396) +--- trial 1 E_truth=0.339630 + tlb-vertex start=0.0508 | 1 power step ->0.0352 (E=0.7114) | 5 steps ->0.1836 (E=0.6409) | warm FGW ->0.8164 (E=0.3396) + random-vertex start=0.0039 | 1 power step ->0.0156 (E=0.7051) | 5 steps ->0.0195 (E=0.6692) | warm FGW ->0.0195 (E=0.6554) + grampa-vertex start=0.0195 | 1 power step ->0.0742 (E=0.7821) | 5 steps ->0.0547 (E=0.7049) | warm FGW ->0.8164 (E=0.3396) +--- trial 2 E_truth=0.339630 + tlb-vertex start=0.0430 | 1 power step ->0.0312 (E=0.7114) | 5 steps ->0.1797 (E=0.6409) | warm FGW ->0.8359 (E=0.3396) + random-vertex start=0.0000 | 1 power step ->0.0195 (E=0.7149) | 5 steps ->0.0117 (E=0.6700) | warm FGW ->0.0391 (E=0.6387) + grampa-vertex start=0.0156 | 1 power step ->0.0820 (E=0.7821) | 5 steps ->0.0508 (E=0.7049) | warm FGW ->0.8203 (E=0.3396) diff --git a/logs/lean.log b/logs/lean.log new file mode 100644 index 0000000..0787289 --- /dev/null +++ b/logs/lean.log @@ -0,0 +1,71 @@ +# omit-size trial0 E_truth=0.3396 + cold a=0.0 raw=0.0625 ref=0.0781 E=0.6734 (8.4s) + cold a=0.2 raw=0.0117 ref=0.0117 E=0.6397 (9.5s) + cold a=0.4 raw=0.0703 ref=0.0742 E=0.6363 (2.8s) + cold a=0.6 raw=0.0586 ref=0.0664 E=0.6366 (1.2s) + cold a=0.75 raw=0.0508 ref=0.0430 E=0.6678 (5.7s) + cold a=0.85 raw=0.0312 ref=0.0234 E=0.6678 (1.6s) + cold a=0.88 raw=0.0586 ref=0.0508 E=0.6401 (2.4s) + cold a=0.9 raw=0.0000 ref=0.0000 E=0.6654 (2.2s) + cold a=0.92 raw=0.0352 ref=0.0312 E=0.7672 (0.5s) + cold a=0.94 raw=0.1680 ref=0.1875 E=0.6087 (0.5s) + cold a=0.95 raw=0.0625 ref=0.0547 E=0.6642 (2.1s) + cold a=0.96 raw=0.0664 ref=0.0664 E=0.6551 (0.3s) + cold a=0.97 raw=0.8203 ref=0.8203 E=0.3396 (0.4s) + cold a=0.98 raw=0.0039 ref=0.0039 E=0.6459 (1.0s) + cold a=0.99 raw=0.0156 ref=0.0156 E=0.6409 (1.0s) + cold a=1.0 raw=0.0195 ref=0.0234 E=0.6229 (0.7s) + == cold: blind-by-E refined=0.8203 (alpha=0.97), oracle-best=0.8203 + warm a=0.0 raw=0.0625 ref=0.0781 E=0.6734 (0.6s) + warm a=0.2 raw=0.8242 ref=0.8320 E=0.3396 (1.2s) + warm a=0.4 raw=0.8281 ref=0.8320 E=0.3396 (0.4s) + warm a=0.6 raw=0.8320 ref=0.8320 E=0.3396 (0.3s) + warm a=0.75 raw=0.8320 ref=0.8320 E=0.3396 (0.2s) + warm a=0.85 raw=0.8320 ref=0.8320 E=0.3396 FROZEN (0.1s) + warm a=0.88 raw=0.8320 ref=0.8320 E=0.3396 FROZEN (0.2s) + warm a=0.9 raw=0.8320 ref=0.8320 E=0.3396 FROZEN (0.2s) + warm a=0.92 raw=0.8320 ref=0.8320 E=0.3396 FROZEN (0.1s) + warm a=0.94 raw=0.8320 ref=0.8320 E=0.3396 FROZEN (0.1s) + warm a=0.95 raw=0.8320 ref=0.8320 E=0.3396 FROZEN (0.3s) + warm a=0.96 raw=0.8320 ref=0.8320 E=0.3396 FROZEN (0.2s) + warm a=0.97 raw=0.8320 ref=0.8320 E=0.3396 FROZEN (0.1s) + warm a=0.98 raw=0.8320 ref=0.8320 E=0.3396 FROZEN (0.3s) + warm a=0.99 raw=0.8320 ref=0.8320 E=0.3396 FROZEN (0.1s) + warm a=1.0 raw=0.8320 ref=0.8320 E=0.3396 FROZEN (0.0s) + == warm: blind-by-E refined=0.8320 (alpha=0.2), oracle-best=0.8320 +# synth-full trial0 E_truth=0.1430 + cold a=0.0 raw=0.2578 ref=0.8633 E=0.2199 (2.1s) + cold a=0.2 raw=0.9531 ref=0.9609 E=0.1425 (2.6s) + cold a=0.4 raw=0.9531 ref=0.9688 E=0.1425 (1.7s) + cold a=0.6 raw=0.9570 ref=0.9766 E=0.1425 (2.2s) + cold a=0.75 raw=0.9375 ref=0.9609 E=0.1425 (3.0s) + cold a=0.85 raw=0.9531 ref=0.9609 E=0.1425 (4.3s) + cold a=0.88 raw=0.9453 ref=0.9609 E=0.1425 (3.8s) + cold a=0.9 raw=0.9766 ref=0.9844 E=0.1425 (3.5s) + cold a=0.92 raw=0.9453 ref=0.9531 E=0.1425 (0.9s) + cold a=0.94 raw=0.9531 ref=0.9766 E=0.1425 (2.0s) + cold a=0.95 raw=0.9453 ref=0.9531 E=0.1425 (1.1s) + cold a=0.96 raw=0.9453 ref=0.9531 E=0.1425 (0.8s) + cold a=0.97 raw=0.9375 ref=0.9531 E=0.1425 (6.2s) + cold a=0.98 raw=0.3789 ref=0.3789 E=0.5018 (7.1s) + cold a=0.99 raw=0.4219 ref=0.4141 E=0.4734 (10.8s) + cold a=1.0 raw=0.3633 ref=0.3906 E=0.5082 (12.6s) + == cold: blind-by-E refined=0.9609 (alpha=0.2), oracle-best=0.9844 + warm a=0.0 raw=0.2578 ref=0.8633 E=0.2199 (4.5s) + warm a=0.2 raw=0.9375 ref=0.9453 E=0.1425 (1.9s) + warm a=0.4 raw=0.9375 ref=0.9453 E=0.1425 FROZEN (2.5s) + warm a=0.6 raw=0.9375 ref=0.9453 E=0.1425 FROZEN (0.3s) + warm a=0.75 raw=0.9375 ref=0.9453 E=0.1425 FROZEN (1.4s) + warm a=0.85 raw=0.9375 ref=0.9453 E=0.1425 FROZEN (0.9s) + warm a=0.88 raw=0.9375 ref=0.9453 E=0.1425 FROZEN (0.6s) + warm a=0.9 raw=0.9375 ref=0.9453 E=0.1425 FROZEN (0.8s) + warm a=0.92 raw=0.9375 ref=0.9453 E=0.1425 FROZEN (1.2s) + warm a=0.94 raw=0.9375 ref=0.9453 E=0.1425 FROZEN (0.8s) + warm a=0.95 raw=0.9375 ref=0.9453 E=0.1425 FROZEN (0.4s) + warm a=0.96 raw=0.9375 ref=0.9453 E=0.1425 FROZEN (0.6s) + warm a=0.97 raw=0.9375 ref=0.9453 E=0.1425 FROZEN (0.7s) + warm a=0.98 raw=0.9375 ref=0.9453 E=0.1425 FROZEN (0.4s) + warm a=0.99 raw=0.9375 ref=0.9453 E=0.1425 FROZEN (0.1s) + warm a=1.0 raw=0.9375 ref=0.9453 E=0.1425 FROZEN (0.2s) + == warm: blind-by-E refined=0.9453 (alpha=0.2), oracle-best=0.9453 +{"done": true} diff --git a/logs/lean_probe.py b/logs/lean_probe.py new file mode 100644 index 0000000..f3b394c --- /dev/null +++ b/logs/lean_probe.py @@ -0,0 +1,84 @@ +"""Lean version: 15-alpha grid, TLB cost, cold vs warm, omit-size then synth-full.""" +from __future__ import annotations +import json, sys, time +sys.path.insert(0, "/home/yurenh2/emm") +import numpy as np, ot, torch +from scipy.optimize import linear_sum_assignment +from worldalign.synth_fast_gate import ClosedFormEnergy, fast_pair_descent +from worldalign.synth_triangle_gate import standardized + +DEV = torch.device("cuda:1") +ALPHAS = [0.0, 0.2, 0.4, 0.6, 0.75, 0.85, 0.88, 0.90, 0.92, 0.94, 0.95, + 0.96, 0.97, 0.98, 0.99, 1.0] + + +def standardise(m): + mask = ~np.eye(len(m), dtype=bool); v = m[mask] + o = (m - v.mean()) / v.std(); np.fill_diagonal(o, 0.0); return o + + +def tlb(V, S): + n = len(V); a = np.sort(V, 1); b = np.sort(S, 1) + return (a * a).sum(1)[:, None] / n + (b * b).sum(1)[None, :] / n - 2 * (a @ b.T) / n + + +def run(path, label, trial=0): + st = torch.load(path, map_location="cpu", weights_only=False) + V = standardise(st["visual_field"].double().numpy()) + T = standardise(st["text_field"].double().numpy()) + n = len(V); w = ot.unif(n) + rng = np.random.default_rng(trial); hid = rng.permutation(n) + S = T[np.ix_(hid, hid)] + Vg = standardized(torch.from_numpy(V).to(DEV)).double() + Sg = standardized(torch.from_numpy(S).to(DEV)).double() + en = ClosedFormEnergy(Sg, Vg, 1.0, 0.0, 64) + M = tlb(V, S); M = M / M.max() + + def acc(c): return float((hid[c] == np.arange(n)).mean()) + + def refine(c): + f = fast_pair_descent(Sg, Vg, torch.from_numpy(np.ascontiguousarray(c)).to(DEV), + 600).cpu().numpy() + e = float(en.energy(torch.from_numpy(np.ascontiguousarray(f)).to(DEV)[None])[0]) + return e, acc(f) + + et = float(en.energy(torch.from_numpy(np.ascontiguousarray(np.argsort(hid))).to(DEV)[None])[0]) + print(f"# {label} trial{trial} E_truth={et:.4f}", flush=True) + + out = {"label": label, "E_truth": et, "cold": [], "warm": []} + for mode in ("cold", "warm"): + G = np.outer(w, w) + prev = None + for a in ALPHAS: + t0 = time.time() + g0 = None if mode == "cold" else G + G2 = ot.gromov.fused_gromov_wasserstein(M, V, S, w, w, "square_loss", + alpha=a, G0=g0, max_iter=200, + tol_rel=1e-9) + if mode == "warm": + G = G2 + _, cols = linear_sum_assignment(-G2) + e, ar = refine(cols) + same = (prev is not None and np.array_equal(cols, prev)) + prev = cols + rec = {"alpha": a, "raw": acc(cols), "refined": ar, "E": e, + "sec": round(time.time() - t0, 1), "same_as_prev": bool(same)} + out[mode].append(rec) + print(f" {mode} a={a:<5} raw={rec['raw']:.4f} ref={ar:.4f} E={e:.4f}" + f" {'FROZEN' if same else ''} ({rec['sec']}s)", flush=True) + good = out[mode] + best = min(good, key=lambda x: x["E"]) + print(f" == {mode}: blind-by-E refined={best['refined']:.4f} (alpha={best['alpha']})," + f" oracle-best={max(x['refined'] for x in good):.4f}", flush=True) + return out + + +if __name__ == "__main__": + base = "/home/yurenh2/emm/artifacts/synth_v1/" + res = [] + for p, l in [("omit_size.pt", "omit-size"), ("omit_none.pt", "synth-full")]: + res.append(run(base + p, l)) + scratch = ("/tmp/claude-1273071/-home-yurenh2-emm/" + "bb97201d-d9b5-46e6-82fc-981d37e7ab98/scratchpad/") + json.dump(res, open(scratch + "lean.json", "w")) + print(json.dumps({"done": True})) diff --git a/logs/mech.log b/logs/mech.log new file mode 100644 index 0000000..817501a --- /dev/null +++ b/logs/mech.log @@ -0,0 +1,11 @@ +--- trial 0 E_truth=0.339630 + tlb-vertex start=0.0586 | 1 power step ->0.0312 (E=0.7114) | 5 steps ->0.1719 (E=0.6409) | warm FGW ->0.8555 (E=0.3396) + random-vertex start=0.0000 | 1 power step ->0.0312 (E=0.7279) | 5 steps ->0.0781 (E=0.6819) | warm FGW ->0.8125 (E=0.3396) + grampa-vertex start=0.0156 | 1 power step ->0.0938 (E=0.7821) | 5 steps ->0.0469 (E=0.7049) | warm FGW ->0.8203 (E=0.3396) +--- trial 1 E_truth=0.339630 + tlb-vertex start=0.0508 | 1 power step ->0.0352 (E=0.7114) | 5 steps ->0.1836 (E=0.6409) | warm FGW ->0.8164 (E=0.3396) + random-vertex start=0.0039 | 1 power step ->0.0156 (E=0.7051) | 5 steps ->0.0195 (E=0.6692) | warm FGW ->0.0195 (E=0.6554) + grampa-vertex start=0.0195 | 1 power step ->0.0742 (E=0.7821) | 5 steps ->0.0547 (E=0.7049) | warm FGW ->0.8164 (E=0.3396) +--- trial 2 E_truth=0.339630 + tlb-vertex start=0.0430 | 1 power step ->0.0312 (E=0.7114) | 5 steps ->0.1797 (E=0.6409) | warm FGW ->0.8359 (E=0.3396) + random-vertex start=0.0000 | 1 power step ->0.0195 (E=0.7149) | 5 steps ->0.0117 (E=0.6700) | warm FGW ->0.0391 (E=0.6387) diff --git a/logs/mech.py b/logs/mech.py new file mode 100644 index 0000000..6762777 --- /dev/null +++ b/logs/mech.py @@ -0,0 +1,51 @@ +import sys, numpy as np, ot, torch +sys.path.insert(0,'/home/yurenh2/emm') +from scipy.optimize import linear_sum_assignment +from worldalign.synth_fast_gate import ClosedFormEnergy, fast_pair_descent +from worldalign.synth_triangle_gate import standardized +DEV=torch.device("cuda:1") +def standardise(m): + mask=~np.eye(len(m),dtype=bool); v=m[mask] + o=(m-v.mean())/v.std(); np.fill_diagonal(o,0.0); return o +def tlb(V,S): + n=len(V); a=np.sort(V,1); b=np.sort(S,1) + return (a*a).sum(1)[:,None]/n+(b*b).sum(1)[None,:]/n-2*(a@b.T)/n +st=torch.load("/home/yurenh2/emm/artifacts/synth_v1/omit_size.pt",map_location='cpu',weights_only=False) +V=standardise(st["visual_field"].double().numpy()); T=standardise(st["text_field"].double().numpy()) +n=len(V); w=ot.unif(n) +for trial in range(3): + rng=np.random.default_rng(trial); hid=rng.permutation(n); S=T[np.ix_(hid,hid)] + Vg=standardized(torch.from_numpy(V).to(DEV)).double(); Sg=standardized(torch.from_numpy(S).to(DEV)).double() + en=ClosedFormEnergy(Sg,Vg,1.0,0.0,64) + Et=float(en.energy(torch.from_numpy(np.ascontiguousarray(np.argsort(hid))).to(DEV)[None])[0]) + acc=lambda c: float((hid[c]==np.arange(n)).mean()) + def refine(c,it=2000): + f=fast_pair_descent(Sg,Vg,torch.from_numpy(np.ascontiguousarray(c)).to(DEV),it).cpu().numpy() + return float(en.energy(torch.from_numpy(np.ascontiguousarray(f)).to(DEV)[None])[0]), acc(f) + M=tlb(V,S); M=M/M.max() + _,tlbcols=linear_sum_assignment(M) + def vert(cols): + P=np.zeros((n,n)); P[np.arange(n),cols]=1.0/n; return P + starts={"tlb-vertex":tlbcols, + "random-vertex":np.random.default_rng(50+trial).permutation(n), + "grampa-vertex":None} + from worldalign.spectral_match import grampa + starts["grampa-vertex"]=grampa(V,S,1.0) + print(f"--- trial {trial} E_truth={Et:.6f}") + for name,cols in starts.items(): + # (i) pure power step: LSAP on gradient V P S (anchor-propagation, one round) + P=vert(cols); grad=V@P@S + _,c1=linear_sum_assignment(-grad) + e1,a1=refine(c1) + # (ii) 5 rounds of power step + c=cols.copy() + for _ in range(5): + P=vert(c); _,c=linear_sum_assignment(-(V@P@S)) + e2,a2=refine(c) + # (iii) warm FGW at alpha=0.1 then 0.2 from this vertex + G=vert(cols) + for a in (0.1,0.2,0.5): + G=ot.gromov.fused_gromov_wasserstein(M,V,S,w,w,"square_loss",alpha=a,G0=G,max_iter=200,tol_rel=1e-9) + _,c3=linear_sum_assignment(-G); e3,a3=refine(c3) + print(" %-14s start=%.4f | 1 power step ->%.4f (E=%.4f) | 5 steps ->%.4f (E=%.4f) | warm FGW ->%.4f (E=%.4f)" + %(name,acc(cols),a1,e1,a2,e2,a3,e3), flush=True) diff --git a/logs/verify.py b/logs/verify.py new file mode 100644 index 0000000..17fd643 --- /dev/null +++ b/logs/verify.py @@ -0,0 +1,59 @@ +import sys, numpy as np, ot, torch +sys.path.insert(0,'/home/yurenh2/emm') +from scipy.optimize import linear_sum_assignment +from worldalign.synth_fast_gate import ClosedFormEnergy, fast_pair_descent +from worldalign.synth_triangle_gate import standardized +DEV=torch.device("cuda:1") +def standardise(m): + mask=~np.eye(len(m),dtype=bool); v=m[mask] + o=(m-v.mean())/v.std(); np.fill_diagonal(o,0.0); return o +def tlb(V,S): + n=len(V); a=np.sort(V,1); b=np.sort(S,1) + return (a*a).sum(1)[:,None]/n+(b*b).sum(1)[None,:]/n-2*(a@b.T)/n +st=torch.load("/home/yurenh2/emm/artifacts/synth_v1/omit_size.pt",map_location='cpu',weights_only=False) +V=standardise(st["visual_field"].double().numpy()); T=standardise(st["text_field"].double().numpy()) +n=len(V); w=ot.unif(n) +rng=np.random.default_rng(0); hid=rng.permutation(n); S=T[np.ix_(hid,hid)] +Vg=standardized(torch.from_numpy(V).to(DEV)).double(); Sg=standardized(torch.from_numpy(S).to(DEV)).double() +en=ClosedFormEnergy(Sg,Vg,1.0,0.0,64) +M=tlb(V,S); M=M/M.max() +G=np.outer(w,w) +for a in (0.0,0.2): + G=ot.gromov.fused_gromov_wasserstein(M,V,S,w,w,"square_loss",alpha=a,G0=G,max_iter=200,tol_rel=1e-9) +_,cols=linear_sum_assignment(-G) +fin=fast_pair_descent(Sg,Vg,torch.from_numpy(np.ascontiguousarray(cols)).to(DEV),2000).cpu().numpy() +truth=np.argsort(hid) +Ef=float(en.energy(torch.from_numpy(np.ascontiguousarray(fin)).to(DEV)[None])[0]) +Et=float(en.energy(torch.from_numpy(np.ascontiguousarray(truth)).to(DEV)[None])[0]) +acc=float((hid[fin]==np.arange(n)).mean()) +print("accuracy=%.4f E_found=%.10f E_truth=%.10f diff=%.3e"%(acc,Ef,Et,Ef-Et)) +wrong=np.where(hid[fin]!=np.arange(n))[0] +print("n_wrong=%d"%len(wrong)) +# for each wrong scene i: correlation between S-row of assigned node and S-row of true node +Sal=S # in shuffled index space +corr=[] +vcorr=[] +for i in wrong: + a_idx=fin[i]; t_idx=truth[i] + x=np.delete(Sal[a_idx],[a_idx,t_idx]); y=np.delete(Sal[t_idx],[a_idx,t_idx]) + corr.append(np.corrcoef(x,y)[0,1]) + u=np.delete(V[i],[i]); + # visual side: is the visually-assigned scene similar to i? compare V rows of i and of the scene truly at a_idx + j=hid[a_idx] + v1=np.delete(V[i],[i,j]); v2=np.delete(V[j],[i,j]) + vcorr.append(np.corrcoef(v1,v2)[0,1]) +rng2=np.random.default_rng(7); pairs=rng2.integers(0,n,(len(wrong),2)) +base=[np.corrcoef(np.delete(Sal[p],[p,q]),np.delete(Sal[q],[p,q]))[0,1] for p,q in pairs if p!=q] +print("text-row corr of confused partners: median=%.3f mean=%.3f | random pair baseline median=%.3f"%(np.median(corr),np.mean(corr),np.median(base))) +print("visual-row corr of confused partners: median=%.3f"%np.median(vcorr)) +# cycle structure of the error +perm=hid[fin] +seen=set(); cyc=[] +for i in range(n): + if i in seen or perm[i]==i: continue + c=0; j=i + while j not in seen: + seen.add(j); j=perm[j]; c+=1 + cyc.append(c) +import collections +print("error cycle lengths:", dict(collections.Counter(cyc))) |
