FAILURE MAP
← Case archive

FA-88731 / Mesh topology invariants / Open access

Boundary face is emitted without canonical rotation · case 01

Output faces start at an arbitrary corner.

Verified by executionVariant 1 · 7 checks per implementationDownload source bundle ↓JSON ↗

ROOT CAUSE

The face is output exactly as generated.

THE FAILURE

The face is output exactly as generated.

Unsuccessful approach: Sorting the corners destroys the outward orientation.

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=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))
        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]]]], [['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]], ['rotated labels', [[[3, 1, 0, 2]]], [[0, 2, 1], [0, 1, 3], [0, 3, 2], [1, 2, 3]]]], [['single tet', [[[0, 1, 2, 3]]], [[0, 2, 1], [0, 1, 3], [0, 3, 2], [1, 2, 3]]], ['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 fixtureActualExpectedOutcome
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], [1, 0, 4], [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]]Failed
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 / 70aee4399e011fc27061ee0d08a5d8ffea4b59fdd6a52158d9327f954b1f76ba

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=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(sorted(f))
        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]]]], [['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]], ['rotated labels', [[[3, 1, 0, 2]]], [[0, 2, 1], [0, 1, 3], [0, 3, 2], [1, 2, 3]]]], [['single tet', [[[0, 1, 2, 3]]], [[0, 2, 1], [0, 1, 3], [0, 3, 2], [1, 2, 3]]], ['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 fixtureActualExpectedOutcome
single tet[[0, 1, 2], [0, 1, 3], [0, 2, 3], [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, 1, 4], [0, 2, 3], [0, 2, 4], [1, 2, 3], [1, 2, 4]][[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, 2, 3], [0, 2, 4], [0, 3, 4], [1, 2, 3], [1, 2, 4], [1, 3, 4]][[0, 3, 2], [0, 2, 4], [0, 4, 3], [1, 2, 3], [1, 4, 2], [1, 3, 4]]Failed
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 / cb11c539efdafe7139cf066a9374a1f18bc3fa9c3806c05f7557fb2986ff9962

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:10.896475+00:00.

Case digest / 63dc157da78d9536feb199b16e85fab04a3e8f5f8707393d369e925fa8aa09a7