coloring_nested_tire_graphs: cycle sources, tire-tree decomposition, seam lemma

Definition 1.1 (Level source) is broadened: a level source is now a set
that is either a single vertex or a simple cycle, splitting the old
notion into 'vertex source' and 'cycle source'.  Downstream theorems
(Prop 1.7, Lemma 1.8, Thm 1.17) remain stated for vertex sources but
are referenced by the new material with cycle sources.

New Theorem 1.19 (Tire-tree decomposition): for any tread T in
T(G, {v_0}) at depth d >= 1 with outer cycle C_T, the sub-graph G_T
inside C_T on the side away from v_0 is a triangulated disk; taking
C_T as a cycle source, T(G_T, C_T) is canonically iso to the
sub-tree of T(G, {v_0}) rooted at T.  Proof in three steps:
(D1) triangulated-disk via Jordan curve, (D2) level-shift
ell_{G_T}(.) = ell_G(.) - d via shortest-path stays in R_T, (D3)
component-of-G'_k bijection with descendants of T.

Figure fig_tire_tree_decomposition.png (and its generator
experiments/draw_tire_tree_decomposition.py) illustrates the
decomposition on a 13-vertex, 5-level example with four nested seams
C_{T_R}, C_{T_L}, C_{T_{LL}}, C_{T_{LLL}}; the generator script
verifies the level-shift assertion on this instance.  Vertex
positions are hand-tuned in TikZiT and copied back; the right-panel
labels are rotated relative to the parent G to emphasise the new
role of C_{T_L} as cycle source.

New Definition 1.21 (Seam): a seam is the outer-boundary cycle
B_out^{(T)} of a non-root tread T, separating G into the seam
interior G_T and seam exterior G_C^{ext}.  Notation Col(X | C) for
boundary-restricted 4-colourings is also defined here.

New Definition 1.22 (Partial tire tree): G_{T_r}^{circle} =
G_{T_r} with V(C_{T_r}) removed, i.e. the strict interior of the
triangulated disk inside the seam.

New Lemma 1.23 (Seam edges shared by <= one other depth-d seam):
an edge on the seam of a depth-d tread T is in the seam of at most
one other depth-d tread T'.  Proof via inner-dual-of-outerplanar-
is-a-tree: C_T bounds a face of the parent's O^{(T_p)} (outerplanar),
so each edge of O^{(T_p)} lies in at most two of its bounded face
cycles, giving at most one sibling seam containing e.

