Files
didericis bb144f069e Add bridge switch / bridge-derived level graph; set up exhaustive test
- Define bridge switch (E/O switch whose new same-parity edge is a bridge
  in its parity subgraph) and bridge-derived level graph in the paper.
  Note that bridge switches preserve bipartite parity subgraphs, so every
  bridge-derived level graph is automatically valid.
- Discover the E/O-switch relation is directed (irreversible when a switch
  produces a cross-parity edge); T*_9 reaches an ELG forward but no ELG
  reaches it, explaining why it is not derived. This rules out a simple
  switch-invariant characterization.
- Bridge orbits are far smaller than full E/O orbits (~10^4 vs ~10^8 for
  some labellings), making exhaustive search feasible. Each of the 4 open
  duals has ~150 valid parity partitions; exhaustive bridge-orbit search
  per partition can decide bridge-derivability conclusively.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 00:09:19 -04:00

144 lines
5.3 KiB
Python

"""Exhaustive bridge-derived test for the 4 open Holton-McKay duals.
Step A (gauge): for each dual, count the valid parity partitions
(bipartitions L with both parity subgraphs bipartite) and measure a few
bridge-orbit sizes run to FULL exhaustion (no timeout).
Step B (decide): for each dual, for every valid parity partition L,
exhaust the backward bridge-orbit and look for an ELG with BFS-parity L.
YES if found for any L; NO (conclusive) if none found for all L.
"""
import sys
import os
sys.path.insert(0, '/Users/didericis/Code/math-research/papers/'
'level_resolutions_of_maximal_planar_graphs/experiments')
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
import networkx as nx
import time
from load_holton_mckay import parse_planar_code
from tutte_dual_treecolor import dual_triangulation
from test_conjecture import is_even_level_graph
from bridge_derived_test import (
sig, parity_subgraph, edge_is_bridge_in_parity,
backward_bridge_neighbors,
)
def valid_parity_partitions(G):
"""Yield labels-dicts for every bipartition (fix node 0 in even class)
such that both induced parity subgraphs are bipartite. Labels are 0
(even) / 1 (odd)."""
nodes = sorted(G.nodes())
n = len(nodes)
assert nodes[0] == 0
for mask in range(2 ** (n - 1)):
labels = {0: 0}
for i in range(n - 1):
labels[nodes[i + 1]] = (mask >> i) & 1
even = [v for v in nodes if labels[v] == 0]
odd = [v for v in nodes if labels[v] == 1]
if not odd:
continue
if nx.is_bipartite(G.subgraph(even)) and nx.is_bipartite(G.subgraph(odd)):
yield labels
def is_elg_with_parity(H, labels):
"""Is H an Even Level Graph for some source whose BFS-parity matches
`labels` (up to global swap)? Only even-class vertices can be the
source (level 0 is even)."""
even = [v for v in H.nodes() if labels[v] == 0]
odd_set = set(v for v in H.nodes() if labels[v] == 1)
for s in even:
# quick reject: all neighbours of s must be odd-class (level 1)
if any(nb not in odd_set for nb in H.neighbors(s)):
# could still match under global swap; handle swap separately
pass
ok, lvls = is_even_level_graph(H, frozenset({s}))
if not ok:
continue
if all(lvls[u] % 2 == labels[u] for u in H.nodes()):
return True
# global swap: source in odd class, BFS-parity is complement of labels
odd = [v for v in H.nodes() if labels[v] == 1]
for s in odd:
ok, lvls = is_even_level_graph(H, frozenset({s}))
if not ok:
continue
if all(lvls[u] % 2 != labels[u] for u in H.nodes()):
return True
return False
def exhaust_bridge_orbit_for_elg(G, labels, cap=3_000_000):
"""Exhaust backward bridge-orbit (no ELG check during BFS), then scan
for an ELG witness. Returns ('found',H) / ('exhausted',size) /
('capped',size)."""
seen = {sig(G): G}
frontier = [G]
while frontier and len(seen) < cap:
new = []
for H in frontier:
for Hp in backward_bridge_neighbors(H, labels):
sg = sig(Hp)
if sg not in seen:
seen[sg] = Hp
new.append(Hp)
frontier = new
status = 'capped' if frontier else 'exhausted'
if status == 'exhausted':
for H in seen.values():
if is_elg_with_parity(H, labels):
return 'found', H
return status, len(seen)
def decide_dual(i, cap=3_000_000, log=print):
graphs = parse_planar_code('experiments/nonham38m4.pc')
G, _ = dual_triangulation(graphs[i][0])
parts = list(valid_parity_partitions(G))
log(f'dual {i}: {len(parts)} valid parity partitions')
any_capped = False
max_orbit = 0
t0 = time.time()
for j, labels in enumerate(parts):
st, info = exhaust_bridge_orbit_for_elg(G, labels, cap=cap)
if st == 'found':
log(f' partition {j}: FOUND ELG -> dual {i} IS bridge-derived '
f'({time.time()-t0:.0f}s)')
return 'bridge-derived'
if st == 'capped':
any_capped = True
log(f' partition {j}: orbit exceeded cap ({info}); inconclusive')
else:
max_orbit = max(max_orbit, info)
if (j + 1) % 25 == 0:
log(f' ...{j+1}/{len(parts)} partitions, max orbit {max_orbit}, '
f'{time.time()-t0:.0f}s')
if any_capped:
log(f' dual {i}: no witness, but some orbits hit cap -> INCONCLUSIVE '
f'({time.time()-t0:.0f}s)')
return 'inconclusive'
log(f' dual {i}: NOT bridge-derived (all {len(parts)} orbits exhausted, '
f'max orbit {max_orbit}, {time.time()-t0:.0f}s)')
return 'not-bridge-derived'
def gauge(dual_indices):
graphs = parse_planar_code('experiments/nonham38m4.pc')
for i in dual_indices:
G, _ = dual_triangulation(graphs[i][0])
t0 = time.time()
parts = list(valid_parity_partitions(G))
print(f'dual {i}: {len(parts)} valid parity partitions '
f'(enumerated in {time.time()-t0:.1f}s)')
if __name__ == '__main__':
import sys as _s
if len(_s.argv) > 1 and _s.argv[1] == 'gauge':
gauge([0, 3, 4, 5])
elif len(_s.argv) > 1:
for idx in _s.argv[1:]:
decide_dual(int(idx))