{"abstract":"Lower-case WKT from some databases is rejected.","category":"GIS polygon topology","checks":8,"contract":"Input: a WKT string. The keyword (case-insensitive) must be POLYGON or MULTIPOLYGON, else None; \"<keyword> EMPTY\" returns []. Otherwise parse the parenthesised body into polygons -> rings -> positions, keeping only x and y of every position (Z/M ordinates are dropped). Every ring must have at least 4 positions and be closed in x/y, else None. Return a list of polygons (a POLYGON gives a one-element list).","evaluation_group":"w2-gis-polygon-topology-wkt-polygon-structure","failed_approach":"Only the geometry keyword is upper-cased; a lower-case EMPTY marker is still not recognised.","family":"w2-gis-polygon-topology-wkt-polygon-structure-keyword-case-folding","id":"FA-70716","implementations":{"attempt":{"sha256":"ae9eb68227865214ee9b7a4126a94b24c2f1ac1dd00afff29f734ec422cc3f47","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\nimport math\nN = 1\nobservations = []\ndef solve(x):\n    s = x.strip()\n    up = s.upper()\n    words = s.replace('(', ' ( ').split()\n    words[:1] = [w.upper() for w in words[:1]]\n    if not words or words[0] not in ('POLYGON', 'MULTIPOLYGON'):\n        return None\n    if len(words) == 2 and words[1] == 'EMPTY':\n        return []\n    if '(' not in s:\n        return None\n    body = s[s.index('('):]\n    stack = [[]]\n    cur = ''\n    for ch in body:\n        if ch == '(':\n            stack.append([])\n        elif ch in '),':\n            if cur.strip():\n                nums = [float(t) for t in cur.split()]\n                stack[-1].append(nums[:2])\n            cur = ''\n            if ch == ')':\n                done = stack.pop()\n                stack[-1].append(done)\n        else:\n            cur += ch\n    tree = stack[0][0]\n    polys = [tree] if words[0] == 'POLYGON' else tree\n    for poly in polys:\n        for ring in poly:\n            if len(ring) < 4 or ring[0] != ring[-1]:\n                return None\n    return polys\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[('control #0', 'POLYGON ((0 0, 4 0, 4 4, 0 4, 0 0))', [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 4.0], [0.0, 0.0]]]]), ('control #1', 'POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0), (2 2, 2 4, 4 4, 2 2))', [[[[0.0, 0.0], [10.0, 0.0], [10.0, 10.0], [0.0, 10.0], [0.0, 0.0]], [[2.0, 2.0], [2.0, 4.0], [4.0, 4.0], [2.0, 2.0]]]]), ('regression #2', 'POLYGON Z ((0 0 5, 4 0 5, 4 4 6, 0 0 5))', [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]]), ('regression #3', 'POLYGON ZM ((0 0 5 1, 4 0 5 2, 4 4 6 3, 0 0 5 1))', [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]]), ('regression #4', 'POLYGON M ((0 0 7, 4 0 8, 4 4 9, 0 0 7))', [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]]), ('boundary #5', 'POLYGON EMPTY', []), ('boundary #6', 'polygon empty', []), ('regression #7', 'MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)), ((5 5, 6 5, 6 6, 5 5), (5.2 5.1, 5.8 5.8, 5.8 5.1, 5.2 5.1)))', [[[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 0.0]]], [[[5.0, 5.0], [6.0, 5.0], [6.0, 6.0], [5.0, 5.0]], [[5.2, 5.1], [5.8, 5.8], [5.8, 5.1], [5.2, 5.1]]]])], [('regression #3', 'POLYGON ZM ((0 0 5 1, 4 0 5 2, 4 4 6 3, 0 0 5 1))', [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]]), ('regression #4', 'POLYGON M ((0 0 7, 4 0 8, 4 4 9, 0 0 7))', [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]]), ('boundary #5', 'POLYGON EMPTY', []), ('boundary #6', 'polygon empty', []), ('regression #7', 'MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)), ((5 5, 6 5, 6 6, 5 5), (5.2 5.1, 5.8 5.8, 5.8 5.1, 5.2 5.1)))', [[[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 0.0]]], [[[5.0, 5.0], [6.0, 5.0], [6.0, 6.0], [5.0, 5.0]], [[5.2, 5.1], [5.8, 5.8], [5.8, 5.1], [5.2, 5.1]]]]), ('regression #8', 'MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)))', [[[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 0.0]]]]), ('regression #9', 'multipolygon (((-1.5 -2, 3e2 0, 0 1e1, -1.5 -2)))', [[[[-1.5, -2.0], [300.0, 0.0], [0.0, 10.0], [-1.5, -2.0]]]]), ('boundary #10', 'POLYGON ((0 0, 4 0, 4 4, 0 1))', None)], [('boundary #6', 'polygon empty', []), ('regression #7', 'MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)), ((5 5, 6 5, 6 6, 5 5), (5.2 5.1, 5.8 5.8, 5.8 5.1, 5.2 5.1)))', [[[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 0.0]]], [[[5.0, 5.0], [6.0, 5.0], [6.0, 6.0], [5.0, 5.0]], [[5.2, 5.1], [5.8, 5.8], [5.8, 5.1], [5.2, 5.1]]]]), ('regression #8', 'MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)))', [[[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 0.0]]]]), ('regression #9', 'multipolygon (((-1.5 -2, 3e2 0, 0 1e1, -1.5 -2)))', [[[[-1.5, -2.0], [300.0, 0.0], [0.0, 10.0], [-1.5, -2.0]]]]), ('boundary #10', 'POLYGON ((0 0, 4 0, 4 4, 0 1))', None), ('boundary #11', 'POLYGON ((0 0, 4 0, 0 0))', None), ('control #12', 'Polygon((1 1,5 1,5 5,1 1))', [[[[1.0, 1.0], [5.0, 1.0], [5.0, 5.0], [1.0, 1.0]]]]), ('boundary #13', 'LINESTRING (0 0, 1 1)', None)], [('boundary #6', 'polygon empty', []), ('boundary #10', 'POLYGON ((0 0, 4 0, 4 4, 0 1))', None), ('boundary #11', 'POLYGON ((0 0, 4 0, 0 0))', None), ('control #12', 'Polygon((1 1,5 1,5 5,1 1))', [[[[1.0, 1.0], [5.0, 1.0], [5.0, 5.0], [1.0, 1.0]]]]), ('boundary #13', 'LINESTRING (0 0, 1 1)', None), ('boundary #14', 'MULTIPOLYGON EMPTY', []), ('control #15', '  POLYGON ((0 0, -3 0, -3 -3, 0 0))  ', [[[[0.0, 0.0], [-3.0, 0.0], [-3.0, -3.0], [0.0, 0.0]]]]), ('regression #16', 'MULTIPOLYGON Z (((0 0 1, 2 0 1, 2 2 1, 0 0 1)), ((9 9 0, 8 9 0, 8 8 0, 9 9 0)))', [[[[0.0, 0.0], [2.0, 0.0], [2.0, 2.0], [0.0, 0.0]]], [[[9.0, 9.0], [8.0, 9.0], [8.0, 8.0], [9.0, 9.0]]]])], [('control #0', 'POLYGON ((0 0, 4 0, 4 4, 0 4, 0 0))', [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 4.0], [0.0, 0.0]]]]), ('control #1', 'POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0), (2 2, 2 4, 4 4, 2 2))', [[[[0.0, 0.0], [10.0, 0.0], [10.0, 10.0], [0.0, 10.0], [0.0, 0.0]], [[2.0, 2.0], [2.0, 4.0], [4.0, 4.0], [2.0, 2.0]]]]), ('boundary #6', 'polygon empty', []), ('regression #9', 'multipolygon (((-1.5 -2, 3e2 0, 0 1e1, -1.5 -2)))', [[[[-1.5, -2.0], [300.0, 0.0], [0.0, 10.0], [-1.5, -2.0]]]]), ('boundary #14', 'MULTIPOLYGON EMPTY', []), ('control #15', '  POLYGON ((0 0, -3 0, -3 -3, 0 0))  ', [[[[0.0, 0.0], [-3.0, 0.0], [-3.0, -3.0], [0.0, 0.0]]]]), ('regression #16', 'MULTIPOLYGON Z (((0 0 1, 2 0 1, 2 2 1, 0 0 1)), ((9 9 0, 8 9 0, 8 8 0, 9 9 0)))', [[[[0.0, 0.0], [2.0, 0.0], [2.0, 2.0], [0.0, 0.0]]], [[[9.0, 9.0], [8.0, 9.0], [8.0, 8.0], [9.0, 9.0]]]]), ('boundary #17', 'POLYGON ((0 0 1, 4 0 1, 4 4 1, 0 0 2))', [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]])]]\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":"4fbf1f0fd1494d072021f3557fa8245e0246aa47d6ae3932d7f9c90a5dea14ed","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\nimport math\nN = 1\nobservations = []\ndef solve(x):\n    s = x.strip()\n    up = s.upper()\n    words = s.replace('(', ' ( ').split()\n    if not words or words[0] not in ('POLYGON', 'MULTIPOLYGON'):\n        return None\n    if len(words) == 2 and words[1] == 'EMPTY':\n        return []\n    if '(' not in s:\n        return None\n    body = s[s.index('('):]\n    stack = [[]]\n    cur = ''\n    for ch in body:\n        if ch == '(':\n            stack.append([])\n        elif ch in '),':\n            if cur.strip():\n                nums = [float(t) for t in cur.split()]\n                stack[-1].append(nums[:2])\n            cur = ''\n            if ch == ')':\n                done = stack.pop()\n                stack[-1].append(done)\n        else:\n            cur += ch\n    tree = stack[0][0]\n    polys = [tree] if words[0] == 'POLYGON' else tree\n    for poly in polys:\n        for ring in poly:\n            if len(ring) < 4 or ring[0] != ring[-1]:\n                return None\n    return polys\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[('control #0', 'POLYGON ((0 0, 4 0, 4 4, 0 4, 0 0))', [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 4.0], [0.0, 0.0]]]]), ('control #1', 'POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0), (2 2, 2 4, 4 4, 2 2))', [[[[0.0, 0.0], [10.0, 0.0], [10.0, 10.0], [0.0, 10.0], [0.0, 0.0]], [[2.0, 2.0], [2.0, 4.0], [4.0, 4.0], [2.0, 2.0]]]]), ('regression #2', 'POLYGON Z ((0 0 5, 4 0 5, 4 4 6, 0 0 5))', [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]]), ('regression #3', 'POLYGON ZM ((0 0 5 1, 4 0 5 2, 4 4 6 3, 0 0 5 1))', [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]]), ('regression #4', 'POLYGON M ((0 0 7, 4 0 8, 4 4 9, 0 0 7))', [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]]), ('boundary #5', 'POLYGON EMPTY', []), ('boundary #6', 'polygon empty', []), ('regression #7', 'MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)), ((5 5, 6 5, 6 6, 5 5), (5.2 5.1, 5.8 5.8, 5.8 5.1, 5.2 5.1)))', [[[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 0.0]]], [[[5.0, 5.0], [6.0, 5.0], [6.0, 6.0], [5.0, 5.0]], [[5.2, 5.1], [5.8, 5.8], [5.8, 5.1], [5.2, 5.1]]]])], [('regression #3', 'POLYGON ZM ((0 0 5 1, 4 0 5 2, 4 4 6 3, 0 0 5 1))', [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]]), ('regression #4', 'POLYGON M ((0 0 7, 4 0 8, 4 4 9, 0 0 7))', [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]]), ('boundary #5', 'POLYGON EMPTY', []), ('boundary #6', 'polygon empty', []), ('regression #7', 'MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)), ((5 5, 6 5, 6 6, 5 5), (5.2 5.1, 5.8 5.8, 5.8 5.1, 5.2 5.1)))', [[[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 0.0]]], [[[5.0, 5.0], [6.0, 5.0], [6.0, 6.0], [5.0, 5.0]], [[5.2, 5.1], [5.8, 5.8], [5.8, 5.1], [5.2, 5.1]]]]), ('regression #8', 'MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)))', [[[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 0.0]]]]), ('regression #9', 'multipolygon (((-1.5 -2, 3e2 0, 0 1e1, -1.5 -2)))', [[[[-1.5, -2.0], [300.0, 0.0], [0.0, 10.0], [-1.5, -2.0]]]]), ('boundary #10', 'POLYGON ((0 0, 4 0, 4 4, 0 1))', None)], [('boundary #6', 'polygon empty', []), ('regression #7', 'MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)), ((5 5, 6 5, 6 6, 5 5), (5.2 5.1, 5.8 5.8, 5.8 5.1, 5.2 5.1)))', [[[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 0.0]]], [[[5.0, 5.0], [6.0, 5.0], [6.0, 6.0], [5.0, 5.0]], [[5.2, 5.1], [5.8, 5.8], [5.8, 5.1], [5.2, 5.1]]]]), ('regression #8', 'MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)))', [[[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 0.0]]]]), ('regression #9', 'multipolygon (((-1.5 -2, 3e2 0, 0 1e1, -1.5 -2)))', [[[[-1.5, -2.0], [300.0, 0.0], [0.0, 10.0], [-1.5, -2.0]]]]), ('boundary #10', 'POLYGON ((0 0, 4 0, 4 4, 0 1))', None), ('boundary #11', 'POLYGON ((0 0, 4 0, 0 0))', None), ('control #12', 'Polygon((1 1,5 1,5 5,1 1))', [[[[1.0, 1.0], [5.0, 1.0], [5.0, 5.0], [1.0, 1.0]]]]), ('boundary #13', 'LINESTRING (0 0, 1 1)', None)], [('boundary #6', 'polygon empty', []), ('boundary #10', 'POLYGON ((0 0, 4 0, 4 4, 0 1))', None), ('boundary #11', 'POLYGON ((0 0, 4 0, 0 0))', None), ('control #12', 'Polygon((1 1,5 1,5 5,1 1))', [[[[1.0, 1.0], [5.0, 1.0], [5.0, 5.0], [1.0, 1.0]]]]), ('boundary #13', 'LINESTRING (0 0, 1 1)', None), ('boundary #14', 'MULTIPOLYGON EMPTY', []), ('control #15', '  POLYGON ((0 0, -3 0, -3 -3, 0 0))  ', [[[[0.0, 0.0], [-3.0, 0.0], [-3.0, -3.0], [0.0, 0.0]]]]), ('regression #16', 'MULTIPOLYGON Z (((0 0 1, 2 0 1, 2 2 1, 0 0 1)), ((9 9 0, 8 9 0, 8 8 0, 9 9 0)))', [[[[0.0, 0.0], [2.0, 0.0], [2.0, 2.0], [0.0, 0.0]]], [[[9.0, 9.0], [8.0, 9.0], [8.0, 8.0], [9.0, 9.0]]]])], [('control #0', 'POLYGON ((0 0, 4 0, 4 4, 0 4, 0 0))', [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 4.0], [0.0, 0.0]]]]), ('control #1', 'POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0), (2 2, 2 4, 4 4, 2 2))', [[[[0.0, 0.0], [10.0, 0.0], [10.0, 10.0], [0.0, 10.0], [0.0, 0.0]], [[2.0, 2.0], [2.0, 4.0], [4.0, 4.0], [2.0, 2.0]]]]), ('boundary #6', 'polygon empty', []), ('regression #9', 'multipolygon (((-1.5 -2, 3e2 0, 0 1e1, -1.5 -2)))', [[[[-1.5, -2.0], [300.0, 0.0], [0.0, 10.0], [-1.5, -2.0]]]]), ('boundary #14', 'MULTIPOLYGON EMPTY', []), ('control #15', '  POLYGON ((0 0, -3 0, -3 -3, 0 0))  ', [[[[0.0, 0.0], [-3.0, 0.0], [-3.0, -3.0], [0.0, 0.0]]]]), ('regression #16', 'MULTIPOLYGON Z (((0 0 1, 2 0 1, 2 2 1, 0 0 1)), ((9 9 0, 8 9 0, 8 8 0, 9 9 0)))', [[[[0.0, 0.0], [2.0, 0.0], [2.0, 2.0], [0.0, 0.0]]], [[[9.0, 9.0], [8.0, 9.0], [8.0, 8.0], [9.0, 9.0]]]]), ('boundary #17', 'POLYGON ((0 0 1, 4 0 1, 4 4 1, 0 0 2))', [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]])]]\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":"ab178526a29e27f5ebc61439dd66c6903fc5eb9bde7abac5392cca56c2a0a09e","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\nimport math\nN = 1\nobservations = []\ndef solve(x):\n    s = x.strip()\n    up = s.upper()\n    words = up.replace('(', ' ( ').split()\n    if not words or words[0] not in ('POLYGON', 'MULTIPOLYGON'):\n        return None\n    if len(words) == 2 and words[1] == 'EMPTY':\n        return []\n    if '(' not in s:\n        return None\n    body = s[s.index('('):]\n    stack = [[]]\n    cur = ''\n    for ch in body:\n        if ch == '(':\n            stack.append([])\n        elif ch in '),':\n            if cur.strip():\n                nums = [float(t) for t in cur.split()]\n                stack[-1].append(nums[:2])\n            cur = ''\n            if ch == ')':\n                done = stack.pop()\n                stack[-1].append(done)\n        else:\n            cur += ch\n    tree = stack[0][0]\n    polys = [tree] if words[0] == 'POLYGON' else tree\n    for poly in polys:\n        for ring in poly:\n            if len(ring) < 4 or ring[0] != ring[-1]:\n                return None\n    return polys\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[('control #0', 'POLYGON ((0 0, 4 0, 4 4, 0 4, 0 0))', [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 4.0], [0.0, 0.0]]]]), ('control #1', 'POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0), (2 2, 2 4, 4 4, 2 2))', [[[[0.0, 0.0], [10.0, 0.0], [10.0, 10.0], [0.0, 10.0], [0.0, 0.0]], [[2.0, 2.0], [2.0, 4.0], [4.0, 4.0], [2.0, 2.0]]]]), ('regression #2', 'POLYGON Z ((0 0 5, 4 0 5, 4 4 6, 0 0 5))', [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]]), ('regression #3', 'POLYGON ZM ((0 0 5 1, 4 0 5 2, 4 4 6 3, 0 0 5 1))', [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]]), ('regression #4', 'POLYGON M ((0 0 7, 4 0 8, 4 4 9, 0 0 7))', [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]]), ('boundary #5', 'POLYGON EMPTY', []), ('boundary #6', 'polygon empty', []), ('regression #7', 'MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)), ((5 5, 6 5, 6 6, 5 5), (5.2 5.1, 5.8 5.8, 5.8 5.1, 5.2 5.1)))', [[[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 0.0]]], [[[5.0, 5.0], [6.0, 5.0], [6.0, 6.0], [5.0, 5.0]], [[5.2, 5.1], [5.8, 5.8], [5.8, 5.1], [5.2, 5.1]]]])], [('regression #3', 'POLYGON ZM ((0 0 5 1, 4 0 5 2, 4 4 6 3, 0 0 5 1))', [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]]), ('regression #4', 'POLYGON M ((0 0 7, 4 0 8, 4 4 9, 0 0 7))', [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]]), ('boundary #5', 'POLYGON EMPTY', []), ('boundary #6', 'polygon empty', []), ('regression #7', 'MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)), ((5 5, 6 5, 6 6, 5 5), (5.2 5.1, 5.8 5.8, 5.8 5.1, 5.2 5.1)))', [[[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 0.0]]], [[[5.0, 5.0], [6.0, 5.0], [6.0, 6.0], [5.0, 5.0]], [[5.2, 5.1], [5.8, 5.8], [5.8, 5.1], [5.2, 5.1]]]]), ('regression #8', 'MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)))', [[[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 0.0]]]]), ('regression #9', 'multipolygon (((-1.5 -2, 3e2 0, 0 1e1, -1.5 -2)))', [[[[-1.5, -2.0], [300.0, 0.0], [0.0, 10.0], [-1.5, -2.0]]]]), ('boundary #10', 'POLYGON ((0 0, 4 0, 4 4, 0 1))', None)], [('boundary #6', 'polygon empty', []), ('regression #7', 'MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)), ((5 5, 6 5, 6 6, 5 5), (5.2 5.1, 5.8 5.8, 5.8 5.1, 5.2 5.1)))', [[[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 0.0]]], [[[5.0, 5.0], [6.0, 5.0], [6.0, 6.0], [5.0, 5.0]], [[5.2, 5.1], [5.8, 5.8], [5.8, 5.1], [5.2, 5.1]]]]), ('regression #8', 'MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)))', [[[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 0.0]]]]), ('regression #9', 'multipolygon (((-1.5 -2, 3e2 0, 0 1e1, -1.5 -2)))', [[[[-1.5, -2.0], [300.0, 0.0], [0.0, 10.0], [-1.5, -2.0]]]]), ('boundary #10', 'POLYGON ((0 0, 4 0, 4 4, 0 1))', None), ('boundary #11', 'POLYGON ((0 0, 4 0, 0 0))', None), ('control #12', 'Polygon((1 1,5 1,5 5,1 1))', [[[[1.0, 1.0], [5.0, 1.0], [5.0, 5.0], [1.0, 1.0]]]]), ('boundary #13', 'LINESTRING (0 0, 1 1)', None)], [('boundary #6', 'polygon empty', []), ('boundary #10', 'POLYGON ((0 0, 4 0, 4 4, 0 1))', None), ('boundary #11', 'POLYGON ((0 0, 4 0, 0 0))', None), ('control #12', 'Polygon((1 1,5 1,5 5,1 1))', [[[[1.0, 1.0], [5.0, 1.0], [5.0, 5.0], [1.0, 1.0]]]]), ('boundary #13', 'LINESTRING (0 0, 1 1)', None), ('boundary #14', 'MULTIPOLYGON EMPTY', []), ('control #15', '  POLYGON ((0 0, -3 0, -3 -3, 0 0))  ', [[[[0.0, 0.0], [-3.0, 0.0], [-3.0, -3.0], [0.0, 0.0]]]]), ('regression #16', 'MULTIPOLYGON Z (((0 0 1, 2 0 1, 2 2 1, 0 0 1)), ((9 9 0, 8 9 0, 8 8 0, 9 9 0)))', [[[[0.0, 0.0], [2.0, 0.0], [2.0, 2.0], [0.0, 0.0]]], [[[9.0, 9.0], [8.0, 9.0], [8.0, 8.0], [9.0, 9.0]]]])], [('control #0', 'POLYGON ((0 0, 4 0, 4 4, 0 4, 0 0))', [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 4.0], [0.0, 0.0]]]]), ('control #1', 'POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0), (2 2, 2 4, 4 4, 2 2))', [[[[0.0, 0.0], [10.0, 0.0], [10.0, 10.0], [0.0, 10.0], [0.0, 0.0]], [[2.0, 2.0], [2.0, 4.0], [4.0, 4.0], [2.0, 2.0]]]]), ('boundary #6', 'polygon empty', []), ('regression #9', 'multipolygon (((-1.5 -2, 3e2 0, 0 1e1, -1.5 -2)))', [[[[-1.5, -2.0], [300.0, 0.0], [0.0, 10.0], [-1.5, -2.0]]]]), ('boundary #14', 'MULTIPOLYGON EMPTY', []), ('control #15', '  POLYGON ((0 0, -3 0, -3 -3, 0 0))  ', [[[[0.0, 0.0], [-3.0, 0.0], [-3.0, -3.0], [0.0, 0.0]]]]), ('regression #16', 'MULTIPOLYGON Z (((0 0 1, 2 0 1, 2 2 1, 0 0 1)), ((9 9 0, 8 9 0, 8 8 0, 9 9 0)))', [[[[0.0, 0.0], [2.0, 0.0], [2.0, 2.0], [0.0, 0.0]]], [[[9.0, 9.0], [8.0, 9.0], [8.0, 8.0], [9.0, 9.0]]]]), ('boundary #17', 'POLYGON ((0 0 1, 4 0 1, 4 4 1, 0 0 2))', [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]])]]\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-wkt-polygon-structure-keyword-case-folding","generated_at":"2026-09-29T14:48:23.195390+00:00","license":"CC0-1.0","python":"3.12.14","seed":1,"split":"open-access"},"relevance":"WKT is the lingua franca between databases and GIS tools; losing a dimension or nesting level corrupts rings.","repair":"At the keyword case folding step restore `words = up.replace('(', ' ( ').split()`, leaving the rest of the model unchanged.","root_cause":"Keywords are compared case-sensitively.","sha256":"4dc392042d907804a8658f7a1583e1b5b2fc076b0d33f183682b822ead456cbe","title":"WKT polygon and multipolygon ring structure: keyword case folding · case 01","variant":1,"variant_policy":"Five numbered records share a model and may reuse boundary fixtures.","verification":{"attempt":{"elapsed_ms":38.995,"exit_code":1,"observations":[{"actual":[[[[0.0,0.0],[4.0,0.0],[4.0,4.0],[0.0,4.0],[0.0,0.0]]]],"check":"control #0","expected":[[[[0.0,0.0],[4.0,0.0],[4.0,4.0],[0.0,4.0],[0.0,0.0]]]],"passed":true},{"actual":[[[[0.0,0.0],[10.0,0.0],[10.0,10.0],[0.0,10.0],[0.0,0.0]],[[2.0,2.0],[2.0,4.0],[4.0,4.0],[2.0,2.0]]]],"check":"control #1","expected":[[[[0.0,0.0],[10.0,0.0],[10.0,10.0],[0.0,10.0],[0.0,0.0]],[[2.0,2.0],[2.0,4.0],[4.0,4.0],[2.0,2.0]]]],"passed":true},{"actual":[[[[0.0,0.0],[4.0,0.0],[4.0,4.0],[0.0,0.0]]]],"check":"regression #2","expected":[[[[0.0,0.0],[4.0,0.0],[4.0,4.0],[0.0,0.0]]]],"passed":true},{"actual":[[[[0.0,0.0],[4.0,0.0],[4.0,4.0],[0.0,0.0]]]],"check":"regression #3","expected":[[[[0.0,0.0],[4.0,0.0],[4.0,4.0],[0.0,0.0]]]],"passed":true},{"actual":[[[[0.0,0.0],[4.0,0.0],[4.0,4.0],[0.0,0.0]]]],"check":"regression #4","expected":[[[[0.0,0.0],[4.0,0.0],[4.0,4.0],[0.0,0.0]]]],"passed":true},{"actual":[],"check":"boundary #5","expected":[],"passed":true},{"actual":null,"check":"boundary #6","expected":[],"passed":false},{"actual":[[[[0.0,0.0],[1.0,0.0],[1.0,1.0],[0.0,0.0]]],[[[5.0,5.0],[6.0,5.0],[6.0,6.0],[5.0,5.0]],[[5.2,5.1],[5.8,5.8],[5.8,5.1],[5.2,5.1]]]],"check":"regression #7","expected":[[[[0.0,0.0],[1.0,0.0],[1.0,1.0],[0.0,0.0]]],[[[5.0,5.0],[6.0,5.0],[6.0,6.0],[5.0,5.0]],[[5.2,5.1],[5.8,5.8],[5.8,5.1],[5.2,5.1]]]],"passed":true}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"control #0\", \"actual\": [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 4.0], [0.0, 0.0]]]], \"expected\": [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 4.0], [0.0, 0.0]]]], \"passed\": true}, {\"check\": \"control #1\", \"actual\": [[[[0.0, 0.0], [10.0, 0.0], [10.0, 10.0], [0.0, 10.0], [0.0, 0.0]], [[2.0, 2.0], [2.0, 4.0], [4.0, 4.0], [2.0, 2.0]]]], \"expected\": [[[[0.0, 0.0], [10.0, 0.0], [10.0, 10.0], [0.0, 10.0], [0.0, 0.0]], [[2.0, 2.0], [2.0, 4.0], [4.0, 4.0], [2.0, 2.0]]]], \"passed\": true}, {\"check\": \"regression #2\", \"actual\": [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]], \"expected\": [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]], \"passed\": true}, {\"check\": \"regression #3\", \"actual\": [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]], \"expected\": [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]], \"passed\": true}, {\"check\": \"regression #4\", \"actual\": [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]], \"expected\": [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]], \"passed\": true}, {\"check\": \"boundary #5\", \"actual\": [], \"expected\": [], \"passed\": true}, {\"check\": \"boundary #6\", \"actual\": null, \"expected\": [], \"passed\": false}, {\"check\": \"regression #7\", \"actual\": [[[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 0.0]]], [[[5.0, 5.0], [6.0, 5.0], [6.0, 6.0], [5.0, 5.0]], [[5.2, 5.1], [5.8, 5.8], [5.8, 5.1], [5.2, 5.1]]]], \"expected\": [[[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 0.0]]], [[[5.0, 5.0], [6.0, 5.0], [6.0, 6.0], [5.0, 5.0]], [[5.2, 5.1], [5.8, 5.8], [5.8, 5.1], [5.2, 5.1]]]], \"passed\": true}], \"passed\": false}\n"},"broken":{"elapsed_ms":39.967,"exit_code":1,"observations":[{"actual":[[[[0.0,0.0],[4.0,0.0],[4.0,4.0],[0.0,4.0],[0.0,0.0]]]],"check":"control #0","expected":[[[[0.0,0.0],[4.0,0.0],[4.0,4.0],[0.0,4.0],[0.0,0.0]]]],"passed":true},{"actual":[[[[0.0,0.0],[10.0,0.0],[10.0,10.0],[0.0,10.0],[0.0,0.0]],[[2.0,2.0],[2.0,4.0],[4.0,4.0],[2.0,2.0]]]],"check":"control #1","expected":[[[[0.0,0.0],[10.0,0.0],[10.0,10.0],[0.0,10.0],[0.0,0.0]],[[2.0,2.0],[2.0,4.0],[4.0,4.0],[2.0,2.0]]]],"passed":true},{"actual":[[[[0.0,0.0],[4.0,0.0],[4.0,4.0],[0.0,0.0]]]],"check":"regression #2","expected":[[[[0.0,0.0],[4.0,0.0],[4.0,4.0],[0.0,0.0]]]],"passed":true},{"actual":[[[[0.0,0.0],[4.0,0.0],[4.0,4.0],[0.0,0.0]]]],"check":"regression #3","expected":[[[[0.0,0.0],[4.0,0.0],[4.0,4.0],[0.0,0.0]]]],"passed":true},{"actual":[[[[0.0,0.0],[4.0,0.0],[4.0,4.0],[0.0,0.0]]]],"check":"regression #4","expected":[[[[0.0,0.0],[4.0,0.0],[4.0,4.0],[0.0,0.0]]]],"passed":true},{"actual":[],"check":"boundary #5","expected":[],"passed":true},{"actual":null,"check":"boundary #6","expected":[],"passed":false},{"actual":[[[[0.0,0.0],[1.0,0.0],[1.0,1.0],[0.0,0.0]]],[[[5.0,5.0],[6.0,5.0],[6.0,6.0],[5.0,5.0]],[[5.2,5.1],[5.8,5.8],[5.8,5.1],[5.2,5.1]]]],"check":"regression #7","expected":[[[[0.0,0.0],[1.0,0.0],[1.0,1.0],[0.0,0.0]]],[[[5.0,5.0],[6.0,5.0],[6.0,6.0],[5.0,5.0]],[[5.2,5.1],[5.8,5.8],[5.8,5.1],[5.2,5.1]]]],"passed":true}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"control #0\", \"actual\": [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 4.0], [0.0, 0.0]]]], \"expected\": [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 4.0], [0.0, 0.0]]]], \"passed\": true}, {\"check\": \"control #1\", \"actual\": [[[[0.0, 0.0], [10.0, 0.0], [10.0, 10.0], [0.0, 10.0], [0.0, 0.0]], [[2.0, 2.0], [2.0, 4.0], [4.0, 4.0], [2.0, 2.0]]]], \"expected\": [[[[0.0, 0.0], [10.0, 0.0], [10.0, 10.0], [0.0, 10.0], [0.0, 0.0]], [[2.0, 2.0], [2.0, 4.0], [4.0, 4.0], [2.0, 2.0]]]], \"passed\": true}, {\"check\": \"regression #2\", \"actual\": [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]], \"expected\": [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]], \"passed\": true}, {\"check\": \"regression #3\", \"actual\": [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]], \"expected\": [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]], \"passed\": true}, {\"check\": \"regression #4\", \"actual\": [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]], \"expected\": [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]], \"passed\": true}, {\"check\": \"boundary #5\", \"actual\": [], \"expected\": [], \"passed\": true}, {\"check\": \"boundary #6\", \"actual\": null, \"expected\": [], \"passed\": false}, {\"check\": \"regression #7\", \"actual\": [[[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 0.0]]], [[[5.0, 5.0], [6.0, 5.0], [6.0, 6.0], [5.0, 5.0]], [[5.2, 5.1], [5.8, 5.8], [5.8, 5.1], [5.2, 5.1]]]], \"expected\": [[[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 0.0]]], [[[5.0, 5.0], [6.0, 5.0], [6.0, 6.0], [5.0, 5.0]], [[5.2, 5.1], [5.8, 5.8], [5.8, 5.1], [5.2, 5.1]]]], \"passed\": true}], \"passed\": false}\n"},"fixed":{"elapsed_ms":40.254,"exit_code":0,"observations":[{"actual":[[[[0.0,0.0],[4.0,0.0],[4.0,4.0],[0.0,4.0],[0.0,0.0]]]],"check":"control #0","expected":[[[[0.0,0.0],[4.0,0.0],[4.0,4.0],[0.0,4.0],[0.0,0.0]]]],"passed":true},{"actual":[[[[0.0,0.0],[10.0,0.0],[10.0,10.0],[0.0,10.0],[0.0,0.0]],[[2.0,2.0],[2.0,4.0],[4.0,4.0],[2.0,2.0]]]],"check":"control #1","expected":[[[[0.0,0.0],[10.0,0.0],[10.0,10.0],[0.0,10.0],[0.0,0.0]],[[2.0,2.0],[2.0,4.0],[4.0,4.0],[2.0,2.0]]]],"passed":true},{"actual":[[[[0.0,0.0],[4.0,0.0],[4.0,4.0],[0.0,0.0]]]],"check":"regression #2","expected":[[[[0.0,0.0],[4.0,0.0],[4.0,4.0],[0.0,0.0]]]],"passed":true},{"actual":[[[[0.0,0.0],[4.0,0.0],[4.0,4.0],[0.0,0.0]]]],"check":"regression #3","expected":[[[[0.0,0.0],[4.0,0.0],[4.0,4.0],[0.0,0.0]]]],"passed":true},{"actual":[[[[0.0,0.0],[4.0,0.0],[4.0,4.0],[0.0,0.0]]]],"check":"regression #4","expected":[[[[0.0,0.0],[4.0,0.0],[4.0,4.0],[0.0,0.0]]]],"passed":true},{"actual":[],"check":"boundary #5","expected":[],"passed":true},{"actual":[],"check":"boundary #6","expected":[],"passed":true},{"actual":[[[[0.0,0.0],[1.0,0.0],[1.0,1.0],[0.0,0.0]]],[[[5.0,5.0],[6.0,5.0],[6.0,6.0],[5.0,5.0]],[[5.2,5.1],[5.8,5.8],[5.8,5.1],[5.2,5.1]]]],"check":"regression #7","expected":[[[[0.0,0.0],[1.0,0.0],[1.0,1.0],[0.0,0.0]]],[[[5.0,5.0],[6.0,5.0],[6.0,6.0],[5.0,5.0]],[[5.2,5.1],[5.8,5.8],[5.8,5.1],[5.2,5.1]]]],"passed":true}],"passed":true,"stderr":"","stdout":"{\"observations\": [{\"check\": \"control #0\", \"actual\": [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 4.0], [0.0, 0.0]]]], \"expected\": [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 4.0], [0.0, 0.0]]]], \"passed\": true}, {\"check\": \"control #1\", \"actual\": [[[[0.0, 0.0], [10.0, 0.0], [10.0, 10.0], [0.0, 10.0], [0.0, 0.0]], [[2.0, 2.0], [2.0, 4.0], [4.0, 4.0], [2.0, 2.0]]]], \"expected\": [[[[0.0, 0.0], [10.0, 0.0], [10.0, 10.0], [0.0, 10.0], [0.0, 0.0]], [[2.0, 2.0], [2.0, 4.0], [4.0, 4.0], [2.0, 2.0]]]], \"passed\": true}, {\"check\": \"regression #2\", \"actual\": [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]], \"expected\": [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]], \"passed\": true}, {\"check\": \"regression #3\", \"actual\": [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]], \"expected\": [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]], \"passed\": true}, {\"check\": \"regression #4\", \"actual\": [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]], \"expected\": [[[[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 0.0]]]], \"passed\": true}, {\"check\": \"boundary #5\", \"actual\": [], \"expected\": [], \"passed\": true}, {\"check\": \"boundary #6\", \"actual\": [], \"expected\": [], \"passed\": true}, {\"check\": \"regression #7\", \"actual\": [[[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 0.0]]], [[[5.0, 5.0], [6.0, 5.0], [6.0, 6.0], [5.0, 5.0]], [[5.2, 5.1], [5.8, 5.8], [5.8, 5.1], [5.2, 5.1]]]], \"expected\": [[[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 0.0]]], [[[5.0, 5.0], [6.0, 5.0], [6.0, 6.0], [5.0, 5.0]], [[5.2, 5.1], [5.8, 5.8], [5.8, 5.1], [5.2, 5.1]]]], \"passed\": true}], \"passed\": true}\n"}},"verified":true,"visibility":"public"}