FAILURE MAP
← Case archive

FA-70366 / GIS polygon topology / Open access

Ring vertex cleaning with snapping tolerance: tolerance inclusivity · case 01

Vertices exactly one tolerance away from the previous vertex survive cleaning.

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

ROOT CAUSE

The drop test uses a strict comparison, so a step of exactly eps is kept.

VERIFIED REPAIR

At the tolerance inclusivity step restore `<= eps: continue`, leaving the rest of the model unchanged.

Unsuccessful approach: Adding an exact-duplicate test only helps when eps is zero.

Case contract

Input [ring, eps] where ring is an open or closed list of integer [x, y] positions and eps >= 0. Walk the ring and drop a position whose Chebyshev distance to the last KEPT position is <= eps. Then repeatedly drop trailing kept positions within eps of the first kept position. If fewer than 3 positions remain return None, else return the kept positions closed by repeating the first.

Why this case matters

Digitised boundaries carry jitter and duplicate clicks; cleaning must not let small steps accumulate into dropped corners or leave near-closing duplicates.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    ring, eps = x
    clean = []
    for p in ring:
        if clean and max(abs(p[0] - clean[-1][0]), abs(p[1] - clean[-1][1])) < eps:
            continue
        clean.append(list(p))
    while len(clean) > 1 and max(abs(clean[0][0] - clean[-1][0]), abs(clean[0][1] - clean[-1][1])) <= eps:
        clean.pop()
    if len(clean) < 3:
        return None
    return clean + [clean[0]]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('control #0', [[[78, 61], [78, 62], [65, 72], [48, 82], [18, 63], [26, 38], [24, 36], [81, 44]], 0], [[78, 61], [78, 62], [65, 72], [48, 82], [18, 63], [26, 38], [24, 36], [81, 44], [78, 61]]), ('control #1', [[[72, 54], [73, 61], [57, 81], [26, 60], [28, 59], [20, 26], [45, 23], [45, 25], [56, 15]], 2], [[72, 54], [73, 61], [57, 81], [26, 60], [20, 26], [45, 23], [56, 15], [72, 54]]), ('control #2', [[[38, 79], [40, 79], [41, 24], [39, 22], [49, 21], [68, 28], [73, 37]], 0], [[38, 79], [40, 79], [41, 24], [39, 22], [49, 21], [68, 28], [73, 37], [38, 79]]), ('control #3', [[[64, 69], [62, 67], [54, 72], [44, 80], [43, 82], [38, 76], [36, 75], [22, 74], [13, 56], [12, 42]], 2], [[64, 69], [54, 72], [44, 80], [38, 76], [22, 74], [13, 56], [12, 42], [64, 69]]), ('control #4', [[[76, 52], [76, 53], [70, 74], [68, 73], [69, 77], [40, 80], [39, 78], [57, 16], [56, 14], [85, 46], [77, 52]], 0], [[76, 52], [76, 53], [70, 74], [68, 73], [69, 77], [40, 80], [39, 78], [57, 16], [56, 14], [85, 46], [77, 52], [76, 52]]), ('control #5', [[[76, 62], [76, 76], [77, 78], [47, 80], [20, 63], [22, 65], [50, 22], [51, 20], [60, 29], [62, 29]], 0], [[76, 62], [76, 76], [77, 78], [47, 80], [20, 63], [22, 65], [50, 22], [51, 20], [60, 29], [62, 29], [76, 62]]), ('control #6', [[[72, 55], [75, 56], [57, 84], [18, 62], [62, 21], [60, 20]], 1], [[72, 55], [75, 56], [57, 84], [18, 62], [62, 21], [60, 20], [72, 55]]), ('control #7', [[[80, 63], [82, 63], [64, 80], [47, 82], [62, 19], [60, 20], [80, 47], [78, 45], [79, 63]], 2], [[80, 63], [64, 80], [47, 82], [62, 19], [80, 47], [80, 63]])], [('control #3', [[[64, 69], [62, 67], [54, 72], [44, 80], [43, 82], [38, 76], [36, 75], [22, 74], [13, 56], [12, 42]], 2], [[64, 69], [54, 72], [44, 80], [38, 76], [22, 74], [13, 56], [12, 42], [64, 69]]), ('control #4', [[[76, 52], [76, 53], [70, 74], [68, 73], [69, 77], [40, 80], [39, 78], [57, 16], [56, 14], [85, 46], [77, 52]], 0], [[76, 52], [76, 53], [70, 74], [68, 73], [69, 77], [40, 80], [39, 78], [57, 16], [56, 14], [85, 46], [77, 52], [76, 52]]), ('control #5', [[[76, 62], [76, 76], [77, 78], [47, 80], [20, 63], [22, 65], [50, 22], [51, 20], [60, 29], [62, 29]], 0], [[76, 62], [76, 76], [77, 78], [47, 80], [20, 63], [22, 65], [50, 22], [51, 20], [60, 29], [62, 29], [76, 62]]), ('control #6', [[[72, 55], [75, 56], [57, 84], [18, 62], [62, 21], [60, 20]], 1], [[72, 55], [75, 56], [57, 84], [18, 62], [62, 21], [60, 20], [72, 55]]), ('control #7', [[[80, 63], [82, 63], [64, 80], [47, 82], [62, 19], [60, 20], [80, 47], [78, 45], [79, 63]], 2], [[80, 63], [64, 80], [47, 82], [62, 19], [80, 47], [80, 63]]), ('control #8', [[[87, 57], [18, 50], [18, 51], [51, 20], [51, 21], [53, 11], [86, 57]], 1], [[87, 57], [18, 50], [51, 20], [53, 11], [87, 57]]), ('control #9', [[[23, 71], [30, 60], [32, 61], [24, 33], [25, 33], [28, 33], [28, 33], [26, 37]], 1], [[23, 71], [30, 60], [32, 61], [24, 33], [28, 33], [26, 37], [23, 71]]), ('control #10', [[[30, 78], [22, 36], [32, 33], [50, 13], [76, 40], [78, 38], [73, 49], [75, 47]], 2], [[30, 78], [22, 36], [32, 33], [50, 13], [76, 40], [73, 49], [30, 78]])], [('control #6', [[[72, 55], [75, 56], [57, 84], [18, 62], [62, 21], [60, 20]], 1], [[72, 55], [75, 56], [57, 84], [18, 62], [62, 21], [60, 20], [72, 55]]), ('control #7', [[[80, 63], [82, 63], [64, 80], [47, 82], [62, 19], [60, 20], [80, 47], [78, 45], [79, 63]], 2], [[80, 63], [64, 80], [47, 82], [62, 19], [80, 47], [80, 63]]), ('control #8', [[[87, 57], [18, 50], [18, 51], [51, 20], [51, 21], [53, 11], [86, 57]], 1], [[87, 57], [18, 50], [51, 20], [53, 11], [87, 57]]), ('control #9', [[[23, 71], [30, 60], [32, 61], [24, 33], [25, 33], [28, 33], [28, 33], [26, 37]], 1], [[23, 71], [30, 60], [32, 61], [24, 33], [28, 33], [26, 37], [23, 71]]), ('control #10', [[[30, 78], [22, 36], [32, 33], [50, 13], [76, 40], [78, 38], [73, 49], [75, 47]], 2], [[30, 78], [22, 36], [32, 33], [50, 13], [76, 40], [73, 49], [30, 78]]), ('control #11', [[[71, 63], [73, 64], [45, 75], [31, 77], [17, 36], [38, 23], [83, 37], [85, 39], [72, 63]], 1], [[71, 63], [73, 64], [45, 75], [31, 77], [17, 36], [38, 23], [83, 37], [85, 39], [71, 63]]), ('boundary #12', [[[0, 0], [2, 0], [10, 0], [10, 10], [0, 10]], 2], [[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]]), ('regression #14', [[[0, 0], [10, 0], [10, 10], [0, 10], [0, 1], [1, 0]], 1], [[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]])], [('control #8', [[[87, 57], [18, 50], [18, 51], [51, 20], [51, 21], [53, 11], [86, 57]], 1], [[87, 57], [18, 50], [51, 20], [53, 11], [87, 57]]), ('control #9', [[[23, 71], [30, 60], [32, 61], [24, 33], [25, 33], [28, 33], [28, 33], [26, 37]], 1], [[23, 71], [30, 60], [32, 61], [24, 33], [28, 33], [26, 37], [23, 71]]), ('control #11', [[[71, 63], [73, 64], [45, 75], [31, 77], [17, 36], [38, 23], [83, 37], [85, 39], [72, 63]], 1], [[71, 63], [73, 64], [45, 75], [31, 77], [17, 36], [38, 23], [83, 37], [85, 39], [71, 63]]), ('boundary #12', [[[0, 0], [2, 0], [10, 0], [10, 10], [0, 10]], 2], [[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]]), ('regression #13', [[[0, 0], [1, 0], [2, 0], [3, 0], [10, 0], [10, 10], [0, 10]], 1], [[0, 0], [2, 0], [10, 0], [10, 10], [0, 10], [0, 0]]), ('regression #14', [[[0, 0], [10, 0], [10, 10], [0, 10], [0, 1], [1, 0]], 1], [[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]]), ('boundary #15', [[[0, 0], [10, 0], [10, 10], [0, 0]], 0], [[0, 0], [10, 0], [10, 10], [0, 0]]), ('boundary #16', [[[0, 0], [10, 0], [10, 1], [0, 0]], 1], None)], [('control #9', [[[23, 71], [30, 60], [32, 61], [24, 33], [25, 33], [28, 33], [28, 33], [26, 37]], 1], [[23, 71], [30, 60], [32, 61], [24, 33], [28, 33], [26, 37], [23, 71]]), ('control #10', [[[30, 78], [22, 36], [32, 33], [50, 13], [76, 40], [78, 38], [73, 49], [75, 47]], 2], [[30, 78], [22, 36], [32, 33], [50, 13], [76, 40], [73, 49], [30, 78]]), ('regression #14', [[[0, 0], [10, 0], [10, 10], [0, 10], [0, 1], [1, 0]], 1], [[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]]), ('boundary #15', [[[0, 0], [10, 0], [10, 10], [0, 0]], 0], [[0, 0], [10, 0], [10, 10], [0, 0]]), ('boundary #16', [[[0, 0], [10, 0], [10, 1], [0, 0]], 1], None), ('boundary #17', [[[0, 0], [10, 0], [0, 0]], 0], None), ('regression #18', [[[0, 0], [1, 1], [10, 0], [10, 10], [0, 10]], 1], [[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]]), ('regression #19', [[[0, 0], [2, 1], [10, 0], [10, 10], [0, 10]], 2], [[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]])]]
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
control #0[[78, 61], [78, 62], [65, 72], [48, 82], [18, 63], [26, 38], [24, 36], [81, 44], [78, 61]][[78, 61], [78, 62], [65, 72], [48, 82], [18, 63], [26, 38], [24, 36], [81, 44], [78, 61]]Passed
control #1[[72, 54], [73, 61], [57, 81], [26, 60], [28, 59], [20, 26], [45, 23], [45, 25], [56, 15], [72, 54]][[72, 54], [73, 61], [57, 81], [26, 60], [20, 26], [45, 23], [56, 15], [72, 54]]Failed
control #2[[38, 79], [40, 79], [41, 24], [39, 22], [49, 21], [68, 28], [73, 37], [38, 79]][[38, 79], [40, 79], [41, 24], [39, 22], [49, 21], [68, 28], [73, 37], [38, 79]]Passed
control #3[[64, 69], [62, 67], [54, 72], [44, 80], [43, 82], [38, 76], [36, 75], [22, 74], [13, 56], [12, 42], [64, 69]][[64, 69], [54, 72], [44, 80], [38, 76], [22, 74], [13, 56], [12, 42], [64, 69]]Failed
control #4[[76, 52], [76, 53], [70, 74], [68, 73], [69, 77], [40, 80], [39, 78], [57, 16], [56, 14], [85, 46], [77, 52], [76, 52]][[76, 52], [76, 53], [70, 74], [68, 73], [69, 77], [40, 80], [39, 78], [57, 16], [56, 14], [85, 46], [77, 52], [76, 52]]Passed
control #5[[76, 62], [76, 76], [77, 78], [47, 80], [20, 63], [22, 65], [50, 22], [51, 20], [60, 29], [62, 29], [76, 62]][[76, 62], [76, 76], [77, 78], [47, 80], [20, 63], [22, 65], [50, 22], [51, 20], [60, 29], [62, 29], [76, 62]]Passed
control #6[[72, 55], [75, 56], [57, 84], [18, 62], [62, 21], [60, 20], [72, 55]][[72, 55], [75, 56], [57, 84], [18, 62], [62, 21], [60, 20], [72, 55]]Passed
control #7[[80, 63], [82, 63], [64, 80], [47, 82], [62, 19], [60, 20], [80, 47], [78, 45], [80, 63]][[80, 63], [64, 80], [47, 82], [62, 19], [80, 47], [80, 63]]Failed

