Find smallest n admitting branching tiles (n=11 unrestricted, n=14 no-tri)

Add kempe_branching_min_probe.py (structural: >=2 inner faces with singletons).
Unrestricted branching first appears at n=11; no-separating-triangle branching
(>=2 inner faces each >=4 singletons, p>=4) first appears at n=14 (193 tiles).
Smallest example: word=UUUUDDDDDDDDDD bite=(8,13), p=4, faces root{4,5,6,7} and
bite{9,10,11,12}. n=14 is the smallest place to test the uniform family / R_T
composition on a genuine branching no-separating-triangle tile.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-12 00:31:19 -04:00
parent bacbdaaf26
commit 2b016bc1ca
2 changed files with 99 additions and 6 deletions
@@ -138,12 +138,42 @@ Caveat: even at n=12 the restricted population has **0 branching tiles** (multi-
faces all require a size-3 face at this n), so the branching case stays untested under
the restriction; and this is `n ≤ 13` only.
## Finding 6 — smallest branching n (`kempe_branching_min_probe.py`)
Branching tile = `≥2` inner faces carrying singleton-down interfaces (a tree node with
`≥2` children).
```
n #tiles branching no-tri branching
9 81 0 0
10 203 0 0
11 503 30 0 <- unrestricted branching first appears
12 1344 175 0
13 3586 789 0
14 9929 3024 193 <- no-separating-triangle branching first appears
15 27481 10538 1022
```
- Unrestricted branching first appears at **n=11**.
- No-separating-triangle branching first appears at **n=14**. Smallest example:
```
word = UUUUDDDDDDDDDD bite = (8,13) p = 4
inner faces: root {4,5,6,7} (size 4) + bite(8,13) {9,10,11,12} (size 4)
```
4 up teeth, two size-4 inner faces — branching, no length-3 boundary. (Reason for the
gap: a branching node needs `≥2` inner faces each `≥4` singletons plus `≥4` up teeth
plus the bite pair = `4 + 4 + 4 + 2 = 14` edges.)
So **n=14** is the smallest place to test the uniform family / `R_T` composition on a
genuine *branching* no-separating-triangle tile — the conjecture's real case.
## Open threads
- **Branching under the restriction.** No-separating-triangle branching tiles need
larger `n` (every inner face ≥ 4). Find the smallest `n` that has them and test the
uniform family there — the genuine conjecture case.
- **Does the restricted uniform family persist?** It holds for `n ≤ 13`; a single
later failure (as in the unrestricted n=12 case) would be very informative. Push to
n=14, 16.
- **Test the uniform family at n=14 (restricted).** The first branching tiles live
here; does `monochromatic-even / min-cut-odd` still thread them (now with 2 inner
faces forced simultaneously)? This is the genuine conjecture case.
- **Does the restricted uniform family persist past n=13?** A single later failure
(as in the unrestricted n=12 case) would be very informative.
- **`R_T` composition along real trees** rather than per-size uniformity.
@@ -0,0 +1,63 @@
"""Smallest n admitting a BRANCHING tile (>=2 inner faces carrying interfaces),
both unrestricted and under the no-separating-triangle restriction.
A branching tile is a tree node with >=2 children: >=2 inner non-tooth faces each
holding singleton down teeth. Under "no separating triangle" we additionally forbid
any length-3 boundary (outer p=3, or an inner face with exactly 3 singletons), so
every inner face must have >=4 singletons and p>=4.
Purely structural (face singleton counts) -- no colouring enumeration.
Run: python3 kempe_branching_min_probe.py --min-n 9 --max-n 16
"""
from __future__ import annotations
import argparse
import sys
import time
from collections import defaultdict
from full_medial_tire_generator import generate, innermost_bite
def inner_face_sizes(g):
faces = defaultdict(int)
for e in g.singleton_down_edges:
faces[innermost_bite(e, g.bites)] += 1
return [c for c in faces.values() if c >= 3]
def run(args):
print("smallest n with branching tiles (>=2 inner faces holding singletons)\n")
print(f"{'n':>3} {'#tiles':>8} {'branching':>10} {'no-tri branch':>14} example (no-tri branching)")
print("-" * 78)
for n in range(args.min_n, args.max_n + 1):
t0 = time.time()
ntiles = nbr = nbr_notri = 0
example = None
for g in generate(n, min_up_teeth=3, dedup=True):
ntiles += 1
sizes = inner_face_sizes(g)
if len(sizes) >= 2:
nbr += 1
p = len(g.up_edges)
if p >= 4 and all(s >= 4 for s in sizes):
nbr_notri += 1
if example is None:
bites = ",".join(f"({i},{j})" for i, j in sorted(g.bites))
example = f"word={g.tooth_word} bites={bites} p={p} faces={sorted(sizes)}"
dt = time.time() - t0
print(f"{n:>3} {ntiles:>8} {nbr:>10} {nbr_notri:>14} {example or '-'} [{dt:.0f}s]")
sys.stdout.flush()
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--min-n", type=int, default=9)
parser.add_argument("--max-n", type=int, default=16)
run(parser.parse_args())
if __name__ == "__main__":
main()