FA-88381 / Mesh topology invariants / Open access
Repeated consecutive indices create a self-loop edge · case 01
Faces with a duplicated corner add a phantom boundary edge.
ROOT CAUSE
The pair (a,a) is recorded as an edge instead of being skipped.
THE FAILURE
The pair (a,a) is recorded as an edge instead of being skipped.
Unsuccessful approach: Dropping the whole face loses its genuine edges too.
Case contract
Input: polygon faces. Empty input returns "empty". Consecutive repeated indices form no edge (skip that pair only). Undirected edges used once are boundary, twice interior, more non-manifold; an interior edge whose two uses have the same direction is inconsistent. Verdict precedence: non-manifold, then "non-orientable-or-inconsistent", then "open-oriented" (boundary present), else "closed-oriented". Return [boundary, interior, nonmanifold, inconsistent, verdict].
Why this case matters
Mesh processing pipelines (remeshing, export, simulation, printing) trust these topological counts and adjacency answers; a wrong invariant silently accepts broken meshes or rejects valid ones.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
faces=x
if not faces: return 'empty'
uses={}
for f in faces:
n=len(f)
for i in range(n):
a,b=f[i],f[(i+1)%n]
uses.setdefault((min(a,b),max(a,b)),[]).append((a,b))
bd=it=nm=inc=0
for k in sorted(uses):
u=uses[k]
if len(u)==1: bd+=1
elif len(u)==2:
it+=1
if u[0]==u[1]: inc+=1
else: nm+=1
if nm: v='non-manifold'
elif inc: v='non-orientable-or-inconsistent'
elif bd: v='open-oriented'
else: v='closed-oriented'
return [bd,it,nm,inc,v]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['tetrahedron', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]]], [0, 6, 0, 0, 'closed-oriented']], ['cube', [[[0, 3, 2, 1], [4, 5, 6, 7], [0, 1, 5, 4], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [0, 12, 0, 0, 'closed-oriented']], ['disk', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1]]], [5, 5, 0, 0, 'open-oriented']], ['mobius', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 0, 3]]], [6, 3, 0, 1, 'non-orientable-or-inconsistent']], ['book', [[[0, 1, 2], [1, 0, 3], [0, 1, 4]]], [6, 0, 1, 0, 'non-manifold']], ['flipped pair', [[[0, 1, 2], [0, 1, 3]]], [4, 1, 0, 1, 'non-orientable-or-inconsistent']], ['repeated corner', [[[0, 1, 1, 2], [2, 1, 3]]], [4, 1, 0, 0, 'open-oriented']]], [['mobius', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 0, 3]]], [6, 3, 0, 1, 'non-orientable-or-inconsistent']], ['book', [[[0, 1, 2], [1, 0, 3], [0, 1, 4]]], [6, 0, 1, 0, 'non-manifold']], ['flipped pair', [[[0, 1, 2], [0, 1, 3]]], [4, 1, 0, 1, 'non-orientable-or-inconsistent']], ['bowtie', [[[0, 1, 2], [0, 3, 4]]], [6, 0, 0, 0, 'open-oriented']], ['empty', [[]], 'empty'], ['repeated corner', [[[0, 1, 1, 2], [2, 1, 3]]], [4, 1, 0, 0, 'open-oriented']], ['repeated corner closed', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 3, 2]]], [0, 6, 0, 0, 'closed-oriented']]], [['bowtie', [[[0, 1, 2], [0, 3, 4]]], [6, 0, 0, 0, 'open-oriented']], ['empty', [[]], 'empty'], ['repeated corner', [[[0, 1, 1, 2], [2, 1, 3]]], [4, 1, 0, 0, 'open-oriented']], ['book and flipped pair', [[[0, 1, 2], [1, 0, 3], [0, 1, 4], [5, 6, 7], [5, 6, 8]]], [10, 1, 1, 1, 'non-manifold']], ['four sheets', [[[0, 1, 2], [1, 0, 3], [0, 1, 4], [1, 0, 5]]], [8, 0, 1, 0, 'non-manifold']], ['torus', [[[0, 3, 4], [0, 4, 1], [1, 4, 5], [1, 5, 2], [2, 5, 3], [2, 3, 0], [3, 6, 7], [3, 7, 4], [4, 7, 8], [4, 8, 5], [5, 8, 6], [5, 6, 3], [6, 0, 1], [6, 1, 7], [7, 1, 2], [7, 2, 8], [8, 2, 0], [8, 0, 6]]], [0, 27, 0, 0, 'closed-oriented']], ['projective plane', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [1, 2, 4], [2, 3, 5], [3, 4, 1], [4, 5, 2], [5, 1, 3]]], [0, 15, 0, 10, 'non-orientable-or-inconsistent']]], [['tetrahedron', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]]], [0, 6, 0, 0, 'closed-oriented']], ['cube', [[[0, 3, 2, 1], [4, 5, 6, 7], [0, 1, 5, 4], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [0, 12, 0, 0, 'closed-oriented']], ['book and flipped pair', [[[0, 1, 2], [1, 0, 3], [0, 1, 4], [5, 6, 7], [5, 6, 8]]], [10, 1, 1, 1, 'non-manifold']], ['four sheets', [[[0, 1, 2], [1, 0, 3], [0, 1, 4], [1, 0, 5]]], [8, 0, 1, 0, 'non-manifold']], ['torus', [[[0, 3, 4], [0, 4, 1], [1, 4, 5], [1, 5, 2], [2, 5, 3], [2, 3, 0], [3, 6, 7], [3, 7, 4], [4, 7, 8], [4, 8, 5], [5, 8, 6], [5, 6, 3], [6, 0, 1], [6, 1, 7], [7, 1, 2], [7, 2, 8], [8, 2, 0], [8, 0, 6]]], [0, 27, 0, 0, 'closed-oriented']], ['projective plane', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [1, 2, 4], [2, 3, 5], [3, 4, 1], [4, 5, 2], [5, 1, 3]]], [0, 15, 0, 10, 'non-orientable-or-inconsistent']], ['repeated corner closed', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 3, 2]]], [0, 6, 0, 0, 'closed-oriented']]], [['tetrahedron', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]]], [0, 6, 0, 0, 'closed-oriented']], ['cube', [[[0, 3, 2, 1], [4, 5, 6, 7], [0, 1, 5, 4], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [0, 12, 0, 0, 'closed-oriented']], ['disk', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1]]], [5, 5, 0, 0, 'open-oriented']], ['mobius', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 0, 3]]], [6, 3, 0, 1, 'non-orientable-or-inconsistent']], ['book', [[[0, 1, 2], [1, 0, 3], [0, 1, 4]]], [6, 0, 1, 0, 'non-manifold']], ['repeated corner', [[[0, 1, 1, 2], [2, 1, 3]]], [4, 1, 0, 0, 'open-oriented']], ['repeated corner closed', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 3, 2]]], [0, 6, 0, 0, 'closed-oriented']]]]
for label, args, expected in fixtures[N-1]:
check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| tetrahedron | [0, 6, 0, 0, 'closed-oriented'] | [0, 6, 0, 0, 'closed-oriented'] | Passed |
| cube | [0, 12, 0, 0, 'closed-oriented'] | [0, 12, 0, 0, 'closed-oriented'] | Passed |
| disk | [5, 5, 0, 0, 'open-oriented'] | [5, 5, 0, 0, 'open-oriented'] | Passed |
| mobius | [6, 3, 0, 1, 'non-orientable-or-inconsistent'] | [6, 3, 0, 1, 'non-orientable-or-inconsistent'] | Passed |
| book | [6, 0, 1, 0, 'non-manifold'] | [6, 0, 1, 0, 'non-manifold'] | Passed |
| flipped pair | [4, 1, 0, 1, 'non-orientable-or-inconsistent'] | [4, 1, 0, 1, 'non-orientable-or-inconsistent'] | Passed |
| repeated corner | [5, 1, 0, 0, 'open-oriented'] | [4, 1, 0, 0, 'open-oriented'] | Failed |
SHA-256 / f6b79af277fe55c0377d51398aa83b8dd821489b6b4906bfffc2c1ffaa0ad6b5
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
faces=x
if not faces: return 'empty'
uses={}
for f in faces:
n=len(f)
if len(set(f))<n: continue
for i in range(n):
a,b=f[i],f[(i+1)%n]
uses.setdefault((min(a,b),max(a,b)),[]).append((a,b))
bd=it=nm=inc=0
for k in sorted(uses):
u=uses[k]
if len(u)==1: bd+=1
elif len(u)==2:
it+=1
if u[0]==u[1]: inc+=1
else: nm+=1
if nm: v='non-manifold'
elif inc: v='non-orientable-or-inconsistent'
elif bd: v='open-oriented'
else: v='closed-oriented'
return [bd,it,nm,inc,v]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['tetrahedron', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]]], [0, 6, 0, 0, 'closed-oriented']], ['cube', [[[0, 3, 2, 1], [4, 5, 6, 7], [0, 1, 5, 4], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [0, 12, 0, 0, 'closed-oriented']], ['disk', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1]]], [5, 5, 0, 0, 'open-oriented']], ['mobius', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 0, 3]]], [6, 3, 0, 1, 'non-orientable-or-inconsistent']], ['book', [[[0, 1, 2], [1, 0, 3], [0, 1, 4]]], [6, 0, 1, 0, 'non-manifold']], ['flipped pair', [[[0, 1, 2], [0, 1, 3]]], [4, 1, 0, 1, 'non-orientable-or-inconsistent']], ['repeated corner', [[[0, 1, 1, 2], [2, 1, 3]]], [4, 1, 0, 0, 'open-oriented']]], [['mobius', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 0, 3]]], [6, 3, 0, 1, 'non-orientable-or-inconsistent']], ['book', [[[0, 1, 2], [1, 0, 3], [0, 1, 4]]], [6, 0, 1, 0, 'non-manifold']], ['flipped pair', [[[0, 1, 2], [0, 1, 3]]], [4, 1, 0, 1, 'non-orientable-or-inconsistent']], ['bowtie', [[[0, 1, 2], [0, 3, 4]]], [6, 0, 0, 0, 'open-oriented']], ['empty', [[]], 'empty'], ['repeated corner', [[[0, 1, 1, 2], [2, 1, 3]]], [4, 1, 0, 0, 'open-oriented']], ['repeated corner closed', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 3, 2]]], [0, 6, 0, 0, 'closed-oriented']]], [['bowtie', [[[0, 1, 2], [0, 3, 4]]], [6, 0, 0, 0, 'open-oriented']], ['empty', [[]], 'empty'], ['repeated corner', [[[0, 1, 1, 2], [2, 1, 3]]], [4, 1, 0, 0, 'open-oriented']], ['book and flipped pair', [[[0, 1, 2], [1, 0, 3], [0, 1, 4], [5, 6, 7], [5, 6, 8]]], [10, 1, 1, 1, 'non-manifold']], ['four sheets', [[[0, 1, 2], [1, 0, 3], [0, 1, 4], [1, 0, 5]]], [8, 0, 1, 0, 'non-manifold']], ['torus', [[[0, 3, 4], [0, 4, 1], [1, 4, 5], [1, 5, 2], [2, 5, 3], [2, 3, 0], [3, 6, 7], [3, 7, 4], [4, 7, 8], [4, 8, 5], [5, 8, 6], [5, 6, 3], [6, 0, 1], [6, 1, 7], [7, 1, 2], [7, 2, 8], [8, 2, 0], [8, 0, 6]]], [0, 27, 0, 0, 'closed-oriented']], ['projective plane', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [1, 2, 4], [2, 3, 5], [3, 4, 1], [4, 5, 2], [5, 1, 3]]], [0, 15, 0, 10, 'non-orientable-or-inconsistent']]], [['tetrahedron', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]]], [0, 6, 0, 0, 'closed-oriented']], ['cube', [[[0, 3, 2, 1], [4, 5, 6, 7], [0, 1, 5, 4], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [0, 12, 0, 0, 'closed-oriented']], ['book and flipped pair', [[[0, 1, 2], [1, 0, 3], [0, 1, 4], [5, 6, 7], [5, 6, 8]]], [10, 1, 1, 1, 'non-manifold']], ['four sheets', [[[0, 1, 2], [1, 0, 3], [0, 1, 4], [1, 0, 5]]], [8, 0, 1, 0, 'non-manifold']], ['torus', [[[0, 3, 4], [0, 4, 1], [1, 4, 5], [1, 5, 2], [2, 5, 3], [2, 3, 0], [3, 6, 7], [3, 7, 4], [4, 7, 8], [4, 8, 5], [5, 8, 6], [5, 6, 3], [6, 0, 1], [6, 1, 7], [7, 1, 2], [7, 2, 8], [8, 2, 0], [8, 0, 6]]], [0, 27, 0, 0, 'closed-oriented']], ['projective plane', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [1, 2, 4], [2, 3, 5], [3, 4, 1], [4, 5, 2], [5, 1, 3]]], [0, 15, 0, 10, 'non-orientable-or-inconsistent']], ['repeated corner closed', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 3, 2]]], [0, 6, 0, 0, 'closed-oriented']]], [['tetrahedron', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]]], [0, 6, 0, 0, 'closed-oriented']], ['cube', [[[0, 3, 2, 1], [4, 5, 6, 7], [0, 1, 5, 4], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [0, 12, 0, 0, 'closed-oriented']], ['disk', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1]]], [5, 5, 0, 0, 'open-oriented']], ['mobius', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 0, 3]]], [6, 3, 0, 1, 'non-orientable-or-inconsistent']], ['book', [[[0, 1, 2], [1, 0, 3], [0, 1, 4]]], [6, 0, 1, 0, 'non-manifold']], ['repeated corner', [[[0, 1, 1, 2], [2, 1, 3]]], [4, 1, 0, 0, 'open-oriented']], ['repeated corner closed', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 3, 2]]], [0, 6, 0, 0, 'closed-oriented']]]]
for label, args, expected in fixtures[N-1]:
check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| tetrahedron | [0, 6, 0, 0, 'closed-oriented'] | [0, 6, 0, 0, 'closed-oriented'] | Passed |
| cube | [0, 12, 0, 0, 'closed-oriented'] | [0, 12, 0, 0, 'closed-oriented'] | Passed |
| disk | [5, 5, 0, 0, 'open-oriented'] | [5, 5, 0, 0, 'open-oriented'] | Passed |
| mobius | [6, 3, 0, 1, 'non-orientable-or-inconsistent'] | [6, 3, 0, 1, 'non-orientable-or-inconsistent'] | Passed |
| book | [6, 0, 1, 0, 'non-manifold'] | [6, 0, 1, 0, 'non-manifold'] | Passed |
| flipped pair | [4, 1, 0, 1, 'non-orientable-or-inconsistent'] | [4, 1, 0, 1, 'non-orientable-or-inconsistent'] | Passed |
| repeated corner | [3, 0, 0, 0, 'open-oriented'] | [4, 1, 0, 0, 'open-oriented'] | Failed |
SHA-256 / 187b6bd20814ab339243620ad6b2cc32b7bbdfecd61b92442db8f7872598c5df
HELD IN THE MEMBER ARCHIVE
The verified repair and its recorded checks are member-only.
This mechanism has 7 recorded checks per implementation. The open-access tier publishes the failure and the unsuccessful fix; the repaired source that passes every check, and the observations that prove it, are available to members.
Every case sharing this mechanism uses the same contract and the same repair, so this one record is held back for all of them.
Member access is invitation-based. Sign in with your invited account to inspect the repair.
Sign in to the archive ↗Verification & scope
Pure combinatorial teaching model over integer face lists with a stipulated contract; no geometry kernel or file format is implied. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.
Observations recorded using Python 3.12.14 at 2026-09-29T14:51:07.649145+00:00.
Case digest / 927d89f403f374e240192ca7a7fa19c6c93086742934fa48afb4dcca6e52d2b2