feat: add numeric and symbolic scripts

This commit is contained in:
Hans Aschauer 2026-07-26 14:09:49 +02:00
parent 6ea7900b55
commit e80b7c3582
38 changed files with 3314 additions and 0 deletions

View file

@ -0,0 +1,69 @@
"""
Seeded exploration around the known-good point (3.0, 3.0, 3.0).
Two questions this answers:
1) Is 3.0 a STABLE fixed point of the alternating scheme (perturb the witnesses a
little, does it converge back to 3.0)?
2) Does searching the FULL PPT-mixture body (strictly larger than biseparable states)
starting from near this point ever find something BETTER than 3.0?
If nothing beats 3.0 even when explicitly seeded nearby and given many iterations, that
is now fairly strong evidence -- across both a from-scratch parametrized search (earlier)
and this SDP-based search over the larger PPT-mixture relaxation -- that 3.0 is the true
supremum (at least for PPT-mixtures, hence an upper bound on the biseparable one too,
since biseparable subset PPT-mixtures).
"""
import numpy as np
from sdp_ppt_mixture import solve_fixed_witness_step, true_norms_and_witnesses, CLUSTERS
data = np.load('O_seed.npz')
O_seed = {name: data[name] for name, _, _ in CLUSTERS}
def project_to_unit_opnorm(A):
"""Rescale A to have operator norm exactly 1 (SVD-based projection)."""
U, s, Vt = np.linalg.svd(A)
return U @ Vt if s.max() == 0 else A / s.max()
def run_seeded(perturbation_strength, n_iters=25, seed=0, verbose=True):
rng = np.random.default_rng(seed)
O = {}
for name, _, _ in CLUSTERS:
noise = rng.normal(size=(15, 15)) * perturbation_strength
O[name] = project_to_unit_opnorm(O_seed[name] + noise)
best_min = -np.inf
history = []
for it in range(n_iters):
rho_val, t_val, M_vals = solve_fixed_witness_step(O)
norms, O = true_norms_and_witnesses(M_vals)
cur_min = min(norms.values())
history.append(cur_min)
best_min = max(best_min, cur_min)
if verbose:
nice = {k: round(v, 5) for k, v in norms.items()}
print(f" iter {it:2d}: SDP t={t_val:.5f} norms={nice} min={cur_min:.5f}")
return best_min, history
if __name__ == "__main__":
print("=== Stability check: seed EXACTLY at the known optimum (no perturbation) ===")
best0, _ = run_seeded(perturbation_strength=0.0, n_iters=10, seed=0)
print(f" best min found: {best0:.6f} (should stay essentially at 3.0)\n")
print("=== Perturbation sweep: does it converge back to 3.0, drift, or improve? ===")
results = {}
for strength in [0.05, 0.1, 0.2, 0.4, 0.7, 1.0]:
print(f"--- perturbation strength {strength} ---")
best, hist = run_seeded(perturbation_strength=strength, n_iters=25, seed=1, verbose=True)
results[strength] = best
print(f" final best: {best:.6f}\n")
print("=" * 60)
for s, v in results.items():
print(f" perturbation {s:.2f} -> best min found = {v:.6f}")
overall_best = max(results.values())
print()
print("Overall best across all perturbed seeded runs:", overall_best)
print("Compare: 3.0 (conjectured exact), 11/3 =", 11/3, "(proven upper bound)")