import json, time import numpy as np from scipy.optimize import nnls def certify(a, b, retained, tol=1e-9): A = np.asarray(a, float); B = np.asarray(b, float) R = list(retained); out = {} for j in range(len(A)): if j in R: continue lam, _ = nnls(A[R].T, A[j]) resid = np.linalg.norm(A[j] - A[R].T @ lam) offset = float(lam @ B[R] - B[j]) out[j] = (resid <= tol and offset <= tol, resid, offset, lam) return out def reduce_constraints(a, b, tol=1e-8): A=np.asarray(a,float); B=np.asarray(b,float) ang=np.mod(np.arctan2(A[:,1], A[:,0]),2*np.pi) order=np.argsort(ang) gaps=np.diff(np.r_[ang[order],ang[order[0]]+2*np.pi]) if gaps.max() > np.pi + tol: k=int(np.argmax(gaps)); R=[int(order[k]),int(order[(k+1)%len(order)])] else: R=[int(order[0]),int(order[len(order)//3]),int(order[2*len(order)//3])] R=list(dict.fromkeys(R)) while True: c=certify(A,B,R,tol) bad=[j for j,v in c.items() if not v[0]] if not bad: return sorted(R), c R.append(bad[0]) def feasible(x,a,b,tol=1e-8): return bool(np.all(np.asarray(a)@x <= np.asarray(b)+tol)) def project(x0,a,b): """2-D Euclidean projection onto intersection of halfspaces.""" A=np.asarray(a,float); B=np.asarray(b,float); x=np.asarray(x0,float) if feasible(x,A,B): return x.copy() best=None; bestv=np.inf # Candidates are projections onto one boundary and intersections of two. for i in range(len(A)): den=A[i]@A[i]; y=x-A[i]*(A[i]@x-B[i])/den if feasible(y,A,B,1e-7) and np.sum((y-x)**2)