FA-92741 / HVAC thermostat control / Open access
Time-proportioning emits one-minute off periods · case 01
Near full demand the burner shuts off for a single minute each cycle.
ROOT CAUSE
The minimum off-time rule is missing.
THE FAILURE
The minimum off-time rule is missing.
Unsuccessful approach: Forcing a 2-minute off time instead cuts capacity when demand is near full.
Case contract
Time-proportioning heating thermostat with a cycles-per-hour setting, sampled per minute. The cycle length is 60 // cph minutes. At each cycle start the error (setpoint - temp) is clamped to 0..band and the on time is error/band of the cycle rounded half up; an on time of 1 minute is extended to the 2-minute minimum, and an off time of 1 minute is eliminated (full on). The output is on for the first on-time minutes of the cycle. Return the heat output 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(cph, band, setpoint, temps):
period = 60 // cph
out = []
on_left = 0
for minute, temp in enumerate(temps):
if minute % period == 0:
err = setpoint - temp
num = max(0, min(err, band)) * period
on = (2 * num + band) // (2 * band)
if 0 < on < 2:
on = 2
on_left = on
out.append(on_left > 0)
if on_left > 0:
on_left -= 1
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: three cycles',
[5,
20,
700,
[690,
690,
690,
690,
690,
690,
690,
690,
690,
690,
690,
690,
700,
700,
700,
700,
700,
700,
700,
700,
700,
700,
700,
700,
681,
681,
681,
681,
681,
681,
681,
681,
681,
681,
681,
681]],
[True,
True,
True,
True,
True,
True,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True]],
['regression: scenario 12',
[9,
30,
700,
[689,
689,
693,
689,
686,
688,
688,
684,
684,
683,
681,
678,
680,
684,
682,
678,
677,
676,
677,
680,
678,
680,
684,
680,
680,
681,
681,
680,
677,
679]],
[True,
True,
False,
False,
False,
False,
True,
True,
False,
False,
False,
False,
True,
True,
True,
True,
False,
False,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
False,
False]],
['control: seven cycles per hour',
[7,
20,
700,
[690,
690,
690,
690,
690,
690,
690,
690,
690,
685,
685,
685,
685,
685,
685,
685,
685,
685,
695,
695,
695,
695,
695,
695,
695,
695,
695]],
[True,
True,
True,
True,
False,
False,
False,
False,
True,
True,
True,
True,
False,
False,
False,
False,
True,
True,
True,
True,
True,
True,
False,
False,
True,
True,
False]],
['control: tiny error',
[6,
30,
700,
[696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698]],
[True,
True,
False,
False,
False,
False,
False,
False,
False,
False,
True,
True,
False,
False,
False,
False,
False,
False,
False,
False]],
['control: above setpoint',
[4,
10,
700,
[705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695]],
[False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
True,
True,
True,
True,
True,
True,
True,
True,
False,
False,
False,
False,
False,
False,
False]],
['control: scenario 1',
[4,
10,
700,
[673,
669,
665,
669,
667,
665,
664,
662,
659,
662,
661,
659,
660,
656,
659,
660,
656,
652,
654,
652,
656,
657,
653,
653,
653,
653,
654,
653,
650,
650,
650,
650,
651,
654,
651,
650,
650,
650,
650]],
[True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True]],
['control: scenario 2',
[6,
30,
700,
[697,
695,
691,
695,
691,
692,
693,
692,
690,
690,
690,
687,
684,
683,
687,
688,
688,
691,
690,
692,
693,
689,
692]],
[True,
True,
False,
False,
False,
False,
False,
False,
False,
False,
True,
True,
True,
False,
False,
False,
False,
False,
False,
False,
True,
True,
False]],
['control: scenario 3',
[7,
30,
700,
[693,
691,
695,
691,
695,
698,
697,
700,
702,
704,
706,
708,
709,
707,
706,
702,
702,
701,
698,
701,
700,
704,
703,
702,
702,
699,
695,
694,
696,
699,
696,
692,
694,
693,
694,
697,
700]],
[True,
True,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
True,
True,
False,
False,
False]]],
[['regression: scenario 37',
[5,
20,
700,
[682,
680,
677,
681,
681,
684,
683,
681,
677,
674,
677,
679,
679,
675,
672,
670,
672,
673,
677,
675,
674,
678,
680,
680,
683,
686,
683,
685,
684,
685,
685]],
[True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True]],
['regression: scenario 49',
[8,
20,
700,
[690,
688,
689,
686,
688,
691,
692,
691,
693,
691,
689,
687,
684,
686,
684,
684,
686,
684,
680,
679,
676,
679,
682,
686,
682]],
[True,
True,
True,
True,
False,
False,
False,
True,
True,
True,
False,
False,
False,
False,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True]],
['regression: three cycles',
[5,
20,
700,
[690,
690,
690,
690,
690,
690,
690,
690,
690,
690,
690,
690,
700,
700,
700,
700,
700,
700,
700,
700,
700,
700,
700,
700,
681,
681,
681,
681,
681,
681,
681,
681,
681,
681,
681,
681]],
[True,
True,
True,
True,
True,
True,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True]],
['control: seven cycles per hour',
[7,
20,
700,
[690,
690,
690,
690,
690,
690,
690,
690,
690,
685,
685,
685,
685,
685,
685,
685,
685,
685,
695,
695,
695,
695,
695,
695,
695,
695,
695]],
[True,
True,
True,
True,
False,
False,
False,
False,
True,
True,
True,
True,
False,
False,
False,
False,
True,
True,
True,
True,
True,
True,
False,
False,
True,
True,
False]],
['control: tiny error',
[6,
30,
700,
[696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698]],
[True,
True,
False,
False,
False,
False,
False,
False,
False,
False,
True,
True,
False,
False,
False,
False,
False,
False,
False,
False]],
['control: above setpoint',
[4,
10,
700,
[705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695]],
[False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
True,
True,
True,
True,
True,
True,
True,
True,
False,
False,
False,
False,
False,
False,
False]],
['control: scenario 1',
[6,
30,
700,
[690,
689,
690,
691,
689,
685,
682,
686,
682,
680,
684,
687,
690,
693,
692,
689,
688,
685,
683,
685,
687,
683,
684,
688,
691,
689,
686,
683,
679,
679,
682,
680,
680,
684]],
[True,
True,
True,
False,
False,
False,
False,
False,
False,
False,
True,
True,
True,
True,
True,
False,
False,
False,
False,
False,
True,
True,
True,
True,
False,
False,
False,
False,
False,
False,
True,
True,
True,
True]],
['control: scenario 2',
[6,
10,
700,
[686,
687,
685,
682,
682,
678,
681,
677,
676,
673,
674,
676,
672,
670,
669,
673,
674,
676,
675,
673,
675,
672,
673,
674,
670,
672]],
[True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True]]],
[['regression: scenario 6',
[7,
10,
700,
[691,
691,
689,
691,
691,
692,
691,
688,
684,
681,
684,
680,
682,
678,
675,
674,
671,
674,
675,
672,
668,
671,
669,
671,
669,
667,
669,
669,
670,
667,
670,
674,
671]],
[True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True]],
['regression: scenario 24',
[9,
30,
700,
[693, 689, 685, 682, 683, 680, 677, 679, 679, 677, 673, 672, 673, 677, 678, 680, 680, 680, 677, 680]],
[True,
True,
False,
False,
False,
False,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True]],
['regression: three cycles',
[5,
20,
700,
[690,
690,
690,
690,
690,
690,
690,
690,
690,
690,
690,
690,
700,
700,
700,
700,
700,
700,
700,
700,
700,
700,
700,
700,
681,
681,
681,
681,
681,
681,
681,
681,
681,
681,
681,
681]],
[True,
True,
True,
True,
True,
True,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True]],
['control: seven cycles per hour',
[7,
20,
700,
[690,
690,
690,
690,
690,
690,
690,
690,
690,
685,
685,
685,
685,
685,
685,
685,
685,
685,
695,
695,
695,
695,
695,
695,
695,
695,
695]],
[True,
True,
True,
True,
False,
False,
False,
False,
True,
True,
True,
True,
False,
False,
False,
False,
True,
True,
True,
True,
True,
True,
False,
False,
True,
True,
False]],
['control: tiny error',
[6,
30,
700,
[696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698]],
[True,
True,
False,
False,
False,
False,
False,
False,
False,
False,
True,
True,
False,
False,
False,
False,
False,
False,
False,
False]],
['control: above setpoint',
[4,
10,
700,
[705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695]],
[False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
True,
True,
True,
True,
True,
True,
True,
True,
False,
False,
False,
False,
False,
False,
False]],
['regression: scenario 1',
[7,
20,
700,
[688,
691,
689,
691,
692,
691,
687,
691,
692,
691,
695,
695,
692,
689,
688,
684,
682,
681,
679,
678,
682,
682,
680,
682,
686,
689,
687,
687,
690,
686,
687,
691]],
[True,
True,
True,
True,
True,
False,
False,
False,
True,
True,
True,
False,
False,
False,
False,
False,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
False,
False]],
['control: scenario 2',
[9,
20,
700,
[702,
703,
707,
703,
700,
697,
699,
698,
696,
693,
696,
695,
694,
690,
692,
695,
697,
700,
698,
699,
701,
704,
708,
712,
710,
709,
713,
709,
710,
714,
711,
711,
707,
706,
706]],
[False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
True,
True,
False,
False,
False,
False,
True,
True,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False]]],
[['regression: scenario 60',
[7,
20,
700,
[678,
681,
677,
678,
681,
681,
680,
684,
682,
681,
680,
678,
674,
673,
669,
671,
668,
671,
672,
671,
670,
667,
669,
666,
662,
658,
656]],
[True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True]],
['regression: three cycles',
[5,
20,
700,
[690,
690,
690,
690,
690,
690,
690,
690,
690,
690,
690,
690,
700,
700,
700,
700,
700,
700,
700,
700,
700,
700,
700,
700,
681,
681,
681,
681,
681,
681,
681,
681,
681,
681,
681,
681]],
[True,
True,
True,
True,
True,
True,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True]],
['control: seven cycles per hour',
[7,
20,
700,
[690,
690,
690,
690,
690,
690,
690,
690,
690,
685,
685,
685,
685,
685,
685,
685,
685,
685,
695,
695,
695,
695,
695,
695,
695,
695,
695]],
[True,
True,
True,
True,
False,
False,
False,
False,
True,
True,
True,
True,
False,
False,
False,
False,
True,
True,
True,
True,
True,
True,
False,
False,
True,
True,
False]],
['control: tiny error',
[6,
30,
700,
[696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698]],
[True,
True,
False,
False,
False,
False,
False,
False,
False,
False,
True,
True,
False,
False,
False,
False,
False,
False,
False,
False]],
['control: above setpoint',
[4,
10,
700,
[705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695]],
[False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
True,
True,
True,
True,
True,
True,
True,
True,
False,
False,
False,
False,
False,
False,
False]],
['control: scenario 1',
[6,
10,
700,
[702,
699,
703,
707,
704,
708,
705,
701,
698,
700,
703,
703,
700,
697,
696,
697,
697,
701,
703,
703,
704,
705,
708,
704,
706,
705,
702,
706,
707,
704,
708,
707,
703,
706,
707,
703,
703,
706,
707,
706]],
[False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False]],
['control: scenario 2',
[3,
20,
700,
[682, 683, 684, 687, 687, 686, 682, 683, 680, 676, 680, 683, 679, 675, 674, 671, 671, 672, 670, 672]],
[True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
False,
False]],
['control: scenario 3',
[4,
10,
700,
[669,
665,
661,
664,
661,
660,
663,
662,
660,
664,
667,
671,
672,
671,
670,
673,
676,
677,
680,
677,
677,
680,
677,
680,
677,
673,
676,
677,
679,
678,
682,
683,
680,
679,
683,
682,
686]],
[True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True]]],
[['regression: scenario 20',
[5,
20,
700,
[681,
678,
678,
675,
675,
672,
669,
665,
666,
667,
664,
668,
671,
671,
669,
665,
668,
671,
674,
676,
680,
681]],
[True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True]],
['regression: scenario 25',
[8,
20,
700,
[682,
684,
684,
680,
678,
678,
675,
678,
680,
683,
684,
680,
678,
679,
681,
678,
678,
675,
678,
680,
681,
680,
679,
679,
676,
675,
678,
682,
684,
685,
683,
687,
689,
685,
689,
688,
687,
690,
690]],
[True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True]],
['regression: three cycles',
[5,
20,
700,
[690,
690,
690,
690,
690,
690,
690,
690,
690,
690,
690,
690,
700,
700,
700,
700,
700,
700,
700,
700,
700,
700,
700,
700,
681,
681,
681,
681,
681,
681,
681,
681,
681,
681,
681,
681]],
[True,
True,
True,
True,
True,
True,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True]],
['control: seven cycles per hour',
[7,
20,
700,
[690,
690,
690,
690,
690,
690,
690,
690,
690,
685,
685,
685,
685,
685,
685,
685,
685,
685,
695,
695,
695,
695,
695,
695,
695,
695,
695]],
[True,
True,
True,
True,
False,
False,
False,
False,
True,
True,
True,
True,
False,
False,
False,
False,
True,
True,
True,
True,
True,
True,
False,
False,
True,
True,
False]],
['control: tiny error',
[6,
30,
700,
[696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698]],
[True,
True,
False,
False,
False,
False,
False,
False,
False,
False,
True,
True,
False,
False,
False,
False,
False,
False,
False,
False]],
['control: above setpoint',
[4,
10,
700,
[705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695]],
[False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
True,
True,
True,
True,
True,
True,
True,
True,
False,
False,
False,
False,
False,
False,
False]],
['control: scenario 1',
[5,
10,
700,
[698,
700,
702,
701,
700,
700,
699,
697,
694,
696,
698,
694,
697,
697,
694,
698,
700,
698,
699,
700,
703,
707,
708,
706,
708,
712,
710,
706,
702,
700,
696,
696,
692]],
[True,
True,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
True,
True,
True,
True,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False]],
['control: scenario 2',
[3,
10,
700,
[669,
665,
665,
665,
666,
665,
663,
665,
667,
665,
667,
663,
663,
667,
667,
668,
664,
664,
664,
663,
661,
661,
661,
664,
666,
664,
668]],
[True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True]]]]
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: three cycles | [True, True, True, True, True, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, True, True, True, True, True, True, True, True, True, True, False] | [True, True, True, True, True, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, True, True, True, True, True, True, True, True, True, True, True] | Failed |
| regression: scenario 12 | [True, True, False, False, False, False, True, True, False, False, False, False, True, True, True, True, False, False, True, True, True, True, True, False, True, True, True, True, False, False] | [True, True, False, False, False, False, True, True, False, False, False, False, True, True, True, True, False, False, True, True, True, True, True, True, True, True, True, True, False, False] | Failed |
| control: seven cycles per hour | [True, True, True, True, False, False, False, False, True, True, True, True, False, False, False, False, True, True, True, True, True, True, False, False, True, True, False] | [True, True, True, True, False, False, False, False, True, True, True, True, False, False, False, False, True, True, True, True, True, True, False, False, True, True, False] | Passed |
| control: tiny error | [True, True, False, False, False, False, False, False, False, False, True, True, False, False, False, False, False, False, False, False] | [True, True, False, False, False, False, False, False, False, False, True, True, False, False, False, False, False, False, False, False] | Passed |
| control: above setpoint | [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, True, True, True, True, True, True, True, False, False, False, False, False, False, False] | [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, True, True, True, True, True, True, True, False, False, False, False, False, False, False] | Passed |
| control: scenario 1 | [True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True] | [True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True] | Passed |
| control: scenario 2 | [True, True, False, False, False, False, False, False, False, False, True, True, True, False, False, False, False, False, False, False, True, True, False] | [True, True, False, False, False, False, False, False, False, False, True, True, True, False, False, False, False, False, False, False, True, True, False] | Passed |
| control: scenario 3 | [True, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, True, False, False, False] | [True, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, True, False, False, False] | Passed |
SHA-256 / d2736c201c7963c7644867251b778f186df7250988baa00a2fdfa08f402d9c91
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(cph, band, setpoint, temps):
period = 60 // cph
out = []
on_left = 0
for minute, temp in enumerate(temps):
if minute % period == 0:
err = setpoint - temp
num = max(0, min(err, band)) * period
on = (2 * num + band) // (2 * band)
if 0 < on < 2:
on = 2
if 0 < period - on < 2:
on = period - 2
on_left = on
out.append(on_left > 0)
if on_left > 0:
on_left -= 1
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: three cycles',
[5,
20,
700,
[690,
690,
690,
690,
690,
690,
690,
690,
690,
690,
690,
690,
700,
700,
700,
700,
700,
700,
700,
700,
700,
700,
700,
700,
681,
681,
681,
681,
681,
681,
681,
681,
681,
681,
681,
681]],
[True,
True,
True,
True,
True,
True,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True]],
['regression: scenario 12',
[9,
30,
700,
[689,
689,
693,
689,
686,
688,
688,
684,
684,
683,
681,
678,
680,
684,
682,
678,
677,
676,
677,
680,
678,
680,
684,
680,
680,
681,
681,
680,
677,
679]],
[True,
True,
False,
False,
False,
False,
True,
True,
False,
False,
False,
False,
True,
True,
True,
True,
False,
False,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
False,
False]],
['control: seven cycles per hour',
[7,
20,
700,
[690,
690,
690,
690,
690,
690,
690,
690,
690,
685,
685,
685,
685,
685,
685,
685,
685,
685,
695,
695,
695,
695,
695,
695,
695,
695,
695]],
[True,
True,
True,
True,
False,
False,
False,
False,
True,
True,
True,
True,
False,
False,
False,
False,
True,
True,
True,
True,
True,
True,
False,
False,
True,
True,
False]],
['control: tiny error',
[6,
30,
700,
[696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698]],
[True,
True,
False,
False,
False,
False,
False,
False,
False,
False,
True,
True,
False,
False,
False,
False,
False,
False,
False,
False]],
['control: above setpoint',
[4,
10,
700,
[705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695]],
[False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
True,
True,
True,
True,
True,
True,
True,
True,
False,
False,
False,
False,
False,
False,
False]],
['control: scenario 1',
[4,
10,
700,
[673,
669,
665,
669,
667,
665,
664,
662,
659,
662,
661,
659,
660,
656,
659,
660,
656,
652,
654,
652,
656,
657,
653,
653,
653,
653,
654,
653,
650,
650,
650,
650,
651,
654,
651,
650,
650,
650,
650]],
[True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True]],
['control: scenario 2',
[6,
30,
700,
[697,
695,
691,
695,
691,
692,
693,
692,
690,
690,
690,
687,
684,
683,
687,
688,
688,
691,
690,
692,
693,
689,
692]],
[True,
True,
False,
False,
False,
False,
False,
False,
False,
False,
True,
True,
True,
False,
False,
False,
False,
False,
False,
False,
True,
True,
False]],
['control: scenario 3',
[7,
30,
700,
[693,
691,
695,
691,
695,
698,
697,
700,
702,
704,
706,
708,
709,
707,
706,
702,
702,
701,
698,
701,
700,
704,
703,
702,
702,
699,
695,
694,
696,
699,
696,
692,
694,
693,
694,
697,
700]],
[True,
True,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
True,
True,
False,
False,
False]]],
[['regression: scenario 37',
[5,
20,
700,
[682,
680,
677,
681,
681,
684,
683,
681,
677,
674,
677,
679,
679,
675,
672,
670,
672,
673,
677,
675,
674,
678,
680,
680,
683,
686,
683,
685,
684,
685,
685]],
[True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True]],
['regression: scenario 49',
[8,
20,
700,
[690,
688,
689,
686,
688,
691,
692,
691,
693,
691,
689,
687,
684,
686,
684,
684,
686,
684,
680,
679,
676,
679,
682,
686,
682]],
[True,
True,
True,
True,
False,
False,
False,
True,
True,
True,
False,
False,
False,
False,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True]],
['regression: three cycles',
[5,
20,
700,
[690,
690,
690,
690,
690,
690,
690,
690,
690,
690,
690,
690,
700,
700,
700,
700,
700,
700,
700,
700,
700,
700,
700,
700,
681,
681,
681,
681,
681,
681,
681,
681,
681,
681,
681,
681]],
[True,
True,
True,
True,
True,
True,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True]],
['control: seven cycles per hour',
[7,
20,
700,
[690,
690,
690,
690,
690,
690,
690,
690,
690,
685,
685,
685,
685,
685,
685,
685,
685,
685,
695,
695,
695,
695,
695,
695,
695,
695,
695]],
[True,
True,
True,
True,
False,
False,
False,
False,
True,
True,
True,
True,
False,
False,
False,
False,
True,
True,
True,
True,
True,
True,
False,
False,
True,
True,
False]],
['control: tiny error',
[6,
30,
700,
[696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698]],
[True,
True,
False,
False,
False,
False,
False,
False,
False,
False,
True,
True,
False,
False,
False,
False,
False,
False,
False,
False]],
['control: above setpoint',
[4,
10,
700,
[705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695]],
[False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
True,
True,
True,
True,
True,
True,
True,
True,
False,
False,
False,
False,
False,
False,
False]],
['control: scenario 1',
[6,
30,
700,
[690,
689,
690,
691,
689,
685,
682,
686,
682,
680,
684,
687,
690,
693,
692,
689,
688,
685,
683,
685,
687,
683,
684,
688,
691,
689,
686,
683,
679,
679,
682,
680,
680,
684]],
[True,
True,
True,
False,
False,
False,
False,
False,
False,
False,
True,
True,
True,
True,
True,
False,
False,
False,
False,
False,
True,
True,
True,
True,
False,
False,
False,
False,
False,
False,
True,
True,
True,
True]],
['control: scenario 2',
[6,
10,
700,
[686,
687,
685,
682,
682,
678,
681,
677,
676,
673,
674,
676,
672,
670,
669,
673,
674,
676,
675,
673,
675,
672,
673,
674,
670,
672]],
[True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True]]],
[['regression: scenario 6',
[7,
10,
700,
[691,
691,
689,
691,
691,
692,
691,
688,
684,
681,
684,
680,
682,
678,
675,
674,
671,
674,
675,
672,
668,
671,
669,
671,
669,
667,
669,
669,
670,
667,
670,
674,
671]],
[True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True]],
['regression: scenario 24',
[9,
30,
700,
[693, 689, 685, 682, 683, 680, 677, 679, 679, 677, 673, 672, 673, 677, 678, 680, 680, 680, 677, 680]],
[True,
True,
False,
False,
False,
False,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True]],
['regression: three cycles',
[5,
20,
700,
[690,
690,
690,
690,
690,
690,
690,
690,
690,
690,
690,
690,
700,
700,
700,
700,
700,
700,
700,
700,
700,
700,
700,
700,
681,
681,
681,
681,
681,
681,
681,
681,
681,
681,
681,
681]],
[True,
True,
True,
True,
True,
True,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True]],
['control: seven cycles per hour',
[7,
20,
700,
[690,
690,
690,
690,
690,
690,
690,
690,
690,
685,
685,
685,
685,
685,
685,
685,
685,
685,
695,
695,
695,
695,
695,
695,
695,
695,
695]],
[True,
True,
True,
True,
False,
False,
False,
False,
True,
True,
True,
True,
False,
False,
False,
False,
True,
True,
True,
True,
True,
True,
False,
False,
True,
True,
False]],
['control: tiny error',
[6,
30,
700,
[696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698]],
[True,
True,
False,
False,
False,
False,
False,
False,
False,
False,
True,
True,
False,
False,
False,
False,
False,
False,
False,
False]],
['control: above setpoint',
[4,
10,
700,
[705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695]],
[False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
True,
True,
True,
True,
True,
True,
True,
True,
False,
False,
False,
False,
False,
False,
False]],
['regression: scenario 1',
[7,
20,
700,
[688,
691,
689,
691,
692,
691,
687,
691,
692,
691,
695,
695,
692,
689,
688,
684,
682,
681,
679,
678,
682,
682,
680,
682,
686,
689,
687,
687,
690,
686,
687,
691]],
[True,
True,
True,
True,
True,
False,
False,
False,
True,
True,
True,
False,
False,
False,
False,
False,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
False,
False]],
['control: scenario 2',
[9,
20,
700,
[702,
703,
707,
703,
700,
697,
699,
698,
696,
693,
696,
695,
694,
690,
692,
695,
697,
700,
698,
699,
701,
704,
708,
712,
710,
709,
713,
709,
710,
714,
711,
711,
707,
706,
706]],
[False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
True,
True,
False,
False,
False,
False,
True,
True,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False]]],
[['regression: scenario 60',
[7,
20,
700,
[678,
681,
677,
678,
681,
681,
680,
684,
682,
681,
680,
678,
674,
673,
669,
671,
668,
671,
672,
671,
670,
667,
669,
666,
662,
658,
656]],
[True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True]],
['regression: three cycles',
[5,
20,
700,
[690,
690,
690,
690,
690,
690,
690,
690,
690,
690,
690,
690,
700,
700,
700,
700,
700,
700,
700,
700,
700,
700,
700,
700,
681,
681,
681,
681,
681,
681,
681,
681,
681,
681,
681,
681]],
[True,
True,
True,
True,
True,
True,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True]],
['control: seven cycles per hour',
[7,
20,
700,
[690,
690,
690,
690,
690,
690,
690,
690,
690,
685,
685,
685,
685,
685,
685,
685,
685,
685,
695,
695,
695,
695,
695,
695,
695,
695,
695]],
[True,
True,
True,
True,
False,
False,
False,
False,
True,
True,
True,
True,
False,
False,
False,
False,
True,
True,
True,
True,
True,
True,
False,
False,
True,
True,
False]],
['control: tiny error',
[6,
30,
700,
[696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698]],
[True,
True,
False,
False,
False,
False,
False,
False,
False,
False,
True,
True,
False,
False,
False,
False,
False,
False,
False,
False]],
['control: above setpoint',
[4,
10,
700,
[705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695]],
[False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
True,
True,
True,
True,
True,
True,
True,
True,
False,
False,
False,
False,
False,
False,
False]],
['control: scenario 1',
[6,
10,
700,
[702,
699,
703,
707,
704,
708,
705,
701,
698,
700,
703,
703,
700,
697,
696,
697,
697,
701,
703,
703,
704,
705,
708,
704,
706,
705,
702,
706,
707,
704,
708,
707,
703,
706,
707,
703,
703,
706,
707,
706]],
[False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False]],
['control: scenario 2',
[3,
20,
700,
[682, 683, 684, 687, 687, 686, 682, 683, 680, 676, 680, 683, 679, 675, 674, 671, 671, 672, 670, 672]],
[True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
False,
False]],
['control: scenario 3',
[4,
10,
700,
[669,
665,
661,
664,
661,
660,
663,
662,
660,
664,
667,
671,
672,
671,
670,
673,
676,
677,
680,
677,
677,
680,
677,
680,
677,
673,
676,
677,
679,
678,
682,
683,
680,
679,
683,
682,
686]],
[True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True]]],
[['regression: scenario 20',
[5,
20,
700,
[681,
678,
678,
675,
675,
672,
669,
665,
666,
667,
664,
668,
671,
671,
669,
665,
668,
671,
674,
676,
680,
681]],
[True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True]],
['regression: scenario 25',
[8,
20,
700,
[682,
684,
684,
680,
678,
678,
675,
678,
680,
683,
684,
680,
678,
679,
681,
678,
678,
675,
678,
680,
681,
680,
679,
679,
676,
675,
678,
682,
684,
685,
683,
687,
689,
685,
689,
688,
687,
690,
690]],
[True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True]],
['regression: three cycles',
[5,
20,
700,
[690,
690,
690,
690,
690,
690,
690,
690,
690,
690,
690,
690,
700,
700,
700,
700,
700,
700,
700,
700,
700,
700,
700,
700,
681,
681,
681,
681,
681,
681,
681,
681,
681,
681,
681,
681]],
[True,
True,
True,
True,
True,
True,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True]],
['control: seven cycles per hour',
[7,
20,
700,
[690,
690,
690,
690,
690,
690,
690,
690,
690,
685,
685,
685,
685,
685,
685,
685,
685,
685,
695,
695,
695,
695,
695,
695,
695,
695,
695]],
[True,
True,
True,
True,
False,
False,
False,
False,
True,
True,
True,
True,
False,
False,
False,
False,
True,
True,
True,
True,
True,
True,
False,
False,
True,
True,
False]],
['control: tiny error',
[6,
30,
700,
[696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698]],
[True,
True,
False,
False,
False,
False,
False,
False,
False,
False,
True,
True,
False,
False,
False,
False,
False,
False,
False,
False]],
['control: above setpoint',
[4,
10,
700,
[705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
705,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695,
695]],
[False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
True,
True,
True,
True,
True,
True,
True,
True,
False,
False,
False,
False,
False,
False,
False]],
['control: scenario 1',
[5,
10,
700,
[698,
700,
702,
701,
700,
700,
699,
697,
694,
696,
698,
694,
697,
697,
694,
698,
700,
698,
699,
700,
703,
707,
708,
706,
708,
712,
710,
706,
702,
700,
696,
696,
692]],
[True,
True,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
True,
True,
True,
True,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False]],
['control: scenario 2',
[3,
10,
700,
[669,
665,
665,
665,
666,
665,
663,
665,
667,
665,
667,
663,
663,
667,
667,
668,
664,
664,
664,
663,
661,
661,
661,
664,
666,
664,
668]],
[True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True,
True]]]]
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: three cycles | [True, True, True, True, True, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, True, True, True, True, True, True, True, True, True, False, False] | [True, True, True, True, True, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, True, True, True, True, True, True, True, True, True, True, True] | Failed |
| regression: scenario 12 | [True, True, False, False, False, False, True, True, False, False, False, False, True, True, True, True, False, False, True, True, True, True, False, False, True, True, True, True, False, False] | [True, True, False, False, False, False, True, True, False, False, False, False, True, True, True, True, False, False, True, True, True, True, True, True, True, True, True, True, False, False] | Failed |
| control: seven cycles per hour | [True, True, True, True, False, False, False, False, True, True, True, True, False, False, False, False, True, True, True, True, True, True, False, False, True, True, False] | [True, True, True, True, False, False, False, False, True, True, True, True, False, False, False, False, True, True, True, True, True, True, False, False, True, True, False] | Passed |
| control: tiny error | [True, True, False, False, False, False, False, False, False, False, True, True, False, False, False, False, False, False, False, False] | [True, True, False, False, False, False, False, False, False, False, True, True, False, False, False, False, False, False, False, False] | Passed |
| control: above setpoint | [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, True, True, True, True, True, True, True, False, False, False, False, False, False, False] | [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, True, True, True, True, True, True, True, False, False, False, False, False, False, False] | Passed |
| control: scenario 1 | [True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True] | [True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True] | Passed |
| control: scenario 2 | [True, True, False, False, False, False, False, False, False, False, True, True, True, False, False, False, False, False, False, False, True, True, False] | [True, True, False, False, False, False, False, False, False, False, True, True, True, False, False, False, False, False, False, False, True, True, False] | Passed |
| control: scenario 3 | [True, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, True, False, False, False] | [True, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, True, False, False, False] | Passed |
SHA-256 / ec2022009af28b412d9ae7341bf1e091d38d6fa6588abf4b39fcaed46a16968e
HELD IN THE MEMBER ARCHIVE
The verified repair and its recorded checks are member-only.
This mechanism has 8 recorded checks per implementation. The open-access tier publishes the failure and the unsuccessful fix; the repaired source that passes every check, and the observations that prove it, are available to members.
Every case sharing this mechanism uses the same contract and the same repair, so this one record is held back for all of them.
Member access is invitation-based. Sign in with your invited account to inspect the repair.
Sign in to the archive ↗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:48.616853+00:00.
Case digest / fc18f502d4d86a67e3baf789fdcbe5c26a1fd262032eb26f5f9869e88e4a601f