Pin the extremal irreducible disk (correcting the wheel claim)

wheel_extremal.py: |Phi(wheel_n)| = floor(2^n/3) exactly (ratio ->4/3),
but the wheel is NOT the irreducible minimiser for n>=6. The extremal disk
is a single MINIMAL-degree interior vertex (degree 4 or 5, both tie),
giving |Phi| = (5/4)*2^(n-2) = 5*2^(n-4). The ratio rises monotonically
with center degree, 5/4 -> 4/3, so minimal degree is extremal. Sharpens
the irreducible lemma to |Phi| >= (5/4)*2^(n-2), tight at the degree-4/5
patch.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-17 20:14:52 -04:00
parent bd8499a25b
commit 24a3d89d88
@@ -0,0 +1,154 @@
"""
Pin the extremal irreducible disk.
The wheel W_n: boundary n-cycle + one center, faces (i,i+1,c). The center is the
only interior vertex (degree n), constraint sum_i lambda_i ≡ 0 (mod 3), and the
boundary value is the cyclic adjacent sum sigma_i = lambda_{i-1}+lambda_i (mod 3).
So
|Phi(W_n)| = #{ (lambda_{i-1}+lambda_i)_i mod 3 : lambda in {+-1}^n, sum ≡ 0 } .
We (1) compute |Phi(W_n)| exactly for a range of n and look for a formula, and
(2) run a thorough irreducible-disk search to check whether the wheel is actually
the MINIMISER over irreducible disks (and dump the minimiser's structure).
"""
import sys
from collections import Counter
from itertools import product
import numpy as np
from scipy.spatial import Delaunay
np.seterr(all="ignore")
# ---------------- exact wheel value ------------------------------------------
def wheel_phi_size(n):
S = set()
cnt = 0
for lam in product((1, -1), repeat=n):
if sum(lam) % 3 != 0:
continue
cnt += 1
sig = tuple((lam[i - 1] + lam[i]) % 3 for i in range(n))
S.add(sig)
return len(S), cnt # distinct boundary seqs, feasible labellings
# ---------------- general disk Phi -------------------------------------------
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.8 * 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 phi_size(faces, n):
interior = sorted(set(v for f in faces for v in f if v >= n))
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 0
return len(set(map(tuple, np.unique((labs @ Cinc.T) % 3, axis=0))))
def min_degree_ok(faces, n, k):
deg = Counter()
for f in faces:
for v in f:
if v >= n:
deg[v] += 1
return len(deg) == k and all(deg[v] >= 4 for v in deg)
def single_deg_disk(n, d):
"""One interior vertex v=n of degree d: fan over boundary 0..d-1, the rest of
the n-gon polygon-triangulated from vertex 0 (so v stays degree d, k=1)."""
v = n
faces = [(i, i + 1, v) for i in range(d - 1)]
poly = [0] + list(range(n - 1, d - 2, -1)) + [v]
for j in range(1, len(poly) - 1):
faces.append((0, poly[j], poly[j + 1]))
return faces
def degree_sweep():
print("\n|Phi| of a single degree-d interior vertex (rest at the floor):\n")
print(" ratio |Phi|/2^(n-2) by center degree d -- MINIMUM marks the extremal disk")
for n in (6, 7, 8):
row = []
for d in range(4, n + 1):
f = single_deg_disk(n, d)
row.append(f"d={d}:{phi_size(f, n)/2**(n-2):.4f}")
print(f" n={n} (floor {2**(n-2)}): " + " ".join(row))
print(" => min ratio 5/4 at d=4,5 (extremal); rises with d to ~4/3 at the wheel.")
def main():
print("Exact |Phi(W_n)| and candidate formula:\n")
print(" n |Phi(W_n)| feasible-labellings ratio-to-2^(n-2)")
vals = {}
for n in range(3, 15):
s, cnt = wheel_phi_size(n)
vals[n] = s
print(f" {n:2d} {s:8d} {cnt:14d} {s / 2**(n-2):.4f}")
# differences / ratios to spot a pattern
print("\n consecutive ratios |Phi(W_{n+1})| / |Phi(W_n)|:")
for n in range(3, 14):
print(f" {n}->{n+1}: {vals[n+1]/vals[n]:.4f}")
print("\nThe actual irreducible minimiser (Delaunay search, dumping structure)\n")
rng = np.random.default_rng(0)
for n in (4, 5, 6, 7):
best = 10**9; bestdeg = None; bestk = None
for _ in range(12000):
k = int(rng.integers(1, 4))
faces = disk(n, k, rng)
if not valid(faces, n, k) or len(faces) > 16:
continue
if not min_degree_ok(faces, n, k):
continue
s = phi_size(faces, n)
if s and s < best:
best = s
deg = Counter()
for f in faces:
for v in f:
if v >= n:
deg[v] += 1
bestdeg = sorted(deg.values()); bestk = k
floor = 2 ** (n - 2)
print(f" n={n}: min irreducible |Phi|={best} (k={bestk}, interior degrees "
f"{bestdeg}) ratio to floor = {best/floor:.4f} "
f"5*2^(n-4)={5*2**(n-4)} wheel={vals[n]}")
degree_sweep()
if __name__ == "__main__":
main()