single.py
Checks: IMAGE: Polynomial slack reaches breadth from the void theorem; rule.
Cited on: IMAGE.
To run it: save single.py, with anchor.py, bridges.py, cgreedy.py, choosy.py, dambar.py, envelope.py, fwide.py, growth.py, slack.py beside it; standard library only.
"""single.py -- the least multiple of the dam's bar under which one run
escapes from the void.
QUESTION. A c-run is a run from the void whose every move from a state
of tide m0 is at most floor(c F(max(m0, 4))), F the dam's bar; a run's
envelope stays within cF at every t exactly when it is a c-run. c0 is
the infimum of the c at which some c-run escapes. Where is c0?
DESIGN. F from fwide.py's widened tau table, fixed on 4..10^4.
(1) Lemma D, the crossing. For a prime r and e >= 1 write d = r^e and its
point T(d) = min(r^(e+1), p(d)) at odd r, min(2^(e+2), p(d)) at 2. At
a state with v_r(lambda) <= e - 1, m0 <= T(d): r's price is at most the
point, and p(d), unheld, prices itself. An escaping run's tide is
unbounded, so it passes every crossing, by a move from a tide <= T(d), at
most X(d) = floor(cF(T(d))), that brings a prime = 1 mod d, every
earlier prime being at most X(d) too. Raising r's own exponent instead
leaves the tide at most r (odd r past depth e with no anchor), at most
2 (2 at b >= e + 2 with u_2 <= b - 2) or at most 4 (the move 4 at
e = 1), until a prime = 1 mod d enters by a move at most X(d).
(2) Lemma H, a held crossing. A held odd q with v_q(lambda) <= f - 1 has
m0 <= q^f, its price q^max(1, v - a + 2) <= q^(f + 1 - a).
(3) Viability. Y*(a), the least Y such that a, entering with every
earlier prime at most Y, has each crossing a^f (a^f <= 10^4) passable: by
a prime b = 1 mod a^f held before a (b <= Y) or after (b <=
Z = floor(cF(a^f)), by (2)), b's earlier primes at most max(Y, Z). So
need_f(a) = 0 if some such b <= Z has Y*(b) <= Z, else the least
max(b, Y*(b)); Y*(a) = max_f need_f(a), and 0 past 10^4. An
over-approximation of viability, so sound for a dam.
(4) THE CROSSING TEST at c: every crossing d with T(d) <= 10^4 has a prime
a = 1 mod d with a <= X(d) and Y*(a) <= X(d). A failing crossing dams
every c-run: a proof at that c, given F's table. It is monotone in c;
c_low, the least c at which it passes, is found by bisection over
exact fractions and named as the critical ratio n/F(x) above the last
failing c.
(5) THE CROSSING-LED RUN, one prime per move at exponent 1 from the void:
at each state the tide's class (anchor.py's modulus and cls), the
candidates its unheld primes P <= floor(cF(m0)) with Y*(P) <=
floor(cF(m0)); it seats the least, and a state with none stops it.
c_up is the least c on the grid 2.30, 2.35, ..., 6.75 at which its
tide passes 10^4.
PREDICTIONS (frozen before the code).
P1 (proved by hand) the crossing test fails at every c < 53/23: c_low >=
53/23, and at c = 2.30 the 4-crossing fails with Y*(5), Y*(13), Y*(17)
> 25.
P2 (guess, 50%) c_low < 3.
P3 (guess, 40%) c_up < 6.7315: some crossing-led run beats the chain-led.
P4 (guess, 30%) c_up <= 1.5 c_low.
CONTROLS, read first. C1 the crossing test fails at c = 1 (F is dammed
from the void at 23). C2 it passes at c = 10831/1609 (the chain-led
run's moves stay within that multiple of F to tide 10^4). C3 Lemma D
over cgreedy's brute box (the primes <= 13) and 2000 random states on
the primes < 300: m0 <= T(d) at every state and every d = r^e <= 10^4,
r < 60, e <= 4, with v_r(lambda) <= e - 1. C4 Y* against a brute recursion
(viable(a, Y) by its definition, bisected on Y) on the primes <= 200
at c = 3.
THE PRINT. "c0 >= <c_low>, PROVED BY THE CROSSING TEST; A c-RUN AT <c_up>
REACHES TIDE 10^4" (frozen as "c0 IN [<c_low>, <c_up>]", which read
the run as an upper bound past 10^4); c_up / c_low above 2 prints
"KILL: THE CROSSING TEST DOES NOT LOCATE c0", and no crossing-led run
below 6.75 prints "KILL: NO CROSSING-LED RUN BELOW THE CHAIN-LED".
(Frozen with "door" where every line now says "crossing".)
FINDINGS (from the printed run; the controls passed first: 309 crossings
with T(d) <= 10^4; C1's first failing crossing at c = 1 is d = 2, T 3, X 5;
C3 over 5780 states and 221,864 (state, crossing) pairs; C4 equal on the
45 primes <= 200).
At c = 2.30 the failing crossings are 2 (X 11), 4 (X 25), 16, 3, 5 and 41,
with Y*(5) = 11251, Y*(13) = 131, Y*(17) = 127739: P1 holds.
c_low = 739/233 = 3.171674, the test failing at 3.1716738 at one crossing
only, d = 41: T(41) = min(1681, 83) = 83, X = 738, and its one
candidate 83 has Y* = 997. While 41 does not divide lambda, 83 prices
itself, so the tide is at most 83 and a prime = 1 mod 41 enters by a
move at most 233c; below 739/233 that is 83 alone. 83's crossing, by a
move at most 738, reaches 167 (Y* 2339, past 167's own reach 2039)
and 499 (Y* 10979: its one anchor in reach, 1997, has Y* 87869 =
p(1997), so the anchor 10979 must be held first); else 997 is held
first. P2 FAILS: c_low is 3.1717, not below 3.
The crossing-led run is STUCK at the void below 2.95 and at tide 83, the
41-crossing, from 2.95 to 3.15; at 3.20 it ESCAPES, tide 10,007 after 503
seats: c_up = 3.20, P3 holds (below 6.7315) and P4 holds (ratio
1.0089). READINGS: at c_low = 739/233 itself the crossing-led run ESCAPES,
tide 10,007 after 503 seats; re-tided by cgreedy.m0 on the full factor
map it AGREES at all 504 states, the void included, and its largest
seat / F(m0) is 739/233 exactly, the seat 739 = 18*41 + 1 taken from
the tide 83.
THE PRINT: c0 >= 739/233, PROVED BY THE CROSSING TEST; A c-RUN AT 3.20
REACHES TIDE 10^4. No kill fires. With the reading, c_low is met: no
run from the void escapes within cF for c < 739/233 (a proof, given
F's table and the lemmas), and the crossing-led run at c = 739/233 stays
within cF until its tide passes 10^4.
RUN RECORD. First run: C3 read p(d) past the sieve at d = r^e > 10^4
and was cut to the crossings the test uses, d <= 10^4; then 6/6, 34.5 s,
60.4 MB. With the c_low run and the Y* readings: 6/6, 34.3 s,
60.7 MB. With the re-tiding: 6/6, 34.7 s, 60.9 MB. With the void
re-tided too (it had been set to 3 by hand) and THE PRINT reworded:
6/6, 35.1 s, 61.3 MB. From code/, THE PRINT giving c_low as a
fraction and the largest seat placed: 6/6, 34.9 s, 60.9 MB. With
"door" renamed "crossing": 6/6, 34.7 s, 60.8 MB. With each Y* reading's
reach and its primes = 1 mod a within it printed (2039 and 1997 had
been worked by hand): 6/6, 34.7 s, 60.9 MB.
python single.py
"""
import os
import random
import time
from fractions import Fraction as Fr
os.environ.setdefault("OPENBLAS_NUM_THREADS", "1")
import cgreedy # noqa: E402
import envelope as ev # noqa: E402
import choosy # noqa: E402
import dambar # noqa: E402
import fwide # noqa: E402
import anchor # noqa: E402
T = ev.T
CHECKS = []
def check(name, ok, detail=""):
CHECKS.append((name, bool(ok)))
print(f" [{'PASS' if ok else 'FAIL'}] {name}"
+ (f" -- {detail}" if detail else ""))
def sieve(n):
s = bytearray([1]) * (n + 1)
s[0] = s[1] = 0
for i in range(2, int(n ** 0.5) + 1):
if s[i]:
s[i * i::i] = bytearray(len(range(i * i, n + 1, i)))
return s
class World:
def __init__(self, F):
self.F = F
self.W = 7 * F[T] + 7
self.S = sieve(self.W)
self.small = [q for q in range(3, T + 1) if self.S[q]]
def Fx(self, t):
return self.F[max(t, 4)]
def cap(self, c, t):
return (c.numerator * self.Fx(t)) // c.denominator
def p(self, s):
n = s + 1
while not self.S[n]:
n += s
return n
def ystar(self, c):
"""{a: Y*(a)} for the odd primes a <= T; W + 1 stands for no
Y within the sieve."""
Y = {}
INF = self.W + 1
for a in reversed(self.small):
worst = 0
s = a
while s <= T:
Z = self.cap(c, s)
need, b = INF, s + 1
while b <= self.W:
if self.S[b]:
yb = Y.get(b, 0)
if b <= Z and yb <= Z:
need = 0
break
need = min(need, max(b, yb))
if b >= need:
break
b += s
worst = max(worst, need)
if worst >= INF:
break
s *= a
Y[a] = worst
return Y
def crossings(self):
out = []
for r in [2] + self.small:
e = 1
while True:
d = r ** e
if d > T:
break
pt = 2 ** (e + 2) if r == 2 else r ** (e + 1)
Td = min(pt, self.p(d))
if Td <= T:
out.append((d, r, e, Td))
e += 1
return out
def test(self, c, Y=None, why=False):
Y = self.ystar(c) if Y is None else Y
bad = []
for d, r, e, Td in self.CROSSINGS:
X = self.cap(c, Td)
ok = False
a = d + 1
while a <= X:
if self.S[a] and Y.get(a, 0) <= X:
ok = True
break
a += d
if not ok:
bad.append((d, Td, X))
if not why:
return False, bad
return not bad, bad
def crossing_run(w, c, Y, log=None):
"""The crossing-led run: (escaped, final tide, seats); log gathers
(m0, seat) per move."""
held, vN, seats = set(), {}, 0
while True:
m0, r, kind = choosy.tide(held, vN)
if m0 > T:
return True, m0, seats
s = anchor.modulus(m0, r, kind, vN)
X = w.cap(c, m0)
P = None
n = s + 1
while n <= X:
if w.S[n] and n not in held and Y.get(n, 0) <= X:
P = n
break
n += s
if P is None:
return False, m0, seats
held.add(P)
seats += 1
if log is not None:
log.append((m0, P))
for q, e in choosy.factor(P - 1).items():
if e > vN.get(q, 0):
vN[q] = e
def brute_y(w, c, top):
"""Y* by its definition on the primes <= top, recursing upward."""
memo = {}
def viable(a, Yb):
if a > T:
return True
key = (a, Yb)
if key in memo:
return memo[key]
memo[key] = False
s, ok = a, True
while s <= T and ok:
Z = w.cap(c, s)
M = max(Yb, Z)
ok = any(w.S[b] and viable(b, M) for b in range(s + 1, M + 1, s))
s *= a
memo[key] = ok
return ok
out = {}
for a in [q for q in w.small if q <= top]:
lo, hi = 0, w.W + 1
if viable(a, 0):
out[a] = 0
continue
if not viable(a, w.W):
out[a] = w.W + 1
continue
lo, hi = 0, w.W
while hi - lo > 1:
mid = (lo + hi) // 2
if viable(a, mid):
hi = mid
else:
lo = mid
out[a] = hi
return out
def main():
t0 = time.time()
fwide.widen(fwide.PMAX)
F = dambar.f_table(fwide.tau_wide(fwide.PMAX, T))
assert all(F[t] is not None for t in range(4, T + 1))
w = World(F)
w.CROSSINGS = w.crossings()
print(f"F fixed on 4..{T}; {len(w.CROSSINGS)} crossings with T(d) <= {T}; "
f"sieve to {w.W} ({time.time() - t0:.1f} s)")
print("CONTROLS")
ok1, bad1 = w.test(Fr(1), why=True)
check("C1 the crossing test fails at c = 1", not ok1,
f"first failing crossing {bad1[0] if bad1 else None}")
cch = Fr(10831, 1609)
ok2, bad2 = w.test(cch, why=True)
check("C2 the crossing test passes at c = 10831/1609", ok2,
f"failing {bad2[:3]}")
rng = random.Random(1)
states = cgreedy.brute_box(13)
pr = [p for p in cgreedy.PR if p < 300]
for _ in range(2000):
mf = {2: rng.randint(0, 8)} if rng.random() < 0.7 else {}
for q in rng.sample(pr[1:], rng.randint(1, 12)):
mf[q] = rng.randint(1, 3)
states.append({q: a for q, a in mf.items() if a})
viol, tested = [], 0
rs = [r for r in cgreedy.PR if r < 60]
for mf in states:
lf = cgreedy.lam(mf)
m0 = cgreedy.m0(mf)
for r in rs:
for e in range(1, 5):
d = r ** e
if d <= T and lf.get(r, 0) <= e - 1:
pt = 2 ** (e + 2) if r == 2 else r ** (e + 1)
tested += 1
if m0 > min(pt, w.p(d)):
viol.append((mf, d))
check("C3 Lemma D: m0 <= T(d) wherever v_r(lambda) <= e - 1",
not viol, f"{len(states)} states, {tested} (state, crossing) pairs, "
f"first violation {viol[:1]}")
Y3 = w.ystar(Fr(3))
B3 = brute_y(w, Fr(3), 200)
diff = [a for a in B3 if min(B3[a], w.W + 1) != min(Y3[a], w.W + 1)]
check("C4 Y* against the brute recursion, primes <= 200 at c = 3",
not diff, f"{len(B3)} primes, differing {diff[:5]}")
if not all(ok for _, ok in CHECKS):
print("CONTROL FAILED: nothing below is read.")
raise SystemExit(1)
print("THE CROSSING TEST")
c23 = Fr(23, 10)
Y = w.ystar(c23)
ok, bad = w.test(c23, Y, why=True)
four = [b for b in bad if b[0] == 4]
ys = {a: Y.get(a) for a in (5, 13, 17)}
p1a = (not ok and bool(four) and four[0][2] == 25
and all(v > 25 for v in ys.values()))
print(f" c = 2.30: failing crossings {bad[:6]}; Y*(5, 13, 17) = {ys}")
lo, hi = Fr(1), cch
while hi - lo > Fr(1, 10 ** 7):
mid = (lo + hi) / 2
mid = Fr(round(mid * 10 ** 8), 10 ** 8)
if w.test(mid)[0]:
hi = mid
else:
lo = mid
fv = sorted(set(F[t] for t in range(4, T + 1)))
crit = min(Fr(int(lo * f) + 1, f) for f in fv)
okc = crit <= hi and w.test(crit)[0] and not w.test(lo)[0]
check("the critical ratio above the last failing c passes", okc,
f"c_low = {crit} = {float(crit):.6f}, last failing {float(lo):.7f}")
Yl = w.ystar(lo)
_, badl = w.test(lo, Yl, why=True)
check("P1 c_low >= 53/23, the 4-crossing failing at 2.30 with "
"Y*(5), Y*(13), Y*(17) > 25", p1a and crit >= Fr(53, 23))
print(f" crossings failing just below c_low: {badl[:8]}")
for d, Td, X in badl[:4]:
cands = [(a, Yl.get(a, 0)) for a in range(d + 1, X + 1, d)
if w.S[a]]
print(f" crossing {d}: T {Td}, X {X}, candidates (a, Y*) "
f"{cands[:10]}")
print(f" P2 (guess) c_low < 3: "
f"{'HOLDS' if crit < 3 else 'FAILS'}, c_low {float(crit):.4f}")
print("THE CROSSING-LED RUN")
grid = [Fr(230 + 5 * i, 100) for i in range(int((675 - 230) / 5) + 1)]
c_up, rows = None, []
for c in grid:
Yc = w.ystar(c)
esc, tide, seats = crossing_run(w, c, Yc)
rows.append((c, esc, tide, seats))
if esc:
c_up = c
break
for c, esc, tide, seats in rows[::max(1, len(rows) // 12)] + rows[-1:]:
print(f" c = {float(c):.2f}: {'ESCAPES' if esc else 'STUCK'} at "
f"tide {tide} after {seats} seats")
if c_up is not None:
print(f" P3 (guess) c_up < 6.7315: "
f"{'HOLDS' if c_up < cch else 'FAILS'}, c_up {float(c_up):.2f}")
print(f" P4 (guess) c_up <= 1.5 c_low: "
f"{'HOLDS' if c_up <= Fr(3, 2) * crit else 'FAILS'}, "
f"ratio {float(c_up / crit):.4f}")
print("READINGS")
log = []
esc, tide, seats = crossing_run(w, crit, w.ystar(crit), log)
print(f" the crossing-led run at c_low = {crit} itself: "
f"{'ESCAPES' if esc else 'STUCK'} at tide {tide} after {seats} "
f"seats")
held, worst, at, agree = set(), Fr(0), None, True
for m0, P in log:
m_full = cgreedy.m0({p: 1 for p in held})
agree = agree and m_full == m0
if Fr(P, w.Fx(m_full)) > worst:
worst, at = Fr(P, w.Fx(m_full)), (m_full, P)
held.add(P)
agree = agree and cgreedy.m0({p: 1 for p in held}) == tide
print(f" re-tided by cgreedy.m0 on the full factor map: "
f"{'AGREES' if agree else 'DIFFERS'} at all {len(log) + 1} states; "
f"largest seat / F(m0) {worst} = {float(worst):.6f}, within "
f"c_low: {worst <= crit}, at (tide, seat) {at}")
for a in (83, 167, 499, 1997):
reach = w.cap(lo, a)
anchors = [b for b in range(2 * a + 1, reach + 1, 2 * a) if w.S[b]]
print(f" Y*({a}) just below c_low: {Yl.get(a)}; its reach "
f"{reach}, the primes = 1 mod {a} within it {anchors}")
print("THE PRINT")
if c_up is None:
print(" KILL: NO CROSSING-LED RUN BELOW THE CHAIN-LED")
else:
print(f" c0 >= {crit}, PROVED BY THE CROSSING TEST; A "
f"c-RUN AT {float(c_up):.2f} REACHES TIDE 10^4")
if c_up / crit > 2:
print(" KILL: THE CROSSING TEST DOES NOT LOCATE c0")
print(f"{sum(ok for _, ok in CHECKS)}/{len(CHECKS)} checks passed, "
f"{time.time() - t0:.1f} s")
raise SystemExit(0 if all(ok for _, ok in CHECKS) else 1)
if __name__ == "__main__":
main()