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,71 @@
"""sum_bound_proof.py -- proof ingredients for the RIGOROUS bound
rho biseparable => min(||M_AB||_*, ||M_AC||_*, ||M_AD||_*) <= 11/3
Step 1: verify (numerically, over each cut type) that
||M_AB||_* + ||M_AC||_* + ||M_AD||_* <= 11
for every PURE state product across a single bipartition (the extreme points of the
biseparable set). Since the SUM of nuclear norms IS convex (unlike the min!), this bound
then extends by convexity to ALL biseparable (mixed) states -- this is the key trick that
lets a convexity/extreme-point argument work here even though it fails for min() itself.
Step 2: verify via linear programming that uniform weights (1/3,1/3,1/3) are optimal for
turning the sum bound into a bound on min(...) via min(a,b,c) <= w.(a,b,c) for any
w in the simplex -- i.e. that 11/3 is the best bound achievable by this proof technique
(cannot be tightened just by re-weighting).
"""
import numpy as np
from scipy.optimize import minimize, linprog
from core import state_1_3, state_2_2
from core2 import full_tensor
from cluster import cluster_map, nuc
def sum3(psi):
C = full_tensor(psi)
return nuc(cluster_map(C, 0, 1)) + nuc(cluster_map(C, 0, 2)) + nuc(cluster_map(C, 0, 3))
def neg_sum_2_2(params, pair1, pair2):
return -sum3(state_2_2(params, pair1, pair2))
def neg_sum_1_3(params, source):
return -sum3(state_1_3(params, source))
def run(obj, nparams, args, n_restarts, seed0, label):
best = -np.inf
for i in range(n_restarts):
rng = np.random.default_rng(seed0 + i)
x0 = rng.normal(size=nparams)
res = minimize(obj, x0, args=args, method='Powell',
options={'maxiter': 1500, 'xtol': 1e-9, 'ftol': 1e-11})
v = -res.fun
if v > best:
best = v
print(f'{label}: max sum = {best:.6f} ({n_restarts} restarts)')
return best
if __name__ == "__main__":
print("=== Step 1: max(||M_AB||+||M_AC||+||M_AD||) over each pure single-cut family ===")
r1 = run(neg_sum_2_2, 16, ((0, 1), (2, 3)), 8, 6000, 'cut AB|CD')
r2 = run(neg_sum_2_2, 16, ((0, 2), (1, 3)), 8, 6100, 'cut AC|BD')
r3 = run(neg_sum_1_3, 18, (0,), 8, 6200, 'cut A|BCD')
r4 = run(neg_sum_1_3, 18, (1,), 8, 6300, 'cut B|ACD')
print()
print('Overall max sum over ALL single-cut pure product states:', max(r1, r2, r3, r4))
print('(convexity of the sum then extends this bound to ALL biseparable mixtures)')
print()
print("=== Step 2: is uniform weighting (1/3,1/3,1/3) optimal for the resulting bound? ===")
# extreme points of the "sum" bound: (1,5,5), (5,1,5), (5,5,1)
c = [0, 0, 0, 1]
A_ub = [[1, 5, 5, -1], [5, 1, 5, -1], [5, 5, 1, -1]]
b_ub = [0, 0, 0]
A_eq = [[1, 1, 1, 0]]
b_eq = [1]
bounds = [(0, 1), (0, 1), (0, 1), (None, None)]
res = linprog(c, A_ub=A_ub, b_ub=b_ub, A_eq=A_eq, b_eq=b_eq, bounds=bounds, method='highs')
print('LP-optimal weights:', res.x[:3], ' bound t=', res.x[3])
print('11/3 =', 11 / 3, ' (confirms uniform weights are optimal for this proof technique)')