coloring_nested_tire_graphs: add Figure 5 illustrating Def 1.15 in the bridge case

Adds fig_facial_dual_choices.png showing T'_{f'} for the three faces
A, B, C of T'_ann = θ(1, 3, 3) in the bridge case:

  Face A (outer): V(A) = all 6 vertices; T'_A pulls in all four
    external neighbors u_1, u_2, u_4, u_5.

  Face B (inner right): V(B) = {v_0, v_1, v_2, v_3}; T'_B pulls in
    only u_1, u_2 and the cycle-neighbors v_4, v_5.

  Face C (inner left): mirror image of B.

The figure also visually conveys that the chord endpoints v_0, v_3
(= the two annular faces sharing the bridge edge) have all three
G'-edges inside T'_ann, so neither contributes an external u_v.

Adds:
- experiments/draw_facial_dual_choices.py
- notes/fig_facial_dual_choices.png
- Figure 5 in paper.tex referencing the new image.

Paper grows from 9 to 10 pages.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-25 22:42:14 -04:00
parent 4a2df75773
commit 8faf37a9dc
6 changed files with 213 additions and 11 deletions
@@ -0,0 +1,171 @@
"""For the bridge case where T'_ann = theta(1, p, q) has three faces,
illustrate how the partial tire facial dual T'_{f'} (Definition 1.15)
depends on the choice of face f'.
We use theta(1, 3, 3) = C_6 + chord (v_0, v_3) as the smallest
example. In the inherited planar embedding theta(1, 3, 3) has three
faces:
Face A (outer/unbounded): V(A) = {v_0, ..., v_5} (all 6 vertices).
Face B (inner, right side): V(B) = {v_0, v_1, v_2, v_3}.
Face C (inner, left side): V(C) = {v_0, v_3, v_4, v_5}.
In the surrounding maximal-planar G, each non-chord annular dual
vertex (v_1, v_2, v_4, v_5) has one external G'-neighbor (corresponding
to a non-annular face of G across a boundary edge of T). The chord
endpoints v_0, v_3 have all three G'-edges inside T'_ann (= 2 cycle
edges + chord edge), so no external neighbors.
T'_{f'} is the closed G'-neighborhood of V(f') together with every
G'-edge incident to V(f').
"""
import math
import os
import matplotlib.pyplot as plt
import matplotlib.patches as patches
# Hexagon positions: v_0 at top, v_3 at bottom, so chord v_0-v_3 is vertical.
def hex_pos(scale=1.0):
pos = {}
for i in range(6):
angle = math.pi / 2 - 2 * math.pi * i / 6
pos[i] = (scale * math.cos(angle), scale * math.sin(angle))
return pos
# External neighbors of v_1, v_2, v_4, v_5 (drawn radially outward).
def ext_pos(scale=1.0, radial=1.8):
pos = hex_pos(scale)
ext = {}
for v in (1, 2, 4, 5):
x, y = pos[v]
nx, ny = x / math.hypot(x, y), y / math.hypot(x, y)
ext[v] = (radial * nx, radial * ny)
return ext
CYCLE_EDGES = [(i, (i + 1) % 6) for i in range(6)]
CHORD = (0, 3)
def draw_panel(ax, vfp, title, show_external_for, face_shade=None,
face_shade_color='#ffe9a1', external_labels=True):
"""Render one panel showing T'_ann (faint) with V(f') highlighted
(dark) and T'_{f'} edges + external neighbors highlighted."""
pos = hex_pos()
ext = ext_pos()
# Shade the chosen face (optional)
if face_shade is not None:
ax.add_patch(patches.Polygon(face_shade, closed=True,
facecolor=face_shade_color,
edgecolor='none', alpha=0.55, zorder=0))
# Draw faint version of T'_ann (cycle + chord) underneath
for u, v in CYCLE_EDGES:
x1, y1 = pos[u]; x2, y2 = pos[v]
ax.plot([x1, x2], [y1, y2], color='#cccccc', linewidth=2.0,
zorder=1)
x1, y1 = pos[CHORD[0]]; x2, y2 = pos[CHORD[1]]
ax.plot([x1, x2], [y1, y2], color='#cccccc', linewidth=2.0,
linestyle=(0, (3, 2)), zorder=1)
# Highlight T'_{f'} edges: any G'-edge incident to V(f')
highlight = '#1f77b4'
for u, v in CYCLE_EDGES:
if u in vfp or v in vfp:
x1, y1 = pos[u]; x2, y2 = pos[v]
ax.plot([x1, x2], [y1, y2], color=highlight, linewidth=3.2,
zorder=2)
if CHORD[0] in vfp or CHORD[1] in vfp:
x1, y1 = pos[CHORD[0]]; x2, y2 = pos[CHORD[1]]
ax.plot([x1, x2], [y1, y2], color=highlight, linewidth=3.2,
linestyle=(0, (3, 2)), zorder=2)
# External edges from V(f') ∩ {v_1, v_2, v_4, v_5}
for v in show_external_for:
if v in vfp:
x1, y1 = pos[v]; x2, y2 = ext[v]
ax.plot([x1, x2], [y1, y2], color=highlight, linewidth=3.2,
zorder=2)
# Draw vertices: V(f') dark, others light
for v in range(6):
x, y = pos[v]
if v in vfp:
ax.plot(x, y, 'o', color='#1f3f70', markersize=18, zorder=3)
tcol = 'white'
else:
ax.plot(x, y, 'o', color='#bbbbbb', markersize=14, zorder=3)
tcol = 'white'
ax.annotate(f"$v_{v}$", (x, y), color=tcol, ha='center',
va='center', fontsize=9, fontweight='bold', zorder=4)
# External neighbors (drawn only if they're added to T'_{f'})
for v in show_external_for:
if v in vfp:
x, y = ext[v]
ax.plot(x, y, 's', color='#d62728', markersize=12, zorder=3)
if external_labels:
ax.annotate(f"$u_{v}$", (x, y), color='white', ha='center',
va='center', fontsize=7, fontweight='bold',
zorder=4)
ax.set_xlim(-2.2, 2.2)
ax.set_ylim(-2.2, 2.2)
ax.set_aspect('equal'); ax.axis('off')
ax.set_title(title, fontsize=10)
def main():
here = os.path.dirname(os.path.abspath(__file__))
out = os.path.join(here, '..', 'notes', 'fig_facial_dual_choices.png')
out = os.path.normpath(out)
pos = hex_pos()
fig, axes = plt.subplots(1, 3, figsize=(12.0, 4.6))
# External neighbors only exist for non-chord vertices
ext_candidates = {1, 2, 4, 5}
# ---- Face A: outer (all 6 vertices) ----
vA = {0, 1, 2, 3, 4, 5}
# Outer face shading: a frame outside the hexagon. Skip explicit shading.
draw_panel(axes[0], vA,
title=r"Face $A$ (outer): $V(A) = \{v_0,\dots,v_5\}$" + "\n" +
r"$T'_{f'=A}$: full $\theta(1,3,3)$ + 4 external neighbors",
show_external_for=ext_candidates)
# ---- Face B: inner right (v_0, v_1, v_2, v_3) ----
vB = {0, 1, 2, 3}
shadeB = [pos[i] for i in (0, 1, 2, 3)]
draw_panel(axes[1], vB,
title=r"Face $B$ (inner right): $V(B) = \{v_0,v_1,v_2,v_3\}$" + "\n"
+ r"$T'_{f'=B}$: includes $v_4, v_5$ via $v_0v_5, v_3v_4$",
show_external_for=ext_candidates,
face_shade=shadeB)
# ---- Face C: inner left (v_0, v_3, v_4, v_5) ----
vC = {0, 3, 4, 5}
shadeC = [pos[i] for i in (0, 5, 4, 3)]
draw_panel(axes[2], vC,
title=r"Face $C$ (inner left): $V(C) = \{v_0,v_3,v_4,v_5\}$" + "\n"
+ r"$T'_{f'=C}$: mirror image of $B$",
show_external_for=ext_candidates,
face_shade=shadeC)
fig.suptitle(r"Partial tire facial dual $T'_{f'}$ for the bridge case " +
r"($T'_{\mathrm{ann}} = \theta(1,3,3)$, three faces $A,B,C$)" + "\n" +
r"Blue: edges of $T'_{f'}$. Dark circles: $V(f')$. " +
r"Red squares: external $G'$-neighbors $u_v$ included via $v \in V(f')$.",
fontsize=11, y=1.02)
plt.tight_layout()
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: 74 KiB

