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>
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
"""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.')
|
||||
Reference in New Issue
Block a user