FAILURE MAP
← Case archive

FA-67091 / Railway interlocking logic / Open access

Movement authority end computation: blocking section boundary · case 01

The authority extends through the blocking section.

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

ROOT CAUSE

The end of authority is placed at the far end of the blocking section.

VERIFIED REPAIR

End the authority at the start of the first non-locked section.

Unsuccessful approach: Ending at the start of the previous section withholds a whole free section.

Case contract

Sections have lengths and states locked, occupied or unlocked; the train front is offset_m into section train_sec (which it occupies itself). Scan the following sections; the end of authority is the start of the first section that is not locked (reason = its state) or the end of the last section (end-of-route). If that exceeds max_ma_m ahead of the train front, the authority is cut to front + max_ma_m (reason max-length). The margin is subtracted from the end except for a max-length cut.

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):
    secs = x['sections']
    bounds = []
    acc = 0
    for s in secs:
        bounds.append(acc)
        acc += s['len']
    k = x['train_sec']
    eoa = acc
    reason = 'end-of-route'
    for j in range(k + 1, len(secs)):
        if secs[j]['state'] != 'locked':
            eoa = bounds[j] + secs[j]['len']
            reason = secs[j]['state']
            break
    front = bounds[k] + x['offset_m']
    if eoa - front > x['max_ma_m']:
        eoa = front + x['max_ma_m']
        reason = 'max-length'
    if reason != 'max-length':
        eoa -= x['margin_m']
    return {'eoa_m': eoa, 'reason': reason}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: occupied section two ahead', {'sections': [{'len': 200, 'state': 'occupied'}, {'len': 200, 'state': 'locked'}, {'len': 300, 'state': 'occupied'}, {'len': 100, 'state': 'locked'}], 'train_sec': 0, 'offset_m': 100, 'max_ma_m': 5000, 'margin_m': 25}, {'eoa_m': 375, 'reason': 'occupied'}), ('regression: unlocked section margin', {'sections': [{'len': 100, 'state': 'occupied'}, {'len': 150, 'state': 'locked'}, {'len': 100, 'state': 'unlocked'}], 'train_sec': 0, 'offset_m': 20, 'max_ma_m': 5000, 'margin_m': 30}, {'eoa_m': 220, 'reason': 'unlocked'}), ('regression: unlocked section next', {'sections': [{'len': 200, 'state': 'locked'}, {'len': 200, 'state': 'occupied'}, {'len': 300, 'state': 'unlocked'}], 'train_sec': 1, 'offset_m': 10, 'max_ma_m': 5000, 'margin_m': 25}, {'eoa_m': 375, 'reason': 'unlocked'}), ('boundary: own section occupied', {'sections': [{'len': 200, 'state': 'occupied'}, {'len': 200, 'state': 'locked'}, {'len': 300, 'state': 'locked'}], 'train_sec': 0, 'offset_m': 50, 'max_ma_m': 5000, 'margin_m': 25}, {'eoa_m': 675, 'reason': 'end-of-route'}), ('boundary: length cap from the front', {'sections': [{'len': 500, 'state': 'occupied'}, {'len': 500, 'state': 'locked'}, {'len': 500, 'state': 'locked'}], 'train_sec': 0, 'offset_m': 400, 'max_ma_m': 600, 'margin_m': 25}, {'eoa_m': 1000, 'reason': 'max-length'}), ('sampled regression 1', {'sections': [{'len': 200, 'state': 'occupied'}, {'len': 100, 'state': 'unlocked'}, {'len': 200, 'state': 'occupied'}, {'len': 350, 'state': 'locked'}], 'train_sec': 0, 'offset_m': 69, 'max_ma_m': 5000, 'margin_m': 50}, {'eoa_m': 150, 'reason': 'unlocked'}), ('control 4', {'sections': [{'len': 500, 'state': 'occupied'}, {'len': 500, 'state': 'locked'}, {'len': 350, 'state': 'locked'}], 'train_sec': 0, 'offset_m': 206, 'max_ma_m': 5000, 'margin_m': 25}, {'eoa_m': 1325, 'reason': 'end-of-route'}), ('sampled regression 7', {'sections': [{'len': 350, 'state': 'locked'}, {'len': 200, 'state': 'occupied'}, {'len': 350, 'state': 'unlocked'}, {'len': 500, 'state': 'unlocked'}, {'len': 500, 'state': 'occupied'}, {'len': 500, 'state': 'unlocked'}], 'train_sec': 1, 'offset_m': 108, 'max_ma_m': 5000, 'margin_m': 0}, {'eoa_m': 550, 'reason': 'unlocked'})], [('regression: unlocked section next', {'sections': [{'len': 200, 'state': 'locked'}, {'len': 200, 'state': 'occupied'}, {'len': 300, 'state': 'unlocked'}], 'train_sec': 1, 'offset_m': 10, 'max_ma_m': 5000, 'margin_m': 25}, {'eoa_m': 375, 'reason': 'unlocked'}), ('sampled regression 10', {'sections': [{'len': 500, 'state': 'occupied'}, {'len': 500, 'state': 'occupied'}, {'len': 500, 'state': 'locked'}, {'len': 100, 'state': 'locked'}, {'len': 200, 'state': 'locked'}, {'len': 200, 'state': 'occupied'}, {'len': 200, 'state': 'occupied'}], 'train_sec': 5, 'offset_m': 104, 'max_ma_m': 600, 'margin_m': 25}, {'eoa_m': 1975, 'reason': 'occupied'}), ('sampled regression 6', {'sections': [{'len': 350, 'state': 'occupied'}, {'len': 200, 'state': 'unlocked'}, {'len': 100, 'state': 'occupied'}, {'len': 350, 'state': 'unlocked'}, {'len': 200, 'state': 'locked'}, {'len': 100, 'state': 'locked'}], 'train_sec': 2, 'offset_m': 2, 'max_ma_m': 5000, 'margin_m': 25}, {'eoa_m': 625, 'reason': 'unlocked'}), ('boundary: length cap from the front', {'sections': [{'len': 500, 'state': 'occupied'}, {'len': 500, 'state': 'locked'}, {'len': 500, 'state': 'locked'}], 'train_sec': 0, 'offset_m': 400, 'max_ma_m': 600, 'margin_m': 25}, {'eoa_m': 1000, 'reason': 'max-length'}), ('regression: cap exactly at the obstacle', {'sections': [{'len': 500, 'state': 'occupied'}, {'len': 500, 'state': 'locked'}, {'len': 500, 'state': 'occupied'}], 'train_sec': 0, 'offset_m': 400, 'max_ma_m': 600, 'margin_m': 25}, {'eoa_m': 975, 'reason': 'occupied'}), ('control 12', {'sections': [{'len': 200, 'state': 'unlocked'}, {'len': 350, 'state': 'locked'}, {'len': 500, 'state': 'occupied'}, {'len': 200, 'state': 'occupied'}, {'len': 100, 'state': 'locked'}], 'train_sec': 2, 'offset_m': 34, 'max_ma_m': 300, 'margin_m': 50}, {'eoa_m': 884, 'reason': 'max-length'}), ('control 15', {'sections': [{'len': 100, 'state': 'locked'}, {'len': 500, 'state': 'locked'}, {'len': 350, 'state': 'locked'}, {'len': 200, 'state': 'locked'}, {'len': 350, 'state': 'occupied'}, {'len': 500, 'state': 'locked'}, {'len': 100, 'state': 'locked'}], 'train_sec': 4, 'offset_m': 137, 'max_ma_m': 5000, 'margin_m': 0}, {'eoa_m': 2100, 'reason': 'end-of-route'}), ('sampled regression 18', {'sections': [{'len': 200, 'state': 'unlocked'}, {'len': 500, 'state': 'locked'}, {'len': 350, 'state': 'unlocked'}, {'len': 200, 'state': 'occupied'}, {'len': 100, 'state': 'occupied'}, {'len': 100, 'state': 'unlocked'}], 'train_sec': 3, 'offset_m': 181, 'max_ma_m': 1000, 'margin_m': 0}, {'eoa_m': 1250, 'reason': 'occupied'})], [('regression: cap exactly at the obstacle', {'sections': [{'len': 500, 'state': 'occupied'}, {'len': 500, 'state': 'locked'}, {'len': 500, 'state': 'occupied'}], 'train_sec': 0, 'offset_m': 400, 'max_ma_m': 600, 'margin_m': 25}, {'eoa_m': 975, 'reason': 'occupied'}), ('sampled regression 22', {'sections': [{'len': 350, 'state': 'locked'}, {'len': 200, 'state': 'locked'}, {'len': 100, 'state': 'locked'}, {'len': 500, 'state': 'occupied'}, {'len': 200, 'state': 'occupied'}, {'len': 350, 'state': 'unlocked'}, {'len': 500, 'state': 'unlocked'}], 'train_sec': 4, 'offset_m': 91, 'max_ma_m': 1000, 'margin_m': 25}, {'eoa_m': 1325, 'reason': 'unlocked'}), ('sampled regression 11', {'sections': [{'len': 200, 'state': 'locked'}, {'len': 350, 'state': 'occupied'}, {'len': 100, 'state': 'unlocked'}], 'train_sec': 1, 'offset_m': 239, 'max_ma_m': 5000, 'margin_m': 50}, {'eoa_m': 500, 'reason': 'unlocked'}), ('boundary: end of route with margin', {'sections': [{'len': 100, 'state': 'occupied'}, {'len': 100, 'state': 'locked'}], 'train_sec': 0, 'offset_m': 0, 'max_ma_m': 5000, 'margin_m': 50}, {'eoa_m': 150, 'reason': 'end-of-route'}), ('regression: unlocked section margin', {'sections': [{'len': 100, 'state': 'occupied'}, {'len': 150, 'state': 'locked'}, {'len': 100, 'state': 'unlocked'}], 'train_sec': 0, 'offset_m': 20, 'max_ma_m': 5000, 'margin_m': 30}, {'eoa_m': 220, 'reason': 'unlocked'}), ('sampled regression 23', {'sections': [{'len': 350, 'state': 'occupied'}, {'len': 200, 'state': 'locked'}, {'len': 100, 'state': 'locked'}, {'len': 500, 'state': 'locked'}, {'len': 100, 'state': 'unlocked'}], 'train_sec': 0, 'offset_m': 20, 'max_ma_m': 5000, 'margin_m': 50}, {'eoa_m': 1100, 'reason': 'unlocked'}), ('control 26', {'sections': [{'len': 100, 'state': 'locked'}, {'len': 500, 'state': 'occupied'}, {'len': 200, 'state': 'locked'}], 'train_sec': 1, 'offset_m': 9, 'max_ma_m': 300, 'margin_m': 25}, {'eoa_m': 409, 'reason': 'max-length'}), ('sampled regression 29', {'sections': [{'len': 200, 'state': 'occupied'}, {'len': 500, 'state': 'occupied'}, {'len': 350, 'state': 'locked'}, {'len': 100, 'state': 'occupied'}, {'len': 100, 'state': 'occupied'}, {'len': 350, 'state': 'unlocked'}], 'train_sec': 1, 'offset_m': 288, 'max_ma_m': 600, 'margin_m': 50}, {'eoa_m': 1000, 'reason': 'occupied'})], [('regression: unlocked section margin', {'sections': [{'len': 100, 'state': 'occupied'}, {'len': 150, 'state': 'locked'}, {'len': 100, 'state': 'unlocked'}], 'train_sec': 0, 'offset_m': 20, 'max_ma_m': 5000, 'margin_m': 30}, {'eoa_m': 220, 'reason': 'unlocked'}), ('sampled regression 35', {'sections': [{'len': 100, 'state': 'locked'}, {'len': 200, 'state': 'occupied'}, {'len': 100, 'state': 'locked'}, {'len': 200, 'state': 'occupied'}, {'len': 200, 'state': 'occupied'}, {'len': 200, 'state': 'locked'}, {'len': 200, 'state': 'locked'}], 'train_sec': 3, 'offset_m': 56, 'max_ma_m': 1000, 'margin_m': 50}, {'eoa_m': 550, 'reason': 'occupied'}), ('sampled regression 19', {'sections': [{'len': 350, 'state': 'occupied'}, {'len': 500, 'state': 'locked'}, {'len': 100, 'state': 'locked'}, {'len': 500, 'state': 'unlocked'}, {'len': 100, 'state': 'locked'}, {'len': 500, 'state': 'occupied'}], 'train_sec': 0, 'offset_m': 103, 'max_ma_m': 5000, 'margin_m': 25}, {'eoa_m': 925, 'reason': 'unlocked'}), ('boundary: own section occupied', {'sections': [{'len': 200, 'state': 'occupied'}, {'len': 200, 'state': 'locked'}, {'len': 300, 'state': 'locked'}], 'train_sec': 0, 'offset_m': 50, 'max_ma_m': 5000, 'margin_m': 25}, {'eoa_m': 675, 'reason': 'end-of-route'}), ('regression: occupied section two ahead', {'sections': [{'len': 200, 'state': 'occupied'}, {'len': 200, 'state': 'locked'}, {'len': 300, 'state': 'occupied'}, {'len': 100, 'state': 'locked'}], 'train_sec': 0, 'offset_m': 100, 'max_ma_m': 5000, 'margin_m': 25}, {'eoa_m': 375, 'reason': 'occupied'}), ('sampled regression 34', {'sections': [{'len': 500, 'state': 'locked'}, {'len': 350, 'state': 'occupied'}, {'len': 350, 'state': 'unlocked'}], 'train_sec': 1, 'offset_m': 222, 'max_ma_m': 600, 'margin_m': 0}, {'eoa_m': 850, 'reason': 'unlocked'}), ('control 37', {'sections': [{'len': 500, 'state': 'occupied'}, {'len': 350, 'state': 'locked'}, {'len': 200, 'state': 'unlocked'}, {'len': 100, 'state': 'locked'}], 'train_sec': 0, 'offset_m': 2, 'max_ma_m': 600, 'margin_m': 50}, {'eoa_m': 602, 'reason': 'max-length'}), ('sampled regression 40', {'sections': [{'len': 500, 'state': 'occupied'}, {'len': 350, 'state': 'unlocked'}, {'len': 200, 'state': 'locked'}, {'len': 500, 'state': 'unlocked'}, {'len': 100, 'state': 'occupied'}, {'len': 100, 'state': 'locked'}], 'train_sec': 0, 'offset_m': 25, 'max_ma_m': 1000, 'margin_m': 0}, {'eoa_m': 500, 'reason': 'unlocked'})], [('regression: occupied section two ahead', {'sections': [{'len': 200, 'state': 'occupied'}, {'len': 200, 'state': 'locked'}, {'len': 300, 'state': 'occupied'}, {'len': 100, 'state': 'locked'}], 'train_sec': 0, 'offset_m': 100, 'max_ma_m': 5000, 'margin_m': 25}, {'eoa_m': 375, 'reason': 'occupied'}), ('sampled regression 50', {'sections': [{'len': 100, 'state': 'unlocked'}, {'len': 350, 'state': 'occupied'}, {'len': 200, 'state': 'locked'}, {'len': 500, 'state': 'occupied'}, {'len': 100, 'state': 'unlocked'}, {'len': 100, 'state': 'locked'}], 'train_sec': 3, 'offset_m': 115, 'max_ma_m': 5000, 'margin_m': 0}, {'eoa_m': 1150, 'reason': 'unlocked'}), ('sampled regression 28', {'sections': [{'len': 500, 'state': 'locked'}, {'len': 100, 'state': 'occupied'}, {'len': 200, 'state': 'locked'}, {'len': 100, 'state': 'locked'}, {'len': 350, 'state': 'locked'}, {'len': 200, 'state': 'occupied'}], 'train_sec': 1, 'offset_m': 74, 'max_ma_m': 5000, 'margin_m': 50}, {'eoa_m': 1200, 'reason': 'occupied'}), ('regression: unlocked section next', {'sections': [{'len': 200, 'state': 'locked'}, {'len': 200, 'state': 'occupied'}, {'len': 300, 'state': 'unlocked'}], 'train_sec': 1, 'offset_m': 10, 'max_ma_m': 5000, 'margin_m': 25}, {'eoa_m': 375, 'reason': 'unlocked'}), ('boundary: length cap from the front', {'sections': [{'len': 500, 'state': 'occupied'}, {'len': 500, 'state': 'locked'}, {'len': 500, 'state': 'locked'}], 'train_sec': 0, 'offset_m': 400, 'max_ma_m': 600, 'margin_m': 25}, {'eoa_m': 1000, 'reason': 'max-length'}), ('control 45', {'sections': [{'len': 350, 'state': 'unlocked'}, {'len': 200, 'state': 'locked'}, {'len': 350, 'state': 'occupied'}, {'len': 500, 'state': 'locked'}, {'len': 200, 'state': 'locked'}, {'len': 200, 'state': 'locked'}, {'len': 200, 'state': 'locked'}], 'train_sec': 2, 'offset_m': 348, 'max_ma_m': 300, 'margin_m': 25}, {'eoa_m': 1198, 'reason': 'max-length'}), ('control 48', {'sections': [{'len': 500, 'state': 'unlocked'}, {'len': 200, 'state': 'unlocked'}, {'len': 350, 'state': 'occupied'}, {'len': 350, 'state': 'locked'}, {'len': 350, 'state': 'locked'}], 'train_sec': 2, 'offset_m': 200, 'max_ma_m': 1000, 'margin_m': 25}, {'eoa_m': 1725, 'reason': 'end-of-route'}), ('sampled regression 51', {'sections': [{'len': 500, 'state': 'locked'}, {'len': 100, 'state': 'occupied'}, {'len': 500, 'state': 'locked'}, {'len': 200, 'state': 'occupied'}, {'len': 200, 'state': 'locked'}], 'train_sec': 1, 'offset_m': 18, 'max_ma_m': 600, 'margin_m': 0}, {'eoa_m': 1100, 'reason': 'occupied'})]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
