dual_decomposition: split iterated reduction into companion paper

- Move the iterated-reduction algorithm, its two structural lemmas
  (exactly-one-match, all-distinct-exists), and the n=14 trace figure
  into a new companion paper at
  papers/dual_decomposition_iterated_reduction/. Figures and figure
  scripts moved via git mv (history preserved).
- In the main paper, Section 3 ("An iterated reduction") becomes
  Section 3 "Cubic-graph edge contraction" (just the contraction
  definition + 4-face theorem).
- Restructure Section 4 to host both the original face-monochromatic-pair
  conjecture (clauses 1-3) and its strengthening (adds clause 4) as
  separate conjectures, after briefly experimenting with folding them
  into one. The empirical evidence is asymmetric (n<=21 for (1)-(3),
  n<=18 for the full set), which the two-conjecture split presents more
  honestly. The companion-paper reference is now in Section 4's intro.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-24 14:07:08 -04:00
parent 440ec9cc86
commit 83e9dba8ac
13 changed files with 759 additions and 427 deletions
@@ -1,219 +0,0 @@
"""Draw the iterated reduction algorithm's trace on the dodecahedron.
Produces three figures:
fig_alg_step0.png -- G' (dodecahedron) with F_v (inner pentagon) shaded.
fig_alg_step1.png -- H_1 (post step 1), 3-edge-coloured; 4 protected edges.
fig_alg_step2.png -- H_2 (post step 2), 3-edge-coloured; 8 protected edges;
algorithm terminates.
Run with: sage experiments/draw_iterated_reduction.py
"""
from sage.all import Graph
from sage.graphs.graph_coloring import edge_coloring
import matplotlib.pyplot as plt
from matplotlib.patches import Polygon
import math
import os
OUT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
C = ['#dc2626', '#16a34a', '#2563eb'] # proper-edge-colour palette
GRAY = '#9ca3af'
DARK = '#374151'
HIGHLIGHT = '#fef3c7'
def dodecahedron_positions():
pos = {}
R = {'a': 1.0, 'b': 2.2, 'c': 3.6, 'd': 4.8}
for i in range(5):
for fam in ('a', 'b'):
th = math.radians(90 - 72 * i)
pos[(fam, i)] = (R[fam] * math.cos(th), R[fam] * math.sin(th))
for fam in ('c', 'd'):
th = math.radians(90 - 72 * i - 36)
pos[(fam, i)] = (R[fam] * math.cos(th), R[fam] * math.sin(th))
return pos
def build_dodecahedron():
edges = []
for i in range(5):
edges.append((('a', i), ('a', (i + 1) % 5)))
edges.append((('a', i), ('b', i)))
edges.append((('b', i), ('c', i)))
edges.append((('b', i), ('c', (i - 1) % 5)))
edges.append((('c', i), ('d', i)))
edges.append((('d', i), ('d', (i + 1) % 5)))
G = Graph(edges, multiedges=False, loops=False)
G.is_planar(set_embedding=True)
return G
def find_safe_pentagonal_face(G, protected):
for face in G.faces():
if len(face) != 5:
continue
boundary = [u for (u, v) in face]
boundary_edges = [frozenset([u, v]) for (u, v) in face]
externals = []
A = []
for B_k in boundary:
outer = [w for w in G.neighbor_iterator(B_k) if w not in boundary]
if len(outer) != 1:
break
externals.append(frozenset([B_k, outer[0]]))
A.append(outer[0])
else:
if not any(e in protected for e in boundary_edges + externals):
return boundary, externals, A
return None
def valid_indices(f_vec):
out = []
for i in range(5):
if f_vec[(i + 3) % 5] != f_vec[(i + 4) % 5]:
continue
if len({f_vec[i], f_vec[(i + 1) % 5], f_vec[(i + 2) % 5]}) == 3:
out.append(i)
return out
def draw(ax, G, pos, *, coloring=None, protected=None,
shade_face=None):
if shade_face:
poly = [pos[v] for v in shade_face]
ax.add_patch(Polygon(poly, closed=True, facecolor=HIGHLIGHT,
edgecolor='none', zorder=0))
protected = protected or set()
for u, v in G.edges(labels=False):
e = frozenset([u, v])
c = C[coloring[e]] if coloring is not None else GRAY
lw = 3.8 if e in protected else 1.4
(x0, y0), (x1, y1) = pos[u], pos[v]
ax.plot([x0, x1], [y0, y1], color=c, lw=lw, zorder=2)
for v in G.vertices(sort=False):
x, y = pos[v]
if isinstance(v, tuple) and v[0] == 'v_n':
t = v[1]
ax.scatter(x, y, s=320, color=HIGHLIGHT, marker='s',
edgecolors='black', linewidths=1.2, zorder=4)
ax.annotate(f'$v_n^{{({t})}}$', (x, y),
textcoords='offset points', xytext=(16, 16),
ha='left', fontsize=14, fontweight='bold',
color=DARK, zorder=6,
bbox=dict(boxstyle='round,pad=0.2', fc='white',
ec=DARK, lw=0.6))
else:
ax.scatter(x, y, s=70, color=DARK, zorder=3)
ax.set_aspect('equal')
ax.axis('off')
def main():
G = build_dodecahedron()
pos = dodecahedron_positions()
F_v = [('a', i) for i in range(5)]
# ----- Step 0: G' with F_v shaded -----
fig, ax = plt.subplots(figsize=(8, 8))
draw(ax, G, pos, shade_face=F_v)
fig.savefig(os.path.join(OUT_DIR, 'fig_alg_step0.png'),
dpi=170, bbox_inches='tight')
plt.close(fig)
# ----- Step 1: Definition 2.1 at F_v with i_1 = 0 -----
safe = find_safe_pentagonal_face(G, set())
boundary_1, externals_1, A_1 = safe
G1 = G.copy()
for v in boundary_1:
G1.delete_vertex(v)
v_n_1 = ('v_n', 1)
G1.add_vertex(v_n_1)
G1.add_edge(v_n_1, A_1[0])
G1.add_edge(v_n_1, A_1[1])
G1.add_edge(v_n_1, A_1[2])
G1.add_edge(A_1[3], A_1[4])
G1.is_planar(set_embedding=True)
pos1 = {v: p for v, p in pos.items() if v not in boundary_1}
cx = (pos[A_1[0]][0] + pos[A_1[1]][0] + pos[A_1[2]][0]) / 3
cy = (pos[A_1[0]][1] + pos[A_1[1]][1] + pos[A_1[2]][1]) / 3
pos1[v_n_1] = (cx * 0.55, cy * 0.55)
cols = edge_coloring(G1, value_only=False)
coloring = {}
for k, edge_list in enumerate(cols):
for u, v in edge_list:
coloring[frozenset([u, v])] = k
E = {
frozenset([v_n_1, A_1[1]]), # spike
frozenset([v_n_1, A_1[0]]), # side-0
frozenset([v_n_1, A_1[2]]), # side-1
frozenset([A_1[3], A_1[4]]), # merged
}
fig, ax = plt.subplots(figsize=(8, 8))
draw(ax, G1, pos1, coloring=coloring, protected=E)
fig.savefig(os.path.join(OUT_DIR, 'fig_alg_step1.png'),
dpi=170, bbox_inches='tight')
plt.close(fig)
# ----- Step 2: reduce at the only remaining safe face (outer pentagon) -----
safe = find_safe_pentagonal_face(G1, E)
if safe is None:
print("ERROR: expected an outer pentagonal face but none found.")
return
boundary_2, externals_2, A_2 = safe
f_vec = [coloring[e] for e in externals_2]
choices = valid_indices(f_vec)
if not choices:
print(f"ERROR: f-vector {f_vec} has no valid index.")
return
i_t = choices[0]
G2 = G1.copy()
for v in boundary_2:
G2.delete_vertex(v)
v_n_2 = ('v_n', 2)
G2.add_vertex(v_n_2)
G2.add_edge(v_n_2, A_2[i_t])
G2.add_edge(v_n_2, A_2[(i_t + 1) % 5])
G2.add_edge(v_n_2, A_2[(i_t + 2) % 5])
G2.add_edge(A_2[(i_t + 3) % 5], A_2[(i_t + 4) % 5])
G2.is_planar(set_embedding=True)
coloring2 = {e: c for e, c in coloring.items()
if not any(u in boundary_2 for u in e)}
side_0_2 = frozenset([v_n_2, A_2[i_t]])
spike_2 = frozenset([v_n_2, A_2[(i_t + 1) % 5]])
side_1_2 = frozenset([v_n_2, A_2[(i_t + 2) % 5]])
merged_2 = frozenset([A_2[(i_t + 3) % 5], A_2[(i_t + 4) % 5]])
coloring2[side_0_2] = coloring[externals_2[i_t]]
coloring2[spike_2] = coloring[externals_2[(i_t + 1) % 5]]
coloring2[side_1_2] = coloring[externals_2[(i_t + 2) % 5]]
coloring2[merged_2] = coloring[externals_2[(i_t + 3) % 5]]
pos2 = {v: p for v, p in pos1.items() if v not in boundary_2}
nbrs = [A_2[i_t], A_2[(i_t + 1) % 5], A_2[(i_t + 2) % 5]]
cx = sum(pos2[a][0] for a in nbrs) / 3
cy = sum(pos2[a][1] for a in nbrs) / 3
r = math.hypot(cx, cy)
# v_n^{(2)} lies outside the surviving graph (the deleted d's were outermost)
target_r = 5.0
pos2[v_n_2] = (cx * target_r / r, cy * target_r / r)
E |= {side_0_2, spike_2, side_1_2, merged_2}
fig, ax = plt.subplots(figsize=(8, 8))
draw(ax, G2, pos2, coloring=coloring2, protected=E)
fig.savefig(os.path.join(OUT_DIR, 'fig_alg_step2.png'),
dpi=170, bbox_inches='tight')
plt.close(fig)
print(f"Wrote fig_alg_step{{0,1,2}}.png to {OUT_DIR}")
if __name__ == '__main__':
main()
@@ -1,520 +0,0 @@
"""Draw the iterated reduction trace on the smallest triangulation where
the chord-apex + Kempe-cycle property is satisfied: the first min-degree-5
plantri triangulation on n = 14 vertices, found by search_kempe_property.py.
Overwrites fig_alg_step{0,1,2}.png in the paper directory with this
triangulation's trace (replacing the dodecahedron version).
Run with: sage experiments/draw_iterated_reduction_n14.py
"""
from sage.all import Graph
from sage.graphs.graph_generators import graphs
import matplotlib.pyplot as plt
from matplotlib.patches import Polygon
import math
import os
def tutte_layout(G_sage, avoid_verts=None, iterations=300):
"""Tutte's barycentric embedding: pick the largest face whose vertex set
avoids `avoid_verts` as the outer face, place its vertices on a regular
polygon, then iterate each interior vertex to the barycenter of its
neighbors. For 3-connected planar graphs this converges to the unique
straight-line planar embedding with the chosen outer face --- balanced
by construction and free of edge crossings."""
avoid = set(avoid_verts or ())
candidates = []
for face in G_sage.faces():
verts = [u for (u, v) in face]
if not (set(verts) & avoid):
candidates.append(verts)
if not candidates:
outer = [u for (u, v) in max(G_sage.faces(), key=len)]
else:
outer = max(candidates, key=len)
n_outer = len(outer)
pos = {}
for k, v in enumerate(outer):
ang = 2 * math.pi * k / n_outer + math.pi / 2
pos[v] = (math.cos(ang), math.sin(ang))
interior = [v for v in G_sage.vertex_iterator() if v not in pos]
for v in interior:
pos[v] = (0.0, 0.0)
for _ in range(iterations):
new_pos = dict(pos)
for v in interior:
nbrs = list(G_sage.neighbor_iterator(v))
sx = sum(pos[w][0] for w in nbrs) / len(nbrs)
sy = sum(pos[w][1] for w in nbrs) / len(nbrs)
new_pos[v] = (sx, sy)
pos = new_pos
return pos
OUT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
C = ['#dc2626', '#16a34a', '#2563eb']
GRAY = '#9ca3af'
DARK = '#374151'
HIGHLIGHT = '#fef3c7'
SHADE = '#fef3c7'
def dual_of(G):
faces = G.faces()
edge_to_faces = {}
for fi, face in enumerate(faces):
for u, v in face:
e = frozenset((u, v))
edge_to_faces.setdefault(e, []).append(fi)
dual_edges = []
for e, fs in edge_to_faces.items():
if len(fs) == 2:
dual_edges.append((fs[0], fs[1]))
return Graph(dual_edges, multiedges=False, loops=False)
def apply_reduction(G, face, i, v_n_label):
boundary = [u for (u, v) in face]
if len(set(boundary)) != 5:
return None
A = []
for B_k in boundary:
outer = [w for w in G.neighbor_iterator(B_k) if w not in boundary]
if len(outer) != 1:
return None
A.append(outer[0])
if len(set(A)) != 5:
return None
if A[(i + 3) % 5] == A[(i + 4) % 5]:
return None
H = G.copy()
for v in boundary:
H.delete_vertex(v)
H.add_vertex(v_n_label)
side_0 = (v_n_label, A[i % 5])
spike = (v_n_label, A[(i + 1) % 5])
side_1 = (v_n_label, A[(i + 2) % 5])
merged = (A[(i + 3) % 5], A[(i + 4) % 5])
H.add_edges([side_0, spike, side_1, merged])
if H.has_multiple_edges() or H.has_loops():
return None
if not H.is_planar(set_embedding=True):
return None
if not all(H.degree(v) == 3 for v in H.vertex_iterator()):
return None
named = {
'spike': frozenset(spike),
'side_0': frozenset(side_0),
'side_1': frozenset(side_1),
'merged': frozenset(merged),
}
return H, named, boundary, A
def proper_3_edge_colorings(G):
edges = list(G.edges(labels=False))
n_edges = len(edges)
adj = [[] for _ in range(n_edges)]
for i in range(n_edges):
u, v = edges[i][0], edges[i][1]
for j in range(i):
x, y = edges[j][0], edges[j][1]
if u in (x, y) or v in (x, y):
adj[i].append(j)
adj[j].append(i)
coloring = [-1] * n_edges
def back(k):
if k == n_edges:
yield tuple(coloring)
return
for c in range(3):
if all(coloring[j] != c for j in adj[k]):
coloring[k] = c
yield from back(k + 1)
coloring[k] = -1
return edges, back(0)
def kempe_cycle(edges, coloring, start_idx, color_pair):
a, b = color_pair
in_sub = [i for i in range(len(edges)) if coloring[i] in (a, b)]
if start_idx not in in_sub:
return None
visited = {start_idx}
stack = [start_idx]
while stack:
cur = stack.pop()
u, v = edges[cur][0], edges[cur][1]
for j in in_sub:
if j in visited:
continue
x, y = edges[j][0], edges[j][1]
if u in (x, y) or v in (x, y):
visited.add(j)
stack.append(j)
return visited
def matches_property(edges, col, named):
idx = {}
for ii, e in enumerate(edges):
es = frozenset((e[0], e[1]))
for role, ns in named.items():
if es == ns:
idx[role] = ii
if len(idx) != 4:
return False
c_spike = col[idx['spike']]
c_merged = col[idx['merged']]
if c_spike != c_merged:
return False
c_s0 = col[idx['side_0']]
c_s1 = col[idx['side_1']]
kc0 = kempe_cycle(edges, col, idx['spike'], (c_spike, c_s0))
if idx['side_0'] not in kc0 or idx['merged'] not in kc0:
return False
kc1 = kempe_cycle(edges, col, idx['spike'], (c_spike, c_s1))
if idx['side_1'] not in kc1 or idx['merged'] not in kc1:
return False
return True
def find_first_match():
"""Iterate over (G, face, i_red, coloring) and return the first hit."""
for G in graphs.triangulations(14, minimum_degree=5):
if not G.is_planar(set_embedding=True):
continue
D = dual_of(G)
D.is_planar(set_embedding=True)
for face in D.faces():
if len(face) != 5:
continue
for i_red in range(5):
res = apply_reduction(D, face, i_red, '__v_n_1__')
if res is None:
continue
H, named, boundary, A = res
edges, gen = proper_3_edge_colorings(H)
for col in gen:
if matches_property(edges, col, named):
coloring_dict = {frozenset((e[0], e[1])): c
for e, c in zip(edges, col)}
return G, D, face, i_red, H, named, boundary, A, coloring_dict
return None
def draw_graph(ax, G, pos, *, coloring=None, protected=None,
shade_vertices=None, vn_labels=None):
if shade_vertices:
poly = [pos[v] for v in shade_vertices]
ax.add_patch(Polygon(poly, closed=True, facecolor=SHADE,
edgecolor='none', zorder=0))
protected = protected or set()
vn_labels = vn_labels or {}
for u, v, _ in G.edges():
e = frozenset([u, v])
c = C[coloring[e]] if (coloring is not None and e in coloring) else GRAY
lw = 3.8 if e in protected else 1.4
(x0, y0), (x1, y1) = pos[u], pos[v]
ax.plot([x0, x1], [y0, y1], color=c, lw=lw, zorder=2)
for v in G.vertices(sort=False):
x, y = pos[v]
if v in vn_labels:
ax.scatter(x, y, s=320, color=HIGHLIGHT, marker='s',
edgecolors='black', linewidths=1.2, zorder=4)
ax.annotate(vn_labels[v], (x, y),
textcoords='offset points', xytext=(16, 16),
ha='left', fontsize=14, fontweight='bold',
color=DARK, zorder=6,
bbox=dict(boxstyle='round,pad=0.2', fc='white',
ec=DARK, lw=0.6))
else:
ax.scatter(x, y, s=60, color=DARK, zorder=3)
ax.set_aspect('equal')
ax.axis('off')
def main():
print("Searching for the first match at n = 14 ...")
result = find_first_match()
if result is None:
print("No match found at n = 14.")
return
G14, D, face, i_red, H1, named1, boundary1, A1, coloring1 = result
print(f"Found at i_red = {i_red}")
print(f" G (n=14): |V|={G14.order()}, |E|={G14.size()}, "
f"min_deg={min(G14.degree())}")
print(f" D = G': |V|={D.order()}, |E|={D.size()}")
print(f" H_1: |V|={H1.order()}, |E|={H1.size()}")
# Relabel H_1 in place so all vertex labels are comparable integers
# (Sage's planar layout and face enumeration need comparable labels).
# Translate coloring1 and named1 accordingly.
H1_relabel_map = {v: i for i, v in enumerate(H1.vertex_iterator())}
H1.relabel(perm=H1_relabel_map, inplace=True)
vn1_int = H1_relabel_map['__v_n_1__']
coloring1 = {frozenset(H1_relabel_map[u] for u in e): c
for e, c in coloring1.items()}
named1 = {role: frozenset(H1_relabel_map[u] for u in e)
for role, e in named1.items()}
D.is_planar(set_embedding=True)
D_layout = tutte_layout(D, avoid_verts=set(u for (u, v) in face))
H1.is_planar(set_embedding=True)
H1_layout = tutte_layout(H1, avoid_verts={vn1_int})
boundary_face_verts = [u for (u, v) in face]
fig, ax = plt.subplots(figsize=(8, 8))
draw_graph(ax, D, D_layout, shade_vertices=boundary_face_verts)
fig.savefig(os.path.join(OUT_DIR, 'fig_alg_step0.png'),
dpi=170, bbox_inches='tight')
plt.close(fig)
print("Wrote fig_alg_step0.png")
E = set(named1.values())
fig, ax = plt.subplots(figsize=(8, 8))
draw_graph(ax, H1, H1_layout, coloring=coloring1, protected=E,
vn_labels={vn1_int: '$v_n^{(1)}$'})
fig.savefig(os.path.join(OUT_DIR, 'fig_alg_step1.png'),
dpi=170, bbox_inches='tight')
plt.close(fig)
print("Wrote fig_alg_step1.png")
# ----- Step 2: try to continue -----
H1.is_planar(set_embedding=True)
chosen2 = None
for face2 in H1.faces():
if len(face2) != 5:
continue
boundary2 = [u for (u, v) in face2]
boundary2_edges = [frozenset([u, v]) for (u, v) in face2]
externals2 = []
A2 = []
valid_face = True
for B_k in boundary2:
outer = [w for w in H1.neighbor_iterator(B_k) if w not in boundary2]
if len(outer) != 1:
valid_face = False
break
externals2.append(frozenset([B_k, outer[0]]))
A2.append(outer[0])
if not valid_face:
continue
if any(e in E for e in boundary2_edges + externals2):
continue
# find valid i_t
f_vec = [coloring1[e] for e in externals2]
for i_t in range(5):
if f_vec[(i_t + 3) % 5] != f_vec[(i_t + 4) % 5]:
continue
if len({f_vec[i_t], f_vec[(i_t + 1) % 5], f_vec[(i_t + 2) % 5]}) != 3:
continue
if A2[(i_t + 3) % 5] == A2[(i_t + 4) % 5]:
continue
chosen2 = (face2, i_t, boundary2, externals2, A2)
break
if chosen2 is not None:
break
if chosen2 is None:
# algorithm terminates at H_1
fig, ax = plt.subplots(figsize=(8, 8))
ax.text(0.5, 0.5,
"Algorithm terminates at $H_1$:\n"
"no pentagonal face of $H_1$ has all\n"
"ten incident edges outside $E$.",
ha='center', va='center', fontsize=18, color=DARK,
transform=ax.transAxes,
bbox=dict(boxstyle='round,pad=0.6', fc=HIGHLIGHT,
ec=DARK, lw=1.0))
ax.set_aspect('equal')
ax.axis('off')
fig.savefig(os.path.join(OUT_DIR, 'fig_alg_step2.png'),
dpi=170, bbox_inches='tight')
plt.close(fig)
print("Wrote fig_alg_step2.png (termination card)")
print(" Algorithm terminates at H_1: no safe pentagonal face.")
return
face2, i_t, boundary2, externals2, A2 = chosen2
print(f"Step 2: safe face found, i_t = {i_t}")
H2 = H1.copy()
for v in boundary2:
H2.delete_vertex(v)
# use a fresh int label for v_n^(2)
v_n_2 = max(H1.vertices(sort=False)) + 1
H2.add_vertex(v_n_2)
side_0_2 = (v_n_2, A2[i_t])
spike_2 = (v_n_2, A2[(i_t + 1) % 5])
side_1_2 = (v_n_2, A2[(i_t + 2) % 5])
merged_2 = (A2[(i_t + 3) % 5], A2[(i_t + 4) % 5])
H2.add_edges([side_0_2, spike_2, side_1_2, merged_2])
H2.is_planar(set_embedding=True)
coloring2 = {e: c for e, c in coloring1.items()
if not any(u in boundary2 for u in e)}
coloring2[frozenset(side_0_2)] = coloring1[externals2[i_t]]
coloring2[frozenset(spike_2)] = coloring1[externals2[(i_t + 1) % 5]]
coloring2[frozenset(side_1_2)] = coloring1[externals2[(i_t + 2) % 5]]
coloring2[frozenset(merged_2)] = coloring1[externals2[(i_t + 3) % 5]]
E |= {frozenset(side_0_2), frozenset(spike_2),
frozenset(side_1_2), frozenset(merged_2)}
H2_layout = tutte_layout(H2, avoid_verts={vn1_int, v_n_2})
fig, ax = plt.subplots(figsize=(8, 8))
draw_graph(ax, H2, H2_layout, coloring=coloring2, protected=E,
vn_labels={vn1_int: '$v_n^{(1)}$',
v_n_2: '$v_n^{(2)}$'})
fig.savefig(os.path.join(OUT_DIR, 'fig_alg_step2.png'),
dpi=170, bbox_inches='tight')
plt.close(fig)
print(f"Wrote fig_alg_step2.png: H_2 with |V|={H2.order()}, "
f"|E|={H2.size()}, |protected|={len(E)}")
# --- continue running to completion, checking Kempe condition each step --
print()
print("=" * 72)
print("Running algorithm to completion, checking chord-apex + Kempe at "
"each step.")
print("=" * 72)
# Step 1 status (by construction this is the matching coloring)
cond1 = check_step_conditions(H1, coloring1, named1)
print(f" step t = 1: |V|={H1.order():>3}, |E_graph|={H1.size():>3}, "
f"|E_prot|= 4 (initial)"
f" | chord-apex: {cond1['chord_apex']}, "
f"side_0-Kempe: {cond1['kc_side_0']}, "
f"side_1-Kempe: {cond1['kc_side_1']}")
run_to_completion_from(H2, coloring2, E,
{'spike': frozenset(spike_2),
'side_0': frozenset(side_0_2),
'side_1': frozenset(side_1_2),
'merged': frozenset(merged_2)},
start_t=2)
def check_step_conditions(H, coloring, named):
"""Given an H_t and the *just-added* spike/side_0/side_1/merged, check
whether chord-apex and the two Kempe-cycle conditions hold."""
edges = list(H.edges(labels=False))
edges_fs = [frozenset((u, v)) for (u, v) in edges]
col = [coloring[e] for e in edges_fs]
idx = {role: edges_fs.index(e) for role, e in named.items()}
c_spike = col[idx['spike']]
c_merged = col[idx['merged']]
chord_apex = (c_spike == c_merged)
if not chord_apex:
return {'chord_apex': False, 'kc_side_0': False, 'kc_side_1': False}
c_s0 = col[idx['side_0']]
c_s1 = col[idx['side_1']]
kc0 = kempe_cycle(edges, col, idx['spike'], (c_spike, c_s0))
kc1 = kempe_cycle(edges, col, idx['spike'], (c_spike, c_s1))
kc_side_0 = (idx['side_0'] in kc0 and idx['merged'] in kc0)
kc_side_1 = (idx['side_1'] in kc1 and idx['merged'] in kc1)
return {'chord_apex': True, 'kc_side_0': kc_side_0, 'kc_side_1': kc_side_1}
def find_safe_face(H, protected):
"""Return (face, externals, A) for some safe pentagonal face avoiding
`protected`, or None."""
for face in H.faces():
if len(face) != 5:
continue
boundary = [u for (u, v) in face]
boundary_edges = [frozenset([u, v]) for (u, v) in face]
externals = []
A = []
valid = True
for B_k in boundary:
outer = [w for w in H.neighbor_iterator(B_k) if w not in boundary]
if len(outer) != 1:
valid = False
break
externals.append(frozenset([B_k, outer[0]]))
A.append(outer[0])
if not valid:
continue
if any(e in protected for e in boundary_edges + externals):
continue
return face, boundary, externals, A
return None
def run_to_completion_from(H, coloring, E, last_named, start_t):
"""Continue iterating from H_{start_t}. The 'last_named' dict carries
the spike/side/merged of step `start_t` so we can report its Kempe
status. Print a row per step."""
t = start_t
print(f" step t = {t}: |V|={H.order():>3}, |E_graph|={H.size():>3}, "
f"|E_prot|={len(E):>3}", end='')
cond = check_step_conditions(H, coloring, last_named)
print(f" | chord-apex: {cond['chord_apex']}, "
f"side_0-Kempe: {cond['kc_side_0']}, "
f"side_1-Kempe: {cond['kc_side_1']}")
while True:
H.is_planar(set_embedding=True)
res = find_safe_face(H, E)
if res is None:
print(f" step t = {t + 1}: no safe pentagonal face --> "
f"algorithm terminates at H_{t}.")
return
face, boundary, externals, A = res
f_vec = [coloring[e] for e in externals]
i_t = None
for i in range(5):
if f_vec[(i + 3) % 5] != f_vec[(i + 4) % 5]:
continue
if len({f_vec[i], f_vec[(i + 1) % 5], f_vec[(i + 2) % 5]}) != 3:
continue
if A[(i + 3) % 5] == A[(i + 4) % 5]:
continue
i_t = i
break
if i_t is None:
print(f" step t = {t + 1}: f = {f_vec}, no valid index --> "
f"terminate (Lemma 2.4 violation? Probably a parallel-edge "
f"or other degenerate case).")
return
t += 1
v_n_new = max(H.vertices(sort=False)) + 1 if all(
isinstance(v, int) for v in H.vertex_iterator()) else f'vn{t}'
H_new = H.copy()
for v in boundary:
H_new.delete_vertex(v)
H_new.add_vertex(v_n_new)
side_0 = (v_n_new, A[i_t])
spike = (v_n_new, A[(i_t + 1) % 5])
side_1 = (v_n_new, A[(i_t + 2) % 5])
merged = (A[(i_t + 3) % 5], A[(i_t + 4) % 5])
H_new.add_edges([side_0, spike, side_1, merged])
H = H_new
coloring = {e: c for e, c in coloring.items()
if not any(u in boundary for u in e)}
coloring[frozenset(side_0)] = coloring[externals[i_t]] \
if frozenset(externals[i_t]) in coloring else f_vec[i_t]
# safer: directly use f_vec
coloring[frozenset(side_0)] = f_vec[i_t]
coloring[frozenset(spike)] = f_vec[(i_t + 1) % 5]
coloring[frozenset(side_1)] = f_vec[(i_t + 2) % 5]
coloring[frozenset(merged)] = f_vec[(i_t + 3) % 5]
named = {
'spike': frozenset(spike),
'side_0': frozenset(side_0),
'side_1': frozenset(side_1),
'merged': frozenset(merged),
}
E |= set(named.values())
cond = check_step_conditions(H, coloring, named)
print(f" step t = {t}: |V|={H.order():>3}, |E_graph|={H.size():>3}, "
f"|E_prot|={len(E):>3}, i_t = {i_t}", end='')
print(f" | chord-apex: {cond['chord_apex']}, "
f"side_0-Kempe: {cond['kc_side_0']}, "
f"side_1-Kempe: {cond['kc_side_1']}")
if __name__ == '__main__':
main()
Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

