coloring_nested_tire_graphs: drop (R1) — empirically all "pinches" are cut-vertices of O, already accommodated

Empirical evidence (from check_r2.py + classify_r1_pinches.py over
maximal planar graphs in n ∈ [7, 11]):

  Total components: 47,253
  Total claimed (R1) pinches: 1,319
  All 1,319 pinches are at level-(d+1) vertices that are cut-vertices
  of O = G[V_{C'} ∩ L_{d+1}].
  ZERO level-d pinches (which would have been a problem for B_out).

Under the relaxed Definition 1.5 (where B_in is the outer-face
boundary closed walk of O, not necessarily a simple cycle), cut-
vertices of O are naturally accommodated: the closed walk visits the
cut-vertex multiple times.  So what I previously called "(R1)
violations" are not obstructions at all — they're just structural
features of O that the closed-walk B_in captures.

Changes:
- Lemma 1.7: dropped (R1) hypothesis.  Lemma is now unconditional
  (modulo the BFS-on-the-outer-face embedding choice already in the
  setup).
- Proof: rewritten boundary-structure paragraph to describe the
  cut-vertex case naturally instead of citing (R1).
- Definition 1.5: removed the "2-manifold" assertion (since R is not
  a manifold at cut-vertices of O); added an explicit note that R may
  fail to be a 2-manifold at cut-vertices and that the closed walk
  B_in visits them multiple times.
- Remark 1.9 (was rem:R1-when): rewritten as "no extra hypotheses
  needed", documenting that both cut-vertex / multi-arc structures
  and multi-hole topology are already accommodated by Definition 1.5.

Adds experiments/check_r1_concrete.py and
experiments/classify_r1_pinches.py for verification, plus
experiments/draw_r1_candidate.py and r1_candidate.png showing the
n=9 bowtie example concretely.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-25 16:37:48 -04:00
parent 717c8cf5ea
commit 78afa9aeeb
8 changed files with 486 additions and 57 deletions
@@ -0,0 +1,122 @@
"""Find a concrete claimed (R1) violation and verify it by hand.
Iterate over small maximal planar graphs, for each single-vertex source
find a depth-d component flagged as having a pinch vertex by the cyclic-
rotation check. Save the graph + the pinch vertex's rotation, the
depth of each face incident to the pinch vertex, and the cyclic
sequence of "is this face in the component?" booleans.
"""
import sys
from collections import defaultdict
from sage.all import Graph
from sage.graphs.graph_generators import graphs
def face_edges_set(face):
return frozenset(frozenset(e) for e in face)
def main():
for n in range(7, 12):
for G in graphs.triangulations(n):
G.is_planar(set_embedding=True)
emb = G.get_embedding()
faces = G.faces(embedding=emb)
for v_source in G.vertices():
dist = G.shortest_path_lengths(v_source)
face_depths = []
for face in faces:
verts = set()
for u, v in face:
verts.add(u); verts.add(v)
d = min(dist[u] for u in verts)
face_depths.append((face, d, verts))
max_d = max(fd[1] for fd in face_depths)
for target_d in range(max_d + 1):
cands = [(i, fd) for i, fd in enumerate(face_depths)
if fd[1] == target_d]
if not cands:
continue
edge_to_idxs = defaultdict(list)
for k, (i, fd) in enumerate(cands):
for e in [frozenset(ed) for ed in fd[0]]:
edge_to_idxs[e].append(k)
n_c = len(cands)
adj = [[] for _ in range(n_c)]
for idxs in edge_to_idxs.values():
if len(idxs) >= 2:
for a in idxs:
for b in idxs:
if a != b:
adj[a].append(b)
visited = [False] * n_c
comps = []
for s in range(n_c):
if visited[s]:
continue
stack = [s]; comp = []
while stack:
x = stack.pop()
if visited[x]: continue
visited[x] = True; comp.append(cands[x])
for y in adj[x]:
if not visited[y]: stack.append(y)
comps.append(comp)
for comp in comps:
comp_fes_set = {face_edges_set(fd[0])
for _, fd in comp}
vertices = set()
for fes in comp_fes_set:
for e in fes:
vertices.update(e)
for v in vertices:
rot = emb[v]
in_c = []
for i in range(len(rot)):
u = rot[i]
w = rot[(i + 1) % len(rot)]
tri = frozenset({frozenset({v, u}),
frozenset({u, w}),
frozenset({v, w})})
in_c.append(tri in comp_fes_set)
n_true = sum(in_c)
if n_true == 0 or n_true == len(in_c):
continue
n_runs = sum(
1 for i in range(len(in_c))
if in_c[i] and not in_c[(i - 1) % len(in_c)])
if n_runs > 1:
# Found one
print(f"=== R1 violation candidate ===")
print(f"n={n}, source={v_source}, "
f"depth={target_d}, pinch vertex={v}")
print(f"edges of G: "
f"{sorted([tuple(sorted(e)) for e in G.edges(labels=False)])}")
print(f"BFS distances: {dict(dist)}")
print(f"rotation around v={v}: {rot}")
lvls = [dist[u] for u in rot]
print(f" levels: {lvls}")
face_depths_around_v = []
for i in range(len(rot)):
u = rot[i]
w = rot[(i + 1) % len(rot)]
d_face = min(dist[v], dist[u], dist[w])
face_depths_around_v.append(d_face)
print(f" face depths: {face_depths_around_v}")
print(f" in_component: {in_c}")
print(f" n_runs of True: {n_runs}")
# Also list the depth-d faces at v
d_target_at_v = [
(rot[i], rot[(i + 1) % len(rot)])
for i in range(len(rot))
if face_depths_around_v[i] == target_d
]
print(f" depth-{target_d} faces at v: "
f"{d_target_at_v}")
return
if __name__ == '__main__':
main()
@@ -0,0 +1,146 @@
"""For each claimed (R1) pinch vertex, classify it as:
(a) a cut-vertex of O = G[L_{d+1} cap V_{C'}] (level d+1 pinch)
(b) a cut-vertex of G[L_d cap V_{C'}] (level d pinch)
(c) other
"""
import sys
from collections import defaultdict
from sage.all import Graph
from sage.graphs.graph_generators import graphs
def face_edges_set(face):
return frozenset(frozenset(e) for e in face)
def is_cut_vertex(G, v):
"""Return True if removing v disconnects the connected component of v."""
if v not in G:
return False
H = G.copy()
H.delete_vertex(v)
if H.order() == 0:
return False
return not H.is_connected()
def main():
counts = defaultdict(int)
n_components = 0
n_pinches = 0
sample_each = {}
for n in range(7, 12):
for G in graphs.triangulations(n):
G.is_planar(set_embedding=True)
emb = G.get_embedding()
faces = G.faces(embedding=emb)
for v_source in G.vertices():
dist = G.shortest_path_lengths(v_source)
face_depths = []
for face in faces:
verts = set()
for u, v in face:
verts.add(u); verts.add(v)
d = min(dist[u] for u in verts)
face_depths.append((face, d, verts))
max_d = max(fd[1] for fd in face_depths)
for target_d in range(max_d + 1):
cands = [(i, fd) for i, fd in enumerate(face_depths)
if fd[1] == target_d]
if not cands:
continue
edge_to_idxs = defaultdict(list)
for k, (i, fd) in enumerate(cands):
for e in [frozenset(ed) for ed in fd[0]]:
edge_to_idxs[e].append(k)
n_c = len(cands)
adj = [[] for _ in range(n_c)]
for idxs in edge_to_idxs.values():
if len(idxs) >= 2:
for a in idxs:
for b in idxs:
if a != b:
adj[a].append(b)
visited = [False] * n_c
comps = []
for s in range(n_c):
if visited[s]:
continue
stack = [s]; comp = []
while stack:
x = stack.pop()
if visited[x]: continue
visited[x] = True; comp.append(cands[x])
for y in adj[x]:
if not visited[y]: stack.append(y)
comps.append(comp)
for comp in comps:
n_components += 1
comp_fes_set = {face_edges_set(fd[0])
for _, fd in comp}
vertices_in_comp = set()
for fes in comp_fes_set:
for e in fes:
vertices_in_comp.update(e)
Vd = {v for v in vertices_in_comp if dist[v] == target_d}
Vdp1 = {v for v in vertices_in_comp if dist[v] == target_d + 1}
O = G.subgraph(vertices=list(Vdp1))
Bout_graph = G.subgraph(vertices=list(Vd))
for v in vertices_in_comp:
rot = emb[v]
in_c = []
for i in range(len(rot)):
u = rot[i]
w = rot[(i + 1) % len(rot)]
tri = frozenset({frozenset({v, u}),
frozenset({u, w}),
frozenset({v, w})})
in_c.append(tri in comp_fes_set)
n_true = sum(in_c)
if n_true == 0 or n_true == len(in_c):
continue
n_runs = sum(
1 for i in range(len(in_c))
if in_c[i] and not in_c[(i - 1) % len(in_c)])
if n_runs <= 1:
continue
# Pinch at v. Classify.
n_pinches += 1
level_v = dist[v]
if level_v == target_d:
lvl_label = 'd'
# Check if v is a cut vertex of B_out_graph
cut_bout = is_cut_vertex(Bout_graph, v)
key = ('d', cut_bout)
elif level_v == target_d + 1:
lvl_label = 'd+1'
cut_o = is_cut_vertex(O, v)
key = ('d+1', cut_o)
else:
key = ('other', None)
counts[key] += 1
if key not in sample_each:
sample_each[key] = {
'n': n, 'source': int(v_source),
'depth': target_d, 'pinch_v': v,
'level_v': level_v,
'edges': sorted(tuple(sorted(e))
for e in G.edges(labels=False)),
}
print(f"Total components: {n_components}")
print(f"Total pinches: {n_pinches}")
print()
print("Classification by (level of pinch, is cut-vertex of corresponding side):")
for k, c in sorted(counts.items()):
print(f" {k}: {c}")
print()
print("Samples:")
for k, sample in sample_each.items():
print(f" key={k}: {sample}")
if __name__ == '__main__':
main()
@@ -0,0 +1,172 @@
"""Draw the claimed (R1) violation: n=9, source=5, depth=1, vertex 9.
The depth-1 component has 9 triangles, and vertex 9 has 4 of them
incident (in two arcs of the rotation around 9, separated by 2
depth-2 faces -- the two triangles of the bowtie at L_2).
The question: is vertex 9 a real "pinch" of the tire, or is it just
a cut-vertex of the inner outerplanar graph O (= the bowtie on
{2, 3, 7, 8, 9}), naturally handled by the relaxed Definition 1.5?
"""
import math
import os
import sys
from collections import defaultdict
from sage.all import Graph
import matplotlib.pyplot as plt
import matplotlib.patches as patches
HERE = os.path.dirname(os.path.abspath(__file__))
EDGES = [(1, 2), (1, 3), (1, 4), (1, 5), (1, 6), (1, 7), (1, 8), (1, 9),
(2, 3), (2, 9), (3, 4), (3, 9), (4, 5), (4, 6), (4, 7), (4, 9),
(5, 6), (6, 7), (7, 8), (7, 9), (8, 9)]
SOURCE = 5
def main():
G = Graph(EDGES)
G.is_planar(set_embedding=True)
emb = G.get_embedding()
dist = G.shortest_path_lengths(SOURCE)
# Pick an external face that doesn't contain source 5 so source
# ends up in the interior.
# Faces of G that don't contain 5: triangle {1,2,3} for example.
pos = G.layout(layout='planar', external_face=(1, 2))
# Normalise
xs = [p[0] for p in pos.values()]; ys = [p[1] for p in pos.values()]
cx, cy = (max(xs)+min(xs))/2, (max(ys)+min(ys))/2
scale = max(max(xs)-min(xs), max(ys)-min(ys))
pos = {v: ((p[0]-cx)/scale, (p[1]-cy)/scale) for v, p in pos.items()}
faces = G.faces(embedding=emb)
face_depths = []
for face in faces:
verts = set()
for u, v in face:
verts.add(u); verts.add(v)
d = min(dist[u] for u in verts)
face_depths.append((face, d, verts))
depth1_faces = [fd for fd in face_depths if fd[1] == 1]
depth2_faces = [fd for fd in face_depths if fd[1] == 2]
fig, ax = plt.subplots(figsize=(10, 9))
# Fill depth-1 faces (R_{C'})
for face, _, _ in depth1_faces:
verts = [e[0] for e in face]
xy = [pos[v] for v in verts]
poly = plt.Polygon(xy, facecolor='#fff3cd', edgecolor='#e8d8a8',
linewidth=0.5, alpha=0.85, zorder=1)
ax.add_patch(poly)
# Fill depth-2 faces (the bowtie's two triangles) in a different colour
for face, _, _ in depth2_faces:
verts = [e[0] for e in face]
xy = [pos[v] for v in verts]
poly = plt.Polygon(xy, facecolor='#d62728', edgecolor='#a01818',
linewidth=0.5, alpha=0.40, zorder=1)
ax.add_patch(poly)
# All edges of G in grey
for u, v in G.edges(labels=False):
x1, y1 = pos[u]; x2, y2 = pos[v]
ax.plot([x1, x2], [y1, y2], color='lightgray', linewidth=1.0,
zorder=2)
# Highlight the bowtie edges (= edges of O = G[L_2])
L2 = [v for v in G.vertices() if dist[v] == 2]
print(f"L_2 = {sorted(L2)}")
bowtie_edges = [(u, v) for u, v in G.edges(labels=False)
if u in L2 and v in L2]
print(f"Edges of O = G[L_2]: {bowtie_edges}")
for u, v in bowtie_edges:
x1, y1 = pos[u]; x2, y2 = pos[v]
ax.plot([x1, x2], [y1, y2], color='#a01818', linewidth=3.0,
zorder=3)
# Highlight the source-side cycle = G[L_1]
L1 = [v for v in G.vertices() if dist[v] == 1]
print(f"L_1 = {sorted(L1)}")
L1_edges = [(u, v) for u, v in G.edges(labels=False)
if u in L1 and v in L1]
print(f"Edges of B_out candidate = G[L_1]: {L1_edges}")
for u, v in L1_edges:
x1, y1 = pos[u]; x2, y2 = pos[v]
ax.plot([x1, x2], [y1, y2], color='#1f77b4', linewidth=3.0,
zorder=3)
# Vertices
level_colors = {0: 'black', 1: '#1f77b4', 2: '#d62728'}
for v in G.vertices():
x, y = pos[v]
c = level_colors.get(dist[v], 'gray')
ax.plot(x, y, 'o', color=c, markersize=22, zorder=4)
ax.annotate(f"{v}", (x, y), color='white', ha='center', va='center',
fontsize=11, fontweight='bold', zorder=5)
# Special annotation: vertex 9 is the cut-vertex of O
if 9 in pos:
x, y = pos[9]
ax.annotate('cut-vertex of $O$',
xy=(x, y), xytext=(x + 0.10, y + 0.18),
fontsize=10, color='#a01818', fontweight='bold',
arrowprops=dict(arrowstyle='->', color='#a01818', lw=1.5),
zorder=6,
bbox=dict(boxstyle='round,pad=0.25',
facecolor='white', edgecolor='#a01818',
alpha=0.95))
if SOURCE in pos:
sx, sy = pos[SOURCE]
ax.annotate(f'source $v_0={SOURCE}$',
xy=(sx, sy), xytext=(sx + 0.08, sy + 0.10),
fontsize=10, color='black', fontweight='bold',
arrowprops=dict(arrowstyle='->', color='black', lw=1.2),
zorder=6,
bbox=dict(boxstyle='round,pad=0.2',
facecolor='white', edgecolor='gray', alpha=0.95))
legend_items = [
plt.Line2D([], [], marker='o', color='w', markerfacecolor='black',
markersize=12, label=f'source ($\\ell=0$)'),
plt.Line2D([], [], marker='o', color='w', markerfacecolor='#1f77b4',
markersize=12, label='$\\ell=1$'),
plt.Line2D([], [], marker='o', color='w', markerfacecolor='#d62728',
markersize=12, label='$\\ell=2$'),
patches.Patch(facecolor='#fff3cd', edgecolor='#e8d8a8',
label='$R_{C^\\prime}$ (depth-1 component, '
'9 triangles)'),
patches.Patch(facecolor='#d62728', alpha=0.4,
label='depth-2 faces (interior faces of $O$)'),
plt.Line2D([], [], color='#1f77b4', linewidth=3.0,
label='$B_{\\mathrm{out}} = G[L_1]$'),
plt.Line2D([], [], color='#a01818', linewidth=3.0,
label='$O = G[L_2]$ = bowtie with cut-vertex 9'),
]
ax.legend(handles=legend_items, loc='upper right', fontsize=9,
framealpha=0.95)
ax.set_title(
'"(R1) candidate": vertex 9 is a cut-vertex of $O$ (the bowtie),\n'
'not a true pinch of the tire under the relaxed Definition 1.5\n'
'(n=9, source $v_0=5$, depth 1)',
fontsize=11)
ax.set_aspect('equal')
ax.axis('off')
pad = 0.08
ax.set_xlim(min(p[0] for p in pos.values()) - pad,
max(p[0] for p in pos.values()) + pad)
ax.set_ylim(min(p[1] for p in pos.values()) - pad,
max(p[1] for p in pos.values()) + pad)
out = os.path.join(HERE, 'r1_candidate.png')
plt.savefig(out, dpi=160, bbox_inches='tight')
plt.close()
print(f"wrote {out}")
if __name__ == '__main__':
main()
Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

+2 -2
View File
@@ -4,12 +4,12 @@
\@writefile{lof}{\contentsline {figure}{\numberline {1}{\ignorespaces Dual depth in a stacked-ring triangulation $G$ with level source $S = \{0\}$. Each $G$ vertex is labelled by its level $\ell $. Each bounded face carries a dual vertex (square, joined by dashed dual edges) coloured by its dual depth $\delta (d_f) = \qopname \relax m{min}_{v \in V(f)} \ell (v)$: the central fan has depth $0$, the inner annulus depth $1$, and the outer annulus depth $2$. The outer face (the level-$3$ triangle) is excluded from the inner dual and carries no dual vertex.}}{2}{}\protected@file@percent }
\newlabel{fig:dual-depth}{{1}{2}}
\newlabel{def:tire-graph}{{1.5}{2}}
\citation{bauerfeld-pds}
\@writefile{lof}{\contentsline {figure}{\numberline {2}{\ignorespaces A tire graph with non-degenerate boundaries: outer boundary $B_{\mathrm {out}}$ a $6$-cycle on vertices $0,\dots ,5$ (blue), inner boundary $B_{\mathrm {in}}$ a $4$-cycle on vertices $6,\dots ,9$ (red), inner outerplanar graph $O = B_{\mathrm {in}} \cup \{7\text {--}9\}$ (with one chord, orange), and $E_{\mathrm {ann}}$ (grey) tiling the annulus between $B_{\mathrm {out}}$ and $B_{\mathrm {in}}$ by ten triangular faces.}}{3}{}\protected@file@percent }
\newlabel{fig:tire-example}{{2}{3}}
\newlabel{rem:tire-counts}{{1.6}{3}}
\newlabel{lem:tire-component}{{1.7}{3}}
\citation{bauerfeld-pds}
\citation{bauerfeld-pds}
\bibcite{bauerfeld-pds}{1}
\newlabel{tocindent-1}{0pt}
\newlabel{tocindent0}{12.7778pt}
@@ -17,6 +17,6 @@
\newlabel{tocindent2}{0pt}
\newlabel{tocindent3}{0pt}
\newlabel{rem:tire-component-degenerate}{{1.8}{5}}
\newlabel{rem:R1-when}{{1.9}{5}}
\newlabel{rem:tire-no-extra-hypotheses}{{1.9}{5}}
\@writefile{toc}{\contentsline {section}{\tocsection {}{}{References}}{5}{}\protected@file@percent }
\gdef \@abspage@last{5}
+5 -5
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) 25 MAY 2026 16:26
This is pdfTeX, Version 3.141592653-2.6-1.40.24 (TeX Live 2022) (preloaded format=pdflatex 2022.10.5) 25 MAY 2026 16:37
entering extended mode
restricted \write18 enabled.
%&-line parsing enabled.
@@ -205,13 +205,13 @@ LaTeX Warning: `h' float specifier changed to `ht'.
<fig_tire_example.png, id=24, 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 158.
Package pdftex.def Info: fig_tire_example.png used on input line 160.
(pdftex.def) Requested size: 280.79956pt x 188.56097pt.
[3 <./fig_tire_example.png>] [4] [5] (./paper.aux) )
Here is how much of TeX's memory you used:
3007 strings out of 478268
41998 string characters out of 5846347
343166 words of memory out of 5000000
42015 string characters out of 5846347
344166 words of memory out of 5000000
21054 multiletter control sequences out of 15000+600000
475666 words of font info for 53 fonts, out of 8000000 for 9000
1302 hyphenation exceptions out of 8191
@@ -233,7 +233,7 @@ e1/public/amsfonts/cm/cmsy5.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1
ublic/amsfonts/cm/cmti10.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/pu
blic/amsfonts/cm/cmti8.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/publ
ic/amsfonts/symbols/msam10.pfb>
Output written on paper.pdf (5 pages, 486084 bytes).
Output written on paper.pdf (5 pages, 483570 bytes).
PDF statistics:
105 PDF objects out of 1000 (max. 8388607)
61 compressed objects within 1 object stream
Binary file not shown.
+39 -50
View File
@@ -145,12 +145,14 @@ $B_{\mathrm{in}}$ is partitioned into triangular faces of $T$ whose
union is $R$.
When $B_{\mathrm{out}}$ is a simple cycle and $O$ is $2$-connected,
$R$ is a closed annulus. More generally, $R$ is a planar
$2$-manifold with boundary whose inner boundary may be a closed walk
rather than a simple cycle, accommodating outerplanar inner graphs
with bridges, cut-vertices, or multiple connected components. When
either boundary is degenerate, $R$ is a closed disk with that vertex
as apex.
$R$ is a closed annulus. More generally, $R$ is a closed planar
region that may fail to be a $2$-manifold at cut-vertices of $O$ (where
two ``lobes'' of the depth-$d$ region meet at a single vertex); the
inner boundary $B_{\mathrm{in}}$ is then a non-simple closed walk that
visits the cut-vertex multiple times. The relaxed definition
accommodates outerplanar inner graphs with bridges, cut-vertices, or
multiple connected components. When either boundary is degenerate,
$R$ is a closed disk with that vertex as apex.
\end{definition}
\begin{figure}[h]
@@ -192,13 +194,6 @@ $V_{C'} := \bigcup_{f \in F_{C'}} V(f)$, and let $C := G[V_{C'}]$ inherit
its embedding from $\Pi_G$. Set $R_{C'} := \bigcup_{f \in F_{C'}} f
\subseteq |\Pi_G|$.
Assume:
\begin{itemize}
\item[\emph{(R1)}] $R_{C'}$ is a topological $2$-manifold with boundary;
equivalently, at every $v \in V_{C'}$ the faces of $F_{C'}$
incident to $v$ form a single contiguous arc in the rotation
around $v$ in $\Pi_G$.
\end{itemize}
Then $C$, with the inherited embedding, is a tire graph in the sense of
Definition~\ref{def:tire-graph}. Its outer boundary
$B_{\mathrm{out}}$ is the side of $R_{C'}$ closer to $S$ in $\Pi_G$,
@@ -251,14 +246,14 @@ incident to it (by R1, see below), both of the same type, so its
level is fixed. Therefore each boundary component of $\partial R_{C'}$
is monochromatic in level.
\emph{Boundary structure.} By hypothesis (R1), $R_{C'}$ is a
$2$-manifold with boundary, so locally at any boundary point $p$ the
region $R_{C'}$ is homeomorphic to a half-disk; the boundary
$\partial R_{C'}$ is therefore a disjoint union of simple closed
curves in $|\Pi_G|$. Each such curve traces a closed walk in $G$
visiting each of its vertices exactly once (a simple cycle), and the
monochromaticity above forces the entire curve to lie in either
$L_d$ or $L_{d+1}$.
\emph{Boundary structure.} Each connected component of
$\partial R_{C'}$ traces a closed walk in $G$ that, by the
monochromaticity above, lies entirely in $L_d$ or entirely in
$L_{d+1}$. At a vertex $v \in V_{C'}$ where the faces of $F_{C'}$
split into multiple arcs of $v$'s rotation, the boundary walk visits
$v$ correspondingly many times; this occurs precisely when $v$ is a
cut-vertex of the induced subgraph on its level (either $L_d$ or
$L_{d+1}$).
\emph{Outer boundary.} Because $S$ lies on the outer face of $\Pi_G$,
the boundary curve(s) of $R_{C'}$ on the $L_d$ side are closer to $S$
@@ -306,37 +301,31 @@ the level-$D_{\max}$ cycle as the outer boundary.
\end{remark}
\begin{remark}
\label{rem:R1-when}
Hypothesis (R1) of Lemma~\ref{lem:tire-component} holds in many
natural settings but can fail. (R1) fails at a \emph{pinch vertex}
$v \in V_{C'}$ when the faces of $F_{C'}$ incident to $v$ split into
two or more disjoint arcs of the rotation around $v$ in $\Pi_G$.
Such a $v$ has at least four neighbours $w_i, w_{i+1}, w_j, w_{j+1}$
(with $i + 1 < j$) in cyclic order such that the faces
$\{v, w_i, w_{i+1}\}$ and $\{v, w_j, w_{j+1}\}$ are both depth-$d$
while at least one face in each of the rotation gaps between them
carries depth $\neq d$. Concretely, this occurs precisely when the
cyclic level sequence $\ell(w_1), \ldots, \ell(w_{\deg v})$ enters and
leaves $\{d, d+1\}$ more than once. Whenever such a $v$ exists and
the two arcs are joined to a common component of $G'_d$ by some
\emph{other} path of depth-$d$ faces (not through $v$), the resulting
$R_{C'}$ is a wedge of two manifold regions at $v$, violating (R1).
\label{rem:tire-no-extra-hypotheses}
Two structural features of $R_{C'}$ that might at first appear to
obstruct the tire-graph conclusion are both already accommodated by
Definition~\ref{def:tire-graph}:
Multi-hole topology (where $R_{C'}$ encloses several disjoint
depth-$>d$ sub-regions) does \emph{not} require an additional
hypothesis: the inner outerplanar graph $O = G[V_{C'} \cap L_{d+1}]$
captures the multi-hole structure as a disconnected (or
non-$2$-connected) outerplanar graph, and its outer-face boundary
closed walk serves as $B_{\mathrm{in}}$. In particular, two disjoint
$L_{d+1}$ triangles inside $R_{C'}$ joined by a bridge edge in $O$
give a $B_{\mathrm{in}}$ that traverses the bridge twice and visits
the bridge endpoints twice each --- not a simple cycle, but a
well-defined closed walk on $V(O)$.
\emph{Cut-vertices of $O$.} A vertex $v \in V_{C'} \cap L_{d+1}$ may
have the faces of $F_{C'}$ incident to it split into two or more
arcs in $v$'s rotation in $\Pi_G$, separated by faces of higher
depth. This corresponds exactly to $v$ being a cut-vertex of
$O = G[V_{C'} \cap L_{d+1}]$, and the inner boundary closed walk
$B_{\mathrm{in}}$ then visits $v$ multiple times --- once for each
arc. No additional hypothesis is needed.
In the special case $d = 0$ with single-vertex source $S = \{v_0\}$
(R1) holds automatically: $R_{C'}$ is the star of $v_0$, a topological
closed disk with one boundary cycle (the link of $v_0$), giving a
tire graph with degenerate outer boundary $\{v_0\}$.
\emph{Multi-hole topology of $R_{C'}$.} Even when $R_{C'}$ encloses
several disjoint depth-$>d$ sub-regions, the inner outerplanar graph
$O$ captures the multi-hole structure as a disconnected or
non-$2$-connected outerplanar graph (with bridges or multiple
components), and its outer-face boundary closed walk serves as
$B_{\mathrm{in}}$ traversing bridges twice and visiting cut-vertices
multiple times.
In the special case $d = 0$ with single-vertex source $S = \{v_0\}$,
$R_{C'}$ is the star of $v_0$, a topological closed disk with one
boundary cycle (the link of $v_0$); the corresponding tire graph has
degenerate outer boundary $\{v_0\}$.
\end{remark}
\begin{thebibliography}{9}