regression: occupied section two ahead{'eoa_m': 675, 'reason': 'occupied'}{'eoa_m': 375, 'reason': 'occupied'}Failed
regression: unlocked section margin{'eoa_m': 320, 'reason': 'unlocked'}{'eoa_m': 220, 'reason': 'unlocked'}Failed
regression: unlocked section next{'eoa_m': 675, 'reason': 'unlocked'}{'eoa_m': 375, 'reason': 'unlocked'}Failed
boundary: own section occupied{'eoa_m': 675, 'reason': 'end-of-route'}{'eoa_m': 675, 'reason': 'end-of-route'}Passed
boundary: length cap from the front{'eoa_m': 1000, 'reason': 'max-length'}{'eoa_m': 1000, 'reason': 'max-length'}Passed
sampled regression 1{'eoa_m': 250, 'reason': 'unlocked'}{'eoa_m': 150, 'reason': 'unlocked'}Failed
control 4{'eoa_m': 1325, 'reason': 'end-of-route'}{'eoa_m': 1325, 'reason': 'end-of-route'}Passed
sampled regression 7{'eoa_m': 900, 'reason': 'unlocked'}{'eoa_m': 550, 'reason': 'unlocked'}Failed

SHA-256 / 9a4c819ac4b529a0ad9449d29a7dd0e3d62df7cef6084aaee567f3ccc34dfbf3

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    secs = x['sections']
    bounds = []
    acc = 0
    for s in secs:
        bounds.append(acc)
        acc += s['len']
    k = x['train_sec']
    eoa = acc
    reason = 'end-of-route'
    for j in range(k + 1, len(secs)):
        if secs[j]['state'] != 'locked':
            eoa = bounds[j - 1]
            reason = secs[j]['state']
            break
    front = bounds[k] + x['offset_m']
    if eoa - front > x['max_ma_m']:
        eoa = front + x['max_ma_m']
        reason = 'max-length'
    if reason != 'max-length':
        eoa -= x['margin_m']
    return {'eoa_m': eoa, 'reason': reason}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: occupied section two ahead', {'sections': [{'len': 200, 'state': 'occupied'}, {'len': 200, 'state': 'locked'}, {'len': 300, 'state': 'occupied'}, {'len': 100, 'state': 'locked'}], 'train_sec': 0, 'offset_m': 100, 'max_ma_m': 5000, 'margin_m': 25}, {'eoa_m': 375, 'reason': 'occupied'}), ('regression: unlocked section margin', {'sections': [{'len': 100, 'state': 'occupied'}, {'len': 150, 'state': 'locked'}, {'len': 100, 'state': 'unlocked'}], 'train_sec': 0, 'offset_m': 20, 'max_ma_m': 5000, 'margin_m': 30}, {'eoa_m': 220, 'reason': 'unlocked'}), ('regression: unlocked section next', {'sections': [{'len': 200, 'state': 'locked'}, {'len': 200, 'state': 'occupied'}, {'len': 300, 'state': 'unlocked'}], 'train_sec': 1, 'offset_m': 10, 'max_ma_m': 5000, 'margin_m': 25}, {'eoa_m': 375, 'reason': 'unlocked'}), ('boundary: own section occupied', {'sections': [{'len': 200, 'state': 'occupied'}, {'len': 200, 'state': 'locked'}, {'len': 300, 'state': 'locked'}], 'train_sec': 0, 'offset_m': 50, 'max_ma_m': 5000, 'margin_m': 25}, {'eoa_m': 675, 'reason': 'end-of-route'}), ('boundary: length cap from the front', {'sections': [{'len': 500, 'state': 'occupied'}, {'len': 500, 'state': 'locked'}, {'len': 500, 'state': 'locked'}], 'train_sec': 0, 'offset_m': 400, 'max_ma_m': 600, 'margin_m': 25}, {'eoa_m': 1000, 'reason': 'max-length'}), ('sampled regression 1', {'sections': [{'len': 200, 'state': 'occupied'}, {'len': 100, 'state': 'unlocked'}, {'len': 200, 'state': 'occupied'}, {'len': 350, 'state': 'locked'}], 'train_sec': 0, 'offset_m': 69, 'max_ma_m': 5000, 'margin_m': 50}, {'eoa_m': 150, 'reason': 'unlocked'}), ('control 4', {'sections': [{'len': 500, 'state': 'occupied'}, {'len': 500, 'state': 'locked'}, {'len': 350, 'state': 'locked'}], 'train_sec': 0, 'offset_m': 206, 'max_ma_m': 5000, 'margin_m': 25}, {'eoa_m': 1325, 'reason': 'end-of-route'}), ('sampled regression 7', {'sections': [{'len': 350, 'state': 'locked'}, {'len': 200, 'state': 'occupied'}, {'len': 350, 'state': 'unlocked'}, {'len': 500, 'state': 'unlocked'}, {'len': 500, 'state': 'occupied'}, {'len': 500, 'state': 'unlocked'}], 'train_sec': 1, 'offset_m': 108, 'max_ma_m': 5000, 'margin_m': 0}, {'eoa_m': 550, 'reason': 'unlocked'})], [('regression: unlocked section next', {'sections': [{'len': 200, 'state': 'locked'}, {'len': 200, 'state': 'occupied'}, {'len': 300, 'state': 'unlocked'}], 'train_sec': 1, 'offset_m': 10, 'max_ma_m': 5000, 'margin_m': 25}, {'eoa_m': 375, 'reason': 'unlocked'}), ('sampled regression 10', {'sections': [{'len': 500, 'state': 'occupied'}, {'len': 500, 'state': 'occupied'}, {'len': 500, 'state': 'locked'}, {'len': 100, 'state': 'locked'}, {'len': 200, 'state': 'locked'}, {'len': 200, 'state': 'occupied'}, {'len': 200, 'state': 'occupied'}], 'train_sec': 5, 'offset_m': 104, 'max_ma_m': 600, 'margin_m': 25}, {'eoa_m': 1975, 'reason': 'occupied'}), ('sampled regression 6', {'sections': [{'len': 350, 'state': 'occupied'}, {'len': 200, 'state': 'unlocked'}, {'len': 100, 'state': 'occupied'}, {'len': 350, 'state': 'unlocked'}, {'len': 200, 'state': 'locked'}, {'len': 100, 'state': 'locked'}], 'train_sec': 2, 'offset_m': 2, 'max_ma_m': 5000, 'margin_m': 25}, {'eoa_m': 625, 'reason': 'unlocked'}), ('boundary: length cap from the front', {'sections': [{'len': 500, 'state': 'occupied'}, {'len': 500, 'state': 'locked'}, {'len': 500, 'state': 'locked'}], 'train_sec': 0, 'offset_m': 400, 'max_ma_m': 600, 'margin_m': 25}, {'eoa_m': 1000, 'reason': 'max-length'}), ('regression: cap exactly at the obstacle', {'sections': [{'len': 500, 'state': 'occupied'}, {'len': 500, 'state': 'locked'}, {'len': 500, 'state': 'occupied'}], 'train_sec': 0, 'offset_m': 400, 'max_ma_m': 600, 'margin_m': 25}, {'eoa_m': 975, 'reason': 'occupied'}), ('control 12', {'sections': [{'len': 200, 'state': 'unlocked'}, {'len': 350, 'state': 'locked'}, {'len': 500, 'state': 'occupied'}, {'len': 200, 'state': 'occupied'}, {'len': 100, 'state': 'locked'}], 'train_sec': 2, 'offset_m': 34, 'max_ma_m': 300, 'margin_m': 50}, {'eoa_m': 884, 'reason': 'max-length'}), ('control 15', {'sections': [{'len': 100, 'state': 'locked'}, {'len': 500, 'state': 'locked'}, {'len': 350, 'state': 'locked'}, {'len': 200, 'state': 'locked'}, {'len': 350, 'state': 'occupied'}, {'len': 500, 'state': 'locked'}, {'len': 100, 'state': 'locked'}], 'train_sec': 4, 'offset_m': 137, 'max_ma_m': 5000, 'margin_m': 0}, {'eoa_m': 2100, 'reason': 'end-of-route'}), ('sampled regression 18', {'sections': [{'len': 200, 'state': 'unlocked'}, {'len': 500, 'state': 'locked'}, {'len': 350, 'state': 'unlocked'}, {'len': 200, 'state': 'occupied'}, {'len': 100, 'state': 'occupied'}, {'len': 100, 'state': 'unlocked'}], 'train_sec': 3, 'offset_m': 181, 'max_ma_m': 1000, 'margin_m': 0}, {'eoa_m': 1250, 'reason': 'occupied'})], [('regression: cap exactly at the obstacle', {'sections': [{'len': 500, 'state': 'occupied'}, {'len': 500, 'state': 'locked'}, {'len': 500, 'state': 'occupied'}], 'train_sec': 0, 'offset_m': 400, 'max_ma_m': 600, 'margin_m': 25}, {'eoa_m': 975, 'reason': 'occupied'}), ('sampled regression 22', {'sections': [{'len': 350, 'state': 'locked'}, {'len': 200, 'state': 'locked'}, {'len': 100, 'state': 'locked'}, {'len': 500, 'state': 'occupied'}, {'len': 200, 'state': 'occupied'}, {'len': 350, 'state': 'unlocked'}, {'len': 500, 'state': 'unlocked'}], 'train_sec': 4, 'offset_m': 91, 'max_ma_m': 1000, 'margin_m': 25}, {'eoa_m': 1325, 'reason': 'unlocked'}), ('sampled regression 11', {'sections': [{'len': 200, 'state': 'locked'}, {'len': 350, 'state': 'occupied'}, {'len': 100, 'state': 'unlocked'}], 'train_sec': 1, 'offset_m': 239, 'max_ma_m': 5000, 'margin_m': 50}, {'eoa_m': 500, 'reason': 'unlocked'}), ('boundary: end of route with margin', {'sections': [{'len': 100, 'state': 'occupied'}, {'len': 100, 'state': 'locked'}], 'train_sec': 0, 'offset_m': 0, 'max_ma_m': 5000, 'margin_m': 50}, {'eoa_m': 150, 'reason': 'end-of-route'}), ('regression: unlocked section margin', {'sections': [{'len': 100, 'state': 'occupied'}, {'len': 150, 'state': 'locked'}, {'len': 100, 'state': 'unlocked'}], 'train_sec': 0, 'offset_m': 20, 'max_ma_m': 5000, 'margin_m': 30}, {'eoa_m': 220, 'reason': 'unlocked'}), ('sampled regression 23', {'sections': [{'len': 350, 'state': 'occupied'}, {'len': 200, 'state': 'locked'}, {'len': 100, 'state': 'locked'}, {'len': 500, 'state': 'locked'}, {'len': 100, 'state': 'unlocked'}], 'train_sec': 0, 'offset_m': 20, 'max_ma_m': 5000, 'margin_m': 50}, {'eoa_m': 1100, 'reason': 'unlocked'}), ('control 26', {'sections': [{'len': 100, 'state': 'locked'}, {'len': 500, 'state': 'occupied'}, {'len': 200, 'state': 'locked'}], 'train_sec': 1, 'offset_m': 9, 'max_ma_m': 300, 'margin_m': 25}, {'eoa_m': 409, 'reason': 'max-length'}), ('sampled regression 29', {'sections': [{'len': 200, 'state': 'occupied'}, {'len': 500, 'state': 'occupied'}, {'len': 350, 'state': 'locked'}, {'len': 100, 'state': 'occupied'}, {'len': 100, 'state': 'occupied'}, {'len': 350, 'state': 'unlocked'}], 'train_sec': 1, 'offset_m': 288, 'max_ma_m': 600, 'margin_m': 50}, {'eoa_m': 1000, 'reason': 'occupied'})], [('regression: unlocked section margin', {'sections': [{'len': 100, 'state': 'occupied'}, {'len': 150, 'state': 'locked'}, {'len': 100, 'state': 'unlocked'}], 'train_sec': 0, 'offset_m': 20, 'max_ma_m': 5000, 'margin_m': 30}, {'eoa_m': 220, 'reason': 'unlocked'}), ('sampled regression 35', {'sections': [{'len': 100, 'state': 'locked'}, {'len': 200, 'state': 'occupied'}, {'len': 100, 'state': 'locked'}, {'len': 200, 'state': 'occupied'}, {'len': 200, 'state': 'occupied'}, {'len': 200, 'state': 'locked'}, {'len': 200, 'state': 'locked'}], 'train_sec': 3, 'offset_m': 56, 'max_ma_m': 1000, 'margin_m': 50}, {'eoa_m': 550, 'reason': 'occupied'}), ('sampled regression 19', {'sections': [{'len': 350, 'state': 'occupied'}, {'len': 500, 'state': 'locked'}, {'len': 100, 'state': 'locked'}, {'len': 500, 'state': 'unlocked'}, {'len': 100, 'state': 'locked'}, {'len': 500, 'state': 'occupied'}], 'train_sec': 0, 'offset_m': 103, 'max_ma_m': 5000, 'margin_m': 25}, {'eoa_m': 925, 'reason': 'unlocked'}), ('boundary: own section occupied', {'sections': [{'len': 200, 'state': 'occupied'}, {'len': 200, 'state': 'locked'}, {'len': 300, 'state': 'locked'}], 'train_sec': 0, 'offset_m': 50, 'max_ma_m': 5000, 'margin_m': 25}, {'eoa_m': 675, 'reason': 'end-of-route'}), ('regression: occupied section two ahead', {'sections': [{'len': 200, 'state': 'occupied'}, {'len': 200, 'state': 'locked'}, {'len': 300, 'state': 'occupied'}, {'len': 100, 'state': 'locked'}], 'train_sec': 0, 'offset_m': 100, 'max_ma_m': 5000, 'margin_m': 25}, {'eoa_m': 375, 'reason': 'occupied'}), ('sampled regression 34', {'sections': [{'len': 500, 'state': 'locked'}, {'len': 350, 'state': 'occupied'}, {'len': 350, 'state': 'unlocked'}], 'train_sec': 1, 'offset_m': 222, 'max_ma_m': 600, 'margin_m': 0}, {'eoa_m': 850, 'reason': 'unlocked'}), ('control 37', {'sections': [{'len': 500, 'state': 'occupied'}, {'len': 350, 'state': 'locked'}, {'len': 200, 'state': 'unlocked'}, {'len': 100, 'state': 'locked'}], 'train_sec': 0, 'offset_m': 2, 'max_ma_m': 600, 'margin_m': 50}, {'eoa_m': 602, 'reason': 'max-length'}), ('sampled regression 40', {'sections': [{'len': 500, 'state': 'occupied'}, {'len': 350, 'state': 'unlocked'}, {'len': 200, 'state': 'locked'}, {'len': 500, 'state': 'unlocked'}, {'len': 100, 'state': 'occupied'}, {'len': 100, 'state': 'locked'}], 'train_sec': 0, 'offset_m': 25, 'max_ma_m': 1000, 'margin_m': 0}, {'eoa_m': 500, 'reason': 'unlocked'})], [('regression: occupied section two ahead', {'sections': [{'len': 200, 'state': 'occupied'}, {'len': 200, 'state': 'locked'}, {'len': 300, 'state': 'occupied'}, {'len': 100, 'state': 'locked'}], 'train_sec': 0, 'offset_m': 100, 'max_ma_m': 5000, 'margin_m': 25}, {'eoa_m': 375, 'reason': 'occupied'}), ('sampled regression 50', {'sections': [{'len': 100, 'state': 'unlocked'}, {'len': 350, 'state': 'occupied'}, {'len': 200, 'state': 'locked'}, {'len': 500, 'state': 'occupied'}, {'len': 100, 'state': 'unlocked'}, {'len': 100, 'state': 'locked'}], 'train_sec': 3, 'offset_m': 115, 'max_ma_m': 5000, 'margin_m': 0}, {'eoa_m': 1150, 'reason': 'unlocked'}), ('sampled regression 28', {'sections': [{'len': 500, 'state': 'locked'}, {'len': 100, 'state': 'occupied'}, {'len': 200, 'state': 'locked'}, {'len': 100, 'state': 'locked'}, {'len': 350, 'state': 'locked'}, {'len': 200, 'state': 'occupied'}], 'train_sec': 1, 'offset_m': 74, 'max_ma_m': 5000, 'margin_m': 50}, {'eoa_m': 1200, 'reason': 'occupied'}), ('regression: unlocked section next', {'sections': [{'len': 200, 'state': 'locked'}, {'len': 200, 'state': 'occupied'}, {'len': 300, 'state': 'unlocked'}], 'train_sec': 1, 'offset_m': 10, 'max_ma_m': 5000, 'margin_m': 25}, {'eoa_m': 375, 'reason': 'unlocked'}), ('boundary: length cap from the front', {'sections': [{'len': 500, 'state': 'occupied'}, {'len': 500, 'state': 'locked'}, {'len': 500, 'state': 'locked'}], 'train_sec': 0, 'offset_m': 400, 'max_ma_m': 600, 'margin_m': 25}, {'eoa_m': 1000, 'reason': 'max-length'}), ('control 45', {'sections': [{'len': 350, 'state': 'unlocked'}, {'len': 200, 'state': 'locked'}, {'len': 350, 'state': 'occupied'}, {'len': 500, 'state': 'locked'}, {'len': 200, 'state': 'locked'}, {'len': 200, 'state': 'locked'}, {'len': 200, 'state': 'locked'}], 'train_sec': 2, 'offset_m': 348, 'max_ma_m': 300, 'margin_m': 25}, {'eoa_m': 1198, 'reason': 'max-length'}), ('control 48', {'sections': [{'len': 500, 'state': 'unlocked'}, {'len': 200, 'state': 'unlocked'}, {'len': 350, 'state': 'occupied'}, {'len': 350, 'state': 'locked'}, {'len': 350, 'state': 'locked'}], 'train_sec': 2, 'offset_m': 200, 'max_ma_m': 1000, 'margin_m': 25}, {'eoa_m': 1725, 'reason': 'end-of-route'}), ('sampled regression 51', {'sections': [{'len': 500, 'state': 'locked'}, {'len': 100, 'state': 'occupied'}, {'len': 500, 'state': 'locked'}, {'len': 200, 'state': 'occupied'}, {'len': 200, 'state': 'locked'}], 'train_sec': 1, 'offset_m': 18, 'max_ma_m': 600, 'margin_m': 0}, {'eoa_m': 1100, 'reason': 'occupied'})]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
