FA-67971 / Traffic signal timing plans / Open access
Actuated phase gap-out and max-out: the max timer runs from the start of green · case 01
Actuated phase gap-out and max-out returns a wrong result when the max timer runs from the start of green.
ROOT CAUSE
Max green is timed from green start instead of from the conflicting call, cutting phases short when the call arrives late.
VERIFIED REPAIR
Restore the max timer start rule so that the step reads `max_end = tc + M`.
Unsuccessful approach: Subtracting min green from the call-based timer is still not the stipulated max-out instant.
Case contract
Input {min_green, gap, max_green, actuations: integer seconds since green start (any order), conflict_call: seconds or null}. Each actuation at a keeps the phase eligible until a+gap; an actuation exactly at expiry extends; actuations during min green always extend. Gap-out time = max(min_green, final expiry). With no conflicting call return ['rest', gap time]. The max timer starts at the call (a call before green start counts as 0); max-out at call+max_green. If gap time <= max-out the phase ends by 'gap-out' at max(gap time, call), else by 'max-out'.
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):
m, p, M = x['min_green'], x['gap'], x['max_green']
exp = 0
for a in sorted(x['actuations']):
if a > exp and a > m:
break
exp = max(exp, a + p)
gap_end = max(m, exp)
tc = x['conflict_call']
if tc is None:
return ['rest', gap_end]
tc = max(tc, 0)
max_end = M
if gap_end <= max_end:
return ['gap-out', max(gap_end, tc)]
return ['max-out', max_end]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[({'min_green': 4, 'gap': 4, 'max_green': 38, 'actuations': [2, 5, 6, 7, 8, 14, 16, 20, 23, 24, 26, 30, 32, 35, 41, 44, 49, 51, 54, 56, 59], 'conflict_call': 15}, ['gap-out', 15]), ({'min_green': 7, 'gap': 5, 'max_green': 40, 'actuations': [2, 3, 5, 7, 10, 12, 13, 14, 15, 18, 19, 20, 25, 29, 32, 33, 35, 37, 39, 44, 45, 46, 51, 52, 54, 57], 'conflict_call': 34}, ['gap-out', 62]), ({'min_green': 8, 'gap': 5, 'max_green': 37, 'actuations': [2, 6, 8, 10, 11, 12, 14, 16, 17, 18, 19, 24, 25, 27, 28, 30, 31, 35, 37, 39, 43, 45, 46, 47, 48, 49, 50, 51, 55, 57], 'conflict_call': 20}, ['max-out', 57]), ({'min_green': 7, 'gap': 3, 'max_green': 15, 'actuations': [46, 42, 45, 38, 32, 27, 3, 9, 1, 15, 24, 16, 56, 2, 22, 40, 20, 14, 7, 28, 26, 8, 55, 58, 29, 5, 48, 59, 34, 35, 11], 'conflict_call': 23}, ['gap-out', 23]), ({'min_green': 10, 'gap': 2, 'max_green': 3, 'actuations': [], 'conflict_call': 0}, ['max-out', 3]), ({'min_green': 5, 'gap': 3, 'max_green': 20, 'actuations': [1, 4, 7, 10, 13], 'conflict_call': 2}, ['gap-out', 16]), ({'min_green': 8, 'gap': 3, 'max_green': 30, 'actuations': [2, 6], 'conflict_call': 20}, ['gap-out', 20]), ({'min_green': 9, 'gap': 4, 'max_green': 38, 'actuations': [13, 39, 8, 1, 36, 52, 20, 18, 53, 9, 45, 56, 55, 17, 2, 58, 23, 42, 26, 24, 14, 7, 34, 11, 33, 30, 51, 54, 28, 35, 50], 'conflict_call': 27}, ['gap-out', 49])], [({'min_green': 6, 'gap': 3, 'max_green': 29, 'actuations': [0, 2, 4, 5, 8, 9, 10, 13, 14, 19, 21, 22, 27, 28, 30, 31, 33, 35, 38, 39, 40, 42, 44, 46, 47, 48, 49, 51, 54, 55, 56, 57, 59], 'conflict_call': 16}, ['gap-out', 17]), ({'min_green': 12, 'gap': 3, 'max_green': 5, 'actuations': [1], 'conflict_call': 2}, ['max-out', 7]), ({'min_green': 4, 'gap': 2, 'max_green': 38, 'actuations': [0, 5, 6, 7, 10, 11, 16, 17, 20, 21, 24, 27, 29, 31, 33, 34, 35, 39, 41, 43, 46, 47, 48, 49, 52, 55, 57, 58], 'conflict_call': 11}, ['gap-out', 11]), ({'min_green': 5, 'gap': 3, 'max_green': 25, 'actuations': [9, 3, 6], 'conflict_call': None}, ['rest', 12]), ({'min_green': 4, 'gap': 5, 'max_green': 23, 'actuations': [1, 3, 6, 8, 11, 12, 15, 20, 25, 27, 28, 29, 31, 35, 37, 38, 41, 42, 43, 44, 50, 57], 'conflict_call': 10}, ['max-out', 33]), ({'min_green': 10, 'gap': 5, 'max_green': 25, 'actuations': [1, 3, 7, 9, 10, 14, 16, 18, 19, 23, 24, 26, 27, 28, 30, 34, 35, 37, 38, 42, 43, 44, 46, 49, 54, 59], 'conflict_call': 20}, ['max-out', 45]), ({'min_green': 10, 'gap': 3, 'max_green': 43, 'actuations': [0, 4, 7, 12, 14, 21, 24, 25, 41, 44, 47, 59], 'conflict_call': 10}, ['gap-out', 10]), ({'min_green': 10, 'gap': 2, 'max_green': 3, 'actuations': [], 'conflict_call': 0}, ['max-out', 3])], [({'min_green': 6, 'gap': 2, 'max_green': 15, 'actuations': [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38], 'conflict_call': -3}, ['max-out', 15]), ({'min_green': 4, 'gap': 3, 'max_green': 31, 'actuations': [7, 8, 11, 14, 15, 21, 27, 32, 37, 46, 52, 57], 'conflict_call': None}, ['rest', 4]), ({'min_green': 10, 'gap': 2, 'max_green': 3, 'actuations': [], 'conflict_call': 0}, ['max-out', 3]), ({'min_green': 5, 'gap': 5, 'max_green': 22, 'actuations': [1, 3, 5, 9, 12, 13, 14, 15, 16, 17, 18, 22, 23, 24, 25, 27, 29, 31, 32, 34, 36, 37, 38, 40, 47, 49, 52, 55, 56, 57, 58, 59], 'conflict_call': 32}, ['gap-out', 45]), ({'min_green': 5, 'gap': 3, 'max_green': 25, 'actuations': [9, 3, 6], 'conflict_call': None}, ['rest', 12]), ({'min_green': 5, 'gap': 4, 'max_green': 44, 'actuations': [1, 3, 4, 5, 6, 7, 10, 16, 17, 19, 20, 21, 25, 26, 28, 29, 32, 33, 34, 35, 38, 39, 41, 43, 44, 47, 49, 52, 56, 57, 58, 59], 'conflict_call': None}, ['rest', 14]), ({'min_green': 8, 'gap': 3, 'max_green': 29, 'actuations': [0, 2, 3, 6, 9, 11, 12, 14, 15, 17, 18, 19, 21, 22, 25, 27, 30, 31, 36, 38, 41, 42, 43, 45, 48, 52, 53, 55, 57, 59], 'conflict_call': 31}, ['gap-out', 34]), ({'min_green': 4, 'gap': 5, 'max_green': 45, 'actuations': [2, 3, 4, 5, 6, 7, 11, 12, 15, 17, 18, 20, 21, 22, 23, 25, 28, 29, 34, 35, 36, 37, 39, 41, 42, 49, 50, 51, 55, 56], 'conflict_call': 29}, ['gap-out', 47])], [({'min_green': 8, 'gap': 3, 'max_green': 30, 'actuations': [2, 6], 'conflict_call': 20}, ['gap-out', 20]), ({'min_green': 5, 'gap': 3, 'max_green': 25, 'actuations': [9, 3, 6], 'conflict_call': None}, ['rest', 12]), ({'min_green': 6, 'gap': 2, 'max_green': 15, 'actuations': [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38], 'conflict_call': -3}, ['max-out', 15]), ({'min_green': 4, 'gap': 3, 'max_green': 33, 'actuations': [13, 36, 51, 10, 4, 20, 44, 6, 49, 32, 40, 7, 47, 14, 21, 31, 29, 8, 9, 56, 53, 50, 38, 5, 24, 27, 12, 17, 45, 52, 54], 'conflict_call': -6}, ['max-out', 33]), ({'min_green': 9, 'gap': 5, 'max_green': 34, 'actuations': [0, 2, 8, 9, 10, 11, 14, 16, 18, 23, 27, 29, 30, 31, 36, 38, 39, 40, 48, 50, 53, 55, 56], 'conflict_call': 33}, ['gap-out', 45]), ({'min_green': 10, 'gap': 5, 'max_green': 28, 'actuations': [13, 1, 18, 8, 59, 45, 3, 31, 4, 36, 12, 50, 6, 46, 7, 34, 40, 54, 19, 53, 48, 20, 52, 25, 57, 47, 5, 24, 16], 'conflict_call': 31}, ['gap-out', 31]), ({'min_green': 7, 'gap': 2, 'max_green': 31, 'actuations': [0, 2, 3, 7, 9, 19, 21, 23, 25, 28, 30, 38, 41, 43, 44, 48, 49, 51, 53, 56, 57], 'conflict_call': None}, ['rest', 11]), ({'min_green': 8, 'gap': 4, 'max_green': 44, 'actuations': [0, 2, 4, 6, 9, 12, 13, 15, 17, 18, 19, 23, 26, 29, 30, 32, 33, 35, 36, 38, 40, 41, 42, 44, 45, 47, 48, 49, 50, 51, 55, 56], 'conflict_call': 15}, ['max-out', 59])], [({'min_green': 7, 'gap': 5, 'max_green': 38, 'actuations': [1, 3, 5, 6, 8, 9, 10, 11, 12, 13, 16, 18, 21, 23, 25, 26, 29, 31, 33, 34, 37, 38, 40, 41, 43, 44, 46, 48, 53, 54, 56, 57, 59], 'conflict_call': 12}, ['max-out', 50]), ({'min_green': 8, 'gap': 3, 'max_green': 30, 'actuations': [2, 6], 'conflict_call': 20}, ['gap-out', 20]), ({'min_green': 7, 'gap': 3, 'max_green': 19, 'actuations': [0, 2, 5, 6, 7, 12, 15, 17, 21, 24, 25, 26, 27, 28, 29, 33, 34, 36, 38, 39, 40, 41, 44, 45, 47, 49, 50, 53, 54, 56], 'conflict_call': 0}, ['gap-out', 10]), ({'min_green': 6, 'gap': 2, 'max_green': 12, 'actuations': [1, 3, 5, 7, 9, 11, 13], 'conflict_call': 3}, ['gap-out', 15]), ({'min_green': 5, 'gap': 4, 'max_green': 41, 'actuations': [1, 2, 4, 6, 7, 8, 10, 13, 14, 17, 18, 19, 20, 21, 25, 26, 27, 28, 32, 35, 37, 38, 39, 40, 41, 43, 45, 47, 48, 50, 54, 55, 59], 'conflict_call': 31}, ['gap-out', 63]), ({'min_green': 10, 'gap': 4, 'max_green': 21, 'actuations': [5, 30, 36, 38, 46, 55], 'conflict_call': 34}, ['gap-out', 34]), ({'min_green': 4, 'gap': 5, 'max_green': 28, 'actuations': [2, 7, 57], 'conflict_call': None}, ['rest', 12]), ({'min_green': 6, 'gap': 2, 'max_green': 15, 'actuations': [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38], 'conflict_call': -3}, ['max-out', 15])]]
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| timing oracle 0 | ['gap-out', 15] | ['gap-out', 15] | Passed |
| timing oracle 1 | ['max-out', 40] | ['gap-out', 62] | Failed |
| timing oracle 2 | ['max-out', 37] | ['max-out', 57] | Failed |
| timing oracle 3 | ['max-out', 15] | ['gap-out', 23] | Failed |
| timing oracle 4 | ['max-out', 3] | ['max-out', 3] | Passed |
| timing oracle 5 | ['gap-out', 16] | ['gap-out', 16] | Passed |
| timing oracle 6 | ['gap-out', 20] | ['gap-out', 20] | Passed |
| timing oracle 7 | ['max-out', 38] | ['gap-out', 49] | Failed |
SHA-256 / c52f611598d42d39a2a981c89d329d08c7d8e0c8f46f2ca793b4fde89c55f1ba
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
m, p, M = x['min_green'], x['gap'], x['max_green']
exp = 0
for a in sorted(x['actuations']):
if a > exp and a > m:
break
exp = max(exp, a + p)
gap_end = max(m, exp)
tc = x['conflict_call']
if tc is None:
return ['rest', gap_end]
tc = max(tc, 0)
max_end = tc + M - m
if gap_end <= max_end:
return ['gap-out', max(gap_end, tc)]
return ['max-out', max_end]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[({'min_green': 4, 'gap': 4, 'max_green': 38, 'actuations': [2, 5, 6, 7, 8, 14, 16, 20, 23, 24, 26, 30, 32, 35, 41, 44, 49, 51, 54, 56, 59], 'conflict_call': 15}, ['gap-out', 15]), ({'min_green': 7, 'gap': 5, 'max_green': 40, 'actuations': [2, 3, 5, 7, 10, 12, 13, 14, 15, 18, 19, 20, 25, 29, 32, 33, 35, 37, 39, 44, 45, 46, 51, 52, 54, 57], 'conflict_call': 34}, ['gap-out', 62]), ({'min_green': 8, 'gap': 5, 'max_green': 37, 'actuations': [2, 6, 8, 10, 11, 12, 14, 16, 17, 18, 19, 24, 25, 27, 28, 30, 31, 35, 37, 39, 43, 45, 46, 47, 48, 49, 50, 51, 55, 57], 'conflict_call': 20}, ['max-out', 57]), ({'min_green': 7, 'gap': 3, 'max_green': 15, 'actuations': [46, 42, 45, 38, 32, 27, 3, 9, 1, 15, 24, 16, 56, 2, 22, 40, 20, 14, 7, 28, 26, 8, 55, 58, 29, 5, 48, 59, 34, 35, 11], 'conflict_call': 23}, ['gap-out', 23]), ({'min_green': 10, 'gap': 2, 'max_green': 3, 'actuations': [], 'conflict_call': 0}, ['max-out', 3]), ({'min_green': 5, 'gap': 3, 'max_green': 20, 'actuations': [1, 4, 7, 10, 13], 'conflict_call': 2}, ['gap-out', 16]), ({'min_green': 8, 'gap': 3, 'max_green': 30, 'actuations': [2, 6], 'conflict_call': 20}, ['gap-out', 20]), ({'min_green': 9, 'gap': 4, 'max_green': 38, 'actuations': [13, 39, 8, 1, 36, 52, 20, 18, 53, 9, 45, 56, 55, 17, 2, 58, 23, 42, 26, 24, 14, 7, 34, 11, 33, 30, 51, 54, 28, 35, 50], 'conflict_call': 27}, ['gap-out', 49])], [({'min_green': 6, 'gap': 3, 'max_green': 29, 'actuations': [0, 2, 4, 5, 8, 9, 10, 13, 14, 19, 21, 22, 27, 28, 30, 31, 33, 35, 38, 39, 40, 42, 44, 46, 47, 48, 49, 51, 54, 55, 56, 57, 59], 'conflict_call': 16}, ['gap-out', 17]), ({'min_green': 12, 'gap': 3, 'max_green': 5, 'actuations': [1], 'conflict_call': 2}, ['max-out', 7]), ({'min_green': 4, 'gap': 2, 'max_green': 38, 'actuations': [0, 5, 6, 7, 10, 11, 16, 17, 20, 21, 24, 27, 29, 31, 33, 34, 35, 39, 41, 43, 46, 47, 48, 49, 52, 55, 57, 58], 'conflict_call': 11}, ['gap-out', 11]), ({'min_green': 5, 'gap': 3, 'max_green': 25, 'actuations': [9, 3, 6], 'conflict_call': None}, ['rest', 12]), ({'min_green': 4, 'gap': 5, 'max_green': 23, 'actuations': [1, 3, 6, 8, 11, 12, 15, 20, 25, 27, 28, 29, 31, 35, 37, 38, 41, 42, 43, 44, 50, 57], 'conflict_call': 10}, ['max-out', 33]), ({'min_green': 10, 'gap': 5, 'max_green': 25, 'actuations': [1, 3, 7, 9, 10, 14, 16, 18, 19, 23, 24, 26, 27, 28, 30, 34, 35, 37, 38, 42, 43, 44, 46, 49, 54, 59], 'conflict_call': 20}, ['max-out', 45]), ({'min_green': 10, 'gap': 3, 'max_green': 43, 'actuations': [0, 4, 7, 12, 14, 21, 24, 25, 41, 44, 47, 59], 'conflict_call': 10}, ['gap-out', 10]), ({'min_green': 10, 'gap': 2, 'max_green': 3, 'actuations': [], 'conflict_call': 0}, ['max-out', 3])], [({'min_green': 6, 'gap': 2, 'max_green': 15, 'actuations': [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38], 'conflict_call': -3}, ['max-out', 15]), ({'min_green': 4, 'gap': 3, 'max_green': 31, 'actuations': [7, 8, 11, 14, 15, 21, 27, 32, 37, 46, 52, 57], 'conflict_call': None}, ['rest', 4]), ({'min_green': 10, 'gap': 2, 'max_green': 3, 'actuations': [], 'conflict_call': 0}, ['max-out', 3]), ({'min_green': 5, 'gap': 5, 'max_green': 22, 'actuations': [1, 3, 5, 9, 12, 13, 14, 15, 16, 17, 18, 22, 23, 24, 25, 27, 29, 31, 32, 34, 36, 37, 38, 40, 47, 49, 52, 55, 56, 57, 58, 59], 'conflict_call': 32}, ['gap-out', 45]), ({'min_green': 5, 'gap': 3, 'max_green': 25, 'actuations': [9, 3, 6], 'conflict_call': None}, ['rest', 12]), ({'min_green': 5, 'gap': 4, 'max_green': 44, 'actuations': [1, 3, 4, 5, 6, 7, 10, 16, 17, 19, 20, 21, 25, 26, 28, 29, 32, 33, 34, 35, 38, 39, 41, 43, 44, 47, 49, 52, 56, 57, 58, 59], 'conflict_call': None}, ['rest', 14]), ({'min_green': 8, 'gap': 3, 'max_green': 29, 'actuations': [0, 2, 3, 6, 9, 11, 12, 14, 15, 17, 18, 19, 21, 22, 25, 27, 30, 31, 36, 38, 41, 42, 43, 45, 48, 52, 53, 55, 57, 59], 'conflict_call': 31}, ['gap-out', 34]), ({'min_green': 4, 'gap': 5, 'max_green': 45, 'actuations': [2, 3, 4, 5, 6, 7, 11, 12, 15, 17, 18, 20, 21, 22, 23, 25, 28, 29, 34, 35, 36, 37, 39, 41, 42, 49, 50, 51, 55, 56], 'conflict_call': 29}, ['gap-out', 47])], [({'min_green': 8, 'gap': 3, 'max_green': 30, 'actuations': [2, 6], 'conflict_call': 20}, ['gap-out', 20]), ({'min_green': 5, 'gap': 3, 'max_green': 25, 'actuations': [9, 3, 6], 'conflict_call': None}, ['rest', 12]), ({'min_green': 6, 'gap': 2, 'max_green': 15, 'actuations': [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38], 'conflict_call': -3}, ['max-out', 15]), ({'min_green': 4, 'gap': 3, 'max_green': 33, 'actuations': [13, 36, 51, 10, 4, 20, 44, 6, 49, 32, 40, 7, 47, 14, 21, 31, 29, 8, 9, 56, 53, 50, 38, 5, 24, 27, 12, 17, 45, 52, 54], 'conflict_call': -6}, ['max-out', 33]), ({'min_green': 9, 'gap': 5, 'max_green': 34, 'actuations': [0, 2, 8, 9, 10, 11, 14, 16, 18, 23, 27, 29, 30, 31, 36, 38, 39, 40, 48, 50, 53, 55, 56], 'conflict_call': 33}, ['gap-out', 45]), ({'min_green': 10, 'gap': 5, 'max_green': 28, 'actuations': [13, 1, 18, 8, 59, 45, 3, 31, 4, 36, 12, 50, 6, 46, 7, 34, 40, 54, 19, 53, 48, 20, 52, 25, 57, 47, 5, 24, 16], 'conflict_call': 31}, ['gap-out', 31]), ({'min_green': 7, 'gap': 2, 'max_green': 31, 'actuations': [0, 2, 3, 7, 9, 19, 21, 23, 25, 28, 30, 38, 41, 43, 44, 48, 49, 51, 53, 56, 57], 'conflict_call': None}, ['rest', 11]), ({'min_green': 8, 'gap': 4, 'max_green': 44, 'actuations': [0, 2, 4, 6, 9, 12, 13, 15, 17, 18, 19, 23, 26, 29, 30, 32, 33, 35, 36, 38, 40, 41, 42, 44, 45, 47, 48, 49, 50, 51, 55, 56], 'conflict_call': 15}, ['max-out', 59])], [({'min_green': 7, 'gap': 5, 'max_green': 38, 'actuations': [1, 3, 5, 6, 8, 9, 10, 11, 12, 13, 16, 18, 21, 23, 25, 26, 29, 31, 33, 34, 37, 38, 40, 41, 43, 44, 46, 48, 53, 54, 56, 57, 59], 'conflict_call': 12}, ['max-out', 50]), ({'min_green': 8, 'gap': 3, 'max_green': 30, 'actuations': [2, 6], 'conflict_call': 20}, ['gap-out', 20]), ({'min_green': 7, 'gap': 3, 'max_green': 19, 'actuations': [0, 2, 5, 6, 7, 12, 15, 17, 21, 24, 25, 26, 27, 28, 29, 33, 34, 36, 38, 39, 40, 41, 44, 45, 47, 49, 50, 53, 54, 56], 'conflict_call': 0}, ['gap-out', 10]), ({'min_green': 6, 'gap': 2, 'max_green': 12, 'actuations': [1, 3, 5, 7, 9, 11, 13], 'conflict_call': 3}, ['gap-out', 15]), ({'min_green': 5, 'gap': 4, 'max_green': 41, 'actuations': [1, 2, 4, 6, 7, 8, 10, 13, 14, 17, 18, 19, 20, 21, 25, 26, 27, 28, 32, 35, 37, 38, 39, 40, 41, 43, 45, 47, 48, 50, 54, 55, 59], 'conflict_call': 31}, ['gap-out', 63]), ({'min_green': 10, 'gap': 4, 'max_green': 21, 'actuations': [5, 30, 36, 38, 46, 55], 'conflict_call': 34}, ['gap-out', 34]), ({'min_green': 4, 'gap': 5, 'max_green': 28, 'actuations': [2, 7, 57], 'conflict_call': None}, ['rest', 12]), ({'min_green': 6, 'gap': 2, 'max_green': 15, 'actuations': [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38], 'conflict_call': -3}, ['max-out', 15])]]
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| timing oracle 0 | ['gap-out', 15] | ['gap-out', 15] | Passed |
| timing oracle 1 | ['gap-out', 62] | ['gap-out', 62] | Passed |
| timing oracle 2 | ['max-out', 49] | ['max-out', 57] | Failed |
| timing oracle 3 | ['gap-out', 23] | ['gap-out', 23] | Passed |
| timing oracle 4 | ['max-out', -7] | ['max-out', 3] | Failed |
| timing oracle 5 | ['gap-out', 16] | ['gap-out', 16] | Passed |
| timing oracle 6 | ['gap-out', 20] | ['gap-out', 20] | Passed |
| timing oracle 7 | ['gap-out', 49] | ['gap-out', 49] | Passed |
SHA-256 / 8aed73e3405174c22fe6d63ec6799029c02a1b6a1b909485513638fe471dcf6f
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
m, p, M = x['min_green'], x['gap'], x['max_green']
exp = 0
for a in sorted(x['actuations']):
if a > exp and a > m:
break
exp = max(exp, a + p)
gap_end = max(m, exp)
tc = x['conflict_call']
if tc is None:
return ['rest', gap_end]
tc = max(tc, 0)
max_end = tc + M
if gap_end <= max_end:
return ['gap-out', max(gap_end, tc)]
return ['max-out', max_end]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[({'min_green': 4, 'gap': 4, 'max_green': 38, 'actuations': [2, 5, 6, 7, 8, 14, 16, 20, 23, 24, 26, 30, 32, 35, 41, 44, 49, 51, 54, 56, 59], 'conflict_call': 15}, ['gap-out', 15]), ({'min_green': 7, 'gap': 5, 'max_green': 40, 'actuations': [2, 3, 5, 7, 10, 12, 13, 14, 15, 18, 19, 20, 25, 29, 32, 33, 35, 37, 39, 44, 45, 46, 51, 52, 54, 57], 'conflict_call': 34}, ['gap-out', 62]), ({'min_green': 8, 'gap': 5, 'max_green': 37, 'actuations': [2, 6, 8, 10, 11, 12, 14, 16, 17, 18, 19, 24, 25, 27, 28, 30, 31, 35, 37, 39, 43, 45, 46, 47, 48, 49, 50, 51, 55, 57], 'conflict_call': 20}, ['max-out', 57]), ({'min_green': 7, 'gap': 3, 'max_green': 15, 'actuations': [46, 42, 45, 38, 32, 27, 3, 9, 1, 15, 24, 16, 56, 2, 22, 40, 20, 14, 7, 28, 26, 8, 55, 58, 29, 5, 48, 59, 34, 35, 11], 'conflict_call': 23}, ['gap-out', 23]), ({'min_green': 10, 'gap': 2, 'max_green': 3, 'actuations': [], 'conflict_call': 0}, ['max-out', 3]), ({'min_green': 5, 'gap': 3, 'max_green': 20, 'actuations': [1, 4, 7, 10, 13], 'conflict_call': 2}, ['gap-out', 16]), ({'min_green': 8, 'gap': 3, 'max_green': 30, 'actuations': [2, 6], 'conflict_call': 20}, ['gap-out', 20]), ({'min_green': 9, 'gap': 4, 'max_green': 38, 'actuations': [13, 39, 8, 1, 36, 52, 20, 18, 53, 9, 45, 56, 55, 17, 2, 58, 23, 42, 26, 24, 14, 7, 34, 11, 33, 30, 51, 54, 28, 35, 50], 'conflict_call': 27}, ['gap-out', 49])], [({'min_green': 6, 'gap': 3, 'max_green': 29, 'actuations': [0, 2, 4, 5, 8, 9, 10, 13, 14, 19, 21, 22, 27, 28, 30, 31, 33, 35, 38, 39, 40, 42, 44, 46, 47, 48, 49, 51, 54, 55, 56, 57, 59], 'conflict_call': 16}, ['gap-out', 17]), ({'min_green': 12, 'gap': 3, 'max_green': 5, 'actuations': [1], 'conflict_call': 2}, ['max-out', 7]), ({'min_green': 4, 'gap': 2, 'max_green': 38, 'actuations': [0, 5, 6, 7, 10, 11, 16, 17, 20, 21, 24, 27, 29, 31, 33, 34, 35, 39, 41, 43, 46, 47, 48, 49, 52, 55, 57, 58], 'conflict_call': 11}, ['gap-out', 11]), ({'min_green': 5, 'gap': 3, 'max_green': 25, 'actuations': [9, 3, 6], 'conflict_call': None}, ['rest', 12]), ({'min_green': 4, 'gap': 5, 'max_green': 23, 'actuations': [1, 3, 6, 8, 11, 12, 15, 20, 25, 27, 28, 29, 31, 35, 37, 38, 41, 42, 43, 44, 50, 57], 'conflict_call': 10}, ['max-out', 33]), ({'min_green': 10, 'gap': 5, 'max_green': 25, 'actuations': [1, 3, 7, 9, 10, 14, 16, 18, 19, 23, 24, 26, 27, 28, 30, 34, 35, 37, 38, 42, 43, 44, 46, 49, 54, 59], 'conflict_call': 20}, ['max-out', 45]), ({'min_green': 10, 'gap': 3, 'max_green': 43, 'actuations': [0, 4, 7, 12, 14, 21, 24, 25, 41, 44, 47, 59], 'conflict_call': 10}, ['gap-out', 10]), ({'min_green': 10, 'gap': 2, 'max_green': 3, 'actuations': [], 'conflict_call': 0}, ['max-out', 3])], [({'min_green': 6, 'gap': 2, 'max_green': 15, 'actuations': [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38], 'conflict_call': -3}, ['max-out', 15]), ({'min_green': 4, 'gap': 3, 'max_green': 31, 'actuations': [7, 8, 11, 14, 15, 21, 27, 32, 37, 46, 52, 57], 'conflict_call': None}, ['rest', 4]), ({'min_green': 10, 'gap': 2, 'max_green': 3, 'actuations': [], 'conflict_call': 0}, ['max-out', 3]), ({'min_green': 5, 'gap': 5, 'max_green': 22, 'actuations': [1, 3, 5, 9, 12, 13, 14, 15, 16, 17, 18, 22, 23, 24, 25, 27, 29, 31, 32, 34, 36, 37, 38, 40, 47, 49, 52, 55, 56, 57, 58, 59], 'conflict_call': 32}, ['gap-out', 45]), ({'min_green': 5, 'gap': 3, 'max_green': 25, 'actuations': [9, 3, 6], 'conflict_call': None}, ['rest', 12]), ({'min_green': 5, 'gap': 4, 'max_green': 44, 'actuations': [1, 3, 4, 5, 6, 7, 10, 16, 17, 19, 20, 21, 25, 26, 28, 29, 32, 33, 34, 35, 38, 39, 41, 43, 44, 47, 49, 52, 56, 57, 58, 59], 'conflict_call': None}, ['rest', 14]), ({'min_green': 8, 'gap': 3, 'max_green': 29, 'actuations': [0, 2, 3, 6, 9, 11, 12, 14, 15, 17, 18, 19, 21, 22, 25, 27, 30, 31, 36, 38, 41, 42, 43, 45, 48, 52, 53, 55, 57, 59], 'conflict_call': 31}, ['gap-out', 34]), ({'min_green': 4, 'gap': 5, 'max_green': 45, 'actuations': [2, 3, 4, 5, 6, 7, 11, 12, 15, 17, 18, 20, 21, 22, 23, 25, 28, 29, 34, 35, 36, 37, 39, 41, 42, 49, 50, 51, 55, 56], 'conflict_call': 29}, ['gap-out', 47])], [({'min_green': 8, 'gap': 3, 'max_green': 30, 'actuations': [2, 6], 'conflict_call': 20}, ['gap-out', 20]), ({'min_green': 5, 'gap': 3, 'max_green': 25, 'actuations': [9, 3, 6], 'conflict_call': None}, ['rest', 12]), ({'min_green': 6, 'gap': 2, 'max_green': 15, 'actuations': [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38], 'conflict_call': -3}, ['max-out', 15]), ({'min_green': 4, 'gap': 3, 'max_green': 33, 'actuations': [13, 36, 51, 10, 4, 20, 44, 6, 49, 32, 40, 7, 47, 14, 21, 31, 29, 8, 9, 56, 53, 50, 38, 5, 24, 27, 12, 17, 45, 52, 54], 'conflict_call': -6}, ['max-out', 33]), ({'min_green': 9, 'gap': 5, 'max_green': 34, 'actuations': [0, 2, 8, 9, 10, 11, 14, 16, 18, 23, 27, 29, 30, 31, 36, 38, 39, 40, 48, 50, 53, 55, 56], 'conflict_call': 33}, ['gap-out', 45]), ({'min_green': 10, 'gap': 5, 'max_green': 28, 'actuations': [13, 1, 18, 8, 59, 45, 3, 31, 4, 36, 12, 50, 6, 46, 7, 34, 40, 54, 19, 53, 48, 20, 52, 25, 57, 47, 5, 24, 16], 'conflict_call': 31}, ['gap-out', 31]), ({'min_green': 7, 'gap': 2, 'max_green': 31, 'actuations': [0, 2, 3, 7, 9, 19, 21, 23, 25, 28, 30, 38, 41, 43, 44, 48, 49, 51, 53, 56, 57], 'conflict_call': None}, ['rest', 11]), ({'min_green': 8, 'gap': 4, 'max_green': 44, 'actuations': [0, 2, 4, 6, 9, 12, 13, 15, 17, 18, 19, 23, 26, 29, 30, 32, 33, 35, 36, 38, 40, 41, 42, 44, 45, 47, 48, 49, 50, 51, 55, 56], 'conflict_call': 15}, ['max-out', 59])], [({'min_green': 7, 'gap': 5, 'max_green': 38, 'actuations': [1, 3, 5, 6, 8, 9, 10, 11, 12, 13, 16, 18, 21, 23, 25, 26, 29, 31, 33, 34, 37, 38, 40, 41, 43, 44, 46, 48, 53, 54, 56, 57, 59], 'conflict_call': 12}, ['max-out', 50]), ({'min_green': 8, 'gap': 3, 'max_green': 30, 'actuations': [2, 6], 'conflict_call': 20}, ['gap-out', 20]), ({'min_green': 7, 'gap': 3, 'max_green': 19, 'actuations': [0, 2, 5, 6, 7, 12, 15, 17, 21, 24, 25, 26, 27, 28, 29, 33, 34, 36, 38, 39, 40, 41, 44, 45, 47, 49, 50, 53, 54, 56], 'conflict_call': 0}, ['gap-out', 10]), ({'min_green': 6, 'gap': 2, 'max_green': 12, 'actuations': [1, 3, 5, 7, 9, 11, 13], 'conflict_call': 3}, ['gap-out', 15]), ({'min_green': 5, 'gap': 4, 'max_green': 41, 'actuations': [1, 2, 4, 6, 7, 8, 10, 13, 14, 17, 18, 19, 20, 21, 25, 26, 27, 28, 32, 35, 37, 38, 39, 40, 41, 43, 45, 47, 48, 50, 54, 55, 59], 'conflict_call': 31}, ['gap-out', 63]), ({'min_green': 10, 'gap': 4, 'max_green': 21, 'actuations': [5, 30, 36, 38, 46, 55], 'conflict_call': 34}, ['gap-out', 34]), ({'min_green': 4, 'gap': 5, 'max_green': 28, 'actuations': [2, 7, 57], 'conflict_call': None}, ['rest', 12]), ({'min_green': 6, 'gap': 2, 'max_green': 15, 'actuations': [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38], 'conflict_call': -3}, ['max-out', 15])]]
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| timing oracle 0 | ['gap-out', 15] | ['gap-out', 15] | Passed |
| timing oracle 1 | ['gap-out', 62] | ['gap-out', 62] | Passed |
| timing oracle 2 | ['max-out', 57] | ['max-out', 57] | Passed |
| timing oracle 3 | ['gap-out', 23] | ['gap-out', 23] | Passed |
| timing oracle 4 | ['max-out', 3] | ['max-out', 3] | Passed |
| timing oracle 5 | ['gap-out', 16] | ['gap-out', 16] | Passed |
| timing oracle 6 | ['gap-out', 20] | ['gap-out', 20] | Passed |
| timing oracle 7 | ['gap-out', 49] | ['gap-out', 49] | Passed |
SHA-256 / eece92289fd2b32c7b078480a6b72ceafd8de8a1191675ae710dc55c66d0fc2d
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:47:57.886220+00:00.
Case digest / 6dcd5f2c54d3575f4c394ae74423d127068a9ca9708f0860e9e7aa79cf59c178