coloring_nested_tire_graphs: remove complete tire dual definition and Tait correspondence

The complete tire dual D*(T) and Tait correspondence material was
giving exact counts but only via Tait colorings with XOR-to-0
conditions at high-degree vertices -- not proper edge colorings,
which was the original goal.  Removed:

- Definition 1.13 (Complete tire dual) and its figure.
- Proposition 1.14 (Tait correspondence on complete tire dual).
- Remark 1.15 (Tait construction).
- Remark 1.16 (octahedron verification).
- Tait1880 bibitem (no longer cited; the body-text mention of
  Tait's theorem in the introduction remains).
- experiments/draw_complete_tire_dual.py + its PNG.
- experiments/draw_tait_coloring_example.py + its PNG.
- fig_complete_tire_dual.png from the paper root.

The partial tire dual definition (Def 1.7), structure proposition
(Prop 1.8), figure, and associated scripts (tire_graph.py,
draw_partial_tire_dual.py) are retained.

Paper shrinks from 9 to 7 pages.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-25 19:48:55 -04:00
parent 2b84513f83
commit c6d4eb06fb
7 changed files with 33 additions and 337 deletions
Binary file not shown.

Before

Width:  |  Height:  |  Size: 151 KiB

@@ -1,199 +0,0 @@
"""Draw the complete tire dual D*(T) on top of a small tire graph.
For a spoke-only tire with 2-connected O = C_k (no chords), D*(T) is
obtained from D(T) by merging:
- all B_out-leaves into a single outer-face vertex v_out (degree n);
- the B_in-leaves into a single inner-face vertex v_in (degree k),
because O has exactly one bounded interior face.
Equivalently, D*(T) is the planar dual of T.
"""
import math
import os
import sys
HERE = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, HERE)
import matplotlib.pyplot as plt
import matplotlib.patches as patches
from tire_graph import random_tire, planar_positions
def draw_complete_tire_dual(tire, filename):
m, k = tire['m'], tire['k']
outer, inner = tire['outer'], tire['inner']
triangles = tire['triangles']
R_out, R_in = 1.0, 0.45
pos = planar_positions(tire, R_out=R_out, R_in=R_in)
fig, ax = plt.subplots(figsize=(9, 9))
# === Draw underlying tire graph faintly ===
outer_set = set(outer)
inner_set = set(inner)
for u, v in tire['edges']:
x1, y1 = pos[u]; x2, y2 = pos[v]
if u in outer_set and v in outer_set:
color = '#a8c9e8'; lw = 2.0
elif u in inner_set and v in inner_set:
color = '#e8a8a8'; lw = 2.0
else:
color = '#cccccc'; lw = 1.0
ax.plot([x1, x2], [y1, y2], color=color, linewidth=lw, zorder=1)
for v in outer:
x, y = pos[v]
ax.plot(x, y, 'o', color='#a8c9e8', markersize=14, zorder=2)
ax.annotate(str(v), (x, y), color='white', ha='center', va='center',
fontsize=8, fontweight='bold', zorder=3)
for v in inner:
x, y = pos[v]
ax.plot(x, y, 'o', color='#e8a8a8', markersize=12, zorder=2)
ax.annotate(str(v), (x, y), color='white', ha='center', va='center',
fontsize=7, fontweight='bold', zorder=3)
n_tri = len(triangles)
centroids = []
for tri in triangles:
v1, v2, v3 = tri
cx = (pos[v1][0] + pos[v2][0] + pos[v3][0]) / 3
cy = (pos[v1][1] + pos[v2][1] + pos[v3][1]) / 3
centroids.append((cx, cy))
# Identify which triangles are incident to a B_out edge (O-move type)
# vs incident to a B_in edge (I-move type).
from collections import defaultdict
bout_edges = {frozenset({outer[i], outer[(i+1) % m]}) for i in range(m)}
bin_edges = {frozenset({inner[j], inner[(j+1) % k]}) for j in range(k)}
bout_incident = [] # triangles incident to a B_out edge
bin_incident = [] # triangles incident to a B_in edge
for t_idx, tri in enumerate(triangles):
tri_edges = {frozenset({tri[0], tri[1]}),
frozenset({tri[1], tri[2]}),
frozenset({tri[0], tri[2]})}
if tri_edges & bout_edges:
bout_incident.append(t_idx)
if tri_edges & bin_edges:
bin_incident.append(t_idx)
print(f"O-move triangles (B_out incident): {bout_incident}")
print(f"I-move triangles (B_in incident): {bin_incident}")
# Place v_out outside the outer cycle (far to the upper right)
# and v_in at the origin (centroid of inner cycle).
v_out_pos = (1.55, 0.0) # well outside the outer cycle
v_in_pos = (0.0, 0.0) # center of inner cycle
# Identify dual cycle (interior dual edges)
edge_to_tris = defaultdict(list)
for t_idx, tri in enumerate(triangles):
e1 = frozenset({tri[0], tri[1]})
e2 = frozenset({tri[1], tri[2]})
e3 = frozenset({tri[0], tri[2]})
for e in (e1, e2, e3):
edge_to_tris[e].append(t_idx)
tri_adj = defaultdict(set)
for e, ts in edge_to_tris.items():
if len(ts) == 2:
t1, t2 = ts
tri_adj[t1].add(t2)
tri_adj[t2].add(t1)
# === Draw complete tire dual ===
DUAL_COLOR = '#7d3c98' # purple
OUT_COLOR = '#1f77b4' # blue (for v_out edges)
IN_COLOR = '#d62728' # red (for v_in edges)
# Interior dual edges (d_f to d_f)
for t1 in range(n_tri):
for t2 in tri_adj[t1]:
if t2 <= t1:
continue
x1, y1 = centroids[t1]
x2, y2 = centroids[t2]
ax.plot([x1, x2], [y1, y2], color=DUAL_COLOR, linewidth=2.0,
zorder=4)
# v_out edges (to all O-move d_f's)
for t_idx in bout_incident:
cx, cy = centroids[t_idx]
ax.plot([cx, v_out_pos[0]], [cy, v_out_pos[1]],
color=OUT_COLOR, linewidth=1.6, linestyle='--', zorder=4)
# v_in edges (to all I-move d_f's)
for t_idx in bin_incident:
cx, cy = centroids[t_idx]
ax.plot([cx, v_in_pos[0]], [cy, v_in_pos[1]],
color=IN_COLOR, linewidth=1.6, linestyle='--', zorder=4)
# Interior dual vertices d_f
for t_idx, (cx, cy) in enumerate(centroids):
ax.plot(cx, cy, 's', color=DUAL_COLOR, markersize=14, zorder=5)
ax.annotate(f"$d_{{{t_idx}}}$", (cx, cy), color='white',
ha='center', va='center', fontsize=7, fontweight='bold',
zorder=6)
# v_out (outer-face vertex)
ax.plot(v_out_pos[0], v_out_pos[1], 'h', color=OUT_COLOR,
markersize=20, zorder=5)
ax.annotate("$v_{\\mathrm{out}}$", v_out_pos, color='white',
ha='center', va='center', fontsize=9, fontweight='bold',
zorder=6)
# v_in (inner-face vertex)
ax.plot(v_in_pos[0], v_in_pos[1], 'h', color=IN_COLOR,
markersize=18, zorder=5)
ax.annotate("$v_{\\mathrm{in}}$", v_in_pos, color='white',
ha='center', va='center', fontsize=8, fontweight='bold',
zorder=6)
# Legend
legend_items = [
plt.Line2D([], [], marker='o', color='w', markerfacecolor='#a8c9e8',
markersize=12, label='$B_{\\mathrm{out}}$ vertex (tire)'),
plt.Line2D([], [], marker='o', color='w', markerfacecolor='#e8a8a8',
markersize=11, label='$B_{\\mathrm{in}}$ vertex (tire)'),
plt.Line2D([], [], marker='s', color='w', markerfacecolor=DUAL_COLOR,
markersize=12, label='$d_f$ (annular face dual vertex)'),
plt.Line2D([], [], marker='h', color='w', markerfacecolor=OUT_COLOR,
markersize=14,
label='$v_{\\mathrm{out}}$ (outer-face vertex, deg ${%d}$)' % m),
plt.Line2D([], [], marker='h', color='w', markerfacecolor=IN_COLOR,
markersize=13,
label='$v_{\\mathrm{in}}$ (inner-face vertex, deg ${%d}$)' % k),
plt.Line2D([], [], color=DUAL_COLOR, linewidth=2.0,
label='interior dual edge ($d_f$$d_{f^\\prime}$)'),
plt.Line2D([], [], color=OUT_COLOR, linewidth=1.6, linestyle='--',
label='dual edge to $v_{\\mathrm{out}}$'),
plt.Line2D([], [], color=IN_COLOR, linewidth=1.6, linestyle='--',
label='dual edge to $v_{\\mathrm{in}}$'),
]
ax.legend(handles=legend_items, loc='upper left',
bbox_to_anchor=(1.02, 1.0), fontsize=9, frameon=False)
ax.set_xlim(-1.35, 2.05)
ax.set_ylim(-1.35, 1.35)
ax.set_aspect('equal')
ax.axis('off')
ax.set_title(
f'Complete tire dual $D^{{*}}(T)$ (m={m}, k={k}, spoke-only)\n'
f'underlying tire faint; $|V| = {n_tri + 2}$, $|E| = {2*n_tri}$',
fontsize=12)
plt.savefig(filename, dpi=160, bbox_inches='tight')
plt.close()
print(f"wrote {filename}")
def main():
tire = random_tire(m=6, k=4, n_chords=0, seed=3)
out = os.path.join(HERE, 'complete_tire_dual_example.png')
draw_complete_tire_dual(tire, out)
if __name__ == '__main__':
main()
Binary file not shown.