regression: occupied section two ahead{'eoa_m': 175, 'reason': 'occupied'}{'eoa_m': 375, 'reason': 'occupied'}Failed
regression: unlocked section margin{'eoa_m': 70, 'reason': 'unlocked'}{'eoa_m': 220, 'reason': 'unlocked'}Failed
regression: unlocked section next{'eoa_m': 175, 'reason': 'unlocked'}{'eoa_m': 375, 'reason': 'unlocked'}Failed
boundary: own section occupied{'eoa_m': 675, 'reason': 'end-of-route'}{'eoa_m': 675, 'reason': 'end-of-route'}Passed
boundary: length cap from the front{'eoa_m': 1000, 'reason': 'max-length'}{'eoa_m': 1000, 'reason': 'max-length'}Passed
sampled regression 1{'eoa_m': -50, 'reason': 'unlocked'}{'eoa_m': 150, 'reason': 'unlocked'}Failed
control 4{'eoa_m': 1325, 'reason': 'end-of-route'}{'eoa_m': 1325, 'reason': 'end-of-route'}Passed
sampled regression 7{'eoa_m': 350, 'reason': 'unlocked'}{'eoa_m': 550, 'reason': 'unlocked'}Failed

SHA-256 / bf0dbfd024b499c92f68aed51ae2148081c39ae8a3579a73eb27b471cc17985b

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    secs = x['sections']
    bounds = []
    acc = 0
    for s in secs:
        bounds.append(acc)
        acc += s['len']
    k = x['train_sec']
    eoa = acc
    reason = 'end-of-route'
    for j in range(k + 1, len(secs)):
        if secs[j]['state'] != 'locked':
            eoa = bounds[j]
            reason = secs[j]['state']
            break
    front = bounds[k] + x['offset_m']
    if eoa - front > x['max_ma_m']:
        eoa = front + x['max_ma_m']
        reason = 'max-length'
    if reason != 'max-length':
        eoa -= x['margin_m']
    return {'eoa_m': eoa, 'reason': reason}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: occupied section two ahead', {'sections': [{'len': 200, 'state': 'occupied'}, {'len': 200, 'state': 'locked'}, {'len': 300, 'state': 'occupied'}, {'len': 100, 'state': 'locked'}], 'train_sec': 0, 'offset_m': 100, 'max_ma_m': 5000, 'margin_m': 25}, {'eoa_m': 375, 'reason': 'occupied'}), ('regression: unlocked section margin', {'sections': [{'len': 100, 'state': 'occupied'}, {'len': 150, 'state': 'locked'}, {'len': 100, 'state': 'unlocked'}], 'train_sec': 0, 'offset_m': 20, 'max_ma_m': 5000, 'margin_m': 30}, {'eoa_m': 220, 'reason': 'unlocked'}), ('regression: unlocked section next', {'sections': [{'len': 200, 'state': 'locked'}, {'len': 200, 'state': 'occupied'}, {'len': 300, 'state': 'unlocked'}], 'train_sec': 1, 'offset_m': 10, 'max_ma_m': 5000, 'margin_m': 25}, {'eoa_m': 375, 'reason': 'unlocked'}), ('boundary: own section occupied', {'sections': [{'len': 200, 'state': 'occupied'}, {'len': 200, 'state': 'locked'}, {'len': 300, 'state': 'locked'}], 'train_sec': 0, 'offset_m': 50, 'max_ma_m': 5000, 'margin_m': 25}, {'eoa_m': 675, 'reason': 'end-of-route'}), ('boundary: length cap from the front', {'sections': [{'len': 500, 'state': 'occupied'}, {'len': 500, 'state': 'locked'}, {'len': 500, 'state': 'locked'}], 'train_sec': 0, 'offset_m': 400, 'max_ma_m': 600, 'margin_m': 25}, {'eoa_m': 1000, 'reason': 'max-length'}), ('sampled regression 1', {'sections': [{'len': 200, 'state': 'occupied'}, {'len': 100, 'state': 'unlocked'}, {'len': 200, 'state': 'occupied'}, {'len': 350, 'state': 'locked'}], 'train_sec': 0, 'offset_m': 69, 'max_ma_m': 5000, 'margin_m': 50}, {'eoa_m': 150, 'reason': 'unlocked'}), ('control 4', {'sections': [{'len': 500, 'state': 'occupied'}, {'len': 500, 'state': 'locked'}, {'len': 350, 'state': 'locked'}], 'train_sec': 0, 'offset_m': 206, 'max_ma_m': 5000, 'margin_m': 25}, {'eoa_m': 1325, 'reason': 'end-of-route'}), ('sampled regression 7', {'sections': [{'len': 350, 'state': 'locked'}, {'len': 200, 'state': 'occupied'}, {'len': 350, 'state': 'unlocked'}, {'len': 500, 'state': 'unlocked'}, {'len': 500, 'state': 'occupied'}, {'len': 500, 'state': 'unlocked'}], 'train_sec': 1, 'offset_m': 108, 'max_ma_m': 5000, 'margin_m': 0}, {'eoa_m': 550, 'reason': 'unlocked'})], [('regression: unlocked section next', {'sections': [{'len': 200, 'state': 'locked'}, {'len': 200, 'state': 'occupied'}, {'len': 300, 'state': 'unlocked'}], 'train_sec': 1, 'offset_m': 10, 'max_ma_m': 5000, 'margin_m': 25}, {'eoa_m': 375, 'reason': 'unlocked'}), ('sampled regression 10', {'sections': [{'len': 500, 'state': 'occupied'}, {'len': 500, 'state': 'occupied'}, {'len': 500, 'state': 'locked'}, {'len': 100, 'state': 'locked'}, {'len': 200, 'state': 'locked'}, {'len': 200, 'state': 'occupied'}, {'len': 200, 'state': 'occupied'}], 'train_sec': 5, 'offset_m': 104, 'max_ma_m': 600, 'margin_m': 25}, {'eoa_m': 1975, 'reason': 'occupied'}), ('sampled regression 6', {'sections': [{'len': 350, 'state': 'occupied'}, {'len': 200, 'state': 'unlocked'}, {'len': 100, 'state': 'occupied'}, {'len': 350, 'state': 'unlocked'}, {'len': 200, 'state': 'locked'}, {'len': 100, 'state': 'locked'}], 'train_sec': 2, 'offset_m': 2, 'max_ma_m': 5000, 'margin_m': 25}, {'eoa_m': 625, 'reason': 'unlocked'}), ('boundary: length cap from the front', {'sections': [{'len': 500, 'state': 'occupied'}, {'len': 500, 'state': 'locked'}, {'len': 500, 'state': 'locked'}], 'train_sec': 0, 'offset_m': 400, 'max_ma_m': 600, 'margin_m': 25}, {'eoa_m': 1000, 'reason': 'max-length'}), ('regression: cap exactly at the obstacle', {'sections': [{'len': 500, 'state': 'occupied'}, {'len': 500, 'state': 'locked'}, {'len': 500, 'state': 'occupied'}], 'train_sec': 0, 'offset_m': 400, 'max_ma_m': 600, 'margin_m': 25}, {'eoa_m': 975, 'reason': 'occupied'}), ('control 12', {'sections': [{'len': 200, 'state': 'unlocked'}, {'len': 350, 'state': 'locked'}, {'len': 500, 'state': 'occupied'}, {'len': 200, 'state': 'occupied'}, {'len': 100, 'state': 'locked'}], 'train_sec': 2, 'offset_m': 34, 'max_ma_m': 300, 'margin_m': 50}, {'eoa_m': 884, 'reason': 'max-length'}), ('control 15', {'sections': [{'len': 100, 'state': 'locked'}, {'len': 500, 'state': 'locked'}, {'len': 350, 'state': 'locked'}, {'len': 200, 'state': 'locked'}, {'len': 350, 'state': 'occupied'}, {'len': 500, 'state': 'locked'}, {'len': 100, 'state': 'locked'}], 'train_sec': 4, 'offset_m': 137, 'max_ma_m': 5000, 'margin_m': 0}, {'eoa_m': 2100, 'reason': 'end-of-route'}), ('sampled regression 18', {'sections': [{'len': 200, 'state': 'unlocked'}, {'len': 500, 'state': 'locked'}, {'len': 350, 'state': 'unlocked'}, {'len': 200, 'state': 'occupied'}, {'len': 100, 'state': 'occupied'}, {'len': 100, 'state': 'unlocked'}], 'train_sec': 3, 'offset_m': 181, 'max_ma_m': 1000, 'margin_m': 0}, {'eoa_m': 1250, 'reason': 'occupied'})], [('regression: cap exactly at the obstacle', {'sections': [{'len': 500, 'state': 'occupied'}, {'len': 500, 'state': 'locked'}, {'len': 500, 'state': 'occupied'}], 'train_sec': 0, 'offset_m': 400, 'max_ma_m': 600, 'margin_m': 25}, {'eoa_m': 975, 'reason': 'occupied'}), ('sampled regression 22', {'sections': [{'len': 350, 'state': 'locked'}, {'len': 200, 'state': 'locked'}, {'len': 100, 'state': 'locked'}, {'len': 500, 'state': 'occupied'}, {'len': 200, 'state': 'occupied'}, {'len': 350, 'state': 'unlocked'}, {'len': 500, 'state': 'unlocked'}], 'train_sec': 4, 'offset_m': 91, 'max_ma_m': 1000, 'margin_m': 25}, {'eoa_m': 1325, 'reason': 'unlocked'}), ('sampled regression 11', {'sections': [{'len': 200, 'state': 'locked'}, {'len': 350, 'state': 'occupied'}, {'len': 100, 'state': 'unlocked'}], 'train_sec': 1, 'offset_m': 239, 'max_ma_m': 5000, 'margin_m': 50}, {'eoa_m': 500, 'reason': 'unlocked'}), ('boundary: end of route with margin', {'sections': [{'len': 100, 'state': 'occupied'}, {'len': 100, 'state': 'locked'}], 'train_sec': 0, 'offset_m': 0, 'max_ma_m': 5000, 'margin_m': 50}, {'eoa_m': 150, 'reason': 'end-of-route'}), ('regression: unlocked section margin', {'sections': [{'len': 100, 'state': 'occupied'}, {'len': 150, 'state': 'locked'}, {'len': 100, 'state': 'unlocked'}], 'train_sec': 0, 'offset_m': 20, 'max_ma_m': 5000, 'margin_m': 30}, {'eoa_m': 220, 'reason': 'unlocked'}), ('sampled regression 23', {'sections': [{'len': 350, 'state': 'occupied'}, {'len': 200, 'state': 'locked'}, {'len': 100, 'state': 'locked'}, {'len': 500, 'state': 'locked'}, {'len': 100, 'state': 'unlocked'}], 'train_sec': 0, 'offset_m': 20, 'max_ma_m': 5000, 'margin_m': 50}, {'eoa_m': 1100, 'reason': 'unlocked'}), ('control 26', {'sections': [{'len': 100, 'state': 'locked'}, {'len': 500, 'state': 'occupied'}, {'len': 200, 'state': 'locked'}], 'train_sec': 1, 'offset_m': 9, 'max_ma_m': 300, 'margin_m': 25}, {'eoa_m': 409, 'reason': 'max-length'}), ('sampled regression 29', {'sections': [{'len': 200, 'state': 'occupied'}, {'len': 500, 'state': 'occupied'}, {'len': 350, 'state': 'locked'}, {'len': 100, 'state': 'occupied'}, {'len': 100, 'state': 'occupied'}, {'len': 350, 'state': 'unlocked'}], 'train_sec': 1, 'offset_m': 288, 'max_ma_m': 600, 'margin_m': 50}, {'eoa_m': 1000, 'reason': 'occupied'})], [('regression: unlocked section margin', {'sections': [{'len': 100, 'state': 'occupied'}, {'len': 150, 'state': 'locked'}, {'len': 100, 'state': 'unlocked'}], 'train_sec': 0, 'offset_m': 20, 'max_ma_m': 5000, 'margin_m': 30}, {'eoa_m': 220, 'reason': 'unlocked'}), ('sampled regression 35', {'sections': [{'len': 100, 'state': 'locked'}, {'len': 200, 'state': 'occupied'}, {'len': 100, 'state': 'locked'}, {'len': 200, 'state': 'occupied'}, {'len': 200, 'state': 'occupied'}, {'len': 200, 'state': 'locked'}, {'len': 200, 'state': 'locked'}], 'train_sec': 3, 'offset_m': 56, 'max_ma_m': 1000, 'margin_m': 50}, {'eoa_m': 550, 'reason': 'occupied'}), ('sampled regression 19', {'sections': [{'len': 350, 'state': 'occupied'}, {'len': 500, 'state': 'locked'}, {'len': 100, 'state': 'locked'}, {'len': 500, 'state': 'unlocked'}, {'len': 100, 'state': 'locked'}, {'len': 500, 'state': 'occupied'}], 'train_sec': 0, 'offset_m': 103, 'max_ma_m': 5000, 'margin_m': 25}, {'eoa_m': 925, 'reason': 'unlocked'}), ('boundary: own section occupied', {'sections': [{'len': 200, 'state': 'occupied'}, {'len': 200, 'state': 'locked'}, {'len': 300, 'state': 'locked'}], 'train_sec': 0, 'offset_m': 50, 'max_ma_m': 5000, 'margin_m': 25}, {'eoa_m': 675, 'reason': 'end-of-route'}), ('regression: occupied section two ahead', {'sections': [{'len': 200, 'state': 'occupied'}, {'len': 200, 'state': 'locked'}, {'len': 300, 'state': 'occupied'}, {'len': 100, 'state': 'locked'}], 'train_sec': 0, 'offset_m': 100, 'max_ma_m': 5000, 'margin_m': 25}, {'eoa_m': 375, 'reason': 'occupied'}), ('sampled regression 34', {'sections': [{'len': 500, 'state': 'locked'}, {'len': 350, 'state': 'occupied'}, {'len': 350, 'state': 'unlocked'}], 'train_sec': 1, 'offset_m': 222, 'max_ma_m': 600, 'margin_m': 0}, {'eoa_m': 850, 'reason': 'unlocked'}), ('control 37', {'sections': [{'len': 500, 'state': 'occupied'}, {'len': 350, 'state': 'locked'}, {'len': 200, 'state': 'unlocked'}, {'len': 100, 'state': 'locked'}], 'train_sec': 0, 'offset_m': 2, 'max_ma_m': 600, 'margin_m': 50}, {'eoa_m': 602, 'reason': 'max-length'}), ('sampled regression 40', {'sections': [{'len': 500, 'state': 'occupied'}, {'len': 350, 'state': 'unlocked'}, {'len': 200, 'state': 'locked'}, {'len': 500, 'state': 'unlocked'}, {'len': 100, 'state': 'occupied'}, {'len': 100, 'state': 'locked'}], 'train_sec': 0, 'offset_m': 25, 'max_ma_m': 1000, 'margin_m': 0}, {'eoa_m': 500, 'reason': 'unlocked'})], [('regression: occupied section two ahead', {'sections': [{'len': 200, 'state': 'occupied'}, {'len': 200, 'state': 'locked'}, {'len': 300, 'state': 'occupied'}, {'len': 100, 'state': 'locked'}], 'train_sec': 0, 'offset_m': 100, 'max_ma_m': 5000, 'margin_m': 25}, {'eoa_m': 375, 'reason': 'occupied'}), ('sampled regression 50', {'sections': [{'len': 100, 'state': 'unlocked'}, {'len': 350, 'state': 'occupied'}, {'len': 200, 'state': 'locked'}, {'len': 500, 'state': 'occupied'}, {'len': 100, 'state': 'unlocked'}, {'len': 100, 'state': 'locked'}], 'train_sec': 3, 'offset_m': 115, 'max_ma_m': 5000, 'margin_m': 0}, {'eoa_m': 1150, 'reason': 'unlocked'}), ('sampled regression 28', {'sections': [{'len': 500, 'state': 'locked'}, {'len': 100, 'state': 'occupied'}, {'len': 200, 'state': 'locked'}, {'len': 100, 'state': 'locked'}, {'len': 350, 'state': 'locked'}, {'len': 200, 'state': 'occupied'}], 'train_sec': 1, 'offset_m': 74, 'max_ma_m': 5000, 'margin_m': 50}, {'eoa_m': 1200, 'reason': 'occupied'}), ('regression: unlocked section next', {'sections': [{'len': 200, 'state': 'locked'}, {'len': 200, 'state': 'occupied'}, {'len': 300, 'state': 'unlocked'}], 'train_sec': 1, 'offset_m': 10, 'max_ma_m': 5000, 'margin_m': 25}, {'eoa_m': 375, 'reason': 'unlocked'}), ('boundary: length cap from the front', {'sections': [{'len': 500, 'state': 'occupied'}, {'len': 500, 'state': 'locked'}, {'len': 500, 'state': 'locked'}], 'train_sec': 0, 'offset_m': 400, 'max_ma_m': 600, 'margin_m': 25}, {'eoa_m': 1000, 'reason': 'max-length'}), ('control 45', {'sections': [{'len': 350, 'state': 'unlocked'}, {'len': 200, 'state': 'locked'}, {'len': 350, 'state': 'occupied'}, {'len': 500, 'state': 'locked'}, {'len': 200, 'state': 'locked'}, {'len': 200, 'state': 'locked'}, {'len': 200, 'state': 'locked'}], 'train_sec': 2, 'offset_m': 348, 'max_ma_m': 300, 'margin_m': 25}, {'eoa_m': 1198, 'reason': 'max-length'}), ('control 48', {'sections': [{'len': 500, 'state': 'unlocked'}, {'len': 200, 'state': 'unlocked'}, {'len': 350, 'state': 'occupied'}, {'len': 350, 'state': 'locked'}, {'len': 350, 'state': 'locked'}], 'train_sec': 2, 'offset_m': 200, 'max_ma_m': 1000, 'margin_m': 25}, {'eoa_m': 1725, 'reason': 'end-of-route'}), ('sampled regression 51', {'sections': [{'len': 500, 'state': 'locked'}, {'len': 100, 'state': 'occupied'}, {'len': 500, 'state': 'locked'}, {'len': 200, 'state': 'occupied'}, {'len': 200, 'state': 'locked'}], 'train_sec': 1, 'offset_m': 18, 'max_ma_m': 600, 'margin_m': 0}, {'eoa_m': 1100, 'reason': 'occupied'})]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
