Strategy A localization fails: local star-vs-fan domination is false
local_star_fan.py: the size step |Phi(D-v)| <= |Phi(D)| localizes to a star-vs-fan contribution comparison at v. But |Star(t)| >= min_root |Fan(t)| is FALSE (6586 violations) -- the star's extra v-constraint (sum mu ≡ 0) can make it realize fewer boundary vectors than the fan when the link has interior vertices. So Strategy A is globally true (100%) but NOT via per-vertex local domination; the size inequality needs a global union/choice-of-v argument. Useful byproduct: the Boolean-bit / mod-3 incidence reformulation of Phi. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,112 @@
|
|||||||
|
"""
|
||||||
|
Local heart of the size-reduction lemma.
|
||||||
|
|
||||||
|
Removing a degree-d interior vertex v swaps its star (d faces, contribution
|
||||||
|
mu_{j-1}+mu_j at link vertex u_j, plus the v-constraint sum mu ≡ 0) for a fan
|
||||||
|
(d-2 faces). Outside is shared, entering only as prescribed residues t_j at the
|
||||||
|
INTERIOR link vertices. The boundary-link contribution sets are
|
||||||
|
|
||||||
|
Star(t) = {(mu_{j-1}+mu_j)_{u_j boundary} : mu in {+-1}^d, sum mu ≡ 0,
|
||||||
|
mu_{j-1}+mu_j ≡ t_j for interior u_j}
|
||||||
|
Fan_r(t)= {(fan_j)_{u_j boundary} : nu in {+-1}^{d-2},
|
||||||
|
fan_j ≡ t_j for interior u_j}
|
||||||
|
(fan rooted at link vertex r; fan_j = contribution of the fan to u_j)
|
||||||
|
|
||||||
|
The reduction may CHOOSE the fan root, so it wants min_r |Fan_r(t)|. For the
|
||||||
|
induction |Phi(D-v)| <= |Phi(D)| to be locally supported we need, for every
|
||||||
|
interior-mask and every t:
|
||||||
|
|
||||||
|
|Star(t)| >= min_r |Fan_r(t)| (and Star(t) nonempty whenever some Fan is)
|
||||||
|
|
||||||
|
We check this exhaustively for small d. (+-1 encoded as 1,2 mod 3.)
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
from itertools import product
|
||||||
|
|
||||||
|
|
||||||
|
def star_contrib(d, interior, t):
|
||||||
|
"""interior: set of link indices that are interior; t: dict j->residue for
|
||||||
|
interior j. Returns set of boundary contribution tuples."""
|
||||||
|
bnd = [j for j in range(d) if j not in interior]
|
||||||
|
out = set()
|
||||||
|
for mu in product((1, 2), repeat=d): # +-1 as 1,2
|
||||||
|
if sum(mu) % 3 != 0: # v-constraint
|
||||||
|
continue
|
||||||
|
contrib = [(mu[(j - 1) % d] + mu[j]) % 3 for j in range(d)]
|
||||||
|
if any(contrib[j] != t[j] for j in interior):
|
||||||
|
continue
|
||||||
|
out.add(tuple(contrib[j] for j in bnd))
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def fan_contrib(d, root, interior, t):
|
||||||
|
"""Fan of the link d-gon rooted at vertex `root`. Reindex so root=0."""
|
||||||
|
bnd = [j for j in range(d) if j not in interior]
|
||||||
|
# contribution of a fan (root r) to vertex u_j, for nu over the d-2 fan faces.
|
||||||
|
# In root-0 coordinates faces are (0,j,j+1) for j=1..d-2 with labels nu[1..d-2].
|
||||||
|
# contribution: u0 -> sum(nu); u1 -> nu1; u_{d-1} -> nu_{d-2};
|
||||||
|
# u_j (1<j<d-1) -> nu_{j-1}+nu_j.
|
||||||
|
out = set()
|
||||||
|
for nu in product((1, 2), repeat=d - 2): # nu indexed 1..d-2 -> 0..d-3
|
||||||
|
nuf = {j: nu[j - 1] for j in range(1, d - 1)}
|
||||||
|
contrib = [0] * d
|
||||||
|
# in root coordinates u'_i = u_{(root+i) mod d}
|
||||||
|
c = [0] * d
|
||||||
|
c[0] = sum(nu) % 3
|
||||||
|
c[1] = nuf[1] % 3
|
||||||
|
c[d - 1] = nuf[d - 2] % 3
|
||||||
|
for j in range(2, d - 1):
|
||||||
|
c[j] = (nuf[j - 1] + nuf[j]) % 3
|
||||||
|
# map back: actual vertex = (root+i) mod d gets c[i]
|
||||||
|
for i in range(d):
|
||||||
|
contrib[(root + i) % d] = c[i]
|
||||||
|
if any(contrib[j] != t[j] for j in interior):
|
||||||
|
continue
|
||||||
|
out.add(tuple(contrib[j] for j in bnd))
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
print("Local claim: |Star(t)| >= min_root |Fan_root(t)| for all interior-masks, t\n")
|
||||||
|
fails = 0
|
||||||
|
checked = 0
|
||||||
|
worst = None
|
||||||
|
for d in range(3, 8):
|
||||||
|
for im in range(0, 1 << d):
|
||||||
|
interior = {j for j in range(d) if im >> j & 1}
|
||||||
|
if len(interior) == d:
|
||||||
|
continue # need a boundary vertex to see
|
||||||
|
int_list = sorted(interior)
|
||||||
|
for tvals in product((0, 1, 2), repeat=len(interior)):
|
||||||
|
t = dict(zip(int_list, tvals))
|
||||||
|
S = star_contrib(d, interior, t)
|
||||||
|
fans = [fan_contrib(d, r, interior, t) for r in range(d)]
|
||||||
|
# the reduction needs Star nonempty whenever it removes v; and
|
||||||
|
# it picks the fan, so compare to the SMALLEST fan that is itself
|
||||||
|
# achievable (nonempty) -- an empty fan means that root is invalid.
|
||||||
|
nonempty_fans = [len(f) for f in fans if f]
|
||||||
|
if not S:
|
||||||
|
# star infeasible: then v cannot carry this context. Only a
|
||||||
|
# problem if some fan IS feasible (then D-v has a seq D lacks).
|
||||||
|
if nonempty_fans:
|
||||||
|
fails += 1
|
||||||
|
continue
|
||||||
|
checked += 1
|
||||||
|
if nonempty_fans:
|
||||||
|
mn = min(nonempty_fans)
|
||||||
|
if len(S) < mn:
|
||||||
|
fails += 1
|
||||||
|
if worst is None or len(S) - mn < worst[0]:
|
||||||
|
worst = (len(S) - mn, d, sorted(interior), t,
|
||||||
|
len(S), mn)
|
||||||
|
print(f" configurations checked: {checked}")
|
||||||
|
print(f" violations of |Star| >= min nonempty |Fan|: {fails}")
|
||||||
|
if worst:
|
||||||
|
print(f" worst gap (|Star|-minFan, d, interior, t, |Star|, minFan): {worst}")
|
||||||
|
if fails == 0:
|
||||||
|
print(" => LOCAL CLAIM HOLDS: the star always dominates the best fan.")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Reference in New Issue
Block a user