Plot the n=12 size-7 universal breaker tile

Add plot_breaker_tile.py and figure for word=UUUDUDUDUDUD bite=(3,11): structure
(7 up teeth = size-7 outer rim, bite (3,11), singleton downs d5,d7,d9) plus a
Kempe-balanced colouring. Reconfirms the outer rim realises 9/10 admissible size-7
necklaces, never 0001112 -- the lone tile that empties the size-7 universal at n=12.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-11 23:51:36 -04:00
parent a724a50344
commit 1aa76a5226
3 changed files with 138 additions and 0 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

@@ -0,0 +1,138 @@
"""Plot the n=12 size-7 universal breaker tile: word=UUUDUDUDUDUD, bite=(3,11).
Left panel: structure (7 up teeth = the size-7 outer rim, ringed; the bite (3,11);
the singleton down teeth). Right panel: a Kempe-balanced colouring, with the outer
rim necklace it presents. This tile's outer rim realises 9 of the 10 admissible
size-7 necklaces but never 0001112, which is why it alone empties the size-7
universal at n=12.
"""
from __future__ import annotations
import math
import os
from full_medial_tire_generator import FullMedialTireGraph
from kempe_valid_colorings import classify_colorings
from kempe_up_tooth_sequences import PALETTE, _positions, canonical_sequence, seq_str
from kempe_transfer_relation_probe import necklace
HERE = os.path.dirname(os.path.abspath(__file__))
WORD = "UUUDUDUDUDUD"
BITE = frozenset({(3, 11)})
N = 12
TYPE_COLOR = {"a": "#999999", "u": "#e6550d", "d": "#31a354", "p": "#756bb1"}
def vtype(v):
return v[0]
def draw_structure(ax, g):
pos = _positions(g)
for u, v in g.edges():
ax.plot([pos[u][0], pos[v][0]], [pos[u][1], pos[v][1]],
color="#cccccc", lw=0.6, zorder=1)
for k in range(g.n):
a, b = f"a{k}", f"a{(k + 1) % g.n}"
ax.plot([pos[a][0], pos[b][0]], [pos[a][1], pos[b][1]],
color="#555555", lw=1.2, zorder=2)
# highlight the bite spokes
for i, j in g.bites:
apex = f"p{i}_{j}"
for e in (i, j):
for av in (f"a{e}", f"a{(e + 1) % g.n}"):
ax.plot([pos[apex][0], pos[av][0]], [pos[apex][1], pos[av][1]],
color="#756bb1", lw=1.6, zorder=2.5)
for v, (x, y) in pos.items():
t = vtype(v)
s = 90 if t in ("u", "p") else 60
ax.scatter([x], [y], s=s, color=TYPE_COLOR[t], edgecolors="black",
linewidths=0.6, zorder=3)
# ring the up-tooth apexes (the size-7 outer rim / boundary)
ux = [pos[f"u{i}"][0] for i in g.up_edges]
uy = [pos[f"u{i}"][1] for i in g.up_edges]
ax.scatter(ux, uy, s=240, facecolors="none", edgecolors="#d62728",
linewidths=1.8, zorder=4)
# label up apexes in boundary order 0..6
for k, i in enumerate(g.up_edges):
x, y = pos[f"u{i}"]
ax.annotate(str(k), (x, y), textcoords="offset points", xytext=(0, 9),
ha="center", fontsize=7, color="#d62728")
ax.set_xlim(-1.7, 1.7)
ax.set_ylim(-1.9, 1.7)
ax.set_aspect("equal")
ax.axis("off")
ax.set_title("structure: 7 up teeth (red-ringed = size-7 outer rim)\n"
"bite (3,11) in purple; singleton down teeth d5,d7,d9",
fontsize=8)
def draw_colored(ax, g, coloring):
pos = _positions(g)
for u, v in g.edges():
ax.plot([pos[u][0], pos[v][0]], [pos[u][1], pos[v][1]],
color="#cccccc", lw=0.6, zorder=1)
for k in range(g.n):
a, b = f"a{k}", f"a{(k + 1) % g.n}"
ax.plot([pos[a][0], pos[b][0]], [pos[a][1], pos[b][1]],
color="#555555", lw=1.2, zorder=2)
for v, (x, y) in pos.items():
is_bite = v.startswith("p")
ax.scatter([x], [y], s=80 if is_bite else 55, color=PALETTE[coloring[v]],
edgecolors="black", linewidths=0.5, zorder=3)
ux = [pos[f"u{i}"][0] for i in g.up_edges]
uy = [pos[f"u{i}"][1] for i in g.up_edges]
ax.scatter(ux, uy, s=240, facecolors="none", edgecolors="#222222",
linewidths=1.6, zorder=4)
raw = seq_str(tuple(coloring[f"u{i}"] for i in g.up_edges))
neck = seq_str(necklace(tuple(coloring[f"u{i}"] for i in g.up_edges)))
ax.set_xlim(-1.7, 1.7)
ax.set_ylim(-1.9, 1.7)
ax.set_aspect("equal")
ax.axis("off")
ax.set_title(f"a Kempe-balanced colouring\nouter rim = {raw} → necklace {neck}",
fontsize=8)
def main():
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
g = FullMedialTireGraph(n=N, tooth_word=WORD, bites=BITE)
# confirm: outer rim realises 9/10 admissible necklaces, never 0001112
realized = set()
sample = None
for c, v in classify_colorings(g, dedup_colors=True):
if not v.valid:
continue
nk = necklace(tuple(c[f"u{i}"] for i in g.up_edges))
realized.add(nk)
if sample is None:
sample = c
target = necklace(tuple(map(int, "0001112")))
print(f"breaker {WORD} bite (3,11): outer rim realises {len(realized)} necklaces")
print(f" contains 0001112? {target in realized} (expect False)")
fig, axes = plt.subplots(1, 2, figsize=(10, 5.4))
draw_structure(axes[0], g)
draw_colored(axes[1], g, sample)
fig.suptitle(
"Size-7 universal breaker (n=12): word=UUUDUDUDUDUD, bite=(3,11)\n"
"outer rim realises 9 of 10 admissible size-7 necklaces — never 0001112",
fontsize=11, y=0.99,
)
fig.tight_layout(rect=(0, 0, 1, 0.93))
png = os.path.join(HERE, "breaker_tile_n12.png")
pdf = os.path.join(HERE, "breaker_tile_n12.pdf")
fig.savefig(png, dpi=200)
fig.savefig(pdf)
print(f"wrote {png}")
print(f"wrote {pdf}")
if __name__ == "__main__":
main()