"""Stage 5: how tight is the boundary lower bound? Computes the exact beta_18(n) for 26 <= n <= 40 by solving F(n,18,b) upward from b = 12 with the project encoder (CaDiCaL); the certificate margin is beta_18(n) - 12. Models are re-checked by direct counting. Output: results/robustness/margin.json""" import json, os, sys, time ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))); os.chdir(ROOT) sys.path.insert(0, os.path.join(ROOT, ".pydeps")); sys.path.insert(0, os.path.join(ROOT, "code")) from pysat.solvers import Solver from sat_or_ilp_solver import boundary_clauses def nbrs(n, k=5): A = {} for i in range(n): A[i] = {(i + 1) % n, (i - 1) % n, n + i}; A[n + i] = {n + (i + k) % n, n + (i - k) % n, i} return A out = [] for n in range(26, 41): A = nbrs(n); t0 = time.time(); rec = {"n": n} for b in range(12, 20): cl, x, z, nv = boundary_clauses(n, 5, 18, b) with Solver(name="cadical195", bootstrap_with=cl) as sv: sat = sv.solve(); model = sv.get_model() if sat else None if sat: X = [w for w in range(2 * n) if model[x[w] - 1] > 0]; Xs = set(X) bd = len({w for q in X for w in A[q] if w not in Xs}) rec.update({"beta_18": b, "model_boundary_recount": bd, "model_size": len(X), "margin": b - 12, "X": ["%s%d" % ("u" if w < n else "v", w % n) for w in X]}) break rec["seconds"] = round(time.time() - t0, 1); out.append(rec); print(rec, flush=True) json.dump(out, open("results/robustness/margin.json", "w"), indent=1)