New Conjecture 1.24 (Seam structure of minimum 4CT counterexamples,
sketch): a hypothetical minimum 4CT counterexample has bilateral
colourability, bilateral incompatibility, Birkhoff's seam-length
>= 6 bound, and an innermost obstruction at a leaf tread T^* whose
seam interior is one of a finite list of minimal seam configurations,
with the boundary palette restriction propagating outward along the
root-to-T^* obstruction chain.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-27 23:21:50 -04:00
parent bfa8b8956d
commit 4810121ec4
6 changed files with 863 additions and 44 deletions
@@ -0,0 +1,480 @@
"""Draw the tire-tree decomposition for Theorem~\\ref{thm:tire-tree-decomposition}.
Uses a Tutte embedding (barycentric solve with the outer face fixed on a
convex polygon) to give a planar straight-line layout.
Panel (a): G with 13 vertices, 5 levels (v_0 at level 0; L_1, L_2, L_3, L_4
on subsequent levels). Tutte outer face = h-g_1-g_2 (the deepest face from
v_0), so v_0 ends up roughly central and the outer triangle is "outermost"
in BFS-from-v_0 distance. Tree-of-treads has 5 nodes:
T_0
/ \\
T_R T_L
|
T_LL
|
T_LLL
Panel (b): G_{T_L} on 10 vertices, with Tutte outer face = C_{T_L} = {a,c,d}.
Levels in G_{T_L} satisfy ell_{G_{T_L}}(.) = ell_G(.) - 1 on V(G_{T_L});
T(G_{T_L}, C_{T_L}) is the chain T_L -> T_LL -> T_LLL.
"""
import math
import os
import networkx as nx
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D
OUT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# ---------------------------------------------------------------------------
# Build G.
# ---------------------------------------------------------------------------
G = nx.Graph()
G.add_nodes_from(['v0', 'a', 'b', 'c', 'd', 'e',
'f1', 'f2', 'f3', 'g1', 'g2', 'g3', 'h'])
# v_0 fan
for v in ['a', 'b', 'c', 'd']:
G.add_edge('v0', v)
# L_1 4-cycle
G.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'), ('d', 'a')])
# Chord a-c (outside L_1 in the planar embedding)
G.add_edge('a', 'c')
# e-fan (Region R)
for v in ['a', 'b', 'c']:
G.add_edge('e', v)
# f-triangle (Region L)
G.add_edges_from([('f1', 'f2'), ('f2', 'f3'), ('f3', 'f1')])
# Annular L_1 -> f-triangle: f_1~{a,d}, f_2~{d,c}, f_3~{a,c}
G.add_edges_from([
('f1', 'a'), ('f1', 'd'),
('f2', 'd'), ('f2', 'c'),
('f3', 'a'), ('f3', 'c'),
])
# g-triangle (inside f-triangle)
G.add_edges_from([('g1', 'g2'), ('g2', 'g3'), ('g3', 'g1')])
# Annular f-triangle -> g-triangle: f_1~{g_1, g_3}, f_2~{g_2, g_3}, f_3~{g_1, g_2}
G.add_edges_from([
('f1', 'g1'), ('f1', 'g3'),
('f2', 'g2'), ('f2', 'g3'),
('f3', 'g1'), ('f3', 'g2'),
])
# h-fan (inside g-triangle)
for v in ['g1', 'g2', 'g3']:
G.add_edge('h', v)
assert G.number_of_edges() == 3 * G.number_of_nodes() - 6, (
f"G not a triangulation: |E|={G.number_of_edges()}, "
f"expected {3 * G.number_of_nodes() - 6}"
)
level_G = nx.shortest_path_length(G, source='v0')
# ---------------------------------------------------------------------------
# Tutte embedding.
# ---------------------------------------------------------------------------
def tutte_embedding(graph, outer_face_cyclic, outer_radius=3.0,
angle_offset_deg=90.0, outer_weight=1.0):
"""Compute (weighted) Tutte embedding.
outer_face_cyclic: list of vertices on the outer face, in cyclic order.
Outer vertices are fixed on a regular polygon of given radius; every
interior vertex is placed at a convex combination of its neighbours'
positions (solved as a linear system). Edges incident to an outer
vertex carry weight `outer_weight`; interior-interior edges carry
weight 1. All weights positive, so Tutte's theorem still gives a
planar straight-line embedding. Larger `outer_weight` pulls interior
vertices more strongly toward the outer triangle, spreading them out.
"""
n_outer = len(outer_face_cyclic)
outer_positions = {}
for i, v in enumerate(outer_face_cyclic):
angle = math.radians(angle_offset_deg + i * 360 / n_outer)
outer_positions[v] = (outer_radius * math.cos(angle),
outer_radius * math.sin(angle))
outer_set = set(outer_face_cyclic)
interior = [v for v in graph.nodes() if v not in outer_set]
interior_idx = {v: i for i, v in enumerate(interior)}
m = len(interior)
if m == 0:
return outer_positions
A = np.zeros((m, m))
bx = np.zeros(m)
by = np.zeros(m)
for v in interior:
i = interior_idx[v]
for u in graph.neighbors(v):
w = outer_weight if u in outer_set else 1.0
A[i, i] += w
if u in outer_set:
bx[i] += w * outer_positions[u][0]
by[i] += w * outer_positions[u][1]
else:
j = interior_idx[u]
A[i, j] -= w
x = np.linalg.solve(A, bx)
y = np.linalg.solve(A, by)
pos = dict(outer_positions)
for v in interior:
i = interior_idx[v]
pos[v] = (float(x[i]), float(y[i]))
return pos
def stretch_radially(pos, outer_face_cyclic, alpha=0.6):
"""Stretch interior positions radially outward from the outer-face centroid.
Outer vertices are unchanged; for each interior vertex at radius r from
the outer-face centroid, replace r by r' = R^(1-alpha) * r^alpha, where
R is the radius of the outer vertices. With alpha < 1 this is a concave
stretch that pushes small radii outward. Angles are preserved, so
planarity of the underlying Tutte embedding is preserved.
"""
outer_set = set(outer_face_cyclic)
outer_positions = [pos[v] for v in outer_face_cyclic]
Cx = sum(p[0] for p in outer_positions) / len(outer_positions)
Cy = sum(p[1] for p in outer_positions) / len(outer_positions)
R = max(math.sqrt((p[0] - Cx)**2 + (p[1] - Cy)**2)
for p in outer_positions)
new_pos = {}
for v, p in pos.items():
if v in outer_set:
new_pos[v] = p
continue
dx, dy = p[0] - Cx, p[1] - Cy
r = math.sqrt(dx * dx + dy * dy)
if r < 1e-10:
new_pos[v] = (Cx, Cy)
continue
r_new = (R ** (1 - alpha)) * (r ** alpha)
scale = r_new / r
new_pos[v] = (Cx + dx * scale, Cy + dy * scale)
return new_pos
# Panel (a) positions: hand-tuned in TikZiT and copied back here so the
# matplotlib panel matches the .tikz layout the user is editing on Desktop.
# The chord a-c is drawable as a straight line at these positions; the
# d-a edge passes through f_1, so it's drawn as a slight Bezier curve.
pos_G = {
'v0': ( 0.00, 6.0),
'a': (-5.50, -5.0),
'b': (-2.75, 3.0),
'c': ( 1.75, 3.0),
'd': ( 8.00, -5.0),
'e': (-1.50, 1.5),
'f1': ( 1.50, -5.0),
'f2': ( 4.00, -1.0),
'f3': (-0.75, -1.0),
'g1': ( 0.70, -3.0),
'g2': ( 1.45, -1.5),
'g3': ( 2.30, -3.0),
'h': ( 1.55, -2.5),
}
# ---------------------------------------------------------------------------
# G_{T_L}: subgraph inside C_{T_L} = {a, c, d}.
# ---------------------------------------------------------------------------
C_TL = {'a', 'c', 'd'}
V_GTL = C_TL | {'f1', 'f2', 'f3', 'g1', 'g2', 'g3', 'h'}
G_TL = G.subgraph(V_GTL).copy()
level_GTL = nx.multi_source_dijkstra_path_length(G_TL, C_TL)
for v in V_GTL:
assert level_GTL[v] == level_G[v] - 1
# Tutte for G_{T_L}: outer face = a-d-c (= C_{T_L}, the seam itself).
# Cyclic order matches the planar boundary: a -> d -> c.
outer_face_GTL = ['a', 'd', 'c']
pos_GTL = tutte_embedding(G_TL, outer_face_GTL, outer_radius=2.8,
angle_offset_deg=90, outer_weight=3.0)
pos_GTL = stretch_radially(pos_GTL, outer_face_GTL, alpha=0.6)
# ---------------------------------------------------------------------------
# Edge sets.
# ---------------------------------------------------------------------------
C_TR_edges = [('a', 'b'), ('b', 'c'), ('a', 'c')]
C_TL_edges = [('a', 'd'), ('d', 'c'), ('a', 'c')]
C_TLL_edges = [('f1', 'f2'), ('f2', 'f3'), ('f3', 'f1')]
C_TLLL_edges = [('g1', 'g2'), ('g2', 'g3'), ('g3', 'g1')]
fan_edges = [('v0', v) for v in ['a', 'b', 'c', 'd']]
# ---------------------------------------------------------------------------
# Tree inset helper.
# ---------------------------------------------------------------------------
def draw_tree_inset(parent_ax, position, tree_nodes, tree_edges, node_pos,
label_text, highlight=None, title=None,
xlim=(-1.4, 1.4), ylim=(-3.6, 0.6)):
ax = parent_ax.inset_axes(position)
for u, v in tree_edges:
x0, y0 = node_pos[u]
x1, y1 = node_pos[v]
ax.plot([x0, x1], [y0, y1], color='black', lw=1.4, zorder=1)
for n in tree_nodes:
x, y = node_pos[n]
is_hi = highlight and n in highlight
ax.scatter([x], [y], s=380, color='#fde68a' if is_hi else '#e5e7eb',
edgecolors='black', linewidths=1.8 if is_hi else 1.0, zorder=3)
ax.text(x, y, label_text[n], ha='center', va='center',
fontsize=7.5, fontweight='bold', zorder=4)
ax.set_xlim(*xlim); ax.set_ylim(*ylim)
ax.set_aspect('equal')
ax.set_xticks([]); ax.set_yticks([])
if title:
ax.set_title(title, fontsize=8.5, pad=2)
for spine in ax.spines.values():
spine.set_edgecolor('#9ca3af')
spine.set_linewidth(0.8)
ax.patch.set_facecolor('#f9fafb')
# ---------------------------------------------------------------------------
# Draw.
# ---------------------------------------------------------------------------
LEVEL_COLOR = {
0: '#1e293b',
1: '#475569',
2: '#94a3b8',
3: '#cbd5e1',
4: '#f1f5f9',
}
fig, axes = plt.subplots(1, 2, figsize=(16, 9))
def _vertex_label(name):
"""Render 'f1' as 'f_1' (subscript) and 'v0' as 'v_0' for display."""
if len(name) >= 2 and name[0].isalpha() and name[1:].isdigit():
return f'{name[0]}_{{{name[1:]}}}'
return name
def draw_panel(ax, graph, pos, levels, seams, fan, title, xlim, ylim,
text_color_threshold=4, label_map=None):
"""seams: list of (edges, color, width) tuples; fan: edges list or None.
label_map: optional dict mapping vertex names to displayed names (so the
panel can show a relabelled version of the graph)."""
nx.draw_networkx_edges(graph, pos, ax=ax, edge_color='#d1d5db', width=1.1)
if fan is not None:
nx.draw_networkx_edges(graph, pos, edgelist=fan, ax=ax,
edge_color='#3b82f6', width=1.5, style='dashed')
for edges, color, width in seams:
nx.draw_networkx_edges(graph, pos, edgelist=edges, ax=ax,
edge_color=color, width=width)
for v, (x, y) in pos.items():
lev = levels[v]
text_color = 'white' if lev < text_color_threshold else 'black'
display_name = (label_map or {}).get(v, v)
ax.scatter([x], [y], s=520, color=LEVEL_COLOR[lev],
edgecolors='black', linewidths=1.0, zorder=3)
ax.text(x, y, f'${_vertex_label(display_name)}$\n$\\ell{{=}}{lev}$',
ha='center', va='center',
color=text_color, fontsize=7, fontweight='bold', zorder=4)
ax.set_aspect('equal')
ax.axis('off')
ax.set_xlim(*xlim); ax.set_ylim(*ylim)
ax.set_title(title, fontsize=10.5, pad=5)
# Compute panel limits from the Tutte positions, with padding.
def compute_limits(pos, pad=0.5):
xs = [p[0] for p in pos.values()]
ys = [p[1] for p in pos.values()]
return (min(xs) - pad, max(xs) + pad), (min(ys) - pad, max(ys) + pad)
xlim_a, ylim_a = compute_limits(pos_G, pad=0.6)
xlim_b, ylim_b = compute_limits(pos_GTL, pad=0.6)
# ============================================================================
# Panel (a): G -- positions match Desktop/tire_tree_decomposition.tikz.
# Draw all non-seam edges as plain gray (no separate dashed fan style here,
# to match the TikZiT version). Edge a-d at y = -5 would pass through f_1
# if drawn straight, so we render it (and seam C_{T_L}'s a-d component) as
# a slight Bezier curve via FancyArrowPatch.
# ============================================================================
ax = axes[0]
# Non-seam edges as straight gray lines; a-d and v_0-a are drawn curved
# below.
_curved_pairs = [{'a', 'd'}, {'v0', 'a'}]
non_seam_edges = [e for e in G.edges
if set(e) not in _curved_pairs
and set(e) not in (set(s) for s in C_TR_edges + C_TL_edges
+ C_TLL_edges + C_TLLL_edges)]
nx.draw_networkx_edges(G, pos_G, edgelist=non_seam_edges, ax=ax,
edge_color='#d1d5db', width=1.1)
# Curved edges (FancyArrowPatch). a-d dodges f_1; v_0-a is bent for
# visual balance (mirrors the TikZiT `bend right`).
from matplotlib.patches import FancyArrowPatch
def add_curved(ax, p_from, p_to, *, color, lw, rad, ls='-', zorder=2):
ax.add_patch(FancyArrowPatch(
posA=p_from, posB=p_to,
arrowstyle='-', connectionstyle=f'arc3,rad={rad}',
color=color, linewidth=lw, linestyle=ls, zorder=zorder,
))
add_curved(ax, pos_G['a'], pos_G['d'], color='#d1d5db', lw=1.1, rad=0.15)
add_curved(ax, pos_G['v0'], pos_G['a'], color='#d1d5db', lw=1.1, rad=0.25)
# Seams (straight, since the layout is now planar with straight chord).
# Order: bottom first (C_{T_LL}, C_{T_LLL}), then chord/L_1 seams on top.
nx.draw_networkx_edges(G, pos_G,
edgelist=[('f1', 'f2'), ('f2', 'f3'), ('f3', 'f1')],
ax=ax, edge_color='#9333ea', width=2.2)
nx.draw_networkx_edges(G, pos_G,
edgelist=[('g1', 'g2'), ('g2', 'g3'), ('g3', 'g1')],
ax=ax, edge_color='#0d9488', width=2.0)
nx.draw_networkx_edges(G, pos_G,
edgelist=[('a', 'b'), ('b', 'c')],
ax=ax, edge_color='#ea580c', width=2.4)
nx.draw_networkx_edges(G, pos_G,
edgelist=[('a', 'c'), ('d', 'c')],
ax=ax, edge_color='#dc2626', width=2.8)
add_curved(ax, pos_G['a'], pos_G['d'], color='#dc2626', lw=2.8, rad=0.15, zorder=4)
# Vertices.
for v, (x, y) in pos_G.items():
lev = level_G[v]
text_color = 'white' if lev < 4 else 'black'
ax.scatter([x], [y], s=520, color=LEVEL_COLOR[lev],
edgecolors='black', linewidths=1.0, zorder=5)
ax.text(x, y, f'${_vertex_label(v)}$\n$\\ell{{=}}{lev}$',
ha='center', va='center',
color=text_color, fontsize=7, fontweight='bold', zorder=6)
ax.set_aspect('equal')
ax.axis('off')
# The a-d arc bulges below y=-5 by ~ rad * |a - d| / 2 ≈ 1.0 with rad=0.15;
# pad the y range so it isn't clipped.
xlim_a, ylim_a = compute_limits(pos_G, pad=0.8)
ylim_a = (ylim_a[0] - 1.2, ylim_a[1])
ax.set_xlim(*xlim_a); ax.set_ylim(*ylim_a)
ax.set_title(
r"$(a)$ $G$: 13 vertices, BFS levels $\ell_G \in \{0,1,2,3,4\}$,"
"\n"
r"four nested seams $C_{T_R}, C_{T_L}, C_{T_{LL}}, C_{T_{LLL}}$ "
r"(chord $a$-$c$ drawn straight in this layout).",
fontsize=10.5, pad=5,
)
tree_pos_a = {
'T_0': (0.0, 0.0),
'T_R': (-0.7, -1.0),
'T_L': (0.7, -1.0),
'T_LL': (0.7, -2.0),
'T_LLL': (0.7, -3.0),
}
tree_labels = {
'T_0': r'$T_0$', 'T_R': r'$T_R$', 'T_L': r'$T_L$',
'T_LL': r'$T_{LL}$', 'T_LLL': r'$T_{LLL}$',
}
draw_tree_inset(
axes[0], [0.70, 0.42, 0.28, 0.55],
tree_nodes=['T_0', 'T_R', 'T_L', 'T_LL', 'T_LLL'],
tree_edges=[('T_0', 'T_R'), ('T_0', 'T_L'),
('T_L', 'T_LL'), ('T_LL', 'T_LLL')],
node_pos=tree_pos_a, label_text=tree_labels,
highlight={'T_L', 'T_LL', 'T_LLL'},
title=r'$\mathcal{T}(G, \{v_0\})$',
xlim=(-1.4, 1.4), ylim=(-3.6, 0.6),
)
# ============================================================================
# Panel (b): G_{T_L}. Vertex names are rotated relative to the parent G
# (a->c, c->d, d->a; f_1->f_3, f_2->f_1, f_3->f_2; g_1->g_2, g_2->g_3,
# g_3->g_1; h stays h) -- the relabelling emphasises the new role of
# C_{T_L} as cycle source, with the boundary now naturally read as
# {a, c, d} in cyclic order from a position the user picked.
# ============================================================================
GTL_LABEL_MAP = {
'a': 'c', 'c': 'd', 'd': 'a',
'f1': 'f3', 'f2': 'f1', 'f3': 'f2',
'g1': 'g2', 'g2': 'g3', 'g3': 'g1',
'h': 'h',
}
draw_panel(
axes[1], G_TL, pos_GTL, level_GTL,
seams=[
(C_TL_edges, '#dc2626', 2.8),
(C_TLL_edges, '#9333ea', 2.2),
(C_TLLL_edges, '#0d9488', 2.0),
],
fan=None,
title=(
r"$(b)$ $G_{T_L}$ (Tutte embedding, outer face $C_{T_L} = \{a,c,d\}$):"
" 10 vertices, cycle source $C_{T_L}$,\n"
r"$\ell_{G_{T_L}}(\cdot) = \ell_G(\cdot) - 1$; "
r"$\mathcal{T}(G_{T_L}, C_{T_L})$ is the chain $T_L \to T_{LL} \to T_{LLL}$."
),
xlim=xlim_b, ylim=ylim_b,
text_color_threshold=3,
label_map=GTL_LABEL_MAP,
)
sub_tree_pos = {
'T_L': (0.0, 0.0),
'T_LL': (0.0, -1.0),
'T_LLL': (0.0, -2.0),
}
draw_tree_inset(
axes[1], [0.70, 0.42, 0.28, 0.55],
tree_nodes=['T_L', 'T_LL', 'T_LLL'],
tree_edges=[('T_L', 'T_LL'), ('T_LL', 'T_LLL')],
node_pos=sub_tree_pos, label_text=tree_labels,
highlight={'T_L', 'T_LL', 'T_LLL'},
title=r'$\mathcal{T}(G_{T_L}, C_{T_L})$',
xlim=(-1.0, 1.0), ylim=(-2.6, 0.4),
)
# ============================================================================
# Legend + suptitle
# ============================================================================
legend = [
Line2D([0], [0], marker='o', color='w', label=r'$\ell = 0$',
markerfacecolor=LEVEL_COLOR[0], markeredgecolor='black', markersize=10),
Line2D([0], [0], marker='o', color='w', label=r'$\ell = 1$',
markerfacecolor=LEVEL_COLOR[1], markeredgecolor='black', markersize=10),
Line2D([0], [0], marker='o', color='w', label=r'$\ell = 2$',
markerfacecolor=LEVEL_COLOR[2], markeredgecolor='black', markersize=10),
Line2D([0], [0], marker='o', color='w', label=r'$\ell = 3$',
markerfacecolor=LEVEL_COLOR[3], markeredgecolor='black', markersize=10),
Line2D([0], [0], marker='o', color='w', label=r'$\ell = 4$',
markerfacecolor=LEVEL_COLOR[4], markeredgecolor='black', markersize=10),
Line2D([0], [0], color='#ea580c', lw=2.4, label=r'seam $C_{T_R}$'),
Line2D([0], [0], color='#dc2626', lw=2.8, label=r'seam $C_{T_L}$'),
Line2D([0], [0], color='#9333ea', lw=2.2, label=r'seam $C_{T_{LL}}$'),
Line2D([0], [0], color='#0d9488', lw=2.0, label=r'seam $C_{T_{LLL}}$'),
]
fig.legend(handles=legend, loc='lower center', ncol=5, fontsize=9.5,
framealpha=0.95, columnspacing=1.8)
fig.suptitle(
r"Tire-tree decomposition (Theorem 1.19): every tread $T$ is the root "
r"of its own tree of tire treads $\mathcal{T}(G_T, C_T)$.",
fontsize=12, y=0.96,
)
fig.subplots_adjust(top=0.88, bottom=0.16, left=0.02, right=0.98, wspace=0.05)
out = os.path.join(OUT_DIR, 'fig_tire_tree_decomposition.png')
fig.savefig(out, dpi=180, bbox_inches='tight')
plt.close(fig)
print(f'G: |V|={G.number_of_nodes()}, |E|={G.number_of_edges()}, '
f'levels {sorted(set(level_G.values()))}')
print(f'G_TL: |V|={G_TL.number_of_nodes()}, |E|={G_TL.number_of_edges()}, '
f'levels {sorted(set(level_GTL.values()))}')
print(f'verified level shift (D2): ell_GTL(v) = ell_G(v) - 1 for all '
f'{len(V_GTL)} v in V(G_TL)')
print(f'panel (a): hand-tuned positions (see Desktop/tire_tree_decomposition.tikz)')
print(f'Tutte (G_TL): outer face = {outer_face_GTL}')
print(f'wrote {out}')
Binary file not shown.

