Isolate the irreducible case: reduces the floor proof to one lemma
irreducible_floor.py: over 10k+ irreducible disks (k>=1, min interior degree >=4), |Phi| never violates 2^(n-2) and never sits on it -- min is 5*2^(n-4) = (5/4)2^(n-2), the wheel being the minimizer. Universal toggles are dead (99.9% have zero boundary-only faces). Since un-stacking degree-3 vertices preserves Phi and terminates at a k=0 or irreducible residue, the whole lower bound reduces to: every irreducible disk has |Phi| >= 2^(n-2). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+134
@@ -0,0 +1,134 @@
|
||||
"""
|
||||
The open case for the 2^(n-2) lower bound is the IRREDUCIBLE disk: k>=1 interior
|
||||
vertices, all of degree >=4 (un-stacking already settles everything reducible to
|
||||
a degree-3 vertex). This probe isolates irreducible disks and asks:
|
||||
|
||||
(a) does the floor |Phi| >= 2^(n-2) hold there (it must, but it's the open case);
|
||||
(b) is it STRICT (|Phi| > 2^(n-2)) -- if irreducible disks never sit ON the floor,
|
||||
the proof only needs ">= floor" via "any nontrivial slack";
|
||||
(c) how many UNIVERSAL toggles each has -- a "boundary-only" face (all 3 vertices
|
||||
on C) can be flipped feasibly regardless of the labelling, giving a guaranteed
|
||||
doubling. n-2 independent ones would prove the bound outright. We count them
|
||||
to see whether universal toggles alone can carry the irreducible case (a wheel
|
||||
has zero, so we expect NOT).
|
||||
"""
|
||||
|
||||
import sys
|
||||
from collections import Counter
|
||||
from itertools import product
|
||||
|
||||
import numpy as np
|
||||
from scipy.spatial import Delaunay
|
||||
|
||||
np.seterr(all="ignore")
|
||||
|
||||
|
||||
def disk(n, k, rng):
|
||||
ang = 2 * np.pi * np.arange(n) / n
|
||||
rad = 1.0 + 0.18 * rng.random(n)
|
||||
bpts = np.c_[rad * np.cos(ang), rad * np.sin(ang)]
|
||||
r = 0.78 * np.sqrt(rng.random(k)); t = 2 * np.pi * rng.random(k)
|
||||
pts = np.vstack([bpts, np.c_[r * np.cos(t), r * np.sin(t)]])
|
||||
return [tuple(int(x) for x in s) for s in Delaunay(pts).simplices]
|
||||
|
||||
|
||||
def valid(faces, n, k):
|
||||
if len(faces) != 2 * k + n - 2:
|
||||
return False
|
||||
ec = Counter()
|
||||
for a, b, c in faces:
|
||||
for e in ((a, b), (b, c), (a, c)):
|
||||
ec[frozenset(e)] += 1
|
||||
return all(ec[frozenset((i, (i + 1) % n))] == 1 for i in range(n))
|
||||
|
||||
|
||||
def interior_degrees(faces, n):
|
||||
deg = Counter()
|
||||
for f in faces:
|
||||
for v in f:
|
||||
if v >= n:
|
||||
deg[v] += 1
|
||||
return deg
|
||||
|
||||
|
||||
def phi(faces, n):
|
||||
interior = sorted(v for f in faces for v in f if v >= n)
|
||||
interior = sorted(set(interior))
|
||||
F = len(faces)
|
||||
if F > 18:
|
||||
return None
|
||||
Bint = np.zeros((len(interior), F), dtype=np.int64)
|
||||
Cinc = np.zeros((n, F), dtype=np.int64)
|
||||
iidx = {w: r for r, w in enumerate(interior)}
|
||||
for j, (a, b, c) in enumerate(faces):
|
||||
for v in (a, b, c):
|
||||
if v >= n:
|
||||
Bint[iidx[v], j] = 1
|
||||
else:
|
||||
Cinc[v, j] = 1
|
||||
labs = np.array(list(product((1, 2), repeat=F)), dtype=np.int64)
|
||||
if interior:
|
||||
labs = labs[np.all((labs @ Bint.T) % 3 == 0, axis=1)]
|
||||
if labs.shape[0] == 0:
|
||||
return set()
|
||||
return set(map(tuple, np.unique((labs @ Cinc.T) % 3, axis=0)))
|
||||
|
||||
|
||||
def boundary_only_faces(faces, n):
|
||||
return sum(1 for (a, b, c) in faces if a < n and b < n and c < n)
|
||||
|
||||
|
||||
def main():
|
||||
seed = int(sys.argv[1]) if len(sys.argv) > 1 else 0
|
||||
rng = np.random.default_rng(seed)
|
||||
by_n = {}
|
||||
n_irred = 0
|
||||
floor_fail = 0
|
||||
on_floor = 0 # irreducible AND exactly at 2^(n-2)
|
||||
bof_ge = 0 # irreducible with >= n-2 boundary-only faces
|
||||
bof_zero = 0
|
||||
min_bof = 99
|
||||
|
||||
for _ in range(6000):
|
||||
n = int(rng.integers(4, 7)); k = int(rng.integers(1, 4))
|
||||
faces = disk(n, k, rng)
|
||||
if not valid(faces, n, k) or len(faces) > 16:
|
||||
continue
|
||||
deg = interior_degrees(faces, n)
|
||||
if any(deg[v] < 4 for v in deg) or len(deg) < k:
|
||||
continue # reducible (has a degree-3 vertex)
|
||||
P = phi(faces, n)
|
||||
if P is None or not P:
|
||||
continue
|
||||
n_irred += 1
|
||||
floor = 2 ** (n - 2)
|
||||
if len(P) < floor:
|
||||
floor_fail += 1
|
||||
if len(P) == floor:
|
||||
on_floor += 1
|
||||
bof = boundary_only_faces(faces, n)
|
||||
min_bof = min(min_bof, bof)
|
||||
bof_ge += (bof >= n - 2)
|
||||
bof_zero += (bof == 0)
|
||||
d = by_n.setdefault(n, {"cnt": 0, "min": 10**9, "floor": floor})
|
||||
d["cnt"] += 1
|
||||
d["min"] = min(d["min"], len(P))
|
||||
|
||||
print(f"irreducible disks (k>=1, all interior degree >=4): {n_irred}\n")
|
||||
for n in sorted(by_n):
|
||||
d = by_n[n]
|
||||
print(f" n={n}: {d['cnt']:5d} disks min|Phi|={d['min']} "
|
||||
f"2^(n-2)={d['floor']} floor-held={d['min']>=d['floor']}")
|
||||
print(f"\n floor violations (|Phi| < 2^(n-2)) : {floor_fail}")
|
||||
print(f" irreducible disks sitting ON the floor: {on_floor} "
|
||||
f"(if 0, irreducible => strictly above floor)")
|
||||
print(f" universal toggles (boundary-only faces):")
|
||||
print(f" >= n-2 such faces : {bof_ge}/{n_irred}")
|
||||
print(f" exactly 0 : {bof_zero}/{n_irred} (min over all = {min_bof})")
|
||||
print(" => universal toggles alone "
|
||||
+ ("CAN" if bof_zero == 0 else "CANNOT")
|
||||
+ " carry the irreducible case.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user