+3 -1
View File
@@ -30,4 +30,6 @@
\newlabel{def:partial-tire-facial-dual}{{1.15}{9}}
\newlabel{rem:facial-dual-spoke-only}{{1.16}{9}}
\@writefile{toc}{\contentsline {section}{\tocsection {}{}{References}}{9}{}\protected@file@percent }
\gdef \@abspage@last{9}
\@writefile{lof}{\contentsline {figure}{\numberline {5}{\ignorespaces The bridge case: $T'_{\mathrm {ann}} = \theta (1, 3, 3)$ has three faces $A, B, C$ in its inherited embedding, with respective vertex sets $V(A) = \{v_0, \dots , v_5\}$, $V(B) = \{v_0, v_1, v_2, v_3\}$, and $V(C) = \{v_0, v_3, v_4, v_5\}$. In the surrounding maximal planar $G$, the chord endpoints $v_0, v_3$ (the two annular faces sharing the bridge edge) have all three $G'$-edges inside $T'_{\mathrm {ann}}$, while each non-chord vertex $v_i$ ($i \in \{1, 2, 4, 5\}$) contributes one $G'$-edge to an external non-annular neighbor $u_i$. Each panel highlights $T'_{f'}$ (blue) inside $G'$: dark circles are $V(f')$, gray circles are $G'$-neighbors of $V(f')$ within $T'_{\mathrm {ann}}$, and red squares are external $G'$-neighbors $u_i$. The choice of face $f'$ controls which external neighbors $u_i$ are pulled into $T'_{f'}$ (face $A$ pulls in all four; face $B$ pulls in $u_1, u_2$ and face $C$ pulls in $u_4, u_5$).}}{10}{}\protected@file@percent }
\newlabel{fig:facial-dual-choices}{{5}{10}}
\gdef \@abspage@last{10}
+19 -10
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 22:36
This is pdfTeX, Version 3.141592653-2.6-1.40.24 (TeX Live 2022) (preloaded format=pdflatex 2022.10.5) 25 MAY 2026 22:42
entering extended mode
restricted \write18 enabled.
%&-line parsing enabled.
@@ -228,16 +228,25 @@ LaTeX Warning: `h' float specifier changed to `ht'.
LaTeX Warning: Reference `def:dual' on page 9 undefined on input line 575.
[9] (./paper.aux)
<notes/fig_facial_dual_choices.png, id=53, 857.75456pt x 341.92744pt>
File: notes/fig_facial_dual_choices.png Graphic file (type png)
<use notes/fig_facial_dual_choices.png>
Package pdftex.def Info: notes/fig_facial_dual_choices.png used on input line
627.
(pdftex.def) Requested size: 360.0pt x 143.50418pt.
LaTeX Warning: `h' float specifier changed to `ht'.
[9] [10 <./notes/fig_facial_dual_choices.png>] (./paper.aux)
LaTeX Warning: There were undefined references.
)
Here is how much of TeX's memory you used:
3031 strings out of 478268
42740 string characters out of 5846347
344259 words of memory out of 5000000
21076 multiletter control sequences out of 15000+600000
3040 strings out of 478268
43027 string characters out of 5846347
344270 words of memory out of 5000000
21083 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
69i,8n,76p,1079b,316s stack positions out of 10000i,1000n,20000p,200000b,200000s
@@ -257,10 +266,10 @@ ve/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmsy5.pfb></usr/local/texlive
022/texmf-dist/fonts/type1/public/amsfonts/cm/cmti10.pfb></usr/local/texlive/20
22/texmf-dist/fonts/type1/public/amsfonts/cm/cmti8.pfb></usr/local/texlive/2022
/texmf-dist/fonts/type1/public/amsfonts/symbols/msam10.pfb>
Output written on paper.pdf (9 pages, 752040 bytes).
Output written on paper.pdf (10 pages, 814715 bytes).
PDF statistics:
123 PDF objects out of 1000 (max. 8388607)
71 compressed objects within 1 object stream
128 PDF objects out of 1000 (max. 8388607)
73 compressed objects within 1 object stream
0 named destinations out of 1000 (max. 500000)
21 words of extra memory for PDF output out of 10000 (max. 10000000)
26 words of extra memory for PDF output out of 10000 (max. 10000000)
Binary file not shown.
@@ -622,6 +622,26 @@ $B_{\mathrm{out}}$ and one $O$-side face inside $B_{\mathrm{in}}$,
$T'_{f'}$ recovers the planar dual of $T$ itself.
\end{remark}
\begin{figure}[h]
\centering
\includegraphics[width=\textwidth]{notes/fig_facial_dual_choices.png}
\caption{\label{fig:facial-dual-choices}
The bridge case: $T'_{\mathrm{ann}} = \theta(1, 3, 3)$ has three faces
$A, B, C$ in its inherited embedding, with respective vertex sets
$V(A) = \{v_0, \dots, v_5\}$, $V(B) = \{v_0, v_1, v_2, v_3\}$, and
$V(C) = \{v_0, v_3, v_4, v_5\}$. In the surrounding maximal planar
$G$, the chord endpoints $v_0, v_3$ (the two annular faces sharing
the bridge edge) have all three $G'$-edges inside $T'_{\mathrm{ann}}$,
while each non-chord vertex $v_i$ ($i \in \{1, 2, 4, 5\}$) contributes
one $G'$-edge to an external non-annular neighbor $u_i$. Each panel
highlights $T'_{f'}$ (blue) inside $G'$: dark circles are $V(f')$,
gray circles are $G'$-neighbors of $V(f')$ within $T'_{\mathrm{ann}}$,
and red squares are external $G'$-neighbors $u_i$. The choice of
face $f'$ controls which external neighbors $u_i$ are pulled into
$T'_{f'}$ (face $A$ pulls in all four; face $B$ pulls in $u_1, u_2$
and face $C$ pulls in $u_4, u_5$).}
\end{figure}
\begin{thebibliography}{9}
\bibitem{bauerfeld-pds}