FA-88531 / Mesh topology invariants / Open access
Loop subdivision accepts polygon faces · case 01
Quads are counted as if they were triangles.
ROOT CAUSE
The triangle-only precondition is missing.
THE FAILURE
The triangle-only precondition is missing.
Unsuccessful approach: Checking only the first face misses later polygons.
Case contract
Input [V,E,arities,B,scheme,levels]: counts of a mesh with face sizes "arities" and B boundary edges. Loop (triangles only, else "non-triangle"): V+=E, E=2E+3F, F=4F. Catmull-Clark: V=V+E+F, E=2E+sum(arities), faces become sum(arities) quads. Boundary edges double per level. Return [V,E,F,B,V-E+F] after the given levels.
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):
V,E,ar,B,scheme,levels=x
ar=list(ar)
for _ in range(levels):
F=len(ar)
S=sum(ar)
if scheme=='loop':
V,E,ar=V+E,2*E+3*F,[3]*(4*F)
else:
V,E,ar=V+E+F,2*E+S,[4]*S
B=2*B
return [V,E,len(ar),B,V-E+len(ar)]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['tetra loop 1', [[4, 6, [3, 3, 3, 3], 0, 'loop', 1]], [10, 24, 16, 0, 2]], ['tetra loop 2', [[4, 6, [3, 3, 3, 3], 0, 'loop', 2]], [34, 96, 64, 0, 2]], ['disk loop', [[6, 10, [3, 3, 3, 3, 3], 5, 'loop', 1]], [16, 35, 20, 10, 1]], ['disk loop 2', [[6, 10, [3, 3, 3, 3, 3], 5, 'loop', 2]], [51, 130, 80, 20, 1]], ['cube cc', [[8, 12, [4, 4, 4, 4, 4, 4], 0, 'cc', 1]], [26, 48, 24, 0, 2]], ['quad under loop', [[4, 4, [4], 4, 'loop', 1]], 'non-triangle'], ['triangle then quad under loop', [[5, 6, [3, 4], 4, 'loop', 1]], 'non-triangle']], [['disk loop 2', [[6, 10, [3, 3, 3, 3, 3], 5, 'loop', 2]], [51, 130, 80, 20, 1]], ['cube cc', [[8, 12, [4, 4, 4, 4, 4, 4], 0, 'cc', 1]], [26, 48, 24, 0, 2]], ['cube cc 2', [[8, 12, [4, 4, 4, 4, 4, 4], 0, 'cc', 2]], [98, 192, 96, 0, 2]], ['single quad cc', [[4, 4, [4], 4, 'cc', 2]], [25, 40, 16, 16, 1]], ['quad and triangle cc', [[5, 6, [4, 3], 4, 'cc', 1]], [13, 19, 7, 8, 1]], ['quad and triangle cc 2', [[5, 6, [4, 3], 4, 'cc', 2]], [39, 66, 28, 16, 1]], ['triangle then quad under loop', [[5, 6, [3, 4], 4, 'loop', 1]], 'non-triangle']], [['single quad cc', [[4, 4, [4], 4, 'cc', 2]], [25, 40, 16, 16, 1]], ['quad and triangle cc', [[5, 6, [4, 3], 4, 'cc', 1]], [13, 19, 7, 8, 1]], ['quad and triangle cc 2', [[5, 6, [4, 3], 4, 'cc', 2]], [39, 66, 28, 16, 1]], ['pentagon cc', [[5, 5, [5], 5, 'cc', 1]], [11, 15, 5, 10, 1]], ['quad under loop', [[4, 4, [4], 4, 'loop', 1]], 'non-triangle'], ['triangle then quad under loop', [[5, 6, [3, 4], 4, 'loop', 1]], 'non-triangle'], ['zero levels', [[4, 6, [3, 3, 3, 3], 0, 'loop', 0]], [4, 6, 4, 0, 2]]], [['pentagon cc', [[5, 5, [5], 5, 'cc', 1]], [11, 15, 5, 10, 1]], ['quad under loop', [[4, 4, [4], 4, 'loop', 1]], 'non-triangle'], ['triangle then quad under loop', [[5, 6, [3, 4], 4, 'loop', 1]], 'non-triangle'], ['zero levels', [[4, 6, [3, 3, 3, 3], 0, 'loop', 0]], [4, 6, 4, 0, 2]], ['torus cc', [[9, 18, [4, 4, 4, 4, 4, 4, 4, 4, 4], 0, 'cc', 1]], [36, 72, 36, 0, 0]], ['triangle tetra cc', [[4, 6, [3, 3, 3, 3], 0, 'cc', 1]], [14, 24, 12, 0, 2]], ['single triangle loop 3', [[3, 3, [3], 3, 'loop', 3]], [45, 108, 64, 24, 1]]], [['tetra loop 1', [[4, 6, [3, 3, 3, 3], 0, 'loop', 1]], [10, 24, 16, 0, 2]], ['tetra loop 2', [[4, 6, [3, 3, 3, 3], 0, 'loop', 2]], [34, 96, 64, 0, 2]], ['disk loop', [[6, 10, [3, 3, 3, 3, 3], 5, 'loop', 1]], [16, 35, 20, 10, 1]], ['quad under loop', [[4, 4, [4], 4, 'loop', 1]], 'non-triangle'], ['triangle then quad under loop', [[5, 6, [3, 4], 4, 'loop', 1]], 'non-triangle'], ['triangle tetra cc', [[4, 6, [3, 3, 3, 3], 0, 'cc', 1]], [14, 24, 12, 0, 2]], ['single triangle loop 3', [[3, 3, [3], 3, 'loop', 3]], [45, 108, 64, 24, 1]]]]
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 |
|---|---|---|---|
| tetra loop 1 | [10, 24, 16, 0, 2] | [10, 24, 16, 0, 2] | Passed |
| tetra loop 2 | [34, 96, 64, 0, 2] | [34, 96, 64, 0, 2] | Passed |
| disk loop | [16, 35, 20, 10, 1] | [16, 35, 20, 10, 1] | Passed |
| disk loop 2 | [51, 130, 80, 20, 1] | [51, 130, 80, 20, 1] | Passed |
| cube cc | [26, 48, 24, 0, 2] | [26, 48, 24, 0, 2] | Passed |
| quad under loop | [8, 11, 4, 8, 1] | non-triangle | Failed |
| triangle then quad under loop | [11, 18, 8, 8, 1] | non-triangle | Failed |
SHA-256 / 6317dd58ab2084ec7a3d183d20ee45d7190fd1652e12318911c0c5e7c441e5db
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
V,E,ar,B,scheme,levels=x
ar=list(ar)
for _ in range(levels):
F=len(ar)
S=sum(ar)
if scheme=='loop':
if ar[0]!=3: return 'non-triangle'
V,E,ar=V+E,2*E+3*F,[3]*(4*F)
else:
V,E,ar=V+E+F,2*E+S,[4]*S
B=2*B
return [V,E,len(ar),B,V-E+len(ar)]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['tetra loop 1', [[4, 6, [3, 3, 3, 3], 0, 'loop', 1]], [10, 24, 16, 0, 2]], ['tetra loop 2', [[4, 6, [3, 3, 3, 3], 0, 'loop', 2]], [34, 96, 64, 0, 2]], ['disk loop', [[6, 10, [3, 3, 3, 3, 3], 5, 'loop', 1]], [16, 35, 20, 10, 1]], ['disk loop 2', [[6, 10, [3, 3, 3, 3, 3], 5, 'loop', 2]], [51, 130, 80, 20, 1]], ['cube cc', [[8, 12, [4, 4, 4, 4, 4, 4], 0, 'cc', 1]], [26, 48, 24, 0, 2]], ['quad under loop', [[4, 4, [4], 4, 'loop', 1]], 'non-triangle'], ['triangle then quad under loop', [[5, 6, [3, 4], 4, 'loop', 1]], 'non-triangle']], [['disk loop 2', [[6, 10, [3, 3, 3, 3, 3], 5, 'loop', 2]], [51, 130, 80, 20, 1]], ['cube cc', [[8, 12, [4, 4, 4, 4, 4, 4], 0, 'cc', 1]], [26, 48, 24, 0, 2]], ['cube cc 2', [[8, 12, [4, 4, 4, 4, 4, 4], 0, 'cc', 2]], [98, 192, 96, 0, 2]], ['single quad cc', [[4, 4, [4], 4, 'cc', 2]], [25, 40, 16, 16, 1]], ['quad and triangle cc', [[5, 6, [4, 3], 4, 'cc', 1]], [13, 19, 7, 8, 1]], ['quad and triangle cc 2', [[5, 6, [4, 3], 4, 'cc', 2]], [39, 66, 28, 16, 1]], ['triangle then quad under loop', [[5, 6, [3, 4], 4, 'loop', 1]], 'non-triangle']], [['single quad cc', [[4, 4, [4], 4, 'cc', 2]], [25, 40, 16, 16, 1]], ['quad and triangle cc', [[5, 6, [4, 3], 4, 'cc', 1]], [13, 19, 7, 8, 1]], ['quad and triangle cc 2', [[5, 6, [4, 3], 4, 'cc', 2]], [39, 66, 28, 16, 1]], ['pentagon cc', [[5, 5, [5], 5, 'cc', 1]], [11, 15, 5, 10, 1]], ['quad under loop', [[4, 4, [4], 4, 'loop', 1]], 'non-triangle'], ['triangle then quad under loop', [[5, 6, [3, 4], 4, 'loop', 1]], 'non-triangle'], ['zero levels', [[4, 6, [3, 3, 3, 3], 0, 'loop', 0]], [4, 6, 4, 0, 2]]], [['pentagon cc', [[5, 5, [5], 5, 'cc', 1]], [11, 15, 5, 10, 1]], ['quad under loop', [[4, 4, [4], 4, 'loop', 1]], 'non-triangle'], ['triangle then quad under loop', [[5, 6, [3, 4], 4, 'loop', 1]], 'non-triangle'], ['zero levels', [[4, 6, [3, 3, 3, 3], 0, 'loop', 0]], [4, 6, 4, 0, 2]], ['torus cc', [[9, 18, [4, 4, 4, 4, 4, 4, 4, 4, 4], 0, 'cc', 1]], [36, 72, 36, 0, 0]], ['triangle tetra cc', [[4, 6, [3, 3, 3, 3], 0, 'cc', 1]], [14, 24, 12, 0, 2]], ['single triangle loop 3', [[3, 3, [3], 3, 'loop', 3]], [45, 108, 64, 24, 1]]], [['tetra loop 1', [[4, 6, [3, 3, 3, 3], 0, 'loop', 1]], [10, 24, 16, 0, 2]], ['tetra loop 2', [[4, 6, [3, 3, 3, 3], 0, 'loop', 2]], [34, 96, 64, 0, 2]], ['disk loop', [[6, 10, [3, 3, 3, 3, 3], 5, 'loop', 1]], [16, 35, 20, 10, 1]], ['quad under loop', [[4, 4, [4], 4, 'loop', 1]], 'non-triangle'], ['triangle then quad under loop', [[5, 6, [3, 4], 4, 'loop', 1]], 'non-triangle'], ['triangle tetra cc', [[4, 6, [3, 3, 3, 3], 0, 'cc', 1]], [14, 24, 12, 0, 2]], ['single triangle loop 3', [[3, 3, [3], 3, 'loop', 3]], [45, 108, 64, 24, 1]]]]
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 |
|---|---|---|---|
| tetra loop 1 | [10, 24, 16, 0, 2] | [10, 24, 16, 0, 2] | Passed |
| tetra loop 2 | [34, 96, 64, 0, 2] | [34, 96, 64, 0, 2] | Passed |
| disk loop | [16, 35, 20, 10, 1] | [16, 35, 20, 10, 1] | Passed |
| disk loop 2 | [51, 130, 80, 20, 1] | [51, 130, 80, 20, 1] | Passed |
| cube cc | [26, 48, 24, 0, 2] | [26, 48, 24, 0, 2] | Passed |
| quad under loop | non-triangle | non-triangle | Passed |
| triangle then quad under loop | [11, 18, 8, 8, 1] | non-triangle | Failed |
SHA-256 / c8a6872b5c79fb0fe9b778c00f9916c5dc602296a6658aaf3f5fb61d354a69a7
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:08.964918+00:00.
Case digest / 007a4dc52ae8334400088b14f4941b71aab3ee8b893f070737a2b7495624bed1