regression: occupied section two ahead{'eoa_m': 375, 'reason': 'occupied'}{'eoa_m': 375, 'reason': 'occupied'}Passed
regression: unlocked section margin{'eoa_m': 220, 'reason': 'unlocked'}{'eoa_m': 220, 'reason': 'unlocked'}Passed
regression: unlocked section next{'eoa_m': 375, 'reason': 'unlocked'}{'eoa_m': 375, 'reason': 'unlocked'}Passed
boundary: own section occupied{'eoa_m': 675, 'reason': 'end-of-route'}{'eoa_m': 675, 'reason': 'end-of-route'}Passed
boundary: length cap from the front{'eoa_m': 1000, 'reason': 'max-length'}{'eoa_m': 1000, 'reason': 'max-length'}Passed
sampled regression 1{'eoa_m': 150, 'reason': 'unlocked'}{'eoa_m': 150, 'reason': 'unlocked'}Passed
control 4{'eoa_m': 1325, 'reason': 'end-of-route'}{'eoa_m': 1325, 'reason': 'end-of-route'}Passed
sampled regression 7{'eoa_m': 550, 'reason': 'unlocked'}{'eoa_m': 550, 'reason': 'unlocked'}Passed

SHA-256 / 419ba4cbacb3b1656703a9badaeffe4613037138bc5eb01a595957d9328eb049

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

Case digest / c68674dd37de64ce798499ed33f5192a525164cb833344b3f09a29391e163080