Files
math-research/papers/level_switching/experiments/d2_preprocessing.py
didericis 77093cb0b0 Extend Level Switching paper with d>=2 preprocessing analysis
Add 21-vertex and 24-vertex examples showing recursive lopsidedness
at d=2. Empirically confirm that the iterated algorithm (balanced
switch when available, preprocess otherwise) drives every face to
depth 0 on all tested configurations. Frame the remaining open
question as identifying a strictly-decreasing monovariant under
unbalanced preprocessing switches.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-20 23:20:06 -04:00

99 lines
3.1 KiB
Python

"""Apply preprocessing surface switches to the 21-vertex depth-2 example
and check whether the new depth-2 face admits a balanced surface switch.
If not, iterate."""
import sys, os
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
import math
import networkx as nx
from d2_balanced_existence import (
POS, n, OUTER_EDGES, outer_set, face_edges, compute_depths,
check_balanced, FACES as FACES0, CHORDS as CHORDS0
)
def apply_switch(faces, chords, uv, ux_vx):
"""Apply an edge switch removing edge uv and inserting edge wx.
`ux_vx` = (third-vertex-of-F = w, third-vertex-of-F' = x).
Returns (new_faces, new_chords).
Replaces the two old triangles uvw, uvx with the two new triangles
uwx, vwx.
"""
u, v = uv
w, x = ux_vx
new_chords = [c for c in chords if set(c) != {u, v}] + [tuple(sorted((w, x)))]
new_faces = []
for f in faces:
if set(f) == {u, v, w} or set(f) == {u, v, x}:
continue
new_faces.append(f)
new_faces.append(tuple(sorted((u, w, x))))
new_faces.append(tuple(sorted((v, w, x))))
return new_faces, new_chords
def find_third_vertices(faces, uv):
"""Find the two faces containing edge uv; return their third vertices."""
u, v = uv
thirds = []
for f in faces:
if u in f and v in f:
for vert in f:
if vert not in (u, v):
thirds.append(vert)
break
return thirds
def find_max_depth_face(faces, depth):
max_d = max(depth.values())
return [i for i, d in depth.items() if d == max_d][0], max_d
# Initial state
faces = list(FACES0)
chords = list(CHORDS0)
depth, _ = compute_depths(faces, outer_set)
F_idx, d = find_max_depth_face(faces, depth)
F = faces[F_idx]
print(f'Iter 0: F = {F}, depth = {d}')
for step in range(8):
ok, _, fp_idx, e = check_balanced(F_idx, faces, depth, outer_set)
if ok:
Fp = faces[fp_idx]
print(f' -> balanced switch exists on edge {tuple(e)}, F = {F}, '
f'F\' = {Fp}. STOP.')
break
# Pick any depth-(d-1) neighbour for preprocessing.
F_set = set(F)
fp_choice = None
for e_test in [frozenset((F[0], F[1])), frozenset((F[1], F[2])),
frozenset((F[0], F[2]))]:
if e_test in outer_set:
continue
cands = [j for j, fj in enumerate(faces)
if j != F_idx and e_test in face_edges(fj)]
if cands and depth[cands[0]] == d - 1:
fp_choice = (e_test, cands[0])
break
if fp_choice is None:
print(' no depth-(d-1) neighbour; cannot preprocess.')
break
e, fp_idx = fp_choice
Fp = faces[fp_idx]
u, v = tuple(e)
w = [vert for vert in F if vert != u and vert != v][0]
x = [vert for vert in Fp if vert != u and vert != v][0]
print(f' preprocessing switch: uv = ({u},{v}), w = {w}, x = {x}, '
f'F\' = {Fp}')
faces, chords = apply_switch(faces, chords, (u, v), (w, x))
depth, _ = compute_depths(faces, outer_set)
F_idx, d = find_max_depth_face(faces, depth)
F = faces[F_idx]
print(f'Iter {step + 1}: max-depth face = {F}, depth = {d}')
print('Done.')