FA-92451 / HVAC thermostat control / Open access
Defrost runtime accumulator is not cleared at initiation · case 01
Defrosts repeat back to back because the accumulated runtime is still above the interval.
ROOT CAUSE
Initiation leaves the accumulator untouched.
VERIFIED REPAIR
Reset the frost runtime accumulator when defrost starts.
Unsuccessful approach: Subtracting half the interval still triggers the next defrost too soon.
Case contract
Heat pump time-temperature defrost sampled per minute (degrees F); samples are [compressor_running, coil_temp, outdoor_temp]. Compressor run minutes accumulate only while coil <= 32. When the accumulation reaches interval and outdoor <= 50, defrost starts that minute and the accumulation resets; otherwise the accumulation keeps growing. Defrost ends on the first later minute with coil >= 57 or when it has lasted max_minutes minutes; that minute reports normal operation. Return heat, off or defrost per minute.
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(interval, max_minutes, samples):
acc = 0
defrost_min = None
out = []
for running, coil, outdoor in samples:
if defrost_min is not None:
defrost_min += 1
if coil >= 57 or defrost_min >= max_minutes:
defrost_min = None
out.append('heat' if running else 'off')
else:
out.append('defrost')
continue
if running and coil <= 32:
acc += 1
if acc >= interval and outdoor <= 50:
defrost_min = 0
out.append('defrost')
continue
out.append('heat' if running else 'off')
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: two defrosts',
[3,
4,
[[True, 30, 20],
[True, 30, 20],
[False, 30, 20],
[True, 32, 20],
[True, 40, 20],
[True, 45, 20],
[True, 57, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20]]],
['heat',
'heat',
'off',
'defrost',
'defrost',
'defrost',
'heat',
'heat',
'heat',
'defrost',
'defrost',
'defrost',
'defrost',
'heat']],
['regression: warm outdoor inhibits',
[2, 3, [[True, 30, 55], [True, 30, 55], [True, 30, 50], [True, 60, 50], [True, 30, 50]]],
['heat', 'heat', 'defrost', 'heat', 'heat']],
['control: dry coil runtime',
[2, 3, [[True, 40, 20], [True, 33, 20], [True, 32, 20], [True, 31, 20], [True, 50, 20]]],
['heat', 'heat', 'heat', 'defrost', 'defrost']],
['regression: exact termination temperature',
[1, 5, [[True, 30, 20], [True, 56, 20], [True, 57, 20], [False, 30, 20], [True, 30, 20]]],
['defrost', 'defrost', 'heat', 'off', 'defrost']],
['control: scenario 1',
[3,
3,
[[True, 40, 35],
[True, 40, 50],
[True, 40, 51],
[True, 40, 51],
[True, 40, 50],
[True, 40, 50],
[False, 20, 35],
[False, 20, 51],
[True, 20, 50],
[True, 50, 20],
[True, 50, 50],
[True, 56, 50],
[True, 40, 50],
[True, 40, 50],
[False, 40, 51],
[True, 40, 50],
[False, 20, 51],
[False, 20, 60],
[True, 57, 51],
[False, 57, 51]]],
['heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'off',
'off',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'off',
'heat',
'off',
'off',
'heat',
'off']],
['regression: scenario 2',
[4,
3,
[[True, 33, 60],
[False, 57, 20],
[True, 57, 50],
[True, 60, 20],
[True, 60, 35],
[True, 60, 50],
[True, 28, 50],
[True, 28, 20],
[True, 28, 20],
[False, 28, 50],
[True, 28, 51],
[True, 28, 35],
[True, 28, 60],
[True, 28, 50],
[True, 40, 50],
[True, 40, 50],
[False, 40, 60]]],
['heat',
'off',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'off',
'heat',
'defrost',
'defrost',
'defrost',
'heat',
'heat',
'off']],
['regression: scenario 3',
[5,
3,
[[True, 20, 20],
[True, 20, 50],
[True, 20, 50],
[True, 20, 50],
[True, 20, 35],
[True, 40, 50],
[False, 40, 20],
[True, 40, 50],
[True, 40, 50],
[True, 33, 60],
[False, 33, 60],
[True, 60, 50]]],
['heat', 'heat', 'heat', 'heat', 'defrost', 'defrost', 'defrost', 'heat', 'heat', 'heat', 'off', 'heat']],
['regression: scenario 4',
[3,
4,
[[True, 20, 50],
[True, 20, 35],
[True, 20, 60],
[True, 20, 50],
[False, 20, 50],
[True, 20, 35],
[True, 20, 60],
[True, 20, 51],
[False, 20, 20],
[True, 50, 50],
[True, 50, 50],
[False, 50, 50],
[True, 50, 35],
[False, 33, 60],
[True, 33, 60],
[True, 33, 50],
[True, 20, 35],
[True, 20, 35],
[True, 20, 50],
[True, 50, 20]]],
['heat',
'heat',
'heat',
'defrost',
'defrost',
'defrost',
'defrost',
'heat',
'off',
'heat',
'heat',
'off',
'heat',
'off',
'heat',
'heat',
'heat',
'heat',
'defrost',
'defrost']]],
[['regression: warm outdoor inhibits',
[2, 3, [[True, 30, 55], [True, 30, 55], [True, 30, 50], [True, 60, 50], [True, 30, 50]]],
['heat', 'heat', 'defrost', 'heat', 'heat']],
['regression: exact termination temperature',
[1, 5, [[True, 30, 20], [True, 56, 20], [True, 57, 20], [False, 30, 20], [True, 30, 20]]],
['defrost', 'defrost', 'heat', 'off', 'defrost']],
['regression: two defrosts',
[3,
4,
[[True, 30, 20],
[True, 30, 20],
[False, 30, 20],
[True, 32, 20],
[True, 40, 20],
[True, 45, 20],
[True, 57, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20]]],
['heat',
'heat',
'off',
'defrost',
'defrost',
'defrost',
'heat',
'heat',
'heat',
'defrost',
'defrost',
'defrost',
'defrost',
'heat']],
['control: dry coil runtime',
[2, 3, [[True, 40, 20], [True, 33, 20], [True, 32, 20], [True, 31, 20], [True, 50, 20]]],
['heat', 'heat', 'heat', 'defrost', 'defrost']],
['regression: scenario 1',
[3,
3,
[[True, 28, 20],
[True, 28, 50],
[True, 32, 50],
[False, 32, 35],
[True, 60, 20],
[True, 60, 35],
[True, 60, 50],
[True, 60, 50],
[True, 57, 50],
[True, 57, 50],
[True, 60, 60],
[False, 60, 50],
[True, 60, 35],
[True, 33, 50]]],
['heat',
'heat',
'defrost',
'defrost',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'off',
'heat',
'heat']],
['regression: scenario 2',
[4,
4,
[[True, 40, 50],
[True, 40, 35],
[True, 40, 60],
[False, 56, 60],
[True, 56, 35],
[True, 50, 50],
[True, 32, 35],
[True, 32, 51],
[True, 32, 20],
[True, 32, 51],
[True, 32, 60],
[True, 57, 35],
[True, 32, 50],
[True, 32, 35],
[True, 20, 35],
[True, 50, 35],
[True, 57, 35],
[True, 57, 51],
[False, 57, 50]]],
['heat',
'heat',
'heat',
'off',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'defrost',
'defrost',
'defrost',
'defrost',
'heat',
'heat',
'heat',
'off']],
['control: scenario 3',
[3,
6,
[[False, 56, 51],
[True, 56, 35],
[False, 56, 35],
[True, 56, 35],
[True, 56, 35],
[True, 33, 50],
[True, 33, 20],
[True, 33, 50],
[False, 33, 60],
[True, 33, 35],
[True, 33, 35],
[True, 33, 50],
[True, 33, 60],
[True, 33, 35],
[True, 33, 35],
[True, 20, 50],
[True, 20, 51]]],
['off',
'heat',
'off',
'heat',
'heat',
'heat',
'heat',
'heat',
'off',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat']],
['regression: scenario 4',
[4,
4,
[[False, 40, 50],
[True, 40, 50],
[True, 40, 35],
[True, 40, 50],
[True, 40, 50],
[True, 28, 50],
[True, 28, 50],
[False, 28, 60],
[False, 28, 20],
[True, 28, 60],
[True, 28, 50],
[False, 28, 60],
[True, 28, 50],
[True, 28, 35],
[False, 28, 50],
[True, 28, 20],
[True, 28, 51],
[True, 33, 20]]],
['off',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'off',
'off',
'heat',
'defrost',
'defrost',
'defrost',
'defrost',
'off',
'heat',
'heat',
'heat']]],
[['regression: exact termination temperature',
[1, 5, [[True, 30, 20], [True, 56, 20], [True, 57, 20], [False, 30, 20], [True, 30, 20]]],
['defrost', 'defrost', 'heat', 'off', 'defrost']],
['regression: scenario 4',
[3,
3,
[[True, 28, 51],
[True, 28, 35],
[True, 56, 50],
[False, 56, 51],
[True, 56, 50],
[True, 56, 20],
[False, 40, 50],
[True, 40, 20],
[False, 60, 20],
[True, 50, 50],
[True, 56, 35],
[True, 56, 35],
[True, 56, 51],
[True, 32, 60],
[True, 32, 60],
[True, 32, 35],
[True, 32, 60],
[True, 32, 20],
[True, 32, 50],
[True, 32, 60],
[True, 32, 51],
[True, 40, 20],
[True, 40, 20],
[True, 40, 20]]],
['heat',
'heat',
'heat',
'off',
'heat',
'heat',
'off',
'heat',
'off',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'defrost',
'defrost',
'defrost',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat']],
['regression: two defrosts',
[3,
4,
[[True, 30, 20],
[True, 30, 20],
[False, 30, 20],
[True, 32, 20],
[True, 40, 20],
[True, 45, 20],
[True, 57, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20]]],
['heat',
'heat',
'off',
'defrost',
'defrost',
'defrost',
'heat',
'heat',
'heat',
'defrost',
'defrost',
'defrost',
'defrost',
'heat']],
['regression: warm outdoor inhibits',
[2, 3, [[True, 30, 55], [True, 30, 55], [True, 30, 50], [True, 60, 50], [True, 30, 50]]],
['heat', 'heat', 'defrost', 'heat', 'heat']],
['control: dry coil runtime',
[2, 3, [[True, 40, 20], [True, 33, 20], [True, 32, 20], [True, 31, 20], [True, 50, 20]]],
['heat', 'heat', 'heat', 'defrost', 'defrost']],
['regression: scenario 1',
[4,
6,
[[True, 33, 20],
[True, 28, 50],
[True, 56, 51],
[True, 33, 51],
[True, 28, 35],
[False, 28, 50],
[True, 28, 60],
[True, 28, 20],
[True, 40, 50],
[True, 40, 35],
[True, 40, 51],
[True, 40, 50],
[True, 28, 60],
[True, 28, 50],
[True, 50, 35],
[True, 60, 50],
[True, 57, 20],
[True, 40, 50]]],
['heat',
'heat',
'heat',
'heat',
'heat',
'off',
'heat',
'defrost',
'defrost',
'defrost',
'defrost',
'defrost',
'defrost',
'heat',
'heat',
'heat',
'heat',
'heat']],
['control: scenario 2',
[4,
3,
[[True, 32, 20],
[True, 57, 60],
[True, 57, 60],
[True, 57, 20],
[False, 40, 51],
[True, 50, 50],
[True, 50, 51],
[True, 50, 50],
[True, 56, 60],
[True, 40, 20],
[False, 40, 35],
[True, 50, 35],
[False, 50, 51],
[False, 50, 35],
[True, 57, 35],
[True, 57, 20],
[True, 57, 20],
[True, 57, 50],
[True, 57, 60]]],
['heat',
'heat',
'heat',
'heat',
'off',
'heat',
'heat',
'heat',
'heat',
'heat',
'off',
'heat',
'off',
'off',
'heat',
'heat',
'heat',
'heat',
'heat']],
['regression: scenario 3',
[3,
6,
[[True, 20, 60],
[True, 33, 20],
[True, 33, 60],
[True, 33, 51],
[True, 33, 35],
[True, 32, 50],
[True, 32, 35],
[True, 32, 35],
[True, 32, 60],
[True, 32, 60],
[False, 32, 60],
[True, 32, 35],
[False, 32, 50],
[True, 40, 50]]],
['heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'defrost',
'defrost',
'defrost',
'defrost',
'defrost',
'defrost',
'off',
'heat']]],
[['regression: scenario 3',
[5,
4,
[[False, 32, 51],
[False, 32, 50],
[True, 32, 20],
[True, 32, 50],
[True, 32, 50],
[True, 32, 51],
[True, 32, 20],
[True, 56, 50],
[False, 56, 50],
[True, 56, 51],
[True, 56, 51],
[False, 56, 35],
[True, 20, 20],
[True, 20, 35],
[True, 20, 60],
[True, 20, 50]]],
['off',
'off',
'heat',
'heat',
'heat',
'heat',
'defrost',
'defrost',
'defrost',
'defrost',
'heat',
'off',
'heat',
'heat',
'heat',
'heat']],
['regression: scenario 7',
[4,
6,
[[True, 28, 50],
[True, 28, 35],
[True, 28, 50],
[True, 28, 50],
[True, 28, 50],
[True, 28, 50],
[True, 28, 60],
[True, 28, 20],
[True, 32, 60],
[False, 40, 60],
[True, 40, 60],
[True, 40, 35],
[True, 32, 60],
[True, 32, 50]]],
['heat',
'heat',
'heat',
'defrost',
'defrost',
'defrost',
'defrost',
'defrost',
'defrost',
'off',
'heat',
'heat',
'heat',
'heat']],
['regression: two defrosts',
[3,
4,
[[True, 30, 20],
[True, 30, 20],
[False, 30, 20],
[True, 32, 20],
[True, 40, 20],
[True, 45, 20],
[True, 57, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20]]],
['heat',
'heat',
'off',
'defrost',
'defrost',
'defrost',
'heat',
'heat',
'heat',
'defrost',
'defrost',
'defrost',
'defrost',
'heat']],
['regression: warm outdoor inhibits',
[2, 3, [[True, 30, 55], [True, 30, 55], [True, 30, 50], [True, 60, 50], [True, 30, 50]]],
['heat', 'heat', 'defrost', 'heat', 'heat']],
['control: dry coil runtime',
[2, 3, [[True, 40, 20], [True, 33, 20], [True, 32, 20], [True, 31, 20], [True, 50, 20]]],
['heat', 'heat', 'heat', 'defrost', 'defrost']],
['regression: exact termination temperature',
[1, 5, [[True, 30, 20], [True, 56, 20], [True, 57, 20], [False, 30, 20], [True, 30, 20]]],
['defrost', 'defrost', 'heat', 'off', 'defrost']],
['control: scenario 1',
[5,
4,
[[True, 57, 60],
[True, 57, 50],
[True, 57, 50],
[True, 57, 35],
[True, 33, 50],
[True, 33, 50],
[True, 32, 50],
[True, 50, 51],
[True, 50, 51],
[False, 50, 20],
[False, 33, 50],
[True, 56, 20],
[True, 32, 60],
[True, 32, 35],
[True, 32, 20]]],
['heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'off',
'off',
'heat',
'heat',
'heat',
'heat']],
['control: scenario 2',
[4,
6,
[[False, 28, 50],
[True, 28, 51],
[True, 28, 35],
[True, 28, 50],
[True, 57, 50],
[True, 57, 20],
[True, 57, 50],
[True, 57, 50],
[True, 56, 50],
[True, 56, 35],
[True, 56, 51],
[True, 56, 50]]],
['off', 'heat', 'heat', 'heat', 'heat', 'heat', 'heat', 'heat', 'heat', 'heat', 'heat', 'heat']]],
[['regression: scenario 5',
[5,
4,
[[True, 28, 51],
[True, 28, 51],
[False, 28, 50],
[True, 28, 35],
[True, 28, 35],
[True, 40, 60],
[True, 56, 20],
[False, 40, 35],
[False, 40, 50],
[True, 40, 50],
[True, 40, 50],
[True, 40, 35],
[True, 40, 50],
[True, 28, 51],
[False, 28, 50],
[True, 28, 50],
[True, 56, 35],
[True, 33, 35],
[True, 50, 50],
[False, 50, 50],
[True, 50, 50]]],
['heat',
'heat',
'off',
'heat',
'heat',
'heat',
'heat',
'off',
'off',
'heat',
'heat',
'heat',
'heat',
'heat',
'defrost',
'defrost',
'defrost',
'defrost',
'heat',
'off',
'heat']],
['regression: scenario 7',
[3,
4,
[[True, 32, 35],
[True, 32, 50],
[True, 32, 60],
[True, 32, 35],
[True, 56, 20],
[True, 20, 50],
[True, 20, 20],
[False, 20, 35],
[True, 28, 20],
[True, 20, 35],
[True, 20, 20],
[True, 20, 20]]],
['heat',
'heat',
'heat',
'defrost',
'defrost',
'defrost',
'defrost',
'off',
'heat',
'heat',
'defrost',
'defrost']],
['regression: two defrosts',
[3,
4,
[[True, 30, 20],
[True, 30, 20],
[False, 30, 20],
[True, 32, 20],
[True, 40, 20],
[True, 45, 20],
[True, 57, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20]]],
['heat',
'heat',
'off',
'defrost',
'defrost',
'defrost',
'heat',
'heat',
'heat',
'defrost',
'defrost',
'defrost',
'defrost',
'heat']],
['regression: warm outdoor inhibits',
[2, 3, [[True, 30, 55], [True, 30, 55], [True, 30, 50], [True, 60, 50], [True, 30, 50]]],
['heat', 'heat', 'defrost', 'heat', 'heat']],
['control: dry coil runtime',
[2, 3, [[True, 40, 20], [True, 33, 20], [True, 32, 20], [True, 31, 20], [True, 50, 20]]],
['heat', 'heat', 'heat', 'defrost', 'defrost']],
['regression: exact termination temperature',
[1, 5, [[True, 30, 20], [True, 56, 20], [True, 57, 20], [False, 30, 20], [True, 30, 20]]],
['defrost', 'defrost', 'heat', 'off', 'defrost']],
['control: scenario 1',
[4,
6,
[[True, 32, 50],
[True, 50, 50],
[True, 50, 35],
[True, 57, 51],
[True, 57, 20],
[False, 57, 51],
[True, 57, 50],
[True, 57, 51],
[True, 32, 50],
[True, 32, 51],
[True, 32, 50],
[False, 28, 50]]],
['heat', 'heat', 'heat', 'heat', 'heat', 'off', 'heat', 'heat', 'heat', 'heat', 'defrost', 'defrost']],
['regression: scenario 2',
[3,
4,
[[True, 32, 35],
[True, 32, 35],
[True, 33, 60],
[True, 33, 50],
[True, 33, 60],
[True, 57, 51],
[True, 20, 60],
[True, 20, 50],
[True, 33, 50],
[False, 33, 51],
[False, 33, 20],
[True, 33, 20],
[True, 40, 50],
[True, 40, 50],
[True, 40, 35],
[True, 40, 35],
[True, 40, 51],
[True, 28, 35],
[True, 28, 51],
[True, 33, 60],
[False, 33, 60],
[True, 56, 51],
[True, 56, 60],
[False, 56, 60]]],
['heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'defrost',
'defrost',
'defrost',
'defrost',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'off',
'heat',
'heat',
'off']]]]
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: two defrosts | ['heat', 'heat', 'off', 'defrost', 'defrost', 'defrost', 'heat', 'defrost', 'defrost', 'defrost', 'defrost', 'heat', 'defrost', 'defrost'] | ['heat', 'heat', 'off', 'defrost', 'defrost', 'defrost', 'heat', 'heat', 'heat', 'defrost', 'defrost', 'defrost', 'defrost', 'heat'] | Failed |
| regression: warm outdoor inhibits | ['heat', 'heat', 'defrost', 'heat', 'defrost'] | ['heat', 'heat', 'defrost', 'heat', 'heat'] | Failed |
| control: dry coil runtime | ['heat', 'heat', 'heat', 'defrost', 'defrost'] | ['heat', 'heat', 'heat', 'defrost', 'defrost'] | Passed |
| regression: exact termination temperature | ['defrost', 'defrost', 'heat', 'defrost', 'defrost'] | ['defrost', 'defrost', 'heat', 'off', 'defrost'] | Failed |
| control: scenario 1 | ['heat', 'heat', 'heat', 'heat', 'heat', 'heat', 'off', 'off', 'heat', 'heat', 'heat', 'heat', 'heat', 'heat', 'off', 'heat', 'off', 'off', 'heat', 'off'] | ['heat', 'heat', 'heat', 'heat', 'heat', 'heat', 'off', 'off', 'heat', 'heat', 'heat', 'heat', 'heat', 'heat', 'off', 'heat', 'off', 'off', 'heat', 'off'] | Passed |
| regression: scenario 2 | ['heat', 'off', 'heat', 'heat', 'heat', 'heat', 'heat', 'heat', 'heat', 'off', 'heat', 'defrost', 'defrost', 'defrost', 'heat', 'defrost', 'defrost'] | ['heat', 'off', 'heat', 'heat', 'heat', 'heat', 'heat', 'heat', 'heat', 'off', 'heat', 'defrost', 'defrost', 'defrost', 'heat', 'heat', 'off'] | Failed |
| regression: scenario 3 | ['heat', 'heat', 'heat', 'heat', 'defrost', 'defrost', 'defrost', 'heat', 'defrost', 'defrost', 'defrost', 'heat'] | ['heat', 'heat', 'heat', 'heat', 'defrost', 'defrost', 'defrost', 'heat', 'heat', 'heat', 'off', 'heat'] | Failed |
| regression: scenario 4 | ['heat', 'heat', 'heat', 'defrost', 'defrost', 'defrost', 'defrost', 'heat', 'defrost', 'defrost', 'defrost', 'defrost', 'heat', 'off', 'heat', 'defrost', 'defrost', 'defrost', 'defrost', 'heat'] | ['heat', 'heat', 'heat', 'defrost', 'defrost', 'defrost', 'defrost', 'heat', 'off', 'heat', 'heat', 'off', 'heat', 'off', 'heat', 'heat', 'heat', 'heat', 'defrost', 'defrost'] | Failed |
SHA-256 / 4eb55b3aec1fdc4c582f246928f3ebff730fcede48a8cd3ccd4ba9c74950f524
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(interval, max_minutes, samples):
acc = 0
defrost_min = None
out = []
for running, coil, outdoor in samples:
if defrost_min is not None:
defrost_min += 1
if coil >= 57 or defrost_min >= max_minutes:
defrost_min = None
out.append('heat' if running else 'off')
else:
out.append('defrost')
continue
if running and coil <= 32:
acc += 1
if acc >= interval and outdoor <= 50:
acc = acc - interval // 2
defrost_min = 0
out.append('defrost')
continue
out.append('heat' if running else 'off')
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: two defrosts',
[3,
4,
[[True, 30, 20],
[True, 30, 20],
[False, 30, 20],
[True, 32, 20],
[True, 40, 20],
[True, 45, 20],
[True, 57, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20]]],
['heat',
'heat',
'off',
'defrost',
'defrost',
'defrost',
'heat',
'heat',
'heat',
'defrost',
'defrost',
'defrost',
'defrost',
'heat']],
['regression: warm outdoor inhibits',
[2, 3, [[True, 30, 55], [True, 30, 55], [True, 30, 50], [True, 60, 50], [True, 30, 50]]],
['heat', 'heat', 'defrost', 'heat', 'heat']],
['control: dry coil runtime',
[2, 3, [[True, 40, 20], [True, 33, 20], [True, 32, 20], [True, 31, 20], [True, 50, 20]]],
['heat', 'heat', 'heat', 'defrost', 'defrost']],
['regression: exact termination temperature',
[1, 5, [[True, 30, 20], [True, 56, 20], [True, 57, 20], [False, 30, 20], [True, 30, 20]]],
['defrost', 'defrost', 'heat', 'off', 'defrost']],
['control: scenario 1',
[3,
3,
[[True, 40, 35],
[True, 40, 50],
[True, 40, 51],
[True, 40, 51],
[True, 40, 50],
[True, 40, 50],
[False, 20, 35],
[False, 20, 51],
[True, 20, 50],
[True, 50, 20],
[True, 50, 50],
[True, 56, 50],
[True, 40, 50],
[True, 40, 50],
[False, 40, 51],
[True, 40, 50],
[False, 20, 51],
[False, 20, 60],
[True, 57, 51],
[False, 57, 51]]],
['heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'off',
'off',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'off',
'heat',
'off',
'off',
'heat',
'off']],
['regression: scenario 2',
[4,
3,
[[True, 33, 60],
[False, 57, 20],
[True, 57, 50],
[True, 60, 20],
[True, 60, 35],
[True, 60, 50],
[True, 28, 50],
[True, 28, 20],
[True, 28, 20],
[False, 28, 50],
[True, 28, 51],
[True, 28, 35],
[True, 28, 60],
[True, 28, 50],
[True, 40, 50],
[True, 40, 50],
[False, 40, 60]]],
['heat',
'off',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'off',
'heat',
'defrost',
'defrost',
'defrost',
'heat',
'heat',
'off']],
['regression: scenario 3',
[5,
3,
[[True, 20, 20],
[True, 20, 50],
[True, 20, 50],
[True, 20, 50],
[True, 20, 35],
[True, 40, 50],
[False, 40, 20],
[True, 40, 50],
[True, 40, 50],
[True, 33, 60],
[False, 33, 60],
[True, 60, 50]]],
['heat', 'heat', 'heat', 'heat', 'defrost', 'defrost', 'defrost', 'heat', 'heat', 'heat', 'off', 'heat']],
['regression: scenario 4',
[3,
4,
[[True, 20, 50],
[True, 20, 35],
[True, 20, 60],
[True, 20, 50],
[False, 20, 50],
[True, 20, 35],
[True, 20, 60],
[True, 20, 51],
[False, 20, 20],
[True, 50, 50],
[True, 50, 50],
[False, 50, 50],
[True, 50, 35],
[False, 33, 60],
[True, 33, 60],
[True, 33, 50],
[True, 20, 35],
[True, 20, 35],
[True, 20, 50],
[True, 50, 20]]],
['heat',
'heat',
'heat',
'defrost',
'defrost',
'defrost',
'defrost',
'heat',
'off',
'heat',
'heat',
'off',
'heat',
'off',
'heat',
'heat',
'heat',
'heat',
'defrost',
'defrost']]],
[['regression: warm outdoor inhibits',
[2, 3, [[True, 30, 55], [True, 30, 55], [True, 30, 50], [True, 60, 50], [True, 30, 50]]],
['heat', 'heat', 'defrost', 'heat', 'heat']],
['regression: exact termination temperature',
[1, 5, [[True, 30, 20], [True, 56, 20], [True, 57, 20], [False, 30, 20], [True, 30, 20]]],
['defrost', 'defrost', 'heat', 'off', 'defrost']],
['regression: two defrosts',
[3,
4,
[[True, 30, 20],
[True, 30, 20],
[False, 30, 20],
[True, 32, 20],
[True, 40, 20],
[True, 45, 20],
[True, 57, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20]]],
['heat',
'heat',
'off',
'defrost',
'defrost',
'defrost',
'heat',
'heat',
'heat',
'defrost',
'defrost',
'defrost',
'defrost',
'heat']],
['control: dry coil runtime',
[2, 3, [[True, 40, 20], [True, 33, 20], [True, 32, 20], [True, 31, 20], [True, 50, 20]]],
['heat', 'heat', 'heat', 'defrost', 'defrost']],
['regression: scenario 1',
[3,
3,
[[True, 28, 20],
[True, 28, 50],
[True, 32, 50],
[False, 32, 35],
[True, 60, 20],
[True, 60, 35],
[True, 60, 50],
[True, 60, 50],
[True, 57, 50],
[True, 57, 50],
[True, 60, 60],
[False, 60, 50],
[True, 60, 35],
[True, 33, 50]]],
['heat',
'heat',
'defrost',
'defrost',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'off',
'heat',
'heat']],
['regression: scenario 2',
[4,
4,
[[True, 40, 50],
[True, 40, 35],
[True, 40, 60],
[False, 56, 60],
[True, 56, 35],
[True, 50, 50],
[True, 32, 35],
[True, 32, 51],
[True, 32, 20],
[True, 32, 51],
[True, 32, 60],
[True, 57, 35],
[True, 32, 50],
[True, 32, 35],
[True, 20, 35],
[True, 50, 35],
[True, 57, 35],
[True, 57, 51],
[False, 57, 50]]],
['heat',
'heat',
'heat',
'off',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'defrost',
'defrost',
'defrost',
'defrost',
'heat',
'heat',
'heat',
'off']],
['control: scenario 3',
[3,
6,
[[False, 56, 51],
[True, 56, 35],
[False, 56, 35],
[True, 56, 35],
[True, 56, 35],
[True, 33, 50],
[True, 33, 20],
[True, 33, 50],
[False, 33, 60],
[True, 33, 35],
[True, 33, 35],
[True, 33, 50],
[True, 33, 60],
[True, 33, 35],
[True, 33, 35],
[True, 20, 50],
[True, 20, 51]]],
['off',
'heat',
'off',
'heat',
'heat',
'heat',
'heat',
'heat',
'off',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat']],
['regression: scenario 4',
[4,
4,
[[False, 40, 50],
[True, 40, 50],
[True, 40, 35],
[True, 40, 50],
[True, 40, 50],
[True, 28, 50],
[True, 28, 50],
[False, 28, 60],
[False, 28, 20],
[True, 28, 60],
[True, 28, 50],
[False, 28, 60],
[True, 28, 50],
[True, 28, 35],
[False, 28, 50],
[True, 28, 20],
[True, 28, 51],
[True, 33, 20]]],
['off',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'off',
'off',
'heat',
'defrost',
'defrost',
'defrost',
'defrost',
'off',
'heat',
'heat',
'heat']]],
[['regression: exact termination temperature',
[1, 5, [[True, 30, 20], [True, 56, 20], [True, 57, 20], [False, 30, 20], [True, 30, 20]]],
['defrost', 'defrost', 'heat', 'off', 'defrost']],
['regression: scenario 4',
[3,
3,
[[True, 28, 51],
[True, 28, 35],
[True, 56, 50],
[False, 56, 51],
[True, 56, 50],
[True, 56, 20],
[False, 40, 50],
[True, 40, 20],
[False, 60, 20],
[True, 50, 50],
[True, 56, 35],
[True, 56, 35],
[True, 56, 51],
[True, 32, 60],
[True, 32, 60],
[True, 32, 35],
[True, 32, 60],
[True, 32, 20],
[True, 32, 50],
[True, 32, 60],
[True, 32, 51],
[True, 40, 20],
[True, 40, 20],
[True, 40, 20]]],
['heat',
'heat',
'heat',
'off',
'heat',
'heat',
'off',
'heat',
'off',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'defrost',
'defrost',
'defrost',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat']],
['regression: two defrosts',
[3,
4,
[[True, 30, 20],
[True, 30, 20],
[False, 30, 20],
[True, 32, 20],
[True, 40, 20],
[True, 45, 20],
[True, 57, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20]]],
['heat',
'heat',
'off',
'defrost',
'defrost',
'defrost',
'heat',
'heat',
'heat',
'defrost',
'defrost',
'defrost',
'defrost',
'heat']],
['regression: warm outdoor inhibits',
[2, 3, [[True, 30, 55], [True, 30, 55], [True, 30, 50], [True, 60, 50], [True, 30, 50]]],
['heat', 'heat', 'defrost', 'heat', 'heat']],
['control: dry coil runtime',
[2, 3, [[True, 40, 20], [True, 33, 20], [True, 32, 20], [True, 31, 20], [True, 50, 20]]],
['heat', 'heat', 'heat', 'defrost', 'defrost']],
['regression: scenario 1',
[4,
6,
[[True, 33, 20],
[True, 28, 50],
[True, 56, 51],
[True, 33, 51],
[True, 28, 35],
[False, 28, 50],
[True, 28, 60],
[True, 28, 20],
[True, 40, 50],
[True, 40, 35],
[True, 40, 51],
[True, 40, 50],
[True, 28, 60],
[True, 28, 50],
[True, 50, 35],
[True, 60, 50],
[True, 57, 20],
[True, 40, 50]]],
['heat',
'heat',
'heat',
'heat',
'heat',
'off',
'heat',
'defrost',
'defrost',
'defrost',
'defrost',
'defrost',
'defrost',
'heat',
'heat',
'heat',
'heat',
'heat']],
['control: scenario 2',
[4,
3,
[[True, 32, 20],
[True, 57, 60],
[True, 57, 60],
[True, 57, 20],
[False, 40, 51],
[True, 50, 50],
[True, 50, 51],
[True, 50, 50],
[True, 56, 60],
[True, 40, 20],
[False, 40, 35],
[True, 50, 35],
[False, 50, 51],
[False, 50, 35],
[True, 57, 35],
[True, 57, 20],
[True, 57, 20],
[True, 57, 50],
[True, 57, 60]]],
['heat',
'heat',
'heat',
'heat',
'off',
'heat',
'heat',
'heat',
'heat',
'heat',
'off',
'heat',
'off',
'off',
'heat',
'heat',
'heat',
'heat',
'heat']],
['regression: scenario 3',
[3,
6,
[[True, 20, 60],
[True, 33, 20],
[True, 33, 60],
[True, 33, 51],
[True, 33, 35],
[True, 32, 50],
[True, 32, 35],
[True, 32, 35],
[True, 32, 60],
[True, 32, 60],
[False, 32, 60],
[True, 32, 35],
[False, 32, 50],
[True, 40, 50]]],
['heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'defrost',
'defrost',
'defrost',
'defrost',
'defrost',
'defrost',
'off',
'heat']]],
[['regression: scenario 3',
[5,
4,
[[False, 32, 51],
[False, 32, 50],
[True, 32, 20],
[True, 32, 50],
[True, 32, 50],
[True, 32, 51],
[True, 32, 20],
[True, 56, 50],
[False, 56, 50],
[True, 56, 51],
[True, 56, 51],
[False, 56, 35],
[True, 20, 20],
[True, 20, 35],
[True, 20, 60],
[True, 20, 50]]],
['off',
'off',
'heat',
'heat',
'heat',
'heat',
'defrost',
'defrost',
'defrost',
'defrost',
'heat',
'off',
'heat',
'heat',
'heat',
'heat']],
['regression: scenario 7',
[4,
6,
[[True, 28, 50],
[True, 28, 35],
[True, 28, 50],
[True, 28, 50],
[True, 28, 50],
[True, 28, 50],
[True, 28, 60],
[True, 28, 20],
[True, 32, 60],
[False, 40, 60],
[True, 40, 60],
[True, 40, 35],
[True, 32, 60],
[True, 32, 50]]],
['heat',
'heat',
'heat',
'defrost',
'defrost',
'defrost',
'defrost',
'defrost',
'defrost',
'off',
'heat',
'heat',
'heat',
'heat']],
['regression: two defrosts',
[3,
4,
[[True, 30, 20],
[True, 30, 20],
[False, 30, 20],
[True, 32, 20],
[True, 40, 20],
[True, 45, 20],
[True, 57, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20]]],
['heat',
'heat',
'off',
'defrost',
'defrost',
'defrost',
'heat',
'heat',
'heat',
'defrost',
'defrost',
'defrost',
'defrost',
'heat']],
['regression: warm outdoor inhibits',
[2, 3, [[True, 30, 55], [True, 30, 55], [True, 30, 50], [True, 60, 50], [True, 30, 50]]],
['heat', 'heat', 'defrost', 'heat', 'heat']],
['control: dry coil runtime',
[2, 3, [[True, 40, 20], [True, 33, 20], [True, 32, 20], [True, 31, 20], [True, 50, 20]]],
['heat', 'heat', 'heat', 'defrost', 'defrost']],
['regression: exact termination temperature',
[1, 5, [[True, 30, 20], [True, 56, 20], [True, 57, 20], [False, 30, 20], [True, 30, 20]]],
['defrost', 'defrost', 'heat', 'off', 'defrost']],
['control: scenario 1',
[5,
4,
[[True, 57, 60],
[True, 57, 50],
[True, 57, 50],
[True, 57, 35],
[True, 33, 50],
[True, 33, 50],
[True, 32, 50],
[True, 50, 51],
[True, 50, 51],
[False, 50, 20],
[False, 33, 50],
[True, 56, 20],
[True, 32, 60],
[True, 32, 35],
[True, 32, 20]]],
['heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'off',
'off',
'heat',
'heat',
'heat',
'heat']],
['control: scenario 2',
[4,
6,
[[False, 28, 50],
[True, 28, 51],
[True, 28, 35],
[True, 28, 50],
[True, 57, 50],
[True, 57, 20],
[True, 57, 50],
[True, 57, 50],
[True, 56, 50],
[True, 56, 35],
[True, 56, 51],
[True, 56, 50]]],
['off', 'heat', 'heat', 'heat', 'heat', 'heat', 'heat', 'heat', 'heat', 'heat', 'heat', 'heat']]],
[['regression: scenario 5',
[5,
4,
[[True, 28, 51],
[True, 28, 51],
[False, 28, 50],
[True, 28, 35],
[True, 28, 35],
[True, 40, 60],
[True, 56, 20],
[False, 40, 35],
[False, 40, 50],
[True, 40, 50],
[True, 40, 50],
[True, 40, 35],
[True, 40, 50],
[True, 28, 51],
[False, 28, 50],
[True, 28, 50],
[True, 56, 35],
[True, 33, 35],
[True, 50, 50],
[False, 50, 50],
[True, 50, 50]]],
['heat',
'heat',
'off',
'heat',
'heat',
'heat',
'heat',
'off',
'off',
'heat',
'heat',
'heat',
'heat',
'heat',
'defrost',
'defrost',
'defrost',
'defrost',
'heat',
'off',
'heat']],
['regression: scenario 7',
[3,
4,
[[True, 32, 35],
[True, 32, 50],
[True, 32, 60],
[True, 32, 35],
[True, 56, 20],
[True, 20, 50],
[True, 20, 20],
[False, 20, 35],
[True, 28, 20],
[True, 20, 35],
[True, 20, 20],
[True, 20, 20]]],
['heat',
'heat',
'heat',
'defrost',
'defrost',
'defrost',
'defrost',
'off',
'heat',
'heat',
'defrost',
'defrost']],
['regression: two defrosts',
[3,
4,
[[True, 30, 20],
[True, 30, 20],
[False, 30, 20],
[True, 32, 20],
[True, 40, 20],
[True, 45, 20],
[True, 57, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20]]],
['heat',
'heat',
'off',
'defrost',
'defrost',
'defrost',
'heat',
'heat',
'heat',
'defrost',
'defrost',
'defrost',
'defrost',
'heat']],
['regression: warm outdoor inhibits',
[2, 3, [[True, 30, 55], [True, 30, 55], [True, 30, 50], [True, 60, 50], [True, 30, 50]]],
['heat', 'heat', 'defrost', 'heat', 'heat']],
['control: dry coil runtime',
[2, 3, [[True, 40, 20], [True, 33, 20], [True, 32, 20], [True, 31, 20], [True, 50, 20]]],
['heat', 'heat', 'heat', 'defrost', 'defrost']],
['regression: exact termination temperature',
[1, 5, [[True, 30, 20], [True, 56, 20], [True, 57, 20], [False, 30, 20], [True, 30, 20]]],
['defrost', 'defrost', 'heat', 'off', 'defrost']],
['control: scenario 1',
[4,
6,
[[True, 32, 50],
[True, 50, 50],
[True, 50, 35],
[True, 57, 51],
[True, 57, 20],
[False, 57, 51],
[True, 57, 50],
[True, 57, 51],
[True, 32, 50],
[True, 32, 51],
[True, 32, 50],
[False, 28, 50]]],
['heat', 'heat', 'heat', 'heat', 'heat', 'off', 'heat', 'heat', 'heat', 'heat', 'defrost', 'defrost']],
['regression: scenario 2',
[3,
4,
[[True, 32, 35],
[True, 32, 35],
[True, 33, 60],
[True, 33, 50],
[True, 33, 60],
[True, 57, 51],
[True, 20, 60],
[True, 20, 50],
[True, 33, 50],
[False, 33, 51],
[False, 33, 20],
[True, 33, 20],
[True, 40, 50],
[True, 40, 50],
[True, 40, 35],
[True, 40, 35],
[True, 40, 51],
[True, 28, 35],
[True, 28, 51],
[True, 33, 60],
[False, 33, 60],
[True, 56, 51],
[True, 56, 60],
[False, 56, 60]]],
['heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'defrost',
'defrost',
'defrost',
'defrost',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'off',
'heat',
'heat',
'off']]]]
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: two defrosts | ['heat', 'heat', 'off', 'defrost', 'defrost', 'defrost', 'heat', 'defrost', 'defrost', 'defrost', 'defrost', 'heat', 'defrost', 'defrost'] | ['heat', 'heat', 'off', 'defrost', 'defrost', 'defrost', 'heat', 'heat', 'heat', 'defrost', 'defrost', 'defrost', 'defrost', 'heat'] | Failed |
| regression: warm outdoor inhibits | ['heat', 'heat', 'defrost', 'heat', 'defrost'] | ['heat', 'heat', 'defrost', 'heat', 'heat'] | Failed |
| control: dry coil runtime | ['heat', 'heat', 'heat', 'defrost', 'defrost'] | ['heat', 'heat', 'heat', 'defrost', 'defrost'] | Passed |
| regression: exact termination temperature | ['defrost', 'defrost', 'heat', 'defrost', 'defrost'] | ['defrost', 'defrost', 'heat', 'off', 'defrost'] | Failed |
| control: scenario 1 | ['heat', 'heat', 'heat', 'heat', 'heat', 'heat', 'off', 'off', 'heat', 'heat', 'heat', 'heat', 'heat', 'heat', 'off', 'heat', 'off', 'off', 'heat', 'off'] | ['heat', 'heat', 'heat', 'heat', 'heat', 'heat', 'off', 'off', 'heat', 'heat', 'heat', 'heat', 'heat', 'heat', 'off', 'heat', 'off', 'off', 'heat', 'off'] | Passed |
| regression: scenario 2 | ['heat', 'off', 'heat', 'heat', 'heat', 'heat', 'heat', 'heat', 'heat', 'off', 'heat', 'defrost', 'defrost', 'defrost', 'heat', 'heat', 'off'] | ['heat', 'off', 'heat', 'heat', 'heat', 'heat', 'heat', 'heat', 'heat', 'off', 'heat', 'defrost', 'defrost', 'defrost', 'heat', 'heat', 'off'] | Passed |
| regression: scenario 3 | ['heat', 'heat', 'heat', 'heat', 'defrost', 'defrost', 'defrost', 'heat', 'heat', 'heat', 'off', 'heat'] | ['heat', 'heat', 'heat', 'heat', 'defrost', 'defrost', 'defrost', 'heat', 'heat', 'heat', 'off', 'heat'] | Passed |
| regression: scenario 4 | ['heat', 'heat', 'heat', 'defrost', 'defrost', 'defrost', 'defrost', 'heat', 'defrost', 'defrost', 'defrost', 'defrost', 'heat', 'off', 'heat', 'heat', 'defrost', 'defrost', 'defrost', 'defrost'] | ['heat', 'heat', 'heat', 'defrost', 'defrost', 'defrost', 'defrost', 'heat', 'off', 'heat', 'heat', 'off', 'heat', 'off', 'heat', 'heat', 'heat', 'heat', 'defrost', 'defrost'] | Failed |
SHA-256 / 53412464fba61ec34ae96caa240f936c96329decbcf85f9e0592a8e635e2be31
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(interval, max_minutes, samples):
acc = 0
defrost_min = None
out = []
for running, coil, outdoor in samples:
if defrost_min is not None:
defrost_min += 1
if coil >= 57 or defrost_min >= max_minutes:
defrost_min = None
out.append('heat' if running else 'off')
else:
out.append('defrost')
continue
if running and coil <= 32:
acc += 1
if acc >= interval and outdoor <= 50:
acc = 0
defrost_min = 0
out.append('defrost')
continue
out.append('heat' if running else 'off')
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: two defrosts',
[3,
4,
[[True, 30, 20],
[True, 30, 20],
[False, 30, 20],
[True, 32, 20],
[True, 40, 20],
[True, 45, 20],
[True, 57, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20]]],
['heat',
'heat',
'off',
'defrost',
'defrost',
'defrost',
'heat',
'heat',
'heat',
'defrost',
'defrost',
'defrost',
'defrost',
'heat']],
['regression: warm outdoor inhibits',
[2, 3, [[True, 30, 55], [True, 30, 55], [True, 30, 50], [True, 60, 50], [True, 30, 50]]],
['heat', 'heat', 'defrost', 'heat', 'heat']],
['control: dry coil runtime',
[2, 3, [[True, 40, 20], [True, 33, 20], [True, 32, 20], [True, 31, 20], [True, 50, 20]]],
['heat', 'heat', 'heat', 'defrost', 'defrost']],
['regression: exact termination temperature',
[1, 5, [[True, 30, 20], [True, 56, 20], [True, 57, 20], [False, 30, 20], [True, 30, 20]]],
['defrost', 'defrost', 'heat', 'off', 'defrost']],
['control: scenario 1',
[3,
3,
[[True, 40, 35],
[True, 40, 50],
[True, 40, 51],
[True, 40, 51],
[True, 40, 50],
[True, 40, 50],
[False, 20, 35],
[False, 20, 51],
[True, 20, 50],
[True, 50, 20],
[True, 50, 50],
[True, 56, 50],
[True, 40, 50],
[True, 40, 50],
[False, 40, 51],
[True, 40, 50],
[False, 20, 51],
[False, 20, 60],
[True, 57, 51],
[False, 57, 51]]],
['heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'off',
'off',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'off',
'heat',
'off',
'off',
'heat',
'off']],
['regression: scenario 2',
[4,
3,
[[True, 33, 60],
[False, 57, 20],
[True, 57, 50],
[True, 60, 20],
[True, 60, 35],
[True, 60, 50],
[True, 28, 50],
[True, 28, 20],
[True, 28, 20],
[False, 28, 50],
[True, 28, 51],
[True, 28, 35],
[True, 28, 60],
[True, 28, 50],
[True, 40, 50],
[True, 40, 50],
[False, 40, 60]]],
['heat',
'off',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'off',
'heat',
'defrost',
'defrost',
'defrost',
'heat',
'heat',
'off']],
['regression: scenario 3',
[5,
3,
[[True, 20, 20],
[True, 20, 50],
[True, 20, 50],
[True, 20, 50],
[True, 20, 35],
[True, 40, 50],
[False, 40, 20],
[True, 40, 50],
[True, 40, 50],
[True, 33, 60],
[False, 33, 60],
[True, 60, 50]]],
['heat', 'heat', 'heat', 'heat', 'defrost', 'defrost', 'defrost', 'heat', 'heat', 'heat', 'off', 'heat']],
['regression: scenario 4',
[3,
4,
[[True, 20, 50],
[True, 20, 35],
[True, 20, 60],
[True, 20, 50],
[False, 20, 50],
[True, 20, 35],
[True, 20, 60],
[True, 20, 51],
[False, 20, 20],
[True, 50, 50],
[True, 50, 50],
[False, 50, 50],
[True, 50, 35],
[False, 33, 60],
[True, 33, 60],
[True, 33, 50],
[True, 20, 35],
[True, 20, 35],
[True, 20, 50],
[True, 50, 20]]],
['heat',
'heat',
'heat',
'defrost',
'defrost',
'defrost',
'defrost',
'heat',
'off',
'heat',
'heat',
'off',
'heat',
'off',
'heat',
'heat',
'heat',
'heat',
'defrost',
'defrost']]],
[['regression: warm outdoor inhibits',
[2, 3, [[True, 30, 55], [True, 30, 55], [True, 30, 50], [True, 60, 50], [True, 30, 50]]],
['heat', 'heat', 'defrost', 'heat', 'heat']],
['regression: exact termination temperature',
[1, 5, [[True, 30, 20], [True, 56, 20], [True, 57, 20], [False, 30, 20], [True, 30, 20]]],
['defrost', 'defrost', 'heat', 'off', 'defrost']],
['regression: two defrosts',
[3,
4,
[[True, 30, 20],
[True, 30, 20],
[False, 30, 20],
[True, 32, 20],
[True, 40, 20],
[True, 45, 20],
[True, 57, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20]]],
['heat',
'heat',
'off',
'defrost',
'defrost',
'defrost',
'heat',
'heat',
'heat',
'defrost',
'defrost',
'defrost',
'defrost',
'heat']],
['control: dry coil runtime',
[2, 3, [[True, 40, 20], [True, 33, 20], [True, 32, 20], [True, 31, 20], [True, 50, 20]]],
['heat', 'heat', 'heat', 'defrost', 'defrost']],
['regression: scenario 1',
[3,
3,
[[True, 28, 20],
[True, 28, 50],
[True, 32, 50],
[False, 32, 35],
[True, 60, 20],
[True, 60, 35],
[True, 60, 50],
[True, 60, 50],
[True, 57, 50],
[True, 57, 50],
[True, 60, 60],
[False, 60, 50],
[True, 60, 35],
[True, 33, 50]]],
['heat',
'heat',
'defrost',
'defrost',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'off',
'heat',
'heat']],
['regression: scenario 2',
[4,
4,
[[True, 40, 50],
[True, 40, 35],
[True, 40, 60],
[False, 56, 60],
[True, 56, 35],
[True, 50, 50],
[True, 32, 35],
[True, 32, 51],
[True, 32, 20],
[True, 32, 51],
[True, 32, 60],
[True, 57, 35],
[True, 32, 50],
[True, 32, 35],
[True, 20, 35],
[True, 50, 35],
[True, 57, 35],
[True, 57, 51],
[False, 57, 50]]],
['heat',
'heat',
'heat',
'off',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'defrost',
'defrost',
'defrost',
'defrost',
'heat',
'heat',
'heat',
'off']],
['control: scenario 3',
[3,
6,
[[False, 56, 51],
[True, 56, 35],
[False, 56, 35],
[True, 56, 35],
[True, 56, 35],
[True, 33, 50],
[True, 33, 20],
[True, 33, 50],
[False, 33, 60],
[True, 33, 35],
[True, 33, 35],
[True, 33, 50],
[True, 33, 60],
[True, 33, 35],
[True, 33, 35],
[True, 20, 50],
[True, 20, 51]]],
['off',
'heat',
'off',
'heat',
'heat',
'heat',
'heat',
'heat',
'off',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat']],
['regression: scenario 4',
[4,
4,
[[False, 40, 50],
[True, 40, 50],
[True, 40, 35],
[True, 40, 50],
[True, 40, 50],
[True, 28, 50],
[True, 28, 50],
[False, 28, 60],
[False, 28, 20],
[True, 28, 60],
[True, 28, 50],
[False, 28, 60],
[True, 28, 50],
[True, 28, 35],
[False, 28, 50],
[True, 28, 20],
[True, 28, 51],
[True, 33, 20]]],
['off',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'off',
'off',
'heat',
'defrost',
'defrost',
'defrost',
'defrost',
'off',
'heat',
'heat',
'heat']]],
[['regression: exact termination temperature',
[1, 5, [[True, 30, 20], [True, 56, 20], [True, 57, 20], [False, 30, 20], [True, 30, 20]]],
['defrost', 'defrost', 'heat', 'off', 'defrost']],
['regression: scenario 4',
[3,
3,
[[True, 28, 51],
[True, 28, 35],
[True, 56, 50],
[False, 56, 51],
[True, 56, 50],
[True, 56, 20],
[False, 40, 50],
[True, 40, 20],
[False, 60, 20],
[True, 50, 50],
[True, 56, 35],
[True, 56, 35],
[True, 56, 51],
[True, 32, 60],
[True, 32, 60],
[True, 32, 35],
[True, 32, 60],
[True, 32, 20],
[True, 32, 50],
[True, 32, 60],
[True, 32, 51],
[True, 40, 20],
[True, 40, 20],
[True, 40, 20]]],
['heat',
'heat',
'heat',
'off',
'heat',
'heat',
'off',
'heat',
'off',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'defrost',
'defrost',
'defrost',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat']],
['regression: two defrosts',
[3,
4,
[[True, 30, 20],
[True, 30, 20],
[False, 30, 20],
[True, 32, 20],
[True, 40, 20],
[True, 45, 20],
[True, 57, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20]]],
['heat',
'heat',
'off',
'defrost',
'defrost',
'defrost',
'heat',
'heat',
'heat',
'defrost',
'defrost',
'defrost',
'defrost',
'heat']],
['regression: warm outdoor inhibits',
[2, 3, [[True, 30, 55], [True, 30, 55], [True, 30, 50], [True, 60, 50], [True, 30, 50]]],
['heat', 'heat', 'defrost', 'heat', 'heat']],
['control: dry coil runtime',
[2, 3, [[True, 40, 20], [True, 33, 20], [True, 32, 20], [True, 31, 20], [True, 50, 20]]],
['heat', 'heat', 'heat', 'defrost', 'defrost']],
['regression: scenario 1',
[4,
6,
[[True, 33, 20],
[True, 28, 50],
[True, 56, 51],
[True, 33, 51],
[True, 28, 35],
[False, 28, 50],
[True, 28, 60],
[True, 28, 20],
[True, 40, 50],
[True, 40, 35],
[True, 40, 51],
[True, 40, 50],
[True, 28, 60],
[True, 28, 50],
[True, 50, 35],
[True, 60, 50],
[True, 57, 20],
[True, 40, 50]]],
['heat',
'heat',
'heat',
'heat',
'heat',
'off',
'heat',
'defrost',
'defrost',
'defrost',
'defrost',
'defrost',
'defrost',
'heat',
'heat',
'heat',
'heat',
'heat']],
['control: scenario 2',
[4,
3,
[[True, 32, 20],
[True, 57, 60],
[True, 57, 60],
[True, 57, 20],
[False, 40, 51],
[True, 50, 50],
[True, 50, 51],
[True, 50, 50],
[True, 56, 60],
[True, 40, 20],
[False, 40, 35],
[True, 50, 35],
[False, 50, 51],
[False, 50, 35],
[True, 57, 35],
[True, 57, 20],
[True, 57, 20],
[True, 57, 50],
[True, 57, 60]]],
['heat',
'heat',
'heat',
'heat',
'off',
'heat',
'heat',
'heat',
'heat',
'heat',
'off',
'heat',
'off',
'off',
'heat',
'heat',
'heat',
'heat',
'heat']],
['regression: scenario 3',
[3,
6,
[[True, 20, 60],
[True, 33, 20],
[True, 33, 60],
[True, 33, 51],
[True, 33, 35],
[True, 32, 50],
[True, 32, 35],
[True, 32, 35],
[True, 32, 60],
[True, 32, 60],
[False, 32, 60],
[True, 32, 35],
[False, 32, 50],
[True, 40, 50]]],
['heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'defrost',
'defrost',
'defrost',
'defrost',
'defrost',
'defrost',
'off',
'heat']]],
[['regression: scenario 3',
[5,
4,
[[False, 32, 51],
[False, 32, 50],
[True, 32, 20],
[True, 32, 50],
[True, 32, 50],
[True, 32, 51],
[True, 32, 20],
[True, 56, 50],
[False, 56, 50],
[True, 56, 51],
[True, 56, 51],
[False, 56, 35],
[True, 20, 20],
[True, 20, 35],
[True, 20, 60],
[True, 20, 50]]],
['off',
'off',
'heat',
'heat',
'heat',
'heat',
'defrost',
'defrost',
'defrost',
'defrost',
'heat',
'off',
'heat',
'heat',
'heat',
'heat']],
['regression: scenario 7',
[4,
6,
[[True, 28, 50],
[True, 28, 35],
[True, 28, 50],
[True, 28, 50],
[True, 28, 50],
[True, 28, 50],
[True, 28, 60],
[True, 28, 20],
[True, 32, 60],
[False, 40, 60],
[True, 40, 60],
[True, 40, 35],
[True, 32, 60],
[True, 32, 50]]],
['heat',
'heat',
'heat',
'defrost',
'defrost',
'defrost',
'defrost',
'defrost',
'defrost',
'off',
'heat',
'heat',
'heat',
'heat']],
['regression: two defrosts',
[3,
4,
[[True, 30, 20],
[True, 30, 20],
[False, 30, 20],
[True, 32, 20],
[True, 40, 20],
[True, 45, 20],
[True, 57, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20]]],
['heat',
'heat',
'off',
'defrost',
'defrost',
'defrost',
'heat',
'heat',
'heat',
'defrost',
'defrost',
'defrost',
'defrost',
'heat']],
['regression: warm outdoor inhibits',
[2, 3, [[True, 30, 55], [True, 30, 55], [True, 30, 50], [True, 60, 50], [True, 30, 50]]],
['heat', 'heat', 'defrost', 'heat', 'heat']],
['control: dry coil runtime',
[2, 3, [[True, 40, 20], [True, 33, 20], [True, 32, 20], [True, 31, 20], [True, 50, 20]]],
['heat', 'heat', 'heat', 'defrost', 'defrost']],
['regression: exact termination temperature',
[1, 5, [[True, 30, 20], [True, 56, 20], [True, 57, 20], [False, 30, 20], [True, 30, 20]]],
['defrost', 'defrost', 'heat', 'off', 'defrost']],
['control: scenario 1',
[5,
4,
[[True, 57, 60],
[True, 57, 50],
[True, 57, 50],
[True, 57, 35],
[True, 33, 50],
[True, 33, 50],
[True, 32, 50],
[True, 50, 51],
[True, 50, 51],
[False, 50, 20],
[False, 33, 50],
[True, 56, 20],
[True, 32, 60],
[True, 32, 35],
[True, 32, 20]]],
['heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'off',
'off',
'heat',
'heat',
'heat',
'heat']],
['control: scenario 2',
[4,
6,
[[False, 28, 50],
[True, 28, 51],
[True, 28, 35],
[True, 28, 50],
[True, 57, 50],
[True, 57, 20],
[True, 57, 50],
[True, 57, 50],
[True, 56, 50],
[True, 56, 35],
[True, 56, 51],
[True, 56, 50]]],
['off', 'heat', 'heat', 'heat', 'heat', 'heat', 'heat', 'heat', 'heat', 'heat', 'heat', 'heat']]],
[['regression: scenario 5',
[5,
4,
[[True, 28, 51],
[True, 28, 51],
[False, 28, 50],
[True, 28, 35],
[True, 28, 35],
[True, 40, 60],
[True, 56, 20],
[False, 40, 35],
[False, 40, 50],
[True, 40, 50],
[True, 40, 50],
[True, 40, 35],
[True, 40, 50],
[True, 28, 51],
[False, 28, 50],
[True, 28, 50],
[True, 56, 35],
[True, 33, 35],
[True, 50, 50],
[False, 50, 50],
[True, 50, 50]]],
['heat',
'heat',
'off',
'heat',
'heat',
'heat',
'heat',
'off',
'off',
'heat',
'heat',
'heat',
'heat',
'heat',
'defrost',
'defrost',
'defrost',
'defrost',
'heat',
'off',
'heat']],
['regression: scenario 7',
[3,
4,
[[True, 32, 35],
[True, 32, 50],
[True, 32, 60],
[True, 32, 35],
[True, 56, 20],
[True, 20, 50],
[True, 20, 20],
[False, 20, 35],
[True, 28, 20],
[True, 20, 35],
[True, 20, 20],
[True, 20, 20]]],
['heat',
'heat',
'heat',
'defrost',
'defrost',
'defrost',
'defrost',
'off',
'heat',
'heat',
'defrost',
'defrost']],
['regression: two defrosts',
[3,
4,
[[True, 30, 20],
[True, 30, 20],
[False, 30, 20],
[True, 32, 20],
[True, 40, 20],
[True, 45, 20],
[True, 57, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20],
[True, 20, 20]]],
['heat',
'heat',
'off',
'defrost',
'defrost',
'defrost',
'heat',
'heat',
'heat',
'defrost',
'defrost',
'defrost',
'defrost',
'heat']],
['regression: warm outdoor inhibits',
[2, 3, [[True, 30, 55], [True, 30, 55], [True, 30, 50], [True, 60, 50], [True, 30, 50]]],
['heat', 'heat', 'defrost', 'heat', 'heat']],
['control: dry coil runtime',
[2, 3, [[True, 40, 20], [True, 33, 20], [True, 32, 20], [True, 31, 20], [True, 50, 20]]],
['heat', 'heat', 'heat', 'defrost', 'defrost']],
['regression: exact termination temperature',
[1, 5, [[True, 30, 20], [True, 56, 20], [True, 57, 20], [False, 30, 20], [True, 30, 20]]],
['defrost', 'defrost', 'heat', 'off', 'defrost']],
['control: scenario 1',
[4,
6,
[[True, 32, 50],
[True, 50, 50],
[True, 50, 35],
[True, 57, 51],
[True, 57, 20],
[False, 57, 51],
[True, 57, 50],
[True, 57, 51],
[True, 32, 50],
[True, 32, 51],
[True, 32, 50],
[False, 28, 50]]],
['heat', 'heat', 'heat', 'heat', 'heat', 'off', 'heat', 'heat', 'heat', 'heat', 'defrost', 'defrost']],
['regression: scenario 2',
[3,
4,
[[True, 32, 35],
[True, 32, 35],
[True, 33, 60],
[True, 33, 50],
[True, 33, 60],
[True, 57, 51],
[True, 20, 60],
[True, 20, 50],
[True, 33, 50],
[False, 33, 51],
[False, 33, 20],
[True, 33, 20],
[True, 40, 50],
[True, 40, 50],
[True, 40, 35],
[True, 40, 35],
[True, 40, 51],
[True, 28, 35],
[True, 28, 51],
[True, 33, 60],
[False, 33, 60],
[True, 56, 51],
[True, 56, 60],
[False, 56, 60]]],
['heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'defrost',
'defrost',
'defrost',
'defrost',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'heat',
'off',
'heat',
'heat',
'off']]]]
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: two defrosts | ['heat', 'heat', 'off', 'defrost', 'defrost', 'defrost', 'heat', 'heat', 'heat', 'defrost', 'defrost', 'defrost', 'defrost', 'heat'] | ['heat', 'heat', 'off', 'defrost', 'defrost', 'defrost', 'heat', 'heat', 'heat', 'defrost', 'defrost', 'defrost', 'defrost', 'heat'] | Passed |
| regression: warm outdoor inhibits | ['heat', 'heat', 'defrost', 'heat', 'heat'] | ['heat', 'heat', 'defrost', 'heat', 'heat'] | Passed |
| control: dry coil runtime | ['heat', 'heat', 'heat', 'defrost', 'defrost'] | ['heat', 'heat', 'heat', 'defrost', 'defrost'] | Passed |
| regression: exact termination temperature | ['defrost', 'defrost', 'heat', 'off', 'defrost'] | ['defrost', 'defrost', 'heat', 'off', 'defrost'] | Passed |
| control: scenario 1 | ['heat', 'heat', 'heat', 'heat', 'heat', 'heat', 'off', 'off', 'heat', 'heat', 'heat', 'heat', 'heat', 'heat', 'off', 'heat', 'off', 'off', 'heat', 'off'] | ['heat', 'heat', 'heat', 'heat', 'heat', 'heat', 'off', 'off', 'heat', 'heat', 'heat', 'heat', 'heat', 'heat', 'off', 'heat', 'off', 'off', 'heat', 'off'] | Passed |
| regression: scenario 2 | ['heat', 'off', 'heat', 'heat', 'heat', 'heat', 'heat', 'heat', 'heat', 'off', 'heat', 'defrost', 'defrost', 'defrost', 'heat', 'heat', 'off'] | ['heat', 'off', 'heat', 'heat', 'heat', 'heat', 'heat', 'heat', 'heat', 'off', 'heat', 'defrost', 'defrost', 'defrost', 'heat', 'heat', 'off'] | Passed |
| regression: scenario 3 | ['heat', 'heat', 'heat', 'heat', 'defrost', 'defrost', 'defrost', 'heat', 'heat', 'heat', 'off', 'heat'] | ['heat', 'heat', 'heat', 'heat', 'defrost', 'defrost', 'defrost', 'heat', 'heat', 'heat', 'off', 'heat'] | Passed |
| regression: scenario 4 | ['heat', 'heat', 'heat', 'defrost', 'defrost', 'defrost', 'defrost', 'heat', 'off', 'heat', 'heat', 'off', 'heat', 'off', 'heat', 'heat', 'heat', 'heat', 'defrost', 'defrost'] | ['heat', 'heat', 'heat', 'defrost', 'defrost', 'defrost', 'defrost', 'heat', 'off', 'heat', 'heat', 'off', 'heat', 'off', 'heat', 'heat', 'heat', 'heat', 'defrost', 'defrost'] | Passed |
SHA-256 / 7d8c4731eed824c323249843600022a18b500149bdce88bd7c9857aee1eb0c96
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.832248+00:00.
Case digest / e595040b9aab62459dffa5e1c3a9edfbae3c239ca750f6a6bdc46f10e7ea20b3