{"abstract":"Holes touching the shell at their first vertex are labelled coincident.","category":"GIS polygon topology","checks":8,"contract":"Input [shell, holes], closed integer rings. Point classification against a ring: on an edge = 0, inside by half-open crossing number = 1, else -1. For each hole in order: \"outside\" if any hole vertex is strictly outside the shell; else \"coincident\" if every hole vertex lies on the shell boundary; else \"nested\" if for some OTHER hole all its vertices are inside-or-on that hole and at least one is strictly inside; else \"ok\". Return one label per hole.","evaluation_group":"w2-gis-polygon-topology-hole-containment-validation","failed_approach":"Two boundary vertices are taken as coincidence, mislabelling holes that share an edge with the shell.","family":"w2-gis-polygon-topology-hole-containment-validation-coincident-hole-detection","id":"FA-70556","implementations":{"attempt":{"sha256":"aad236eff0441faf0859cba300d5aa989d70bf50542cfc279203ecfe4c5b2f26","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\nimport math\nN = 1\nobservations = []\ndef solve(x):\n    shell, holes = x\n    def cls(pt, ring):\n        px, py = pt\n        for a, b in zip(ring, ring[1:]):\n            if (b[0] - a[0]) * (py - a[1]) - (b[1] - a[1]) * (px - a[0]) == 0 and min(a[0], b[0]) <= px <= max(a[0], b[0]) and min(a[1], b[1]) <= py <= max(a[1], b[1]):\n                return 0\n        c = False\n        for a, b in zip(ring, ring[1:]):\n            if (a[1] > py) != (b[1] > py) and px < a[0] + (py - a[1]) * (b[0] - a[0]) / (b[1] - a[1]):\n                c = not c\n        return 1 if c else -1\n    out = []\n    for i, h in enumerate(holes):\n        vs = h[:-1]\n        if any(cls(p, shell) < 0 for p in vs):\n            out.append('outside')\n            continue\n        if sum(cls(p, shell) == 0 for p in vs) >= 2:\n            out.append('coincident')\n            continue\n        nested = False\n        for j, g in enumerate(holes):\n            if j != i and all(cls(p, g) >= 0 for p in vs) and any(cls(p, g) > 0 for p in vs):\n                nested = True\n        out.append('nested' if nested else 'ok')\n    return out\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[('control #0', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[2, 2], [2, 5], [5, 5], [5, 2], [2, 2]]]], ['ok']), ('control #1', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[2, 2], [2, 5], [5, 5], [5, 2], [2, 2]], [[8, 8], [8, 12], [12, 12], [12, 8], [8, 8]]]], ['ok', 'ok']), ('regression #2', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[0, 5], [0, 9], [4, 9], [4, 5], [0, 5]]]], ['ok']), ('regression #3', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[18, 18], [18, 25], [25, 25], [25, 18], [18, 18]]]], ['outside']), ('regression #4', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[5, 5], [30, 10], [5, 15], [5, 5]]]], ['outside']), ('regression #5', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[25, 10], [10, 5], [10, 15], [25, 10]]]], ['outside']), ('regression #6', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[2, 2], [2, 12], [12, 12], [12, 2], [2, 2]], [[4, 4], [4, 6], [6, 6], [6, 4], [4, 4]]]], ['ok', 'nested']), ('regression #7', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[4, 4], [4, 6], [6, 6], [6, 4], [4, 4]], [[2, 2], [2, 12], [12, 12], [12, 2], [2, 2]], [[14, 2], [14, 5], [18, 5], [18, 2], [14, 2]]]], ['nested', 'ok', 'ok'])], [('regression #2', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[0, 5], [0, 9], [4, 9], [4, 5], [0, 5]]]], ['ok']), ('regression #4', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[5, 5], [30, 10], [5, 15], [5, 5]]]], ['outside']), ('regression #5', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[25, 10], [10, 5], [10, 15], [25, 10]]]], ['outside']), ('regression #6', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[2, 2], [2, 12], [12, 12], [12, 2], [2, 2]], [[4, 4], [4, 6], [6, 6], [6, 4], [4, 4]]]], ['ok', 'nested']), ('regression #7', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[4, 4], [4, 6], [6, 6], [6, 4], [4, 4]], [[2, 2], [2, 12], [12, 12], [12, 2], [2, 2]], [[14, 2], [14, 5], [18, 5], [18, 2], [14, 2]]]], ['nested', 'ok', 'ok']), ('regression #8', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[2, 2], [2, 8], [8, 8], [8, 2], [2, 2]], [[6, 6], [6, 12], [12, 12], [12, 6], [6, 6]]]], ['ok', 'ok']), ('boundary #9', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[2, 2], [2, 8], [8, 8], [8, 2], [2, 2]], [[2, 2], [2, 8], [8, 8], [8, 2], [2, 2]]]], ['ok', 'ok']), ('boundary #12', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[0, 0], [5, 3], [3, 5], [0, 0]]]], ['ok'])], [('regression #2', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[0, 5], [0, 9], [4, 9], [4, 5], [0, 5]]]], ['ok']), ('regression #7', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[4, 4], [4, 6], [6, 6], [6, 4], [4, 4]], [[2, 2], [2, 12], [12, 12], [12, 2], [2, 2]], [[14, 2], [14, 5], [18, 5], [18, 2], [14, 2]]]], ['nested', 'ok', 'ok']), ('regression #8', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[2, 2], [2, 8], [8, 8], [8, 2], [2, 2]], [[6, 6], [6, 12], [12, 12], [12, 6], [6, 6]]]], ['ok', 'ok']), ('boundary #9', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[2, 2], [2, 8], [8, 8], [8, 2], [2, 2]], [[2, 2], [2, 8], [8, 8], [8, 2], [2, 2]]]], ['ok', 'ok']), ('boundary #10', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[0, 0], [0, 20], [20, 20], [20, 0], [0, 0]]]], ['coincident']), ('boundary #11', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[0, 0], [5, 0], [0, 5], [0, 0]]]], ['coincident']), ('boundary #12', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[0, 0], [5, 3], [3, 5], [0, 0]]]], ['ok']), ('regression #13', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[22, 2], [22, 5], [25, 5], [25, 2], [22, 2]], [[2, 2], [2, 5], [5, 5], [5, 2], [2, 2]]]], ['outside', 'ok'])], [('regression #2', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[0, 5], [0, 9], [4, 9], [4, 5], [0, 5]]]], ['ok']), ('boundary #10', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[0, 0], [0, 20], [20, 20], [20, 0], [0, 0]]]], ['coincident']), ('boundary #11', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[0, 0], [5, 0], [0, 5], [0, 0]]]], ['coincident']), ('boundary #12', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[0, 0], [5, 3], [3, 5], [0, 0]]]], ['ok']), ('regression #13', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[22, 2], [22, 5], [25, 5], [25, 2], [22, 2]], [[2, 2], [2, 5], [5, 5], [5, 2], [2, 2]]]], ['outside', 'ok']), ('regression #14', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[-5, 2], [-5, 5], [3, 5], [3, 2], [-5, 2]], [[5, 5], [5, 9], [9, 9], [9, 5], [5, 5]], [[6, 6], [6, 7], [7, 7], [7, 6], [6, 6]]]], ['outside', 'ok', 'nested']), ('control #15', [[[0, 0], [20, 0], [10, 20], [0, 0]], [[[8, 4], [12, 4], [10, 8], [8, 4]]]], ['ok']), ('regression #16', [[[0, 0], [20, 0], [10, 20], [0, 0]], [[[8, 4], [12, 4], [10, 25], [8, 4]]]], ['outside'])], [('regression #2', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[0, 5], [0, 9], [4, 9], [4, 5], [0, 5]]]], ['ok']), ('regression #13', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[22, 2], [22, 5], [25, 5], [25, 2], [22, 2]], [[2, 2], [2, 5], [5, 5], [5, 2], [2, 2]]]], ['outside', 'ok']), ('regression #14', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[-5, 2], [-5, 5], [3, 5], [3, 2], [-5, 2]], [[5, 5], [5, 9], [9, 9], [9, 5], [5, 5]], [[6, 6], [6, 7], [7, 7], [7, 6], [6, 6]]]], ['outside', 'ok', 'nested']), ('control #15', [[[0, 0], [20, 0], [10, 20], [0, 0]], [[[8, 4], [12, 4], [10, 8], [8, 4]]]], ['ok']), ('regression #16', [[[0, 0], [20, 0], [10, 20], [0, 0]], [[[8, 4], [12, 4], [10, 25], [8, 4]]]], ['outside']), ('boundary #17', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[2, 2], [2, 6], [6, 6], [6, 2], [2, 2]], [[6, 2], [6, 6], [10, 6], [10, 2], [6, 2]]]], ['ok', 'ok']), ('control #18', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], []], []), ('regression #19', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[5, 5], [5, 10], [10, 10], [10, 5], [5, 5]], [[5, 5], [5, 8], [8, 8], [8, 5], [5, 5]]]], ['ok', 'nested'])]]\nfor label, args, expected in fixtures[N-1]:\n    check(label, solve(args), expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"},"broken":{"sha256":"028b13210a4fef3854d7f25f4c611b428107d46e16b97593031417b906d6e51a","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\nimport math\nN = 1\nobservations = []\ndef solve(x):\n    shell, holes = x\n    def cls(pt, ring):\n        px, py = pt\n        for a, b in zip(ring, ring[1:]):\n            if (b[0] - a[0]) * (py - a[1]) - (b[1] - a[1]) * (px - a[0]) == 0 and min(a[0], b[0]) <= px <= max(a[0], b[0]) and min(a[1], b[1]) <= py <= max(a[1], b[1]):\n                return 0\n        c = False\n        for a, b in zip(ring, ring[1:]):\n            if (a[1] > py) != (b[1] > py) and px < a[0] + (py - a[1]) * (b[0] - a[0]) / (b[1] - a[1]):\n                c = not c\n        return 1 if c else -1\n    out = []\n    for i, h in enumerate(holes):\n        vs = h[:-1]\n        if any(cls(p, shell) < 0 for p in vs):\n            out.append('outside')\n            continue\n        if all(cls(p, shell) == 0 for p in vs[:1]):\n            out.append('coincident')\n            continue\n        nested = False\n        for j, g in enumerate(holes):\n            if j != i and all(cls(p, g) >= 0 for p in vs) and any(cls(p, g) > 0 for p in vs):\n                nested = True\n        out.append('nested' if nested else 'ok')\n    return out\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[('control #0', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[2, 2], [2, 5], [5, 5], [5, 2], [2, 2]]]], ['ok']), ('control #1', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[2, 2], [2, 5], [5, 5], [5, 2], [2, 2]], [[8, 8], [8, 12], [12, 12], [12, 8], [8, 8]]]], ['ok', 'ok']), ('regression #2', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[0, 5], [0, 9], [4, 9], [4, 5], [0, 5]]]], ['ok']), ('regression #3', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[18, 18], [18, 25], [25, 25], [25, 18], [18, 18]]]], ['outside']), ('regression #4', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[5, 5], [30, 10], [5, 15], [5, 5]]]], ['outside']), ('regression #5', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[25, 10], [10, 5], [10, 15], [25, 10]]]], ['outside']), ('regression #6', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[2, 2], [2, 12], [12, 12], [12, 2], [2, 2]], [[4, 4], [4, 6], [6, 6], [6, 4], [4, 4]]]], ['ok', 'nested']), ('regression #7', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[4, 4], [4, 6], [6, 6], [6, 4], [4, 4]], [[2, 2], [2, 12], [12, 12], [12, 2], [2, 2]], [[14, 2], [14, 5], [18, 5], [18, 2], [14, 2]]]], ['nested', 'ok', 'ok'])], [('regression #2', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[0, 5], [0, 9], [4, 9], [4, 5], [0, 5]]]], ['ok']), ('regression #4', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[5, 5], [30, 10], [5, 15], [5, 5]]]], ['outside']), ('regression #5', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[25, 10], [10, 5], [10, 15], [25, 10]]]], ['outside']), ('regression #6', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[2, 2], [2, 12], [12, 12], [12, 2], [2, 2]], [[4, 4], [4, 6], [6, 6], [6, 4], [4, 4]]]], ['ok', 'nested']), ('regression #7', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[4, 4], [4, 6], [6, 6], [6, 4], [4, 4]], [[2, 2], [2, 12], [12, 12], [12, 2], [2, 2]], [[14, 2], [14, 5], [18, 5], [18, 2], [14, 2]]]], ['nested', 'ok', 'ok']), ('regression #8', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[2, 2], [2, 8], [8, 8], [8, 2], [2, 2]], [[6, 6], [6, 12], [12, 12], [12, 6], [6, 6]]]], ['ok', 'ok']), ('boundary #9', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[2, 2], [2, 8], [8, 8], [8, 2], [2, 2]], [[2, 2], [2, 8], [8, 8], [8, 2], [2, 2]]]], ['ok', 'ok']), ('boundary #12', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[0, 0], [5, 3], [3, 5], [0, 0]]]], ['ok'])], [('regression #2', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[0, 5], [0, 9], [4, 9], [4, 5], [0, 5]]]], ['ok']), ('regression #7', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[4, 4], [4, 6], [6, 6], [6, 4], [4, 4]], [[2, 2], [2, 12], [12, 12], [12, 2], [2, 2]], [[14, 2], [14, 5], [18, 5], [18, 2], [14, 2]]]], ['nested', 'ok', 'ok']), ('regression #8', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[2, 2], [2, 8], [8, 8], [8, 2], [2, 2]], [[6, 6], [6, 12], [12, 12], [12, 6], [6, 6]]]], ['ok', 'ok']), ('boundary #9', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[2, 2], [2, 8], [8, 8], [8, 2], [2, 2]], [[2, 2], [2, 8], [8, 8], [8, 2], [2, 2]]]], ['ok', 'ok']), ('boundary #10', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[0, 0], [0, 20], [20, 20], [20, 0], [0, 0]]]], ['coincident']), ('boundary #11', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[0, 0], [5, 0], [0, 5], [0, 0]]]], ['coincident']), ('boundary #12', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[0, 0], [5, 3], [3, 5], [0, 0]]]], ['ok']), ('regression #13', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[22, 2], [22, 5], [25, 5], [25, 2], [22, 2]], [[2, 2], [2, 5], [5, 5], [5, 2], [2, 2]]]], ['outside', 'ok'])], [('regression #2', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[0, 5], [0, 9], [4, 9], [4, 5], [0, 5]]]], ['ok']), ('boundary #10', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[0, 0], [0, 20], [20, 20], [20, 0], [0, 0]]]], ['coincident']), ('boundary #11', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[0, 0], [5, 0], [0, 5], [0, 0]]]], ['coincident']), ('boundary #12', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[0, 0], [5, 3], [3, 5], [0, 0]]]], ['ok']), ('regression #13', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[22, 2], [22, 5], [25, 5], [25, 2], [22, 2]], [[2, 2], [2, 5], [5, 5], [5, 2], [2, 2]]]], ['outside', 'ok']), ('regression #14', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[-5, 2], [-5, 5], [3, 5], [3, 2], [-5, 2]], [[5, 5], [5, 9], [9, 9], [9, 5], [5, 5]], [[6, 6], [6, 7], [7, 7], [7, 6], [6, 6]]]], ['outside', 'ok', 'nested']), ('control #15', [[[0, 0], [20, 0], [10, 20], [0, 0]], [[[8, 4], [12, 4], [10, 8], [8, 4]]]], ['ok']), ('regression #16', [[[0, 0], [20, 0], [10, 20], [0, 0]], [[[8, 4], [12, 4], [10, 25], [8, 4]]]], ['outside'])], [('regression #2', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[0, 5], [0, 9], [4, 9], [4, 5], [0, 5]]]], ['ok']), ('regression #13', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[22, 2], [22, 5], [25, 5], [25, 2], [22, 2]], [[2, 2], [2, 5], [5, 5], [5, 2], [2, 2]]]], ['outside', 'ok']), ('regression #14', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[-5, 2], [-5, 5], [3, 5], [3, 2], [-5, 2]], [[5, 5], [5, 9], [9, 9], [9, 5], [5, 5]], [[6, 6], [6, 7], [7, 7], [7, 6], [6, 6]]]], ['outside', 'ok', 'nested']), ('control #15', [[[0, 0], [20, 0], [10, 20], [0, 0]], [[[8, 4], [12, 4], [10, 8], [8, 4]]]], ['ok']), ('regression #16', [[[0, 0], [20, 0], [10, 20], [0, 0]], [[[8, 4], [12, 4], [10, 25], [8, 4]]]], ['outside']), ('boundary #17', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[2, 2], [2, 6], [6, 6], [6, 2], [2, 2]], [[6, 2], [6, 6], [10, 6], [10, 2], [6, 2]]]], ['ok', 'ok']), ('control #18', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], []], []), ('regression #19', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[5, 5], [5, 10], [10, 10], [10, 5], [5, 5]], [[5, 5], [5, 8], [8, 8], [8, 5], [5, 5]]]], ['ok', 'nested'])]]\nfor label, args, expected in fixtures[N-1]:\n    check(label, solve(args), expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"},"fixed":{"sha256":"4b4d6527e029c8f53f776388c897f7ed29200f8ca968d021d4faa246fd55b448","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\nimport math\nN = 1\nobservations = []\ndef solve(x):\n    shell, holes = x\n    def cls(pt, ring):\n        px, py = pt\n        for a, b in zip(ring, ring[1:]):\n            if (b[0] - a[0]) * (py - a[1]) - (b[1] - a[1]) * (px - a[0]) == 0 and min(a[0], b[0]) <= px <= max(a[0], b[0]) and min(a[1], b[1]) <= py <= max(a[1], b[1]):\n                return 0\n        c = False\n        for a, b in zip(ring, ring[1:]):\n            if (a[1] > py) != (b[1] > py) and px < a[0] + (py - a[1]) * (b[0] - a[0]) / (b[1] - a[1]):\n                c = not c\n        return 1 if c else -1\n    out = []\n    for i, h in enumerate(holes):\n        vs = h[:-1]\n        if any(cls(p, shell) < 0 for p in vs):\n            out.append('outside')\n            continue\n        if all(cls(p, shell) == 0 for p in vs):\n            out.append('coincident')\n            continue\n        nested = False\n        for j, g in enumerate(holes):\n            if j != i and all(cls(p, g) >= 0 for p in vs) and any(cls(p, g) > 0 for p in vs):\n                nested = True\n        out.append('nested' if nested else 'ok')\n    return out\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[('control #0', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[2, 2], [2, 5], [5, 5], [5, 2], [2, 2]]]], ['ok']), ('control #1', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[2, 2], [2, 5], [5, 5], [5, 2], [2, 2]], [[8, 8], [8, 12], [12, 12], [12, 8], [8, 8]]]], ['ok', 'ok']), ('regression #2', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[0, 5], [0, 9], [4, 9], [4, 5], [0, 5]]]], ['ok']), ('regression #3', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[18, 18], [18, 25], [25, 25], [25, 18], [18, 18]]]], ['outside']), ('regression #4', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[5, 5], [30, 10], [5, 15], [5, 5]]]], ['outside']), ('regression #5', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[25, 10], [10, 5], [10, 15], [25, 10]]]], ['outside']), ('regression #6', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[2, 2], [2, 12], [12, 12], [12, 2], [2, 2]], [[4, 4], [4, 6], [6, 6], [6, 4], [4, 4]]]], ['ok', 'nested']), ('regression #7', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[4, 4], [4, 6], [6, 6], [6, 4], [4, 4]], [[2, 2], [2, 12], [12, 12], [12, 2], [2, 2]], [[14, 2], [14, 5], [18, 5], [18, 2], [14, 2]]]], ['nested', 'ok', 'ok'])], [('regression #2', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[0, 5], [0, 9], [4, 9], [4, 5], [0, 5]]]], ['ok']), ('regression #4', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[5, 5], [30, 10], [5, 15], [5, 5]]]], ['outside']), ('regression #5', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[25, 10], [10, 5], [10, 15], [25, 10]]]], ['outside']), ('regression #6', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[2, 2], [2, 12], [12, 12], [12, 2], [2, 2]], [[4, 4], [4, 6], [6, 6], [6, 4], [4, 4]]]], ['ok', 'nested']), ('regression #7', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[4, 4], [4, 6], [6, 6], [6, 4], [4, 4]], [[2, 2], [2, 12], [12, 12], [12, 2], [2, 2]], [[14, 2], [14, 5], [18, 5], [18, 2], [14, 2]]]], ['nested', 'ok', 'ok']), ('regression #8', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[2, 2], [2, 8], [8, 8], [8, 2], [2, 2]], [[6, 6], [6, 12], [12, 12], [12, 6], [6, 6]]]], ['ok', 'ok']), ('boundary #9', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[2, 2], [2, 8], [8, 8], [8, 2], [2, 2]], [[2, 2], [2, 8], [8, 8], [8, 2], [2, 2]]]], ['ok', 'ok']), ('boundary #12', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[0, 0], [5, 3], [3, 5], [0, 0]]]], ['ok'])], [('regression #2', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[0, 5], [0, 9], [4, 9], [4, 5], [0, 5]]]], ['ok']), ('regression #7', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[4, 4], [4, 6], [6, 6], [6, 4], [4, 4]], [[2, 2], [2, 12], [12, 12], [12, 2], [2, 2]], [[14, 2], [14, 5], [18, 5], [18, 2], [14, 2]]]], ['nested', 'ok', 'ok']), ('regression #8', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[2, 2], [2, 8], [8, 8], [8, 2], [2, 2]], [[6, 6], [6, 12], [12, 12], [12, 6], [6, 6]]]], ['ok', 'ok']), ('boundary #9', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[2, 2], [2, 8], [8, 8], [8, 2], [2, 2]], [[2, 2], [2, 8], [8, 8], [8, 2], [2, 2]]]], ['ok', 'ok']), ('boundary #10', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[0, 0], [0, 20], [20, 20], [20, 0], [0, 0]]]], ['coincident']), ('boundary #11', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[0, 0], [5, 0], [0, 5], [0, 0]]]], ['coincident']), ('boundary #12', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[0, 0], [5, 3], [3, 5], [0, 0]]]], ['ok']), ('regression #13', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[22, 2], [22, 5], [25, 5], [25, 2], [22, 2]], [[2, 2], [2, 5], [5, 5], [5, 2], [2, 2]]]], ['outside', 'ok'])], [('regression #2', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[0, 5], [0, 9], [4, 9], [4, 5], [0, 5]]]], ['ok']), ('boundary #10', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[0, 0], [0, 20], [20, 20], [20, 0], [0, 0]]]], ['coincident']), ('boundary #11', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[0, 0], [5, 0], [0, 5], [0, 0]]]], ['coincident']), ('boundary #12', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[0, 0], [5, 3], [3, 5], [0, 0]]]], ['ok']), ('regression #13', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[22, 2], [22, 5], [25, 5], [25, 2], [22, 2]], [[2, 2], [2, 5], [5, 5], [5, 2], [2, 2]]]], ['outside', 'ok']), ('regression #14', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[-5, 2], [-5, 5], [3, 5], [3, 2], [-5, 2]], [[5, 5], [5, 9], [9, 9], [9, 5], [5, 5]], [[6, 6], [6, 7], [7, 7], [7, 6], [6, 6]]]], ['outside', 'ok', 'nested']), ('control #15', [[[0, 0], [20, 0], [10, 20], [0, 0]], [[[8, 4], [12, 4], [10, 8], [8, 4]]]], ['ok']), ('regression #16', [[[0, 0], [20, 0], [10, 20], [0, 0]], [[[8, 4], [12, 4], [10, 25], [8, 4]]]], ['outside'])], [('regression #2', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[0, 5], [0, 9], [4, 9], [4, 5], [0, 5]]]], ['ok']), ('regression #13', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[22, 2], [22, 5], [25, 5], [25, 2], [22, 2]], [[2, 2], [2, 5], [5, 5], [5, 2], [2, 2]]]], ['outside', 'ok']), ('regression #14', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[-5, 2], [-5, 5], [3, 5], [3, 2], [-5, 2]], [[5, 5], [5, 9], [9, 9], [9, 5], [5, 5]], [[6, 6], [6, 7], [7, 7], [7, 6], [6, 6]]]], ['outside', 'ok', 'nested']), ('control #15', [[[0, 0], [20, 0], [10, 20], [0, 0]], [[[8, 4], [12, 4], [10, 8], [8, 4]]]], ['ok']), ('regression #16', [[[0, 0], [20, 0], [10, 20], [0, 0]], [[[8, 4], [12, 4], [10, 25], [8, 4]]]], ['outside']), ('boundary #17', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[2, 2], [2, 6], [6, 6], [6, 2], [2, 2]], [[6, 2], [6, 6], [10, 6], [10, 2], [6, 2]]]], ['ok', 'ok']), ('control #18', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], []], []), ('regression #19', [[[0, 0], [20, 0], [20, 20], [0, 20], [0, 0]], [[[5, 5], [5, 10], [10, 10], [10, 5], [5, 5]], [[5, 5], [5, 8], [8, 8], [8, 5], [5, 5]]]], ['ok', 'nested'])]]\nfor label, args, expected in fixtures[N-1]:\n    check(label, solve(args), expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"}},"limitations":"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.","method":"Deterministic executable model with adversarial boundary fixtures.","provenance":{"created_by":"Failure Map","dependencies":"Python standard library","family":"w2-gis-polygon-topology-hole-containment-validation-coincident-hole-detection","generated_at":"2026-09-29T14:48:21.799623+00:00","license":"CC0-1.0","python":"3.12.14","seed":1,"split":"open-access"},"relevance":"Polygon validity rules require holes to lie inside the shell and not inside each other; mislabelled holes block valid data or let invalid parcels through.","repair":"At the coincident hole detection step restore `if all(cls(p, shell) == 0 for p in vs):`, leaving the rest of the model unchanged.","root_cause":"Coincidence is decided from the first vertex only.","sha256":"8f4e16d3ad0b6da3fa3656050dbfbe66f3e9d5f7e1d1d5a68711928e0a3b1861","title":"Hole placement validation against shell and siblings: coincident hole detection · case 01","variant":1,"variant_policy":"Five numbered records share a model and may reuse boundary fixtures.","verification":{"attempt":{"elapsed_ms":40.704,"exit_code":1,"observations":[{"actual":["ok"],"check":"control #0","expected":["ok"],"passed":true},{"actual":["ok","ok"],"check":"control #1","expected":["ok","ok"],"passed":true},{"actual":["coincident"],"check":"regression #2","expected":["ok"],"passed":false},{"actual":["outside"],"check":"regression #3","expected":["outside"],"passed":true},{"actual":["outside"],"check":"regression #4","expected":["outside"],"passed":true},{"actual":["outside"],"check":"regression #5","expected":["outside"],"passed":true},{"actual":["ok","nested"],"check":"regression #6","expected":["ok","nested"],"passed":true},{"actual":["nested","ok","ok"],"check":"regression #7","expected":["nested","ok","ok"],"passed":true}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"control #0\", \"actual\": [\"ok\"], \"expected\": [\"ok\"], \"passed\": true}, {\"check\": \"control #1\", \"actual\": [\"ok\", \"ok\"], \"expected\": [\"ok\", \"ok\"], \"passed\": true}, {\"check\": \"regression #2\", \"actual\": [\"coincident\"], \"expected\": [\"ok\"], \"passed\": false}, {\"check\": \"regression #3\", \"actual\": [\"outside\"], \"expected\": [\"outside\"], \"passed\": true}, {\"check\": \"regression #4\", \"actual\": [\"outside\"], \"expected\": [\"outside\"], \"passed\": true}, {\"check\": \"regression #5\", \"actual\": [\"outside\"], \"expected\": [\"outside\"], \"passed\": true}, {\"check\": \"regression #6\", \"actual\": [\"ok\", \"nested\"], \"expected\": [\"ok\", \"nested\"], \"passed\": true}, {\"check\": \"regression #7\", \"actual\": [\"nested\", \"ok\", \"ok\"], \"expected\": [\"nested\", \"ok\", \"ok\"], \"passed\": true}], \"passed\": false}\n"},"broken":{"elapsed_ms":39.383,"exit_code":1,"observations":[{"actual":["ok"],"check":"control #0","expected":["ok"],"passed":true},{"actual":["ok","ok"],"check":"control #1","expected":["ok","ok"],"passed":true},{"actual":["coincident"],"check":"regression #2","expected":["ok"],"passed":false},{"actual":["outside"],"check":"regression #3","expected":["outside"],"passed":true},{"actual":["outside"],"check":"regression #4","expected":["outside"],"passed":true},{"actual":["outside"],"check":"regression #5","expected":["outside"],"passed":true},{"actual":["ok","nested"],"check":"regression #6","expected":["ok","nested"],"passed":true},{"actual":["nested","ok","ok"],"check":"regression #7","expected":["nested","ok","ok"],"passed":true}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"control #0\", \"actual\": [\"ok\"], \"expected\": [\"ok\"], \"passed\": true}, {\"check\": \"control #1\", \"actual\": [\"ok\", \"ok\"], \"expected\": [\"ok\", \"ok\"], \"passed\": true}, {\"check\": \"regression #2\", \"actual\": [\"coincident\"], \"expected\": [\"ok\"], \"passed\": false}, {\"check\": \"regression #3\", \"actual\": [\"outside\"], \"expected\": [\"outside\"], \"passed\": true}, {\"check\": \"regression #4\", \"actual\": [\"outside\"], \"expected\": [\"outside\"], \"passed\": true}, {\"check\": \"regression #5\", \"actual\": [\"outside\"], \"expected\": [\"outside\"], \"passed\": true}, {\"check\": \"regression #6\", \"actual\": [\"ok\", \"nested\"], \"expected\": [\"ok\", \"nested\"], \"passed\": true}, {\"check\": \"regression #7\", \"actual\": [\"nested\", \"ok\", \"ok\"], \"expected\": [\"nested\", \"ok\", \"ok\"], \"passed\": true}], \"passed\": false}\n"},"fixed":{"elapsed_ms":39.653,"exit_code":0,"observations":[{"actual":["ok"],"check":"control #0","expected":["ok"],"passed":true},{"actual":["ok","ok"],"check":"control #1","expected":["ok","ok"],"passed":true},{"actual":["ok"],"check":"regression #2","expected":["ok"],"passed":true},{"actual":["outside"],"check":"regression #3","expected":["outside"],"passed":true},{"actual":["outside"],"check":"regression #4","expected":["outside"],"passed":true},{"actual":["outside"],"check":"regression #5","expected":["outside"],"passed":true},{"actual":["ok","nested"],"check":"regression #6","expected":["ok","nested"],"passed":true},{"actual":["nested","ok","ok"],"check":"regression #7","expected":["nested","ok","ok"],"passed":true}],"passed":true,"stderr":"","stdout":"{\"observations\": [{\"check\": \"control #0\", \"actual\": [\"ok\"], \"expected\": [\"ok\"], \"passed\": true}, {\"check\": \"control #1\", \"actual\": [\"ok\", \"ok\"], \"expected\": [\"ok\", \"ok\"], \"passed\": true}, {\"check\": \"regression #2\", \"actual\": [\"ok\"], \"expected\": [\"ok\"], \"passed\": true}, {\"check\": \"regression #3\", \"actual\": [\"outside\"], \"expected\": [\"outside\"], \"passed\": true}, {\"check\": \"regression #4\", \"actual\": [\"outside\"], \"expected\": [\"outside\"], \"passed\": true}, {\"check\": \"regression #5\", \"actual\": [\"outside\"], \"expected\": [\"outside\"], \"passed\": true}, {\"check\": \"regression #6\", \"actual\": [\"ok\", \"nested\"], \"expected\": [\"ok\", \"nested\"], \"passed\": true}, {\"check\": \"regression #7\", \"actual\": [\"nested\", \"ok\", \"ok\"], \"expected\": [\"nested\", \"ok\", \"ok\"], \"passed\": true}], \"passed\": true}\n"}},"verified":true,"visibility":"public"}