Public

P versus NP problem (code)

Code written by the AI agents of “P versus NP problem”. Each agent works on its own branch; main follows the lead agent.

Commits

Replace soft constraints with explicit minimize in full mode; delete old placeholder

Lasques agent 1 (lead, iteration 1) · 26 oct. 2026 · 20325dee37166488edd264593addc2f905e54d0f

1 fichier modifié

+29−49
mod_dnf.pyModified+29−49
@@ -1,17 +1,12 @@
11"""Depth-2 ACC0[m] = MOD_m o AND minimal size computation.
22
33Circuit class: f(x) = ( sum_j c_j * T_j(x) ) mod m, T_j = AND of a subset of
4literals, c_j in {0..m-1}, c_j != 0 iff term T_j is present.
5Minimize the number of present terms (L_0 of the coefficient vector).
4literals, c_j in {1..m-1} for present terms. Minimize number of present terms.
65
7Full mode: exact optimization over all 3^n monomials with z3 Optimize.
8Sym mode: symmetric functions only. Restrict to solutions that use all
9monomials of an orbit (a positives, b negatives) with a common coefficient.
10Then T_{a,b} fires C(w,a)*C(n-w,b) times at inputs of weight w, and the
11constraint becomes a small integer program over n^2 orbit coefficients.
12This is a restriction (upper bounds); validity checked against full mode.
6Full mode: exact optimization over all 3^n monomials with z3 Optimize (minimize).
7Sym mode: symmetric functions, orbit-restricted ILP (upper bound), scalable.
138"""
14import itertools, math, sys
9import itertools, math
1510import numpy as np
1611import lasques
1712import z3
@@ -21,7 +16,7 @@ n = int(p.get("n", 5))
2116m = int(p.get("m", 3))
2217fn = p.get("fn", "parity")
2318mode = p.get("mode", "sym")
24q = int(p.get("q", 2)) # for modq
19q = int(p.get("q", 2))
2520
2621
2722def truth_table(fn, n, q=2):
@@ -36,59 +31,45 @@ def truth_table(fn, n, q=2):
3631 raise ValueError(fn)
3732
3833
39def monomial_value(x, a_idx, b_idx):
40 """AND over positives a_idx (x=1) and negatives b_idx (x=0)."""
34def monomial_value(x, pos, neg):
4135 v = 1
42 for i in a_idx:
36 for i in pos:
4337 v &= (x >> i) & 1
44 for i in b_idx:
38 for i in neg:
4539 v &= 1 - ((x >> i) & 1)
4640 return v
4741
4842
49def solve_full_z3(n, m, tt, max_time=180):
50 """Exact minimal number of MOD_m o AND terms over all monomials."""
43def solve_full_z3(n, m, tt, max_time=200):
5144 cols = []
5245 for a in range(n + 1):
5346 for b in range(n + 1 - a):
5447 for pos in itertools.combinations(range(n), a):
5548 rest = [i for i in range(n) if i not in pos]
5649 for neg in itertools.combinations(rest, b):
57 col = [monomial_value(x, pos, neg) for x in range(2**n)]
58 cols.append(col)
50 cols.append([monomial_value(x, pos, neg) for x in range(2**n)])
5951 A = np.array(cols, dtype=np.int64).T # 2^n x 3^n
6052 ncol = A.shape[1]
6153 opt = z3.Optimize()
6254 opt.set("timeout", max_time * 1000)
6355 c = [z3.Int(f"c_{j}") for j in range(ncol)]
64 used = [z3.Bool(f"u_{j}") for j in range(ncol)]
56 used = [z3.If(c[j] > 0, 1, 0) for j in range(ncol)]
6557 for j in range(ncol):
6658 opt.add(c[j] >= 0, c[j] <= m - 1)
67 opt.add(z3.Implies(used[j], c[j] > 0))
68 opt.add(z3.Implies(c[j] > 0, used[j]))
6959 for x in range(2**n):
70 terms = [z3.If(used[j], c[j] * int(A[x, j]), 0) for j in range(ncol)]
71 # mod m equality with the target
60 terms = [c[j] * int(A[x, j]) for j in range(ncol)]
7261 opt.add(z3.Sum(terms) % m == tt[x])
73 for j in range(ncol):
74 opt.add_soft(z3.Not(used[j]))
75 if opt.check() == z3.sat:
62 opt.minimize(z3.Sum(used))
63 r = opt.check()
64 if r == z3.sat:
7665 mdl = opt.model()
77 size = sum(1 for j in range(ncol) if z3.is_true(mdl.eval(used[j])))
78 if opt.reason_unknown() == "":
79 proven_optimal = True
80 else:
81 proven_optimal = False
82 return size, proven_optimal
66 size = sum(1 for j in range(ncol) if mdl.eval(c[j]).as_long() > 0)
67 proven = (opt.reason_unknown() == "")
68 return size, proven
8369 return None, False
8470
8571
86def solve_symmetric(n, m, tt, max_time=180):
87 """Orbit-restricted ILP: variables = coefficient per orbit (a,b).
88 Upper bound on the true optimum for symmetric f. Sizes:
89 cost of orbit (a,b) = C(n,a)*C(n-a,b) monomials * coeff usage.
90 We minimize total monomial count = sum coeff * C(n,a) C(n-a,b).
91 """
72def solve_symmetric(n, m, tt, max_time=200):
9273 opt = z3.Optimize()
9374 opt.set("timeout", max_time * 1000)
9475 orbs = [(a, b) for a in range(n + 1) for b in range(n + 1 - a)]
@@ -96,19 +77,17 @@ def solve_symmetric(n, m, tt, max_time=180):
9677 for (a, b) in orbs:
9778 row = []
9879 for w in range(n + 1):
99 if w >= a and (n - w) >= b:
100 row.append(math.comb(w, a) * math.comb(n - w, b))
101 else:
102 row.append(0)
80 row.append(math.comb(w, a) * math.comb(n - w, b)
81 if w >= a and (n - w) >= b else 0)
10382 wvals[(a, b)] = row
10483 cvars = {o: z3.Int(f"c_{o[0]}_{o[1]}") for o in orbs}
10584 for o in orbs:
10685 opt.add(cvars[o] >= 0, cvars[o] <= m - 1)
10786 for w in range(n + 1):
10887 terms = [cvars[o] * wvals[o][w] for o in orbs]
109 opt.add(z3.Sum(terms) % m == tt[2**n - 1] if False else
110 z3.Sum(terms) % m == tt[(1 << w) - 1]) # input of weight w
111 cost = z3.Sum([cvars[o] * math.comb(n, o[0]) * math.comb(n - o[0], o[1]) for o in orbs])
88 opt.add(z3.Sum(terms) % m == tt[(1 << w) - 1])
89 cost = z3.Sum([cvars[o] * math.comb(n, o[0]) * math.comb(n - o[0], o[1])
90 for o in orbs])
11291 opt.minimize(cost)
11392 if opt.check() == z3.sat:
11493 mdl = opt.model()
@@ -126,9 +105,10 @@ else:
126105 size, proven = solve_symmetric(n, m, tt)
127106
128107lasques.set_metrics({
129 "n": n, "m": m, "fn": fn, "mode": mode, "size": size if size is not None else -1,
130 "proven_optimal": proven, "exponent_guess": math.log2(size) / n if size else None,
108 "n": n, "m": m, "fn": fn, "mode": mode, "q": q,
109 "size": size if size is not None else -1,
110 "proven_optimal": proven,
111 "exponent_guess": math.log2(size) / n if size else None,
131112})
132lasques.save_table([{**{k: v for k, v in lasques.params().items()}, "size": size,
133 "proven_optimal": proven}], "result")
113lasques.save_table([{**lasques.params(), "size": size, "proven_optimal": proven}], "result")
134114lasques.summary(f"{fn} depth-2 MOD_{m}oAND min size at n={n} ({mode}): {size} (optimal={proven})")