FAILURE MAP
← Case archive

FA-68286 / Traffic signal timing plans / Open access

Conflict monitor fault scan: compatible pairs are stored in the order given · case 01

Conflict monitor fault scan returns a wrong result when compatible pairs are stored in the order given.

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

ROOT CAUSE

A compatibility entry written high-low never matches the ascending live pair, so permitted concurrency is reported as conflict.

VERIFIED REPAIR

Restore the compatibility pair normalisation rule so that the step reads `(min(a, b), max(a, b))`.

Unsuccessful approach: Normalising to descending order breaks the ascending lookup for every pair.

Case contract

Input {channels: [[channel, lit colors string over R/Y/G, enabled]], compat: unordered compatible pairs, yellow_durations: [[channel, tenths]]}. Disabled channels are ignored entirely. A channel with more than one lit color is 'multi'; with none lit is 'red-fail'; any channel showing G or Y takes part in the conflict check, and every live pair not listed as compatible is 'conflict:a-b' (a<b). A completed yellow shorter than 2.7 s is 'short-yellow'. Return the sorted fault strings.

Why this case matters

Signal timing arithmetic is exact and integer or rational; a wrong rule silently produces unsafe or inefficient timing plans.

1 / The failure

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

N = 1
observations = []
def solve(x):
    ok = {(a, b) for a, b in x['compat']}
    faults = []
    live = []
    for ch, col, en in x['channels']:
        if not en:
            continue
        if len(col) > 1:
            faults.append('multi:%d' % ch)
        if col == '':
            faults.append('red-fail:%d' % ch)
        if 'G' in col or 'Y' in col:
            live.append(ch)
    live.sort()
    for i in range(len(live)):
        for j in range(i + 1, len(live)):
            if (live[i], live[j]) not in ok:
                faults.append('conflict:%d-%d' % (live[i], live[j]))
    for ch, tenths in x['yellow_durations']:
        if tenths < 27:
            faults.append('short-yellow:%d' % ch)
    return sorted(faults)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[({'channels': [[1, 'G', True], [2, 'R', True], [3, 'Y', True], [4, 'G', False]], 'compat': [[3, 1]], 'yellow_durations': [[2, 27]]}, []), ({'channels': [[1, 'GY', False], [2, '', True], [3, 'Y', True], [4, 'R', True], [5, 'G', True], [6, 'R', True]], 'compat': [[1, 3], [1, 4], [1, 5], [2, 4], [3, 6], [4, 5], [6, 4], [5, 6]], 'yellow_durations': [[3, 30], [5, 28]]}, ['conflict:3-5', 'red-fail:2']), ({'channels': [[1, '', True], [2, 'R', True], [3, 'R', True], [4, 'G', True]], 'compat': [[2, 1], [1, 4], [4, 2]], 'yellow_durations': [[4, 26]]}, ['red-fail:1', 'short-yellow:4']), ({'channels': [[1, 'RG', True], [2, 'R', True], [3, 'R', False], [4, 'R', True], [5, 'GY', True], [6, 'Y', True]], 'compat': [[2, 1], [3, 1], [5, 1], [3, 4], [5, 3], [6, 3], [6, 5]], 'yellow_durations': [[5, 27]]}, ['conflict:1-6', 'multi:1', 'multi:5']), ({'channels': [[1, '', True], [2, 'GY', True], [3, 'RG', True], [4, 'G', True], [5, 'GY', True], [6, 'R', True]], 'compat': [[1, 3], [4, 1], [2, 3], [3, 5], [5, 4]], 'yellow_durations': [[1, 28], [6, 30]]}, ['conflict:2-4', 'conflict:2-5', 'conflict:3-4', 'multi:2', 'multi:3', 'multi:5', 'red-fail:1']), ({'channels': [[1, 'GY', True], [2, 'G', True], [3, '', True]], 'compat': [], 'yellow_durations': [[1, 26]]}, ['conflict:1-2', 'multi:1', 'red-fail:3', 'short-yellow:1']), ({'channels': [[1, '', True], [2, 'GY', True], [3, 'RY', True], [4, 'Y', True], [5, 'R', True]], 'compat': [[1, 2], [1, 4], [2, 4], [5, 2], [3, 4], [5, 3]], 'yellow_durations': [[3, 25], [4, 25]]}, ['conflict:2-3', 'multi:2', 'multi:3', 'red-fail:1', 'short-yellow:3', 'short-yellow:4']), ({'channels': [[1, 'R', True], [2, '', True], [3, 'RY', True], [4, 'RG', True]], 'compat': [[3, 1], [4, 1], [4, 2]], 'yellow_durations': [[1, 26], [2, 26]]}, ['conflict:3-4', 'multi:3', 'multi:4', 'red-fail:2', 'short-yellow:1', 'short-yellow:2'])], [({'channels': [[1, 'R', True], [2, 'Y', True], [3, '', True]], 'compat': [[1, 3]], 'yellow_durations': [[1, 26], [2, 26], [3, 26]]}, ['red-fail:3', 'short-yellow:1', 'short-yellow:2', 'short-yellow:3']), ({'channels': [[1, 'R', True], [2, 'Y', False], [3, 'GY', True], [4, 'GY', True], [5, 'GY', True]], 'compat': [[2, 3], [2, 5], [4, 5]], 'yellow_durations': [[3, 27], [5, 30]]}, ['conflict:3-4', 'conflict:3-5', 'multi:3', 'multi:4', 'multi:5']), ({'channels': [[1, 'R', True], [2, 'RG', False], [3, 'Y', True], [4, 'R', True], [5, 'Y', False], [6, 'RY', True]], 'compat': [[5, 1], [3, 4], [3, 5], [4, 5], [5, 6]], 'yellow_durations': [[5, 30]]}, ['conflict:3-6', 'multi:6']), ({'channels': [[1, 'G', True], [2, 'R', True], [3, 'Y', True], [4, 'G', False]], 'compat': [[3, 1]], 'yellow_durations': [[2, 27]]}, []), ({'channels': [[1, 'Y', True], [2, 'GY', True], [3, 'GY', True], [4, 'G', True], [5, 'G', True], [6, 'Y', True]], 'compat': [[1, 2], [1, 4], [5, 1], [4, 2], [5, 2], [5, 3], [4, 6], [5, 6]], 'yellow_durations': [[4, 30], [6, 25]]}, ['conflict:1-3', 'conflict:1-6', 'conflict:2-3', 'conflict:2-6', 'conflict:3-4', 'conflict:3-6', 'conflict:4-5', 'multi:2', 'multi:3', 'short-yellow:6']), ({'channels': [[1, '', True], [2, 'R', True], [3, 'R', True], [4, 'R', True], [5, 'R', True], [6, 'R', True]], 'compat': [[1, 3], [5, 3], [3, 6], [5, 4], [6, 4]], 'yellow_durations': [[2, 28]]}, ['red-fail:1']), ({'channels': [[1, 'Y', True], [2, 'GY', True], [3, 'Y', True], [4, 'GY', True], [5, 'GY', True], [6, 'R', True]], 'compat': [[1, 2], [4, 2], [6, 2], [4, 3], [3, 5], [3, 6], [6, 5]], 'yellow_durations': [[2, 35], [4, 28]]}, ['conflict:1-3', 'conflict:1-4', 'conflict:1-5', 'conflict:2-3', 'conflict:2-5', 'conflict:4-5', 'multi:2', 'multi:4', 'multi:5']), ({'channels': [[1, 'GY', True], [2, 'G', True], [3, '', True]], 'compat': [], 'yellow_durations': [[1, 26]]}, ['conflict:1-2', 'multi:1', 'red-fail:3', 'short-yellow:1'])], [({'channels': [[1, 'R', True], [2, 'GY', True], [3, 'Y', True], [4, '', True], [5, 'RY', True], [6, 'R', False]], 'compat': [[4, 1], [1, 6], [4, 2], [4, 3], [5, 4]], 'yellow_durations': [[1, 26], [2, 26]]}, ['conflict:2-3', 'conflict:2-5', 'conflict:3-5', 'multi:2', 'multi:5', 'red-fail:4', 'short-yellow:1', 'short-yellow:2']), ({'channels': [[1, 'Y', True], [2, '', True], [3, 'Y', True], [4, 'R', True]], 'compat': [[3, 1], [4, 1], [3, 2], [4, 2]], 'yellow_durations': []}, ['red-fail:2']), ({'channels': [[1, 'G', True], [2, 'R', True], [3, 'Y', True], [4, 'G', False]], 'compat': [[3, 1]], 'yellow_durations': [[2, 27]]}, []), ({'channels': [[1, 'RG', True], [2, 'R', True], [3, 'R', True], [4, '', True], [5, 'G', True], [6, 'RY', True]], 'compat': [[5, 3]], 'yellow_durations': []}, ['conflict:1-5', 'conflict:1-6', 'conflict:5-6', 'multi:1', 'multi:6', 'red-fail:4']), ({'channels': [[1, 'R', True], [2, 'R', True], [3, 'GY', False], [4, 'R', False], [5, 'R', True], [6, 'RY', True]], 'compat': [[3, 1], [5, 1], [4, 3], [6, 3], [4, 5]], 'yellow_durations': [[2, 28]]}, ['multi:6']), ({'channels': [[1, 'GY', True], [2, 'G', True], [3, '', True]], 'compat': [], 'yellow_durations': [[1, 26]]}, ['conflict:1-2', 'multi:1', 'red-fail:3', 'short-yellow:1']), ({'channels': [[1, 'R', True], [2, 'RG', True], [3, '', True], [4, 'R', True]], 'compat': [], 'yellow_durations': [[1, 28], [3, 26], [4, 25]]}, ['multi:2', 'red-fail:3', 'short-yellow:3', 'short-yellow:4']), ({'channels': [[1, 'R', True], [2, 'GY', True], [3, 'GY', True], [4, 'GY', True]], 'compat': [[4, 3]], 'yellow_durations': []}, ['conflict:2-3', 'conflict:2-4', 'multi:2', 'multi:3', 'multi:4'])], [({'channels': [[1, 'G', True], [2, 'R', True], [3, '', True], [4, 'G', True], [5, 'R', True]], 'compat': [[4, 1], [5, 1], [3, 2], [3, 4]], 'yellow_durations': [[5, 25]]}, ['red-fail:3', 'short-yellow:5']), ({'channels': [[1, '', True], [2, 'Y', True], [3, 'GY', True], [4, 'Y', False]], 'compat': [[1, 2], [3, 1], [4, 1], [3, 4]], 'yellow_durations': [[4, 25]]}, ['conflict:2-3', 'multi:3', 'red-fail:1', 'short-yellow:4']), ({'channels': [[1, 'GY', True], [2, 'G', True], [3, '', True]], 'compat': [], 'yellow_durations': [[1, 26]]}, ['conflict:1-2', 'multi:1', 'red-fail:3', 'short-yellow:1']), ({'channels': [[1, 'R', True], [2, 'RY', True], [3, 'GY', True], [4, 'G', False], [5, 'RG', False], [6, 'R', True]], 'compat': [[3, 1], [5, 1], [3, 2], [2, 5], [6, 2], [6, 3]], 'yellow_durations': [[2, 25], [5, 35]]}, ['multi:2', 'multi:3', 'short-yellow:2']), ({'channels': [[1, 'G', True], [2, 'R', True], [3, 'Y', True], [4, 'G', False]], 'compat': [[3, 1]], 'yellow_durations': [[2, 27]]}, []), ({'channels': [[1, 'G', True], [2, 'GY', True], [3, 'R', True], [4, 'R', True], [5, 'R', True], [6, 'R', True]], 'compat': [[4, 1], [2, 6], [3, 4], [6, 5]], 'yellow_durations': [[1, 26], [2, 28]]}, ['conflict:1-2', 'multi:2', 'short-yellow:1']), ({'channels': [[1, 'Y', False], [2, '', True], [3, '', True], [4, '', True], [5, 'RG', True]], 'compat': [[1, 3], [1, 4], [1, 5], [3, 4], [5, 3], [4, 5]], 'yellow_durations': [[4, 28]]}, ['multi:5', 'red-fail:2', 'red-fail:3', 'red-fail:4']), ({'channels': [[1, 'R', True], [2, 'G', True], [3, '', True]], 'compat': [[1, 3]], 'yellow_durations': []}, ['red-fail:3'])], [({'channels': [[1, 'G', True], [2, 'R', True], [3, 'Y', True], [4, 'G', False]], 'compat': [[3, 1]], 'yellow_durations': [[2, 27]]}, []), ({'channels': [[1, 'GY', True], [2, 'R', True], [3, 'RY', True], [4, 'RY', True], [5, 'R', True], [6, 'RY', False]], 'compat': [[2, 1], [1, 3], [4, 1], [5, 1], [2, 3], [4, 2], [2, 6], [4, 5], [4, 6]], 'yellow_durations': []}, ['conflict:3-4', 'multi:1', 'multi:3', 'multi:4']), ({'channels': [[1, 'R', True], [2, '', True], [3, 'G', True]], 'compat': [[1, 2], [3, 1], [2, 3]], 'yellow_durations': [[2, 35], [3, 25]]}, ['red-fail:2', 'short-yellow:3']), ({'channels': [[1, 'R', True], [2, 'GY', False], [3, 'R', True]], 'compat': [[3, 1], [2, 3]], 'yellow_durations': [[1, 35]]}, []), ({'channels': [[1, 'GY', True], [2, 'G', True], [3, '', True]], 'compat': [], 'yellow_durations': [[1, 26]]}, ['conflict:1-2', 'multi:1', 'red-fail:3', 'short-yellow:1']), ({'channels': [[1, 'RG', True], [2, 'R', True], [3, 'R', True], [4, '', True], [5, 'R', True], [6, 'RG', True]], 'compat': [[4, 1], [3, 2], [2, 4], [6, 2], [3, 6]], 'yellow_durations': []}, ['conflict:1-6', 'multi:1', 'multi:6', 'red-fail:4']), ({'channels': [[1, '', True], [2, 'GY', True], [3, 'R', False], [4, 'RY', True]], 'compat': [[3, 1], [4, 2]], 'yellow_durations': [[1, 26], [3, 25]]}, ['multi:2', 'multi:4', 'red-fail:1', 'short-yellow:1', 'short-yellow:3']), ({'channels': [[1, 'RG', True], [2, '', True], [3, 'Y', True]], 'compat': [[1, 2], [1, 3], [3, 2]], 'yellow_durations': [[2, 35], [3, 28]]}, ['multi:1', 'red-fail:2'])]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check('timing oracle' + ' %d' % i, 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
timing oracle 0['conflict:1-3'][]Failed
timing oracle 1['conflict:3-5', 'red-fail:2']['conflict:3-5', 'red-fail:2']Passed
timing oracle 2['red-fail:1', 'short-yellow:4']['red-fail:1', 'short-yellow:4']Passed
timing oracle 3['conflict:1-5', 'conflict:1-6', 'conflict:5-6', 'multi:1', 'multi:5']['conflict:1-6', 'multi:1', 'multi:5']Failed
timing oracle 4['conflict:2-4', 'conflict:2-5', 'conflict:3-4', 'conflict:4-5', 'multi:2', 'multi:3', 'multi:5', 'red-fail:1']['conflict:2-4', 'conflict:2-5', 'conflict:3-4', 'multi:2', 'multi:3', 'multi:5', 'red-fail:1']Failed
timing oracle 5['conflict:1-2', 'multi:1', 'red-fail:3', 'short-yellow:1']['conflict:1-2', 'multi:1', 'red-fail:3', 'short-yellow:1']Passed
timing oracle 6['conflict:2-3', 'multi:2', 'multi:3', 'red-fail:1', 'short-yellow:3', 'short-yellow:4']['conflict:2-3', 'multi:2', 'multi:3', 'red-fail:1', 'short-yellow:3', 'short-yellow:4']Passed
timing oracle 7['conflict:3-4', 'multi:3', 'multi:4', 'red-fail:2', 'short-yellow:1', 'short-yellow:2']['conflict:3-4', 'multi:3', 'multi:4', 'red-fail:2', 'short-yellow:1', 'short-yellow:2']Passed

SHA-256 / aa6ba0864182cfc046f1e6bb1288475abfa386ce14a41657add83e9643078a83

2 / The unsuccessful fix

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

N = 1
observations = []
def solve(x):
    ok = {(max(a, b), min(a, b)) for a, b in x['compat']}
    faults = []
    live = []
    for ch, col, en in x['channels']:
        if not en:
            continue
        if len(col) > 1:
            faults.append('multi:%d' % ch)
        if col == '':
            faults.append('red-fail:%d' % ch)
        if 'G' in col or 'Y' in col:
            live.append(ch)
    live.sort()
    for i in range(len(live)):
        for j in range(i + 1, len(live)):
            if (live[i], live[j]) not in ok:
                faults.append('conflict:%d-%d' % (live[i], live[j]))
    for ch, tenths in x['yellow_durations']:
        if tenths < 27:
            faults.append('short-yellow:%d' % ch)
    return sorted(faults)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[({'channels': [[1, 'G', True], [2, 'R', True], [3, 'Y', True], [4, 'G', False]], 'compat': [[3, 1]], 'yellow_durations': [[2, 27]]}, []), ({'channels': [[1, 'GY', False], [2, '', True], [3, 'Y', True], [4, 'R', True], [5, 'G', True], [6, 'R', True]], 'compat': [[1, 3], [1, 4], [1, 5], [2, 4], [3, 6], [4, 5], [6, 4], [5, 6]], 'yellow_durations': [[3, 30], [5, 28]]}, ['conflict:3-5', 'red-fail:2']), ({'channels': [[1, '', True], [2, 'R', True], [3, 'R', True], [4, 'G', True]], 'compat': [[2, 1], [1, 4], [4, 2]], 'yellow_durations': [[4, 26]]}, ['red-fail:1', 'short-yellow:4']), ({'channels': [[1, 'RG', True], [2, 'R', True], [3, 'R', False], [4, 'R', True], [5, 'GY', True], [6, 'Y', True]], 'compat': [[2, 1], [3, 1], [5, 1], [3, 4], [5, 3], [6, 3], [6, 5]], 'yellow_durations': [[5, 27]]}, ['conflict:1-6', 'multi:1', 'multi:5']), ({'channels': [[1, '', True], [2, 'GY', True], [3, 'RG', True], [4, 'G', True], [5, 'GY', True], [6, 'R', True]], 'compat': [[1, 3], [4, 1], [2, 3], [3, 5], [5, 4]], 'yellow_durations': [[1, 28], [6, 30]]}, ['conflict:2-4', 'conflict:2-5', 'conflict:3-4', 'multi:2', 'multi:3', 'multi:5', 'red-fail:1']), ({'channels': [[1, 'GY', True], [2, 'G', True], [3, '', True]], 'compat': [], 'yellow_durations': [[1, 26]]}, ['conflict:1-2', 'multi:1', 'red-fail:3', 'short-yellow:1']), ({'channels': [[1, '', True], [2, 'GY', True], [3, 'RY', True], [4, 'Y', True], [5, 'R', True]], 'compat': [[1, 2], [1, 4], [2, 4], [5, 2], [3, 4], [5, 3]], 'yellow_durations': [[3, 25], [4, 25]]}, ['conflict:2-3', 'multi:2', 'multi:3', 'red-fail:1', 'short-yellow:3', 'short-yellow:4']), ({'channels': [[1, 'R', True], [2, '', True], [3, 'RY', True], [4, 'RG', True]], 'compat': [[3, 1], [4, 1], [4, 2]], 'yellow_durations': [[1, 26], [2, 26]]}, ['conflict:3-4', 'multi:3', 'multi:4', 'red-fail:2', 'short-yellow:1', 'short-yellow:2'])], [({'channels': [[1, 'R', True], [2, 'Y', True], [3, '', True]], 'compat': [[1, 3]], 'yellow_durations': [[1, 26], [2, 26], [3, 26]]}, ['red-fail:3', 'short-yellow:1', 'short-yellow:2', 'short-yellow:3']), ({'channels': [[1, 'R', True], [2, 'Y', False], [3, 'GY', True], [4, 'GY', True], [5, 'GY', True]], 'compat': [[2, 3], [2, 5], [4, 5]], 'yellow_durations': [[3, 27], [5, 30]]}, ['conflict:3-4', 'conflict:3-5', 'multi:3', 'multi:4', 'multi:5']), ({'channels': [[1, 'R', True], [2, 'RG', False], [3, 'Y', True], [4, 'R', True], [5, 'Y', False], [6, 'RY', True]], 'compat': [[5, 1], [3, 4], [3, 5], [4, 5], [5, 6]], 'yellow_durations': [[5, 30]]}, ['conflict:3-6', 'multi:6']), ({'channels': [[1, 'G', True], [2, 'R', True], [3, 'Y', True], [4, 'G', False]], 'compat': [[3, 1]], 'yellow_durations': [[2, 27]]}, []), ({'channels': [[1, 'Y', True], [2, 'GY', True], [3, 'GY', True], [4, 'G', True], [5, 'G', True], [6, 'Y', True]], 'compat': [[1, 2], [1, 4], [5, 1], [4, 2], [5, 2], [5, 3], [4, 6], [5, 6]], 'yellow_durations': [[4, 30], [6, 25]]}, ['conflict:1-3', 'conflict:1-6', 'conflict:2-3', 'conflict:2-6', 'conflict:3-4', 'conflict:3-6', 'conflict:4-5', 'multi:2', 'multi:3', 'short-yellow:6']), ({'channels': [[1, '', True], [2, 'R', True], [3, 'R', True], [4, 'R', True], [5, 'R', True], [6, 'R', True]], 'compat': [[1, 3], [5, 3], [3, 6], [5, 4], [6, 4]], 'yellow_durations': [[2, 28]]}, ['red-fail:1']), ({'channels': [[1, 'Y', True], [2, 'GY', True], [3, 'Y', True], [4, 'GY', True], [5, 'GY', True], [6, 'R', True]], 'compat': [[1, 2], [4, 2], [6, 2], [4, 3], [3, 5], [3, 6], [6, 5]], 'yellow_durations': [[2, 35], [4, 28]]}, ['conflict:1-3', 'conflict:1-4', 'conflict:1-5', 'conflict:2-3', 'conflict:2-5', 'conflict:4-5', 'multi:2', 'multi:4', 'multi:5']), ({'channels': [[1, 'GY', True], [2, 'G', True], [3, '', True]], 'compat': [], 'yellow_durations': [[1, 26]]}, ['conflict:1-2', 'multi:1', 'red-fail:3', 'short-yellow:1'])], [({'channels': [[1, 'R', True], [2, 'GY', True], [3, 'Y', True], [4, '', True], [5, 'RY', True], [6, 'R', False]], 'compat': [[4, 1], [1, 6], [4, 2], [4, 3], [5, 4]], 'yellow_durations': [[1, 26], [2, 26]]}, ['conflict:2-3', 'conflict:2-5', 'conflict:3-5', 'multi:2', 'multi:5', 'red-fail:4', 'short-yellow:1', 'short-yellow:2']), ({'channels': [[1, 'Y', True], [2, '', True], [3, 'Y', True], [4, 'R', True]], 'compat': [[3, 1], [4, 1], [3, 2], [4, 2]], 'yellow_durations': []}, ['red-fail:2']), ({'channels': [[1, 'G', True], [2, 'R', True], [3, 'Y', True], [4, 'G', False]], 'compat': [[3, 1]], 'yellow_durations': [[2, 27]]}, []), ({'channels': [[1, 'RG', True], [2, 'R', True], [3, 'R', True], [4, '', True], [5, 'G', True], [6, 'RY', True]], 'compat': [[5, 3]], 'yellow_durations': []}, ['conflict:1-5', 'conflict:1-6', 'conflict:5-6', 'multi:1', 'multi:6', 'red-fail:4']), ({'channels': [[1, 'R', True], [2, 'R', True], [3, 'GY', False], [4, 'R', False], [5, 'R', True], [6, 'RY', True]], 'compat': [[3, 1], [5, 1], [4, 3], [6, 3], [4, 5]], 'yellow_durations': [[2, 28]]}, ['multi:6']), ({'channels': [[1, 'GY', True], [2, 'G', True], [3, '', True]], 'compat': [], 'yellow_durations': [[1, 26]]}, ['conflict:1-2', 'multi:1', 'red-fail:3', 'short-yellow:1']), ({'channels': [[1, 'R', True], [2, 'RG', True], [3, '', True], [4, 'R', True]], 'compat': [], 'yellow_durations': [[1, 28], [3, 26], [4, 25]]}, ['multi:2', 'red-fail:3', 'short-yellow:3', 'short-yellow:4']), ({'channels': [[1, 'R', True], [2, 'GY', True], [3, 'GY', True], [4, 'GY', True]], 'compat': [[4, 3]], 'yellow_durations': []}, ['conflict:2-3', 'conflict:2-4', 'multi:2', 'multi:3', 'multi:4'])], [({'channels': [[1, 'G', True], [2, 'R', True], [3, '', True], [4, 'G', True], [5, 'R', True]], 'compat': [[4, 1], [5, 1], [3, 2], [3, 4]], 'yellow_durations': [[5, 25]]}, ['red-fail:3', 'short-yellow:5']), ({'channels': [[1, '', True], [2, 'Y', True], [3, 'GY', True], [4, 'Y', False]], 'compat': [[1, 2], [3, 1], [4, 1], [3, 4]], 'yellow_durations': [[4, 25]]}, ['conflict:2-3', 'multi:3', 'red-fail:1', 'short-yellow:4']), ({'channels': [[1, 'GY', True], [2, 'G', True], [3, '', True]], 'compat': [], 'yellow_durations': [[1, 26]]}, ['conflict:1-2', 'multi:1', 'red-fail:3', 'short-yellow:1']), ({'channels': [[1, 'R', True], [2, 'RY', True], [3, 'GY', True], [4, 'G', False], [5, 'RG', False], [6, 'R', True]], 'compat': [[3, 1], [5, 1], [3, 2], [2, 5], [6, 2], [6, 3]], 'yellow_durations': [[2, 25], [5, 35]]}, ['multi:2', 'multi:3', 'short-yellow:2']), ({'channels': [[1, 'G', True], [2, 'R', True], [3, 'Y', True], [4, 'G', False]], 'compat': [[3, 1]], 'yellow_durations': [[2, 27]]}, []), ({'channels': [[1, 'G', True], [2, 'GY', True], [3, 'R', True], [4, 'R', True], [5, 'R', True], [6, 'R', True]], 'compat': [[4, 1], [2, 6], [3, 4], [6, 5]], 'yellow_durations': [[1, 26], [2, 28]]}, ['conflict:1-2', 'multi:2', 'short-yellow:1']), ({'channels': [[1, 'Y', False], [2, '', True], [3, '', True], [4, '', True], [5, 'RG', True]], 'compat': [[1, 3], [1, 4], [1, 5], [3, 4], [5, 3], [4, 5]], 'yellow_durations': [[4, 28]]}, ['multi:5', 'red-fail:2', 'red-fail:3', 'red-fail:4']), ({'channels': [[1, 'R', True], [2, 'G', True], [3, '', True]], 'compat': [[1, 3]], 'yellow_durations': []}, ['red-fail:3'])], [({'channels': [[1, 'G', True], [2, 'R', True], [3, 'Y', True], [4, 'G', False]], 'compat': [[3, 1]], 'yellow_durations': [[2, 27]]}, []), ({'channels': [[1, 'GY', True], [2, 'R', True], [3, 'RY', True], [4, 'RY', True], [5, 'R', True], [6, 'RY', False]], 'compat': [[2, 1], [1, 3], [4, 1], [5, 1], [2, 3], [4, 2], [2, 6], [4, 5], [4, 6]], 'yellow_durations': []}, ['conflict:3-4', 'multi:1', 'multi:3', 'multi:4']), ({'channels': [[1, 'R', True], [2, '', True], [3, 'G', True]], 'compat': [[1, 2], [3, 1], [2, 3]], 'yellow_durations': [[2, 35], [3, 25]]}, ['red-fail:2', 'short-yellow:3']), ({'channels': [[1, 'R', True], [2, 'GY', False], [3, 'R', True]], 'compat': [[3, 1], [2, 3]], 'yellow_durations': [[1, 35]]}, []), ({'channels': [[1, 'GY', True], [2, 'G', True], [3, '', True]], 'compat': [], 'yellow_durations': [[1, 26]]}, ['conflict:1-2', 'multi:1', 'red-fail:3', 'short-yellow:1']), ({'channels': [[1, 'RG', True], [2, 'R', True], [3, 'R', True], [4, '', True], [5, 'R', True], [6, 'RG', True]], 'compat': [[4, 1], [3, 2], [2, 4], [6, 2], [3, 6]], 'yellow_durations': []}, ['conflict:1-6', 'multi:1', 'multi:6', 'red-fail:4']), ({'channels': [[1, '', True], [2, 'GY', True], [3, 'R', False], [4, 'RY', True]], 'compat': [[3, 1], [4, 2]], 'yellow_durations': [[1, 26], [3, 25]]}, ['multi:2', 'multi:4', 'red-fail:1', 'short-yellow:1', 'short-yellow:3']), ({'channels': [[1, 'RG', True], [2, '', True], [3, 'Y', True]], 'compat': [[1, 2], [1, 3], [3, 2]], 'yellow_durations': [[2, 35], [3, 28]]}, ['multi:1', 'red-fail:2'])]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check('timing oracle' + ' %d' % i, 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
timing oracle 0['conflict:1-3'][]Failed
timing oracle 1['conflict:3-5', 'red-fail:2']['conflict:3-5', 'red-fail:2']Passed
timing oracle 2['red-fail:1', 'short-yellow:4']['red-fail:1', 'short-yellow:4']Passed
timing oracle 3['conflict:1-5', 'conflict:1-6', 'conflict:5-6', 'multi:1', 'multi:5']['conflict:1-6', 'multi:1', 'multi:5']Failed
timing oracle 4['conflict:2-3', 'conflict:2-4', 'conflict:2-5', 'conflict:3-4', 'conflict:3-5', 'conflict:4-5', 'multi:2', 'multi:3', 'multi:5', 'red-fail:1']['conflict:2-4', 'conflict:2-5', 'conflict:3-4', 'multi:2', 'multi:3', 'multi:5', 'red-fail:1']Failed
timing oracle 5['conflict:1-2', 'multi:1', 'red-fail:3', 'short-yellow:1']['conflict:1-2', 'multi:1', 'red-fail:3', 'short-yellow:1']Passed
timing oracle 6['conflict:2-3', 'conflict:2-4', 'conflict:3-4', 'multi:2', 'multi:3', 'red-fail:1', 'short-yellow:3', 'short-yellow:4']['conflict:2-3', 'multi:2', 'multi:3', 'red-fail:1', 'short-yellow:3', 'short-yellow:4']Failed
timing oracle 7['conflict:3-4', 'multi:3', 'multi:4', 'red-fail:2', 'short-yellow:1', 'short-yellow:2']['conflict:3-4', 'multi:3', 'multi:4', 'red-fail:2', 'short-yellow:1', 'short-yellow:2']Passed

SHA-256 / 36549728ed21f0634473bb1e36e7823f51176102a8f29bd8722ffb44ad250f53

3 / The verified repair

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

N = 1
observations = []
def solve(x):
    ok = {(min(a, b), max(a, b)) for a, b in x['compat']}
    faults = []
    live = []
    for ch, col, en in x['channels']:
        if not en:
            continue
        if len(col) > 1:
            faults.append('multi:%d' % ch)
        if col == '':
            faults.append('red-fail:%d' % ch)
        if 'G' in col or 'Y' in col:
            live.append(ch)
    live.sort()
    for i in range(len(live)):
        for j in range(i + 1, len(live)):
            if (live[i], live[j]) not in ok:
                faults.append('conflict:%d-%d' % (live[i], live[j]))
    for ch, tenths in x['yellow_durations']:
        if tenths < 27:
            faults.append('short-yellow:%d' % ch)
    return sorted(faults)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[({'channels': [[1, 'G', True], [2, 'R', True], [3, 'Y', True], [4, 'G', False]], 'compat': [[3, 1]], 'yellow_durations': [[2, 27]]}, []), ({'channels': [[1, 'GY', False], [2, '', True], [3, 'Y', True], [4, 'R', True], [5, 'G', True], [6, 'R', True]], 'compat': [[1, 3], [1, 4], [1, 5], [2, 4], [3, 6], [4, 5], [6, 4], [5, 6]], 'yellow_durations': [[3, 30], [5, 28]]}, ['conflict:3-5', 'red-fail:2']), ({'channels': [[1, '', True], [2, 'R', True], [3, 'R', True], [4, 'G', True]], 'compat': [[2, 1], [1, 4], [4, 2]], 'yellow_durations': [[4, 26]]}, ['red-fail:1', 'short-yellow:4']), ({'channels': [[1, 'RG', True], [2, 'R', True], [3, 'R', False], [4, 'R', True], [5, 'GY', True], [6, 'Y', True]], 'compat': [[2, 1], [3, 1], [5, 1], [3, 4], [5, 3], [6, 3], [6, 5]], 'yellow_durations': [[5, 27]]}, ['conflict:1-6', 'multi:1', 'multi:5']), ({'channels': [[1, '', True], [2, 'GY', True], [3, 'RG', True], [4, 'G', True], [5, 'GY', True], [6, 'R', True]], 'compat': [[1, 3], [4, 1], [2, 3], [3, 5], [5, 4]], 'yellow_durations': [[1, 28], [6, 30]]}, ['conflict:2-4', 'conflict:2-5', 'conflict:3-4', 'multi:2', 'multi:3', 'multi:5', 'red-fail:1']), ({'channels': [[1, 'GY', True], [2, 'G', True], [3, '', True]], 'compat': [], 'yellow_durations': [[1, 26]]}, ['conflict:1-2', 'multi:1', 'red-fail:3', 'short-yellow:1']), ({'channels': [[1, '', True], [2, 'GY', True], [3, 'RY', True], [4, 'Y', True], [5, 'R', True]], 'compat': [[1, 2], [1, 4], [2, 4], [5, 2], [3, 4], [5, 3]], 'yellow_durations': [[3, 25], [4, 25]]}, ['conflict:2-3', 'multi:2', 'multi:3', 'red-fail:1', 'short-yellow:3', 'short-yellow:4']), ({'channels': [[1, 'R', True], [2, '', True], [3, 'RY', True], [4, 'RG', True]], 'compat': [[3, 1], [4, 1], [4, 2]], 'yellow_durations': [[1, 26], [2, 26]]}, ['conflict:3-4', 'multi:3', 'multi:4', 'red-fail:2', 'short-yellow:1', 'short-yellow:2'])], [({'channels': [[1, 'R', True], [2, 'Y', True], [3, '', True]], 'compat': [[1, 3]], 'yellow_durations': [[1, 26], [2, 26], [3, 26]]}, ['red-fail:3', 'short-yellow:1', 'short-yellow:2', 'short-yellow:3']), ({'channels': [[1, 'R', True], [2, 'Y', False], [3, 'GY', True], [4, 'GY', True], [5, 'GY', True]], 'compat': [[2, 3], [2, 5], [4, 5]], 'yellow_durations': [[3, 27], [5, 30]]}, ['conflict:3-4', 'conflict:3-5', 'multi:3', 'multi:4', 'multi:5']), ({'channels': [[1, 'R', True], [2, 'RG', False], [3, 'Y', True], [4, 'R', True], [5, 'Y', False], [6, 'RY', True]], 'compat': [[5, 1], [3, 4], [3, 5], [4, 5], [5, 6]], 'yellow_durations': [[5, 30]]}, ['conflict:3-6', 'multi:6']), ({'channels': [[1, 'G', True], [2, 'R', True], [3, 'Y', True], [4, 'G', False]], 'compat': [[3, 1]], 'yellow_durations': [[2, 27]]}, []), ({'channels': [[1, 'Y', True], [2, 'GY', True], [3, 'GY', True], [4, 'G', True], [5, 'G', True], [6, 'Y', True]], 'compat': [[1, 2], [1, 4], [5, 1], [4, 2], [5, 2], [5, 3], [4, 6], [5, 6]], 'yellow_durations': [[4, 30], [6, 25]]}, ['conflict:1-3', 'conflict:1-6', 'conflict:2-3', 'conflict:2-6', 'conflict:3-4', 'conflict:3-6', 'conflict:4-5', 'multi:2', 'multi:3', 'short-yellow:6']), ({'channels': [[1, '', True], [2, 'R', True], [3, 'R', True], [4, 'R', True], [5, 'R', True], [6, 'R', True]], 'compat': [[1, 3], [5, 3], [3, 6], [5, 4], [6, 4]], 'yellow_durations': [[2, 28]]}, ['red-fail:1']), ({'channels': [[1, 'Y', True], [2, 'GY', True], [3, 'Y', True], [4, 'GY', True], [5, 'GY', True], [6, 'R', True]], 'compat': [[1, 2], [4, 2], [6, 2], [4, 3], [3, 5], [3, 6], [6, 5]], 'yellow_durations': [[2, 35], [4, 28]]}, ['conflict:1-3', 'conflict:1-4', 'conflict:1-5', 'conflict:2-3', 'conflict:2-5', 'conflict:4-5', 'multi:2', 'multi:4', 'multi:5']), ({'channels': [[1, 'GY', True], [2, 'G', True], [3, '', True]], 'compat': [], 'yellow_durations': [[1, 26]]}, ['conflict:1-2', 'multi:1', 'red-fail:3', 'short-yellow:1'])], [({'channels': [[1, 'R', True], [2, 'GY', True], [3, 'Y', True], [4, '', True], [5, 'RY', True], [6, 'R', False]], 'compat': [[4, 1], [1, 6], [4, 2], [4, 3], [5, 4]], 'yellow_durations': [[1, 26], [2, 26]]}, ['conflict:2-3', 'conflict:2-5', 'conflict:3-5', 'multi:2', 'multi:5', 'red-fail:4', 'short-yellow:1', 'short-yellow:2']), ({'channels': [[1, 'Y', True], [2, '', True], [3, 'Y', True], [4, 'R', True]], 'compat': [[3, 1], [4, 1], [3, 2], [4, 2]], 'yellow_durations': []}, ['red-fail:2']), ({'channels': [[1, 'G', True], [2, 'R', True], [3, 'Y', True], [4, 'G', False]], 'compat': [[3, 1]], 'yellow_durations': [[2, 27]]}, []), ({'channels': [[1, 'RG', True], [2, 'R', True], [3, 'R', True], [4, '', True], [5, 'G', True], [6, 'RY', True]], 'compat': [[5, 3]], 'yellow_durations': []}, ['conflict:1-5', 'conflict:1-6', 'conflict:5-6', 'multi:1', 'multi:6', 'red-fail:4']), ({'channels': [[1, 'R', True], [2, 'R', True], [3, 'GY', False], [4, 'R', False], [5, 'R', True], [6, 'RY', True]], 'compat': [[3, 1], [5, 1], [4, 3], [6, 3], [4, 5]], 'yellow_durations': [[2, 28]]}, ['multi:6']), ({'channels': [[1, 'GY', True], [2, 'G', True], [3, '', True]], 'compat': [], 'yellow_durations': [[1, 26]]}, ['conflict:1-2', 'multi:1', 'red-fail:3', 'short-yellow:1']), ({'channels': [[1, 'R', True], [2, 'RG', True], [3, '', True], [4, 'R', True]], 'compat': [], 'yellow_durations': [[1, 28], [3, 26], [4, 25]]}, ['multi:2', 'red-fail:3', 'short-yellow:3', 'short-yellow:4']), ({'channels': [[1, 'R', True], [2, 'GY', True], [3, 'GY', True], [4, 'GY', True]], 'compat': [[4, 3]], 'yellow_durations': []}, ['conflict:2-3', 'conflict:2-4', 'multi:2', 'multi:3', 'multi:4'])], [({'channels': [[1, 'G', True], [2, 'R', True], [3, '', True], [4, 'G', True], [5, 'R', True]], 'compat': [[4, 1], [5, 1], [3, 2], [3, 4]], 'yellow_durations': [[5, 25]]}, ['red-fail:3', 'short-yellow:5']), ({'channels': [[1, '', True], [2, 'Y', True], [3, 'GY', True], [4, 'Y', False]], 'compat': [[1, 2], [3, 1], [4, 1], [3, 4]], 'yellow_durations': [[4, 25]]}, ['conflict:2-3', 'multi:3', 'red-fail:1', 'short-yellow:4']), ({'channels': [[1, 'GY', True], [2, 'G', True], [3, '', True]], 'compat': [], 'yellow_durations': [[1, 26]]}, ['conflict:1-2', 'multi:1', 'red-fail:3', 'short-yellow:1']), ({'channels': [[1, 'R', True], [2, 'RY', True], [3, 'GY', True], [4, 'G', False], [5, 'RG', False], [6, 'R', True]], 'compat': [[3, 1], [5, 1], [3, 2], [2, 5], [6, 2], [6, 3]], 'yellow_durations': [[2, 25], [5, 35]]}, ['multi:2', 'multi:3', 'short-yellow:2']), ({'channels': [[1, 'G', True], [2, 'R', True], [3, 'Y', True], [4, 'G', False]], 'compat': [[3, 1]], 'yellow_durations': [[2, 27]]}, []), ({'channels': [[1, 'G', True], [2, 'GY', True], [3, 'R', True], [4, 'R', True], [5, 'R', True], [6, 'R', True]], 'compat': [[4, 1], [2, 6], [3, 4], [6, 5]], 'yellow_durations': [[1, 26], [2, 28]]}, ['conflict:1-2', 'multi:2', 'short-yellow:1']), ({'channels': [[1, 'Y', False], [2, '', True], [3, '', True], [4, '', True], [5, 'RG', True]], 'compat': [[1, 3], [1, 4], [1, 5], [3, 4], [5, 3], [4, 5]], 'yellow_durations': [[4, 28]]}, ['multi:5', 'red-fail:2', 'red-fail:3', 'red-fail:4']), ({'channels': [[1, 'R', True], [2, 'G', True], [3, '', True]], 'compat': [[1, 3]], 'yellow_durations': []}, ['red-fail:3'])], [({'channels': [[1, 'G', True], [2, 'R', True], [3, 'Y', True], [4, 'G', False]], 'compat': [[3, 1]], 'yellow_durations': [[2, 27]]}, []), ({'channels': [[1, 'GY', True], [2, 'R', True], [3, 'RY', True], [4, 'RY', True], [5, 'R', True], [6, 'RY', False]], 'compat': [[2, 1], [1, 3], [4, 1], [5, 1], [2, 3], [4, 2], [2, 6], [4, 5], [4, 6]], 'yellow_durations': []}, ['conflict:3-4', 'multi:1', 'multi:3', 'multi:4']), ({'channels': [[1, 'R', True], [2, '', True], [3, 'G', True]], 'compat': [[1, 2], [3, 1], [2, 3]], 'yellow_durations': [[2, 35], [3, 25]]}, ['red-fail:2', 'short-yellow:3']), ({'channels': [[1, 'R', True], [2, 'GY', False], [3, 'R', True]], 'compat': [[3, 1], [2, 3]], 'yellow_durations': [[1, 35]]}, []), ({'channels': [[1, 'GY', True], [2, 'G', True], [3, '', True]], 'compat': [], 'yellow_durations': [[1, 26]]}, ['conflict:1-2', 'multi:1', 'red-fail:3', 'short-yellow:1']), ({'channels': [[1, 'RG', True], [2, 'R', True], [3, 'R', True], [4, '', True], [5, 'R', True], [6, 'RG', True]], 'compat': [[4, 1], [3, 2], [2, 4], [6, 2], [3, 6]], 'yellow_durations': []}, ['conflict:1-6', 'multi:1', 'multi:6', 'red-fail:4']), ({'channels': [[1, '', True], [2, 'GY', True], [3, 'R', False], [4, 'RY', True]], 'compat': [[3, 1], [4, 2]], 'yellow_durations': [[1, 26], [3, 25]]}, ['multi:2', 'multi:4', 'red-fail:1', 'short-yellow:1', 'short-yellow:3']), ({'channels': [[1, 'RG', True], [2, '', True], [3, 'Y', True]], 'compat': [[1, 2], [1, 3], [3, 2]], 'yellow_durations': [[2, 35], [3, 28]]}, ['multi:1', 'red-fail:2'])]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check('timing oracle' + ' %d' % i, 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
timing oracle 0[][]Passed
timing oracle 1['conflict:3-5', 'red-fail:2']['conflict:3-5', 'red-fail:2']Passed
timing oracle 2['red-fail:1', 'short-yellow:4']['red-fail:1', 'short-yellow:4']Passed
timing oracle 3['conflict:1-6', 'multi:1', 'multi:5']['conflict:1-6', 'multi:1', 'multi:5']Passed
timing oracle 4['conflict:2-4', 'conflict:2-5', 'conflict:3-4', 'multi:2', 'multi:3', 'multi:5', 'red-fail:1']['conflict:2-4', 'conflict:2-5', 'conflict:3-4', 'multi:2', 'multi:3', 'multi:5', 'red-fail:1']Passed
timing oracle 5['conflict:1-2', 'multi:1', 'red-fail:3', 'short-yellow:1']['conflict:1-2', 'multi:1', 'red-fail:3', 'short-yellow:1']Passed
timing oracle 6['conflict:2-3', 'multi:2', 'multi:3', 'red-fail:1', 'short-yellow:3', 'short-yellow:4']['conflict:2-3', 'multi:2', 'multi:3', 'red-fail:1', 'short-yellow:3', 'short-yellow:4']Passed
timing oracle 7['conflict:3-4', 'multi:3', 'multi:4', 'red-fail:2', 'short-yellow:1', 'short-yellow:2']['conflict:3-4', 'multi:3', 'multi:4', 'red-fail:2', 'short-yellow:1', 'short-yellow:2']Passed

SHA-256 / 905eafad45ad267e5780231fd458e0637c37b1f32bdd715c4bca3cebcd2a831f

Verification & scope

A deterministic, bounded toy model with a stipulated contract; it makes no claim of conformance to any agency manual or standard. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.

Observations recorded using Python 3.12.14 at 2026-09-29T14:48:00.846812+00:00.

Case digest / 5413e925532ed19e724fb347871191fd3b826424b5b015f29b2d230a1b5bf8a0