SHA-256 / 9b811947ea738208894e473b58f37f7b277c124782f6d4dc200184424bf21f27

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    ring, eps = x
    clean = []
    for p in ring:
        if clean and max(abs(p[0] - clean[-1][0]), abs(p[1] - clean[-1][1])) < eps or clean and p == clean[-1]:
            continue
        clean.append(list(p))
    while len(clean) > 1 and max(abs(clean[0][0] - clean[-1][0]), abs(clean[0][1] - clean[-1][1])) <= eps:
        clean.pop()
    if len(clean) < 3:
        return None
    return clean + [clean[0]]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('control #0', [[[78, 61], [78, 62], [65, 72], [48, 82], [18, 63], [26, 38], [24, 36], [81, 44]], 0], [[78, 61], [78, 62], [65, 72], [48, 82], [18, 63], [26, 38], [24, 36], [81, 44], [78, 61]]), ('control #1', [[[72, 54], [73, 61], [57, 81], [26, 60], [28, 59], [20, 26], [45, 23], [45, 25], [56, 15]], 2], [[72, 54], [73, 61], [57, 81], [26, 60], [20, 26], [45, 23], [56, 15], [72, 54]]), ('control #2', [[[38, 79], [40, 79], [41, 24], [39, 22], [49, 21], [68, 28], [73, 37]], 0], [[38, 79], [40, 79], [41, 24], [39, 22], [49, 21], [68, 28], [73, 37], [38, 79]]), ('control #3', [[[64, 69], [62, 67], [54, 72], [44, 80], [43, 82], [38, 76], [36, 75], [22, 74], [13, 56], [12, 42]], 2], [[64, 69], [54, 72], [44, 80], [38, 76], [22, 74], [13, 56], [12, 42], [64, 69]]), ('control #4', [[[76, 52], [76, 53], [70, 74], [68, 73], [69, 77], [40, 80], [39, 78], [57, 16], [56, 14], [85, 46], [77, 52]], 0], [[76, 52], [76, 53], [70, 74], [68, 73], [69, 77], [40, 80], [39, 78], [57, 16], [56, 14], [85, 46], [77, 52], [76, 52]]), ('control #5', [[[76, 62], [76, 76], [77, 78], [47, 80], [20, 63], [22, 65], [50, 22], [51, 20], [60, 29], [62, 29]], 0], [[76, 62], [76, 76], [77, 78], [47, 80], [20, 63], [22, 65], [50, 22], [51, 20], [60, 29], [62, 29], [76, 62]]), ('control #6', [[[72, 55], [75, 56], [57, 84], [18, 62], [62, 21], [60, 20]], 1], [[72, 55], [75, 56], [57, 84], [18, 62], [62, 21], [60, 20], [72, 55]]), ('control #7', [[[80, 63], [82, 63], [64, 80], [47, 82], [62, 19], [60, 20], [80, 47], [78, 45], [79, 63]], 2], [[80, 63], [64, 80], [47, 82], [62, 19], [80, 47], [80, 63]])], [('control #3', [[[64, 69], [62, 67], [54, 72], [44, 80], [43, 82], [38, 76], [36, 75], [22, 74], [13, 56], [12, 42]], 2], [[64, 69], [54, 72], [44, 80], [38, 76], [22, 74], [13, 56], [12, 42], [64, 69]]), ('control #4', [[[76, 52], [76, 53], [70, 74], [68, 73], [69, 77], [40, 80], [39, 78], [57, 16], [56, 14], [85, 46], [77, 52]], 0], [[76, 52], [76, 53], [70, 74], [68, 73], [69, 77], [40, 80], [39, 78], [57, 16], [56, 14], [85, 46], [77, 52], [76, 52]]), ('control #5', [[[76, 62], [76, 76], [77, 78], [47, 80], [20, 63], [22, 65], [50, 22], [51, 20], [60, 29], [62, 29]], 0], [[76, 62], [76, 76], [77, 78], [47, 80], [20, 63], [22, 65], [50, 22], [51, 20], [60, 29], [62, 29], [76, 62]]), ('control #6', [[[72, 55], [75, 56], [57, 84], [18, 62], [62, 21], [60, 20]], 1], [[72, 55], [75, 56], [57, 84], [18, 62], [62, 21], [60, 20], [72, 55]]), ('control #7', [[[80, 63], [82, 63], [64, 80], [47, 82], [62, 19], [60, 20], [80, 47], [78, 45], [79, 63]], 2], [[80, 63], [64, 80], [47, 82], [62, 19], [80, 47], [80, 63]]), ('control #8', [[[87, 57], [18, 50], [18, 51], [51, 20], [51, 21], [53, 11], [86, 57]], 1], [[87, 57], [18, 50], [51, 20], [53, 11], [87, 57]]), ('control #9', [[[23, 71], [30, 60], [32, 61], [24, 33], [25, 33], [28, 33], [28, 33], [26, 37]], 1], [[23, 71], [30, 60], [32, 61], [24, 33], [28, 33], [26, 37], [23, 71]]), ('control #10', [[[30, 78], [22, 36], [32, 33], [50, 13], [76, 40], [78, 38], [73, 49], [75, 47]], 2], [[30, 78], [22, 36], [32, 33], [50, 13], [76, 40], [73, 49], [30, 78]])], [('control #6', [[[72, 55], [75, 56], [57, 84], [18, 62], [62, 21], [60, 20]], 1], [[72, 55], [75, 56], [57, 84], [18, 62], [62, 21], [60, 20], [72, 55]]), ('control #7', [[[80, 63], [82, 63], [64, 80], [47, 82], [62, 19], [60, 20], [80, 47], [78, 45], [79, 63]], 2], [[80, 63], [64, 80], [47, 82], [62, 19], [80, 47], [80, 63]]), ('control #8', [[[87, 57], [18, 50], [18, 51], [51, 20], [51, 21], [53, 11], [86, 57]], 1], [[87, 57], [18, 50], [51, 20], [53, 11], [87, 57]]), ('control #9', [[[23, 71], [30, 60], [32, 61], [24, 33], [25, 33], [28, 33], [28, 33], [26, 37]], 1], [[23, 71], [30, 60], [32, 61], [24, 33], [28, 33], [26, 37], [23, 71]]), ('control #10', [[[30, 78], [22, 36], [32, 33], [50, 13], [76, 40], [78, 38], [73, 49], [75, 47]], 2], [[30, 78], [22, 36], [32, 33], [50, 13], [76, 40], [73, 49], [30, 78]]), ('control #11', [[[71, 63], [73, 64], [45, 75], [31, 77], [17, 36], [38, 23], [83, 37], [85, 39], [72, 63]], 1], [[71, 63], [73, 64], [45, 75], [31, 77], [17, 36], [38, 23], [83, 37], [85, 39], [71, 63]]), ('boundary #12', [[[0, 0], [2, 0], [10, 0], [10, 10], [0, 10]], 2], [[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]]), ('regression #14', [[[0, 0], [10, 0], [10, 10], [0, 10], [0, 1], [1, 0]], 1], [[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]])], [('control #8', [[[87, 57], [18, 50], [18, 51], [51, 20], [51, 21], [53, 11], [86, 57]], 1], [[87, 57], [18, 50], [51, 20], [53, 11], [87, 57]]), ('control #9', [[[23, 71], [30, 60], [32, 61], [24, 33], [25, 33], [28, 33], [28, 33], [26, 37]], 1], [[23, 71], [30, 60], [32, 61], [24, 33], [28, 33], [26, 37], [23, 71]]), ('control #11', [[[71, 63], [73, 64], [45, 75], [31, 77], [17, 36], [38, 23], [83, 37], [85, 39], [72, 63]], 1], [[71, 63], [73, 64], [45, 75], [31, 77], [17, 36], [38, 23], [83, 37], [85, 39], [71, 63]]), ('boundary #12', [[[0, 0], [2, 0], [10, 0], [10, 10], [0, 10]], 2], [[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]]), ('regression #13', [[[0, 0], [1, 0], [2, 0], [3, 0], [10, 0], [10, 10], [0, 10]], 1], [[0, 0], [2, 0], [10, 0], [10, 10], [0, 10], [0, 0]]), ('regression #14', [[[0, 0], [10, 0], [10, 10], [0, 10], [0, 1], [1, 0]], 1], [[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]]), ('boundary #15', [[[0, 0], [10, 0], [10, 10], [0, 0]], 0], [[0, 0], [10, 0], [10, 10], [0, 0]]), ('boundary #16', [[[0, 0], [10, 0], [10, 1], [0, 0]], 1], None)], [('control #9', [[[23, 71], [30, 60], [32, 61], [24, 33], [25, 33], [28, 33], [28, 33], [26, 37]], 1], [[23, 71], [30, 60], [32, 61], [24, 33], [28, 33], [26, 37], [23, 71]]), ('control #10', [[[30, 78], [22, 36], [32, 33], [50, 13], [76, 40], [78, 38], [73, 49], [75, 47]], 2], [[30, 78], [22, 36], [32, 33], [50, 13], [76, 40], [73, 49], [30, 78]]), ('regression #14', [[[0, 0], [10, 0], [10, 10], [0, 10], [0, 1], [1, 0]], 1], [[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]]), ('boundary #15', [[[0, 0], [10, 0], [10, 10], [0, 0]], 0], [[0, 0], [10, 0], [10, 10], [0, 0]]), ('boundary #16', [[[0, 0], [10, 0], [10, 1], [0, 0]], 1], None), ('boundary #17', [[[0, 0], [10, 0], [0, 0]], 0], None), ('regression #18', [[[0, 0], [1, 1], [10, 0], [10, 10], [0, 10]], 1], [[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]]), ('regression #19', [[[0, 0], [2, 1], [10, 0], [10, 10], [0, 10]], 2], [[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]])]]
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
control #0[[78, 61], [78, 62], [65, 72], [48, 82], [18, 63], [26, 38], [24, 36], [81, 44], [78, 61]][[78, 61], [78, 62], [65, 72], [48, 82], [18, 63], [26, 38], [24, 36], [81, 44], [78, 61]]Passed
control #1[[72, 54], [73, 61], [57, 81], [26, 60], [28, 59], [20, 26], [45, 23], [45, 25], [56, 15], [72, 54]][[72, 54], [73, 61], [57, 81], [26, 60], [20, 26], [45, 23], [56, 15], [72, 54]]Failed
control #2[[38, 79], [40, 79], [41, 24], [39, 22], [49, 21], [68, 28], [73, 37], [38, 79]][[38, 79], [40, 79], [41, 24], [39, 22], [49, 21], [68, 28], [73, 37], [38, 79]]Passed
control #3[[64, 69], [62, 67], [54, 72], [44, 80], [43, 82], [38, 76], [36, 75], [22, 74], [13, 56], [12, 42], [64, 69]][[64, 69], [54, 72], [44, 80], [38, 76], [22, 74], [13, 56], [12, 42], [64, 69]]Failed
control #4[[76, 52], [76, 53], [70, 74], [68, 73], [69, 77], [40, 80], [39, 78], [57, 16], [56, 14], [85, 46], [77, 52], [76, 52]][[76, 52], [76, 53], [70, 74], [68, 73], [69, 77], [40, 80], [39, 78], [57, 16], [56, 14], [85, 46], [77, 52], [76, 52]]Passed
control #5[[76, 62], [76, 76], [77, 78], [47, 80], [20, 63], [22, 65], [50, 22], [51, 20], [60, 29], [62, 29], [76, 62]][[76, 62], [76, 76], [77, 78], [47, 80], [20, 63], [22, 65], [50, 22], [51, 20], [60, 29], [62, 29], [76, 62]]Passed
control #6[[72, 55], [75, 56], [57, 84], [18, 62], [62, 21], [60, 20], [72, 55]][[72, 55], [75, 56], [57, 84], [18, 62], [62, 21], [60, 20], [72, 55]]Passed
control #7[[80, 63], [82, 63], [64, 80], [47, 82], [62, 19], [60, 20], [80, 47], [78, 45], [80, 63]][[80, 63], [64, 80], [47, 82], [62, 19], [80, 47], [80, 63]]Failed

