FA-67246 / Railway interlocking logic / Open access
Sequential point throwing under a power budget: lock check scope · case 01
A route sharing a point in the same lie with another route is refused.
ROOT CAUSE
The lock check runs before the already-in-position check.
VERIFIED REPAIR
Only block the request for a locked point that actually has to move.
Unsuccessful approach: Silently skipping locked points reports the route set while a point lies wrong.
Case contract
A route needs points in given lies (processed in list order). Points already detected in the needed lie are skipped; an undetected point (missing from current) must be thrown. A point that must move but is locked by another route blocks the whole request (blocked:<p>, nothing thrown). At most max_parallel points move at once: each point starts on the earliest-free supply slot (lowest index on ties) and takes its own throw time or the default. Return the start time per thrown point and the time all have finished.
Why this case matters
Interlocking logic decides whether trains may be given authority; a wrong decision at this point either grants unsafe movements or strands traffic.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
cur = x['current']
locked = set(x['locked'])
todo = []
for p, pos in x['need']:
if p in locked:
return {'result': 'blocked:' + p, 'starts': {}, 'done_s': 0}
if cur.get(p) == pos:
continue
todo.append(p)
slots = [0] * x['max_parallel']
starts = {}
for p in todo:
k = min(range(len(slots)), key=lambda i: (slots[i], i))
starts[p] = slots[k]
slots[k] += x['throw_s'][p] if p in x['throw_s'] else x['default_throw_s']
done = max(slots) if todo else 0
return {'result': 'set', 'starts': starts, 'done_s': done}
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: locked point already in the right lie', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P2': 0}, 'done_s': 5}), ('boundary: locked point needing to move', {'need': [['P1', 'R'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'blocked:P1', 'starts': {}, 'done_s': 0}), ('sampled regression 45', {'need': [['P5', 'N'], ['P3', 'R'], ['P2', 'R'], ['P6', 'N'], ['P4', 'N']], 'current': {'P1': 'N', 'P2': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'N'}, 'locked': ['P1', 'P2', 'P5'], 'max_parallel': 1, 'throw_s': {'P1': 6, 'P2': 4, 'P4': 6, 'P5': 3}, 'default_throw_s': 5}, {'result': 'blocked:P2', 'starts': {}, 'done_s': 0}), ('control 15', {'need': [['P1', 'N'], ['P5', 'R'], ['P4', 'R'], ['P3', 'R'], ['P2', 'R']], 'current': {'P2': 'R', 'P4': 'R', 'P5': 'R', 'P6': 'N'}, 'locked': ['P1', 'P4'], 'max_parallel': 1, 'throw_s': {'P2': 3, 'P5': 4}, 'default_throw_s': 5}, {'result': 'blocked:P1', 'starts': {}, 'done_s': 0}), ('boundary: undetected point', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P2': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0}, 'done_s': 5}), ('control 1', {'need': [['P3', 'R'], ['P6', 'N'], ['P1', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'N', 'P4': 'N', 'P5': 'N', 'P6': 'R'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P1': 6, 'P2': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P3': 0, 'P6': 0, 'P1': 5}, 'done_s': 11}), ('control 4', {'need': [['P1', 'N'], ['P5', 'N']], 'current': {'P1': 'N', 'P2': 'R', 'P3': 'R', 'P4': 'R', 'P5': 'N', 'P6': 'R'}, 'locked': [], 'max_parallel': 3, 'throw_s': {'P3': 4, 'P5': 3, 'P6': 4}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0}), ('control 7', {'need': [['P6', 'R']], 'current': {'P1': 'R', 'P2': 'N', 'P4': 'R', 'P5': 'R', 'P6': 'R'}, 'locked': [], 'max_parallel': 1, 'throw_s': {'P2': 3, 'P3': 3, 'P6': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0})], [('regression: locked point already in the right lie', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P2': 0}, 'done_s': 5}), ('boundary: locked point needing to move', {'need': [['P1', 'R'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'blocked:P1', 'starts': {}, 'done_s': 0}), ('sampled regression 36', {'need': [['P5', 'N']], 'current': {'P1': 'R', 'P3': 'R', 'P5': 'N', 'P6': 'R'}, 'locked': ['P5'], 'max_parallel': 1, 'throw_s': {'P1': 4, 'P3': 6, 'P4': 6, 'P5': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0}), ('sampled regression 45', {'need': [['P5', 'N'], ['P3', 'R'], ['P2', 'R'], ['P6', 'N'], ['P4', 'N']], 'current': {'P1': 'N', 'P2': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'N'}, 'locked': ['P1', 'P2', 'P5'], 'max_parallel': 1, 'throw_s': {'P1': 6, 'P2': 4, 'P4': 6, 'P5': 3}, 'default_throw_s': 5}, {'result': 'blocked:P2', 'starts': {}, 'done_s': 0}), ('boundary: undetected point', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P2': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0}, 'done_s': 5}), ('control 12', {'need': [['P1', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'N'}, 'locked': ['P6'], 'max_parallel': 2, 'throw_s': {'P2': 6, 'P4': 3, 'P6': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0}, 'done_s': 5}), ('control 15', {'need': [['P1', 'N'], ['P5', 'R'], ['P4', 'R'], ['P3', 'R'], ['P2', 'R']], 'current': {'P2': 'R', 'P4': 'R', 'P5': 'R', 'P6': 'N'}, 'locked': ['P1', 'P4'], 'max_parallel': 1, 'throw_s': {'P2': 3, 'P5': 4}, 'default_throw_s': 5}, {'result': 'blocked:P1', 'starts': {}, 'done_s': 0}), ('control 18', {'need': [['P2', 'N'], ['P3', 'R']], 'current': {'P1': 'R', 'P2': 'R', 'P3': 'N', 'P4': 'N', 'P5': 'R', 'P6': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P3': 6, 'P4': 4}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P2': 0, 'P3': 0}, 'done_s': 6})], [('regression: locked point already in the right lie', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P2': 0}, 'done_s': 5}), ('boundary: locked point needing to move', {'need': [['P1', 'R'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'blocked:P1', 'starts': {}, 'done_s': 0}), ('sampled regression 30', {'need': [['P6', 'N'], ['P5', 'R'], ['P3', 'R'], ['P1', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'R', 'P4': 'R', 'P5': 'R', 'P6': 'R'}, 'locked': ['P3'], 'max_parallel': 2, 'throw_s': {'P1': 3, 'P2': 6, 'P3': 3, 'P4': 6, 'P6': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P6': 0, 'P1': 0}, 'done_s': 6}), ('boundary: long first throw then short ones', {'need': [['P1', 'R'], ['P2', 'R'], ['P3', 'R'], ['P4', 'R']], 'current': {'P1': 'N', 'P2': 'N', 'P3': 'N', 'P4': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P1': 6, 'P2': 3, 'P3': 3, 'P4': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0, 'P3': 3, 'P4': 6}, 'done_s': 9}), ('boundary: single supply', {'need': [['P1', 'R'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': [], 'max_parallel': 1, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 5}, 'done_s': 10}), ('control 23', {'need': [['P3', 'N'], ['P4', 'N'], ['P1', 'R'], ['P6', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'N', 'P4': 'R'}, 'locked': [], 'max_parallel': 1, 'throw_s': {'P2': 3, 'P4': 3, 'P5': 4, 'P6': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P4': 0, 'P6': 3}, 'done_s': 6}), ('control 26', {'need': [['P1', 'N']], 'current': {'P1': 'N', 'P2': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'N'}, 'locked': ['P5', 'P6'], 'max_parallel': 1, 'throw_s': {'P2': 3, 'P3': 4}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0}), ('control 29', {'need': [['P4', 'N'], ['P2', 'N'], ['P1', 'N'], ['P5', 'N'], ['P6', 'R']], 'current': {'P2': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'R'}, 'locked': [], 'max_parallel': 1, 'throw_s': {'P1': 4, 'P2': 3, 'P3': 6, 'P4': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P4': 0, 'P1': 6}, 'done_s': 10})], [('regression: locked point already in the right lie', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P2': 0}, 'done_s': 5}), ('boundary: locked point needing to move', {'need': [['P1', 'R'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'blocked:P1', 'starts': {}, 'done_s': 0}), ('control 43', {'need': [['P1', 'R'], ['P6', 'R'], ['P4', 'R'], ['P3', 'N'], ['P5', 'R']], 'current': {'P1': 'N', 'P2': 'R', 'P3': 'R', 'P4': 'R', 'P6': 'N'}, 'locked': ['P5'], 'max_parallel': 1, 'throw_s': {'P3': 3, 'P5': 4, 'P6': 6}, 'default_throw_s': 5}, {'result': 'blocked:P5', 'starts': {}, 'done_s': 0}), ('boundary: nothing to move', {'need': [['P1', 'N']], 'current': {'P1': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0}), ('boundary: points with individual throw times', {'need': [['P4', 'R'], ['P5', 'N']], 'current': {'P4': 'N', 'P5': 'R'}, 'locked': [], 'max_parallel': 1, 'throw_s': {'P4': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P4': 0, 'P5': 3}, 'done_s': 8}), ('control 34', {'need': [['P3', 'R']], 'current': {'P1': 'R', 'P3': 'N', 'P4': 'R', 'P6': 'R'}, 'locked': [], 'max_parallel': 3, 'throw_s': {'P1': 6, 'P2': 3, 'P4': 4, 'P6': 4}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P3': 0}, 'done_s': 5}), ('control 37', {'need': [['P5', 'R'], ['P1', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'N', 'P5': 'R'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P3': 6, 'P6': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0}, 'done_s': 5}), ('control 40', {'need': [['P5', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'R', 'P4': 'R', 'P5': 'N', 'P6': 'R'}, 'locked': ['P3'], 'max_parallel': 2, 'throw_s': {'P1': 4, 'P2': 6, 'P3': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0})], [('regression: locked point already in the right lie', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P2': 0}, 'done_s': 5}), ('boundary: locked point needing to move', {'need': [['P1', 'R'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'blocked:P1', 'starts': {}, 'done_s': 0}), ('sampled regression 74', {'need': [['P6', 'N'], ['P3', 'N']], 'current': {'P1': 'R', 'P2': 'R', 'P3': 'N', 'P4': 'N', 'P5': 'N', 'P6': 'R'}, 'locked': ['P3'], 'max_parallel': 3, 'throw_s': {'P2': 6, 'P4': 4, 'P6': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P6': 0}, 'done_s': 3}), ('control 73', {'need': [['P6', 'N'], ['P5', 'R'], ['P4', 'R']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'N'}, 'locked': ['P1', 'P3', 'P4', 'P5'], 'max_parallel': 3, 'throw_s': {'P1': 6, 'P2': 3, 'P4': 3, 'P5': 6}, 'default_throw_s': 5}, {'result': 'blocked:P5', 'starts': {}, 'done_s': 0}), ('boundary: undetected point', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P2': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0}, 'done_s': 5}), ('sampled regression 45', {'need': [['P5', 'N'], ['P3', 'R'], ['P2', 'R'], ['P6', 'N'], ['P4', 'N']], 'current': {'P1': 'N', 'P2': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'N'}, 'locked': ['P1', 'P2', 'P5'], 'max_parallel': 1, 'throw_s': {'P1': 6, 'P2': 4, 'P4': 6, 'P5': 3}, 'default_throw_s': 5}, {'result': 'blocked:P2', 'starts': {}, 'done_s': 0}), ('control 48', {'need': [['P3', 'R']], 'current': {'P1': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'N'}, 'locked': ['P4'], 'max_parallel': 1, 'throw_s': {'P4': 6, 'P5': 6, 'P6': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P3': 0}, 'done_s': 5}), ('control 51', {'need': [['P6', 'R'], ['P5', 'N'], ['P1', 'R'], ['P4', 'N']], 'current': {'P1': 'R', 'P2': 'R', 'P3': 'N', 'P4': 'N', 'P5': 'N', 'P6': 'R'}, 'locked': ['P3'], 'max_parallel': 3, 'throw_s': {'P2': 6, 'P3': 6, 'P4': 6, 'P5': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression: locked point already in the right lie | {'done_s': 0, 'result': 'blocked:P1', 'starts': {}} | {'done_s': 5, 'result': 'set', 'starts': {'P2': 0}} | Failed |
| boundary: locked point needing to move | {'done_s': 0, 'result': 'blocked:P1', 'starts': {}} | {'done_s': 0, 'result': 'blocked:P1', 'starts': {}} | Passed |
| sampled regression 45 | {'done_s': 0, 'result': 'blocked:P5', 'starts': {}} | {'done_s': 0, 'result': 'blocked:P2', 'starts': {}} | Failed |
| control 15 | {'done_s': 0, 'result': 'blocked:P1', 'starts': {}} | {'done_s': 0, 'result': 'blocked:P1', 'starts': {}} | Passed |
| boundary: undetected point | {'done_s': 5, 'result': 'set', 'starts': {'P1': 0, 'P2': 0}} | {'done_s': 5, 'result': 'set', 'starts': {'P1': 0, 'P2': 0}} | Passed |
| control 1 | {'done_s': 11, 'result': 'set', 'starts': {'P1': 5, 'P3': 0, 'P6': 0}} | {'done_s': 11, 'result': 'set', 'starts': {'P1': 5, 'P3': 0, 'P6': 0}} | Passed |
| control 4 | {'done_s': 0, 'result': 'set', 'starts': {}} | {'done_s': 0, 'result': 'set', 'starts': {}} | Passed |
| control 7 | {'done_s': 0, 'result': 'set', 'starts': {}} | {'done_s': 0, 'result': 'set', 'starts': {}} | Passed |
SHA-256 / e8c40a6529a5f44f08d46c9c7797ff2f16d67a6311c85757bdbdb688c061731d
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
cur = x['current']
locked = set(x['locked'])
todo = []
for p, pos in x['need']:
if cur.get(p) == pos:
continue
if p in locked:
continue
todo.append(p)
slots = [0] * x['max_parallel']
starts = {}
for p in todo:
k = min(range(len(slots)), key=lambda i: (slots[i], i))
starts[p] = slots[k]
slots[k] += x['throw_s'][p] if p in x['throw_s'] else x['default_throw_s']
done = max(slots) if todo else 0
return {'result': 'set', 'starts': starts, 'done_s': done}
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: locked point already in the right lie', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P2': 0}, 'done_s': 5}), ('boundary: locked point needing to move', {'need': [['P1', 'R'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'blocked:P1', 'starts': {}, 'done_s': 0}), ('sampled regression 45', {'need': [['P5', 'N'], ['P3', 'R'], ['P2', 'R'], ['P6', 'N'], ['P4', 'N']], 'current': {'P1': 'N', 'P2': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'N'}, 'locked': ['P1', 'P2', 'P5'], 'max_parallel': 1, 'throw_s': {'P1': 6, 'P2': 4, 'P4': 6, 'P5': 3}, 'default_throw_s': 5}, {'result': 'blocked:P2', 'starts': {}, 'done_s': 0}), ('control 15', {'need': [['P1', 'N'], ['P5', 'R'], ['P4', 'R'], ['P3', 'R'], ['P2', 'R']], 'current': {'P2': 'R', 'P4': 'R', 'P5': 'R', 'P6': 'N'}, 'locked': ['P1', 'P4'], 'max_parallel': 1, 'throw_s': {'P2': 3, 'P5': 4}, 'default_throw_s': 5}, {'result': 'blocked:P1', 'starts': {}, 'done_s': 0}), ('boundary: undetected point', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P2': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0}, 'done_s': 5}), ('control 1', {'need': [['P3', 'R'], ['P6', 'N'], ['P1', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'N', 'P4': 'N', 'P5': 'N', 'P6': 'R'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P1': 6, 'P2': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P3': 0, 'P6': 0, 'P1': 5}, 'done_s': 11}), ('control 4', {'need': [['P1', 'N'], ['P5', 'N']], 'current': {'P1': 'N', 'P2': 'R', 'P3': 'R', 'P4': 'R', 'P5': 'N', 'P6': 'R'}, 'locked': [], 'max_parallel': 3, 'throw_s': {'P3': 4, 'P5': 3, 'P6': 4}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0}), ('control 7', {'need': [['P6', 'R']], 'current': {'P1': 'R', 'P2': 'N', 'P4': 'R', 'P5': 'R', 'P6': 'R'}, 'locked': [], 'max_parallel': 1, 'throw_s': {'P2': 3, 'P3': 3, 'P6': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0})], [('regression: locked point already in the right lie', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P2': 0}, 'done_s': 5}), ('boundary: locked point needing to move', {'need': [['P1', 'R'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'blocked:P1', 'starts': {}, 'done_s': 0}), ('sampled regression 36', {'need': [['P5', 'N']], 'current': {'P1': 'R', 'P3': 'R', 'P5': 'N', 'P6': 'R'}, 'locked': ['P5'], 'max_parallel': 1, 'throw_s': {'P1': 4, 'P3': 6, 'P4': 6, 'P5': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0}), ('sampled regression 45', {'need': [['P5', 'N'], ['P3', 'R'], ['P2', 'R'], ['P6', 'N'], ['P4', 'N']], 'current': {'P1': 'N', 'P2': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'N'}, 'locked': ['P1', 'P2', 'P5'], 'max_parallel': 1, 'throw_s': {'P1': 6, 'P2': 4, 'P4': 6, 'P5': 3}, 'default_throw_s': 5}, {'result': 'blocked:P2', 'starts': {}, 'done_s': 0}), ('boundary: undetected point', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P2': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0}, 'done_s': 5}), ('control 12', {'need': [['P1', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'N'}, 'locked': ['P6'], 'max_parallel': 2, 'throw_s': {'P2': 6, 'P4': 3, 'P6': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0}, 'done_s': 5}), ('control 15', {'need': [['P1', 'N'], ['P5', 'R'], ['P4', 'R'], ['P3', 'R'], ['P2', 'R']], 'current': {'P2': 'R', 'P4': 'R', 'P5': 'R', 'P6': 'N'}, 'locked': ['P1', 'P4'], 'max_parallel': 1, 'throw_s': {'P2': 3, 'P5': 4}, 'default_throw_s': 5}, {'result': 'blocked:P1', 'starts': {}, 'done_s': 0}), ('control 18', {'need': [['P2', 'N'], ['P3', 'R']], 'current': {'P1': 'R', 'P2': 'R', 'P3': 'N', 'P4': 'N', 'P5': 'R', 'P6': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P3': 6, 'P4': 4}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P2': 0, 'P3': 0}, 'done_s': 6})], [('regression: locked point already in the right lie', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P2': 0}, 'done_s': 5}), ('boundary: locked point needing to move', {'need': [['P1', 'R'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'blocked:P1', 'starts': {}, 'done_s': 0}), ('sampled regression 30', {'need': [['P6', 'N'], ['P5', 'R'], ['P3', 'R'], ['P1', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'R', 'P4': 'R', 'P5': 'R', 'P6': 'R'}, 'locked': ['P3'], 'max_parallel': 2, 'throw_s': {'P1': 3, 'P2': 6, 'P3': 3, 'P4': 6, 'P6': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P6': 0, 'P1': 0}, 'done_s': 6}), ('boundary: long first throw then short ones', {'need': [['P1', 'R'], ['P2', 'R'], ['P3', 'R'], ['P4', 'R']], 'current': {'P1': 'N', 'P2': 'N', 'P3': 'N', 'P4': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P1': 6, 'P2': 3, 'P3': 3, 'P4': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0, 'P3': 3, 'P4': 6}, 'done_s': 9}), ('boundary: single supply', {'need': [['P1', 'R'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': [], 'max_parallel': 1, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 5}, 'done_s': 10}), ('control 23', {'need': [['P3', 'N'], ['P4', 'N'], ['P1', 'R'], ['P6', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'N', 'P4': 'R'}, 'locked': [], 'max_parallel': 1, 'throw_s': {'P2': 3, 'P4': 3, 'P5': 4, 'P6': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P4': 0, 'P6': 3}, 'done_s': 6}), ('control 26', {'need': [['P1', 'N']], 'current': {'P1': 'N', 'P2': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'N'}, 'locked': ['P5', 'P6'], 'max_parallel': 1, 'throw_s': {'P2': 3, 'P3': 4}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0}), ('control 29', {'need': [['P4', 'N'], ['P2', 'N'], ['P1', 'N'], ['P5', 'N'], ['P6', 'R']], 'current': {'P2': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'R'}, 'locked': [], 'max_parallel': 1, 'throw_s': {'P1': 4, 'P2': 3, 'P3': 6, 'P4': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P4': 0, 'P1': 6}, 'done_s': 10})], [('regression: locked point already in the right lie', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P2': 0}, 'done_s': 5}), ('boundary: locked point needing to move', {'need': [['P1', 'R'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'blocked:P1', 'starts': {}, 'done_s': 0}), ('control 43', {'need': [['P1', 'R'], ['P6', 'R'], ['P4', 'R'], ['P3', 'N'], ['P5', 'R']], 'current': {'P1': 'N', 'P2': 'R', 'P3': 'R', 'P4': 'R', 'P6': 'N'}, 'locked': ['P5'], 'max_parallel': 1, 'throw_s': {'P3': 3, 'P5': 4, 'P6': 6}, 'default_throw_s': 5}, {'result': 'blocked:P5', 'starts': {}, 'done_s': 0}), ('boundary: nothing to move', {'need': [['P1', 'N']], 'current': {'P1': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0}), ('boundary: points with individual throw times', {'need': [['P4', 'R'], ['P5', 'N']], 'current': {'P4': 'N', 'P5': 'R'}, 'locked': [], 'max_parallel': 1, 'throw_s': {'P4': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P4': 0, 'P5': 3}, 'done_s': 8}), ('control 34', {'need': [['P3', 'R']], 'current': {'P1': 'R', 'P3': 'N', 'P4': 'R', 'P6': 'R'}, 'locked': [], 'max_parallel': 3, 'throw_s': {'P1': 6, 'P2': 3, 'P4': 4, 'P6': 4}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P3': 0}, 'done_s': 5}), ('control 37', {'need': [['P5', 'R'], ['P1', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'N', 'P5': 'R'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P3': 6, 'P6': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0}, 'done_s': 5}), ('control 40', {'need': [['P5', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'R', 'P4': 'R', 'P5': 'N', 'P6': 'R'}, 'locked': ['P3'], 'max_parallel': 2, 'throw_s': {'P1': 4, 'P2': 6, 'P3': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0})], [('regression: locked point already in the right lie', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P2': 0}, 'done_s': 5}), ('boundary: locked point needing to move', {'need': [['P1', 'R'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'blocked:P1', 'starts': {}, 'done_s': 0}), ('sampled regression 74', {'need': [['P6', 'N'], ['P3', 'N']], 'current': {'P1': 'R', 'P2': 'R', 'P3': 'N', 'P4': 'N', 'P5': 'N', 'P6': 'R'}, 'locked': ['P3'], 'max_parallel': 3, 'throw_s': {'P2': 6, 'P4': 4, 'P6': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P6': 0}, 'done_s': 3}), ('control 73', {'need': [['P6', 'N'], ['P5', 'R'], ['P4', 'R']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'N'}, 'locked': ['P1', 'P3', 'P4', 'P5'], 'max_parallel': 3, 'throw_s': {'P1': 6, 'P2': 3, 'P4': 3, 'P5': 6}, 'default_throw_s': 5}, {'result': 'blocked:P5', 'starts': {}, 'done_s': 0}), ('boundary: undetected point', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P2': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0}, 'done_s': 5}), ('sampled regression 45', {'need': [['P5', 'N'], ['P3', 'R'], ['P2', 'R'], ['P6', 'N'], ['P4', 'N']], 'current': {'P1': 'N', 'P2': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'N'}, 'locked': ['P1', 'P2', 'P5'], 'max_parallel': 1, 'throw_s': {'P1': 6, 'P2': 4, 'P4': 6, 'P5': 3}, 'default_throw_s': 5}, {'result': 'blocked:P2', 'starts': {}, 'done_s': 0}), ('control 48', {'need': [['P3', 'R']], 'current': {'P1': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'N'}, 'locked': ['P4'], 'max_parallel': 1, 'throw_s': {'P4': 6, 'P5': 6, 'P6': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P3': 0}, 'done_s': 5}), ('control 51', {'need': [['P6', 'R'], ['P5', 'N'], ['P1', 'R'], ['P4', 'N']], 'current': {'P1': 'R', 'P2': 'R', 'P3': 'N', 'P4': 'N', 'P5': 'N', 'P6': 'R'}, 'locked': ['P3'], 'max_parallel': 3, 'throw_s': {'P2': 6, 'P3': 6, 'P4': 6, 'P5': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression: locked point already in the right lie | {'done_s': 5, 'result': 'set', 'starts': {'P2': 0}} | {'done_s': 5, 'result': 'set', 'starts': {'P2': 0}} | Passed |
| boundary: locked point needing to move | {'done_s': 5, 'result': 'set', 'starts': {'P2': 0}} | {'done_s': 0, 'result': 'blocked:P1', 'starts': {}} | Failed |
| sampled regression 45 | {'done_s': 11, 'result': 'set', 'starts': {'P3': 0, 'P4': 5}} | {'done_s': 0, 'result': 'blocked:P2', 'starts': {}} | Failed |
| control 15 | {'done_s': 5, 'result': 'set', 'starts': {'P3': 0}} | {'done_s': 0, 'result': 'blocked:P1', 'starts': {}} | Failed |
| boundary: undetected point | {'done_s': 5, 'result': 'set', 'starts': {'P1': 0, 'P2': 0}} | {'done_s': 5, 'result': 'set', 'starts': {'P1': 0, 'P2': 0}} | Passed |
| control 1 | {'done_s': 11, 'result': 'set', 'starts': {'P1': 5, 'P3': 0, 'P6': 0}} | {'done_s': 11, 'result': 'set', 'starts': {'P1': 5, 'P3': 0, 'P6': 0}} | Passed |
| control 4 | {'done_s': 0, 'result': 'set', 'starts': {}} | {'done_s': 0, 'result': 'set', 'starts': {}} | Passed |
| control 7 | {'done_s': 0, 'result': 'set', 'starts': {}} | {'done_s': 0, 'result': 'set', 'starts': {}} | Passed |
SHA-256 / acedb695d2ee9ffec4f65dabd5087b2a9b1d91eaec85b3d4156374f80edec5b6
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
cur = x['current']
locked = set(x['locked'])
todo = []
for p, pos in x['need']:
if cur.get(p) == pos:
continue
if p in locked:
return {'result': 'blocked:' + p, 'starts': {}, 'done_s': 0}
todo.append(p)
slots = [0] * x['max_parallel']
starts = {}
for p in todo:
k = min(range(len(slots)), key=lambda i: (slots[i], i))
starts[p] = slots[k]
slots[k] += x['throw_s'][p] if p in x['throw_s'] else x['default_throw_s']
done = max(slots) if todo else 0
return {'result': 'set', 'starts': starts, 'done_s': done}
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: locked point already in the right lie', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P2': 0}, 'done_s': 5}), ('boundary: locked point needing to move', {'need': [['P1', 'R'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'blocked:P1', 'starts': {}, 'done_s': 0}), ('sampled regression 45', {'need': [['P5', 'N'], ['P3', 'R'], ['P2', 'R'], ['P6', 'N'], ['P4', 'N']], 'current': {'P1': 'N', 'P2': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'N'}, 'locked': ['P1', 'P2', 'P5'], 'max_parallel': 1, 'throw_s': {'P1': 6, 'P2': 4, 'P4': 6, 'P5': 3}, 'default_throw_s': 5}, {'result': 'blocked:P2', 'starts': {}, 'done_s': 0}), ('control 15', {'need': [['P1', 'N'], ['P5', 'R'], ['P4', 'R'], ['P3', 'R'], ['P2', 'R']], 'current': {'P2': 'R', 'P4': 'R', 'P5': 'R', 'P6': 'N'}, 'locked': ['P1', 'P4'], 'max_parallel': 1, 'throw_s': {'P2': 3, 'P5': 4}, 'default_throw_s': 5}, {'result': 'blocked:P1', 'starts': {}, 'done_s': 0}), ('boundary: undetected point', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P2': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0}, 'done_s': 5}), ('control 1', {'need': [['P3', 'R'], ['P6', 'N'], ['P1', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'N', 'P4': 'N', 'P5': 'N', 'P6': 'R'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P1': 6, 'P2': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P3': 0, 'P6': 0, 'P1': 5}, 'done_s': 11}), ('control 4', {'need': [['P1', 'N'], ['P5', 'N']], 'current': {'P1': 'N', 'P2': 'R', 'P3': 'R', 'P4': 'R', 'P5': 'N', 'P6': 'R'}, 'locked': [], 'max_parallel': 3, 'throw_s': {'P3': 4, 'P5': 3, 'P6': 4}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0}), ('control 7', {'need': [['P6', 'R']], 'current': {'P1': 'R', 'P2': 'N', 'P4': 'R', 'P5': 'R', 'P6': 'R'}, 'locked': [], 'max_parallel': 1, 'throw_s': {'P2': 3, 'P3': 3, 'P6': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0})], [('regression: locked point already in the right lie', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P2': 0}, 'done_s': 5}), ('boundary: locked point needing to move', {'need': [['P1', 'R'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'blocked:P1', 'starts': {}, 'done_s': 0}), ('sampled regression 36', {'need': [['P5', 'N']], 'current': {'P1': 'R', 'P3': 'R', 'P5': 'N', 'P6': 'R'}, 'locked': ['P5'], 'max_parallel': 1, 'throw_s': {'P1': 4, 'P3': 6, 'P4': 6, 'P5': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0}), ('sampled regression 45', {'need': [['P5', 'N'], ['P3', 'R'], ['P2', 'R'], ['P6', 'N'], ['P4', 'N']], 'current': {'P1': 'N', 'P2': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'N'}, 'locked': ['P1', 'P2', 'P5'], 'max_parallel': 1, 'throw_s': {'P1': 6, 'P2': 4, 'P4': 6, 'P5': 3}, 'default_throw_s': 5}, {'result': 'blocked:P2', 'starts': {}, 'done_s': 0}), ('boundary: undetected point', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P2': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0}, 'done_s': 5}), ('control 12', {'need': [['P1', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'N'}, 'locked': ['P6'], 'max_parallel': 2, 'throw_s': {'P2': 6, 'P4': 3, 'P6': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0}, 'done_s': 5}), ('control 15', {'need': [['P1', 'N'], ['P5', 'R'], ['P4', 'R'], ['P3', 'R'], ['P2', 'R']], 'current': {'P2': 'R', 'P4': 'R', 'P5': 'R', 'P6': 'N'}, 'locked': ['P1', 'P4'], 'max_parallel': 1, 'throw_s': {'P2': 3, 'P5': 4}, 'default_throw_s': 5}, {'result': 'blocked:P1', 'starts': {}, 'done_s': 0}), ('control 18', {'need': [['P2', 'N'], ['P3', 'R']], 'current': {'P1': 'R', 'P2': 'R', 'P3': 'N', 'P4': 'N', 'P5': 'R', 'P6': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P3': 6, 'P4': 4}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P2': 0, 'P3': 0}, 'done_s': 6})], [('regression: locked point already in the right lie', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P2': 0}, 'done_s': 5}), ('boundary: locked point needing to move', {'need': [['P1', 'R'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'blocked:P1', 'starts': {}, 'done_s': 0}), ('sampled regression 30', {'need': [['P6', 'N'], ['P5', 'R'], ['P3', 'R'], ['P1', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'R', 'P4': 'R', 'P5': 'R', 'P6': 'R'}, 'locked': ['P3'], 'max_parallel': 2, 'throw_s': {'P1': 3, 'P2': 6, 'P3': 3, 'P4': 6, 'P6': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P6': 0, 'P1': 0}, 'done_s': 6}), ('boundary: long first throw then short ones', {'need': [['P1', 'R'], ['P2', 'R'], ['P3', 'R'], ['P4', 'R']], 'current': {'P1': 'N', 'P2': 'N', 'P3': 'N', 'P4': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P1': 6, 'P2': 3, 'P3': 3, 'P4': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0, 'P3': 3, 'P4': 6}, 'done_s': 9}), ('boundary: single supply', {'need': [['P1', 'R'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': [], 'max_parallel': 1, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 5}, 'done_s': 10}), ('control 23', {'need': [['P3', 'N'], ['P4', 'N'], ['P1', 'R'], ['P6', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'N', 'P4': 'R'}, 'locked': [], 'max_parallel': 1, 'throw_s': {'P2': 3, 'P4': 3, 'P5': 4, 'P6': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P4': 0, 'P6': 3}, 'done_s': 6}), ('control 26', {'need': [['P1', 'N']], 'current': {'P1': 'N', 'P2': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'N'}, 'locked': ['P5', 'P6'], 'max_parallel': 1, 'throw_s': {'P2': 3, 'P3': 4}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0}), ('control 29', {'need': [['P4', 'N'], ['P2', 'N'], ['P1', 'N'], ['P5', 'N'], ['P6', 'R']], 'current': {'P2': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'R'}, 'locked': [], 'max_parallel': 1, 'throw_s': {'P1': 4, 'P2': 3, 'P3': 6, 'P4': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P4': 0, 'P1': 6}, 'done_s': 10})], [('regression: locked point already in the right lie', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P2': 0}, 'done_s': 5}), ('boundary: locked point needing to move', {'need': [['P1', 'R'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'blocked:P1', 'starts': {}, 'done_s': 0}), ('control 43', {'need': [['P1', 'R'], ['P6', 'R'], ['P4', 'R'], ['P3', 'N'], ['P5', 'R']], 'current': {'P1': 'N', 'P2': 'R', 'P3': 'R', 'P4': 'R', 'P6': 'N'}, 'locked': ['P5'], 'max_parallel': 1, 'throw_s': {'P3': 3, 'P5': 4, 'P6': 6}, 'default_throw_s': 5}, {'result': 'blocked:P5', 'starts': {}, 'done_s': 0}), ('boundary: nothing to move', {'need': [['P1', 'N']], 'current': {'P1': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0}), ('boundary: points with individual throw times', {'need': [['P4', 'R'], ['P5', 'N']], 'current': {'P4': 'N', 'P5': 'R'}, 'locked': [], 'max_parallel': 1, 'throw_s': {'P4': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P4': 0, 'P5': 3}, 'done_s': 8}), ('control 34', {'need': [['P3', 'R']], 'current': {'P1': 'R', 'P3': 'N', 'P4': 'R', 'P6': 'R'}, 'locked': [], 'max_parallel': 3, 'throw_s': {'P1': 6, 'P2': 3, 'P4': 4, 'P6': 4}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P3': 0}, 'done_s': 5}), ('control 37', {'need': [['P5', 'R'], ['P1', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'N', 'P5': 'R'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P3': 6, 'P6': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0}, 'done_s': 5}), ('control 40', {'need': [['P5', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'R', 'P4': 'R', 'P5': 'N', 'P6': 'R'}, 'locked': ['P3'], 'max_parallel': 2, 'throw_s': {'P1': 4, 'P2': 6, 'P3': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0})], [('regression: locked point already in the right lie', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P2': 0}, 'done_s': 5}), ('boundary: locked point needing to move', {'need': [['P1', 'R'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'blocked:P1', 'starts': {}, 'done_s': 0}), ('sampled regression 74', {'need': [['P6', 'N'], ['P3', 'N']], 'current': {'P1': 'R', 'P2': 'R', 'P3': 'N', 'P4': 'N', 'P5': 'N', 'P6': 'R'}, 'locked': ['P3'], 'max_parallel': 3, 'throw_s': {'P2': 6, 'P4': 4, 'P6': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P6': 0}, 'done_s': 3}), ('control 73', {'need': [['P6', 'N'], ['P5', 'R'], ['P4', 'R']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'N'}, 'locked': ['P1', 'P3', 'P4', 'P5'], 'max_parallel': 3, 'throw_s': {'P1': 6, 'P2': 3, 'P4': 3, 'P5': 6}, 'default_throw_s': 5}, {'result': 'blocked:P5', 'starts': {}, 'done_s': 0}), ('boundary: undetected point', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P2': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0}, 'done_s': 5}), ('sampled regression 45', {'need': [['P5', 'N'], ['P3', 'R'], ['P2', 'R'], ['P6', 'N'], ['P4', 'N']], 'current': {'P1': 'N', 'P2': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'N'}, 'locked': ['P1', 'P2', 'P5'], 'max_parallel': 1, 'throw_s': {'P1': 6, 'P2': 4, 'P4': 6, 'P5': 3}, 'default_throw_s': 5}, {'result': 'blocked:P2', 'starts': {}, 'done_s': 0}), ('control 48', {'need': [['P3', 'R']], 'current': {'P1': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'N'}, 'locked': ['P4'], 'max_parallel': 1, 'throw_s': {'P4': 6, 'P5': 6, 'P6': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P3': 0}, 'done_s': 5}), ('control 51', {'need': [['P6', 'R'], ['P5', 'N'], ['P1', 'R'], ['P4', 'N']], 'current': {'P1': 'R', 'P2': 'R', 'P3': 'N', 'P4': 'N', 'P5': 'N', 'P6': 'R'}, 'locked': ['P3'], 'max_parallel': 3, 'throw_s': {'P2': 6, 'P3': 6, 'P4': 6, 'P5': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression: locked point already in the right lie | {'done_s': 5, 'result': 'set', 'starts': {'P2': 0}} | {'done_s': 5, 'result': 'set', 'starts': {'P2': 0}} | Passed |
| boundary: locked point needing to move | {'done_s': 0, 'result': 'blocked:P1', 'starts': {}} | {'done_s': 0, 'result': 'blocked:P1', 'starts': {}} | Passed |
| sampled regression 45 | {'done_s': 0, 'result': 'blocked:P2', 'starts': {}} | {'done_s': 0, 'result': 'blocked:P2', 'starts': {}} | Passed |
| control 15 | {'done_s': 0, 'result': 'blocked:P1', 'starts': {}} | {'done_s': 0, 'result': 'blocked:P1', 'starts': {}} | Passed |
| boundary: undetected point | {'done_s': 5, 'result': 'set', 'starts': {'P1': 0, 'P2': 0}} | {'done_s': 5, 'result': 'set', 'starts': {'P1': 0, 'P2': 0}} | Passed |
| control 1 | {'done_s': 11, 'result': 'set', 'starts': {'P1': 5, 'P3': 0, 'P6': 0}} | {'done_s': 11, 'result': 'set', 'starts': {'P1': 5, 'P3': 0, 'P6': 0}} | Passed |
| control 4 | {'done_s': 0, 'result': 'set', 'starts': {}} | {'done_s': 0, 'result': 'set', 'starts': {}} | Passed |
| control 7 | {'done_s': 0, 'result': 'set', 'starts': {}} | {'done_s': 0, 'result': 'set', 'starts': {}} | Passed |
SHA-256 / a185e3551c96260bb758b0a814ea38ac8addd03c4a747a32c1a604e4bc057c36
Verification & scope
Stipulated toy interlocking contract for a bounded teaching model; it makes no claim of conformance to any railway signalling standard and omits real safety cases. 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:47:51.095271+00:00.
Case digest / f7acc87cf8213a1eb0db9b1b89300cc5411dccaf0b0b5ced13f7d4e5fd51cd4f