Track odd-size universal trend; the n=12 failure is sporadic, not a trend

Add kempe_universal_trend_probe.py (|D[m]| per size across n). Across n=6..13 and
all sizes, the ONLY empty per-size universal is (n=12, m=7): at n=13 size 7 is back
to |D|=2 with more boundaries (579), so the vanishing is sporadic, not monotone.
The lone n=12 breaker is the outer rim of word=UUUDUDUDUDUD bite=(3,11) (most-
alternating 7-up word, antipodal bite), realising 9/10 size-7 necklaces and missing
only 0001112. Correct the earlier "doomed at scale" reading in the findings note:
the uniform shortcut almost always works (near-total coverage) but is fragile to a
single exceptional tile; pairwise gluability still always holds.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-11 23:40:48 -04:00
parent b1100b41d9
commit a724a50344
2 changed files with 135 additions and 14 deletions
@@ -56,23 +56,60 @@ cycle `σ_m` glues any tree with no pigeonhole.
Per-size universal domain sizes at n=12: `3:1 4:1 5:1 6:2 7:0 8:4 9:1`.
## Finding 3 — interpretation
## Finding 3 — the failure is SPORADIC, not a monotone trend
Universals vanish as the tile population grows (more boundaries of a given size → more
sets to intersect → empty), so the "paint every seam identically" shortcut is doomed
at scale; the per-interface pigeonhole choice is genuinely necessary. **But this is
not an obstruction to gluing** — pairwise overlap still always holds, so chains still
glue by choosing states per interface. We have *located why the conjecture is hard*:
the difficulty lives in the non-uniform, branch-coupled selection across the tree,
exactly where the paper's pigeonhole sits — not in any single seam or a uniform
assignment.
`kempe_universal_trend_probe.py` tracks `|D[m]|` (universal count) per size across
`n = 6..13`. Legend `|D[m]| (best_coverage / num_boundaries)`; `*` = odd size:
```
n= 6: m3*=1(6/6) m4=2(2/2) m6=4(1/1)
n= 7: m3*=1(10/10) m4=1(8/8) m5*=1(2/2) m7*=3(1/1)
n= 8: m3*=1(28/28) m4=2(21/21) m5*=1(10/10) m6=2(3/3) m8=8(1/1)
n= 9: m3*=1(49/49) m4=1(52/52) m5*=1(28/28) m6=1(14/14) m7*=2(3/3) m9*=8(1/1)
n=10: m3*=1(118) m4=2(106) m5*=1(86) m6=2(46) m7*=1(16/16) m8=4(4/4) m10=18(1/1)
n=11: m3*=1(310) m4=1(263) m5*=1(188) m6=1(139) m7*=2(60/60) m8=2(20/20) m9*=3(4/4) m11*=21(1/1)
n=12: m3*=1(849) m4=1(691) m5*=1(534) m6=2(353) m7*=0(210/211) m8=3(88) m9*=1(24/24) m10=6(5/5) m12=48(1/1)
n=13: m3*=1(2457) m4=1(1805) m5*=1(1386) m6=1(1070) m7*=2(579/579) m8=1(315) m9*=2(110) m10=1(28) m11*=7(5) m13*=63(1/1)
```
The earlier "universals vanish as the tile population grows" reading is **wrong**.
Across all `n = 6..13` and all sizes, the **only** empty universal anywhere is
`(n=12, m=7)`. Size 7 has *more* boundaries at n=13 (579) than n=12 (211), yet its
universal is back (`|D|=2`). So the failure is **sporadic**, not monotone — a
number-theoretic quirk of `n=12`, not a scaling law. Note also that best_coverage is
always near-total: the most-shared necklace reaches all-but-rarely-one boundary, so
the universal is "almost there" even when it fails.
### The single breaker (n=12, m=7)
The lone size-7 boundary that kills the universal is the **outer rim** of
```
word = UUUDUDUDUDUD bite = (3,11) (7 up teeth)
```
— the most-alternating word with a near-full-span bite. Its outer rim realises 9 of
the 10 admissible size-7 necklaces, missing exactly `0001112` (the balanced two-block
`3+3+1` pattern); every other size-7 boundary realises `0001112`. One exceptional tile
breaks the shortcut.
## Finding 4 — interpretation
The uniform "paint every seam the same" shortcut **almost always works** (universals
non-empty with near-total coverage, even at thousands of boundaries), but is
**fragile**: a single exceptional tile can empty a per-size universal, as at
`(n=12, m=7)`. So the shortcut cannot be relied on in general — yet its failures are
rare, not systematic. The per-interface pigeonhole choice is needed precisely to
absorb these sporadic breakers. **This is not an obstruction to gluing** — pairwise
overlap always holds, so chains still glue by choosing states per interface. The
conjecture's difficulty is thus concentrated in rare exceptional tiles and the
branch-coupled selection around them, not in any single seam or in a scaling trend.
## Open threads
- **Odd-size seams are the pressure point.** Uniformity first fails at size 7 (odd);
small odd sizes 3, 5 kept unique universals. Does every large odd size lose its
universal as `n` grows? (tracked below / in follow-up).
- **The 210/211 near-miss.** A single tile blocks the size-7 universal — identifying
the "universal-breaker" tiles may expose the combinatorial core.
- **Why n=12 / why this tile?** The breaker is the most-alternating 7-up word with an
antipodal bite. Is the sporadic failure tied to `n` even / specific bite spans?
Worth checking n=14, 16 for size-7 (and other) re-failures.
- **CSP at n=13.** With `|D[m]| > 0` for every size, the per-size obstruction is gone;
whether the joint uniform-family CSP is feasible again at n=13 needs a run.
- **Branch-tree composition.** n=12 has 175 true branching tiles; composing `R_T`
along actual trees (not just per-size uniformity) is the conjecture proper.
@@ -0,0 +1,84 @@
"""Do per-size universal boundary states survive as n grows?
For each annular size n and each boundary size m, D[m] is the set of boundary
necklaces realisable on EVERY size-m boundary (outer up-rim or inner >=3-singleton
face) across all tiles. |D[m]| > 0 means a uniform state of size m exists; |D[m]|=0
means no state threads every size-m seam (the uniform shortcut is dead at that size).
This tracks |D[m]| as a function of n, to see whether/when each size -- especially
odd sizes -- loses its universal. Also reports, per (n,m), the best coverage
(how many of the size-m boundaries the most-shared necklace reaches).
Run: python3 kempe_universal_trend_probe.py --min-n 6 --max-n 12
"""
from __future__ import annotations
import argparse
import sys
import time
from collections import defaultdict
from full_medial_tire_generator import generate, innermost_bite
from kempe_valid_colorings import classify_colorings
from kempe_transfer_relation_probe import necklace, admissible_necklaces
def per_size_universals(n: int):
"""size m -> (num boundaries, |D[m]|, best coverage count)."""
boundaries: dict[int, list[set]] = defaultdict(list)
for g in generate(n, min_up_teeth=3, dedup=True):
valid = [c for c, v in classify_colorings(g, dedup_colors=True) if v.valid]
if not valid:
continue
p = len(g.up_edges)
if p >= 3:
boundaries[p].append(
{necklace(tuple(c[f"u{e}"] for e in g.up_edges)) for c in valid})
faces = defaultdict(list)
for e in g.singleton_down_edges:
faces[innermost_bite(e, g.bites)].append(e)
for es in faces.values():
if len(es) >= 3:
es = sorted(es)
boundaries[len(es)].append(
{necklace(tuple(c[f"d{e}"] for e in es)) for c in valid})
out = {}
for m, sets in boundaries.items():
inter = set.intersection(*sets)
cnt: dict = defaultdict(int)
for s in sets:
for x in s:
cnt[x] += 1
best = max(cnt.values()) if cnt else 0
out[m] = (len(sets), len(inter), best)
return out
def run(args):
print("|D[m]| = number of universal boundary necklaces of size m "
"(0 => uniform shortcut dead at that size)\n")
print("legend per cell: |D[m]| (best_coverage/num_boundaries)\n")
for n in range(args.min_n, args.max_n + 1):
t0 = time.time()
res = per_size_universals(n)
dt = time.time() - t0
cells = []
for m in sorted(res):
nb, dsz, best = res[m]
tag = "*" if (m % 2 == 1) else " "
cells.append(f"m{m}{tag}={dsz}({best}/{nb})")
print(f"n={n:>2} [{dt:>4.0f}s]: " + " ".join(cells))
sys.stdout.flush()
print("\n(* = odd size)")
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--min-n", type=int, default=6)
parser.add_argument("--max-n", type=int, default=12)
run(parser.parse_args())
if __name__ == "__main__":
main()