FA-88726 / Mesh topology invariants / Open access
Tetrahedral faces are matched by oriented tuple · case 01
Internal faces, which appear with opposite orientation, are never matched and all appear on the boundary.
ROOT CAUSE
The face key keeps the corner order instead of the vertex set.
VERIFIED REPAIR
Match faces by their sorted vertex tuple.
Unsuccessful approach: Keying by the smallest and largest vertex merges different faces sharing those two vertices.
Case contract
Input: tetrahedra [a,b,c,d] (positively oriented). A tet with repeated vertices returns ["degenerate", i]. Outward faces are (b,c,d),(a,d,c),(a,b,d),(a,c,b). Faces are matched by their vertex set; a set used once is boundary (kept with its first orientation, rotated to start at its smallest vertex); used more than twice returns ["non-manifold", sorted vertices]. Output boundary faces in increasing sorted-vertex-set order.
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):
tets=x
cnt={}
first={}
for i,t in enumerate(tets):
if len(set(t))<4: return ['degenerate',i]
a,b,c,d=t
for f in ((b,c,d),(a,d,c),(a,b,d),(a,c,b)):
k=f
cnt[k]=cnt.get(k,0)+1
if k not in first: first[k]=f
out=[]
for k in sorted(cnt):
if cnt[k]==1:
f=first[k]
m=f.index(min(f))
out.append(list(f[m:]+f[:m]))
elif cnt[k]>2: return ['non-manifold',list(k)]
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['single tet', [[[0, 1, 2, 3]]], [[0, 2, 1], [0, 1, 3], [0, 3, 2], [1, 2, 3]]], ['two tets sharing a face', [[[0, 1, 2, 3], [1, 0, 2, 4]]], [[0, 1, 3], [0, 4, 1], [0, 3, 2], [0, 2, 4], [1, 2, 3], [1, 4, 2]]], ['three tets around an edge', [[[0, 1, 2, 3], [0, 1, 3, 4], [0, 1, 4, 2]]], [[0, 3, 2], [0, 2, 4], [0, 4, 3], [1, 2, 3], [1, 4, 2], [1, 3, 4]]], ['fin face', [[[0, 1, 2, 3], [1, 0, 2, 4], [0, 1, 2, 5]]], ['non-manifold', [0, 1, 2]]], ['degenerate tet', [[[0, 1, 2, 3], [4, 5, 5, 6]]], ['degenerate', 1]], ['degenerate first pair', [[[2, 2, 3, 4]]], ['degenerate', 0]], ['degenerate late pair', [[[0, 1, 2, 2]]], ['degenerate', 0]]], [['two tets sharing a face', [[[0, 1, 2, 3], [1, 0, 2, 4]]], [[0, 1, 3], [0, 4, 1], [0, 3, 2], [0, 2, 4], [1, 2, 3], [1, 4, 2]]], ['degenerate tet', [[[0, 1, 2, 3], [4, 5, 5, 6]]], ['degenerate', 1]], ['degenerate first pair', [[[2, 2, 3, 4]]], ['degenerate', 0]], ['degenerate late pair', [[[0, 1, 2, 2]]], ['degenerate', 0]], ['rotated labels', [[[3, 1, 0, 2]]], [[0, 2, 1], [0, 1, 3], [0, 3, 2], [1, 2, 3]]], ['large labels', [[[10, 7, 9, 8], [7, 10, 9, 11]]], [[7, 9, 8], [7, 8, 10], [7, 11, 9], [7, 10, 11], [8, 9, 10], [9, 11, 10]]], ['two separate tets', [[[0, 1, 2, 3], [4, 5, 6, 7]]], [[0, 2, 1], [0, 1, 3], [0, 3, 2], [1, 2, 3], [4, 6, 5], [4, 5, 7], [4, 7, 6], [5, 6, 7]]]], [['single tet', [[[0, 1, 2, 3]]], [[0, 2, 1], [0, 1, 3], [0, 3, 2], [1, 2, 3]]], ['two tets sharing a face', [[[0, 1, 2, 3], [1, 0, 2, 4]]], [[0, 1, 3], [0, 4, 1], [0, 3, 2], [0, 2, 4], [1, 2, 3], [1, 4, 2]]], ['three tets around an edge', [[[0, 1, 2, 3], [0, 1, 3, 4], [0, 1, 4, 2]]], [[0, 3, 2], [0, 2, 4], [0, 4, 3], [1, 2, 3], [1, 4, 2], [1, 3, 4]]], ['fin face', [[[0, 1, 2, 3], [1, 0, 2, 4], [0, 1, 2, 5]]], ['non-manifold', [0, 1, 2]]], ['rotated labels', [[[3, 1, 0, 2]]], [[0, 2, 1], [0, 1, 3], [0, 3, 2], [1, 2, 3]]], ['large labels', [[[10, 7, 9, 8], [7, 10, 9, 11]]], [[7, 9, 8], [7, 8, 10], [7, 11, 9], [7, 10, 11], [8, 9, 10], [9, 11, 10]]], ['two separate tets', [[[0, 1, 2, 3], [4, 5, 6, 7]]], [[0, 2, 1], [0, 1, 3], [0, 3, 2], [1, 2, 3], [4, 6, 5], [4, 5, 7], [4, 7, 6], [5, 6, 7]]]], [['single tet', [[[0, 1, 2, 3]]], [[0, 2, 1], [0, 1, 3], [0, 3, 2], [1, 2, 3]]], ['two tets sharing a face', [[[0, 1, 2, 3], [1, 0, 2, 4]]], [[0, 1, 3], [0, 4, 1], [0, 3, 2], [0, 2, 4], [1, 2, 3], [1, 4, 2]]], ['three tets around an edge', [[[0, 1, 2, 3], [0, 1, 3, 4], [0, 1, 4, 2]]], [[0, 3, 2], [0, 2, 4], [0, 4, 3], [1, 2, 3], [1, 4, 2], [1, 3, 4]]], ['fin face', [[[0, 1, 2, 3], [1, 0, 2, 4], [0, 1, 2, 5]]], ['non-manifold', [0, 1, 2]]], ['degenerate tet', [[[0, 1, 2, 3], [4, 5, 5, 6]]], ['degenerate', 1]], ['degenerate first pair', [[[2, 2, 3, 4]]], ['degenerate', 0]], ['degenerate late pair', [[[0, 1, 2, 2]]], ['degenerate', 0]]], [['fin face', [[[0, 1, 2, 3], [1, 0, 2, 4], [0, 1, 2, 5]]], ['non-manifold', [0, 1, 2]]], ['degenerate tet', [[[0, 1, 2, 3], [4, 5, 5, 6]]], ['degenerate', 1]], ['degenerate first pair', [[[2, 2, 3, 4]]], ['degenerate', 0]], ['degenerate late pair', [[[0, 1, 2, 2]]], ['degenerate', 0]], ['rotated labels', [[[3, 1, 0, 2]]], [[0, 2, 1], [0, 1, 3], [0, 3, 2], [1, 2, 3]]], ['large labels', [[[10, 7, 9, 8], [7, 10, 9, 11]]], [[7, 9, 8], [7, 8, 10], [7, 11, 9], [7, 10, 11], [8, 9, 10], [9, 11, 10]]], ['two separate tets', [[[0, 1, 2, 3], [4, 5, 6, 7]]], [[0, 2, 1], [0, 1, 3], [0, 3, 2], [1, 2, 3], [4, 6, 5], [4, 5, 7], [4, 7, 6], [5, 6, 7]]]]]
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 |
|---|---|---|---|
| single tet | [[0, 1, 3], [0, 2, 1], [0, 3, 2], [1, 2, 3]] | [[0, 2, 1], [0, 1, 3], [0, 3, 2], [1, 2, 3]] | Failed |
| two tets sharing a face | [[0, 1, 3], [0, 2, 1], [0, 2, 4], [0, 3, 2], [0, 4, 1], [0, 1, 2], [1, 2, 3], [1, 4, 2]] | [[0, 1, 3], [0, 4, 1], [0, 3, 2], [0, 2, 4], [1, 2, 3], [1, 4, 2]] | Failed |
| three tets around an edge | [[0, 1, 2], [0, 1, 3], [0, 1, 4], [0, 2, 1], [0, 2, 4], [0, 3, 1], [0, 3, 2], [0, 4, 1], [0, 4, 3], [1, 2, 3], [1, 3, 4], [1, 4, 2]] | [[0, 3, 2], [0, 2, 4], [0, 4, 3], [1, 2, 3], [1, 4, 2], [1, 3, 4]] | Failed |
| fin face | [[0, 1, 3], [0, 1, 5], [0, 2, 4], [0, 3, 2], [0, 5, 2], [0, 4, 1], [0, 1, 2], [1, 2, 3], [1, 2, 5], [1, 4, 2]] | ['non-manifold', [0, 1, 2]] | Failed |
| degenerate tet | ['degenerate', 1] | ['degenerate', 1] | Passed |
| degenerate first pair | ['degenerate', 0] | ['degenerate', 0] | Passed |
| degenerate late pair | ['degenerate', 0] | ['degenerate', 0] | Passed |
SHA-256 / 63092c405fc6a1ceac0e49f3f5f1afcb8d3c61b852a2039406443b8851ab2154
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
tets=x
cnt={}
first={}
for i,t in enumerate(tets):
if len(set(t))<4: return ['degenerate',i]
a,b,c,d=t
for f in ((b,c,d),(a,d,c),(a,b,d),(a,c,b)):
k=(min(f),max(f))
cnt[k]=cnt.get(k,0)+1
if k not in first: first[k]=f
out=[]
for k in sorted(cnt):
if cnt[k]==1:
f=first[k]
m=f.index(min(f))
out.append(list(f[m:]+f[:m]))
elif cnt[k]>2: return ['non-manifold',list(k)]
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['single tet', [[[0, 1, 2, 3]]], [[0, 2, 1], [0, 1, 3], [0, 3, 2], [1, 2, 3]]], ['two tets sharing a face', [[[0, 1, 2, 3], [1, 0, 2, 4]]], [[0, 1, 3], [0, 4, 1], [0, 3, 2], [0, 2, 4], [1, 2, 3], [1, 4, 2]]], ['three tets around an edge', [[[0, 1, 2, 3], [0, 1, 3, 4], [0, 1, 4, 2]]], [[0, 3, 2], [0, 2, 4], [0, 4, 3], [1, 2, 3], [1, 4, 2], [1, 3, 4]]], ['fin face', [[[0, 1, 2, 3], [1, 0, 2, 4], [0, 1, 2, 5]]], ['non-manifold', [0, 1, 2]]], ['degenerate tet', [[[0, 1, 2, 3], [4, 5, 5, 6]]], ['degenerate', 1]], ['degenerate first pair', [[[2, 2, 3, 4]]], ['degenerate', 0]], ['degenerate late pair', [[[0, 1, 2, 2]]], ['degenerate', 0]]], [['two tets sharing a face', [[[0, 1, 2, 3], [1, 0, 2, 4]]], [[0, 1, 3], [0, 4, 1], [0, 3, 2], [0, 2, 4], [1, 2, 3], [1, 4, 2]]], ['degenerate tet', [[[0, 1, 2, 3], [4, 5, 5, 6]]], ['degenerate', 1]], ['degenerate first pair', [[[2, 2, 3, 4]]], ['degenerate', 0]], ['degenerate late pair', [[[0, 1, 2, 2]]], ['degenerate', 0]], ['rotated labels', [[[3, 1, 0, 2]]], [[0, 2, 1], [0, 1, 3], [0, 3, 2], [1, 2, 3]]], ['large labels', [[[10, 7, 9, 8], [7, 10, 9, 11]]], [[7, 9, 8], [7, 8, 10], [7, 11, 9], [7, 10, 11], [8, 9, 10], [9, 11, 10]]], ['two separate tets', [[[0, 1, 2, 3], [4, 5, 6, 7]]], [[0, 2, 1], [0, 1, 3], [0, 3, 2], [1, 2, 3], [4, 6, 5], [4, 5, 7], [4, 7, 6], [5, 6, 7]]]], [['single tet', [[[0, 1, 2, 3]]], [[0, 2, 1], [0, 1, 3], [0, 3, 2], [1, 2, 3]]], ['two tets sharing a face', [[[0, 1, 2, 3], [1, 0, 2, 4]]], [[0, 1, 3], [0, 4, 1], [0, 3, 2], [0, 2, 4], [1, 2, 3], [1, 4, 2]]], ['three tets around an edge', [[[0, 1, 2, 3], [0, 1, 3, 4], [0, 1, 4, 2]]], [[0, 3, 2], [0, 2, 4], [0, 4, 3], [1, 2, 3], [1, 4, 2], [1, 3, 4]]], ['fin face', [[[0, 1, 2, 3], [1, 0, 2, 4], [0, 1, 2, 5]]], ['non-manifold', [0, 1, 2]]], ['rotated labels', [[[3, 1, 0, 2]]], [[0, 2, 1], [0, 1, 3], [0, 3, 2], [1, 2, 3]]], ['large labels', [[[10, 7, 9, 8], [7, 10, 9, 11]]], [[7, 9, 8], [7, 8, 10], [7, 11, 9], [7, 10, 11], [8, 9, 10], [9, 11, 10]]], ['two separate tets', [[[0, 1, 2, 3], [4, 5, 6, 7]]], [[0, 2, 1], [0, 1, 3], [0, 3, 2], [1, 2, 3], [4, 6, 5], [4, 5, 7], [4, 7, 6], [5, 6, 7]]]], [['single tet', [[[0, 1, 2, 3]]], [[0, 2, 1], [0, 1, 3], [0, 3, 2], [1, 2, 3]]], ['two tets sharing a face', [[[0, 1, 2, 3], [1, 0, 2, 4]]], [[0, 1, 3], [0, 4, 1], [0, 3, 2], [0, 2, 4], [1, 2, 3], [1, 4, 2]]], ['three tets around an edge', [[[0, 1, 2, 3], [0, 1, 3, 4], [0, 1, 4, 2]]], [[0, 3, 2], [0, 2, 4], [0, 4, 3], [1, 2, 3], [1, 4, 2], [1, 3, 4]]], ['fin face', [[[0, 1, 2, 3], [1, 0, 2, 4], [0, 1, 2, 5]]], ['non-manifold', [0, 1, 2]]], ['degenerate tet', [[[0, 1, 2, 3], [4, 5, 5, 6]]], ['degenerate', 1]], ['degenerate first pair', [[[2, 2, 3, 4]]], ['degenerate', 0]], ['degenerate late pair', [[[0, 1, 2, 2]]], ['degenerate', 0]]], [['fin face', [[[0, 1, 2, 3], [1, 0, 2, 4], [0, 1, 2, 5]]], ['non-manifold', [0, 1, 2]]], ['degenerate tet', [[[0, 1, 2, 3], [4, 5, 5, 6]]], ['degenerate', 1]], ['degenerate first pair', [[[2, 2, 3, 4]]], ['degenerate', 0]], ['degenerate late pair', [[[0, 1, 2, 2]]], ['degenerate', 0]], ['rotated labels', [[[3, 1, 0, 2]]], [[0, 2, 1], [0, 1, 3], [0, 3, 2], [1, 2, 3]]], ['large labels', [[[10, 7, 9, 8], [7, 10, 9, 11]]], [[7, 9, 8], [7, 8, 10], [7, 11, 9], [7, 10, 11], [8, 9, 10], [9, 11, 10]]], ['two separate tets', [[[0, 1, 2, 3], [4, 5, 6, 7]]], [[0, 2, 1], [0, 1, 3], [0, 3, 2], [1, 2, 3], [4, 6, 5], [4, 5, 7], [4, 7, 6], [5, 6, 7]]]]]
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 |
|---|---|---|---|
| single tet | [[0, 2, 1], [1, 2, 3]] | [[0, 2, 1], [0, 1, 3], [0, 3, 2], [1, 2, 3]] | Failed |
| two tets sharing a face | [[1, 2, 3], [1, 4, 2]] | [[0, 1, 3], [0, 4, 1], [0, 3, 2], [0, 2, 4], [1, 2, 3], [1, 4, 2]] | Failed |
| three tets around an edge | ['non-manifold', [0, 3]] | [[0, 3, 2], [0, 2, 4], [0, 4, 3], [1, 2, 3], [1, 4, 2], [1, 3, 4]] | Failed |
| fin face | ['non-manifold', [0, 2]] | ['non-manifold', [0, 1, 2]] | Failed |
| degenerate tet | ['degenerate', 1] | ['degenerate', 1] | Passed |
| degenerate first pair | ['degenerate', 0] | ['degenerate', 0] | Passed |
| degenerate late pair | ['degenerate', 0] | ['degenerate', 0] | Passed |
SHA-256 / 2cacf2ca5390f2adf7b061e3d792af601a533a8b38d538bdab137b756a193387
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
tets=x
cnt={}
first={}
for i,t in enumerate(tets):
if len(set(t))<4: return ['degenerate',i]
a,b,c,d=t
for f in ((b,c,d),(a,d,c),(a,b,d),(a,c,b)):
k=tuple(sorted(f))
cnt[k]=cnt.get(k,0)+1
if k not in first: first[k]=f
out=[]
for k in sorted(cnt):
if cnt[k]==1:
f=first[k]
m=f.index(min(f))
out.append(list(f[m:]+f[:m]))
elif cnt[k]>2: return ['non-manifold',list(k)]
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['single tet', [[[0, 1, 2, 3]]], [[0, 2, 1], [0, 1, 3], [0, 3, 2], [1, 2, 3]]], ['two tets sharing a face', [[[0, 1, 2, 3], [1, 0, 2, 4]]], [[0, 1, 3], [0, 4, 1], [0, 3, 2], [0, 2, 4], [1, 2, 3], [1, 4, 2]]], ['three tets around an edge', [[[0, 1, 2, 3], [0, 1, 3, 4], [0, 1, 4, 2]]], [[0, 3, 2], [0, 2, 4], [0, 4, 3], [1, 2, 3], [1, 4, 2], [1, 3, 4]]], ['fin face', [[[0, 1, 2, 3], [1, 0, 2, 4], [0, 1, 2, 5]]], ['non-manifold', [0, 1, 2]]], ['degenerate tet', [[[0, 1, 2, 3], [4, 5, 5, 6]]], ['degenerate', 1]], ['degenerate first pair', [[[2, 2, 3, 4]]], ['degenerate', 0]], ['degenerate late pair', [[[0, 1, 2, 2]]], ['degenerate', 0]]], [['two tets sharing a face', [[[0, 1, 2, 3], [1, 0, 2, 4]]], [[0, 1, 3], [0, 4, 1], [0, 3, 2], [0, 2, 4], [1, 2, 3], [1, 4, 2]]], ['degenerate tet', [[[0, 1, 2, 3], [4, 5, 5, 6]]], ['degenerate', 1]], ['degenerate first pair', [[[2, 2, 3, 4]]], ['degenerate', 0]], ['degenerate late pair', [[[0, 1, 2, 2]]], ['degenerate', 0]], ['rotated labels', [[[3, 1, 0, 2]]], [[0, 2, 1], [0, 1, 3], [0, 3, 2], [1, 2, 3]]], ['large labels', [[[10, 7, 9, 8], [7, 10, 9, 11]]], [[7, 9, 8], [7, 8, 10], [7, 11, 9], [7, 10, 11], [8, 9, 10], [9, 11, 10]]], ['two separate tets', [[[0, 1, 2, 3], [4, 5, 6, 7]]], [[0, 2, 1], [0, 1, 3], [0, 3, 2], [1, 2, 3], [4, 6, 5], [4, 5, 7], [4, 7, 6], [5, 6, 7]]]], [['single tet', [[[0, 1, 2, 3]]], [[0, 2, 1], [0, 1, 3], [0, 3, 2], [1, 2, 3]]], ['two tets sharing a face', [[[0, 1, 2, 3], [1, 0, 2, 4]]], [[0, 1, 3], [0, 4, 1], [0, 3, 2], [0, 2, 4], [1, 2, 3], [1, 4, 2]]], ['three tets around an edge', [[[0, 1, 2, 3], [0, 1, 3, 4], [0, 1, 4, 2]]], [[0, 3, 2], [0, 2, 4], [0, 4, 3], [1, 2, 3], [1, 4, 2], [1, 3, 4]]], ['fin face', [[[0, 1, 2, 3], [1, 0, 2, 4], [0, 1, 2, 5]]], ['non-manifold', [0, 1, 2]]], ['rotated labels', [[[3, 1, 0, 2]]], [[0, 2, 1], [0, 1, 3], [0, 3, 2], [1, 2, 3]]], ['large labels', [[[10, 7, 9, 8], [7, 10, 9, 11]]], [[7, 9, 8], [7, 8, 10], [7, 11, 9], [7, 10, 11], [8, 9, 10], [9, 11, 10]]], ['two separate tets', [[[0, 1, 2, 3], [4, 5, 6, 7]]], [[0, 2, 1], [0, 1, 3], [0, 3, 2], [1, 2, 3], [4, 6, 5], [4, 5, 7], [4, 7, 6], [5, 6, 7]]]], [['single tet', [[[0, 1, 2, 3]]], [[0, 2, 1], [0, 1, 3], [0, 3, 2], [1, 2, 3]]], ['two tets sharing a face', [[[0, 1, 2, 3], [1, 0, 2, 4]]], [[0, 1, 3], [0, 4, 1], [0, 3, 2], [0, 2, 4], [1, 2, 3], [1, 4, 2]]], ['three tets around an edge', [[[0, 1, 2, 3], [0, 1, 3, 4], [0, 1, 4, 2]]], [[0, 3, 2], [0, 2, 4], [0, 4, 3], [1, 2, 3], [1, 4, 2], [1, 3, 4]]], ['fin face', [[[0, 1, 2, 3], [1, 0, 2, 4], [0, 1, 2, 5]]], ['non-manifold', [0, 1, 2]]], ['degenerate tet', [[[0, 1, 2, 3], [4, 5, 5, 6]]], ['degenerate', 1]], ['degenerate first pair', [[[2, 2, 3, 4]]], ['degenerate', 0]], ['degenerate late pair', [[[0, 1, 2, 2]]], ['degenerate', 0]]], [['fin face', [[[0, 1, 2, 3], [1, 0, 2, 4], [0, 1, 2, 5]]], ['non-manifold', [0, 1, 2]]], ['degenerate tet', [[[0, 1, 2, 3], [4, 5, 5, 6]]], ['degenerate', 1]], ['degenerate first pair', [[[2, 2, 3, 4]]], ['degenerate', 0]], ['degenerate late pair', [[[0, 1, 2, 2]]], ['degenerate', 0]], ['rotated labels', [[[3, 1, 0, 2]]], [[0, 2, 1], [0, 1, 3], [0, 3, 2], [1, 2, 3]]], ['large labels', [[[10, 7, 9, 8], [7, 10, 9, 11]]], [[7, 9, 8], [7, 8, 10], [7, 11, 9], [7, 10, 11], [8, 9, 10], [9, 11, 10]]], ['two separate tets', [[[0, 1, 2, 3], [4, 5, 6, 7]]], [[0, 2, 1], [0, 1, 3], [0, 3, 2], [1, 2, 3], [4, 6, 5], [4, 5, 7], [4, 7, 6], [5, 6, 7]]]]]
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 |
|---|---|---|---|
| single tet | [[0, 2, 1], [0, 1, 3], [0, 3, 2], [1, 2, 3]] | [[0, 2, 1], [0, 1, 3], [0, 3, 2], [1, 2, 3]] | Passed |
| two tets sharing a face | [[0, 1, 3], [0, 4, 1], [0, 3, 2], [0, 2, 4], [1, 2, 3], [1, 4, 2]] | [[0, 1, 3], [0, 4, 1], [0, 3, 2], [0, 2, 4], [1, 2, 3], [1, 4, 2]] | Passed |
| three tets around an edge | [[0, 3, 2], [0, 2, 4], [0, 4, 3], [1, 2, 3], [1, 4, 2], [1, 3, 4]] | [[0, 3, 2], [0, 2, 4], [0, 4, 3], [1, 2, 3], [1, 4, 2], [1, 3, 4]] | Passed |
| fin face | ['non-manifold', [0, 1, 2]] | ['non-manifold', [0, 1, 2]] | Passed |
| degenerate tet | ['degenerate', 1] | ['degenerate', 1] | Passed |
| degenerate first pair | ['degenerate', 0] | ['degenerate', 0] | Passed |
| degenerate late pair | ['degenerate', 0] | ['degenerate', 0] | Passed |
SHA-256 / d772c93affff9a14187d6ffb55646611e7e5c40094b65c4556ed144bebaeadb9
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:10.770740+00:00.
Case digest / 388f0767aebe1d6dc84495710b02c53481c2ccfa975e685e8778b489bd4f7d41