SHA-256 / 2ae0d991847dc19c0fb3d96684a822830d7425e7ae4fe74ba9b11073ececbb8a

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    ring, eps = x
    clean = []
    for p in ring:
        if clean and max(abs(p[0] - clean[-1][0]), abs(p[1] - clean[-1][1])) <= eps:
            continue
        clean.append(list(p))
    while len(clean) > 1 and max(abs(clean[0][0] - clean[-1][0]), abs(clean[0][1] - clean[-1][1])) <= eps:
        clean.pop()
    if len(clean) < 3:
        return None
    return clean + [clean[0]]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('control #0', [[[78, 61], [78, 62], [65, 72], [48, 82], [18, 63], [26, 38], [24, 36], [81, 44]], 0], [[78, 61], [78, 62], [65, 72], [48, 82], [18, 63], [26, 38], [24, 36], [81, 44], [78, 61]]), ('control #1', [[[72, 54], [73, 61], [57, 81], [26, 60], [28, 59], [20, 26], [45, 23], [45, 25], [56, 15]], 2], [[72, 54], [73, 61], [57, 81], [26, 60], [20, 26], [45, 23], [56, 15], [72, 54]]), ('control #2', [[[38, 79], [40, 79], [41, 24], [39, 22], [49, 21], [68, 28], [73, 37]], 0], [[38, 79], [40, 79], [41, 24], [39, 22], [49, 21], [68, 28], [73, 37], [38, 79]]), ('control #3', [[[64, 69], [62, 67], [54, 72], [44, 80], [43, 82], [38, 76], [36, 75], [22, 74], [13, 56], [12, 42]], 2], [[64, 69], [54, 72], [44, 80], [38, 76], [22, 74], [13, 56], [12, 42], [64, 69]]), ('control #4', [[[76, 52], [76, 53], [70, 74], [68, 73], [69, 77], [40, 80], [39, 78], [57, 16], [56, 14], [85, 46], [77, 52]], 0], [[76, 52], [76, 53], [70, 74], [68, 73], [69, 77], [40, 80], [39, 78], [57, 16], [56, 14], [85, 46], [77, 52], [76, 52]]), ('control #5', [[[76, 62], [76, 76], [77, 78], [47, 80], [20, 63], [22, 65], [50, 22], [51, 20], [60, 29], [62, 29]], 0], [[76, 62], [76, 76], [77, 78], [47, 80], [20, 63], [22, 65], [50, 22], [51, 20], [60, 29], [62, 29], [76, 62]]), ('control #6', [[[72, 55], [75, 56], [57, 84], [18, 62], [62, 21], [60, 20]], 1], [[72, 55], [75, 56], [57, 84], [18, 62], [62, 21], [60, 20], [72, 55]]), ('control #7', [[[80, 63], [82, 63], [64, 80], [47, 82], [62, 19], [60, 20], [80, 47], [78, 45], [79, 63]], 2], [[80, 63], [64, 80], [47, 82], [62, 19], [80, 47], [80, 63]])], [('control #3', [[[64, 69], [62, 67], [54, 72], [44, 80], [43, 82], [38, 76], [36, 75], [22, 74], [13, 56], [12, 42]], 2], [[64, 69], [54, 72], [44, 80], [38, 76], [22, 74], [13, 56], [12, 42], [64, 69]]), ('control #4', [[[76, 52], [76, 53], [70, 74], [68, 73], [69, 77], [40, 80], [39, 78], [57, 16], [56, 14], [85, 46], [77, 52]], 0], [[76, 52], [76, 53], [70, 74], [68, 73], [69, 77], [40, 80], [39, 78], [57, 16], [56, 14], [85, 46], [77, 52], [76, 52]]), ('control #5', [[[76, 62], [76, 76], [77, 78], [47, 80], [20, 63], [22, 65], [50, 22], [51, 20], [60, 29], [62, 29]], 0], [[76, 62], [76, 76], [77, 78], [47, 80], [20, 63], [22, 65], [50, 22], [51, 20], [60, 29], [62, 29], [76, 62]]), ('control #6', [[[72, 55], [75, 56], [57, 84], [18, 62], [62, 21], [60, 20]], 1], [[72, 55], [75, 56], [57, 84], [18, 62], [62, 21], [60, 20], [72, 55]]), ('control #7', [[[80, 63], [82, 63], [64, 80], [47, 82], [62, 19], [60, 20], [80, 47], [78, 45], [79, 63]], 2], [[80, 63], [64, 80], [47, 82], [62, 19], [80, 47], [80, 63]]), ('control #8', [[[87, 57], [18, 50], [18, 51], [51, 20], [51, 21], [53, 11], [86, 57]], 1], [[87, 57], [18, 50], [51, 20], [53, 11], [87, 57]]), ('control #9', [[[23, 71], [30, 60], [32, 61], [24, 33], [25, 33], [28, 33], [28, 33], [26, 37]], 1], [[23, 71], [30, 60], [32, 61], [24, 33], [28, 33], [26, 37], [23, 71]]), ('control #10', [[[30, 78], [22, 36], [32, 33], [50, 13], [76, 40], [78, 38], [73, 49], [75, 47]], 2], [[30, 78], [22, 36], [32, 33], [50, 13], [76, 40], [73, 49], [30, 78]])], [('control #6', [[[72, 55], [75, 56], [57, 84], [18, 62], [62, 21], [60, 20]], 1], [[72, 55], [75, 56], [57, 84], [18, 62], [62, 21], [60, 20], [72, 55]]), ('control #7', [[[80, 63], [82, 63], [64, 80], [47, 82], [62, 19], [60, 20], [80, 47], [78, 45], [79, 63]], 2], [[80, 63], [64, 80], [47, 82], [62, 19], [80, 47], [80, 63]]), ('control #8', [[[87, 57], [18, 50], [18, 51], [51, 20], [51, 21], [53, 11], [86, 57]], 1], [[87, 57], [18, 50], [51, 20], [53, 11], [87, 57]]), ('control #9', [[[23, 71], [30, 60], [32, 61], [24, 33], [25, 33], [28, 33], [28, 33], [26, 37]], 1], [[23, 71], [30, 60], [32, 61], [24, 33], [28, 33], [26, 37], [23, 71]]), ('control #10', [[[30, 78], [22, 36], [32, 33], [50, 13], [76, 40], [78, 38], [73, 49], [75, 47]], 2], [[30, 78], [22, 36], [32, 33], [50, 13], [76, 40], [73, 49], [30, 78]]), ('control #11', [[[71, 63], [73, 64], [45, 75], [31, 77], [17, 36], [38, 23], [83, 37], [85, 39], [72, 63]], 1], [[71, 63], [73, 64], [45, 75], [31, 77], [17, 36], [38, 23], [83, 37], [85, 39], [71, 63]]), ('boundary #12', [[[0, 0], [2, 0], [10, 0], [10, 10], [0, 10]], 2], [[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]]), ('regression #14', [[[0, 0], [10, 0], [10, 10], [0, 10], [0, 1], [1, 0]], 1], [[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]])], [('control #8', [[[87, 57], [18, 50], [18, 51], [51, 20], [51, 21], [53, 11], [86, 57]], 1], [[87, 57], [18, 50], [51, 20], [53, 11], [87, 57]]), ('control #9', [[[23, 71], [30, 60], [32, 61], [24, 33], [25, 33], [28, 33], [28, 33], [26, 37]], 1], [[23, 71], [30, 60], [32, 61], [24, 33], [28, 33], [26, 37], [23, 71]]), ('control #11', [[[71, 63], [73, 64], [45, 75], [31, 77], [17, 36], [38, 23], [83, 37], [85, 39], [72, 63]], 1], [[71, 63], [73, 64], [45, 75], [31, 77], [17, 36], [38, 23], [83, 37], [85, 39], [71, 63]]), ('boundary #12', [[[0, 0], [2, 0], [10, 0], [10, 10], [0, 10]], 2], [[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]]), ('regression #13', [[[0, 0], [1, 0], [2, 0], [3, 0], [10, 0], [10, 10], [0, 10]], 1], [[0, 0], [2, 0], [10, 0], [10, 10], [0, 10], [0, 0]]), ('regression #14', [[[0, 0], [10, 0], [10, 10], [0, 10], [0, 1], [1, 0]], 1], [[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]]), ('boundary #15', [[[0, 0], [10, 0], [10, 10], [0, 0]], 0], [[0, 0], [10, 0], [10, 10], [0, 0]]), ('boundary #16', [[[0, 0], [10, 0], [10, 1], [0, 0]], 1], None)], [('control #9', [[[23, 71], [30, 60], [32, 61], [24, 33], [25, 33], [28, 33], [28, 33], [26, 37]], 1], [[23, 71], [30, 60], [32, 61], [24, 33], [28, 33], [26, 37], [23, 71]]), ('control #10', [[[30, 78], [22, 36], [32, 33], [50, 13], [76, 40], [78, 38], [73, 49], [75, 47]], 2], [[30, 78], [22, 36], [32, 33], [50, 13], [76, 40], [73, 49], [30, 78]]), ('regression #14', [[[0, 0], [10, 0], [10, 10], [0, 10], [0, 1], [1, 0]], 1], [[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]]), ('boundary #15', [[[0, 0], [10, 0], [10, 10], [0, 0]], 0], [[0, 0], [10, 0], [10, 10], [0, 0]]), ('boundary #16', [[[0, 0], [10, 0], [10, 1], [0, 0]], 1], None), ('boundary #17', [[[0, 0], [10, 0], [0, 0]], 0], None), ('regression #18', [[[0, 0], [1, 1], [10, 0], [10, 10], [0, 10]], 1], [[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]]), ('regression #19', [[[0, 0], [2, 1], [10, 0], [10, 10], [0, 10]], 2], [[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]])]]
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
control #0[[78, 61], [78, 62], [65, 72], [48, 82], [18, 63], [26, 38], [24, 36], [81, 44], [78, 61]][[78, 61], [78, 62], [65, 72], [48, 82], [18, 63], [26, 38], [24, 36], [81, 44], [78, 61]]Passed
control #1[[72, 54], [73, 61], [57, 81], [26, 60], [20, 26], [45, 23], [56, 15], [72, 54]][[72, 54], [73, 61], [57, 81], [26, 60], [20, 26], [45, 23], [56, 15], [72, 54]]Passed
control #2[[38, 79], [40, 79], [41, 24], [39, 22], [49, 21], [68, 28], [73, 37], [38, 79]][[38, 79], [40, 79], [41, 24], [39, 22], [49, 21], [68, 28], [73, 37], [38, 79]]Passed
control #3[[64, 69], [54, 72], [44, 80], [38, 76], [22, 74], [13, 56], [12, 42], [64, 69]][[64, 69], [54, 72], [44, 80], [38, 76], [22, 74], [13, 56], [12, 42], [64, 69]]Passed
control #4[[76, 52], [76, 53], [70, 74], [68, 73], [69, 77], [40, 80], [39, 78], [57, 16], [56, 14], [85, 46], [77, 52], [76, 52]][[76, 52], [76, 53], [70, 74], [68, 73], [69, 77], [40, 80], [39, 78], [57, 16], [56, 14], [85, 46], [77, 52], [76, 52]]Passed
control #5[[76, 62], [76, 76], [77, 78], [47, 80], [20, 63], [22, 65], [50, 22], [51, 20], [60, 29], [62, 29], [76, 62]][[76, 62], [76, 76], [77, 78], [47, 80], [20, 63], [22, 65], [50, 22], [51, 20], [60, 29], [62, 29], [76, 62]]Passed
control #6[[72, 55], [75, 56], [57, 84], [18, 62], [62, 21], [60, 20], [72, 55]][[72, 55], [75, 56], [57, 84], [18, 62], [62, 21], [60, 20], [72, 55]]Passed
control #7[[80, 63], [64, 80], [47, 82], [62, 19], [80, 47], [80, 63]][[80, 63], [64, 80], [47, 82], [62, 19], [80, 47], [80, 63]]Passed

SHA-256 / b286ef8a6a49afadbfab4509898eab61f8e4e803c602557e86cd194a43c66192

Verification & scope

Stipulated deterministic toy contract on a bounded input domain; results are rounded as stated and no conformance with any published standard or library is claimed. 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:48:20.083441+00:00.

Case digest / ecd3f43d44d12d6839f097319a092137def46f5c184c2b4e3de1d60fd0686eb8