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:
-219
@@ -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()
|
||||
-520
@@ -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)
|
||||
|
||||
|
||||
Binary file not shown.
@@ -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]
|
||||
|
||||
Reference in New Issue
Block a user