Before

Width:  |  Height:  |  Size: 151 KiB

+5 -13
View File
@@ -15,21 +15,13 @@
\newlabel{lem:tire-component}{{1.10}{5}}
\citation{bauerfeld-pds}
\citation{bauerfeld-pds}
\newlabel{rem:tire-component-degenerate}{{1.11}{7}}
\newlabel{rem:tire-no-extra-hypotheses}{{1.12}{7}}
\newlabel{def:complete-tire-dual}{{1.13}{7}}
\citation{Tait1880}
\@writefile{lof}{\contentsline {figure}{\numberline {4}{\ignorespaces The complete tire dual $D^{\ast }(T)$ (purple squares + face hexagons) drawn on top of the same $m = 6$, $k = 4$ spoke-only tire graph as Figure\nonbreakingspace 3\hbox {}. The ten annular-face vertices $d_f$ form a $10$-cycle (solid purple); the $n$ outer leaves of $D(T)$ have been merged into a single outer-face vertex $v_{\mathrm {out}}$ (blue hexagon, drawn outside the tire) of degree $n = 6$, and the $m$ inner leaves into a single inner-face vertex $v_{\mathrm {in}}$ (red hexagon, at the centre of the inner cycle) of degree $m = 4$. Total $|V(D^{\ast }(T))| = 12$ and $|E(D^{\ast }(T))| = 20$.}}{8}{}\protected@file@percent }
\newlabel{fig:complete-tire-dual-example}{{4}{8}}
\newlabel{prop:tait-tire-complete}{{1.14}{8}}
\newlabel{rem:tait-construction}{{1.15}{8}}
\newlabel{rem:tait-octahedron}{{1.16}{8}}
\bibcite{Tait1880}{1}
\bibcite{bauerfeld-pds}{2}
\bibcite{bauerfeld-pds}{1}
\newlabel{tocindent-1}{0pt}
\newlabel{tocindent0}{12.7778pt}
\newlabel{tocindent1}{17.77782pt}
\newlabel{tocindent2}{0pt}
\newlabel{tocindent3}{0pt}
\@writefile{toc}{\contentsline {section}{\tocsection {}{}{References}}{9}{}\protected@file@percent }
\gdef \@abspage@last{9}
\newlabel{rem:tire-component-degenerate}{{1.11}{7}}
\newlabel{rem:tire-no-extra-hypotheses}{{1.12}{7}}
\@writefile{toc}{\contentsline {section}{\tocsection {}{}{References}}{7}{}\protected@file@percent }
\gdef \@abspage@last{7}
+28 -35
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 19:28
This is pdfTeX, Version 3.141592653-2.6-1.40.24 (TeX Live 2022) (preloaded format=pdflatex 2022.10.5) 25 MAY 2026 19:48
entering extended mode
restricted \write18 enabled.
%&-line parsing enabled.
@@ -213,43 +213,36 @@ File: fig_partial_tire_dual.png Graphic file (type png)
<use fig_partial_tire_dual.png>
Package pdftex.def Info: fig_partial_tire_dual.png used on input line 225.
(pdftex.def) Requested size: 280.79956pt x 233.36552pt.
[4 <./fig_partial_tire_dual.png>] [5] [6] [7]
<fig_complete_tire_dual.png, id=48, 701.47069pt x 448.074pt>
File: fig_complete_tire_dual.png Graphic file (type png)
<use fig_complete_tire_dual.png>
Package pdftex.def Info: fig_complete_tire_dual.png used on input line 513.
(pdftex.def) Requested size: 295.20264pt x 188.55899pt.
[8 <./fig_complete_tire_dual.png>] [9] (./paper.aux) )
[4 <./fig_partial_tire_dual.png>] [5] [6] [7] (./paper.aux) )
Here is how much of TeX's memory you used:
3031 strings out of 478268
42680 string characters out of 5846347
345262 words of memory out of 5000000
21076 multiletter control sequences out of 15000+600000
3018 strings out of 478268
42332 string characters out of 5846347
345207 words of memory out of 5000000
21064 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,742b,316s 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/cmcsc10.pfb></usr/local/texlive/2022/
texmf-dist/fonts/type1/public/amsfonts/cm/cmex10.pfb></usr/local/texlive/2022/t
exmf-dist/fonts/type1/public/amsfonts/cm/cmmi10.pfb></usr/local/texlive/2022/te
xmf-dist/fonts/type1/public/amsfonts/cm/cmmi5.pfb></usr/local/texlive/2022/texm
f-dist/fonts/type1/public/amsfonts/cm/cmmi7.pfb></usr/local/texlive/2022/texmf-
dist/fonts/type1/public/amsfonts/cm/cmr10.pfb></usr/local/texlive/2022/texmf-di
st/fonts/type1/public/amsfonts/cm/cmr5.pfb></usr/local/texlive/2022/texmf-dist/
fonts/type1/public/amsfonts/cm/cmr7.pfb></usr/local/texlive/2022/texmf-dist/fon
ts/type1/public/amsfonts/cm/cmr8.pfb></usr/local/texlive/2022/texmf-dist/fonts/
type1/public/amsfonts/cm/cmsy10.pfb></usr/local/texlive/2022/texmf-dist/fonts/t
ype1/public/amsfonts/cm/cmsy5.pfb></usr/local/texlive/2022/texmf-dist/fonts/typ
e1/public/amsfonts/cm/cmsy7.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/pu
blic/amsfonts/symbols/msam10.pfb></usr/local/texlive/2022/texmf-dist/fonts/type
1/public/amsfonts/symbols/msbm10.pfb>
Output written on paper.pdf (9 pages, 748601 bytes).
69i,8n,76p,687b,316s stack positions out of 10000i,1000n,20000p,200000b,200000s
</usr/local/texli
ve/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmbx10.pfb></usr/local/texliv
e/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmcsc10.pfb></usr/local/texliv
e/2022/texmf-dist/fonts/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/20
22/texmf-dist/fonts/type1/public/amsfonts/cm/cmmi7.pfb></usr/local/texlive/2022
/texmf-dist/fonts/type1/public/amsfonts/cm/cmr10.pfb></usr/local/texlive/2022/t
exmf-dist/fonts/type1/public/amsfonts/cm/cmr5.pfb></usr/local/texlive/2022/texm
f-dist/fonts/type1/public/amsfonts/cm/cmr7.pfb></usr/local/texlive/2022/texmf-d
ist/fonts/type1/public/amsfonts/cm/cmr8.pfb></usr/local/texlive/2022/texmf-dist
/fonts/type1/public/amsfonts/cm/cmsy10.pfb></usr/local/texlive/2022/texmf-dist/
fonts/type1/public/amsfonts/cm/cmsy5.pfb></usr/local/texlive/2022/texmf-dist/fo
nts/type1/public/amsfonts/cm/cmsy7.pfb></usr/local/texlive/2022/texmf-dist/font
s/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/t
ype1/public/amsfonts/symbols/msam10.pfb>
Output written on paper.pdf (7 pages, 616266 bytes).
PDF statistics:
128 PDF objects out of 1000 (max. 8388607)
74 compressed objects within 1 object stream
115 PDF objects out of 1000 (max. 8388607)
67 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)
16 words of extra memory for PDF output out of 10000 (max. 10000000)
Binary file not shown.
@@ -487,98 +487,8 @@ boundary cycle (the link of $v_0$); the corresponding tire graph has
degenerate outer boundary $\{v_0\}$.
\end{remark}
\begin{definition}[Complete tire dual]
\label{def:complete-tire-dual}
The \emph{complete tire dual} $D^{\ast}(T)$ of a tire graph $T$ is
obtained from the partial tire dual $D(T)$ by quotienting its
leaves into non-annular-face vertices:
\begin{itemize}
\item Replace the $n$ outer leaves $\{\ell_e^{\mathrm{out}} :
e \in E(B_{\mathrm{out}})\}$ by a single \emph{outer-face
vertex} $v_{\mathrm{out}}$ of degree $n$. Each former leaf
edge $\{d_f, \ell_e^{\mathrm{out}}\}$ becomes an edge
$\{d_f, v_{\mathrm{out}}\}$ of $D^{\ast}(T)$.
\item For each bounded face $F$ of $O$ interior to $B_{\mathrm{in}}$,
replace the $|F|$ inner leaves whose edges lie on $\partial F$
by a single \emph{inner-face vertex} $v_F$ of degree $|F|$,
in the same way.
\end{itemize}
Equivalently, $D^{\ast}(T)$ is the planar dual of $T$: one dual
vertex per face of $T$ (annular triangle, outer face, or bounded
interior face of $O$), one dual edge per edge of $T$.
\end{definition}
\begin{figure}[h]
\centering
\includegraphics[width=0.82\textwidth]{fig_complete_tire_dual.png}
\caption{The complete tire dual $D^{\ast}(T)$ (purple squares + face
hexagons) drawn on top of the same $m = 6$, $k = 4$ spoke-only tire
graph as Figure~\ref{fig:partial-tire-dual-example}. The ten
annular-face vertices $d_f$ form a $10$-cycle (solid purple); the
$n$ outer leaves of $D(T)$ have been merged into a single outer-face
vertex $v_{\mathrm{out}}$ (blue hexagon, drawn outside the tire) of
degree $n = 6$, and the $m$ inner leaves into a single inner-face
vertex $v_{\mathrm{in}}$ (red hexagon, at the centre of the inner
cycle) of degree $m = 4$. Total $|V(D^{\ast}(T))| = 12$ and
$|E(D^{\ast}(T))| = 20$.}
\label{fig:complete-tire-dual-example}
\end{figure}
\begin{proposition}[Tait correspondence on the complete tire dual]
\label{prop:tait-tire-complete}
Let $T$ be a tire graph. Then the number of non-equivalent proper
$4$-vertex-colorings of $T$ (modulo permutation of the four colors)
equals the number of non-equivalent \emph{Tait colorings} of
$D^{\ast}(T)$ (modulo permutation of the three nonzero elements of
$\mathbb{Z}_2 \times \mathbb{Z}_2$), where a Tait coloring is an
edge-labelling by the three nonzero elements of
$\mathbb{Z}_2 \times \mathbb{Z}_2$ such that at every vertex of
$D^{\ast}(T)$ the XOR of incident labels vanishes.
\end{proposition}
\begin{remark}
\label{rem:tait-construction}
The correspondence is the classical Tait XOR map~\cite{Tait1880}:
identifying the four colors with $\mathbb{Z}_2 \times \mathbb{Z}_2$,
each edge of $T$ receives the XOR of its endpoint colors, which is
nonzero and so a Tait color. At any degree-$3$ vertex $d_f$ of
$D^{\ast}(T)$ (an annular triangle of $T$), the XOR-to-$0$ condition
forces the three incident edge colors to be distinct, recovering
proper $3$-edge-coloring at $d_f$. At the higher-degree dual
vertices $v_{\mathrm{out}}$ (degree $n$) and $v_F$ (degree $|F|$),
the XOR-to-$0$ condition is the non-trivial non-annular consistency
constraint absent from the partial tire dual $D(T)$.
\end{remark}
\begin{remark}
\label{rem:tait-octahedron}
For the octahedron viewed as a tire graph with $n = m = 3$,
$O = C_3$ (no chords), and the spoke-only annular triangulation,
$D^{\ast}(T)$ is the cube $Q_3$: the six $d_f$ vertices form a
$6$-cycle, $v_{\mathrm{out}}$ is connected to the three O-move
$d_f$'s and $v_{\mathrm{in}}$ to the three I-move $d_f$'s, giving a
$3$-regular bipartite graph on $8$ vertices. The octahedron has
$96$ proper $4$-vertex-colorings, hence $96 / 24 = 4$ equivalence
classes modulo $S_4$; the cube has $24$ Tait colorings ($= 96 / 4$
by Tait), hence $24 / 6 = 4$ equivalence classes modulo $S_3$. The
counts match, illustrating
Proposition~\ref{prop:tait-tire-complete}. In contrast, the partial
tire dual $D(T) \cong C_6 \circ K_1$ has $2^6 + 2 = 66$ proper
$3$-edge-colorings, i.e.\ $11$ classes modulo $S_3$, exceeding the
four vertex-coloring classes of $T$; the excess is precisely the
edge-colorings of $D(T)$ that violate the non-annular
XOR-to-$0$ constraints captured only in $D^{\ast}(T)$.
\end{remark}
\begin{thebibliography}{9}
\bibitem{Tait1880}
P.~G.~Tait,
\emph{Remarks on the colouring of maps},
Proceedings of the Royal Society of Edinburgh, vol.~10, pp.~501--503
and~728--729, 1880.
\bibitem{bauerfeld-pds}
E.~Bauerfeld,
\emph{Plane Depth Sequencing},