
d = 0
for j in adj[pi]:
if j!=ni: d += 1 if s[j]==1 else -1
for j in adj[ni]:
if j!=pi: d += 1 if s[j]==0 else -1
if d > 0:
s[pi], s[ni] = 0, 1; cut += d
elif d==0 and np.random.random()<0.2:
s[pi], s[ni] = 0, 1
if cut > best: best = cut
return best
# Experimental data: A -> (Z, BE/A MeV, name)
exp = {
2:(1,1.112,'2H'), 4:(2,7.074,'4He'),
6:(3,5.333,'6Li'), 7:(3,5.606,'7Li'),
9:(4,6.463,'9Be'), 12:(6,7.680,'12C'),
14:(7,7.476,'14N'), 16:(8,7.976,'16O'),
20:(10,8.032,'20Ne'), 24:(12,8.261,'24Mg'),
28:(14,8.448,'28Si'), 32:(16,8.493,'32S'),
40:(20,8.551,'40Ca'), 56:(26,8.790,'56Fe'),
58:(28,8.732,'58Ni'), 80:(34,8.711,'80Se'),
90:(40,8.710,'90Zr'), 120:(50,8.505,'120Sn'),
150:(62,8.278,'150Sm'),208:(82,7.868,'208Pb'),
238:(92,7.570,'238U'),
}
ALPHA = 4.5; GAMMA = 23.2
np.random.seed(42)
# Pre-compute Max-Cut for all (A, Z)
mc = {}
for A in sorted(exp.keys()):
coords = fcc_cluster(A)
adj = adj_list(coords)
zmin = max(1, int(A*0.20))
zmax = min(A-1, int(A*0.55))
if A < 10: zmin, zmax = 1, A-1
for Z in range(zmin, zmax+1):
mc[(A,Z)] = maxcut(adj, A, Z, 3,
min(A*12, 3500))
# Predict Z for each nucleus
hdr = f"{'A':>4} {'name':<7} {'Zp':>3} {'Ze':>3}"
hdr += f" {'dZ':>4} {'pn':>5} {'BE/A':>6} {'exp':>6}"
print(hdr); print("-"*45)
for A in sorted(exp.keys()):
Ze, BE, nm = exp[A]
zmin = max(1, int(A*0.20))
zmax = min(A-1, int(A*0.55))
if A < 10: zmin, zmax = 1, A-1
bZ=zmin; bS=-1e9; bPN=0
for Z in range(zmin, zmax+1):
if (A,Z) not in mc: continue
pn = mc[(A,Z)]
asym = GAMMA * (A-2*Z)**2 / A
coul = 0.72*Z*(Z-1)/(A**(1/3)) if A>1 else 0
sc = ALPHA*pn - asym - coul
10