FA-67986 / Traffic signal timing plans / Open access
Actuated phase gap-out and max-out: the passage timer is started only after min green · case 01
Actuated phase gap-out and max-out returns a wrong result when the passage timer is started only after min green.
ROOT CAUSE
Counting the actuation second as part of the gap expires every extension one second early.
VERIFIED REPAIR
Restore the passage expiry instant rule so that the step reads `exp = max(exp, a + p)`.
Unsuccessful approach: Delaying the passage timer until the end of min green extends phases for actuations the contract counts from their own time.
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 - 1)
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': 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': 8, 'gap': 3, 'max_green': 30, 'actuations': [2, 6], 'conflict_call': 20}, ['gap-out', 20]), ({'min_green': 9, 'gap': 2, 'max_green': 27, 'actuations': [2, 4, 6, 12, 13, 19, 22, 25, 39, 42], 'conflict_call': 8}, ['gap-out', 9]), ({'min_green': 9, 'gap': 2, 'max_green': 28, 'actuations': [1, 6, 8, 12, 14, 16, 18, 19, 21, 22, 24, 33, 34, 37, 40, 47, 50, 52, 58], 'conflict_call': 21}, ['gap-out', 21]), ({'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': 34, 'actuations': [25, 15, 18, 8, 49, 45, 14, 40, 51, 13, 33, 42, 36, 11, 58, 16, 10, 55, 3], 'conflict_call': -1}, ['gap-out', 21]), ({'min_green': 4, 'gap': 3, 'max_green': 27, 'actuations': [0, 10, 18, 20, 23, 25, 36, 39, 40, 50, 54, 58], 'conflict_call': None}, ['rest', 4]), ({'min_green': 4, 'gap': 5, 'max_green': 24, 'actuations': [4, 18, 35, 45, 48, 49], 'conflict_call': 31}, ['gap-out', 31])], [({'min_green': 6, 'gap': 5, 'max_green': 32, 'actuations': [2, 5, 6, 7, 8, 11, 12, 15, 16, 17, 19, 21, 23, 26, 27, 28, 29, 32, 35, 37, 42, 44, 45, 47, 49, 50, 52, 56, 57, 59], 'conflict_call': 25}, ['max-out', 57]), ({'min_green': 5, 'gap': 4, 'max_green': 23, 'actuations': [0, 2, 4, 16, 19, 21, 22, 24, 28, 40, 44, 45, 46, 54, 55, 57, 58], 'conflict_call': None}, ['rest', 8]), ({'min_green': 5, 'gap': 3, 'max_green': 10, 'actuations': [0, 3, 6, 9, 12], 'conflict_call': 5}, ['gap-out', 15]), ({'min_green': 7, 'gap': 4, 'max_green': 21, 'actuations': [3, 6, 8, 9, 11, 12, 15, 17, 19, 21, 23, 25, 28, 33, 34, 35, 39, 47, 52, 54, 56, 58, 59], 'conflict_call': 7}, ['max-out', 28]), ({'min_green': 6, 'gap': 2, 'max_green': 12, 'actuations': [1, 3, 5, 7, 9, 11, 13], 'conflict_call': 3}, ['gap-out', 15]), ({'min_green': 4, 'gap': 4, 'max_green': 15, 'actuations': [1, 2, 4, 6, 11, 13, 15, 19, 20, 22, 23, 26, 27, 37, 41, 44, 47, 48, 50, 52, 53, 54, 56, 58, 59], 'conflict_call': 26}, ['gap-out', 26]), ({'min_green': 12, 'gap': 3, 'max_green': 5, 'actuations': [1], 'conflict_call': 2}, ['max-out', 7]), ({'min_green': 8, 'gap': 5, 'max_green': 16, 'actuations': [2, 17, 23, 41, 50, 54, 57, 59], 'conflict_call': -2}, ['gap-out', 8])], [({'min_green': 5, 'gap': 3, 'max_green': 20, 'actuations': [1, 4, 7, 10, 13], 'conflict_call': 2}, ['gap-out', 16]), ({'min_green': 6, 'gap': 2, 'max_green': 29, 'actuations': [0, 1, 2, 3, 7, 8, 9, 10, 11, 12, 16, 17, 19, 24, 27, 29, 32, 34, 36, 40, 41, 42, 43, 45, 46, 47, 48, 49, 50, 53, 56, 58, 59], 'conflict_call': -3}, ['gap-out', 6]), ({'min_green': 4, 'gap': 5, 'max_green': 22, 'actuations': [1, 2, 8, 11, 18, 20, 24, 26, 35, 37, 39, 45, 47, 50, 51, 54, 55, 56, 57, 59], 'conflict_call': 31}, ['gap-out', 31]), ({'min_green': 7, 'gap': 5, 'max_green': 42, 'actuations': [1, 3, 5, 8, 10, 29, 33, 38, 42, 44, 50, 53, 55], 'conflict_call': -5}, ['gap-out', 15]), ({'min_green': 6, 'gap': 2, 'max_green': 12, 'actuations': [1, 3, 5, 7, 9, 11, 13], 'conflict_call': 3}, ['gap-out', 15]), ({'min_green': 7, 'gap': 4, 'max_green': 34, 'actuations': [49, 44, 18, 9, 59, 20, 16, 5, 26, 24, 37, 54, 32, 3, 27, 6, 15, 53, 28, 57, 52, 47, 46, 19, 38, 51, 58, 23, 40, 30], 'conflict_call': 24}, ['gap-out', 24]), ({'min_green': 5, 'gap': 5, 'max_green': 30, 'actuations': [3, 12, 14, 28, 29, 34, 37, 42, 44, 45, 48, 52, 54, 56, 59], 'conflict_call': None}, ['rest', 8]), ({'min_green': 12, 'gap': 3, 'max_green': 5, 'actuations': [1], 'conflict_call': 2}, ['max-out', 7])], [({'min_green': 10, 'gap': 2, 'max_green': 15, 'actuations': [2, 5, 6, 8, 9, 14, 15, 17, 18, 22, 25, 26, 30, 31, 33, 36, 40, 42, 50], 'conflict_call': 6}, ['gap-out', 11]), ({'min_green': 12, 'gap': 3, 'max_green': 5, 'actuations': [1], 'conflict_call': 2}, ['max-out', 7]), ({'min_green': 4, 'gap': 5, 'max_green': 25, 'actuations': [1, 9, 10, 12, 13, 14, 15, 16, 17, 21, 24, 26, 27, 29, 30, 36, 37, 38, 41, 42, 43, 46, 47, 48, 49, 51, 53, 55, 58], 'conflict_call': 10}, ['gap-out', 10]), ({'min_green': 7, 'gap': 3, 'max_green': 15, 'actuations': [54, 34, 26, 11, 41, 56, 5], 'conflict_call': 10}, ['gap-out', 10]), ({'min_green': 5, 'gap': 3, 'max_green': 20, 'actuations': [1, 4, 7, 10, 13], 'conflict_call': 2}, ['gap-out', 16]), ({'min_green': 6, 'gap': 2, 'max_green': 12, 'actuations': [1, 3, 5, 7, 9, 11, 13], 'conflict_call': 3}, ['gap-out', 15]), ({'min_green': 4, 'gap': 3, 'max_green': 19, 'actuations': [0, 4, 7, 8, 13, 15, 17, 18, 21, 22, 23, 26, 28, 29, 30, 33, 35, 37, 41, 43, 45, 46, 47, 49, 50, 53, 56, 57], 'conflict_call': 30}, ['gap-out', 30]), ({'min_green': 4, 'gap': 3, 'max_green': 45, 'actuations': [0, 4, 5, 6, 8, 16, 17, 22, 23, 27, 31, 39, 40, 42, 45, 47, 48, 52, 54, 58], 'conflict_call': 27}, ['gap-out', 27])], [({'min_green': 4, 'gap': 2, 'max_green': 32, 'actuations': [10, 16, 21, 24, 25, 27, 30, 34, 39, 42, 49, 50, 52, 53, 56], 'conflict_call': 9}, ['gap-out', 9]), ({'min_green': 4, 'gap': 3, 'max_green': 31, 'actuations': [14, 21, 44, 47], 'conflict_call': 0}, ['gap-out', 4]), ({'min_green': 12, 'gap': 3, 'max_green': 5, 'actuations': [1], 'conflict_call': 2}, ['max-out', 7]), ({'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': 10, 'gap': 3, 'max_green': 39, 'actuations': [1, 2, 3, 4, 5, 8, 9, 11, 13, 15, 16, 17, 20, 21, 23, 29, 31, 32, 35, 36, 37, 42, 44, 45, 47, 48, 52, 55, 56, 59], 'conflict_call': 12}, ['gap-out', 26]), ({'min_green': 9, 'gap': 4, 'max_green': 29, 'actuations': [2, 4, 7, 17, 23, 25, 27, 36, 37, 45, 50], 'conflict_call': None}, ['rest', 11]), ({'min_green': 5, 'gap': 3, 'max_green': 20, 'actuations': [1, 4, 7, 10, 13], 'conflict_call': 2}, ['gap-out', 16]), ({'min_green': 8, 'gap': 2, 'max_green': 31, 'actuations': [2, 11, 12, 14, 15, 27, 37, 41, 46, 49], 'conflict_call': None}, ['rest', 8])]]
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', 7] | ['max-out', 15] | Failed |
| timing oracle 1 | ['gap-out', 20] | ['gap-out', 20] | Passed |
| timing oracle 2 | ['gap-out', 9] | ['gap-out', 9] | Passed |
| timing oracle 3 | ['gap-out', 21] | ['gap-out', 21] | Passed |
| timing oracle 4 | ['gap-out', 6] | ['gap-out', 16] | Failed |
| timing oracle 5 | ['gap-out', 20] | ['gap-out', 21] | Failed |
| timing oracle 6 | ['rest', 4] | ['rest', 4] | Passed |
| timing oracle 7 | ['gap-out', 31] | ['gap-out', 31] | Passed |
SHA-256 / 6dd39b93f2413ed483221d4fc1d1061344194ef1f7506e0e77f646e210c38c1e
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, max(a, m) + 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': 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': 8, 'gap': 3, 'max_green': 30, 'actuations': [2, 6], 'conflict_call': 20}, ['gap-out', 20]), ({'min_green': 9, 'gap': 2, 'max_green': 27, 'actuations': [2, 4, 6, 12, 13, 19, 22, 25, 39, 42], 'conflict_call': 8}, ['gap-out', 9]), ({'min_green': 9, 'gap': 2, 'max_green': 28, 'actuations': [1, 6, 8, 12, 14, 16, 18, 19, 21, 22, 24, 33, 34, 37, 40, 47, 50, 52, 58], 'conflict_call': 21}, ['gap-out', 21]), ({'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': 34, 'actuations': [25, 15, 18, 8, 49, 45, 14, 40, 51, 13, 33, 42, 36, 11, 58, 16, 10, 55, 3], 'conflict_call': -1}, ['gap-out', 21]), ({'min_green': 4, 'gap': 3, 'max_green': 27, 'actuations': [0, 10, 18, 20, 23, 25, 36, 39, 40, 50, 54, 58], 'conflict_call': None}, ['rest', 4]), ({'min_green': 4, 'gap': 5, 'max_green': 24, 'actuations': [4, 18, 35, 45, 48, 49], 'conflict_call': 31}, ['gap-out', 31])], [({'min_green': 6, 'gap': 5, 'max_green': 32, 'actuations': [2, 5, 6, 7, 8, 11, 12, 15, 16, 17, 19, 21, 23, 26, 27, 28, 29, 32, 35, 37, 42, 44, 45, 47, 49, 50, 52, 56, 57, 59], 'conflict_call': 25}, ['max-out', 57]), ({'min_green': 5, 'gap': 4, 'max_green': 23, 'actuations': [0, 2, 4, 16, 19, 21, 22, 24, 28, 40, 44, 45, 46, 54, 55, 57, 58], 'conflict_call': None}, ['rest', 8]), ({'min_green': 5, 'gap': 3, 'max_green': 10, 'actuations': [0, 3, 6, 9, 12], 'conflict_call': 5}, ['gap-out', 15]), ({'min_green': 7, 'gap': 4, 'max_green': 21, 'actuations': [3, 6, 8, 9, 11, 12, 15, 17, 19, 21, 23, 25, 28, 33, 34, 35, 39, 47, 52, 54, 56, 58, 59], 'conflict_call': 7}, ['max-out', 28]), ({'min_green': 6, 'gap': 2, 'max_green': 12, 'actuations': [1, 3, 5, 7, 9, 11, 13], 'conflict_call': 3}, ['gap-out', 15]), ({'min_green': 4, 'gap': 4, 'max_green': 15, 'actuations': [1, 2, 4, 6, 11, 13, 15, 19, 20, 22, 23, 26, 27, 37, 41, 44, 47, 48, 50, 52, 53, 54, 56, 58, 59], 'conflict_call': 26}, ['gap-out', 26]), ({'min_green': 12, 'gap': 3, 'max_green': 5, 'actuations': [1], 'conflict_call': 2}, ['max-out', 7]), ({'min_green': 8, 'gap': 5, 'max_green': 16, 'actuations': [2, 17, 23, 41, 50, 54, 57, 59], 'conflict_call': -2}, ['gap-out', 8])], [({'min_green': 5, 'gap': 3, 'max_green': 20, 'actuations': [1, 4, 7, 10, 13], 'conflict_call': 2}, ['gap-out', 16]), ({'min_green': 6, 'gap': 2, 'max_green': 29, 'actuations': [0, 1, 2, 3, 7, 8, 9, 10, 11, 12, 16, 17, 19, 24, 27, 29, 32, 34, 36, 40, 41, 42, 43, 45, 46, 47, 48, 49, 50, 53, 56, 58, 59], 'conflict_call': -3}, ['gap-out', 6]), ({'min_green': 4, 'gap': 5, 'max_green': 22, 'actuations': [1, 2, 8, 11, 18, 20, 24, 26, 35, 37, 39, 45, 47, 50, 51, 54, 55, 56, 57, 59], 'conflict_call': 31}, ['gap-out', 31]), ({'min_green': 7, 'gap': 5, 'max_green': 42, 'actuations': [1, 3, 5, 8, 10, 29, 33, 38, 42, 44, 50, 53, 55], 'conflict_call': -5}, ['gap-out', 15]), ({'min_green': 6, 'gap': 2, 'max_green': 12, 'actuations': [1, 3, 5, 7, 9, 11, 13], 'conflict_call': 3}, ['gap-out', 15]), ({'min_green': 7, 'gap': 4, 'max_green': 34, 'actuations': [49, 44, 18, 9, 59, 20, 16, 5, 26, 24, 37, 54, 32, 3, 27, 6, 15, 53, 28, 57, 52, 47, 46, 19, 38, 51, 58, 23, 40, 30], 'conflict_call': 24}, ['gap-out', 24]), ({'min_green': 5, 'gap': 5, 'max_green': 30, 'actuations': [3, 12, 14, 28, 29, 34, 37, 42, 44, 45, 48, 52, 54, 56, 59], 'conflict_call': None}, ['rest', 8]), ({'min_green': 12, 'gap': 3, 'max_green': 5, 'actuations': [1], 'conflict_call': 2}, ['max-out', 7])], [({'min_green': 10, 'gap': 2, 'max_green': 15, 'actuations': [2, 5, 6, 8, 9, 14, 15, 17, 18, 22, 25, 26, 30, 31, 33, 36, 40, 42, 50], 'conflict_call': 6}, ['gap-out', 11]), ({'min_green': 12, 'gap': 3, 'max_green': 5, 'actuations': [1], 'conflict_call': 2}, ['max-out', 7]), ({'min_green': 4, 'gap': 5, 'max_green': 25, 'actuations': [1, 9, 10, 12, 13, 14, 15, 16, 17, 21, 24, 26, 27, 29, 30, 36, 37, 38, 41, 42, 43, 46, 47, 48, 49, 51, 53, 55, 58], 'conflict_call': 10}, ['gap-out', 10]), ({'min_green': 7, 'gap': 3, 'max_green': 15, 'actuations': [54, 34, 26, 11, 41, 56, 5], 'conflict_call': 10}, ['gap-out', 10]), ({'min_green': 5, 'gap': 3, 'max_green': 20, 'actuations': [1, 4, 7, 10, 13], 'conflict_call': 2}, ['gap-out', 16]), ({'min_green': 6, 'gap': 2, 'max_green': 12, 'actuations': [1, 3, 5, 7, 9, 11, 13], 'conflict_call': 3}, ['gap-out', 15]), ({'min_green': 4, 'gap': 3, 'max_green': 19, 'actuations': [0, 4, 7, 8, 13, 15, 17, 18, 21, 22, 23, 26, 28, 29, 30, 33, 35, 37, 41, 43, 45, 46, 47, 49, 50, 53, 56, 57], 'conflict_call': 30}, ['gap-out', 30]), ({'min_green': 4, 'gap': 3, 'max_green': 45, 'actuations': [0, 4, 5, 6, 8, 16, 17, 22, 23, 27, 31, 39, 40, 42, 45, 47, 48, 52, 54, 58], 'conflict_call': 27}, ['gap-out', 27])], [({'min_green': 4, 'gap': 2, 'max_green': 32, 'actuations': [10, 16, 21, 24, 25, 27, 30, 34, 39, 42, 49, 50, 52, 53, 56], 'conflict_call': 9}, ['gap-out', 9]), ({'min_green': 4, 'gap': 3, 'max_green': 31, 'actuations': [14, 21, 44, 47], 'conflict_call': 0}, ['gap-out', 4]), ({'min_green': 12, 'gap': 3, 'max_green': 5, 'actuations': [1], 'conflict_call': 2}, ['max-out', 7]), ({'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': 10, 'gap': 3, 'max_green': 39, 'actuations': [1, 2, 3, 4, 5, 8, 9, 11, 13, 15, 16, 17, 20, 21, 23, 29, 31, 32, 35, 36, 37, 42, 44, 45, 47, 48, 52, 55, 56, 59], 'conflict_call': 12}, ['gap-out', 26]), ({'min_green': 9, 'gap': 4, 'max_green': 29, 'actuations': [2, 4, 7, 17, 23, 25, 27, 36, 37, 45, 50], 'conflict_call': None}, ['rest', 11]), ({'min_green': 5, 'gap': 3, 'max_green': 20, 'actuations': [1, 4, 7, 10, 13], 'conflict_call': 2}, ['gap-out', 16]), ({'min_green': 8, 'gap': 2, 'max_green': 31, 'actuations': [2, 11, 12, 14, 15, 27, 37, 41, 46, 49], 'conflict_call': None}, ['rest', 8])]]
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 | ['max-out', 15] | ['max-out', 15] | Passed |
| timing oracle 1 | ['gap-out', 20] | ['gap-out', 20] | Passed |
| timing oracle 2 | ['gap-out', 11] | ['gap-out', 9] | Failed |
| timing oracle 3 | ['gap-out', 21] | ['gap-out', 21] | Passed |
| timing oracle 4 | ['gap-out', 16] | ['gap-out', 16] | Passed |
| timing oracle 5 | ['gap-out', 21] | ['gap-out', 21] | Passed |
| timing oracle 6 | ['rest', 7] | ['rest', 4] | Failed |
| timing oracle 7 | ['gap-out', 31] | ['gap-out', 31] | Passed |
SHA-256 / 8cd1f4a389542c7b8b66cba24cc3ffc0ca356e259482fb18cd7bcc0c2680dbec
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': 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': 8, 'gap': 3, 'max_green': 30, 'actuations': [2, 6], 'conflict_call': 20}, ['gap-out', 20]), ({'min_green': 9, 'gap': 2, 'max_green': 27, 'actuations': [2, 4, 6, 12, 13, 19, 22, 25, 39, 42], 'conflict_call': 8}, ['gap-out', 9]), ({'min_green': 9, 'gap': 2, 'max_green': 28, 'actuations': [1, 6, 8, 12, 14, 16, 18, 19, 21, 22, 24, 33, 34, 37, 40, 47, 50, 52, 58], 'conflict_call': 21}, ['gap-out', 21]), ({'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': 34, 'actuations': [25, 15, 18, 8, 49, 45, 14, 40, 51, 13, 33, 42, 36, 11, 58, 16, 10, 55, 3], 'conflict_call': -1}, ['gap-out', 21]), ({'min_green': 4, 'gap': 3, 'max_green': 27, 'actuations': [0, 10, 18, 20, 23, 25, 36, 39, 40, 50, 54, 58], 'conflict_call': None}, ['rest', 4]), ({'min_green': 4, 'gap': 5, 'max_green': 24, 'actuations': [4, 18, 35, 45, 48, 49], 'conflict_call': 31}, ['gap-out', 31])], [({'min_green': 6, 'gap': 5, 'max_green': 32, 'actuations': [2, 5, 6, 7, 8, 11, 12, 15, 16, 17, 19, 21, 23, 26, 27, 28, 29, 32, 35, 37, 42, 44, 45, 47, 49, 50, 52, 56, 57, 59], 'conflict_call': 25}, ['max-out', 57]), ({'min_green': 5, 'gap': 4, 'max_green': 23, 'actuations': [0, 2, 4, 16, 19, 21, 22, 24, 28, 40, 44, 45, 46, 54, 55, 57, 58], 'conflict_call': None}, ['rest', 8]), ({'min_green': 5, 'gap': 3, 'max_green': 10, 'actuations': [0, 3, 6, 9, 12], 'conflict_call': 5}, ['gap-out', 15]), ({'min_green': 7, 'gap': 4, 'max_green': 21, 'actuations': [3, 6, 8, 9, 11, 12, 15, 17, 19, 21, 23, 25, 28, 33, 34, 35, 39, 47, 52, 54, 56, 58, 59], 'conflict_call': 7}, ['max-out', 28]), ({'min_green': 6, 'gap': 2, 'max_green': 12, 'actuations': [1, 3, 5, 7, 9, 11, 13], 'conflict_call': 3}, ['gap-out', 15]), ({'min_green': 4, 'gap': 4, 'max_green': 15, 'actuations': [1, 2, 4, 6, 11, 13, 15, 19, 20, 22, 23, 26, 27, 37, 41, 44, 47, 48, 50, 52, 53, 54, 56, 58, 59], 'conflict_call': 26}, ['gap-out', 26]), ({'min_green': 12, 'gap': 3, 'max_green': 5, 'actuations': [1], 'conflict_call': 2}, ['max-out', 7]), ({'min_green': 8, 'gap': 5, 'max_green': 16, 'actuations': [2, 17, 23, 41, 50, 54, 57, 59], 'conflict_call': -2}, ['gap-out', 8])], [({'min_green': 5, 'gap': 3, 'max_green': 20, 'actuations': [1, 4, 7, 10, 13], 'conflict_call': 2}, ['gap-out', 16]), ({'min_green': 6, 'gap': 2, 'max_green': 29, 'actuations': [0, 1, 2, 3, 7, 8, 9, 10, 11, 12, 16, 17, 19, 24, 27, 29, 32, 34, 36, 40, 41, 42, 43, 45, 46, 47, 48, 49, 50, 53, 56, 58, 59], 'conflict_call': -3}, ['gap-out', 6]), ({'min_green': 4, 'gap': 5, 'max_green': 22, 'actuations': [1, 2, 8, 11, 18, 20, 24, 26, 35, 37, 39, 45, 47, 50, 51, 54, 55, 56, 57, 59], 'conflict_call': 31}, ['gap-out', 31]), ({'min_green': 7, 'gap': 5, 'max_green': 42, 'actuations': [1, 3, 5, 8, 10, 29, 33, 38, 42, 44, 50, 53, 55], 'conflict_call': -5}, ['gap-out', 15]), ({'min_green': 6, 'gap': 2, 'max_green': 12, 'actuations': [1, 3, 5, 7, 9, 11, 13], 'conflict_call': 3}, ['gap-out', 15]), ({'min_green': 7, 'gap': 4, 'max_green': 34, 'actuations': [49, 44, 18, 9, 59, 20, 16, 5, 26, 24, 37, 54, 32, 3, 27, 6, 15, 53, 28, 57, 52, 47, 46, 19, 38, 51, 58, 23, 40, 30], 'conflict_call': 24}, ['gap-out', 24]), ({'min_green': 5, 'gap': 5, 'max_green': 30, 'actuations': [3, 12, 14, 28, 29, 34, 37, 42, 44, 45, 48, 52, 54, 56, 59], 'conflict_call': None}, ['rest', 8]), ({'min_green': 12, 'gap': 3, 'max_green': 5, 'actuations': [1], 'conflict_call': 2}, ['max-out', 7])], [({'min_green': 10, 'gap': 2, 'max_green': 15, 'actuations': [2, 5, 6, 8, 9, 14, 15, 17, 18, 22, 25, 26, 30, 31, 33, 36, 40, 42, 50], 'conflict_call': 6}, ['gap-out', 11]), ({'min_green': 12, 'gap': 3, 'max_green': 5, 'actuations': [1], 'conflict_call': 2}, ['max-out', 7]), ({'min_green': 4, 'gap': 5, 'max_green': 25, 'actuations': [1, 9, 10, 12, 13, 14, 15, 16, 17, 21, 24, 26, 27, 29, 30, 36, 37, 38, 41, 42, 43, 46, 47, 48, 49, 51, 53, 55, 58], 'conflict_call': 10}, ['gap-out', 10]), ({'min_green': 7, 'gap': 3, 'max_green': 15, 'actuations': [54, 34, 26, 11, 41, 56, 5], 'conflict_call': 10}, ['gap-out', 10]), ({'min_green': 5, 'gap': 3, 'max_green': 20, 'actuations': [1, 4, 7, 10, 13], 'conflict_call': 2}, ['gap-out', 16]), ({'min_green': 6, 'gap': 2, 'max_green': 12, 'actuations': [1, 3, 5, 7, 9, 11, 13], 'conflict_call': 3}, ['gap-out', 15]), ({'min_green': 4, 'gap': 3, 'max_green': 19, 'actuations': [0, 4, 7, 8, 13, 15, 17, 18, 21, 22, 23, 26, 28, 29, 30, 33, 35, 37, 41, 43, 45, 46, 47, 49, 50, 53, 56, 57], 'conflict_call': 30}, ['gap-out', 30]), ({'min_green': 4, 'gap': 3, 'max_green': 45, 'actuations': [0, 4, 5, 6, 8, 16, 17, 22, 23, 27, 31, 39, 40, 42, 45, 47, 48, 52, 54, 58], 'conflict_call': 27}, ['gap-out', 27])], [({'min_green': 4, 'gap': 2, 'max_green': 32, 'actuations': [10, 16, 21, 24, 25, 27, 30, 34, 39, 42, 49, 50, 52, 53, 56], 'conflict_call': 9}, ['gap-out', 9]), ({'min_green': 4, 'gap': 3, 'max_green': 31, 'actuations': [14, 21, 44, 47], 'conflict_call': 0}, ['gap-out', 4]), ({'min_green': 12, 'gap': 3, 'max_green': 5, 'actuations': [1], 'conflict_call': 2}, ['max-out', 7]), ({'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': 10, 'gap': 3, 'max_green': 39, 'actuations': [1, 2, 3, 4, 5, 8, 9, 11, 13, 15, 16, 17, 20, 21, 23, 29, 31, 32, 35, 36, 37, 42, 44, 45, 47, 48, 52, 55, 56, 59], 'conflict_call': 12}, ['gap-out', 26]), ({'min_green': 9, 'gap': 4, 'max_green': 29, 'actuations': [2, 4, 7, 17, 23, 25, 27, 36, 37, 45, 50], 'conflict_call': None}, ['rest', 11]), ({'min_green': 5, 'gap': 3, 'max_green': 20, 'actuations': [1, 4, 7, 10, 13], 'conflict_call': 2}, ['gap-out', 16]), ({'min_green': 8, 'gap': 2, 'max_green': 31, 'actuations': [2, 11, 12, 14, 15, 27, 37, 41, 46, 49], 'conflict_call': None}, ['rest', 8])]]
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 | ['max-out', 15] | ['max-out', 15] | Passed |
| timing oracle 1 | ['gap-out', 20] | ['gap-out', 20] | Passed |
| timing oracle 2 | ['gap-out', 9] | ['gap-out', 9] | Passed |
| timing oracle 3 | ['gap-out', 21] | ['gap-out', 21] | Passed |
| timing oracle 4 | ['gap-out', 16] | ['gap-out', 16] | Passed |
| timing oracle 5 | ['gap-out', 21] | ['gap-out', 21] | Passed |
| timing oracle 6 | ['rest', 4] | ['rest', 4] | Passed |
| timing oracle 7 | ['gap-out', 31] | ['gap-out', 31] | Passed |
SHA-256 / ad9f72e29064931bcb1159575abefe659ae3736a0793c6ecf7b48bf6a7a9a03e
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.898214+00:00.
Case digest / b76c9b1e047ca2f09773bdd56cdd2c34cc8cb14ff7ed279a717a62e9f3c62561