@@ -13,30 +13,23 @@
\@writefile{lof}{\contentsline {figure}{\numberline {2}{\ignorespaces The proof of Lemma\nonbreakingspace 2.6\hbox {}, illustrated for $i = 0$ on $G' = $ the dodecahedron. Top: under the assumption $W \neq Y$, propriety at $v_n$ forces $W \in \{X, Z\}$. Bottom: in either case the lift to $G'$ has externals satisfying the hypothesis of Lemma\nonbreakingspace 2.4\hbox {}, which colours $\partial F_v$ to extend $\psi $ to a proper $3$-edge-colouring of $G'$.}}{5}{}\protected@file@percent }
\newlabel{fig:chord-apex-proof}{{2}{5}}
\newlabel{lem:kempe-spike}{{2.7}{6}}
\@writefile{toc}{\contentsline {section}{\tocsection {}{3}{An iterated reduction}}{7}{}\protected@file@percent }
\newlabel{alg:iterated-reduction}{{3.1}{7}}
\newlabel{rem:alg-invariants}{{3.2}{7}}
\newlabel{rem:alg-chord-apex}{{3.3}{7}}
\@writefile{lof}{\contentsline {figure}{\numberline {3}{\ignorespaces Algorithm\nonbreakingspace 3.1\hbox {} on $G'=\mathrm {dual}(G)$, where $G$ is the first min-degree-$5$ plantri triangulation on $14$ vertices and $\varphi _1$ is a specific proper $3$-edge-colouring of $H_1$ that satisfies both the chord-apex condition (Lemma\nonbreakingspace 2.6\hbox {}) and the Kempe-cycle condition (Lemma\nonbreakingspace 2.7\hbox {}), found by \texttt {experiments/search\_kempe\_property.py}. \emph {Left:} $G'$ ($24$ vertices, $36$ edges) with the chosen pentagonal face shaded. \emph {Centre:} $H_1$ ($20$ vertices, $30$ edges) after step\nonbreakingspace (1) with $i_1 = 1$, $3$-edge-coloured by $\varphi _1$; the four edges around $v_n^{(1)}$ in $E$ are drawn thicker, and the spike and merged edges share the colour green. \emph {Right:} $H_2$ ($16$ vertices, $24$ edges) after step\nonbreakingspace (3) with $i_t = 3$; eight edges are protected, and the algorithm terminates one step later (no remaining safe pentagonal face in $H_2$). The generating script is \texttt {experiments/draw\_iterated\_reduction\_n14.py}; layouts are Tutte barycentric embeddings with the outer face picked to keep $v_n^{(1)}, v_n^{(2)}$ in the interior.}}{8}{}\protected@file@percent }
\newlabel{fig:iterated-reduction-trace}{{3}{8}}
\newlabel{lem:exactly-one-match}{{3.4}{8}}
\newlabel{lem:all-distinct-exists}{{3.5}{9}}
\newlabel{conj:face-monochromatic-pair-on-merged-kempe-cycle}{{3.6}{9}}
\newlabel{rem:conj-3-6-empirical}{{3.7}{10}}
\newlabel{def:cubic-edge-contraction}{{3.8}{10}}
\@writefile{lof}{\contentsline {figure}{\numberline {4}{\ignorespaces Cubic-graph edge contraction (Definition\nonbreakingspace 3.8\hbox {}). Left: a fragment of a cubic plane graph with the contracted edge $e = uv$ highlighted in red. Middle: deleting $e$ leaves $u$ and $v$ of degree\nonbreakingspace $2$. Right: smoothing $u$ and $v$ replaces each pair of incident edges by a single new edge, removing $u, v$ and giving a cubic plane graph again.}}{11}{}\protected@file@percent }
\newlabel{fig:cubic-edge-contraction}{{4}{11}}
\newlabel{thm:cubic-contraction-4face}{{3.9}{11}}
\@writefile{lof}{\contentsline {figure}{\numberline {5}{\ignorespaces The recolouring used in the proof of Theorem\nonbreakingspace 3.9\hbox {}. Left: the $4$-face $f$ of $H$ under $\varphi $, with the forced colours $\varphi (e_0) = a$, $\varphi (e_1) = b$, $\varphi (e_2) = \varphi (e_3) = c$, $\varphi (w_0) = \varphi (w_1) = b$, and $\varphi (w_2) = \varphi (w_3) = a$. Right: the contracted graph $H'$ under $\varphi '$. The smoothed-in edges $e_2', e_3'$ inherit the colour $b$ from $w_0, w_1$, and $e_1$ is recoloured from $b$ to $c$; every edge outside the face neighbourhood keeps its $\varphi $-colour (dotted in red: the five edges of $H$ removed by the contraction).}}{12}{}\protected@file@percent }
\newlabel{fig:thm-cubic-contraction-4face}{{5}{12}}
\@writefile{toc}{\contentsline {section}{\tocsection {}{4}{The Four Colour Theorem from a strengthened conjecture}}{12}{}\protected@file@percent }
\newlabel{sec:toward-4ct}{{4}{12}}
\newlabel{conj:face-monochromatic-pair-strengthened}{{4.1}{12}}
\@writefile{toc}{\contentsline {section}{\tocsection {}{3}{Cubic-graph edge contraction}}{7}{}\protected@file@percent }
\newlabel{def:cubic-edge-contraction}{{3.1}{7}}
\@writefile{lof}{\contentsline {figure}{\numberline {3}{\ignorespaces Cubic-graph edge contraction (Definition\nonbreakingspace 3.1\hbox {}). Left: a fragment of a cubic plane graph with the contracted edge $e = uv$ highlighted in red. Middle: deleting $e$ leaves $u$ and $v$ of degree\nonbreakingspace $2$. Right: smoothing $u$ and $v$ replaces each pair of incident edges by a single new edge, removing $u, v$ and giving a cubic plane graph again.}}{7}{}\protected@file@percent }
\newlabel{fig:cubic-edge-contraction}{{3}{7}}
\newlabel{thm:cubic-contraction-4face}{{3.2}{7}}
\@writefile{toc}{\contentsline {section}{\tocsection {}{4}{The face-monochromatic-pair conjecture and the Four Colour Theorem}}{8}{}\protected@file@percent }
\newlabel{sec:toward-4ct}{{4}{8}}
\newlabel{conj:face-monochromatic-pair-on-merged-kempe-cycle}{{4.1}{8}}
\@writefile{lof}{\contentsline {figure}{\numberline {4}{\ignorespaces The recolouring used in the proof of Theorem\nonbreakingspace 3.2\hbox {}. Left: the $4$-face $f$ of $H$ under $\varphi $, with the forced colours $\varphi (e_0) = a$, $\varphi (e_1) = b$, $\varphi (e_2) = \varphi (e_3) = c$, $\varphi (w_0) = \varphi (w_1) = b$, and $\varphi (w_2) = \varphi (w_3) = a$. Right: the contracted graph $H'$ under $\varphi '$. The smoothed-in edges $e_2', e_3'$ inherit the colour $b$ from $w_0, w_1$, and $e_1$ is recoloured from $b$ to $c$; every edge outside the face neighbourhood keeps its $\varphi $-colour (dotted in red: the five edges of $H$ removed by the contraction).}}{9}{}\protected@file@percent }
\newlabel{fig:thm-cubic-contraction-4face}{{4}{9}}
\newlabel{rem:conj-3-6-empirical}{{4.2}{9}}
\newlabel{conj:face-monochromatic-pair-strengthened}{{4.3}{10}}
\newlabel{rem:conj-3-8-empirical}{{4.4}{10}}
\newlabel{rem:implication-4ct}{{4.5}{10}}
\newlabel{tocindent-1}{0pt}
\newlabel{tocindent0}{0pt}
\newlabel{tocindent1}{17.77782pt}
\newlabel{tocindent2}{0pt}
\newlabel{tocindent3}{0pt}
\newlabel{rem:conj-3-8-empirical}{{4.2}{13}}
\newlabel{rem:implication-4ct}{{4.3}{13}}
\gdef \@abspage@last{14}
\gdef \@abspage@last{11}
@@ -1,4 +1,4 @@
This is pdfTeX, Version 3.141592653-2.6-1.40.24 (TeX Live 2022) (preloaded format=pdflatex 2022.10.5) 24 MAY 2026 13:42
This is pdfTeX, Version 3.141592653-2.6-1.40.24 (TeX Live 2022) (preloaded format=pdflatex 2022.10.5) 24 MAY 2026 14:04
entering extended mode
restricted \write18 enabled.
%&-line parsing enabled.
@@ -244,119 +244,69 @@ LaTeX Warning: `h' float specifier changed to `ht'.
[4] [5 <./fig_chord_apex_step1.png> <./fig_chord_apex_step2.png> <./fig_chord_a
pex_step3.png>] [6]
Overfull \hbox (4.76643pt too wide) in paragraph at lines 433--440
\OT1/cmr/m/n/10 which $\OML/cmm/m/it/10 '[]\OT1/cmr/m/n/10 (\OML/cmm/m/it/10 f[
]\OT1/cmr/m/n/10 ) = \OML/cmm/m/it/10 '[]\OT1/cmr/m/n/10 (\OML/cmm/m/it/10 f[]\
OT1/cmr/m/n/10 )$ and $\OML/cmm/m/it/10 '[]\OT1/cmr/m/n/10 (\OML/cmm/m/it/10 f[
]\OT1/cmr/m/n/10 )\OML/cmm/m/it/10 ; '[]\OT1/cmr/m/n/10 (\OML/cmm/m/it/10 f[]\O
T1/cmr/m/n/10 )\OML/cmm/m/it/10 ; '[]\OT1/cmr/m/n/10 (\OML/cmm/m/it/10 f[]\OT1/
cmr/m/n/10 )$
[]
<fig_alg_step0.png, id=49, 399.6106pt x 459.55217pt>
File: fig_alg_step0.png Graphic file (type png)
<use fig_alg_step0.png>
Package pdftex.def Info: fig_alg_step0.png used on input line 479.
(pdftex.def) Requested size: 115.20264pt x 132.48134pt.
<fig_alg_step1.png, id=50, 399.6106pt x 459.55217pt>
File: fig_alg_step1.png Graphic file (type png)
<use fig_alg_step1.png>
Package pdftex.def Info: fig_alg_step1.png used on input line 480.
(pdftex.def) Requested size: 115.20264pt x 132.48134pt.
<fig_alg_step2.png, id=51, 399.6106pt x 459.55217pt>
File: fig_alg_step2.png Graphic file (type png)
<use fig_alg_step2.png>
Package pdftex.def Info: fig_alg_step2.png used on input line 481.
(pdftex.def) Requested size: 115.20264pt x 132.48134pt.
Underfull \hbox (badness 4391) in paragraph at lines 498--498
\OT1/cmr/m/sc/10 Figure 3.\OT1/cmr/m/n/10 Algorithm 3.1[] on $\OML/cmm/m/it/10
G[] \OT1/cmr/m/n/10 = [](\OML/cmm/m/it/10 G\OT1/cmr/m/n/10 )$, where $\OML/cmm/
m/it/10 G$
[]
Underfull \hbox (badness 3623) in paragraph at lines 498--498
\OT1/cmr/m/n/10 is the first min-degree-$5$ plantri tri-an-gu-la-tion on $14$ v
er-
[]
Underfull \hbox (badness 3179) in paragraph at lines 498--498
\OT1/cmr/m/n/10 tices and $\OML/cmm/m/it/10 '[]$ \OT1/cmr/m/n/10 is a spe-cific
proper $3$-edge-colouring of $\OML/cmm/m/it/10 H[]$
[]
Underfull \hbox (badness 3209) in paragraph at lines 498--498
\OT1/cmr/m/n/10 that sat-is-fies both the chord-apex con-di-tion (Lemma 2.6[])
[]
Underfull \hbox (badness 6094) in paragraph at lines 498--498
\OT1/cmr/m/n/10 and the Kempe-cycle con-di-tion (Lemma 2.7[]), found by
[]
[7] [8 <./fig_alg_step0.png> <./fig_alg_step1.png> <./fig_alg_step2.png>]
[9] [10]
<fig_cubic_edge_contraction.png, id=75, 950.752pt x 203.159pt>
<fig_cubic_edge_contraction.png, id=49, 950.752pt x 203.159pt>
File: fig_cubic_edge_contraction.png Graphic file (type png)
<use fig_cubic_edge_contraction.png>
Package pdftex.def Info: fig_cubic_edge_contraction.png used on input line 702
Package pdftex.def Info: fig_cubic_edge_contraction.png used on input line 432
.
(pdftex.def) Requested size: 341.9989pt x 73.08138pt.
[11 <./fig_cubic_edge_contraction.png>]
<fig_thm_cubic_contraction_4face.png, id=80, 916.223pt x 417.56pt>
[7 <./fig_cubic_edge_contraction.png>]
<fig_thm_cubic_contraction_4face.png, id=55, 916.223pt x 417.56pt>
File: fig_thm_cubic_contraction_4face.png Graphic file (type png)
<use fig_thm_cubic_contraction_4face.png>
Package pdftex.def Info: fig_thm_cubic_contraction_4face.png used on input lin
e 777.
e 507.
(pdftex.def) Requested size: 352.79846pt x 160.78339pt.
[12 <./fig_thm_cubic_contraction_4face.png>]
Underfull \hbox (badness 1648) in paragraph at lines 837--842
\OT1/cmr/m/it/10 Remark \OT1/cmr/m/n/10 4.2\OT1/cmr/m/it/10 . \OT1/cmr/m/n/10 T
LaTeX Warning: `h' float specifier changed to `ht'.
[8]
Underfull \vbox (badness 10000) has occurred while \output is active []
[9 <./fig_thm_cubic_contraction_4face.png>]
Underfull \hbox (badness 1648) in paragraph at lines 638--644
\OT1/cmr/m/it/10 Remark \OT1/cmr/m/n/10 4.4\OT1/cmr/m/it/10 . \OT1/cmr/m/n/10 T
he strength-ened con-jec-ture was tested on the same chord-
[]
Underfull \hbox (badness 1014) in paragraph at lines 837--842
\OT1/cmr/m/n/10 apex+Kempe colour-ings as Re-mark 3.7[]; for each colour-ing we
Underfull \hbox (badness 1014) in paragraph at lines 638--644
\OT1/cmr/m/n/10 apex+Kempe colour-ings as Re-mark 4.2[]; for each colour-ing we
sought any
[]
[13] [14] (./paper.aux) )
[10] [11] (./paper.aux) )
Here is how much of TeX's memory you used:
3114 strings out of 478268
44776 string characters out of 5846347
346374 words of memory out of 5000000
21145 multiletter control sequences out of 15000+600000
3087 strings out of 478268
44184 string characters out of 5846347
350310 words of memory out of 5000000
21121 multiletter control sequences out of 15000+600000
478077 words of font info for 62 fonts, out of 8000000 for 9000
1302 hyphenation exceptions out of 8191
69i,9n,76p,1306b,326s stack positions out of 10000i,1000n,20000p,200000b,200000s
69i,9n,76p,744b,373s 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/texmf-dist/fonts/type1/public/a
msfonts/cm/cmmi10.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/am
sfonts/cm/cmmi5.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsf
onts/cm/cmmi7.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfon
ts/cm/cmmi9.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts
/cm/cmr10.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/c
m/cmr5.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/c
mr7.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.pf
b></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/fonts/type1/public/amsfonts/cm/cmsy7.pfb></u
sr/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/lo
cal/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmtt10.pfb></usr/loc
al/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/symbols/msam10.pfb>
Output written on paper.pdf (14 pages, 1148116 bytes).
sfonts/cm/cmmi7.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsf
onts/cm/cmmi9.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfon
ts/cm/cmr10.pfb></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></usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cm
r9.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmsy1
0.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmsy7.
pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmsy9.pf
b></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/cm/cmtt10.pfb></
usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/symbols/msam10.pf
b>
Output written on paper.pdf (11 pages, 941151 bytes).
PDF statistics:
175 PDF objects out of 1000 (max. 8388607)
94 compressed objects within 1 object stream
144 PDF objects out of 1000 (max. 8388607)
78 compressed objects within 1 object stream
0 named destinations out of 1000 (max. 500000)
61 words of extra memory for PDF output out of 10000 (max. 10000000)
46 words of extra memory for PDF output out of 10000 (max. 10000000)
@@ -393,281 +393,11 @@ distinct colours, contradicting Lemma~\ref{lem:chord-apex} applied to
$\varphi'$.
\end{proof}
\section{An iterated reduction}
\section{Cubic-graph edge contraction}
The reduced-dual construction in Definition~\ref{def:reduced-dual} can be
iterated: starting from a proper $3$-edge-colouring $\varphi_1$ of a reduced
dual $\widehat{G}'_{v,i}$, we apply the construction again to that graph at
a pentagonal face whose ten incident edges avoid the four named edges from
the first reduction, extending $\varphi_1$ across the new reduction. The
protected edges accumulate into a set $E$ that grows by four per iteration,
and the process terminates when $E$ has blocked every pentagonal face.
\begin{algorithm}[Iterated reduction with protected edges]
\label{alg:iterated-reduction}
Let $G$ be a triangulation we assume to be a minimal counterexample to the
Four Colour Theorem. The algorithm produces a sequence $H_1, H_2, \dots$ of
cubic plane graphs, proper $3$-edge-colourings $\varphi_t$ of $H_t$, and a
growing set $E$ of protected edges.
\begin{enumerate}
\item[(0)] Form $G' := \mathrm{dual}(G)$, a cubic plane graph.
\item[(1)] Choose a degree-$5$ vertex $v$ of $G$ (equivalently a pentagonal
face $F_v$ of $G'$) and an index $i_1 \in \{0, \dots, 4\}$. Apply
Definition~\ref{def:reduced-dual} to form
$H_1 := \widehat{G'}_{v, i_1}$, and fix any proper
$3$-edge-colouring $\varphi_1$ of $H_1$ (one exists by the minimality
of $G$).
\item[(2)] Initialise $E := \{\text{spike}, \text{side-}0, \text{side-}1,
\text{merged}\}$, the four named edges of the reduction in (1).
\item[(3)] (Iterate.) At step $t \geq 2$, given $H_{t-1}$, $\varphi_{t-1}$,
and $E \subseteq E(H_{t-1})$:
\begin{enumerate}
\item[(a)] Find a pentagonal face $F$ of $H_{t-1}$ whose ten
incident edges --- the five boundary edges of $\partial F$
and the five external edges at $\partial F$ --- are all
outside $E$. If no such $F$ exists, terminate.
\item[(b)] By Lemma~\ref{lem:pentagonal-externals} applied to
$H_{t-1}$ at $F$ under $\varphi_{t-1}$, the external vector
has shape $(a, b, c, c, c)$ up to cyclic rotation. Choose an
index $i_t$ for which
$\varphi_{t-1}(f_{i_t + 3}) = \varphi_{t-1}(f_{i_t + 4})$ and
$\varphi_{t-1}(f_{i_t}), \varphi_{t-1}(f_{i_t + 1}),
\varphi_{t-1}(f_{i_t + 2})$ are three distinct colours.
\item[(c)] Apply Definition~\ref{def:reduced-dual} to $H_{t-1}$ at
$(F, i_t)$ to form $H_t$.
\item[(d)] Extend $\varphi_{t-1}$ to a proper $3$-edge-colouring
$\varphi_t$ of $H_t$: every surviving edge keeps its
$\varphi_{t-1}$-colour, and each new edge takes the unique
colour completing the palette at its endpoint (consistent
across both endpoints of the chord by the choice of $i_t$).
\item[(e)] Add the four named edges of the step-$t$ reduction to
$E$.
\end{enumerate}
\item[(4)] Repeat (3) until termination.
\end{enumerate}
\end{algorithm}
\begin{remark}
\label{rem:alg-invariants}
At each iteration, $|V(H_t)| = |V(H_{t-1})| - 4$ and
$|E(H_t)| = |E(H_{t-1})| - 6$, so $H_t$ shrinks at a fixed rate; the
protected set $|E|$ grows by exactly four; and every protected edge survives
all subsequent reductions. Since the graph is finite, termination is
guaranteed. By Lemma~\ref{lem:pentagonal-externals}, step~(b) never fails:
some valid $i_t$ always exists for any pentagonal face under any proper
colouring. Termination is therefore combinatorial: it occurs precisely when
$E$ touches every pentagonal face of $H_{t-1}$.
\end{remark}
\begin{remark}
\label{rem:alg-chord-apex}
Lemma~\ref{lem:chord-apex} applies only at $t = 1$, when $H_1$ is a reduced
dual of $G'$. For $t \geq 2$, $H_t$ is a reduced dual of $H_{t-1}$ rather than
of $G'$, and $H_{t-1}$ is itself $3$-edge-colourable, so the
non-$3$-edge-colourability argument that drives Lemma~\ref{lem:chord-apex}
does not carry over. Whether the constraints accumulated in $E$ propagate
any further structure to $\varphi_t$ for $t \geq 2$ is left open.
\end{remark}
\begin{figure}[h]
\centering
\includegraphics[width=0.32\textwidth]{fig_alg_step0.png}\hfill
\includegraphics[width=0.32\textwidth]{fig_alg_step1.png}\hfill
\includegraphics[width=0.32\textwidth]{fig_alg_step2.png}
\caption{Algorithm~\ref{alg:iterated-reduction} on $G'=\mathrm{dual}(G)$, where
$G$ is the first min-degree-$5$ plantri triangulation on $14$ vertices and
$\varphi_1$ is a specific proper $3$-edge-colouring of $H_1$ that satisfies
both the chord-apex condition (Lemma~\ref{lem:chord-apex}) and the Kempe-cycle
condition (Lemma~\ref{lem:kempe-spike}), found by
\texttt{experiments/search\_kempe\_property.py}. \emph{Left:} $G'$
($24$ vertices, $36$ edges) with the chosen pentagonal face shaded.
\emph{Centre:} $H_1$ ($20$ vertices, $30$ edges) after step~(1) with
$i_1 = 1$, $3$-edge-coloured by $\varphi_1$; the four edges around
$v_n^{(1)}$ in $E$ are drawn thicker, and the spike and merged edges share
the colour green. \emph{Right:} $H_2$ ($16$ vertices, $24$ edges) after
step~(3) with $i_t = 3$; eight edges are protected, and the algorithm
terminates one step later (no remaining safe pentagonal face in $H_2$).
The generating script is
\texttt{experiments/draw\_iterated\_reduction\_n14.py}; layouts are Tutte
barycentric embeddings with the outer face picked to keep $v_n^{(1)},
v_n^{(2)}$ in the interior.}
\label{fig:iterated-reduction-trace}
\end{figure}
\begin{lemma}[Exactly one matching pair in the algorithm's output]
\label{lem:exactly-one-match}
Let $G$ be a minimal counterexample to the Four Colour Theorem, and let
$(H_{t^*}, \varphi_{t^*})$ be the final graph-and-colouring produced by some
terminating execution of Algorithm~\ref{alg:iterated-reduction} on $G$, with
named pairs $(\mathrm{spike}_t, \mathrm{merged}_t)$ for $t = 1, \dots, t^*$.
Then there is exactly one $t$ with
$\varphi_{t^*}(\mathrm{spike}_t) = \varphi_{t^*}(\mathrm{merged}_t)$, and it
is $t = 1$.
\end{lemma}
\begin{proof}
The algorithm never re-colours an existing edge: at each iteration
step~(3d) every surviving edge keeps its $\varphi_{t-1}$-colour, and the
four new edges receive fresh colours forced by propriety. Hence for every
$1 \leq k \leq t \leq t^*$,
\[
\varphi_t(\mathrm{spike}_k) = \varphi_k(\mathrm{spike}_k),
\qquad
\varphi_t(\mathrm{merged}_k) = \varphi_k(\mathrm{merged}_k);
\]
the colours of the step-$k$ named edges, once written, are permanent. It
suffices to compare $\varphi_k(\mathrm{spike}_k)$ and
$\varphi_k(\mathrm{merged}_k)$ at the step where each pair is introduced.
\textbf{Case $k = 1$.} Since $G$ is a minimal counterexample, $H_1$ is a
reduced dual of $G'$. Lemma~\ref{lem:chord-apex} applied to $\varphi_1$ gives
$\varphi_1(\mathrm{spike}_1) = \varphi_1(\mathrm{merged}_1)$.
\textbf{Case $k \geq 2$.} At step $k$ the algorithm picks an index $i_k$ for
which $f_{i_k+3} = f_{i_k+4}$ (chord consistency) and $f_{i_k}, f_{i_k+1},
f_{i_k+2}$ are pairwise distinct (propriety at the new $v_n$), where $f$ is
the external vector of the chosen pentagonal face of $H_{k-1}$ under
$\varphi_{k-1}$. Step~(3d) then assigns
\[
\varphi_k(\mathrm{spike}_k) = f_{i_k+1},
\qquad
\varphi_k(\mathrm{merged}_k) = f_{i_k+3}.
\]
By Lemma~\ref{lem:pentagonal-externals}, $f$ has the $(2,2,1)$ pattern: a
block of three consecutive positions $\{p, p+1, p+2\}$ (mod $5$) on which it
is constantly some colour $c$, while the remaining two positions
$\{p+3, p+4\}$ hold the two non-$c$ colours, one each. The condition
$f_{i_k+3} = f_{i_k+4}$ forces $(i_k+3, i_k+4)$ to be either $(p, p+1)$ or
$(p+1, p+2)$ --- the two consecutive pairs inside the block --- and
correspondingly $i_k + 1 \in \{p+3, p+4\}$, \emph{outside} the block. So
$f_{i_k+1}$ is not $c$, whereas $f_{i_k+3} = c$, and hence
$\varphi_k(\mathrm{spike}_k) \neq \varphi_k(\mathrm{merged}_k)$.
Combining the two cases, exactly one $t \in \{1, \dots, t^*\}$ --- namely
$t = 1$ --- has $\varphi_{t^*}(\mathrm{spike}_t) =
\varphi_{t^*}(\mathrm{merged}_t)$.
\end{proof}
\begin{lemma}[All-distinct colouring exists on a 4-colourable graph]
\label{lem:all-distinct-exists}
Let $G$ be a $4$-colourable maximal planar graph of minimum degree $\geq 5$
(equivalently, a maximal planar graph that is \emph{not} a minimal
counterexample to the Four Colour Theorem). Then there is an execution of
Algorithm~\ref{alg:iterated-reduction} on $G$ whose final colouring
$\varphi_{t^*}$ satisfies
$\varphi_{t^*}(\mathrm{spike}_t) \neq \varphi_{t^*}(\mathrm{merged}_t)$ for
every $t \in \{1, \dots, t^*\}$. In particular, there exists a proper
$3$-edge-colouring of $H_{t^*}$ under which every spike-merged pair has
distinct colours.
\end{lemma}
\begin{proof}
The argument mirrors Lemma~\ref{lem:exactly-one-match}, but extends a
colouring \emph{downward} from $G'$ rather than carrying one forward from
$H_1$.
Since $G$ is $4$-colourable, by Tait's theorem
$G' = \mathrm{dual}(G)$ admits a proper $3$-edge-colouring $\xi$. Apply
Lemma~\ref{lem:pentagonal-externals} to $\xi$ at the pentagonal face $F_v$
selected in step~(1): the external vector $f = (f_0, \dots, f_4)$ at $F_v$
under $\xi$ has the $(3,1,1)$ cyclic-consecutive shape, with a block of
three consecutive positions $\{p, p+1, p+2\}$ (mod $5$) holding a common
colour $c$, and the remaining two positions $\{p+3, p+4\}$ holding the two
non-$c$ colours, one each. The algorithm's choice of $i_1$ forces
$\{i_1+3, i_1+4\}$ inside the $c$-block (so the chord is consistently
coloured) and the three positions $\{i_1, i_1+1, i_1+2\}$ pairwise distinct;
in particular $i_1+1$ lies \emph{outside} the $c$-block.
Choose $\varphi_1$ to be the proper $3$-edge-colouring of $H_1$ that agrees
with $\xi$ on every surviving edge and assigns each new edge at $A_j$ the
unique third colour at $A_j$. Then
$\varphi_1(\mathrm{spike}_1) = f_{i_1+1}$, a value not equal to $c$, while
$\varphi_1(\mathrm{merged}_1) = f_{i_1+3} = c$, so
$\varphi_1(\mathrm{spike}_1) \neq \varphi_1(\mathrm{merged}_1)$.
The same argument repeats at every step $k \geq 2$: the external vector at
the chosen pentagonal face under $\varphi_{k-1}$ has the $(3,1,1)$
cyclic-consecutive shape (Lemma~\ref{lem:pentagonal-externals}), the
algorithm's index choice $i_k$ puts $i_k+3, i_k+4$ inside the colour block
and $i_k+1$ outside, and step~(3d) thus assigns
$\varphi_k(\mathrm{spike}_k) \neq \varphi_k(\mathrm{merged}_k)$. The
algorithm preserves these colours through every later step, so
$\varphi_{t^*}(\mathrm{spike}_t) \neq \varphi_{t^*}(\mathrm{merged}_t)$ for
every $t \in \{1, \dots, t^*\}$.
\end{proof}
\begin{conjecture}
\label{conj:face-monochromatic-pair-on-merged-kempe-cycle}
Let $G$ be a minimal counterexample to the Four Colour Theorem, and let
$\widehat{G}'_{v,i}$ be a reduced dual of $G' = \mathrm{dual}(G)$. Then for
every proper $3$-edge-colouring $\varphi$ of $\widehat{G}'_{v,i}$ there exist
a face $F$ of $\widehat{G}'_{v,i}$ and two distinct edges
$e_1, e_2 \in \partial F$, with neither $e_1$ nor $e_2$ equal to the merged
edge, such that
\begin{enumerate}
\item $\varphi(e_1) = \varphi(e_2)$,
\item $e_1$, $e_2$, and the merged edge all lie on a common
$\{a, b\}$-Kempe cycle of $\varphi$, and
\item exactly one edge of $\partial F$ lies between $e_1$ and $e_2$ along
one of the two arcs of $\partial F$; equivalently, subdividing $e_1$
and $e_2$ by new vertices $X_1, X_2$ and joining them by a new edge
$X_1 X_2$ inside $F$ creates a new face bounded by exactly $4$
edges (the new edge, the two subdivision halves adjacent to it, and
the single $\partial F$-edge between $e_1$ and $e_2$).
\end{enumerate}
\end{conjecture}
\begin{remark}
\label{rem:conj-3-6-empirical}
The conjecture cannot be tested on actual minimal counterexamples (none exist
by the Four Colour Theorem), but its conclusion is checkable on the
structural surrogates: proper $3$-edge-colourings of reduced duals that
satisfy both the chord-apex condition (Lemma~\ref{lem:chord-apex}) and the
Kempe-cycle conditions (Lemma~\ref{lem:kempe-spike}), since a counterexample's
reduced dual is forced to admit such colourings under any proper colouring.
For every min-degree-$5$ triangulation $G$ with $|V(G)| \leq 21$, every
pentagonal face $F$ of $G'$, and every reduction index
$i \in \{0,\dots,4\}$, we enumerated all such colourings and tested the
three clauses of Conjecture~\ref{conj:face-monochromatic-pair-on-merged-kempe-cycle}
(see \texttt{experiments/check\_conj\_face\_kempe\_scaled.py}); $n = 22$
ran past a $1800$\,s budget after $641{,}700$ colourings (all pass), but
did not finish the full set of $651$ triangulations:
\begin{center}
\small
\renewcommand{\arraystretch}{1.15}
\begin{tabular}{r|r|r|r|l}
$n$ & \#tri & \#col.\ tested & \#sat.\ & status \\
\hline
$12$ & $1$ & $0$ & --- & vacuous (icosahedron) \\
$13$ & $0$ & --- & --- & no min-deg-$5$ tri \\
$14$ & $1$ & $216$ & $216$ & all pass \\
$15$ & $1$ & $0$ & --- & vacuous \\
$16$ & $3$ & $864$ & $864$ & all pass \\
$17$ & $4$ & $4{,}650$ & $4{,}650$ & all pass \\
$18$ & $12$ & $8{,}070$ & $8{,}070$ & all pass \\
$19$ & $23$ & $21{,}138$ & $21{,}138$ & all pass \\
$20$ & $73$ & $107{,}874$ & $107{,}874$ & all pass \\
$21$ & $192$ & $392{,}370$ & $392{,}370$ & all pass \\
$22$ (part.) & $651$ & $641{,}700$ & $641{,}700$ & timeout \\
\hline
total ($n \le 21$) & $311$ & $535{,}182$ & $535{,}182$ & \\
\end{tabular}
\end{center}
\noindent The vacuous rows ($n = 12, 15$) are those where the relevant
reduced duals admit no proper $3$-edge-colouring satisfying chord-apex +
both Kempe-cycle conditions, so the conjecture has no content there. On
every $(G, F, i, \varphi)$ with content, all three clauses of the
conjecture hold simultaneously.
\end{remark}
The next definition records a cubic-preserving analogue of edge contraction
which turns out --- under planar duality --- to coincide with simple-graph
contraction on the dual side. It will be the central tool in
We introduce a cubic-preserving analogue of edge contraction which turns
out --- under planar duality --- to coincide with simple-graph contraction
on the dual side. It will be the central tool in
Section~\ref{sec:toward-4ct} below, where we formulate a sufficient
condition for the Four Colour Theorem.
@@ -788,39 +518,110 @@ by the contraction).}
\label{fig:thm-cubic-contraction-4face}
\end{figure}
\section{The Four Colour Theorem from a strengthened conjecture}
\section{The face-monochromatic-pair conjecture and the Four Colour Theorem}
\label{sec:toward-4ct}
The next conjecture strengthens
Conjecture~\ref{conj:face-monochromatic-pair-on-merged-kempe-cycle} by adding
a clause that arranges the new $4$-edge face $f_n$ to satisfy the hypotheses
of Theorem~\ref{thm:cubic-contraction-4face}. The strengthening, if true,
would imply the Four Colour Theorem.
The following conjecture identifies a structural property of every proper
$3$-edge-colouring of a reduced dual of a minimal counterexample. If true,
it implies the Four Colour Theorem via
Theorem~\ref{thm:cubic-contraction-4face}.
\begin{conjecture}[Strengthening of Conjecture~\ref{conj:face-monochromatic-pair-on-merged-kempe-cycle}]
The reduced-dual construction of Definition~\ref{def:reduced-dual} can also
be applied \emph{iteratively}, producing a sequence $H_1, H_2, \dots$ of
progressively smaller cubic plane graphs and tracking an accumulating set
of ``protected'' edges; that iterated reduction, with its termination
analysis and structural lemmas about spike/merged pairs at each stage, is
the subject of a companion paper and is not used below.
\begin{conjecture}[Face-monochromatic-pair conjecture]
\label{conj:face-monochromatic-pair-on-merged-kempe-cycle}
Let $G$ be a minimal counterexample to the Four Colour Theorem, and let
$\widehat{G}'_{v,i}$ be a reduced dual of $G' = \mathrm{dual}(G)$. Then
for every proper $3$-edge-colouring $\varphi$ of $\widehat{G}'_{v,i}$
there exist a face $F$ of $\widehat{G}'_{v,i}$ and two distinct edges
$e_1, e_2 \in \partial F$, with neither $e_1$ nor $e_2$ equal to the
merged edge, such that:
\begin{enumerate}
\item $\varphi(e_1) = \varphi(e_2)$. Write
$a := \varphi(e_1) = \varphi(e_2)$.
\item $e_1$, $e_2$, and the merged edge all lie on a common
$\{a, b\}$-Kempe cycle of $\varphi$, for some colour $b \neq a$.
\item Exactly one edge of $\partial F$ lies between $e_1$ and $e_2$
along one of the two arcs of $\partial F$. Equivalently,
subdividing $e_1, e_2$ by new vertices $X_1, X_2$ and joining
them by a new edge $X_1 X_2$ inside $F$ creates a new face $f_n$
bounded by exactly $4$ edges (the new edge $X_1 X_2$, the two
subdivision halves adjacent to it, and the single
$\partial F$-edge between $e_1$ and $e_2$).
\end{enumerate}
\end{conjecture}
\begin{remark}
\label{rem:conj-3-6-empirical}
\sloppy
The conjecture cannot be tested on actual minimal counterexamples (none
exist by the Four Colour Theorem), but its conclusion is checkable on the
structural surrogates: proper $3$-edge-colourings of reduced duals that
satisfy both the chord-apex condition (Lemma~\ref{lem:chord-apex}) and
the Kempe-cycle conditions (Lemma~\ref{lem:kempe-spike}), since a minimal
counterexample's reduced dual is forced to admit such colourings. For
every min-degree-$5$ triangulation $G$ with $|V(G)| \leq 21$, every
pentagonal face $F$ of $G'$, and every reduction index
$i \in \{0,\dots,4\}$, we enumerated all such colourings and verified the
three clauses of
Conjecture~\ref{conj:face-monochromatic-pair-on-merged-kempe-cycle} (see
\texttt{experiments/check\_conj\_face\_kempe\_scaled.py}); $n = 22$ ran
past a $1800$\,s budget after $641{,}700$ colourings (all pass) without
finishing the full set of $651$ triangulations.
\begin{center}
\small
\renewcommand{\arraystretch}{1.15}
\begin{tabular}{r|r|r|r|l}
$n$ & \#tri & \#col.\ tested & \#sat. & status \\
\hline
$12$ & $1$ & $0$ & --- & vacuous (icosahedron) \\
$13$ & $0$ & --- & --- & no min-deg-$5$ tri \\
$14$ & $1$ & $216$ & $216$ & all pass \\
$15$ & $1$ & $0$ & --- & vacuous \\
$16$ & $3$ & $864$ & $864$ & all pass \\
$17$ & $4$ & $4{,}650$ & $4{,}650$ & all pass \\
$18$ & $12$ & $8{,}070$ & $8{,}070$ & all pass \\
$19$ & $23$ & $21{,}138$ & $21{,}138$ & all pass \\
$20$ & $73$ & $107{,}874$ & $107{,}874$ & all pass \\
$21$ & $192$ & $392{,}370$ & $392{,}370$ & all pass \\
$22$ (part.) & $651$ & $641{,}700$ & $641{,}700$ & timeout \\
\hline
total ($n \le 21$) & $311$ & $535{,}182$ & $535{,}182$ & \\
\end{tabular}
\end{center}
\noindent The vacuous rows ($n = 12, 15$) are those where the relevant
reduced duals admit no chord-apex+Kempe colourings, so the conjecture
has no content there.
\end{remark}
The following strengthening adds a fourth clause that arranges the new
$4$-face $f_n$ to satisfy the hypotheses of
Theorem~\ref{thm:cubic-contraction-4face}.
\begin{conjecture}[Strengthening of
Conjecture~\ref{conj:face-monochromatic-pair-on-merged-kempe-cycle}]
\label{conj:face-monochromatic-pair-strengthened}
Let $G$, $\widehat{G}'_{v,i}$, $\varphi$ be as in
Conjecture~\ref{conj:face-monochromatic-pair-on-merged-kempe-cycle}. Then
there exist $F$, $e_1$, $e_2$ satisfying clauses (1)--(3) of that
conjecture, and the following additional clause holds.
Let $X_1, X_2$ be the new vertices subdividing $e_1, e_2$, joined by a new
edge $X_1 X_2$ inside $F$; write $\widehat{G}'^{+}$ for the resulting
modified graph (which has $|V(\widehat{G}'_{v,i})|+2$ vertices and
$|E(\widehat{G}'_{v,i})|+3$ edges, is again cubic and plane, and admits a
proper $3$-edge-colouring). Let $\varphi'$ be the proper
$3$-edge-colouring of $\widehat{G}'^{+}$ obtained from $\varphi$ by
swapping the two colours along the (subdivided) $\{a, b\}$-Kempe cycle of
clause~(2) and assigning the new edge $X_1 X_2$ the remaining (third)
colour. In particular $\varphi'$ agrees with $\varphi$ on every edge of
$\widehat{G}'_{v,i}$ outside that Kempe cycle, and at $X_1$ and $X_2$ the
two subdivision halves take the colours $\{a, b\}$ in the order forced by
propriety. Write $a := \varphi(e_1) = \varphi(e_2)$,
$c := \varphi'(X_1 X_2)$, and let $b$ be the third colour. Let $f_n$ be
the new $4$-edge face of $\widehat{G}'^{+}$ incident to $X_1 X_2$. Then:
there exist $F$, $e_1$, $e_2$ satisfying clauses~(1)--(3) of that
conjecture, together with the following additional clause.
\begin{enumerate}
\setcounter{enumi}{3}
\item either
\item Let $\widehat{G}'^{+}$ be the modified graph obtained from
$\widehat{G}'_{v,i}$ by the modification of clause~(3), and let
$\varphi'$ be the proper $3$-edge-colouring of $\widehat{G}'^{+}$
obtained from $\varphi$ by swapping the two colours along the
(subdivided) $\{a, b\}$-Kempe cycle of clause~(2) and assigning
the new edge $X_1 X_2$ the remaining (third) colour $c$.
(Equivalently: $\varphi'$ agrees with $\varphi$ on every edge of
$\widehat{G}'_{v,i}$ outside that Kempe cycle, and at $X_1, X_2$
the two subdivision halves take the colours $\{a, b\}$ in the
order forced by propriety.) Then either
\begin{enumerate}
\item[(i)] $\partial f_n$ uses all three colours under
$\varphi'$, or
@@ -836,30 +637,29 @@ the new $4$-edge face of $\widehat{G}'^{+}$ incident to $X_1 X_2$. Then:
\sloppy
The strengthened conjecture was tested on the same chord-apex+Kempe
colourings as Remark~\ref{rem:conj-3-6-empirical}; for each colouring we
sought any Conjecture-3.6-witness $(F, e_1, e_2)$ whose accompanying
$f_n$ satisfies clause~(4) (see
sought any
Conjecture-\ref{conj:face-monochromatic-pair-on-merged-kempe-cycle}-witness
$(F, e_1, e_2)$ whose accompanying $f_n$ satisfies clause~(4) (see
\texttt{experiments/check\_conj\_3\_8\_scaled.py}):
\begin{center}
\small
\renewcommand{\arraystretch}{1.15}
\begin{tabular}{r|r|r|r|l}
$n$ & \#tri & \#col.\ tested & \#sat.\ & status \\
$n$ & \#tri & \#col.\ tested & \#sat. & status \\
\hline
$12$ & $1$ & $0$ & --- & vacuous \\
$13$ & $0$ & --- & --- & no min-deg-$5$ tri \\
$14$ & $1$ & $216$ & $216$ & all pass \\
$15$ & $1$ & $0$ & --- & vacuous \\
$16$ & $3$ & $864$ & $864$ & all pass \\
$17$ & $4$ & $4{,}650$ & $4{,}650$ & all pass \\
$18$ & $12$ & $8{,}070$ & $8{,}070$ & all pass \\
$14$ & $1$ & $216$ & $216$ & all pass \\
$16$ & $3$ & $864$ & $864$ & all pass \\
$17$ & $4$ & $4{,}650$ & $4{,}650$ & all pass \\
$18$ & $12$ & $8{,}070$ & $8{,}070$ & all pass \\
\hline
total & $23$ & $13{,}800$ & $13{,}800$ & \\
total ($n \le 18$) & $20$ & $13{,}800$ & $13{,}800$ & \\
\end{tabular}
\end{center}
\noindent A subtlety: only about half of the Conjecture-3.6-witnesses
individually satisfy clause (4) on each colouring, but in every case some
witness does. The conjecture is therefore an existential statement at the
witness level, not a property of every witness.
\noindent A subtlety: only about half of the
Conjecture-\ref{conj:face-monochromatic-pair-on-merged-kempe-cycle}-witnesses
individually satisfy clause~(4) on each colouring, but in every case
\emph{some} witness does. Clause~(4) is therefore an existential statement
at the witness level, not a property of every witness.
\end{remark}
\begin{remark}[The implication to the Four Colour Theorem]