After

Width:  |  Height:  |  Size: 364 KiB

+10 -3
View File
@@ -30,6 +30,14 @@
\newlabel{rem:count-general-outerplanar}{{1.16}{10}}
\newlabel{thm:tread-tree}{{1.17}{10}}
\newlabel{rem:tree-multiple-children}{{1.18}{11}}
\newlabel{thm:tire-tree-decomposition}{{1.19}{12}}
\newlabel{rem:tree-coloring-factorisation}{{1.20}{13}}
\@writefile{lof}{\contentsline {figure}{\numberline {5}{\ignorespaces Tire-tree decomposition (Theorem\nonbreakingspace 1.19\hbox {}) on a $13$-vertex maximal planar example $G$ with five BFS levels. $(a)$ $G$ with vertex source $v_0$ and $\ell _G \in \{0,1,2,3,4\}$; four nested seams are highlighted, $C_{T_R} = \{a,b,c\}$ (orange), $C_{T_L} = \{a,c,d\}$ (red, including the chord $a$-$c$ shared with $C_{T_R}$), $C_{T_{LL}} = \{f_1, f_2, f_3\}$ (purple), $C_{T_{LLL}} = \{g_1, g_2, g_3\}$ (teal). Inset: the rooted tree of tire treads $\mathcal {T}(G, \{v_0\})$ branches at $T_0$ into the leaf $T_R$ (containing $e$) and a chain $T_L \to T_{LL} \to T_{LLL}$ (the highlighted sub-tree). $(b)$ The disk $G_{T_L}$ inside the seam $C_{T_L}$, drawn standalone with $C_{T_L}$ as cycle source and vertex labels rotated to match the new (cycle-source) role of the boundary triangle. $\ell _{G_{T_L}}(\cdot ) = \ell _G(\cdot ) - 1$ on $V(G_{T_L})$ (verified by the generator script), and $\mathcal {T}(G_{T_L}, C_{T_L})$ is the chain $T_L \to T_{LL} \to T_{LLL}$, iso to the highlighted sub-tree of $(a)$.}}{14}{}\protected@file@percent }
\newlabel{fig:tire-tree-decomposition}{{5}{14}}
\newlabel{def:seam}{{1.21}{14}}
\newlabel{def:partial-tire-tree}{{1.22}{15}}
\newlabel{lem:seam-edge-shared}{{1.23}{15}}
\newlabel{conj:seam-counterexample}{{1.24}{15}}
\bibcite{tait-original}{1}
\bibcite{bauerfeld-depth}{2}
\bibcite{bauerfeld-nested-tire-duals}{3}
@@ -38,6 +46,5 @@
\newlabel{tocindent1}{17.77782pt}
\newlabel{tocindent2}{0pt}
\newlabel{tocindent3}{0pt}
\newlabel{rem:tree-coloring-factorisation}{{1.19}{12}}
\@writefile{toc}{\contentsline {section}{\tocsection {}{}{References}}{12}{}\protected@file@percent }
\gdef \@abspage@last{12}
\@writefile{toc}{\contentsline {section}{\tocsection {}{}{References}}{16}{}\protected@file@percent }
\gdef \@abspage@last{16}
+57 -39
View File
@@ -1,4 +1,4 @@
This is pdfTeX, Version 3.141592653-2.6-1.40.24 (TeX Live 2022) (preloaded format=pdflatex 2022.10.5) 27 MAY 2026 04:39
This is pdfTeX, Version 3.141592653-2.6-1.40.24 (TeX Live 2022) (preloaded format=pdflatex 2022.10.5) 27 MAY 2026 22:18
entering extended mode
restricted \write18 enabled.
%&-line parsing enabled.
@@ -498,58 +498,76 @@ e
<fig_dual_depth.png, id=25, 642.8015pt x 606.265pt>
File: fig_dual_depth.png Graphic file (type png)
<use fig_dual_depth.png>
Package pdftex.def Info: fig_dual_depth.png used on input line 124.
Package pdftex.def Info: fig_dual_depth.png used on input line 128.
(pdftex.def) Requested size: 251.9989pt x 237.67276pt.
[2 <./fig_dual_depth.png>]
<fig_tire_example.png, id=31, 559.64081pt x 375.804pt>
File: fig_tire_example.png Graphic file (type png)
<use fig_tire_example.png>
Package pdftex.def Info: fig_tire_example.png used on input line 179.
Package pdftex.def Info: fig_tire_example.png used on input line 183.
(pdftex.def) Requested size: 280.79956pt x 188.56097pt.
[3 <./fig_tire_example.png>] [4] [5] [6]
LaTeX Warning: `h' float specifier changed to `ht'.
[7] [8] [9] [10] [11] [12] (./paper.aux) )
[7] [8] [9] [10] [11] [12]
<fig_tire_tree_decomposition.png, id=72, 1101.3145pt x 633.9685pt>
File: fig_tire_tree_decomposition.png Graphic file (type png)
<use fig_tire_tree_decomposition.png>
Package pdftex.def Info: fig_tire_tree_decomposition.png used on input line 10
98.
(pdftex.def) Requested size: 341.9989pt x 196.86678pt.
LaTeX Warning: `h' float specifier changed to `ht'.
[13] [14 <./fig_tire_tree_decomposition.png>]
Overfull \hbox (1.78508pt too wide) in paragraph at lines 1228--1230
[]\OT1/cmr/m/n/10 Length lower bound (Birkhoff). \OT1/cmr/m/it/10 Ev-ery non-tr
ivial seam $\OML/cmm/m/it/10 C$ \OT1/cmr/m/it/10 of $\OML/cmm/m/it/10 G$ \OT1/c
mr/m/it/10 has $\OMS/cmsy/m/n/10 j\OML/cmm/m/it/10 V\OT1/cmr/m/n/10 (\OML/cmm/m
/it/10 C\OT1/cmr/m/n/10 )\OMS/cmsy/m/n/10 j ^^U
[]
[15] [16] (./paper.aux) )
Here is how much of TeX's memory you used:
14048 strings out of 478268
279229 string characters out of 5846347
563840 words of memory out of 5000000
31872 multiletter control sequences out of 15000+600000
14061 strings out of 478268
279616 string characters out of 5846347
563910 words of memory out of 5000000
31884 multiletter control sequences out of 15000+600000
478218 words of font info for 62 fonts, out of 8000000 for 9000
1302 hyphenation exceptions out of 8191
84i,12n,89p,1156b,803s stack positions out of 10000i,1000n,20000p,200000b,200000s
</usr/local/texlive/2022/texmf-dist/f
onts/type1/public/amsfonts/cm/cmbx10.pfb></usr/local/texlive/2022/texmf-dist/fo
nts/type1/public/amsfonts/cm/cmbx8.pfb></usr/local/texlive/2022/texmf-dist/font
s/type1/public/amsfonts/cm/cmcsc10.pfb></usr/local/texlive/2022/texmf-dist/font
s/type1/public/amsfonts/cm/cmex10.pfb></usr/local/texlive/2022/texmf-dist/fonts
/type1/public/amsfonts/cm/cmmi10.pfb></usr/local/texlive/2022/texmf-dist/fonts/
type1/public/amsfonts/cm/cmmi5.pfb></usr/local/texlive/2022/texmf-dist/fonts/ty
pe1/public/amsfonts/cm/cmmi6.pfb></usr/local/texlive/2022/texmf-dist/fonts/type
1/public/amsfonts/cm/cmmi7.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/
public/amsfonts/cm/cmmi8.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/pu
blic/amsfonts/cm/cmmi9.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/publ
ic/amsfonts/cm/cmr10.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public
/amsfonts/cm/cmr5.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/am
sfonts/cm/cmr6.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfo
nts/cm/cmr7.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts
/cm/cmr8.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm
/cmr9.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cm
sy10.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cms
y5.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmsy6
.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmsy7.p
fb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmsy9.pfb
></usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmti10.pfb>
</usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmti8.pfb></
usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/symbols/msam10.pf
b></usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/symbols/msbm1
0.pfb>
Output written on paper.pdf (12 pages, 618557 bytes).
84i,12n,89p,1168b,803s stack positions out of 10000i,1000n,20000p,200000b,200000s
</usr/local/texlive/2022/texmf-dist/fonts/type1/public
/amsfonts/cm/cmbx10.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/
amsfonts/cm/cmbx8.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/am
sfonts/cm/cmcsc10.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/am
sfonts/cm/cmex10.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/ams
fonts/cm/cmmi10.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsf
onts/cm/cmmi5.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfon
ts/cm/cmmi6.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts
/cm/cmmi7.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/c
m/cmmi8.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/
cmmi9.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cm
r10.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmr5
.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmr6.pf
b></usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmr7.pfb><
/usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmr8.pfb></us
r/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmr9.pfb></usr/l
ocal/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmsy10.pfb></usr/lo
cal/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmsy5.pfb></usr/loca
l/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmsy6.pfb></usr/local/
texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmsy7.pfb></usr/local/te
xlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmsy9.pfb></usr/local/texl
ive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmti10.pfb></usr/local/texli
ve/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmti8.pfb></usr/local/texlive
/2022/texmf-dist/fonts/type1/public/amsfonts/symbols/msam10.pfb></usr/local/tex
live/2022/texmf-dist/fonts/type1/public/amsfonts/symbols/msbm10.pfb>
Output written on paper.pdf (16 pages, 927226 bytes).
PDF statistics:
177 PDF objects out of 1000 (max. 8388607)
107 compressed objects within 2 object streams
192 PDF objects out of 1000 (max. 8388607)
116 compressed objects within 2 object streams
0 named destinations out of 1000 (max. 500000)
23 words of extra memory for PDF output out of 10000 (max. 10000000)
28 words of extra memory for PDF output out of 10000 (max. 10000000)
Binary file not shown.
+316 -2
View File
@@ -87,8 +87,12 @@ with a fixed planar embedding $\Pi_G$. We write $|V| = n$, so $|E| = 3n - 6$
and $G$ has $2n - 4$ triangular faces.
\begin{definition}[Level source]
A \emph{level source} of $G$ is any vertex $v \in V$; we write
$S = \{v\}$ for the level-0 source.
A \emph{level source} of $G$ is a set $S \subseteq V$ that is either
\begin{itemize}
\item a single vertex $\{v\}$ (a \emph{vertex source}), or
\item a set inducing a simple cycle in $G$ --- i.e.\ $G[S]$ is a
simple cycle of length $\geq 3$ (a \emph{cycle source}).
\end{itemize}
\end{definition}
\begin{definition}[Levels]
@@ -932,6 +936,186 @@ of Remark~\ref{rem:hamilton-cycle-spoke-only}) with a non-empty
interior, $T_p$ has exactly one child.
\end{remark}
\begin{theorem}[Tire-tree decomposition]
\label{thm:tire-tree-decomposition}
Let $G$ be a maximal planar graph with planar embedding $\Pi_G$ and let
$v_0 \in V(G)$. The tree of tire treads $\mathcal{T}(G, \{v_0\})$ of
Theorem~\ref{thm:tread-tree} \emph{decomposes $G$ into nested tires}:
it is a finite rooted tree, rooted at the depth-$0$ tread containing
$v_0$, whose nodes (tire treads) partition the bounded faces of $G$
(Theorem~\ref{thm:tread-partition}).
This decomposition is moreover \emph{self-similar}. For any tread $T$
in $\mathcal{T}(G, \{v_0\})$ at depth $d \ge 1$, with outer-boundary
cycle $C_T := B_{\mathrm{out}}^{(T)}$, let $G_T$ be the sub-graph of $G$
induced by $C_T$ together with all vertices of $G$ lying in the closed
planar region $R_T \subset |\Pi_G|$ bounded by $C_T$ on the side of
$C_T$ away from $v_0$. Then:
\begin{enumerate}
\item[(D1)] $G_T$, with the embedding inherited from $\Pi_G$, is a
\emph{triangulated disk}: every bounded face is a triangle,
and the outer face is bounded by $C_T$.
\item[(D2)] Taking $C_T$ as a cycle source of $G_T$ (so $C_T$ has
level $0$ in $G_T$ and the BFS-from-$C_T$ levels in $G_T$
equal $\ell_G(\cdot) - d$ on $V(G_T)$), the construction of
Theorem~\ref{thm:tread-tree} extends to give a rooted tree
of tire treads $\mathcal{T}(G_T, C_T)$ whose depth-$0$ root
tread has $B_{\mathrm{out}} = C_T$ and inner outerplanar
graph $O = O^{(T)}$.
\item[(D3)] $\mathcal{T}(G_T, C_T)$ is canonically iso to the sub-tree
of $\mathcal{T}(G, \{v_0\})$ rooted at $T$, preserving
outer-boundary cycles, inner outerplanar graphs, and the
parent--child face correspondence.
\end{enumerate}
In short: pick any vertex $v_0 \in V(G)$ to root the global tree
$\mathcal{T}(G, \{v_0\})$ describing the whole graph; pick any tread $T$
in this tree; then $T$ is itself the root of a local tree
$\mathcal{T}(G_T, C_T)$ describing the triangulated disk of $G$ inside
$C_T$, with $C_T$ as cycle source. Maximal planar graphs decompose
into nested trees of tire treads.
\end{theorem}
\begin{proof}
\emph{Decomposition.} Theorem~\ref{thm:tread-tree} gives the rooted
tree structure of $\mathcal{T}(G, \{v_0\})$, with root the depth-$0$
tread containing $v_0$; Theorem~\ref{thm:tread-partition} gives that
its tire treads partition the bounded faces of $G$. Finiteness of
the tree is immediate from finiteness of $G$.
\emph{(D1) $G_T$ is a triangulated disk.} By
Lemma~\ref{lem:tire-component} applied to the component of $G'_d$ that
gives rise to $T$, the outer boundary $C_T = B_{\mathrm{out}}^{(T)}$ is
a simple cycle in $L_d^G$. By the Jordan curve theorem, $C_T$
separates $|\Pi_G| \setminus C_T$ into two open regions; $R_T$ is the
closure of the one not containing $v_0$. The bounded faces of $G_T$ in
its inherited embedding are exactly the bounded faces of $G$ contained
in $R_T$, each of which is a triangle since $G$ is a triangulation.
The unbounded face of $G_T$'s embedding is the complement of $R_T$,
whose boundary is $C_T$.
\emph{(D2) Level shift.} We show $\mathrm{dist}_{G_T}(v, C_T) =
\ell_G(v) - d$ for every $v \in V(G_T)$. When $v \in C_T$ both sides
equal $0$, so fix $v \in V(G_T) \setminus C_T$.
\smallskip
\emph{Step 1: $\mathrm{dist}_G(v, C_T) = \ell_G(v) - d$.} A shortest
$G$-path from $v$ to $v_0$ must visit $C_T$, since $v$ and $v_0$ lie in
different open regions of $|\Pi_G| \setminus C_T$; let $w$ be its first
$C_T$-vertex. The $v$-to-$w$ sub-path has length $\ge \mathrm{dist}_G(v,
C_T)$ and the $w$-to-$v_0$ sub-path has length $\ell_G(w) = d$, so
$\ell_G(v) \ge \mathrm{dist}_G(v, C_T) + d$. Conversely, concatenating
a shortest $G$-path from $v$ to a nearest $C_T$-vertex $w'$ with a
shortest $G$-path from $w'$ to $v_0$ gives a $v$-to-$v_0$ path of
length $\mathrm{dist}_G(v, C_T) + d$, so $\ell_G(v) \le
\mathrm{dist}_G(v, C_T) + d$.
\smallskip
\emph{Step 2: $\mathrm{dist}_{G_T}(v, C_T) = \mathrm{dist}_G(v, C_T)$.}
The inequality $\ge$ is automatic since $G_T \subseteq G$. For $\le$,
pick a shortest $G$-path $\pi$ from $v$ to $C_T$; we may assume $\pi$
has no internal vertex in $C_T$ (truncate otherwise). Any internal
vertex of $\pi$ then lies in the same open region of $|\Pi_G| \setminus
C_T$ as $v$, i.e.\ in $R_T \setminus C_T \subseteq V(G_T)$; every edge
of $\pi$ has both endpoints in $V(G_T)$ and so lies in $E(G_T)$. Hence
$\pi$ is a path in $G_T$ realising $\mathrm{dist}_G(v, C_T)$.
\smallskip
Combining the two steps yields $\mathrm{dist}_{G_T}(v, C_T) = \ell_G(v)
- d$, as claimed.
\emph{(D3) Tree iso.} By (D2), $L_k^{G_T} = L_{d+k}^G \cap V(G_T)$ for
every $k \ge 0$. For a bounded face $f$ of $G_T$, dual depth in $G_T$
equals $\min_{u \in V(f)} \ell_{G_T}(u) = \min_{u \in V(f)} \ell_G(u) -
d = \delta_G(d_f) - d$. Hence the inner-dual subgraph $(G_T)'_{k}$ at
depth $k$ in $G_T$ is the induced subgraph of $G'_{d+k}$ on the faces
of $G$ lying in $R_T$, and two such faces are dual-adjacent in $G_T'$
iff they are dual-adjacent in $G'$ (the shared edge is in $E(G_T)$).
\smallskip
\emph{Step 3: components of $(G_T)'_{k}$ are precisely the depth-$(d+k)$
descendants of $T$ in $\mathcal{T}(G, \{v_0\})$.} We show by induction
on $k$ that a component $C'$ of $G'_{d+k}$ has $F_{C'} \subseteq R_T$
iff $C'$ is a depth-$(d+k)$ descendant of $T$.
For $k = 0$: the components of $G'_d$ are the depth-$d$ treads; the
component giving rise to $T$ has its faces in $T$'s tread region
$R \subseteq R_T$, while any other depth-$d$ tread $T''$ has
$C_{T''}$ disjoint from $C_T$ and lying in a different bounded face of
$O^{(T_p'')}$ at depth $d - 1$, hence $R_{T''} \cap R_T = \emptyset$.
For $k \ge 1$: by Theorem~\ref{thm:tread-tree}, each component $C'$ of
$G'_{d+k}$ has a unique parent $C'_p$ at depth $d+k-1$, with
$B_{\mathrm{out}}^{(C')}$ bounding a face of $O^{(C'_p)}$; equivalently
$R_{C'}$ lies inside that bounded face, hence inside $R_{C'_p}$. By
the induction hypothesis $R_{C'_p} \subseteq R_T$ iff $C'_p$ is a
descendant of $T$ at depth $d+k-1$, and $R_{C'} \subseteq R_{C'_p}$, so
$R_{C'} \subseteq R_T$ iff $C'$ is a descendant of $T$ at depth $d+k$.
\smallskip
\emph{Step 4: tread data and child--face correspondence.} The
Tire-component lemma (Lemma~\ref{lem:tire-component}) and the
source-side simple-cycle property
(Proposition~\ref{prop:no-level-d-pinch}) extend verbatim to the
cycle-sourced triangulated disk $(G_T, C_T)$: the proofs use only
the triangular structure of bounded faces, the local arrangement of
faces around each vertex's rotation, and the connectivity of the BFS
ball $G_T[L_{<k}^{G_T}]$ (which holds for every $k \ge 1$ since
$L_0^{G_T} = V(C_T)$ is connected as a cycle and each higher level is
BFS-adjacent to the previous). Applied to each component of
$(G_T)'_{k}$, the lemma produces a tire graph with outer boundary
$B_{\mathrm{out}}$, inner outerplanar graph $O$, and tread region $R$
identical to those produced by the corresponding component of
$G'_{d+k}$ in $\mathcal{T}(G, \{v_0\})$, since these data depend only
on level-$d+k$ and level-$(d+k+1)$ vertices and the bounded faces in
between --- all of which are unchanged when restricting to $G_T$.
The depth-$0$ case ($k = 0$) gives a single component, namely the one
producing $T$, with root tread $B_{\mathrm{out}} = C_T$ and $O = O^{(T)}$.
The parent--child face correspondence of
Theorem~\ref{thm:tread-tree} is preserved: for any tread $T'$ in
$\mathcal{T}(G_T, C_T)$ at depth $k$, its children correspond to
non-trivial bounded faces of $O^{(T')}$, and the bounded faces of
$O^{(T')}$ together with the descendant-side interior of each are
identical in $G_T$ and in $G$.
Combining Steps 3 and 4: the bijection $C' \leftrightarrow C'$
(component of $(G_T)'_{k}$ to corresponding component of $G'_{d+k}$
inside $R_T$) lifts to a rooted-tree iso $\mathcal{T}(G_T, C_T) \to
\text{sub-tree of } \mathcal{T}(G, \{v_0\}) \text{ rooted at } T$,
preserving outer boundaries, inner outerplanar graphs, and the
parent--child face correspondence.
\end{proof}
\begin{figure}[h]
\centering
\includegraphics[width=0.95\textwidth]{fig_tire_tree_decomposition.png}
\caption{Tire-tree decomposition
(Theorem~\ref{thm:tire-tree-decomposition}) on a $13$-vertex maximal
planar example $G$ with five BFS levels. $(a)$ $G$ with vertex source
$v_0$ and $\ell_G \in \{0,1,2,3,4\}$; four nested seams are
highlighted, $C_{T_R} = \{a,b,c\}$ (orange), $C_{T_L} = \{a,c,d\}$
(red, including the chord $a$-$c$ shared with $C_{T_R}$),
$C_{T_{LL}} = \{f_1, f_2, f_3\}$ (purple), $C_{T_{LLL}} = \{g_1, g_2, g_3\}$
(teal). Inset: the rooted tree of tire treads $\mathcal{T}(G, \{v_0\})$
branches at $T_0$ into the leaf $T_R$ (containing $e$) and a chain
$T_L \to T_{LL} \to T_{LLL}$ (the highlighted sub-tree).
$(b)$ The disk $G_{T_L}$ inside the seam $C_{T_L}$, drawn standalone
with $C_{T_L}$ as cycle source and vertex labels rotated to match the
new (cycle-source) role of the boundary triangle.
$\ell_{G_{T_L}}(\cdot) = \ell_G(\cdot) - 1$ on $V(G_{T_L})$ (verified
by the generator script), and $\mathcal{T}(G_{T_L}, C_{T_L})$ is the
chain $T_L \to T_{LL} \to T_{LLL}$, iso to the highlighted sub-tree
of $(a)$.}
\label{fig:tire-tree-decomposition}
\end{figure}
\begin{remark}
\label{rem:tree-coloring-factorisation}
Combining Theorem~\ref{thm:tread-partition} (treads partition
@@ -950,6 +1134,136 @@ This is the structural setup underlying the chain-pigeonhole
program for tire treads.
\end{remark}
\begin{definition}[Seam]
\label{def:seam}
A \emph{seam} of a maximal planar graph $G$ is a simple cycle
$C \subset G$ such that, for some vertex $v_0 \in V(G)$, $C =
B_{\mathrm{out}}^{(T)}$ for some non-root tread $T$ in
$\mathcal{T}(G, \{v_0\})$.
By Theorem~\ref{thm:tire-tree-decomposition}, every seam $C$ separates
$G$ into:
\begin{itemize}
\item the \emph{seam interior} $G_T$, the triangulated disk on the
$T$-descendant side of $C$;
\item the \emph{seam exterior} $G_C^{\mathrm{ext}} := G \setminus
\mathrm{int}(G_T)$, the triangulated polygon with outer face
bounded by $C$ on the side containing $v_0$;
\end{itemize}
both sharing $C$. A seam is \emph{non-trivial} if both
$V(G_T) \setminus V(C)$ and $V(G_C^{\mathrm{ext}}) \setminus V(C)$ are
non-empty.
For any seam $C$ and either side $X \in \{G_T, G_C^{\mathrm{ext}}\}$,
write
\[
\mathrm{Col}(X \mid C) \;:=\; \bigl\{\, c|_{V(C)} \;:\; c \text{ a
proper $4$-colouring of } X \,\bigr\} \;\subseteq\; \{1,2,3,4\}^{V(C)}
\]
for the set of $C$-restricted $4$-colourings induced by $4$-colourings
of $X$ (each element is a proper $4$-colouring of the cycle $C$).
\end{definition}
\begin{definition}[Partial tire tree]
\label{def:partial-tire-tree}
Let $T_r$ be a tire tread in $\mathcal{T}(G, S)$ with outer boundary
cycle $C_{T_r} = B_{\mathrm{out}}^{(T_r)}$, and let $G_{T_r}$ be the
triangulated disk inside $C_{T_r}$ given by
Theorem~\ref{thm:tire-tree-decomposition}. The \emph{partial tire
tree} with root $T_r$, written $G_{T_r}^{\circ}$, is the induced
subgraph of $G$ on the vertex set
$V(G_{T_r}) \setminus V(C_{T_r})$ ---
i.e.\ $G_{T_r}$ with the seam-cycle vertices removed.
Equivalently, $V(G_{T_r}^{\circ})$ is the set of vertices of $G$
strictly inside $C_{T_r}$ on the side away from the level source,
and $E(G_{T_r}^{\circ})$ consists of the edges of $G$ both of whose
endpoints lie in this strict interior. The tree-of-tire-treads
structure of $G_{T_r}^{\circ}$ is the sub-tree of $\mathcal{T}(G, S)$
rooted at $T_r$, with $T_r$'s outer boundary peeled away.
\end{definition}
\begin{lemma}[Seam edges are shared by at most one other depth-$d$ seam]
\label{lem:seam-edge-shared}
Let $G$ be a maximal planar graph with single-vertex level source
$S = \{v_0\}$, fix $d \ge 1$, and let $e \in E(G)$ be an edge lying on
the seam $C_T = B_{\mathrm{out}}^{(T)}$ of some tire tread
$T \in \mathcal{T}(G, S)$ at depth $d$. Then there is at most one
other tire tread $T' \in \mathcal{T}(G, S)$ at the same depth $d$ with
$e \in C_{T'}$.
\end{lemma}
\begin{proof}
By Theorem~\ref{thm:tread-tree}, $C_T$ is the boundary cycle of a
bounded face of the parent's inner outerplanar graph $O^{(T_p)}$,
where $T_p \in \mathcal{T}(G, S)$ is the parent of $T$ at depth
$d - 1$. The inner dual of an outerplanar graph is a tree (a forest,
if the outerplanar graph is disconnected), so each edge of
$O^{(T_p)}$ lies on at most two of its bounded face cycles. Hence
$e$ lies on at most one other bounded face cycle of $O^{(T_p)}$,
corresponding (Theorem~\ref{thm:tread-tree}, child--face bijection)
to at most one sibling of $T$ at depth $d$ whose seam contains $e$.
\end{proof}
\begin{conjecture}[Seam structure of minimum $4$CT counterexamples, sketch]
\label{conj:seam-counterexample}
Suppose the Four Colour Theorem fails: there exists a maximal planar
graph that is not $4$-colourable. Let $G$ be a \emph{minimum} such
counterexample (with $|V(G)|$ minimal among non-$4$-colourable maximal
planar graphs). Then:
\medskip
\noindent\emph{Restatement-of-classical content.}
\begin{itemize}
\item[(C1)] \emph{Bilateral colourability.} For every non-trivial seam
$C$ of $G$, both $\mathrm{Col}(G_T \mid C)$ and
$\mathrm{Col}(G_C^{\mathrm{ext}} \mid C)$ are non-empty.
\item[(C2)] \emph{Bilateral incompatibility.} For every non-trivial
seam $C$,
\[
\mathrm{Col}(G_T \mid C) \;\cap\;
\mathrm{Col}(G_C^{\mathrm{ext}} \mid C) \;=\; \emptyset.
\]
\item[(C3)] \emph{Length lower bound (Birkhoff).} Every non-trivial
seam $C$ of $G$ has $|V(C)| \ge 6$.
\end{itemize}
(C1) and (C2) together restate ``$G$ is a counterexample whose every
internal cut by a seam splits into two colourable pieces with
incompatible boundary palettes''; (C1) follows from minimality applied
to each side after closing the polygonal outer face by a single apex,
(C2) from $G$ itself being non-$4$-colourable. (C3) is Birkhoff's
internally-$6$-connected condition restated in the seam language.
\medskip
\noindent\emph{Substantive (speculative) content.}
\begin{itemize}
\item[(C4)] \emph{Innermost obstruction.} There exists a vertex source
$v_0 \in V(G)$ and a \emph{leaf} tread $T^* \in
\mathcal{T}(G, \{v_0\})$ (a tread with no children in the
tree-of-treads) such that:
\begin{enumerate}
\item[(i)] the seam interior $G_{T^*}$ is, up to plane
iso, one of a finite list of \emph{minimal seam
configurations}, characterized by their boundary
palette $\mathrm{Col}(G_{T^*} \mid C_{T^*})$ being a
specific proper subset of the proper $4$-colourings
of the cycle $C_{T^*}$;
\item[(ii)] the path in $\mathcal{T}(G, \{v_0\})$ from the
root $T_0$ to $T^*$ is an \emph{obstruction chain}:
$\mathrm{Col}(G_T \mid C_T)$ is monotonically
restricted (under the natural pull-back along
parent--child seams of
Remark~\ref{rem:tree-coloring-factorisation}) as $T$
descends from the root to $T^*$, with the final
restriction at $T^*$ being incompatible with the
$v_0$-side palette.
\end{enumerate}
\end{itemize}
\end{conjecture}
\begin{thebibliography}{9}
\bibitem{tait-original}