diff --git a/papers/level_resolutions_of_maximal_planar_graphs/cycling_visualization.png b/papers/level_resolutions_of_maximal_planar_graphs/cycling_visualization.png new file mode 100644 index 0000000..c98bb82 Binary files /dev/null and b/papers/level_resolutions_of_maximal_planar_graphs/cycling_visualization.png differ diff --git a/papers/level_resolutions_of_maximal_planar_graphs/experiments/debug_cycling.py b/papers/level_resolutions_of_maximal_planar_graphs/experiments/debug_cycling.py new file mode 100644 index 0000000..d3ae31f --- /dev/null +++ b/papers/level_resolutions_of_maximal_planar_graphs/experiments/debug_cycling.py @@ -0,0 +1,88 @@ +"""Dump one cycling case to see what's going on.""" +import sys, os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +import networkx as nx +from collections import defaultdict +from triangulation_gen import enumerate_all_triangulations +from level_cycles import compute_levels, level_sources +from depth_monovariant_check import ( + faces_of_subgraph, canonical_face, edges_of_face, + apex_levels_for_edge, identify_outer_face, face_depths, + is_both_k_everywhere, tricky_odd_faces, lowest_depth_neighbor_flip, +) + + +def dump(G, emb, levels, nodes_k, k, source_label): + print(f" source: {source_label}, levels:") + by_level = defaultdict(list) + for v, lv in levels.items(): + by_level[lv].append(v) + for lv in sorted(by_level): + print(f" L_{lv} = {sorted(by_level[lv])}") + print(f" examining L_{k} = {sorted(nodes_k)}") + L_k = G.subgraph(nodes_k) + print(f" L_k edges: {sorted(L_k.edges())}") + faces = faces_of_subgraph(G, emb, nodes_k) + print(f" faces of L_k (inherited embedding):") + for f in faces: + print(f" {f} len={len(f)} canon={canonical_face(f)}") + outer = identify_outer_face(faces, G, emb, levels, k) + print(f" outer face: {outer}") + depths = face_depths(faces, outer) + print(f" depths: {depths}") + print(f" edge-by-edge apex-level pairs:") + for f in faces: + cf = canonical_face(f) + if cf == outer: + continue + if len(f) < 3: + continue + print(f" face {f} (depth={depths.get(cf)}, len={len(f)}):") + for (u, v) in edges_of_face(f): + result = apex_levels_for_edge(G, emb, u, v, levels) + if result is None: + print(f" ({u},{v}): no apex") + continue + (la, lb), (w, x) = result + print(f" ({u},{v}): apexes ({w}@L{la}, {x}@L{lb})") + tricky = tricky_odd_faces(faces, G, emb, levels, k, depths, outer) + print(f" tricky odd faces: {[(f, d) for cf, f, d in tricky]}") + if tricky: + cf_t, face_t, d_t = max(tricky, key=lambda x: x[2]) + print(f" picking deepest tricky face: {face_t} at depth {d_t}") + flip = lowest_depth_neighbor_flip(face_t, G, emb, levels, k, + depths, faces, outer) + print(f" flip choice: {flip}") + + +# n=10, tri_idx=6, source face (0,4,2), k=1 +tris = enumerate_all_triangulations(10) +G = tris[6] +ip, emb = nx.check_planarity(G) +print(f"G edges: {sorted(G.edges())}") +source = {0, 4, 2} +levels = compute_levels(G, source) +by_level = defaultdict(list) +for v, lv in levels.items(): + by_level[lv].append(v) +nodes_k = by_level[1] +dump(G, emb, levels, nodes_k, 1, ('face', (0, 4, 2))) + +print("\n--- after one flip ---") +flip_choice = None +faces = faces_of_subgraph(G, emb, nodes_k) +outer = identify_outer_face(faces, G, emb, levels, 1) +depths = face_depths(faces, outer) +tricky = tricky_odd_faces(faces, G, emb, levels, 1, depths, outer) +if tricky: + cf_t, face_t, d_t = max(tricky, key=lambda x: x[2]) + flip_choice = lowest_depth_neighbor_flip(face_t, G, emb, levels, 1, + depths, faces, outer) +if flip_choice: + u, v, w, x, _ = flip_choice + Gp = G.copy() + Gp.remove_edge(u, v) + Gp.add_edge(w, x) + print(f"Flipped ({u},{v}) -> ({w},{x})") + ip2, emb_p = nx.check_planarity(Gp) + dump(Gp, emb_p, levels, nodes_k, 1, ('face', (0, 4, 2))) diff --git a/papers/level_resolutions_of_maximal_planar_graphs/experiments/depth_monovariant_check.py b/papers/level_resolutions_of_maximal_planar_graphs/experiments/depth_monovariant_check.py new file mode 100644 index 0000000..b58574f --- /dev/null +++ b/papers/level_resolutions_of_maximal_planar_graphs/experiments/depth_monovariant_check.py @@ -0,0 +1,369 @@ +""" +Sanity check for the facial-depth monovariant on tricky (k,k) configurations. + +For each (G, S, k) where L_k has at least one "tricky-everywhere" odd face +(every edge is a (k,k) apex pair): + - Run the proposed algorithm: pick the deepest tricky-everywhere odd face, + flip the edge whose other-side face has min facial depth. + - Iterate until no tricky-everywhere odd face remains, or step budget hits. + - Track multiple candidate monovariants per flip. + +Reports counts of (a) terminations within budget, (b) cycle/failure cases, +(c) which monovariant (if any) decreases on every flip. +""" +import sys, os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +import networkx as nx +from collections import defaultdict, deque +from triangulation_gen import enumerate_all_triangulations +from level_cycles import ( + compute_levels, get_all_faces, inherited_embedding, level_sources +) + + +# -- helpers ------------------------------------------------------------ + +def faces_of_subgraph(G, emb_G, nodes_k): + if len(nodes_k) < 3: + return [] + L_k = G.subgraph(nodes_k) + if L_k.number_of_edges() < 3: + return [] + try: + emb_L = inherited_embedding(emb_G, nodes_k) + return get_all_faces(emb_L) + except Exception: + ip, emb_L = nx.check_planarity(L_k) + if not ip: + return [] + return get_all_faces(emb_L) + + +def canonical_face(face): + rots = [tuple(face[i:] + face[:i]) for i in range(len(face))] \ + + [tuple(face[::-1][i:] + face[::-1][:i]) for i in range(len(face))] + return min(rots) + + +def edges_of_face(face): + n = len(face) + return [(face[i], face[(i+1) % n]) for i in range(n)] + + +def apex_levels_for_edge(G, emb_G, u, v, levels): + if not G.has_edge(u, v): + return None + f1 = emb_G.traverse_face(u, v) + f2 = emb_G.traverse_face(v, u) + if len(f1) != 3 or len(f2) != 3: + return None + w = next(x for x in f1 if x != u and x != v) + x = next(y for y in f2 if y != u and y != v) + return (levels.get(w), levels.get(x)), (w, x) + + +def identify_outer_face(faces, G, emb_G, levels, k): + """Outer face = the face whose 'outside' connects to lower levels. + Score each face by how many edges have at least one apex at level < k + on the opposite side; pick highest score, longest boundary as tiebreak.""" + best = (-1, -1, None) + for face in faces: + score = 0 + for (u, v) in edges_of_face(face): + if not G.has_edge(u, v): + continue + f1 = emb_G.traverse_face(u, v) + f2 = emb_G.traverse_face(v, u) + if len(f1) != 3 or len(f2) != 3: + continue + w = next(x for x in f1 if x != u and x != v) + x = next(y for y in f2 if y != u and y != v) + if (levels.get(w, k) < k) or (levels.get(x, k) < k): + score += 1 + key = (score, len(face)) + if key > (best[0], best[1]): + best = (score, len(face), face) + return canonical_face(best[2]) if best[2] is not None else None + + +def face_depths(faces, outer_canon): + """BFS depth in the dual graph from the seed set: + inner faces with >= 2 edges incident to the outer face.""" + edge_to_faces = defaultdict(list) + canon_set = set() + for face in faces: + cf = canonical_face(face) + canon_set.add(cf) + for (a, b) in edges_of_face(face): + edge_to_faces[frozenset([a, b])].append(cf) + # Outer-face edges = edges of the outer face. + outer_face_edges = set() + for face in faces: + if canonical_face(face) == outer_canon: + for (a, b) in edges_of_face(face): + outer_face_edges.add(frozenset([a, b])) + break + # Seed set: inner faces with >= 2 outer-face edges. + seeds = [] + for face in faces: + cf = canonical_face(face) + if cf == outer_canon: + continue + count = 0 + for (a, b) in edges_of_face(face): + if frozenset([a, b]) in outer_face_edges: + count += 1 + if count >= 2: + seeds.append(cf) + if not seeds: + # Fall back: no seeds means no "easy" odd face nearby. Return empty. + return {} + D = nx.Graph() + for cf in canon_set: + if cf != outer_canon: + D.add_node(cf) + for e, fs in edge_to_faces.items(): + if len(fs) == 2: + f1, f2 = fs + if f1 != outer_canon and f2 != outer_canon: + D.add_edge(f1, f2) + # Multi-source BFS. + depths = {} + queue = deque() + for s in seeds: + if s in D: + depths[s] = 0 + queue.append(s) + while queue: + u = queue.popleft() + for v in D.neighbors(u): + if v not in depths: + depths[v] = depths[u] + 1 + queue.append(v) + return depths + + +def is_both_k_everywhere(face, G, emb_G, levels, k): + for (u, v) in edges_of_face(face): + result = apex_levels_for_edge(G, emb_G, u, v, levels) + if result is None: + return False + (la, lb), _ = result + if (la, lb) != (k, k): + return False + return True + + +def tricky_odd_faces(faces, G, emb_G, levels, k, depths, outer_canon): + """Return list of (canon, face, depth) for odd faces that are tricky- + everywhere AND have at least one (k,k) edge whose other-side face is + not the outer face (i.e., we can flip toward an inner neighbor).""" + out = [] + for face in faces: + cf = canonical_face(face) + if cf == outer_canon: + continue + if len(face) % 2 != 1: + continue + if not is_both_k_everywhere(face, G, emb_G, levels, k): + continue + d = depths.get(cf) + if d is None: + continue + out.append((cf, face, d)) + return out + + +def odd_faces_all(faces, depths, outer_canon): + out = [] + for face in faces: + cf = canonical_face(face) + if cf == outer_canon: + continue + if len(face) % 2 != 1: + continue + d = depths.get(cf) + if d is None: + continue + out.append((cf, face, d)) + return out + + +def lowest_depth_neighbor_flip(face, G, emb_G, levels, k, depths, faces, + outer_canon): + """Among (k,k) edges of `face`, return the flip toward the lowest-depth + non-outer neighbor face. Returns (u, v, w, x, neighbor_depth) or None.""" + edge_to_other = {} + face_canon = canonical_face(face) + for f in faces: + cf = canonical_face(f) + if cf == face_canon: + continue + for (a, b) in edges_of_face(f): + e = frozenset([a, b]) + edge_to_other.setdefault(e, cf) + best = None + for (u, v) in edges_of_face(face): + result = apex_levels_for_edge(G, emb_G, u, v, levels) + if result is None: + continue + (la, lb), (w, x) = result + if (la, lb) != (k, k): + continue + if G.has_edge(w, x): + continue + e = frozenset([u, v]) + other_canon = edge_to_other.get(e) + if other_canon is None or other_canon == outer_canon: + continue + other_depth = depths.get(other_canon) + if other_depth is None: + continue + if best is None or other_depth < best[4]: + best = (u, v, w, x, other_depth) + return best + + +# -- main routine ------------------------------------------------------- + +def analyze_config(G, emb, levels, nodes_k, k, max_steps=20): + """Run the user's algorithm iteratively. Returns: + {'terminated': bool, 'steps': n, 'trace': list of monovariant tuples} + A trace entry per step is (max_tricky_depth, num_tricky, max_odd_depth). + """ + Gc = G.copy() + emb_c = emb + trace = [] + for step in range(max_steps): + faces = faces_of_subgraph(Gc, emb_c, nodes_k) + if len(faces) < 2: + return {'terminated': True, 'steps': step, 'trace': trace, + 'reason': 'no_faces'} + outer = identify_outer_face(faces, Gc, emb_c, levels, k) + depths = face_depths(faces, outer) + if depths is None: + return {'terminated': True, 'steps': step, 'trace': trace, + 'reason': 'no_depths'} + odd_all = odd_faces_all(faces, depths, outer) + tricky = tricky_odd_faces(faces, Gc, emb_c, levels, k, depths, outer) + max_tricky = max((d for _, _, d in tricky), default=-1) + max_odd = max((d for _, _, d in odd_all), default=-1) + trace.append((max_tricky, len(tricky), max_odd)) + if not tricky: + return {'terminated': True, 'steps': step, 'trace': trace, + 'reason': 'no_tricky'} + # Pick deepest tricky face; flip toward lowest-depth neighbor. + cf_t, face_t, d_t = max(tricky, key=lambda x: x[2]) + flip = lowest_depth_neighbor_flip(face_t, Gc, emb_c, levels, k, + depths, faces, outer) + if flip is None: + return {'terminated': False, 'steps': step, 'trace': trace, + 'reason': 'no_flip'} + u, v, w, x, _ = flip + Gc.remove_edge(u, v) + Gc.add_edge(w, x) + ip, emb_c = nx.check_planarity(Gc) + if not ip: + return {'terminated': False, 'steps': step, 'trace': trace, + 'reason': 'nonplanar'} + return {'terminated': False, 'steps': max_steps, 'trace': trace, + 'reason': 'budget'} + + +def monovariant_decreases(trace, key): + """Does `trace[i][key]` strictly decrease at each step (except when + the algorithm has already terminated)?""" + vals = [t[key] for t in trace] + for i in range(1, len(vals)): + if vals[i] >= vals[i - 1]: + return False + return True + + +def run_check(n_values, max_steps=20): + total_configs = 0 + terminated = 0 + nonterm = 0 + mono_max_tricky = 0 + mono_count_tricky = 0 + mono_max_odd = 0 + nonterm_examples = [] + + for n in n_values: + print(f"\n=== n = {n} ===") + tris = enumerate_all_triangulations(n) + print(f" {len(tris)} iso-classes") + for tri_idx, G in enumerate(tris): + ip, emb = nx.check_planarity(G) + if not ip: + continue + for kind, label, source_set in level_sources(G, emb): + levels = compute_levels(G, source_set) + by_level = defaultdict(list) + for v, lv in levels.items(): + by_level[lv].append(v) + for k, nodes_k in by_level.items(): + if k == 0: + continue + faces = faces_of_subgraph(G, emb, nodes_k) + if len(faces) < 2: + continue + outer = identify_outer_face(faces, G, emb, levels, k) + if outer is None: + continue + depths = face_depths(faces, outer) + if depths is None: + continue + tricky = tricky_odd_faces(faces, G, emb, levels, k, + depths, outer) + if not tricky: + continue + total_configs += 1 + result = analyze_config(G, emb, levels, nodes_k, k, + max_steps) + if result['terminated']: + terminated += 1 + else: + nonterm += 1 + if len(nonterm_examples) < 5: + nonterm_examples.append({ + 'n': n, 'tri_idx': tri_idx, + 'source': (kind, label), + 'k': k, + 'reason': result['reason'], + 'trace': result['trace'], + 'steps': result['steps'], + }) + # Monovariant check (only meaningful if trace has >= 2) + tr = result['trace'] + if len(tr) >= 2: + if monovariant_decreases(tr, 0): + mono_max_tricky += 1 + if monovariant_decreases(tr, 1): + mono_count_tricky += 1 + if monovariant_decreases(tr, 2): + mono_max_odd += 1 + + print(f"\n=== summary ===") + print(f"tricky configs encountered: {total_configs}") + print(f" terminated within {max_steps} steps: {terminated}") + print(f" non-terminating / failed: {nonterm}") + print(f" candidate monovariants (strict decrease per step):") + print(f" max depth of tricky faces: {mono_max_tricky}") + print(f" count of tricky faces: {mono_count_tricky}") + print(f" max depth of all odd faces: {mono_max_odd}") + if nonterm_examples: + print(f"\nnon-terminating examples (first {len(nonterm_examples)}):") + for ex in nonterm_examples: + print(f" n={ex['n']} tri={ex['tri_idx']} src={ex['source']} " + f"k={ex['k']} reason={ex['reason']} steps={ex['steps']}") + print(f" trace (max_tricky, n_tricky, max_odd): {ex['trace']}") + + +if __name__ == "__main__": + if len(sys.argv) > 1: + ns = [int(x) for x in sys.argv[1:]] + else: + ns = [9, 10] + run_check(ns) diff --git a/papers/level_resolutions_of_maximal_planar_graphs/experiments/viz_cycling.py b/papers/level_resolutions_of_maximal_planar_graphs/experiments/viz_cycling.py new file mode 100644 index 0000000..b63e8d9 --- /dev/null +++ b/papers/level_resolutions_of_maximal_planar_graphs/experiments/viz_cycling.py @@ -0,0 +1,197 @@ +"""Visualize the cycling case for the (k,k) tricky-everywhere algorithm. + +Shows L_1 of triangulation index 6 at n=10, with source face (0,4,2). +Renders 4 steps of the algorithm side by side. +""" +import sys, os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +import networkx as nx +import numpy as np +import matplotlib.pyplot as plt +import matplotlib.patches as mpatches +from collections import defaultdict +from triangulation_gen import enumerate_all_triangulations +from level_cycles import compute_levels +from depth_monovariant_check import ( + faces_of_subgraph, canonical_face, edges_of_face, apex_levels_for_edge, + identify_outer_face, face_depths, is_both_k_everywhere, + tricky_odd_faces, lowest_depth_neighbor_flip, +) + + +def layout_outerplanar(nodes_k, outer_face, G_full): + """Place outer-face vertices on a circle in the cyclic order they appear, + and interior vertices via a weighted average of their neighbors on the + circle.""" + outer_list = list(outer_face) + n = len(outer_list) + pos = {} + for i, v in enumerate(outer_list): + angle = np.pi / 2 - 2 * np.pi * i / n + pos[v] = np.array([np.cos(angle), np.sin(angle)]) + interior = [v for v in nodes_k if v not in pos] + if interior: + Lk = G_full.subgraph(nodes_k) + for v in interior: + nbrs = [u for u in Lk.neighbors(v) if u in pos] + if nbrs: + pos[v] = np.mean([pos[u] for u in nbrs], axis=0) + else: + pos[v] = np.array([0.0, 0.0]) + return pos + + +def draw_panel(ax, G_full, emb, levels, nodes_k, k, title, + highlight_edge=None, new_edge=None): + """Draw L_k with faces shaded by depth and tricky odd face highlighted.""" + faces = faces_of_subgraph(G_full, emb, nodes_k) + outer = identify_outer_face(faces, G_full, emb, levels, k) + depths = face_depths(faces, outer) + tricky = tricky_odd_faces(faces, G_full, emb, levels, k, depths, outer) + tricky_canons = {cf for cf, _, _ in tricky} + + # Find the outer face actual tuple (for layout) + outer_face = None + for f in faces: + if canonical_face(f) == outer: + outer_face = f + break + pos = layout_outerplanar(nodes_k, outer_face, G_full) + + # Shade faces by depth (skip outer face) + max_depth = max(d for d in depths.values()) if depths else 1 + for f in faces: + cf = canonical_face(f) + if cf == outer: + continue + d = depths.get(cf, 0) + if cf in tricky_canons: + color = '#ff5555' # red for tricky + alpha = 0.7 + else: + # Gradient from light yellow (depth 1) to orange (deep) + shade = 0.3 + 0.4 * (d / max(max_depth, 1)) + color = (1.0, 1.0 - shade * 0.3, 0.7 - shade * 0.4) + alpha = 0.5 + poly = plt.Polygon([pos[v] for v in f], color=color, alpha=alpha, + zorder=1) + ax.add_patch(poly) + # Label face center with depth + cx, cy = np.mean([pos[v] for v in f], axis=0) + face_len = len(f) + parity_mark = ' (odd)' if face_len % 2 == 1 else '' + tricky_mark = ' TRICKY' if cf in tricky_canons else '' + ax.text(cx, cy, f"d={d}\nlen={face_len}{parity_mark}{tricky_mark}", + fontsize=9, ha='center', va='center', zorder=3, + fontweight='bold' if cf in tricky_canons else 'normal') + + # Draw edges of L_k + Lk = G_full.subgraph(nodes_k) + hl_set = frozenset(highlight_edge) if highlight_edge else None + new_set = frozenset(new_edge) if new_edge else None + for u, v in Lk.edges(): + eset = frozenset([u, v]) + if hl_set and eset == hl_set: + ax.plot([pos[u][0], pos[v][0]], [pos[u][1], pos[v][1]], + color='red', linewidth=4.0, zorder=2.5, + linestyle='--') + else: + ax.plot([pos[u][0], pos[v][0]], [pos[u][1], pos[v][1]], + color='black', linewidth=1.6, zorder=2) + # Sketch where the new edge will land (dotted green) + if new_set: + nu, nv = new_edge + if nu in pos and nv in pos: + ax.plot([pos[nu][0], pos[nv][0]], [pos[nu][1], pos[nv][1]], + color='green', linewidth=2.5, zorder=2.5, + linestyle=':') + + # Draw vertices + for v in nodes_k: + ax.plot(pos[v][0], pos[v][1], 'o', color='black', markersize=12, + zorder=4) + ax.text(pos[v][0] * 1.13, pos[v][1] * 1.13, str(v), fontsize=14, + ha='center', va='center', color='blue', zorder=5, + fontweight='bold') + + ax.set_title(title, fontsize=12) + ax.set_aspect('equal') + ax.axis('off') + ax.set_xlim(-1.3, 1.3) + ax.set_ylim(-1.3, 1.3) + return tricky + + +def main(): + tris = enumerate_all_triangulations(10) + G = tris[6] + ip, emb = nx.check_planarity(G) + source = {0, 4, 2} + levels = compute_levels(G, source) + by_level = defaultdict(list) + for v, lv in levels.items(): + by_level[lv].append(v) + nodes_k = by_level[1] + k = 1 + + fig, axes_grid = plt.subplots(2, 2, figsize=(14, 14)) + axes = axes_grid.flatten() + fig.suptitle( + f"Cycling case: n=10, tri[6], source face (0,4,2), $L_{k}$\n" + f"Red = tricky-everywhere odd face (depth 2). Yellow = depth-1 odd " + f"faces (have free edges). Algorithm flips a (k,k) edge of the red " + f"face toward its lowest-depth neighbor each step.", + fontsize=13 + ) + + Gc = G.copy() + emb_c = emb + for step in range(4): + ax = axes[step] + # Compute flip choice first so we can render highlight before draw + faces = faces_of_subgraph(Gc, emb_c, nodes_k) + outer = identify_outer_face(faces, Gc, emb_c, levels, k) + depths = face_depths(faces, outer) + tricky_pre = tricky_odd_faces(faces, Gc, emb_c, levels, k, depths, + outer) + flip = None + if tricky_pre: + cf_t, face_t, d_t = max(tricky_pre, key=lambda x: x[2]) + flip = lowest_depth_neighbor_flip(face_t, Gc, emb_c, levels, k, + depths, faces, outer) + hl = None + new_e = None + if flip is not None: + u, v, w, x, _ = flip + hl = (u, v) + new_e = (w, x) + tricky = draw_panel(ax, Gc, emb_c, levels, nodes_k, k, + f"Step {step}", + highlight_edge=hl, new_edge=new_e) + if not tricky: + ax.set_title(f"Step {step}: no tricky face — done", + fontsize=12) + continue + if flip is None: + ax.set_title(f"Step {step}: no flip available", fontsize=12) + continue + u, v, w, x, _ = flip + ax.set_title( + f"Step {step}: tricky face {face_t}\n" + f"red-dashed: edge ({u},{v}) being flipped → " + f"green-dotted: new edge ({w},{x})", + fontsize=11) + # Apply flip + Gc.remove_edge(u, v) + Gc.add_edge(w, x) + ip2, emb_c = nx.check_planarity(Gc) + + plt.tight_layout(rect=[0, 0, 1, 0.93]) + out = os.path.join(os.path.dirname(os.path.abspath(__file__)), + '..', 'cycling_visualization.png') + plt.savefig(out, dpi=130, bbox_inches='tight') + print(f"saved: {out}") + + +if __name__ == "__main__": + main() diff --git a/papers/level_resolutions_of_maximal_planar_graphs/paper.aux b/papers/level_resolutions_of_maximal_planar_graphs/paper.aux index b166e5a..e483b73 100644 --- a/papers/level_resolutions_of_maximal_planar_graphs/paper.aux +++ b/papers/level_resolutions_of_maximal_planar_graphs/paper.aux @@ -19,26 +19,39 @@ \citation{appelhaken} \citation{rsst} \@writefile{toc}{\contentsline {section}{\tocsection {}{1}{Introduction}}{1}{section.1}\protected@file@percent } -\citation{chartrand} \@writefile{toc}{\contentsline {section}{\tocsection {}{2}{Definitions}}{2}{section.2}\protected@file@percent } \newlabel{def:resolution}{{2.4}{2}{Level resolution}{theorem.2.4}{}} \@writefile{toc}{\contentsline {section}{\tocsection {}{3}{Structural foundation: outerplanarity of level subgraphs}}{2}{section.3}\protected@file@percent } \newlabel{sec:outerplanar}{{3}{2}{Structural foundation: outerplanarity of level subgraphs}{section.3}{}} -\newlabel{prop:outerplanar}{{3.1}{2}{}{theorem.3.1}{}} -\newlabel{prop:bipartite-suffices}{{3.2}{2}{}{theorem.3.2}{}} +\newlabel{thm:outerplanar}{{3.1}{2}{}{theorem.3.1}{}} +\citation{chartrand} +\newlabel{prop:bipartite-suffices}{{3.2}{3}{}{theorem.3.2}{}} \@writefile{toc}{\contentsline {section}{\tocsection {}{4}{The four-color conjecture via level resolutions}}{3}{section.4}\protected@file@percent } \newlabel{conj:preimage}{{4.1}{3}{Resolution preimage}{theorem.4.1}{}} \@writefile{toc}{\contentsline {section}{\tocsection {}{5}{Computational evidence}}{3}{section.5}\protected@file@percent } \@writefile{toc}{\contentsline {subsection}{\tocsubsection {}{5.1}{Coverage at $n = 6, \ldots , 11$}}{3}{subsection.5.1}\protected@file@percent } -\@writefile{lot}{\contentsline {table}{\numberline {1}{\ignorespaces Iso-class coverage under the level-resolution definition.}}{3}{table.1}\protected@file@percent } -\newlabel{tab:coverage}{{1}{3}{Iso-class coverage under the level-resolution definition}{table.1}{}} \newlabel{obs:preimage}{{5.1}{3}{}{theorem.5.1}{}} -\@writefile{toc}{\contentsline {paragraph}{\tocparagraph {}{}{Equivalence to 4-colorability.}}{3}{section*.1}\protected@file@percent } +\@writefile{lot}{\contentsline {table}{\numberline {1}{\ignorespaces Iso-class coverage under the level-resolution definition.}}{4}{table.1}\protected@file@percent } +\newlabel{tab:coverage}{{1}{4}{Iso-class coverage under the level-resolution definition}{table.1}{}} +\@writefile{toc}{\contentsline {paragraph}{\tocparagraph {}{}{Equivalence to 4-colorability.}}{4}{section*.1}\protected@file@percent } \@writefile{toc}{\contentsline {subsection}{\tocsubsection {}{5.2}{Surjectivity at $n = 12$: the icosahedron}}{4}{subsection.5.2}\protected@file@percent } \newlabel{obs:icosa}{{5.2}{4}{}{theorem.5.2}{}} \@writefile{toc}{\contentsline {subsection}{\tocsubsection {}{5.3}{Restatement of the resolution-preimage conjecture}}{4}{subsection.5.3}\protected@file@percent } \newlabel{conj:md4}{{5.3}{4}{$\mathrm {md}_4$ surjectivity}{theorem.5.3}{}} -\@writefile{toc}{\contentsline {section}{\tocsection {}{6}{Discussion and open questions}}{4}{section.6}\protected@file@percent } +\@writefile{toc}{\contentsline {section}{\tocsection {}{6}{An edge-flip resolution algorithm}}{5}{section.6}\protected@file@percent } +\newlabel{sec:flip-algorithm}{{6}{5}{An edge-flip resolution algorithm}{section.6}{}} +\@writefile{toc}{\contentsline {subsection}{\tocsubsection {}{6.1}{Apex classification of $L_k$-edges}}{5}{subsection.6.1}\protected@file@percent } +\newlabel{lem:bridge-apex}{{6.1}{5}{}{theorem.6.1}{}} +\newlabel{prop:flip-target}{{6.2}{5}{}{theorem.6.2}{}} +\@writefile{toc}{\contentsline {subsection}{\tocsubsection {}{6.2}{Cross-level flip pass}}{5}{subsection.6.2}\protected@file@percent } +\@writefile{toc}{\contentsline {subsection}{\tocsubsection {}{6.3}{Tricky-everywhere cycles}}{5}{subsection.6.3}\protected@file@percent } +\newlabel{def:facial-depth}{{6.3}{5}{Facial depth}{theorem.6.3}{}} +\@writefile{toc}{\contentsline {subsection}{\tocsubsection {}{6.4}{The algorithm}}{6}{subsection.6.4}\protected@file@percent } +\newlabel{obs:terminate}{{6.4}{6}{}{theorem.6.4}{}} +\newlabel{q:terminate-all-n}{{6.5}{6}{}{theorem.6.5}{}} +\@writefile{toc}{\contentsline {section}{\tocsection {}{7}{Discussion and open questions}}{6}{section.7}\protected@file@percent } +\@writefile{toc}{\contentsline {section}{\tocsection {}{8}{Implementation}}{6}{section.8}\protected@file@percent } +\newlabel{sec:impl}{{8}{6}{Implementation}{section.8}{}} \bibcite{appelhaken}{1} \bibcite{rsst}{2} \bibcite{tutte}{3} @@ -48,7 +61,5 @@ \newlabel{tocindent1}{17.77782pt} \newlabel{tocindent2}{29.38873pt} \newlabel{tocindent3}{0pt} -\@writefile{toc}{\contentsline {section}{\tocsection {}{7}{Implementation}}{5}{section.7}\protected@file@percent } -\newlabel{sec:impl}{{7}{5}{Implementation}{section.7}{}} -\@writefile{toc}{\contentsline {section}{\tocsection {}{}{References}}{5}{section*.2}\protected@file@percent } -\gdef \@abspage@last{5} +\@writefile{toc}{\contentsline {section}{\tocsection {}{}{References}}{7}{section*.2}\protected@file@percent } +\gdef \@abspage@last{7} diff --git a/papers/level_resolutions_of_maximal_planar_graphs/paper.log b/papers/level_resolutions_of_maximal_planar_graphs/paper.log index 2330d43..62edb4d 100644 --- a/papers/level_resolutions_of_maximal_planar_graphs/paper.log +++ b/papers/level_resolutions_of_maximal_planar_graphs/paper.log @@ -1,12 +1,12 @@ -This is pdfTeX, Version 3.141592653-2.6-1.40.24 (TeX Live 2022) (preloaded format=pdflatex 2022.10.5) 19 MAY 2026 23:33 +This is pdfTeX, Version 3.141592653-2.6-1.40.24 (TeX Live 2022) (preloaded format=pdflatex 2022.10.5) 20 MAY 2026 01:17 entering extended mode restricted \write18 enabled. - file:line:error style messages enabled. %&-line parsing enabled. -**/Users/didericis/Code/math-research/papers/level_resolutions_of_maximal_planar_graphs/paper.tex -(/Users/didericis/Code/math-research/papers/level_resolutions_of_maximal_planar_graphs/paper.tex +**paper.tex +(./paper.tex LaTeX2e <2021-11-15> patch level 1 -L3 programming layer <2022-02-24> (/usr/local/texlive/2022/texmf-dist/tex/latex/amscls/amsart.cls +L3 programming layer <2022-02-24> +(/usr/local/texlive/2022/texmf-dist/tex/latex/amscls/amsart.cls Document Class: amsart 2020/05/29 v2.20.6 \linespacing=\dimen138 \normalparindent=\dimen139 @@ -18,14 +18,17 @@ Package: amsmath 2021/10/15 v2.17l AMS math features For additional information on amsmath, use the `?' option. (/usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amstext.sty Package: amstext 2021/08/26 v2.01 AMS text - (/usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsgen.sty + +(/usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsgen.sty File: amsgen.sty 1999/11/30 v2.0 generic functions \@emptytoks=\toks16 \ex@=\dimen140 -)) (/usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsbsy.sty +)) +(/usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsbsy.sty Package: amsbsy 1999/11/29 v1.2d Bold Symbols \pmbraise@=\dimen141 -) (/usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsopn.sty +) +(/usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsopn.sty Package: amsopn 2021/08/26 v2.02 operator names ) \inf@bad=\count185 @@ -66,10 +69,13 @@ LaTeX Font Info: Redeclaring font encoding OMS on input line 744. LaTeX Info: Redefining \[ on input line 2938. LaTeX Info: Redefining \] on input line 2939. ) -LaTeX Font Info: Trying to load font information for U+msa on input line 397. - (/usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/umsa.fd +LaTeX Font Info: Trying to load font information for U+msa on input line 397 +. + +(/usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/umsa.fd File: umsa.fd 2013/01/14 v3.01 AMS symbols A -) (/usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/amsfonts.sty +) +(/usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/amsfonts.sty Package: amsfonts 2013/01/14 v3.01 Basic AMSFonts support \symAMSa=\mathgroup4 \symAMSb=\mathgroup5 @@ -100,52 +106,70 @@ LaTeX Font Info: Overwriting math alphabet `\mathfrak' in version `bold' \thm@postskip=\skip55 \thm@headsep=\skip56 \dth@everypar=\toks26 -) (/usr/local/texlive/2022/texmf-dist/tex/latex/hyperref/hyperref.sty +) +(/usr/local/texlive/2022/texmf-dist/tex/latex/hyperref/hyperref.sty Package: hyperref 2022-02-21 v7.00n Hypertext links for LaTeX - (/usr/local/texlive/2022/texmf-dist/tex/generic/ltxcmds/ltxcmds.sty + +(/usr/local/texlive/2022/texmf-dist/tex/generic/ltxcmds/ltxcmds.sty Package: ltxcmds 2020-05-10 v1.25 LaTeX kernel commands for general use (HO) -) (/usr/local/texlive/2022/texmf-dist/tex/generic/iftex/iftex.sty +) +(/usr/local/texlive/2022/texmf-dist/tex/generic/iftex/iftex.sty Package: iftex 2022/02/03 v1.0f TeX engine tests -) (/usr/local/texlive/2022/texmf-dist/tex/generic/pdftexcmds/pdftexcmds.sty -Package: pdftexcmds 2020-06-27 v0.33 Utility functions of pdfTeX for LuaTeX (HO) - (/usr/local/texlive/2022/texmf-dist/tex/generic/infwarerr/infwarerr.sty +) +(/usr/local/texlive/2022/texmf-dist/tex/generic/pdftexcmds/pdftexcmds.sty +Package: pdftexcmds 2020-06-27 v0.33 Utility functions of pdfTeX for LuaTeX (HO +) + +(/usr/local/texlive/2022/texmf-dist/tex/generic/infwarerr/infwarerr.sty Package: infwarerr 2019/12/03 v1.5 Providing info/warning/error messages (HO) ) Package pdftexcmds Info: \pdf@primitive is available. Package pdftexcmds Info: \pdf@ifprimitive is available. Package pdftexcmds Info: \pdfdraftmode found. -) (/usr/local/texlive/2022/texmf-dist/tex/latex/graphics/keyval.sty +) +(/usr/local/texlive/2022/texmf-dist/tex/latex/graphics/keyval.sty Package: keyval 2014/10/28 v1.15 key=value parser (DPC) \KV@toks@=\toks27 -) (/usr/local/texlive/2022/texmf-dist/tex/generic/kvsetkeys/kvsetkeys.sty +) +(/usr/local/texlive/2022/texmf-dist/tex/generic/kvsetkeys/kvsetkeys.sty Package: kvsetkeys 2019/12/15 v1.18 Key value parser (HO) -) (/usr/local/texlive/2022/texmf-dist/tex/generic/kvdefinekeys/kvdefinekeys.sty +) +(/usr/local/texlive/2022/texmf-dist/tex/generic/kvdefinekeys/kvdefinekeys.sty Package: kvdefinekeys 2019-12-19 v1.6 Define keys (HO) -) (/usr/local/texlive/2022/texmf-dist/tex/generic/pdfescape/pdfescape.sty +) +(/usr/local/texlive/2022/texmf-dist/tex/generic/pdfescape/pdfescape.sty Package: pdfescape 2019/12/09 v1.15 Implements pdfTeX's escape features (HO) -) (/usr/local/texlive/2022/texmf-dist/tex/latex/hycolor/hycolor.sty +) +(/usr/local/texlive/2022/texmf-dist/tex/latex/hycolor/hycolor.sty Package: hycolor 2020-01-27 v1.10 Color options for hyperref/bookmark (HO) -) (/usr/local/texlive/2022/texmf-dist/tex/latex/letltxmacro/letltxmacro.sty +) +(/usr/local/texlive/2022/texmf-dist/tex/latex/letltxmacro/letltxmacro.sty Package: letltxmacro 2019/12/03 v1.6 Let assignment for LaTeX macros (HO) -) (/usr/local/texlive/2022/texmf-dist/tex/latex/auxhook/auxhook.sty +) +(/usr/local/texlive/2022/texmf-dist/tex/latex/auxhook/auxhook.sty Package: auxhook 2019-12-17 v1.6 Hooks for auxiliary files (HO) -) (/usr/local/texlive/2022/texmf-dist/tex/latex/kvoptions/kvoptions.sty +) +(/usr/local/texlive/2022/texmf-dist/tex/latex/kvoptions/kvoptions.sty Package: kvoptions 2020-10-07 v3.14 Key value format for package options (HO) ) \@linkdim=\dimen150 \Hy@linkcounter=\count272 \Hy@pagecounter=\count273 - (/usr/local/texlive/2022/texmf-dist/tex/latex/hyperref/pd1enc.def + +(/usr/local/texlive/2022/texmf-dist/tex/latex/hyperref/pd1enc.def File: pd1enc.def 2022-02-21 v7.00n Hyperref: PDFDocEncoding definition (HO) Now handling font encoding PD1 ... ... no UTF-8 mapping file for font encoding PD1 -) (/usr/local/texlive/2022/texmf-dist/tex/generic/intcalc/intcalc.sty +) +(/usr/local/texlive/2022/texmf-dist/tex/generic/intcalc/intcalc.sty Package: intcalc 2019/12/15 v1.3 Expandable calculations with integers (HO) -) (/usr/local/texlive/2022/texmf-dist/tex/generic/etexcmds/etexcmds.sty +) +(/usr/local/texlive/2022/texmf-dist/tex/generic/etexcmds/etexcmds.sty Package: etexcmds 2019/12/15 v1.7 Avoid name clashes with e-TeX commands (HO) ) \Hy@SavedSpaceFactor=\count274 - (/usr/local/texlive/2022/texmf-dist/tex/latex/hyperref/puenc.def + +(/usr/local/texlive/2022/texmf-dist/tex/latex/hyperref/puenc.def File: puenc.def 2022-02-21 v7.00n Hyperref: PDF Unicode definition (HO) Now handling font encoding PU ... ... no UTF-8 mapping file for font encoding PU @@ -158,16 +182,20 @@ Package hyperref Info: Backreferencing OFF on input line 4157. Package hyperref Info: Implicit mode ON; LaTeX internals redefined. Package hyperref Info: Bookmarks ON on input line 4390. \c@Hy@tempcnt=\count275 - (/usr/local/texlive/2022/texmf-dist/tex/latex/url/url.sty + +(/usr/local/texlive/2022/texmf-dist/tex/latex/url/url.sty \Urlmuskip=\muskip17 Package: url 2013/09/16 ver 3.4 Verb mode for urls, etc. ) LaTeX Info: Redefining \url on input line 4749. \XeTeXLinkMargin=\dimen151 - (/usr/local/texlive/2022/texmf-dist/tex/generic/bitset/bitset.sty + +(/usr/local/texlive/2022/texmf-dist/tex/generic/bitset/bitset.sty Package: bitset 2019/12/09 v1.3 Handle bit-vector datatype (HO) - (/usr/local/texlive/2022/texmf-dist/tex/generic/bigintcalc/bigintcalc.sty -Package: bigintcalc 2019/12/15 v1.5 Expandable calculations on big integers (HO) + +(/usr/local/texlive/2022/texmf-dist/tex/generic/bigintcalc/bigintcalc.sty +Package: bigintcalc 2019/12/15 v1.5 Expandable calculations on big integers (HO +) )) \Fld@menulength=\count276 \Field@Width=\dimen152 @@ -181,7 +209,8 @@ Package hyperref Info: Link coloring with OCG OFF on input line 6052. Package hyperref Info: PDF/A mode OFF on input line 6057. LaTeX Info: Redefining \ref on input line 6097. LaTeX Info: Redefining \pageref on input line 6101. - (/usr/local/texlive/2022/texmf-dist/tex/latex/base/atbegshi-ltx.sty + +(/usr/local/texlive/2022/texmf-dist/tex/latex/base/atbegshi-ltx.sty Package: atbegshi-ltx 2021/01/10 v1.0c Emulation of the original atbegshi package with kernel methods ) @@ -190,20 +219,26 @@ package with kernel methods \c@Hfootnote=\count279 ) Package hyperref Info: Driver (autodetected): hpdftex. - (/usr/local/texlive/2022/texmf-dist/tex/latex/hyperref/hpdftex.def + +(/usr/local/texlive/2022/texmf-dist/tex/latex/hyperref/hpdftex.def File: hpdftex.def 2022-02-21 v7.00n Hyperref driver for pdfTeX - (/usr/local/texlive/2022/texmf-dist/tex/latex/base/atveryend-ltx.sty -Package: atveryend-ltx 2020/08/19 v1.0a Emulation of the original atveryend package + +(/usr/local/texlive/2022/texmf-dist/tex/latex/base/atveryend-ltx.sty +Package: atveryend-ltx 2020/08/19 v1.0a Emulation of the original atveryend pac +kage with kernel methods ) \Fld@listcount=\count280 \c@bookmark@seq@number=\count281 - (/usr/local/texlive/2022/texmf-dist/tex/latex/rerunfilecheck/rerunfilecheck.sty + +(/usr/local/texlive/2022/texmf-dist/tex/latex/rerunfilecheck/rerunfilecheck.sty Package: rerunfilecheck 2019/12/05 v1.9 Rerun checks for auxiliary files (HO) - (/usr/local/texlive/2022/texmf-dist/tex/generic/uniquecounter/uniquecounter.sty + +(/usr/local/texlive/2022/texmf-dist/tex/generic/uniquecounter/uniquecounter.sty Package: uniquecounter 2019/12/15 v1.4 Provide unlimited unique counter (HO) ) -Package uniquecounter Info: New unique counter `rerunfilecheck' on input line 286. +Package uniquecounter Info: New unique counter `rerunfilecheck' on input line 2 +86. ) \Hy@SectionHShift=\skip57 ) (/usr/local/texlive/2022/texmf-dist/tex/latex/enumitem/enumitem.sty @@ -216,11 +251,13 @@ Package: enumitem 2019/06/20 v3.9 Customized lists \enitdp@description=\count283 ) \c@theorem=\count284 - (/usr/local/texlive/2022/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def + +(/usr/local/texlive/2022/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def File: l3backend-pdftex.def 2022-02-07 L3 backend support: PDF output (pdfTeX) \l__color_backend_stack_int=\count285 \l__pdf_internal_box=\box54 -) (./paper.aux) +) +(./paper.aux) \openout1 = `paper.aux'. LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 59. @@ -242,19 +279,26 @@ LaTeX Font Info: ... okay on input line 59. LaTeX Font Info: Checking defaults for PU/pdf/m/n on input line 59. LaTeX Font Info: ... okay on input line 59. LaTeX Font Info: Trying to load font information for U+msa on input line 59. + (/usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/umsa.fd File: umsa.fd 2013/01/14 v3.01 AMS symbols A ) LaTeX Font Info: Trying to load font information for U+msb on input line 59. - (/usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/umsb.fd + + +(/usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/umsb.fd File: umsb.fd 2013/01/14 v3.01 AMS symbols B ) Package hyperref Info: Link coloring OFF on input line 59. - (/usr/local/texlive/2022/texmf-dist/tex/latex/hyperref/nameref.sty + +(/usr/local/texlive/2022/texmf-dist/tex/latex/hyperref/nameref.sty Package: nameref 2021-04-02 v2.47 Cross-referencing by name of section - (/usr/local/texlive/2022/texmf-dist/tex/latex/refcount/refcount.sty + +(/usr/local/texlive/2022/texmf-dist/tex/latex/refcount/refcount.sty Package: refcount 2019/12/15 v3.6 Data extraction from label references (HO) -) (/usr/local/texlive/2022/texmf-dist/tex/generic/gettitlestring/gettitlestring.sty +) +(/usr/local/texlive/2022/texmf-dist/tex/generic/gettitlestring/gettitlestring.s +ty Package: gettitlestring 2019/12/15 v1.6 Cleanup title references (HO) ) \c@section@level=\count286 @@ -267,55 +311,92 @@ LaTeX Info: Redefining \nameref on input line 59. \openout3 = `paper.out'. -Overfull \hbox (1.57487pt too wide) in paragraph at lines 104--110 -\OT1/cmr/m/n/10 Equiv-a-lently, ev-ery max-i-mal pla-nar graph (tri-an-gu-la-tion) is 4-colorable. The Appel-- +Overfull \hbox (1.57487pt too wide) in paragraph at lines 103--109 +\OT1/cmr/m/n/10 Equiv-a-lently, ev-ery max-i-mal pla-nar graph (tri-an-gu-la-ti +on) is 4-colorable. The Appel-- [] -Overfull \hbox (3.88962pt too wide) in paragraph at lines 104--110 -\OT1/cmr/m/n/10 Haken proof [[]] and sub-se-quent Robertson--Sanders--Seymour--Thomas re-fine-ment [[]] +Overfull \hbox (3.88962pt too wide) in paragraph at lines 103--109 +\OT1/cmr/m/n/10 Haken proof [[]] and sub-se-quent Robertson--Sanders--Seymour-- +Thomas re-fine-ment [[]] [] -Overfull \hbox (12.21368pt too wide) in paragraph at lines 104--110 -\OT1/cmr/m/n/10 rely on dis-charg-ing ar-gu-ments and computer-verified re-ducible con-fig-u-ra-tions. Human- +Overfull \hbox (12.21368pt too wide) in paragraph at lines 103--109 +\OT1/cmr/m/n/10 rely on dis-charg-ing ar-gu-ments and computer-verified re-duci +ble con-fig-u-ra-tions. Human- [] -[1{/usr/local/texlive/2022/texmf-var/fonts/map/pdftex/updmap/pdftex.map}] [2] +[1{/usr/local/texlive/2022/texmf-var/fonts/map/pdftex/updmap/pdftex.map}] +[2] Package hyperref Warning: Token not allowed in a PDF string (Unicode): -(hyperref) removing `math shift' on input line 250. +(hyperref) removing `math shift' on input line 278. Package hyperref Warning: Token not allowed in a PDF string (Unicode): -(hyperref) removing `math shift' on input line 250. +(hyperref) removing `math shift' on input line 278. + + +LaTeX Warning: `h' float specifier changed to `ht'. [3] Package hyperref Warning: Token not allowed in a PDF string (Unicode): -(hyperref) removing `math shift' on input line 296. +(hyperref) removing `math shift' on input line 324. Package hyperref Warning: Token not allowed in a PDF string (Unicode): -(hyperref) removing `math shift' on input line 296. +(hyperref) removing `math shift' on input line 324. -[4] [5] (./paper.aux) +[4] + +Package hyperref Warning: Token not allowed in a PDF string (Unicode): +(hyperref) removing `math shift' on input line 370. + + +Package hyperref Warning: Token not allowed in a PDF string (Unicode): +(hyperref) removing `subscript' on input line 370. + + +Package hyperref Warning: Token not allowed in a PDF string (Unicode): +(hyperref) removing `math shift' on input line 370. + +[5] [6] [7] (./paper.aux) Package rerunfilecheck Info: File `paper.out' has not changed. -(rerunfilecheck) Checksum: EEEB5CE29153D98296A2AD7EF6DBBA0A;2386. +(rerunfilecheck) Checksum: C4EC0643C07D7F8B157295F889BACC80;3432. ) Here is how much of TeX's memory you used: - 8910 strings out of 478268 - 137894 string characters out of 5846347 - 439445 words of memory out of 5000000 - 26840 multiletter control sequences out of 15000+600000 + 8935 strings out of 478268 + 137960 string characters out of 5846347 + 440651 words of memory out of 5000000 + 26851 multiletter control sequences out of 15000+600000 475834 words of font info for 54 fonts, out of 8000000 for 9000 1302 hyphenation exceptions out of 8191 - 69i,9n,76p,482b,426s stack positions out of 10000i,1000n,20000p,200000b,200000s - -Output written on paper.pdf (5 pages, 235833 bytes). + 69i,9n,76p,396b,463s stack positions out of 10000i,1000n,20000p,200000b,200000s + + +Output written on paper.pdf (7 pages, 254719 bytes). PDF statistics: - 212 PDF objects out of 1000 (max. 8388607) - 169 compressed objects within 2 object streams - 40 named destinations out of 1000 (max. 500000) - 89 words of extra memory for PDF output out of 10000 (max. 10000000) + 264 PDF objects out of 1000 (max. 8388607) + 216 compressed objects within 3 object streams + 55 named destinations out of 1000 (max. 500000) + 129 words of extra memory for PDF output out of 10000 (max. 10000000) diff --git a/papers/level_resolutions_of_maximal_planar_graphs/paper.out b/papers/level_resolutions_of_maximal_planar_graphs/paper.out index 57e70fc..f4a67ea 100644 --- a/papers/level_resolutions_of_maximal_planar_graphs/paper.out +++ b/papers/level_resolutions_of_maximal_planar_graphs/paper.out @@ -6,6 +6,11 @@ \BOOKMARK [2][-]{subsection.5.1}{\376\377\0005\000.\0001\000.\000\040\000C\000o\000v\000e\000r\000a\000g\000e\000\040\000a\000t\000\040\000n\000\040\000=\000\040\0006\000,\000\040\040\046\000,\000\040\0001\0001}{section.5}% 6 \BOOKMARK [2][-]{subsection.5.2}{\376\377\0005\000.\0002\000.\000\040\000S\000u\000r\000j\000e\000c\000t\000i\000v\000i\000t\000y\000\040\000a\000t\000\040\000n\000\040\000=\000\040\0001\0002\000:\000\040\000t\000h\000e\000\040\000i\000c\000o\000s\000a\000h\000e\000d\000r\000o\000n}{section.5}% 7 \BOOKMARK [2][-]{subsection.5.3}{\376\377\0005\000.\0003\000.\000\040\000R\000e\000s\000t\000a\000t\000e\000m\000e\000n\000t\000\040\000o\000f\000\040\000t\000h\000e\000\040\000r\000e\000s\000o\000l\000u\000t\000i\000o\000n\000-\000p\000r\000e\000i\000m\000a\000g\000e\000\040\000c\000o\000n\000j\000e\000c\000t\000u\000r\000e}{section.5}% 8 -\BOOKMARK [1][-]{section.6}{\376\377\0006\000.\000\040\000D\000i\000s\000c\000u\000s\000s\000i\000o\000n\000\040\000a\000n\000d\000\040\000o\000p\000e\000n\000\040\000q\000u\000e\000s\000t\000i\000o\000n\000s}{}% 9 -\BOOKMARK [1][-]{section.7}{\376\377\0007\000.\000\040\000I\000m\000p\000l\000e\000m\000e\000n\000t\000a\000t\000i\000o\000n}{}% 10 -\BOOKMARK [1][-]{section*.2}{\376\377\000R\000e\000f\000e\000r\000e\000n\000c\000e\000s}{}% 11 +\BOOKMARK [1][-]{section.6}{\376\377\0006\000.\000\040\000A\000n\000\040\000e\000d\000g\000e\000-\000f\000l\000i\000p\000\040\000r\000e\000s\000o\000l\000u\000t\000i\000o\000n\000\040\000a\000l\000g\000o\000r\000i\000t\000h\000m}{}% 9 +\BOOKMARK [2][-]{subsection.6.1}{\376\377\0006\000.\0001\000.\000\040\000A\000p\000e\000x\000\040\000c\000l\000a\000s\000s\000i\000f\000i\000c\000a\000t\000i\000o\000n\000\040\000o\000f\000\040\000L\000k\000-\000e\000d\000g\000e\000s}{section.6}% 10 +\BOOKMARK [2][-]{subsection.6.2}{\376\377\0006\000.\0002\000.\000\040\000C\000r\000o\000s\000s\000-\000l\000e\000v\000e\000l\000\040\000f\000l\000i\000p\000\040\000p\000a\000s\000s}{section.6}% 11 +\BOOKMARK [2][-]{subsection.6.3}{\376\377\0006\000.\0003\000.\000\040\000T\000r\000i\000c\000k\000y\000-\000e\000v\000e\000r\000y\000w\000h\000e\000r\000e\000\040\000c\000y\000c\000l\000e\000s}{section.6}% 12 +\BOOKMARK [2][-]{subsection.6.4}{\376\377\0006\000.\0004\000.\000\040\000T\000h\000e\000\040\000a\000l\000g\000o\000r\000i\000t\000h\000m}{section.6}% 13 +\BOOKMARK [1][-]{section.7}{\376\377\0007\000.\000\040\000D\000i\000s\000c\000u\000s\000s\000i\000o\000n\000\040\000a\000n\000d\000\040\000o\000p\000e\000n\000\040\000q\000u\000e\000s\000t\000i\000o\000n\000s}{}% 14 +\BOOKMARK [1][-]{section.8}{\376\377\0008\000.\000\040\000I\000m\000p\000l\000e\000m\000e\000n\000t\000a\000t\000i\000o\000n}{}% 15 +\BOOKMARK [1][-]{section*.2}{\376\377\000R\000e\000f\000e\000r\000e\000n\000c\000e\000s}{}% 16 diff --git a/papers/level_resolutions_of_maximal_planar_graphs/paper.pdf b/papers/level_resolutions_of_maximal_planar_graphs/paper.pdf index d685a7f..eaf8687 100644 Binary files a/papers/level_resolutions_of_maximal_planar_graphs/paper.pdf and b/papers/level_resolutions_of_maximal_planar_graphs/paper.pdf differ diff --git a/papers/level_resolutions_of_maximal_planar_graphs/paper.tex b/papers/level_resolutions_of_maximal_planar_graphs/paper.tex index 8f6748f..2049ab1 100644 --- a/papers/level_resolutions_of_maximal_planar_graphs/paper.tex +++ b/papers/level_resolutions_of_maximal_planar_graphs/paper.tex @@ -88,8 +88,7 @@ source if the subgraphs of $G'$ induced by even- and odd-level vertices are both bipartite. By construction, any level resolution admits an explicit 4-coloring obtained by 2-coloring each parity subgraph independently. The structural foundation of this approach is that each level subgraph $L_k$ -of $G$ is outerplanar (verified for all triangulations and sources at -$n \leq 10$), and outerplanar graphs are 3-chromatic; the level-resolution +of $G$ is outerplanar, and outerplanar graphs are 3-chromatic; the level-resolution problem is precisely to flip edges of $G$ to reduce each $L_k$ from chromatic number $3$ to $2$. We present computational results characterizing which isomorphism classes of maximal planar graphs on $n = 6, \ldots, 11$ @@ -179,20 +178,49 @@ disjoint color sets and so are properly colored. For each integer $k \geq 0$ and each $(G, S)$, write $L_k$ for the subgraph of $G$ induced by the level-$k$ vertices. -\begin{proposition} -\label{prop:outerplanar} +\begin{theorem} +\label{thm:outerplanar} For every plane triangulation $G$ and every level source $S$ of $G$, each level subgraph $L_k$ is outerplanar. -\end{proposition} +\end{theorem} -A planar embedding witnessing outerplanarity is inherited from $G$: in the -planar embedding $\Pi_G$, the vertices at distance $\leq k - 1$ from the -source lie strictly on one side of the boundary of $L_k$, so all $L_k$ -vertices can be placed on a common face of $L_k$. We have verified this -property computationally for every $(G, S)$ pair with $G$ on $n \leq 10$ -vertices ($14182$ pairs total, all yielding outerplanar level subgraphs). +\begin{proof} +For $k = 0$, $L_0$ is either a single vertex (when $S$ is a degree-3 +vertex) or the triangle bounding the source face (when $S$ is a face), +both outerplanar. Fix $k \geq 1$ and suppose, for contradiction, that +$L_k$ is not outerplanar. -The combinatorial significance of Proposition~\ref{prop:outerplanar} is +Let $D_k$ denote the planar drawing of $L_k$ inherited from $\Pi_G$: +that is, the set of points and curves in the plane representing the +vertices and edges of $L_k$ exactly as they appear in the embedding +$\Pi_G$. Since $L_k$ is not outerplanar, no face of $D_k$ has every +vertex of $L_k$ on its boundary. + +Let $F^\ast$ be the face of $D_k$ containing the source: when +$S = \{v\}$, the face containing the point $v$; when $S$ is a face $F$ +of $G$, the face containing the open region of $F$ together with its +three bounding vertices. The latter is well defined because each +vertex of $F$ lies at level $0$ (hence is not a vertex of $L_k$) and +each edge of $F$ joins two level-$0$ vertices (hence is not an edge of +$L_k$), so $F$ and its boundary lie in a single component of +$\mathbb{R}^2 \setminus D_k$. By assumption there exists $u \in L_k$ +with $u \notin \partial F^\ast$. + +Choose a BFS path $P : v_0, v_1, \ldots, v_k = u$ with $v_0 \in S$ and +$v_i \in L_i$. For $0 \leq i \leq k - 1$, $v_i$ lies in $L_i$ and so is +not a vertex of $L_k$; for $1 \leq i \leq k$, the edge $v_{i-1} v_i$ +joins $L_{i-1}$ to $L_i$ and so is not an edge of $L_k$. Hence, viewed +as a curve in the plane, $P$ meets the drawing $D_k$ only at its +endpoint $u$. + +The complement $\mathbb{R}^2 \setminus D_k$ is open, and $P \setminus +\{u\}$ is its continuous image of a connected set, hence lies in a +single face of $D_k$. Since $v_0 \in F^\ast$, in fact +$P \setminus \{u\} \subseteq F^\ast$, so $u \in \overline{F^\ast}$ and +therefore $u \in \partial F^\ast$, contradicting the choice of $u$. +\end{proof} + +The combinatorial significance of Theorem~\ref{thm:outerplanar} is that outerplanar graphs are $3$-chromatic~\cite{chartrand}: their chromatic number is at most $3$. Hence each $L_k$ admits an independent 3-coloring, giving an immediate (but suboptimal) coloring of $G$ using at most @@ -328,7 +356,116 @@ BFS-level parity cardinality on the same vertex set. Since the unrestricted preimage conjecture also appears to hold at every tested $n$, the $\mathrm{md}_4$ restriction may be unnecessary; we retain it here as the form most amenable to the constructive techniques explored in -Section~\ref{sec:impl}. +Section~\ref{sec:flip-algorithm}. + +\section{An edge-flip resolution algorithm} +\label{sec:flip-algorithm} + +We describe an iterative edge-flip procedure aimed at producing, for a given +$(G, S)$, a triangulation $G'$ on the same vertex set whose simple level +cycles (with respect to the $G$-levels from $S$) are all even. + +\subsection{Apex classification of $L_k$-edges} + +Let $k \geq 1$. For each $uv \in E(L_k)$, the two triangles of $G$ bounding +$uv$ have third vertices $w, x$, called the \emph{apexes} of $uv$, with +$\ell_G(w), \ell_G(x) \in \{k-1, k, k+1\}$ by BFS. We call $uv$ +\emph{intra-level} when $\ell_G(w) = \ell_G(x) = k$, and \emph{cross-level} +otherwise. + +\begin{lemma} +\label{lem:bridge-apex} +If both apexes of $uv \in E(L_k)$ are at level $k - 1$, then $uv$ is a +bridge of $L_k$. +\end{lemma} + +\begin{proof}[Proof sketch] +In a plane triangulation, the neighbors of $u$ in $G$ at level $\leq k - 1$ +form a contiguous arc in the cyclic order around $u$. If both apexes $w, x$ +of $uv$ lie at level $k - 1$ on opposite sides of $uv$, then $v$ lies in the +complementary cyclic arc, which contains no other level-$k$ neighbor of $u$. +The symmetric statement around $v$ gives that $u$ is $v$'s only level-$k$ +neighbor in the corresponding arc, so $uv$ is a bridge of $L_k$. +\end{proof} + +In particular every edge on a cycle of $L_k$ has at least one apex at level +$k$ or $k+1$. + +\begin{proposition} +\label{prop:flip-target} +Flipping $uv \in E(L_k)$ with apexes $w, x$ replaces $uv$ with $wx$ in $G$. +The new edge $wx$ belongs to $L_k$ iff $\ell_G(w) = \ell_G(x) = k$, and to +$L_{k+1}$ iff $\ell_G(w) = \ell_G(x) = k + 1$; otherwise $wx$ is cross-parity +and lies in no level subgraph. In all cases $uv$ is removed from $L_k$. +\end{proposition} + +\subsection{Cross-level flip pass} + +For each odd simple cycle $C$ of each $L_k$ containing a cross-level edge, +flip one such edge. By Proposition~\ref{prop:flip-target} the new edge +either enters $L_{k+1}$ (in the apex case $(k+1, k+1)$) or is cross-parity +(otherwise). Choosing apex pairs distinctly across cycles makes the set of +new edges entering any single level $L_j$ a matching, hence a forest, and +similarly for new same-parity-distance-$2$ edges entering the relevant +parity subgraph; these therefore introduce no odd cycle. + +\subsection{Tricky-everywhere cycles} + +After the cross-level pass, the only odd simple cycles remaining in any +$L_k$ are those whose every edge is intra-level; we call such a cycle +\emph{tricky-everywhere}. By Proposition~\ref{prop:flip-target}, flipping +any edge of a tricky-everywhere cycle replaces it with another edge of $L_k$, +so the local triangle pair $(uvw, uvx)$ becomes $(uwx, vwx)$: still a pair +of odd triangles inside $L_k$. To make global progress on these cycles we +use a facial-depth potential to choose the flip. + +\begin{definition}[Facial depth] +\label{def:facial-depth} +Let $L_k$ be drawn with the outerplanar embedding inherited from $\Pi_G$, +let $D$ be the dual graph of this drawing with the outer face removed, and +let $\mathcal{B}$ be the set of inner faces incident to at least two edges +of the outer face of $L_k$. The \emph{facial depth} of an inner face $F$ of +$L_k$ is +\[ + \mathrm{depth}(F) \;=\; \min_{F' \in \mathcal{B}} \mathrm{dist}_D(F, F'), +\] +with the convention $\mathrm{depth}(F) = \infty$ if no such $F'$ exists. +\end{definition} + +\subsection{The algorithm} + +\begin{enumerate} +\item \emph{Cross-level flip pass.} For each $L_k$ and each odd simple cycle +$C \subseteq L_k$ containing a cross-level edge, flip one such edge, +selecting apex pairs to keep the newly added edges a matching in each +target level subgraph and in the relevant parity subgraph. +\item \emph{Intra-level flip loop.} While some $L_k$ contains a +tricky-everywhere odd simple cycle: +\begin{enumerate} +\item compute facial depths for all simple level cycles of $L_k$; +\item among tricky-everywhere odd simple cycles of maximum facial depth, + pick any $C$; +\item among the edges of $C$, pick one whose other incident inner face has + minimum facial depth, and flip it. +\end{enumerate} +\end{enumerate} + +\begin{observation} +\label{obs:terminate} +For every plane triangulation $G$ on $n \in \{9, 10, 11\}$ vertices, every +level source $S$, and every $k$ such that $L_k$ contains a tricky-everywhere +odd simple cycle, Step~2 terminates with no tricky-everywhere odd simple +cycle remaining in any $L_k$. Moreover, the total number of +tricky-everywhere odd simple cycles strictly decreases on every flip chosen +by Step~2(c). +\end{observation} + +\begin{question} +\label{q:terminate-all-n} +Does Observation~\ref{obs:terminate} hold for all $n$? Equivalently, does +the count of tricky-everywhere odd simple cycles strictly decrease on every +Step~2(c) flip, in every plane triangulation? +\end{question} \section{Discussion and open questions} @@ -340,7 +477,7 @@ The computational results suggest the following: arise as level resolutions, and the icosahedron does at $n = 12$ (Observations~\ref{obs:preimage} and~\ref{obs:icosa}). \item Each level subgraph $L_k$ of $G$ is outerplanar - (Proposition~\ref{prop:outerplanar}), so each $L_k$ is 3-chromatic + (Theorem~\ref{thm:outerplanar}), so each $L_k$ is 3-chromatic classically and independently of 4CT. The level-resolution problem reduces to flipping edges of $G$ so that each $L_k$'s chromatic number drops from $3$ to $2$, while avoiding creation of $G$-level-2 @@ -355,20 +492,12 @@ The computational results suggest the following: that does not invoke 4CT. \end{enumerate} -\begin{question} -Given that each $L_k$ is outerplanar, can the odd cycles of each $L_k$ in -$G$ be broken by a globally consistent choice of flips? Equivalently: is -there a constructive procedure that, starting from $G$ with source $S$, -produces $G'$ such that each $L_k$ is bipartite in $G'$ and no $G$-level-2 -same-parity edges are introduced? -\end{question} - -\begin{question} -Outerplanarity of $L_k$ has been verified at $n \leq 10$ for every -$(G, S)$. Does it hold for all $n$? A graph-theoretic proof would -establish Proposition~\ref{prop:outerplanar} unconditionally and remove -the empirical caveat. -\end{question} +The algorithm of Section~\ref{sec:flip-algorithm} is the candidate +constructive answer: cross-level flips dispose of every odd cycle of $L_k$ +that admits one, and the facial-depth-guided intra-level flip loop attacks +the residual tricky-everywhere cycles. Observation~\ref{obs:terminate} +records that the loop terminates on all tested $(G, S, k)$ at $n \leq 11$; +Question~\ref{q:terminate-all-n} asks whether termination holds for all $n$. \section{Implementation} \label{sec:impl}