anchor.py
Checks: IMAGE: Polynomial slack reaches breadth from the void theorem; rule.
Cited on: IMAGE.
To run it: save anchor.py, with bridges.py, cgreedy.py, choosy.py, dambar.py, envelope.py, fwide.py, growth.py, slack.py beside it; standard library only.
"""anchor.py -- does a run that chooses its seats by their anchors stay
below the record run against the dam's bar F?
QUESTION. E/F peaks at 7.6829 at t = 1997 (fwide.py), where the record
and the skipping run both pay p(1997) = 87869. Does a run that weighs
each seat by the anchor it will owe stay below that peak?
DESIGN. choosy.py's engine and tide: one odd prime per move, exponent 1,
2 never seated, read until the tide m0 passes 10^4. F from fwide.py's
widened table, fixed at every t in 4..10^4, read at max(t, 4). At each
move the class is the primes = 1 mod s, s the tide's unborn power (m0 at
a seated r, m0/r at a skipped one, m0/4 at 2, m* at an open r, m* the
part of r - 1 not dividing lambda); every class prime is past m0 (one
below would be open, priced under m0), and at an open r the least is r.
L1 seats the class prime with least p(P), ties to the least P; the
candidates are the class primes below p(P0), P0 the least.
LV seats the class prime with least max(P/F(m0), V(P)), ties to the
least P; candidates until P/F(m0) reaches the best score.
(a) THE ANCHOR BAR, by hand: the tide never falls, since lambda only
grows, so no other price falls, and the seat's new price is at least
P >= m0. Every
seat P raises lambda, so it was priced at most P and came from a tide
<= P. If no held prime is 1 mod P,
the price at P is P and the tide stays at most P until one enters, at
least p(P) (if none ever does, the run's endless new primes all come
from a tide <= P, the run being endless); if one is held, it entered from a tide <= P. So E_run(P) >=
p(P) at every seat P.
(b) By hand: at the skipping run's tide-167 state (m* = 83) the class
is 167, 499, 997, ...; p(167) = 2339, p(499) = 1997, and every class
prime from 997 on has p(P) > 1997; L1 seats 499, whose anchor is 1997,
whose anchor is p(1997) = 87869.
(c) The chain value: V(q) = min over primes a = 1 mod q of
max(a/F(q), V(a)), V(q) = 0 past 10^4. An anchor a of q comes from a
tide <= q, so a/F(q) <= E_run(q)/F(q) along the chain a run follows.
PREDICTIONS (frozen before the code).
P1 (forced) the engine under choosy's arms A and B gives their seats.
P2 (proved, (a)) E_run(P) >= p(P) at every seat P <= 10^4, both arms.
P3 (proved) F <= E_run at every t in 4..10^4, both arms.
P4 (a guess, 65%) L1 has E(1997) = 87869 or max E/F >= 7.6829.
P5 (a guess, 55%) LV has max E/F < 7.6829 and E(1997) < 87869.
THE PRINT. Per arm: max E_run/F over 4..10^4 with its t, and
E_run(1997). "ANCHOR CHOICE MOVES THE PRICE: <arms>" for the arms with
max E_run/F below the record run's and E_run(1997) < 87869, else
"KILL: NO ARM BELOW THE RECORD RUN". The second clause is implied by
the first, p(1997)/F(1997) being the record run's peak itself.
CONTROLS, read first. C1 is P1 (and arm A's envelope is E). C2 L1's
chooser at the skipping run's tide-167 state seats 499, by (b). C3 the
kill's reading passes F and fails F planted at 8 F at one t. C4 P2's
test flags E_run lowered to p(P) - 1 at one seat P.
FINDINGS (from the printed run; the controls passed first). C1: the
engine gives choosy's arm A (519 seats) and arm B (425) exactly, and
arm A's envelope is E. C2: m* = 83, L1 seats 499. P2 and P3 hold on both
arms. P4 holds: L1's max E_run/F is 22.0322 at t = 1319 (E_run 129263 =
98 * 1319 + 1, F 5867), E_run(1997) 129263; it never seats 1997.
P5 holds: LV's max E_run/F is 6.7315 at t = 361 (E_run 10831, F 1609),
E_run(1997) = 14591; it never seats 1997. THE PRINT: ANCHOR CHOICE
MOVES THE PRICE: LV; the kill is silent.
LV: 417 seats, 175 held primes <= 10^4, 242 seats past 10^4, the
largest 153757. L1: 470 seats, 257 held primes <= 10^4. Five dear
primes q <= 10^4 have p(q)/F(q) >= 7.6829: 1997, 2053, 5227, 5641, 6637.
V(1997) = 7.6829, V(499) = 4.7881, V(167) = 3.6376.
Readings added after the first run: LV = F at 1491 t in 4..10^4, 1458 of
them >= 100, every t in 8543..10^4: at tide 8543 (open, m* = 4271) LV
seats 153757 = 36 * 4271 + 1, which is F(8543), F(8542) being 121697.
E_LV/F over t >= 100 has median 2.0702; E_LV < E at 9317 t and > E at
28 t in 4..10^4. LV misses F first at 7, 8, 9, 10, 17.
Readings added after the second run: L1 never stands at the open 167 of
(b) (open at 167: False); its peak is another failure, at tide 1319 (seated,
s = 1319) it seats 129263, p(P) = 258527, over the least class prime
23743, p(P0) = 284917: least p(P) overpays the seat to cheapen the next
anchor. Added with the second audit: E, E_B and E_LV are all above F
first at t = 25 (then 26..29), at 8492 t in 4..10^4; below 25 one of
them meets F at every t.
So a run choosing each seat by the chain of anchors it will owe stays
within 6.7315 F to 10^4, below the record run's 7.6829, and meets F
at 1491 of the 9997 t: there the least envelope over escaping runs
is F itself (LV, continued past its tide 10^4 by the record rule,
seating the least open prime r, from a tide <= r, keeps its tide
nondecreasing by (a) and a new prime at every move, so escapes; moves
from tides past t do not count at t).
RUN RECORD. First run: the dear-prime reading read F at q = 3, where it
is unset, and was given F(max(q, 4)), the prints above it unchanged.
10/10, 37.3 s, 60.5 MB. With the readings: 10/10, 37.2 s, 60.4 MB.
P1 and C3 as frozen read the record policy's E and an arm planted at
8 F; before the first run they became choosy's arms A and B and F
planted at 8 F, each at least as strict. With the last readings, the
monotone tide in (a) and the guard on LV's top run: 10/10, 37.3 s,
60.4 MB. With the second audit's reading: 10/10, 36.9 s, 61.5 MB.
Run from code/: 10/10, 40.4 s, 60.4 MB.
python anchor.py
"""
import os
import time
os.environ.setdefault("OPENBLAS_NUM_THREADS", "1")
import growth # noqa: E402
import envelope as ev # noqa: E402
import choosy # noqa: E402
import dambar # noqa: E402
import fwide # 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 isp(n):
return ev.SPF[n] == n if n <= ev.N else growth.is_prime(n)
def cls(s):
"""The primes = 1 mod s, increasing."""
n = s + 1
while True:
if isp(n):
yield n
n += s
def modulus(m0, r, kind, vN):
if kind == "seated":
return m0
if kind == "skipped":
return m0 // r
if kind == "two":
return m0 // 4
ms = 1
for q, e in ev.fac(r - 1).items():
if e > vN.get(q, 0):
ms *= q ** e
return ms
def make_v(F):
memo = {}
def V(q):
if q > T:
return 0.0
if q not in memo:
best = None
for a in cls(q):
x = a / F[max(q, 4)]
if best is not None and x >= best:
break
v = max(x, V(a))
if best is None or v < best:
best = v
memo[q] = best
return memo[q]
return V
def pick_a(m0, r, kind, s, F, V):
return next(cls(s))
def pick_b(m0, r, kind, s, F, V):
g = cls(s)
P = next(g)
return next(g) if kind == "open" else P
def pick_l1(m0, r, kind, s, F, V):
best = None
for P in cls(s):
if best is not None and P >= best[0]:
break
key = (ev.p_of(P), P)
if best is None or key < best:
best = key
return best[1]
def pick_lv(m0, r, kind, s, F, V):
f = F[max(m0, 4)]
best = None
for P in cls(s):
if best is not None and P / f >= best[0]:
break
key = (max(P / f, V(P)), P)
if best is None or key < best:
best = key
return best[1]
def run(pick, F, V, stop=None, log=None):
"""[(m0, seat)] until m0 > T; with stop=(m0, kind), the state
(held, vN, r, s) at the first tide matching it instead; log gathers
(m0, kind, s) per move."""
held, vN, pairs = set(), {}, []
while True:
m0, r, kind = choosy.tide(held, vN)
if m0 > T:
return pairs
s = modulus(m0, r, kind, vN)
if stop and (m0, kind) == stop:
return held, vN, r, s
P = pick(m0, r, kind, s, F, V)
if log is not None:
log.append((m0, kind, s))
assert P not in held and P > 2 and (P - 1) % s == 0
pairs.append((m0, P))
held.add(P)
for q, e in choosy.factor(P - 1).items():
if e > vN.get(q, 0):
vN[q] = e
def main():
t0 = time.time()
fwide.widen(fwide.PMAX)
F = dambar.f_table(fwide.tau_wide(fwide.PMAX, T))
ts = range(4, T + 1)
assert all(F[t] is not None for t in ts)
print(f"F fixed on 4..{T} ({time.time() - t0:.1f} s)")
V = make_v(F)
epairs, _, _, _ = ev.record_run()
E = ev.hull([(m, R) for m, R, _ in epairs])
rec = max(E[t] / F[t] for t in ts)
p1997 = ev.p_of(1997)
def passes(Ex):
return max(Ex[t] / F[t] for t in ts) < rec and Ex[1997] < p1997
def p2_bad(Ex, seats):
return [P for P in seats if P <= T and Ex[P] < ev.p_of(P)]
print("CONTROLS")
out = {}
for name, pick in (("A", pick_a), ("B", pick_b)):
mine = run(pick, F, V)
theirs, _ = choosy.run(name)
out[name] = mine
check(f"C1 the engine under arm {name} gives choosy's seats",
mine == theirs, f"{len(mine)} seats, {len(theirs)} choosy's")
EA = ev.hull(out["A"])
check("C1 arm A's envelope is E at every t <= 10^4",
all(EA[t] == E[t] for t in range(T + 1)))
held, vN, r, s = run(pick_b, F, V, stop=(167, "open"))
got = pick_l1(167, r, "open", s, F, V)
check("C2 L1 at the skipping run's tide-167 state seats 499",
got == 499 and s == 83, f"m* = {s}, seat {got}")
plant = list(F)
plant[500] = 8 * F[500]
check("C3 the kill's reading passes F and fails F planted at 8 F",
passes(F) and not passes(plant), f"record bar {rec:.4f}")
seats = [P for _, P in out["A"]]
Pp = max(P for P in seats if P <= T)
plant = list(EA)
plant[Pp] = ev.p_of(Pp) - 1
check("C4 P2's test flags E_run lowered to p(P) - 1 at one seat",
Pp in p2_bad(plant, seats) and not p2_bad(EA, seats),
f"P = {Pp}")
if not all(ok for _, ok in CHECKS):
print("CONTROL FAILED: nothing below is read.")
raise SystemExit(1)
print("THE ARMS")
res = {}
for name, pick in (("L1", pick_l1), ("LV", pick_lv)):
t1 = time.time()
log = []
pairs = run(pick, F, V, log=log)
Ex = ev.hull(pairs)
seats = [P for _, P in pairs]
res[name] = (pairs, Ex, log)
bad = p2_bad(Ex, seats)
check(f"P2 {name}: E_run(P) >= p(P) at every seat P <= {T}",
not bad, f"{len(bad)} off {bad[:3]}")
under = [t for t in ts if Ex[t] < F[t]]
check(f"P3 {name}: F <= E_run on 4..{T}", not under,
f"{len(under)} off {under[:3]}")
print(f" {name}: {len(pairs)} seats, "
f"{sum(P <= T for P in seats)} held primes <= {T}, "
f"E_run({T})/F {Ex[T] / F[T]:.4f} ({time.time() - t1:.1f} s)")
if 1997 in seats:
i = seats.index(1997)
print(f" {name}: 1997 seated at move {i} from tide "
f"{pairs[i][0]}")
print("READINGS")
dear = [q for q in ev.PRIMES if 3 <= q <= T
and ev.p_of(q) / F[max(q, 4)] >= rec]
print(f" dear primes (p(q)/F(q) >= {rec:.4f}), q <= {T}: "
f"{len(dear)}, first {dear[:8]}")
print(f" V(1997) {V(1997):.4f}, V(499) {V(499):.4f}, "
f"V(167) {V(167):.4f}")
# added after the first run: where LV meets F, LV against E, and
# LV's seat at the tide where F takes its last jump
pairs, Ex, log = res["LV"]
eq = [t for t in ts if Ex[t] == F[t]]
top = T if Ex[T] == F[T] else T + 1
while top > 4 and Ex[top - 1] == F[top - 1]:
top -= 1
print(f" LV = F at {len(eq)} t in 4..{T}, {sum(t >= 100 for t in eq)}"
f" of them >= 100, every t in "
+ (f"{top}..{T}" if top <= T else "none at the top"))
r = sorted(Ex[t] / F[t] for t in ts if t >= 100)
print(f" E_LV/F over t >= 100: median {r[len(r) // 2]:.4f}; E_LV < E at"
f" {sum(Ex[t] < E[t] for t in ts)} t, > E at "
f"{sum(Ex[t] > E[t] for t in ts)} t in 4..{T}")
for (m0, kind, s), (_, P) in zip(log, pairs):
if m0 == top:
print(f" LV at tide {m0} ({kind}, s = {s}) seats {P} = "
f"{(P - 1) // s} s + 1; F({m0 - 1}) {F[m0 - 1]}, "
f"F({m0}) {F[m0]}")
print(f" LV seats past {T}: {sum(P > T for _, P in pairs)}, largest "
f"{max(P for _, P in pairs)}")
print(f" LV misses F first at {[t for t in ts if Ex[t] != F[t]][:5]}")
# added with the second audit: where no run read here meets F
EB = ev.hull(out["B"])
none = [t for t in ts if min(E[t], EB[t], Ex[t]) > F[t]]
print(f" E, E_B and E_LV all above F first at {none[:5]}; "
f"{len(none)} t in 4..{T}")
# added after the second run: what L1 seats at its peak, against the least
# class prime there, and whether it ever stands at an open 167
pairs, Ex, log = res["L1"]
tm = max(ts, key=lambda t: Ex[t] / F[t])
for (m0, kind, s), (_, P) in zip(log, pairs):
if P == Ex[tm]:
P0 = next(cls(s))
print(f" L1 at tide {m0} ({kind}, s = {s}) seats {P}, p(P) "
f"{ev.p_of(P)}; least class prime {P0}, p(P0) "
f"{ev.p_of(P0)}")
print(f" L1 seats 167: {167 in [P for _, P in pairs]}; open at 167: "
f"{(167, 'open') in [(m, k) for m, k, _ in log]}")
print("THE PRINT")
ok = []
for name in ("L1", "LV"):
Ex = res[name][1]
tm = max(ts, key=lambda t: Ex[t] / F[t])
print(f" {name}: max E_run/F {Ex[tm] / F[tm]:.4f} at t = {tm} "
f"(E_run {Ex[tm]}, F {F[tm]}); E_run(1997) {Ex[1997]}")
if passes(Ex):
ok.append(name)
print(" " + (f"ANCHOR CHOICE MOVES THE PRICE: {', '.join(ok)}" if ok
else "KILL: NO ARM BELOW THE RECORD RUN"))
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()