FA-92426 / HVAC thermostat control / Open access
Aux heat lockout applies while the compressor is locked out · case 01
Inside the compressor release band there is no heat source at all.
ROOT CAUSE
The locked-out branch also applies the aux outdoor lockout.
VERIFIED REPAIR
While the compressor is locked out, aux serves stage 1 regardless of the aux lockout.
Unsuccessful approach: Serving only stage 2 with aux while locked out under-heats on stage-1 demand.
Case contract
Heat pump with electric auxiliary heat; samples are [indoor, outdoor, mode] in tenths F. The compressor is locked out when outdoor < comp_lockout and released when outdoor >= comp_lockout + 2.0 F. Stage 1 demand is indoor < sp - 1.0 F, stage 2 is indoor < sp - 3.0 F. Emergency mode: no compressor, aux on stage-1 demand. Compressor locked out: aux replaces it on stage-1 demand regardless of the aux lockout. Otherwise the compressor serves stage 1 and aux serves stage 2 only when outdoor <= aux_lockout. Return [compressor, aux] per sample.
Why this case matters
Residential and light-commercial thermostats make these decisions sample by sample; each defect changes equipment calls in a way that shows up as short cycling, comfort complaints or equipment stress.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(settings, samples):
locked = False
out = []
for indoor, outdoor, mode in samples:
if locked and outdoor >= settings['comp_lockout'] + 20:
locked = False
elif not locked and outdoor < settings['comp_lockout']:
locked = True
stage1 = indoor < settings['sp'] - 10
stage2 = indoor < settings['sp'] - 30
if mode == 'emergency':
comp, aux = False, stage1
elif locked:
comp, aux = False, stage1 and outdoor <= settings['aux_lockout']
else:
comp = stage1
aux = stage2 and outdoor <= settings['aux_lockout']
out.append([comp, aux])
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: lockout band',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 260},
[[680, 300, 'normal'],
[660, 300, 'normal'],
[680, 240, 'normal'],
[680, 265, 'normal'],
[680, 275, 'normal'],
[680, 275, 'emergency'],
[705, 275, 'normal']]],
[[True, False],
[True, False],
[False, True],
[False, True],
[True, False],
[False, True],
[False, False]]],
['regression: scenario 7',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 400},
[[642, 176, 'emergency'],
[645, 191, 'normal'],
[708, 177, 'emergency'],
[663, 190, 'normal'],
[665, 178, 'normal'],
[672, 206, 'normal'],
[698, 200, 'normal'],
[640, 227, 'normal'],
[686, 249, 'normal'],
[686, 249, 'emergency'],
[676, 251, 'normal'],
[707, 267, 'normal']]],
[[False, True],
[False, True],
[False, False],
[False, True],
[False, True],
[False, True],
[False, False],
[False, True],
[False, True],
[False, True],
[False, True],
[False, False]]],
['control: emergency deep demand',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 260},
[[660, 300, 'emergency'], [685, 300, 'emergency'], [660, 200, 'emergency']]],
[[False, True], [False, True], [False, True]]],
['control: mild weather second stage',
[{'sp': 700, 'comp_lockout': 100, 'aux_lockout': 350},
[[660, 300, 'normal'], [660, 400, 'normal'], [685, 300, 'normal']]],
[[True, True], [True, False], [True, False]]],
['control: scenario 1',
[{'sp': 700, 'comp_lockout': 100, 'aux_lockout': 400},
[[687, 348, 'normal'],
[652, 381, 'normal'],
[674, 420, 'normal'],
[677, 440, 'normal'],
[683, 450, 'normal'],
[663, 450, 'normal'],
[653, 450, 'emergency'],
[676, 450, 'normal']]],
[[True, False],
[True, True],
[True, False],
[True, False],
[True, False],
[True, False],
[False, True],
[True, False]]],
['control: scenario 2',
[{'sp': 700, 'comp_lockout': 200, 'aux_lockout': 350},
[[699, 249, 'normal'],
[700, 272, 'normal'],
[645, 234, 'normal'],
[690, 236, 'normal'],
[673, 263, 'normal'],
[640, 258, 'normal'],
[654, 238, 'normal'],
[643, 242, 'normal'],
[684, 258, 'normal'],
[708, 254, 'normal'],
[694, 251, 'normal']]],
[[False, False],
[False, False],
[True, True],
[False, False],
[True, False],
[True, True],
[True, True],
[True, True],
[True, False],
[False, False],
[False, False]]],
['control: scenario 3',
[{'sp': 700, 'comp_lockout': 100, 'aux_lockout': 400},
[[686, 162, 'normal'],
[670, 135, 'normal'],
[670, 167, 'normal'],
[669, 193, 'normal'],
[644, 179, 'normal'],
[688, 208, 'normal'],
[667, 194, 'normal'],
[675, 157, 'emergency'],
[694, 183, 'normal']]],
[[True, False],
[True, False],
[True, False],
[True, True],
[True, True],
[True, False],
[True, True],
[False, True],
[False, False]]],
['control: scenario 4',
[{'sp': 700, 'comp_lockout': 100, 'aux_lockout': 400},
[[644, 286, 'normal'],
[705, 298, 'normal'],
[682, 281, 'emergency'],
[671, 281, 'normal'],
[648, 278, 'normal'],
[676, 245, 'normal'],
[688, 265, 'normal'],
[709, 228, 'normal'],
[660, 218, 'normal'],
[665, 244, 'normal'],
[644, 223, 'emergency']]],
[[True, True],
[False, False],
[False, True],
[True, False],
[True, True],
[True, False],
[True, False],
[False, False],
[True, True],
[True, True],
[False, True]]]],
[['regression: scenario 50',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 260},
[[699, 316, 'emergency'],
[650, 295, 'normal'],
[703, 271, 'normal'],
[667, 288, 'normal'],
[704, 326, 'normal'],
[660, 286, 'normal'],
[702, 313, 'normal'],
[702, 276, 'normal'],
[687, 254, 'normal'],
[651, 261, 'normal'],
[703, 235, 'normal'],
[651, 255, 'normal'],
[674, 261, 'normal'],
[668, 235, 'emergency']]],
[[False, False],
[True, False],
[False, False],
[True, False],
[False, False],
[True, False],
[False, False],
[False, False],
[True, False],
[True, False],
[False, False],
[False, True],
[False, True],
[False, True]]],
['regression: scenario 1',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 400},
[[678, 181, 'normal'],
[678, 142, 'normal'],
[683, 132, 'normal'],
[658, 153, 'normal'],
[693, 132, 'normal'],
[649, 113, 'normal'],
[678, 138, 'emergency'],
[696, 166, 'emergency']]],
[[False, True],
[False, True],
[False, True],
[False, True],
[False, False],
[False, True],
[False, True],
[False, False]]],
['regression: lockout band',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 260},
[[680, 300, 'normal'],
[660, 300, 'normal'],
[680, 240, 'normal'],
[680, 265, 'normal'],
[680, 275, 'normal'],
[680, 275, 'emergency'],
[705, 275, 'normal']]],
[[True, False],
[True, False],
[False, True],
[False, True],
[True, False],
[False, True],
[False, False]]],
['control: emergency deep demand',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 260},
[[660, 300, 'emergency'], [685, 300, 'emergency'], [660, 200, 'emergency']]],
[[False, True], [False, True], [False, True]]],
['control: mild weather second stage',
[{'sp': 700, 'comp_lockout': 100, 'aux_lockout': 350},
[[660, 300, 'normal'], [660, 400, 'normal'], [685, 300, 'normal']]],
[[True, True], [True, False], [True, False]]],
['regression: scenario 2',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 350},
[[697, 219, 'normal'],
[704, 237, 'normal'],
[668, 209, 'emergency'],
[683, 245, 'normal'],
[642, 277, 'normal'],
[657, 316, 'normal'],
[702, 302, 'normal'],
[678, 281, 'normal'],
[661, 253, 'normal']]],
[[False, False],
[False, False],
[False, True],
[False, True],
[True, True],
[True, True],
[False, False],
[True, False],
[True, True]]],
['control: scenario 3',
[{'sp': 700, 'comp_lockout': 200, 'aux_lockout': 260},
[[692, 278, 'normal'],
[691, 268, 'normal'],
[684, 292, 'normal'],
[688, 283, 'normal'],
[653, 265, 'normal'],
[680, 269, 'emergency'],
[707, 242, 'normal'],
[669, 239, 'emergency'],
[643, 234, 'normal'],
[651, 213, 'normal'],
[644, 185, 'normal'],
[647, 176, 'normal'],
[663, 170, 'normal']]],
[[False, False],
[False, False],
[True, False],
[True, False],
[True, False],
[False, True],
[False, False],
[False, True],
[True, True],
[True, True],
[False, True],
[False, True],
[False, True]]],
['control: scenario 4',
[{'sp': 700, 'comp_lockout': 100, 'aux_lockout': 400},
[[698, 201, 'normal'],
[643, 184, 'normal'],
[672, 162, 'normal'],
[705, 174, 'normal'],
[677, 136, 'normal'],
[672, 158, 'normal'],
[648, 177, 'emergency'],
[670, 217, 'normal'],
[654, 224, 'normal'],
[658, 203, 'normal'],
[659, 228, 'normal'],
[710, 227, 'normal']]],
[[False, False],
[True, True],
[True, False],
[False, False],
[True, False],
[True, False],
[False, True],
[True, False],
[True, True],
[True, True],
[True, True],
[False, False]]]],
[['regression: lockout band',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 260},
[[680, 300, 'normal'],
[660, 300, 'normal'],
[680, 240, 'normal'],
[680, 265, 'normal'],
[680, 275, 'normal'],
[680, 275, 'emergency'],
[705, 275, 'normal']]],
[[True, False],
[True, False],
[False, True],
[False, True],
[True, False],
[False, True],
[False, False]]],
['regression: scenario 5',
[{'sp': 700, 'comp_lockout': 200, 'aux_lockout': 400},
[[660, 230, 'emergency'],
[682, 226, 'normal'],
[678, 266, 'normal'],
[651, 246, 'normal'],
[666, 260, 'normal'],
[710, 220, 'normal'],
[691, 190, 'normal'],
[700, 168, 'emergency'],
[661, 186, 'normal'],
[665, 195, 'normal'],
[666, 222, 'normal'],
[697, 194, 'normal'],
[677, 202, 'normal']]],
[[False, True],
[True, False],
[True, False],
[True, True],
[True, True],
[False, False],
[False, False],
[False, False],
[False, True],
[False, True],
[True, True],
[False, False],
[False, True]]],
['control: emergency deep demand',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 260},
[[660, 300, 'emergency'], [685, 300, 'emergency'], [660, 200, 'emergency']]],
[[False, True], [False, True], [False, True]]],
['control: mild weather second stage',
[{'sp': 700, 'comp_lockout': 100, 'aux_lockout': 350},
[[660, 300, 'normal'], [660, 400, 'normal'], [685, 300, 'normal']]],
[[True, True], [True, False], [True, False]]],
['control: scenario 1',
[{'sp': 700, 'comp_lockout': 100, 'aux_lockout': 350},
[[656, 273, 'normal'],
[679, 265, 'normal'],
[672, 284, 'emergency'],
[690, 310, 'normal'],
[697, 308, 'normal'],
[641, 322, 'emergency'],
[679, 346, 'normal'],
[640, 329, 'normal']]],
[[True, True],
[True, False],
[False, True],
[False, False],
[False, False],
[False, True],
[True, False],
[True, True]]],
['regression: scenario 2',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 350},
[[672, 231, 'normal'],
[699, 194, 'normal'],
[704, 214, 'emergency'],
[667, 230, 'normal'],
[666, 253, 'normal'],
[654, 226, 'emergency'],
[693, 222, 'normal'],
[664, 244, 'normal'],
[687, 282, 'normal']]],
[[False, True],
[False, False],
[False, False],
[False, True],
[False, True],
[False, True],
[False, False],
[False, True],
[True, False]]],
['regression: scenario 3',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 400},
[[678, 176, 'normal'],
[691, 141, 'normal'],
[686, 110, 'normal'],
[675, 124, 'emergency'],
[703, 99, 'normal'],
[680, 101, 'normal'],
[698, 114, 'normal'],
[672, 121, 'emergency'],
[691, 83, 'normal'],
[656, 108, 'emergency'],
[692, 99, 'emergency'],
[643, 79, 'normal'],
[648, 52, 'emergency']]],
[[False, True],
[False, False],
[False, True],
[False, True],
[False, False],
[False, True],
[False, False],
[False, True],
[False, False],
[False, True],
[False, False],
[False, True],
[False, True]]],
['control: scenario 4',
[{'sp': 700, 'comp_lockout': 100, 'aux_lockout': 350},
[[704, 427, 'normal'],
[693, 433, 'normal'],
[707, 450, 'normal'],
[647, 450, 'normal'],
[704, 450, 'normal'],
[708, 450, 'normal'],
[656, 450, 'normal'],
[649, 450, 'normal'],
[705, 450, 'normal'],
[657, 450, 'emergency'],
[689, 420, 'normal']]],
[[False, False],
[False, False],
[False, False],
[True, False],
[False, False],
[False, False],
[True, False],
[True, False],
[False, False],
[False, True],
[True, False]]]],
[['regression: scenario 25',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 260},
[[640, 241, 'normal'],
[710, 246, 'normal'],
[697, 237, 'normal'],
[694, 212, 'normal'],
[681, 176, 'normal'],
[640, 213, 'normal'],
[648, 237, 'normal'],
[680, 207, 'normal'],
[683, 244, 'normal'],
[704, 255, 'normal'],
[694, 251, 'normal'],
[677, 269, 'normal'],
[686, 281, 'emergency']]],
[[False, True],
[False, False],
[False, False],
[False, False],
[False, True],
[False, True],
[False, True],
[False, True],
[False, True],
[False, False],
[False, False],
[False, True],
[False, True]]],
['regression: scenario 9',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 400},
[[642, 209, 'normal'],
[695, 214, 'normal'],
[665, 189, 'normal'],
[660, 179, 'normal'],
[640, 167, 'normal'],
[674, 129, 'normal'],
[684, 154, 'emergency'],
[691, 135, 'normal'],
[681, 142, 'normal'],
[653, 163, 'normal'],
[705, 140, 'normal'],
[685, 137, 'emergency'],
[657, 119, 'normal']]],
[[False, True],
[False, False],
[False, True],
[False, True],
[False, True],
[False, True],
[False, True],
[False, False],
[False, True],
[False, True],
[False, False],
[False, True],
[False, True]]],
['regression: lockout band',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 260},
[[680, 300, 'normal'],
[660, 300, 'normal'],
[680, 240, 'normal'],
[680, 265, 'normal'],
[680, 275, 'normal'],
[680, 275, 'emergency'],
[705, 275, 'normal']]],
[[True, False],
[True, False],
[False, True],
[False, True],
[True, False],
[False, True],
[False, False]]],
['control: emergency deep demand',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 260},
[[660, 300, 'emergency'], [685, 300, 'emergency'], [660, 200, 'emergency']]],
[[False, True], [False, True], [False, True]]],
['control: mild weather second stage',
[{'sp': 700, 'comp_lockout': 100, 'aux_lockout': 350},
[[660, 300, 'normal'], [660, 400, 'normal'], [685, 300, 'normal']]],
[[True, True], [True, False], [True, False]]],
['regression: scenario 1',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 350},
[[646, 150, 'normal'],
[640, 123, 'normal'],
[670, 110, 'normal'],
[675, 118, 'normal'],
[648, 101, 'normal'],
[649, 91, 'normal'],
[710, 74, 'normal'],
[697, 95, 'normal'],
[708, 135, 'normal'],
[649, 147, 'normal'],
[671, 109, 'normal'],
[710, 89, 'normal']]],
[[False, True],
[False, True],
[False, True],
[False, True],
[False, True],
[False, True],
[False, False],
[False, False],
[False, False],
[False, True],
[False, True],
[False, False]]],
['control: scenario 2',
[{'sp': 700, 'comp_lockout': 100, 'aux_lockout': 260},
[[658, 406, 'emergency'],
[643, 441, 'emergency'],
[654, 450, 'normal'],
[657, 450, 'normal'],
[665, 450, 'normal'],
[695, 448, 'normal'],
[697, 442, 'normal'],
[675, 450, 'normal'],
[708, 418, 'emergency'],
[709, 386, 'normal'],
[681, 419, 'normal']]],
[[False, True],
[False, True],
[True, False],
[True, False],
[True, False],
[False, False],
[False, False],
[True, False],
[False, False],
[False, False],
[True, False]]],
['control: scenario 3',
[{'sp': 700, 'comp_lockout': 200, 'aux_lockout': 350},
[[690, 409, 'emergency'],
[686, 373, 'normal'],
[681, 348, 'normal'],
[644, 353, 'normal'],
[673, 341, 'normal'],
[673, 370, 'emergency'],
[680, 331, 'normal'],
[708, 324, 'normal'],
[641, 331, 'normal'],
[660, 331, 'normal'],
[697, 361, 'normal'],
[691, 365, 'emergency'],
[667, 390, 'normal']]],
[[False, False],
[True, False],
[True, False],
[True, False],
[True, False],
[False, True],
[True, False],
[False, False],
[True, True],
[True, True],
[False, False],
[False, False],
[True, False]]]],
[['regression: lockout band',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 260},
[[680, 300, 'normal'],
[660, 300, 'normal'],
[680, 240, 'normal'],
[680, 265, 'normal'],
[680, 275, 'normal'],
[680, 275, 'emergency'],
[705, 275, 'normal']]],
[[True, False],
[True, False],
[False, True],
[False, True],
[True, False],
[False, True],
[False, False]]],
['regression: scenario 20',
[{'sp': 700, 'comp_lockout': 200, 'aux_lockout': 260},
[[689, 166, 'normal'],
[659, 127, 'normal'],
[694, 165, 'normal'],
[646, 173, 'normal'],
[661, 143, 'normal'],
[652, 163, 'normal'],
[685, 150, 'normal'],
[691, 114, 'normal'],
[683, 145, 'normal'],
[645, 137, 'emergency'],
[700, 174, 'normal'],
[661, 149, 'normal'],
[647, 156, 'normal'],
[671, 159, 'normal']]],
[[False, True],
[False, True],
[False, False],
[False, True],
[False, True],
[False, True],
[False, True],
[False, False],
[False, True],
[False, True],
[False, False],
[False, True],
[False, True],
[False, True]]],
['control: emergency deep demand',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 260},
[[660, 300, 'emergency'], [685, 300, 'emergency'], [660, 200, 'emergency']]],
[[False, True], [False, True], [False, True]]],
['control: mild weather second stage',
[{'sp': 700, 'comp_lockout': 100, 'aux_lockout': 350},
[[660, 300, 'normal'], [660, 400, 'normal'], [685, 300, 'normal']]],
[[True, True], [True, False], [True, False]]],
['regression: scenario 1',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 260},
[[678, 197, 'normal'],
[653, 218, 'normal'],
[654, 208, 'normal'],
[686, 178, 'normal'],
[675, 155, 'normal'],
[678, 163, 'normal'],
[708, 201, 'normal'],
[702, 220, 'normal'],
[697, 255, 'normal']]],
[[False, True],
[False, True],
[False, True],
[False, True],
[False, True],
[False, True],
[False, False],
[False, False],
[False, False]]],
['control: scenario 2',
[{'sp': 700, 'comp_lockout': 200, 'aux_lockout': 350},
[[696, 417, 'normal'],
[700, 441, 'normal'],
[669, 443, 'normal'],
[695, 420, 'normal'],
[699, 380, 'normal'],
[657, 360, 'emergency'],
[665, 359, 'normal'],
[646, 335, 'emergency'],
[705, 331, 'normal'],
[699, 371, 'emergency'],
[696, 334, 'emergency'],
[698, 318, 'normal']]],
[[False, False],
[False, False],
[True, False],
[False, False],
[False, False],
[False, True],
[True, False],
[False, True],
[False, False],
[False, False],
[False, False],
[False, False]]],
['control: scenario 3',
[{'sp': 700, 'comp_lockout': 100, 'aux_lockout': 350},
[[670, 296, 'normal'],
[694, 303, 'normal'],
[704, 303, 'normal'],
[692, 316, 'normal'],
[688, 277, 'normal'],
[695, 304, 'normal'],
[691, 336, 'normal'],
[648, 337, 'normal'],
[686, 313, 'normal']]],
[[True, False],
[False, False],
[False, False],
[False, False],
[True, False],
[False, False],
[False, False],
[True, True],
[True, False]]],
['control: scenario 4',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 260},
[[666, 410, 'normal'],
[706, 407, 'normal'],
[684, 447, 'normal'],
[682, 450, 'normal'],
[660, 450, 'normal'],
[664, 413, 'normal'],
[657, 443, 'normal'],
[676, 425, 'normal'],
[662, 436, 'normal'],
[666, 429, 'normal'],
[696, 429, 'normal'],
[706, 410, 'normal']]],
[[True, False],
[False, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[False, False],
[False, False]]]]]
for label, args, expected in fixtures[N-1]:
check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression: lockout band | [[True, False], [True, False], [False, True], [False, False], [True, False], [False, True], [False, False]] | [[True, False], [True, False], [False, True], [False, True], [True, False], [False, True], [False, False]] | Failed |
| regression: scenario 7 | [[False, True], [False, True], [False, False], [False, True], [False, True], [False, True], [False, False], [False, True], [False, True], [False, True], [False, True], [False, False]] | [[False, True], [False, True], [False, False], [False, True], [False, True], [False, True], [False, False], [False, True], [False, True], [False, True], [False, True], [False, False]] | Passed |
| control: emergency deep demand | [[False, True], [False, True], [False, True]] | [[False, True], [False, True], [False, True]] | Passed |
| control: mild weather second stage | [[True, True], [True, False], [True, False]] | [[True, True], [True, False], [True, False]] | Passed |
| control: scenario 1 | [[True, False], [True, True], [True, False], [True, False], [True, False], [True, False], [False, True], [True, False]] | [[True, False], [True, True], [True, False], [True, False], [True, False], [True, False], [False, True], [True, False]] | Passed |
| control: scenario 2 | [[False, False], [False, False], [True, True], [False, False], [True, False], [True, True], [True, True], [True, True], [True, False], [False, False], [False, False]] | [[False, False], [False, False], [True, True], [False, False], [True, False], [True, True], [True, True], [True, True], [True, False], [False, False], [False, False]] | Passed |
| control: scenario 3 | [[True, False], [True, False], [True, False], [True, True], [True, True], [True, False], [True, True], [False, True], [False, False]] | [[True, False], [True, False], [True, False], [True, True], [True, True], [True, False], [True, True], [False, True], [False, False]] | Passed |
| control: scenario 4 | [[True, True], [False, False], [False, True], [True, False], [True, True], [True, False], [True, False], [False, False], [True, True], [True, True], [False, True]] | [[True, True], [False, False], [False, True], [True, False], [True, True], [True, False], [True, False], [False, False], [True, True], [True, True], [False, True]] | Passed |
SHA-256 / 9b2e97c0e2e62b7fecf9f597c8c9121374837a064f40abb6e46b8d448f03b961
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(settings, samples):
locked = False
out = []
for indoor, outdoor, mode in samples:
if locked and outdoor >= settings['comp_lockout'] + 20:
locked = False
elif not locked and outdoor < settings['comp_lockout']:
locked = True
stage1 = indoor < settings['sp'] - 10
stage2 = indoor < settings['sp'] - 30
if mode == 'emergency':
comp, aux = False, stage1
elif locked:
comp, aux = False, stage2
else:
comp = stage1
aux = stage2 and outdoor <= settings['aux_lockout']
out.append([comp, aux])
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: lockout band',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 260},
[[680, 300, 'normal'],
[660, 300, 'normal'],
[680, 240, 'normal'],
[680, 265, 'normal'],
[680, 275, 'normal'],
[680, 275, 'emergency'],
[705, 275, 'normal']]],
[[True, False],
[True, False],
[False, True],
[False, True],
[True, False],
[False, True],
[False, False]]],
['regression: scenario 7',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 400},
[[642, 176, 'emergency'],
[645, 191, 'normal'],
[708, 177, 'emergency'],
[663, 190, 'normal'],
[665, 178, 'normal'],
[672, 206, 'normal'],
[698, 200, 'normal'],
[640, 227, 'normal'],
[686, 249, 'normal'],
[686, 249, 'emergency'],
[676, 251, 'normal'],
[707, 267, 'normal']]],
[[False, True],
[False, True],
[False, False],
[False, True],
[False, True],
[False, True],
[False, False],
[False, True],
[False, True],
[False, True],
[False, True],
[False, False]]],
['control: emergency deep demand',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 260},
[[660, 300, 'emergency'], [685, 300, 'emergency'], [660, 200, 'emergency']]],
[[False, True], [False, True], [False, True]]],
['control: mild weather second stage',
[{'sp': 700, 'comp_lockout': 100, 'aux_lockout': 350},
[[660, 300, 'normal'], [660, 400, 'normal'], [685, 300, 'normal']]],
[[True, True], [True, False], [True, False]]],
['control: scenario 1',
[{'sp': 700, 'comp_lockout': 100, 'aux_lockout': 400},
[[687, 348, 'normal'],
[652, 381, 'normal'],
[674, 420, 'normal'],
[677, 440, 'normal'],
[683, 450, 'normal'],
[663, 450, 'normal'],
[653, 450, 'emergency'],
[676, 450, 'normal']]],
[[True, False],
[True, True],
[True, False],
[True, False],
[True, False],
[True, False],
[False, True],
[True, False]]],
['control: scenario 2',
[{'sp': 700, 'comp_lockout': 200, 'aux_lockout': 350},
[[699, 249, 'normal'],
[700, 272, 'normal'],
[645, 234, 'normal'],
[690, 236, 'normal'],
[673, 263, 'normal'],
[640, 258, 'normal'],
[654, 238, 'normal'],
[643, 242, 'normal'],
[684, 258, 'normal'],
[708, 254, 'normal'],
[694, 251, 'normal']]],
[[False, False],
[False, False],
[True, True],
[False, False],
[True, False],
[True, True],
[True, True],
[True, True],
[True, False],
[False, False],
[False, False]]],
['control: scenario 3',
[{'sp': 700, 'comp_lockout': 100, 'aux_lockout': 400},
[[686, 162, 'normal'],
[670, 135, 'normal'],
[670, 167, 'normal'],
[669, 193, 'normal'],
[644, 179, 'normal'],
[688, 208, 'normal'],
[667, 194, 'normal'],
[675, 157, 'emergency'],
[694, 183, 'normal']]],
[[True, False],
[True, False],
[True, False],
[True, True],
[True, True],
[True, False],
[True, True],
[False, True],
[False, False]]],
['control: scenario 4',
[{'sp': 700, 'comp_lockout': 100, 'aux_lockout': 400},
[[644, 286, 'normal'],
[705, 298, 'normal'],
[682, 281, 'emergency'],
[671, 281, 'normal'],
[648, 278, 'normal'],
[676, 245, 'normal'],
[688, 265, 'normal'],
[709, 228, 'normal'],
[660, 218, 'normal'],
[665, 244, 'normal'],
[644, 223, 'emergency']]],
[[True, True],
[False, False],
[False, True],
[True, False],
[True, True],
[True, False],
[True, False],
[False, False],
[True, True],
[True, True],
[False, True]]]],
[['regression: scenario 50',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 260},
[[699, 316, 'emergency'],
[650, 295, 'normal'],
[703, 271, 'normal'],
[667, 288, 'normal'],
[704, 326, 'normal'],
[660, 286, 'normal'],
[702, 313, 'normal'],
[702, 276, 'normal'],
[687, 254, 'normal'],
[651, 261, 'normal'],
[703, 235, 'normal'],
[651, 255, 'normal'],
[674, 261, 'normal'],
[668, 235, 'emergency']]],
[[False, False],
[True, False],
[False, False],
[True, False],
[False, False],
[True, False],
[False, False],
[False, False],
[True, False],
[True, False],
[False, False],
[False, True],
[False, True],
[False, True]]],
['regression: scenario 1',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 400},
[[678, 181, 'normal'],
[678, 142, 'normal'],
[683, 132, 'normal'],
[658, 153, 'normal'],
[693, 132, 'normal'],
[649, 113, 'normal'],
[678, 138, 'emergency'],
[696, 166, 'emergency']]],
[[False, True],
[False, True],
[False, True],
[False, True],
[False, False],
[False, True],
[False, True],
[False, False]]],
['regression: lockout band',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 260},
[[680, 300, 'normal'],
[660, 300, 'normal'],
[680, 240, 'normal'],
[680, 265, 'normal'],
[680, 275, 'normal'],
[680, 275, 'emergency'],
[705, 275, 'normal']]],
[[True, False],
[True, False],
[False, True],
[False, True],
[True, False],
[False, True],
[False, False]]],
['control: emergency deep demand',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 260},
[[660, 300, 'emergency'], [685, 300, 'emergency'], [660, 200, 'emergency']]],
[[False, True], [False, True], [False, True]]],
['control: mild weather second stage',
[{'sp': 700, 'comp_lockout': 100, 'aux_lockout': 350},
[[660, 300, 'normal'], [660, 400, 'normal'], [685, 300, 'normal']]],
[[True, True], [True, False], [True, False]]],
['regression: scenario 2',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 350},
[[697, 219, 'normal'],
[704, 237, 'normal'],
[668, 209, 'emergency'],
[683, 245, 'normal'],
[642, 277, 'normal'],
[657, 316, 'normal'],
[702, 302, 'normal'],
[678, 281, 'normal'],
[661, 253, 'normal']]],
[[False, False],
[False, False],
[False, True],
[False, True],
[True, True],
[True, True],
[False, False],
[True, False],
[True, True]]],
['control: scenario 3',
[{'sp': 700, 'comp_lockout': 200, 'aux_lockout': 260},
[[692, 278, 'normal'],
[691, 268, 'normal'],
[684, 292, 'normal'],
[688, 283, 'normal'],
[653, 265, 'normal'],
[680, 269, 'emergency'],
[707, 242, 'normal'],
[669, 239, 'emergency'],
[643, 234, 'normal'],
[651, 213, 'normal'],
[644, 185, 'normal'],
[647, 176, 'normal'],
[663, 170, 'normal']]],
[[False, False],
[False, False],
[True, False],
[True, False],
[True, False],
[False, True],
[False, False],
[False, True],
[True, True],
[True, True],
[False, True],
[False, True],
[False, True]]],
['control: scenario 4',
[{'sp': 700, 'comp_lockout': 100, 'aux_lockout': 400},
[[698, 201, 'normal'],
[643, 184, 'normal'],
[672, 162, 'normal'],
[705, 174, 'normal'],
[677, 136, 'normal'],
[672, 158, 'normal'],
[648, 177, 'emergency'],
[670, 217, 'normal'],
[654, 224, 'normal'],
[658, 203, 'normal'],
[659, 228, 'normal'],
[710, 227, 'normal']]],
[[False, False],
[True, True],
[True, False],
[False, False],
[True, False],
[True, False],
[False, True],
[True, False],
[True, True],
[True, True],
[True, True],
[False, False]]]],
[['regression: lockout band',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 260},
[[680, 300, 'normal'],
[660, 300, 'normal'],
[680, 240, 'normal'],
[680, 265, 'normal'],
[680, 275, 'normal'],
[680, 275, 'emergency'],
[705, 275, 'normal']]],
[[True, False],
[True, False],
[False, True],
[False, True],
[True, False],
[False, True],
[False, False]]],
['regression: scenario 5',
[{'sp': 700, 'comp_lockout': 200, 'aux_lockout': 400},
[[660, 230, 'emergency'],
[682, 226, 'normal'],
[678, 266, 'normal'],
[651, 246, 'normal'],
[666, 260, 'normal'],
[710, 220, 'normal'],
[691, 190, 'normal'],
[700, 168, 'emergency'],
[661, 186, 'normal'],
[665, 195, 'normal'],
[666, 222, 'normal'],
[697, 194, 'normal'],
[677, 202, 'normal']]],
[[False, True],
[True, False],
[True, False],
[True, True],
[True, True],
[False, False],
[False, False],
[False, False],
[False, True],
[False, True],
[True, True],
[False, False],
[False, True]]],
['control: emergency deep demand',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 260},
[[660, 300, 'emergency'], [685, 300, 'emergency'], [660, 200, 'emergency']]],
[[False, True], [False, True], [False, True]]],
['control: mild weather second stage',
[{'sp': 700, 'comp_lockout': 100, 'aux_lockout': 350},
[[660, 300, 'normal'], [660, 400, 'normal'], [685, 300, 'normal']]],
[[True, True], [True, False], [True, False]]],
['control: scenario 1',
[{'sp': 700, 'comp_lockout': 100, 'aux_lockout': 350},
[[656, 273, 'normal'],
[679, 265, 'normal'],
[672, 284, 'emergency'],
[690, 310, 'normal'],
[697, 308, 'normal'],
[641, 322, 'emergency'],
[679, 346, 'normal'],
[640, 329, 'normal']]],
[[True, True],
[True, False],
[False, True],
[False, False],
[False, False],
[False, True],
[True, False],
[True, True]]],
['regression: scenario 2',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 350},
[[672, 231, 'normal'],
[699, 194, 'normal'],
[704, 214, 'emergency'],
[667, 230, 'normal'],
[666, 253, 'normal'],
[654, 226, 'emergency'],
[693, 222, 'normal'],
[664, 244, 'normal'],
[687, 282, 'normal']]],
[[False, True],
[False, False],
[False, False],
[False, True],
[False, True],
[False, True],
[False, False],
[False, True],
[True, False]]],
['regression: scenario 3',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 400},
[[678, 176, 'normal'],
[691, 141, 'normal'],
[686, 110, 'normal'],
[675, 124, 'emergency'],
[703, 99, 'normal'],
[680, 101, 'normal'],
[698, 114, 'normal'],
[672, 121, 'emergency'],
[691, 83, 'normal'],
[656, 108, 'emergency'],
[692, 99, 'emergency'],
[643, 79, 'normal'],
[648, 52, 'emergency']]],
[[False, True],
[False, False],
[False, True],
[False, True],
[False, False],
[False, True],
[False, False],
[False, True],
[False, False],
[False, True],
[False, False],
[False, True],
[False, True]]],
['control: scenario 4',
[{'sp': 700, 'comp_lockout': 100, 'aux_lockout': 350},
[[704, 427, 'normal'],
[693, 433, 'normal'],
[707, 450, 'normal'],
[647, 450, 'normal'],
[704, 450, 'normal'],
[708, 450, 'normal'],
[656, 450, 'normal'],
[649, 450, 'normal'],
[705, 450, 'normal'],
[657, 450, 'emergency'],
[689, 420, 'normal']]],
[[False, False],
[False, False],
[False, False],
[True, False],
[False, False],
[False, False],
[True, False],
[True, False],
[False, False],
[False, True],
[True, False]]]],
[['regression: scenario 25',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 260},
[[640, 241, 'normal'],
[710, 246, 'normal'],
[697, 237, 'normal'],
[694, 212, 'normal'],
[681, 176, 'normal'],
[640, 213, 'normal'],
[648, 237, 'normal'],
[680, 207, 'normal'],
[683, 244, 'normal'],
[704, 255, 'normal'],
[694, 251, 'normal'],
[677, 269, 'normal'],
[686, 281, 'emergency']]],
[[False, True],
[False, False],
[False, False],
[False, False],
[False, True],
[False, True],
[False, True],
[False, True],
[False, True],
[False, False],
[False, False],
[False, True],
[False, True]]],
['regression: scenario 9',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 400},
[[642, 209, 'normal'],
[695, 214, 'normal'],
[665, 189, 'normal'],
[660, 179, 'normal'],
[640, 167, 'normal'],
[674, 129, 'normal'],
[684, 154, 'emergency'],
[691, 135, 'normal'],
[681, 142, 'normal'],
[653, 163, 'normal'],
[705, 140, 'normal'],
[685, 137, 'emergency'],
[657, 119, 'normal']]],
[[False, True],
[False, False],
[False, True],
[False, True],
[False, True],
[False, True],
[False, True],
[False, False],
[False, True],
[False, True],
[False, False],
[False, True],
[False, True]]],
['regression: lockout band',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 260},
[[680, 300, 'normal'],
[660, 300, 'normal'],
[680, 240, 'normal'],
[680, 265, 'normal'],
[680, 275, 'normal'],
[680, 275, 'emergency'],
[705, 275, 'normal']]],
[[True, False],
[True, False],
[False, True],
[False, True],
[True, False],
[False, True],
[False, False]]],
['control: emergency deep demand',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 260},
[[660, 300, 'emergency'], [685, 300, 'emergency'], [660, 200, 'emergency']]],
[[False, True], [False, True], [False, True]]],
['control: mild weather second stage',
[{'sp': 700, 'comp_lockout': 100, 'aux_lockout': 350},
[[660, 300, 'normal'], [660, 400, 'normal'], [685, 300, 'normal']]],
[[True, True], [True, False], [True, False]]],
['regression: scenario 1',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 350},
[[646, 150, 'normal'],
[640, 123, 'normal'],
[670, 110, 'normal'],
[675, 118, 'normal'],
[648, 101, 'normal'],
[649, 91, 'normal'],
[710, 74, 'normal'],
[697, 95, 'normal'],
[708, 135, 'normal'],
[649, 147, 'normal'],
[671, 109, 'normal'],
[710, 89, 'normal']]],
[[False, True],
[False, True],
[False, True],
[False, True],
[False, True],
[False, True],
[False, False],
[False, False],
[False, False],
[False, True],
[False, True],
[False, False]]],
['control: scenario 2',
[{'sp': 700, 'comp_lockout': 100, 'aux_lockout': 260},
[[658, 406, 'emergency'],
[643, 441, 'emergency'],
[654, 450, 'normal'],
[657, 450, 'normal'],
[665, 450, 'normal'],
[695, 448, 'normal'],
[697, 442, 'normal'],
[675, 450, 'normal'],
[708, 418, 'emergency'],
[709, 386, 'normal'],
[681, 419, 'normal']]],
[[False, True],
[False, True],
[True, False],
[True, False],
[True, False],
[False, False],
[False, False],
[True, False],
[False, False],
[False, False],
[True, False]]],
['control: scenario 3',
[{'sp': 700, 'comp_lockout': 200, 'aux_lockout': 350},
[[690, 409, 'emergency'],
[686, 373, 'normal'],
[681, 348, 'normal'],
[644, 353, 'normal'],
[673, 341, 'normal'],
[673, 370, 'emergency'],
[680, 331, 'normal'],
[708, 324, 'normal'],
[641, 331, 'normal'],
[660, 331, 'normal'],
[697, 361, 'normal'],
[691, 365, 'emergency'],
[667, 390, 'normal']]],
[[False, False],
[True, False],
[True, False],
[True, False],
[True, False],
[False, True],
[True, False],
[False, False],
[True, True],
[True, True],
[False, False],
[False, False],
[True, False]]]],
[['regression: lockout band',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 260},
[[680, 300, 'normal'],
[660, 300, 'normal'],
[680, 240, 'normal'],
[680, 265, 'normal'],
[680, 275, 'normal'],
[680, 275, 'emergency'],
[705, 275, 'normal']]],
[[True, False],
[True, False],
[False, True],
[False, True],
[True, False],
[False, True],
[False, False]]],
['regression: scenario 20',
[{'sp': 700, 'comp_lockout': 200, 'aux_lockout': 260},
[[689, 166, 'normal'],
[659, 127, 'normal'],
[694, 165, 'normal'],
[646, 173, 'normal'],
[661, 143, 'normal'],
[652, 163, 'normal'],
[685, 150, 'normal'],
[691, 114, 'normal'],
[683, 145, 'normal'],
[645, 137, 'emergency'],
[700, 174, 'normal'],
[661, 149, 'normal'],
[647, 156, 'normal'],
[671, 159, 'normal']]],
[[False, True],
[False, True],
[False, False],
[False, True],
[False, True],
[False, True],
[False, True],
[False, False],
[False, True],
[False, True],
[False, False],
[False, True],
[False, True],
[False, True]]],
['control: emergency deep demand',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 260},
[[660, 300, 'emergency'], [685, 300, 'emergency'], [660, 200, 'emergency']]],
[[False, True], [False, True], [False, True]]],
['control: mild weather second stage',
[{'sp': 700, 'comp_lockout': 100, 'aux_lockout': 350},
[[660, 300, 'normal'], [660, 400, 'normal'], [685, 300, 'normal']]],
[[True, True], [True, False], [True, False]]],
['regression: scenario 1',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 260},
[[678, 197, 'normal'],
[653, 218, 'normal'],
[654, 208, 'normal'],
[686, 178, 'normal'],
[675, 155, 'normal'],
[678, 163, 'normal'],
[708, 201, 'normal'],
[702, 220, 'normal'],
[697, 255, 'normal']]],
[[False, True],
[False, True],
[False, True],
[False, True],
[False, True],
[False, True],
[False, False],
[False, False],
[False, False]]],
['control: scenario 2',
[{'sp': 700, 'comp_lockout': 200, 'aux_lockout': 350},
[[696, 417, 'normal'],
[700, 441, 'normal'],
[669, 443, 'normal'],
[695, 420, 'normal'],
[699, 380, 'normal'],
[657, 360, 'emergency'],
[665, 359, 'normal'],
[646, 335, 'emergency'],
[705, 331, 'normal'],
[699, 371, 'emergency'],
[696, 334, 'emergency'],
[698, 318, 'normal']]],
[[False, False],
[False, False],
[True, False],
[False, False],
[False, False],
[False, True],
[True, False],
[False, True],
[False, False],
[False, False],
[False, False],
[False, False]]],
['control: scenario 3',
[{'sp': 700, 'comp_lockout': 100, 'aux_lockout': 350},
[[670, 296, 'normal'],
[694, 303, 'normal'],
[704, 303, 'normal'],
[692, 316, 'normal'],
[688, 277, 'normal'],
[695, 304, 'normal'],
[691, 336, 'normal'],
[648, 337, 'normal'],
[686, 313, 'normal']]],
[[True, False],
[False, False],
[False, False],
[False, False],
[True, False],
[False, False],
[False, False],
[True, True],
[True, False]]],
['control: scenario 4',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 260},
[[666, 410, 'normal'],
[706, 407, 'normal'],
[684, 447, 'normal'],
[682, 450, 'normal'],
[660, 450, 'normal'],
[664, 413, 'normal'],
[657, 443, 'normal'],
[676, 425, 'normal'],
[662, 436, 'normal'],
[666, 429, 'normal'],
[696, 429, 'normal'],
[706, 410, 'normal']]],
[[True, False],
[False, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[False, False],
[False, False]]]]]
for label, args, expected in fixtures[N-1]:
check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression: lockout band | [[True, False], [True, False], [False, False], [False, False], [True, False], [False, True], [False, False]] | [[True, False], [True, False], [False, True], [False, True], [True, False], [False, True], [False, False]] | Failed |
| regression: scenario 7 | [[False, True], [False, True], [False, False], [False, True], [False, True], [False, False], [False, False], [False, True], [False, False], [False, True], [False, False], [False, False]] | [[False, True], [False, True], [False, False], [False, True], [False, True], [False, True], [False, False], [False, True], [False, True], [False, True], [False, True], [False, False]] | Failed |
| control: emergency deep demand | [[False, True], [False, True], [False, True]] | [[False, True], [False, True], [False, True]] | Passed |
| control: mild weather second stage | [[True, True], [True, False], [True, False]] | [[True, True], [True, False], [True, False]] | Passed |
| control: scenario 1 | [[True, False], [True, True], [True, False], [True, False], [True, False], [True, False], [False, True], [True, False]] | [[True, False], [True, True], [True, False], [True, False], [True, False], [True, False], [False, True], [True, False]] | Passed |
| control: scenario 2 | [[False, False], [False, False], [True, True], [False, False], [True, False], [True, True], [True, True], [True, True], [True, False], [False, False], [False, False]] | [[False, False], [False, False], [True, True], [False, False], [True, False], [True, True], [True, True], [True, True], [True, False], [False, False], [False, False]] | Passed |
| control: scenario 3 | [[True, False], [True, False], [True, False], [True, True], [True, True], [True, False], [True, True], [False, True], [False, False]] | [[True, False], [True, False], [True, False], [True, True], [True, True], [True, False], [True, True], [False, True], [False, False]] | Passed |
| control: scenario 4 | [[True, True], [False, False], [False, True], [True, False], [True, True], [True, False], [True, False], [False, False], [True, True], [True, True], [False, True]] | [[True, True], [False, False], [False, True], [True, False], [True, True], [True, False], [True, False], [False, False], [True, True], [True, True], [False, True]] | Passed |
SHA-256 / 74e8b5beacd3e95d5dab536ed985cc4d80e1b5227bf65155a3b42aa9e39ff888
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(settings, samples):
locked = False
out = []
for indoor, outdoor, mode in samples:
if locked and outdoor >= settings['comp_lockout'] + 20:
locked = False
elif not locked and outdoor < settings['comp_lockout']:
locked = True
stage1 = indoor < settings['sp'] - 10
stage2 = indoor < settings['sp'] - 30
if mode == 'emergency':
comp, aux = False, stage1
elif locked:
comp, aux = False, stage1
else:
comp = stage1
aux = stage2 and outdoor <= settings['aux_lockout']
out.append([comp, aux])
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: lockout band',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 260},
[[680, 300, 'normal'],
[660, 300, 'normal'],
[680, 240, 'normal'],
[680, 265, 'normal'],
[680, 275, 'normal'],
[680, 275, 'emergency'],
[705, 275, 'normal']]],
[[True, False],
[True, False],
[False, True],
[False, True],
[True, False],
[False, True],
[False, False]]],
['regression: scenario 7',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 400},
[[642, 176, 'emergency'],
[645, 191, 'normal'],
[708, 177, 'emergency'],
[663, 190, 'normal'],
[665, 178, 'normal'],
[672, 206, 'normal'],
[698, 200, 'normal'],
[640, 227, 'normal'],
[686, 249, 'normal'],
[686, 249, 'emergency'],
[676, 251, 'normal'],
[707, 267, 'normal']]],
[[False, True],
[False, True],
[False, False],
[False, True],
[False, True],
[False, True],
[False, False],
[False, True],
[False, True],
[False, True],
[False, True],
[False, False]]],
['control: emergency deep demand',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 260},
[[660, 300, 'emergency'], [685, 300, 'emergency'], [660, 200, 'emergency']]],
[[False, True], [False, True], [False, True]]],
['control: mild weather second stage',
[{'sp': 700, 'comp_lockout': 100, 'aux_lockout': 350},
[[660, 300, 'normal'], [660, 400, 'normal'], [685, 300, 'normal']]],
[[True, True], [True, False], [True, False]]],
['control: scenario 1',
[{'sp': 700, 'comp_lockout': 100, 'aux_lockout': 400},
[[687, 348, 'normal'],
[652, 381, 'normal'],
[674, 420, 'normal'],
[677, 440, 'normal'],
[683, 450, 'normal'],
[663, 450, 'normal'],
[653, 450, 'emergency'],
[676, 450, 'normal']]],
[[True, False],
[True, True],
[True, False],
[True, False],
[True, False],
[True, False],
[False, True],
[True, False]]],
['control: scenario 2',
[{'sp': 700, 'comp_lockout': 200, 'aux_lockout': 350},
[[699, 249, 'normal'],
[700, 272, 'normal'],
[645, 234, 'normal'],
[690, 236, 'normal'],
[673, 263, 'normal'],
[640, 258, 'normal'],
[654, 238, 'normal'],
[643, 242, 'normal'],
[684, 258, 'normal'],
[708, 254, 'normal'],
[694, 251, 'normal']]],
[[False, False],
[False, False],
[True, True],
[False, False],
[True, False],
[True, True],
[True, True],
[True, True],
[True, False],
[False, False],
[False, False]]],
['control: scenario 3',
[{'sp': 700, 'comp_lockout': 100, 'aux_lockout': 400},
[[686, 162, 'normal'],
[670, 135, 'normal'],
[670, 167, 'normal'],
[669, 193, 'normal'],
[644, 179, 'normal'],
[688, 208, 'normal'],
[667, 194, 'normal'],
[675, 157, 'emergency'],
[694, 183, 'normal']]],
[[True, False],
[True, False],
[True, False],
[True, True],
[True, True],
[True, False],
[True, True],
[False, True],
[False, False]]],
['control: scenario 4',
[{'sp': 700, 'comp_lockout': 100, 'aux_lockout': 400},
[[644, 286, 'normal'],
[705, 298, 'normal'],
[682, 281, 'emergency'],
[671, 281, 'normal'],
[648, 278, 'normal'],
[676, 245, 'normal'],
[688, 265, 'normal'],
[709, 228, 'normal'],
[660, 218, 'normal'],
[665, 244, 'normal'],
[644, 223, 'emergency']]],
[[True, True],
[False, False],
[False, True],
[True, False],
[True, True],
[True, False],
[True, False],
[False, False],
[True, True],
[True, True],
[False, True]]]],
[['regression: scenario 50',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 260},
[[699, 316, 'emergency'],
[650, 295, 'normal'],
[703, 271, 'normal'],
[667, 288, 'normal'],
[704, 326, 'normal'],
[660, 286, 'normal'],
[702, 313, 'normal'],
[702, 276, 'normal'],
[687, 254, 'normal'],
[651, 261, 'normal'],
[703, 235, 'normal'],
[651, 255, 'normal'],
[674, 261, 'normal'],
[668, 235, 'emergency']]],
[[False, False],
[True, False],
[False, False],
[True, False],
[False, False],
[True, False],
[False, False],
[False, False],
[True, False],
[True, False],
[False, False],
[False, True],
[False, True],
[False, True]]],
['regression: scenario 1',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 400},
[[678, 181, 'normal'],
[678, 142, 'normal'],
[683, 132, 'normal'],
[658, 153, 'normal'],
[693, 132, 'normal'],
[649, 113, 'normal'],
[678, 138, 'emergency'],
[696, 166, 'emergency']]],
[[False, True],
[False, True],
[False, True],
[False, True],
[False, False],
[False, True],
[False, True],
[False, False]]],
['regression: lockout band',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 260},
[[680, 300, 'normal'],
[660, 300, 'normal'],
[680, 240, 'normal'],
[680, 265, 'normal'],
[680, 275, 'normal'],
[680, 275, 'emergency'],
[705, 275, 'normal']]],
[[True, False],
[True, False],
[False, True],
[False, True],
[True, False],
[False, True],
[False, False]]],
['control: emergency deep demand',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 260},
[[660, 300, 'emergency'], [685, 300, 'emergency'], [660, 200, 'emergency']]],
[[False, True], [False, True], [False, True]]],
['control: mild weather second stage',
[{'sp': 700, 'comp_lockout': 100, 'aux_lockout': 350},
[[660, 300, 'normal'], [660, 400, 'normal'], [685, 300, 'normal']]],
[[True, True], [True, False], [True, False]]],
['regression: scenario 2',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 350},
[[697, 219, 'normal'],
[704, 237, 'normal'],
[668, 209, 'emergency'],
[683, 245, 'normal'],
[642, 277, 'normal'],
[657, 316, 'normal'],
[702, 302, 'normal'],
[678, 281, 'normal'],
[661, 253, 'normal']]],
[[False, False],
[False, False],
[False, True],
[False, True],
[True, True],
[True, True],
[False, False],
[True, False],
[True, True]]],
['control: scenario 3',
[{'sp': 700, 'comp_lockout': 200, 'aux_lockout': 260},
[[692, 278, 'normal'],
[691, 268, 'normal'],
[684, 292, 'normal'],
[688, 283, 'normal'],
[653, 265, 'normal'],
[680, 269, 'emergency'],
[707, 242, 'normal'],
[669, 239, 'emergency'],
[643, 234, 'normal'],
[651, 213, 'normal'],
[644, 185, 'normal'],
[647, 176, 'normal'],
[663, 170, 'normal']]],
[[False, False],
[False, False],
[True, False],
[True, False],
[True, False],
[False, True],
[False, False],
[False, True],
[True, True],
[True, True],
[False, True],
[False, True],
[False, True]]],
['control: scenario 4',
[{'sp': 700, 'comp_lockout': 100, 'aux_lockout': 400},
[[698, 201, 'normal'],
[643, 184, 'normal'],
[672, 162, 'normal'],
[705, 174, 'normal'],
[677, 136, 'normal'],
[672, 158, 'normal'],
[648, 177, 'emergency'],
[670, 217, 'normal'],
[654, 224, 'normal'],
[658, 203, 'normal'],
[659, 228, 'normal'],
[710, 227, 'normal']]],
[[False, False],
[True, True],
[True, False],
[False, False],
[True, False],
[True, False],
[False, True],
[True, False],
[True, True],
[True, True],
[True, True],
[False, False]]]],
[['regression: lockout band',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 260},
[[680, 300, 'normal'],
[660, 300, 'normal'],
[680, 240, 'normal'],
[680, 265, 'normal'],
[680, 275, 'normal'],
[680, 275, 'emergency'],
[705, 275, 'normal']]],
[[True, False],
[True, False],
[False, True],
[False, True],
[True, False],
[False, True],
[False, False]]],
['regression: scenario 5',
[{'sp': 700, 'comp_lockout': 200, 'aux_lockout': 400},
[[660, 230, 'emergency'],
[682, 226, 'normal'],
[678, 266, 'normal'],
[651, 246, 'normal'],
[666, 260, 'normal'],
[710, 220, 'normal'],
[691, 190, 'normal'],
[700, 168, 'emergency'],
[661, 186, 'normal'],
[665, 195, 'normal'],
[666, 222, 'normal'],
[697, 194, 'normal'],
[677, 202, 'normal']]],
[[False, True],
[True, False],
[True, False],
[True, True],
[True, True],
[False, False],
[False, False],
[False, False],
[False, True],
[False, True],
[True, True],
[False, False],
[False, True]]],
['control: emergency deep demand',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 260},
[[660, 300, 'emergency'], [685, 300, 'emergency'], [660, 200, 'emergency']]],
[[False, True], [False, True], [False, True]]],
['control: mild weather second stage',
[{'sp': 700, 'comp_lockout': 100, 'aux_lockout': 350},
[[660, 300, 'normal'], [660, 400, 'normal'], [685, 300, 'normal']]],
[[True, True], [True, False], [True, False]]],
['control: scenario 1',
[{'sp': 700, 'comp_lockout': 100, 'aux_lockout': 350},
[[656, 273, 'normal'],
[679, 265, 'normal'],
[672, 284, 'emergency'],
[690, 310, 'normal'],
[697, 308, 'normal'],
[641, 322, 'emergency'],
[679, 346, 'normal'],
[640, 329, 'normal']]],
[[True, True],
[True, False],
[False, True],
[False, False],
[False, False],
[False, True],
[True, False],
[True, True]]],
['regression: scenario 2',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 350},
[[672, 231, 'normal'],
[699, 194, 'normal'],
[704, 214, 'emergency'],
[667, 230, 'normal'],
[666, 253, 'normal'],
[654, 226, 'emergency'],
[693, 222, 'normal'],
[664, 244, 'normal'],
[687, 282, 'normal']]],
[[False, True],
[False, False],
[False, False],
[False, True],
[False, True],
[False, True],
[False, False],
[False, True],
[True, False]]],
['regression: scenario 3',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 400},
[[678, 176, 'normal'],
[691, 141, 'normal'],
[686, 110, 'normal'],
[675, 124, 'emergency'],
[703, 99, 'normal'],
[680, 101, 'normal'],
[698, 114, 'normal'],
[672, 121, 'emergency'],
[691, 83, 'normal'],
[656, 108, 'emergency'],
[692, 99, 'emergency'],
[643, 79, 'normal'],
[648, 52, 'emergency']]],
[[False, True],
[False, False],
[False, True],
[False, True],
[False, False],
[False, True],
[False, False],
[False, True],
[False, False],
[False, True],
[False, False],
[False, True],
[False, True]]],
['control: scenario 4',
[{'sp': 700, 'comp_lockout': 100, 'aux_lockout': 350},
[[704, 427, 'normal'],
[693, 433, 'normal'],
[707, 450, 'normal'],
[647, 450, 'normal'],
[704, 450, 'normal'],
[708, 450, 'normal'],
[656, 450, 'normal'],
[649, 450, 'normal'],
[705, 450, 'normal'],
[657, 450, 'emergency'],
[689, 420, 'normal']]],
[[False, False],
[False, False],
[False, False],
[True, False],
[False, False],
[False, False],
[True, False],
[True, False],
[False, False],
[False, True],
[True, False]]]],
[['regression: scenario 25',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 260},
[[640, 241, 'normal'],
[710, 246, 'normal'],
[697, 237, 'normal'],
[694, 212, 'normal'],
[681, 176, 'normal'],
[640, 213, 'normal'],
[648, 237, 'normal'],
[680, 207, 'normal'],
[683, 244, 'normal'],
[704, 255, 'normal'],
[694, 251, 'normal'],
[677, 269, 'normal'],
[686, 281, 'emergency']]],
[[False, True],
[False, False],
[False, False],
[False, False],
[False, True],
[False, True],
[False, True],
[False, True],
[False, True],
[False, False],
[False, False],
[False, True],
[False, True]]],
['regression: scenario 9',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 400},
[[642, 209, 'normal'],
[695, 214, 'normal'],
[665, 189, 'normal'],
[660, 179, 'normal'],
[640, 167, 'normal'],
[674, 129, 'normal'],
[684, 154, 'emergency'],
[691, 135, 'normal'],
[681, 142, 'normal'],
[653, 163, 'normal'],
[705, 140, 'normal'],
[685, 137, 'emergency'],
[657, 119, 'normal']]],
[[False, True],
[False, False],
[False, True],
[False, True],
[False, True],
[False, True],
[False, True],
[False, False],
[False, True],
[False, True],
[False, False],
[False, True],
[False, True]]],
['regression: lockout band',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 260},
[[680, 300, 'normal'],
[660, 300, 'normal'],
[680, 240, 'normal'],
[680, 265, 'normal'],
[680, 275, 'normal'],
[680, 275, 'emergency'],
[705, 275, 'normal']]],
[[True, False],
[True, False],
[False, True],
[False, True],
[True, False],
[False, True],
[False, False]]],
['control: emergency deep demand',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 260},
[[660, 300, 'emergency'], [685, 300, 'emergency'], [660, 200, 'emergency']]],
[[False, True], [False, True], [False, True]]],
['control: mild weather second stage',
[{'sp': 700, 'comp_lockout': 100, 'aux_lockout': 350},
[[660, 300, 'normal'], [660, 400, 'normal'], [685, 300, 'normal']]],
[[True, True], [True, False], [True, False]]],
['regression: scenario 1',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 350},
[[646, 150, 'normal'],
[640, 123, 'normal'],
[670, 110, 'normal'],
[675, 118, 'normal'],
[648, 101, 'normal'],
[649, 91, 'normal'],
[710, 74, 'normal'],
[697, 95, 'normal'],
[708, 135, 'normal'],
[649, 147, 'normal'],
[671, 109, 'normal'],
[710, 89, 'normal']]],
[[False, True],
[False, True],
[False, True],
[False, True],
[False, True],
[False, True],
[False, False],
[False, False],
[False, False],
[False, True],
[False, True],
[False, False]]],
['control: scenario 2',
[{'sp': 700, 'comp_lockout': 100, 'aux_lockout': 260},
[[658, 406, 'emergency'],
[643, 441, 'emergency'],
[654, 450, 'normal'],
[657, 450, 'normal'],
[665, 450, 'normal'],
[695, 448, 'normal'],
[697, 442, 'normal'],
[675, 450, 'normal'],
[708, 418, 'emergency'],
[709, 386, 'normal'],
[681, 419, 'normal']]],
[[False, True],
[False, True],
[True, False],
[True, False],
[True, False],
[False, False],
[False, False],
[True, False],
[False, False],
[False, False],
[True, False]]],
['control: scenario 3',
[{'sp': 700, 'comp_lockout': 200, 'aux_lockout': 350},
[[690, 409, 'emergency'],
[686, 373, 'normal'],
[681, 348, 'normal'],
[644, 353, 'normal'],
[673, 341, 'normal'],
[673, 370, 'emergency'],
[680, 331, 'normal'],
[708, 324, 'normal'],
[641, 331, 'normal'],
[660, 331, 'normal'],
[697, 361, 'normal'],
[691, 365, 'emergency'],
[667, 390, 'normal']]],
[[False, False],
[True, False],
[True, False],
[True, False],
[True, False],
[False, True],
[True, False],
[False, False],
[True, True],
[True, True],
[False, False],
[False, False],
[True, False]]]],
[['regression: lockout band',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 260},
[[680, 300, 'normal'],
[660, 300, 'normal'],
[680, 240, 'normal'],
[680, 265, 'normal'],
[680, 275, 'normal'],
[680, 275, 'emergency'],
[705, 275, 'normal']]],
[[True, False],
[True, False],
[False, True],
[False, True],
[True, False],
[False, True],
[False, False]]],
['regression: scenario 20',
[{'sp': 700, 'comp_lockout': 200, 'aux_lockout': 260},
[[689, 166, 'normal'],
[659, 127, 'normal'],
[694, 165, 'normal'],
[646, 173, 'normal'],
[661, 143, 'normal'],
[652, 163, 'normal'],
[685, 150, 'normal'],
[691, 114, 'normal'],
[683, 145, 'normal'],
[645, 137, 'emergency'],
[700, 174, 'normal'],
[661, 149, 'normal'],
[647, 156, 'normal'],
[671, 159, 'normal']]],
[[False, True],
[False, True],
[False, False],
[False, True],
[False, True],
[False, True],
[False, True],
[False, False],
[False, True],
[False, True],
[False, False],
[False, True],
[False, True],
[False, True]]],
['control: emergency deep demand',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 260},
[[660, 300, 'emergency'], [685, 300, 'emergency'], [660, 200, 'emergency']]],
[[False, True], [False, True], [False, True]]],
['control: mild weather second stage',
[{'sp': 700, 'comp_lockout': 100, 'aux_lockout': 350},
[[660, 300, 'normal'], [660, 400, 'normal'], [685, 300, 'normal']]],
[[True, True], [True, False], [True, False]]],
['regression: scenario 1',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 260},
[[678, 197, 'normal'],
[653, 218, 'normal'],
[654, 208, 'normal'],
[686, 178, 'normal'],
[675, 155, 'normal'],
[678, 163, 'normal'],
[708, 201, 'normal'],
[702, 220, 'normal'],
[697, 255, 'normal']]],
[[False, True],
[False, True],
[False, True],
[False, True],
[False, True],
[False, True],
[False, False],
[False, False],
[False, False]]],
['control: scenario 2',
[{'sp': 700, 'comp_lockout': 200, 'aux_lockout': 350},
[[696, 417, 'normal'],
[700, 441, 'normal'],
[669, 443, 'normal'],
[695, 420, 'normal'],
[699, 380, 'normal'],
[657, 360, 'emergency'],
[665, 359, 'normal'],
[646, 335, 'emergency'],
[705, 331, 'normal'],
[699, 371, 'emergency'],
[696, 334, 'emergency'],
[698, 318, 'normal']]],
[[False, False],
[False, False],
[True, False],
[False, False],
[False, False],
[False, True],
[True, False],
[False, True],
[False, False],
[False, False],
[False, False],
[False, False]]],
['control: scenario 3',
[{'sp': 700, 'comp_lockout': 100, 'aux_lockout': 350},
[[670, 296, 'normal'],
[694, 303, 'normal'],
[704, 303, 'normal'],
[692, 316, 'normal'],
[688, 277, 'normal'],
[695, 304, 'normal'],
[691, 336, 'normal'],
[648, 337, 'normal'],
[686, 313, 'normal']]],
[[True, False],
[False, False],
[False, False],
[False, False],
[True, False],
[False, False],
[False, False],
[True, True],
[True, False]]],
['control: scenario 4',
[{'sp': 700, 'comp_lockout': 250, 'aux_lockout': 260},
[[666, 410, 'normal'],
[706, 407, 'normal'],
[684, 447, 'normal'],
[682, 450, 'normal'],
[660, 450, 'normal'],
[664, 413, 'normal'],
[657, 443, 'normal'],
[676, 425, 'normal'],
[662, 436, 'normal'],
[666, 429, 'normal'],
[696, 429, 'normal'],
[706, 410, 'normal']]],
[[True, False],
[False, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[False, False],
[False, False]]]]]
for label, args, expected in fixtures[N-1]:
check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression: lockout band | [[True, False], [True, False], [False, True], [False, True], [True, False], [False, True], [False, False]] | [[True, False], [True, False], [False, True], [False, True], [True, False], [False, True], [False, False]] | Passed |
| regression: scenario 7 | [[False, True], [False, True], [False, False], [False, True], [False, True], [False, True], [False, False], [False, True], [False, True], [False, True], [False, True], [False, False]] | [[False, True], [False, True], [False, False], [False, True], [False, True], [False, True], [False, False], [False, True], [False, True], [False, True], [False, True], [False, False]] | Passed |
| control: emergency deep demand | [[False, True], [False, True], [False, True]] | [[False, True], [False, True], [False, True]] | Passed |
| control: mild weather second stage | [[True, True], [True, False], [True, False]] | [[True, True], [True, False], [True, False]] | Passed |
| control: scenario 1 | [[True, False], [True, True], [True, False], [True, False], [True, False], [True, False], [False, True], [True, False]] | [[True, False], [True, True], [True, False], [True, False], [True, False], [True, False], [False, True], [True, False]] | Passed |
| control: scenario 2 | [[False, False], [False, False], [True, True], [False, False], [True, False], [True, True], [True, True], [True, True], [True, False], [False, False], [False, False]] | [[False, False], [False, False], [True, True], [False, False], [True, False], [True, True], [True, True], [True, True], [True, False], [False, False], [False, False]] | Passed |
| control: scenario 3 | [[True, False], [True, False], [True, False], [True, True], [True, True], [True, False], [True, True], [False, True], [False, False]] | [[True, False], [True, False], [True, False], [True, True], [True, True], [True, False], [True, True], [False, True], [False, False]] | Passed |
| control: scenario 4 | [[True, True], [False, False], [False, True], [True, False], [True, True], [True, False], [True, False], [False, False], [True, True], [True, True], [False, True]] | [[True, True], [False, False], [False, True], [True, False], [True, True], [True, False], [True, False], [False, False], [True, True], [True, True], [False, True]] | Passed |
SHA-256 / c117f056ee4f4362db6915c165f61cbfbface6d90885c1efe32f035de4663f0e
Verification & scope
A deterministic bounded teaching model of one thermostat or HVAC controller decision evaluated per sample. Temperatures are integer tenths of a degree Fahrenheit unless stated otherwise. The contract is a stipulated toy convention, not a claim of conformance to any manufacturer, ASHRAE guideline or code. 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:51:45.645117+00:00.
Case digest / 87547bb156e162b1835e4d8a658917e06c580904463b849704c5e27d52cf09ed