FAILURE MAP
← Case archive

FA-92716 / HVAC thermostat control / Open access

DCV damper opens to target in a single step · case 01

The damper slams open when a meeting room fills, upsetting mixed-air temperature.

Verified by executionVariant 1 · 8 checks per implementationDownload source bundle ↓JSON ↗

ROOT CAUSE

The opening path assigns the target without a rate limit.

VERIFIED REPAIR

Open by at most 10 points per sample.

Unsuccessful approach: Adding 10 points without stopping at the target overshoots it.

Case contract

CO2 demand-controlled ventilation per sample; samples are [co2_ppm, occupied]. Unoccupied target is 0%. Occupied: min_pos at or below co2_low, max_pos at or above co2_high, and linear in between rounded half up to whole percent. The damper moves toward the target by at most 10 percentage points per sample in either direction. Return the damper position per sample.

Why this case matters

Residential and light-commercial thermostats make these decisions sample by sample; each defect changes equipment calls in a way that shows up as short cycling, comfort complaints or equipment stress.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(settings, samples):
    pos = 0
    out = []
    for co2, occupied in samples:
        if not occupied:
            target = 0
        elif co2 <= settings['co2_low']:
            target = settings['min_pos']
        elif co2 >= settings['co2_high']:
            target = settings['max_pos']
        else:
            span = settings['co2_high'] - settings['co2_low']
            num = (co2 - settings['co2_low']) * (settings['max_pos'] - settings['min_pos'])
            target = settings['min_pos'] + (2 * num + span) // (2 * span)
        if target > pos:
            pos = target
        else:
            pos = max(target, pos - 10)
        out.append(pos)
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: occupied day',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[650, True],
     [650, True],
     [900, True],
     [900, True],
     [900, True],
     [900, True],
     [1300, True],
     [1300, False]]],
   [10, 20, 30, 40, 50, 50, 60, 50]],
  ['regression: moderate co2',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[800, True], [800, True], [800, True], [800, True], [800, True], [750, True], [750, True]]],
   [10, 20, 30, 35, 35, 28, 28]],
  ['regression: crowd arrives',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, False],
     [1500, False]]],
   [10, 20, 30, 40, 50, 60, 70, 80, 80, 70, 60]],
  ['regression: unoccupied high co2',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[1200, False], [1200, False], [1200, True]]],
   [0, 0, 10]],
  ['regression: scenario 1',
   [{'min_pos': 20, 'max_pos': 100, 'co2_low': 600, 'co2_high': 1000},
    [[424, True], [551, True], [655, True], [713, True], [740, True], [769, True], [840, True], [858, True]]],
   [10, 20, 30, 40, 48, 54, 64, 72]],
  ['regression: scenario 2',
   [{'min_pos': 10, 'max_pos': 60, 'co2_low': 700, 'co2_high': 1000},
    [[1150, True],
     [1009, True],
     [1044, True],
     [985, False],
     [1131, False],
     [982, True],
     [895, True],
     [828, False]]],
   [10, 20, 30, 20, 10, 20, 30, 20]],
  ['regression: scenario 3',
   [{'min_pos': 15, 'max_pos': 80, 'co2_low': 600, 'co2_high': 1000},
    [[1300, False],
     [1254, True],
     [1354, True],
     [1400, False],
     [1471, True],
     [1498, True],
     [1500, False],
     [1488, True],
     [1500, False],
     [1500, True],
     [1500, False],
     [1464, True]]],
   [0, 10, 20, 10, 20, 30, 20, 30, 20, 30, 20, 30]],
  ['regression: scenario 4',
   [{'min_pos': 10, 'max_pos': 100, 'co2_low': 700, 'co2_high': 1000},
    [[802, True],
     [856, True],
     [954, True],
     [853, True],
     [816, True],
     [847, False],
     [865, True],
     [741, True],
     [680, True],
     [592, True],
     [485, True]]],
   [10, 20, 30, 40, 45, 35, 45, 35, 25, 15, 10]]],
 [['regression: crowd arrives',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, False],
     [1500, False]]],
   [10, 20, 30, 40, 50, 60, 70, 80, 80, 70, 60]],
  ['regression: scenario 2',
   [{'min_pos': 15, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1000},
    [[775, True],
     [743, True],
     [851, True],
     [853, True],
     [893, True],
     [872, True],
     [870, True],
     [781, False],
     [813, True],
     [851, True],
     [955, True]]],
   [10, 20, 30, 40, 50, 52, 52, 42, 39, 48, 58]],
  ['regression: occupied day',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[650, True],
     [650, True],
     [900, True],
     [900, True],
     [900, True],
     [900, True],
     [1300, True],
     [1300, False]]],
   [10, 20, 30, 40, 50, 50, 60, 50]],
  ['regression: moderate co2',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[800, True], [800, True], [800, True], [800, True], [800, True], [750, True], [750, True]]],
   [10, 20, 30, 35, 35, 28, 28]],
  ['regression: unoccupied high co2',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[1200, False], [1200, False], [1200, True]]],
   [0, 0, 10]],
  ['regression: scenario 1',
   [{'min_pos': 20, 'max_pos': 100, 'co2_low': 600, 'co2_high': 1200},
    [[631, True],
     [545, True],
     [465, True],
     [503, True],
     [568, True],
     [550, True],
     [450, False],
     [459, True],
     [434, True],
     [539, True],
     [480, True],
     [462, False],
     [400, True],
     [400, True]]],
   [10, 20, 20, 20, 20, 20, 10, 20, 20, 20, 20, 10, 20, 20]],
  ['regression: scenario 3',
   [{'min_pos': 10, 'max_pos': 100, 'co2_low': 700, 'co2_high': 1200},
    [[1109, True],
     [1033, False],
     [1170, False],
     [1235, True],
     [1208, True],
     [1230, True],
     [1178, True],
     [1182, True],
     [1206, False],
     [1261, True],
     [1328, True],
     [1474, True]]],
   [10, 0, 0, 10, 20, 30, 40, 50, 40, 50, 60, 70]],
  ['regression: scenario 4',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 600, 'co2_high': 1200},
    [[1028, True],
     [998, True],
     [1129, True],
     [1164, True],
     [1200, True],
     [1276, False],
     [1335, True],
     [1192, True],
     [1105, True],
     [1194, True],
     [1207, True]]],
   [10, 20, 30, 40, 50, 40, 50, 60, 70, 79, 80]]],
 [['regression: moderate co2',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[800, True], [800, True], [800, True], [800, True], [800, True], [750, True], [750, True]]],
   [10, 20, 30, 35, 35, 28, 28]],
  ['regression: scenario 7',
   [{'min_pos': 15, 'max_pos': 100, 'co2_low': 700, 'co2_high': 1200},
    [[675, True],
     [553, False],
     [630, True],
     [746, True],
     [799, False],
     [713, True],
     [783, True],
     [718, True]]],
   [10, 0, 10, 20, 10, 17, 27, 18]],
  ['regression: occupied day',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[650, True],
     [650, True],
     [900, True],
     [900, True],
     [900, True],
     [900, True],
     [1300, True],
     [1300, False]]],
   [10, 20, 30, 40, 50, 50, 60, 50]],
  ['regression: crowd arrives',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, False],
     [1500, False]]],
   [10, 20, 30, 40, 50, 60, 70, 80, 80, 70, 60]],
  ['regression: unoccupied high co2',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[1200, False], [1200, False], [1200, True]]],
   [0, 0, 10]],
  ['control: scenario 1',
   [{'min_pos': 10, 'max_pos': 60, 'co2_low': 700, 'co2_high': 1000},
    [[523, True],
     [506, True],
     [620, False],
     [668, True],
     [557, True],
     [453, True],
     [400, True],
     [400, True],
     [409, True],
     [455, False],
     [443, False],
     [561, True]]],
   [10, 10, 0, 10, 10, 10, 10, 10, 10, 0, 0, 10]],
  ['regression: scenario 2',
   [{'min_pos': 20, 'max_pos': 60, 'co2_low': 600, 'co2_high': 1000},
    [[640, True],
     [668, False],
     [658, True],
     [602, False],
     [640, False],
     [525, False],
     [604, True],
     [456, True],
     [591, True],
     [611, True]]],
   [10, 0, 10, 0, 0, 0, 10, 20, 20, 21]],
  ['regression: scenario 3',
   [{'min_pos': 20, 'max_pos': 60, 'co2_low': 700, 'co2_high': 1000},
    [[1018, True],
     [1052, True],
     [988, True],
     [1071, True],
     [1109, True],
     [1124, True],
     [1196, True],
     [1221, False],
     [1203, True]]],
   [10, 20, 30, 40, 50, 60, 60, 50, 60]]],
 [['regression: unoccupied high co2',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[1200, False], [1200, False], [1200, True]]],
   [0, 0, 10]],
  ['regression: scenario 6',
   [{'min_pos': 15, 'max_pos': 60, 'co2_low': 600, 'co2_high': 1200},
    [[1241, True],
     [1251, True],
     [1129, True],
     [1007, True],
     [865, True],
     [796, True],
     [856, True],
     [908, True],
     [822, True],
     [747, True],
     [773, True],
     [762, True],
     [674, True]]],
   [10, 20, 30, 40, 35, 30, 34, 38, 32, 26, 28, 27, 21]],
  ['regression: occupied day',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[650, True],
     [650, True],
     [900, True],
     [900, True],
     [900, True],
     [900, True],
     [1300, True],
     [1300, False]]],
   [10, 20, 30, 40, 50, 50, 60, 50]],
  ['regression: crowd arrives',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, False],
     [1500, False]]],
   [10, 20, 30, 40, 50, 60, 70, 80, 80, 70, 60]],
  ['regression: moderate co2',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[800, True], [800, True], [800, True], [800, True], [800, True], [750, True], [750, True]]],
   [10, 20, 30, 35, 35, 28, 28]],
  ['regression: scenario 1',
   [{'min_pos': 15, 'max_pos': 60, 'co2_low': 700, 'co2_high': 1200},
    [[1121, True],
     [1144, True],
     [1172, True],
     [1223, True],
     [1138, True],
     [1273, True],
     [1319, True],
     [1227, False],
     [1253, True]]],
   [10, 20, 30, 40, 50, 60, 60, 50, 60]],
  ['regression: scenario 2',
   [{'min_pos': 20, 'max_pos': 60, 'co2_low': 600, 'co2_high': 1200},
    [[570, True],
     [539, True],
     [432, True],
     [498, True],
     [536, True],
     [559, True],
     [607, True],
     [706, False],
     [703, False],
     [767, True],
     [618, False],
     [742, False],
     [796, True]]],
   [10, 20, 20, 20, 20, 20, 20, 10, 0, 10, 0, 0, 10]],
  ['regression: scenario 3',
   [{'min_pos': 20, 'max_pos': 60, 'co2_low': 600, 'co2_high': 1000},
    [[853, True],
     [828, True],
     [845, True],
     [890, False],
     [973, True],
     [895, True],
     [751, True],
     [855, True],
     [839, False],
     [909, True],
     [1031, True],
     [926, True],
     [1032, True]]],
   [10, 20, 30, 20, 30, 40, 35, 45, 35, 45, 55, 53, 60]]],
 [['regression: scenario 1',
   [{'min_pos': 15, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1200},
    [[1383, True],
     [1500, True],
     [1500, True],
     [1483, True],
     [1492, True],
     [1500, False],
     [1500, True],
     [1500, True],
     [1500, False],
     [1465, True],
     [1443, False],
     [1458, False],
     [1430, True]]],
   [10, 20, 30, 40, 50, 40, 50, 60, 50, 60, 50, 40, 50]],
  ['regression: scenario 10',
   [{'min_pos': 15, 'max_pos': 60, 'co2_low': 700, 'co2_high': 1200},
    [[1256, False],
     [1206, True],
     [1065, True],
     [1046, True],
     [1037, True],
     [1140, True],
     [1055, False],
     [1023, True],
     [930, True],
     [795, True],
     [685, False]]],
   [0, 10, 20, 30, 40, 50, 40, 44, 36, 26, 16]],
  ['regression: occupied day',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[650, True],
     [650, True],
     [900, True],
     [900, True],
     [900, True],
     [900, True],
     [1300, True],
     [1300, False]]],
   [10, 20, 30, 40, 50, 50, 60, 50]],
  ['regression: crowd arrives',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, False],
     [1500, False]]],
   [10, 20, 30, 40, 50, 60, 70, 80, 80, 70, 60]],
  ['regression: moderate co2',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[800, True], [800, True], [800, True], [800, True], [800, True], [750, True], [750, True]]],
   [10, 20, 30, 35, 35, 28, 28]],
  ['regression: unoccupied high co2',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[1200, False], [1200, False], [1200, True]]],
   [0, 0, 10]],
  ['regression: scenario 2',
   [{'min_pos': 15, 'max_pos': 100, 'co2_low': 700, 'co2_high': 1000},
    [[788, True],
     [835, True],
     [980, True],
     [906, False],
     [1052, True],
     [960, False],
     [1028, True],
     [1053, False],
     [1100, True],
     [1140, False]]],
   [10, 20, 30, 20, 30, 20, 30, 20, 30, 20]],
  ['regression: scenario 3',
   [{'min_pos': 20, 'max_pos': 100, 'co2_low': 600, 'co2_high': 1200},
    [[1068, True],
     [969, True],
     [993, True],
     [1093, True],
     [1019, True],
     [1021, True],
     [1037, False],
     [990, True],
     [876, False],
     [997, True],
     [984, True],
     [903, False],
     [822, False]]],
   [10, 20, 30, 40, 50, 60, 50, 60, 50, 60, 70, 60, 50]]]]
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 fixtureActualExpectedOutcome
regression: occupied day[20, 20, 50, 50, 50, 50, 80, 70][10, 20, 30, 40, 50, 50, 60, 50]Failed
regression: moderate co2[35, 35, 35, 35, 35, 28, 28][10, 20, 30, 35, 35, 28, 28]Failed
regression: crowd arrives[80, 80, 80, 80, 80, 80, 80, 80, 80, 70, 60][10, 20, 30, 40, 50, 60, 70, 80, 80, 70, 60]Failed
regression: unoccupied high co2[0, 0, 80][0, 0, 10]Failed
regression: scenario 1[20, 20, 31, 43, 48, 54, 68, 72][10, 20, 30, 40, 48, 54, 64, 72]Failed
regression: scenario 2[60, 60, 60, 50, 40, 57, 47, 37][10, 20, 30, 20, 10, 20, 30, 20]Failed
regression: scenario 3[0, 80, 80, 70, 80, 80, 70, 80, 70, 80, 70, 80][0, 10, 20, 10, 20, 30, 20, 30, 20, 30, 20, 30]Failed
regression: scenario 4[41, 57, 86, 76, 66, 56, 60, 50, 40, 30, 20][10, 20, 30, 40, 45, 35, 45, 35, 25, 15, 10]Failed

SHA-256 / 9009b0f53d4269fd89ee6cf1a2ff41408e46e66b330a9c1bc1c5154e962bdb0e

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(settings, samples):
    pos = 0
    out = []
    for co2, occupied in samples:
        if not occupied:
            target = 0
        elif co2 <= settings['co2_low']:
            target = settings['min_pos']
        elif co2 >= settings['co2_high']:
            target = settings['max_pos']
        else:
            span = settings['co2_high'] - settings['co2_low']
            num = (co2 - settings['co2_low']) * (settings['max_pos'] - settings['min_pos'])
            target = settings['min_pos'] + (2 * num + span) // (2 * span)
        if target > pos:
            pos = pos + 10
        else:
            pos = max(target, pos - 10)
        out.append(pos)
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: occupied day',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[650, True],
     [650, True],
     [900, True],
     [900, True],
     [900, True],
     [900, True],
     [1300, True],
     [1300, False]]],
   [10, 20, 30, 40, 50, 50, 60, 50]],
  ['regression: moderate co2',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[800, True], [800, True], [800, True], [800, True], [800, True], [750, True], [750, True]]],
   [10, 20, 30, 35, 35, 28, 28]],
  ['regression: crowd arrives',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, False],
     [1500, False]]],
   [10, 20, 30, 40, 50, 60, 70, 80, 80, 70, 60]],
  ['regression: unoccupied high co2',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[1200, False], [1200, False], [1200, True]]],
   [0, 0, 10]],
  ['regression: scenario 1',
   [{'min_pos': 20, 'max_pos': 100, 'co2_low': 600, 'co2_high': 1000},
    [[424, True], [551, True], [655, True], [713, True], [740, True], [769, True], [840, True], [858, True]]],
   [10, 20, 30, 40, 48, 54, 64, 72]],
  ['regression: scenario 2',
   [{'min_pos': 10, 'max_pos': 60, 'co2_low': 700, 'co2_high': 1000},
    [[1150, True],
     [1009, True],
     [1044, True],
     [985, False],
     [1131, False],
     [982, True],
     [895, True],
     [828, False]]],
   [10, 20, 30, 20, 10, 20, 30, 20]],
  ['regression: scenario 3',
   [{'min_pos': 15, 'max_pos': 80, 'co2_low': 600, 'co2_high': 1000},
    [[1300, False],
     [1254, True],
     [1354, True],
     [1400, False],
     [1471, True],
     [1498, True],
     [1500, False],
     [1488, True],
     [1500, False],
     [1500, True],
     [1500, False],
     [1464, True]]],
   [0, 10, 20, 10, 20, 30, 20, 30, 20, 30, 20, 30]],
  ['regression: scenario 4',
   [{'min_pos': 10, 'max_pos': 100, 'co2_low': 700, 'co2_high': 1000},
    [[802, True],
     [856, True],
     [954, True],
     [853, True],
     [816, True],
     [847, False],
     [865, True],
     [741, True],
     [680, True],
     [592, True],
     [485, True]]],
   [10, 20, 30, 40, 45, 35, 45, 35, 25, 15, 10]]],
 [['regression: crowd arrives',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, False],
     [1500, False]]],
   [10, 20, 30, 40, 50, 60, 70, 80, 80, 70, 60]],
  ['regression: scenario 2',
   [{'min_pos': 15, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1000},
    [[775, True],
     [743, True],
     [851, True],
     [853, True],
     [893, True],
     [872, True],
     [870, True],
     [781, False],
     [813, True],
     [851, True],
     [955, True]]],
   [10, 20, 30, 40, 50, 52, 52, 42, 39, 48, 58]],
  ['regression: occupied day',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[650, True],
     [650, True],
     [900, True],
     [900, True],
     [900, True],
     [900, True],
     [1300, True],
     [1300, False]]],
   [10, 20, 30, 40, 50, 50, 60, 50]],
  ['regression: moderate co2',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[800, True], [800, True], [800, True], [800, True], [800, True], [750, True], [750, True]]],
   [10, 20, 30, 35, 35, 28, 28]],
  ['regression: unoccupied high co2',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[1200, False], [1200, False], [1200, True]]],
   [0, 0, 10]],
  ['regression: scenario 1',
   [{'min_pos': 20, 'max_pos': 100, 'co2_low': 600, 'co2_high': 1200},
    [[631, True],
     [545, True],
     [465, True],
     [503, True],
     [568, True],
     [550, True],
     [450, False],
     [459, True],
     [434, True],
     [539, True],
     [480, True],
     [462, False],
     [400, True],
     [400, True]]],
   [10, 20, 20, 20, 20, 20, 10, 20, 20, 20, 20, 10, 20, 20]],
  ['regression: scenario 3',
   [{'min_pos': 10, 'max_pos': 100, 'co2_low': 700, 'co2_high': 1200},
    [[1109, True],
     [1033, False],
     [1170, False],
     [1235, True],
     [1208, True],
     [1230, True],
     [1178, True],
     [1182, True],
     [1206, False],
     [1261, True],
     [1328, True],
     [1474, True]]],
   [10, 0, 0, 10, 20, 30, 40, 50, 40, 50, 60, 70]],
  ['regression: scenario 4',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 600, 'co2_high': 1200},
    [[1028, True],
     [998, True],
     [1129, True],
     [1164, True],
     [1200, True],
     [1276, False],
     [1335, True],
     [1192, True],
     [1105, True],
     [1194, True],
     [1207, True]]],
   [10, 20, 30, 40, 50, 40, 50, 60, 70, 79, 80]]],
 [['regression: moderate co2',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[800, True], [800, True], [800, True], [800, True], [800, True], [750, True], [750, True]]],
   [10, 20, 30, 35, 35, 28, 28]],
  ['regression: scenario 7',
   [{'min_pos': 15, 'max_pos': 100, 'co2_low': 700, 'co2_high': 1200},
    [[675, True],
     [553, False],
     [630, True],
     [746, True],
     [799, False],
     [713, True],
     [783, True],
     [718, True]]],
   [10, 0, 10, 20, 10, 17, 27, 18]],
  ['regression: occupied day',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[650, True],
     [650, True],
     [900, True],
     [900, True],
     [900, True],
     [900, True],
     [1300, True],
     [1300, False]]],
   [10, 20, 30, 40, 50, 50, 60, 50]],
  ['regression: crowd arrives',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, False],
     [1500, False]]],
   [10, 20, 30, 40, 50, 60, 70, 80, 80, 70, 60]],
  ['regression: unoccupied high co2',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[1200, False], [1200, False], [1200, True]]],
   [0, 0, 10]],
  ['control: scenario 1',
   [{'min_pos': 10, 'max_pos': 60, 'co2_low': 700, 'co2_high': 1000},
    [[523, True],
     [506, True],
     [620, False],
     [668, True],
     [557, True],
     [453, True],
     [400, True],
     [400, True],
     [409, True],
     [455, False],
     [443, False],
     [561, True]]],
   [10, 10, 0, 10, 10, 10, 10, 10, 10, 0, 0, 10]],
  ['regression: scenario 2',
   [{'min_pos': 20, 'max_pos': 60, 'co2_low': 600, 'co2_high': 1000},
    [[640, True],
     [668, False],
     [658, True],
     [602, False],
     [640, False],
     [525, False],
     [604, True],
     [456, True],
     [591, True],
     [611, True]]],
   [10, 0, 10, 0, 0, 0, 10, 20, 20, 21]],
  ['regression: scenario 3',
   [{'min_pos': 20, 'max_pos': 60, 'co2_low': 700, 'co2_high': 1000},
    [[1018, True],
     [1052, True],
     [988, True],
     [1071, True],
     [1109, True],
     [1124, True],
     [1196, True],
     [1221, False],
     [1203, True]]],
   [10, 20, 30, 40, 50, 60, 60, 50, 60]]],
 [['regression: unoccupied high co2',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[1200, False], [1200, False], [1200, True]]],
   [0, 0, 10]],
  ['regression: scenario 6',
   [{'min_pos': 15, 'max_pos': 60, 'co2_low': 600, 'co2_high': 1200},
    [[1241, True],
     [1251, True],
     [1129, True],
     [1007, True],
     [865, True],
     [796, True],
     [856, True],
     [908, True],
     [822, True],
     [747, True],
     [773, True],
     [762, True],
     [674, True]]],
   [10, 20, 30, 40, 35, 30, 34, 38, 32, 26, 28, 27, 21]],
  ['regression: occupied day',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[650, True],
     [650, True],
     [900, True],
     [900, True],
     [900, True],
     [900, True],
     [1300, True],
     [1300, False]]],
   [10, 20, 30, 40, 50, 50, 60, 50]],
  ['regression: crowd arrives',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, False],
     [1500, False]]],
   [10, 20, 30, 40, 50, 60, 70, 80, 80, 70, 60]],
  ['regression: moderate co2',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[800, True], [800, True], [800, True], [800, True], [800, True], [750, True], [750, True]]],
   [10, 20, 30, 35, 35, 28, 28]],
  ['regression: scenario 1',
   [{'min_pos': 15, 'max_pos': 60, 'co2_low': 700, 'co2_high': 1200},
    [[1121, True],
     [1144, True],
     [1172, True],
     [1223, True],
     [1138, True],
     [1273, True],
     [1319, True],
     [1227, False],
     [1253, True]]],
   [10, 20, 30, 40, 50, 60, 60, 50, 60]],
  ['regression: scenario 2',
   [{'min_pos': 20, 'max_pos': 60, 'co2_low': 600, 'co2_high': 1200},
    [[570, True],
     [539, True],
     [432, True],
     [498, True],
     [536, True],
     [559, True],
     [607, True],
     [706, False],
     [703, False],
     [767, True],
     [618, False],
     [742, False],
     [796, True]]],
   [10, 20, 20, 20, 20, 20, 20, 10, 0, 10, 0, 0, 10]],
  ['regression: scenario 3',
   [{'min_pos': 20, 'max_pos': 60, 'co2_low': 600, 'co2_high': 1000},
    [[853, True],
     [828, True],
     [845, True],
     [890, False],
     [973, True],
     [895, True],
     [751, True],
     [855, True],
     [839, False],
     [909, True],
     [1031, True],
     [926, True],
     [1032, True]]],
   [10, 20, 30, 20, 30, 40, 35, 45, 35, 45, 55, 53, 60]]],
 [['regression: scenario 1',
   [{'min_pos': 15, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1200},
    [[1383, True],
     [1500, True],
     [1500, True],
     [1483, True],
     [1492, True],
     [1500, False],
     [1500, True],
     [1500, True],
     [1500, False],
     [1465, True],
     [1443, False],
     [1458, False],
     [1430, True]]],
   [10, 20, 30, 40, 50, 40, 50, 60, 50, 60, 50, 40, 50]],
  ['regression: scenario 10',
   [{'min_pos': 15, 'max_pos': 60, 'co2_low': 700, 'co2_high': 1200},
    [[1256, False],
     [1206, True],
     [1065, True],
     [1046, True],
     [1037, True],
     [1140, True],
     [1055, False],
     [1023, True],
     [930, True],
     [795, True],
     [685, False]]],
   [0, 10, 20, 30, 40, 50, 40, 44, 36, 26, 16]],
  ['regression: occupied day',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[650, True],
     [650, True],
     [900, True],
     [900, True],
     [900, True],
     [900, True],
     [1300, True],
     [1300, False]]],
   [10, 20, 30, 40, 50, 50, 60, 50]],
  ['regression: crowd arrives',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, False],
     [1500, False]]],
   [10, 20, 30, 40, 50, 60, 70, 80, 80, 70, 60]],
  ['regression: moderate co2',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[800, True], [800, True], [800, True], [800, True], [800, True], [750, True], [750, True]]],
   [10, 20, 30, 35, 35, 28, 28]],
  ['regression: unoccupied high co2',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[1200, False], [1200, False], [1200, True]]],
   [0, 0, 10]],
  ['regression: scenario 2',
   [{'min_pos': 15, 'max_pos': 100, 'co2_low': 700, 'co2_high': 1000},
    [[788, True],
     [835, True],
     [980, True],
     [906, False],
     [1052, True],
     [960, False],
     [1028, True],
     [1053, False],
     [1100, True],
     [1140, False]]],
   [10, 20, 30, 20, 30, 20, 30, 20, 30, 20]],
  ['regression: scenario 3',
   [{'min_pos': 20, 'max_pos': 100, 'co2_low': 600, 'co2_high': 1200},
    [[1068, True],
     [969, True],
     [993, True],
     [1093, True],
     [1019, True],
     [1021, True],
     [1037, False],
     [990, True],
     [876, False],
     [997, True],
     [984, True],
     [903, False],
     [822, False]]],
   [10, 20, 30, 40, 50, 60, 50, 60, 50, 60, 70, 60, 50]]]]
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 fixtureActualExpectedOutcome
regression: occupied day[10, 20, 30, 40, 50, 50, 60, 50][10, 20, 30, 40, 50, 50, 60, 50]Passed
regression: moderate co2[10, 20, 30, 40, 35, 28, 28][10, 20, 30, 35, 35, 28, 28]Failed
regression: crowd arrives[10, 20, 30, 40, 50, 60, 70, 80, 80, 70, 60][10, 20, 30, 40, 50, 60, 70, 80, 80, 70, 60]Passed
regression: unoccupied high co2[0, 0, 10][0, 0, 10]Passed
regression: scenario 1[10, 20, 30, 40, 50, 60, 70, 80][10, 20, 30, 40, 48, 54, 64, 72]Failed
regression: scenario 2[10, 20, 30, 20, 10, 20, 30, 20][10, 20, 30, 20, 10, 20, 30, 20]Passed
regression: scenario 3[0, 10, 20, 10, 20, 30, 20, 30, 20, 30, 20, 30][0, 10, 20, 10, 20, 30, 20, 30, 20, 30, 20, 30]Passed
regression: scenario 4[10, 20, 30, 40, 50, 40, 50, 40, 30, 20, 10][10, 20, 30, 40, 45, 35, 45, 35, 25, 15, 10]Failed

SHA-256 / 3b44183ef54cd11ecbd1c168f6dae9e190a6af42b6653979995920746c8d353c

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(settings, samples):
    pos = 0
    out = []
    for co2, occupied in samples:
        if not occupied:
            target = 0
        elif co2 <= settings['co2_low']:
            target = settings['min_pos']
        elif co2 >= settings['co2_high']:
            target = settings['max_pos']
        else:
            span = settings['co2_high'] - settings['co2_low']
            num = (co2 - settings['co2_low']) * (settings['max_pos'] - settings['min_pos'])
            target = settings['min_pos'] + (2 * num + span) // (2 * span)
        if target > pos:
            pos = min(target, pos + 10)
        else:
            pos = max(target, pos - 10)
        out.append(pos)
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: occupied day',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[650, True],
     [650, True],
     [900, True],
     [900, True],
     [900, True],
     [900, True],
     [1300, True],
     [1300, False]]],
   [10, 20, 30, 40, 50, 50, 60, 50]],
  ['regression: moderate co2',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[800, True], [800, True], [800, True], [800, True], [800, True], [750, True], [750, True]]],
   [10, 20, 30, 35, 35, 28, 28]],
  ['regression: crowd arrives',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, False],
     [1500, False]]],
   [10, 20, 30, 40, 50, 60, 70, 80, 80, 70, 60]],
  ['regression: unoccupied high co2',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[1200, False], [1200, False], [1200, True]]],
   [0, 0, 10]],
  ['regression: scenario 1',
   [{'min_pos': 20, 'max_pos': 100, 'co2_low': 600, 'co2_high': 1000},
    [[424, True], [551, True], [655, True], [713, True], [740, True], [769, True], [840, True], [858, True]]],
   [10, 20, 30, 40, 48, 54, 64, 72]],
  ['regression: scenario 2',
   [{'min_pos': 10, 'max_pos': 60, 'co2_low': 700, 'co2_high': 1000},
    [[1150, True],
     [1009, True],
     [1044, True],
     [985, False],
     [1131, False],
     [982, True],
     [895, True],
     [828, False]]],
   [10, 20, 30, 20, 10, 20, 30, 20]],
  ['regression: scenario 3',
   [{'min_pos': 15, 'max_pos': 80, 'co2_low': 600, 'co2_high': 1000},
    [[1300, False],
     [1254, True],
     [1354, True],
     [1400, False],
     [1471, True],
     [1498, True],
     [1500, False],
     [1488, True],
     [1500, False],
     [1500, True],
     [1500, False],
     [1464, True]]],
   [0, 10, 20, 10, 20, 30, 20, 30, 20, 30, 20, 30]],
  ['regression: scenario 4',
   [{'min_pos': 10, 'max_pos': 100, 'co2_low': 700, 'co2_high': 1000},
    [[802, True],
     [856, True],
     [954, True],
     [853, True],
     [816, True],
     [847, False],
     [865, True],
     [741, True],
     [680, True],
     [592, True],
     [485, True]]],
   [10, 20, 30, 40, 45, 35, 45, 35, 25, 15, 10]]],
 [['regression: crowd arrives',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, False],
     [1500, False]]],
   [10, 20, 30, 40, 50, 60, 70, 80, 80, 70, 60]],
  ['regression: scenario 2',
   [{'min_pos': 15, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1000},
    [[775, True],
     [743, True],
     [851, True],
     [853, True],
     [893, True],
     [872, True],
     [870, True],
     [781, False],
     [813, True],
     [851, True],
     [955, True]]],
   [10, 20, 30, 40, 50, 52, 52, 42, 39, 48, 58]],
  ['regression: occupied day',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[650, True],
     [650, True],
     [900, True],
     [900, True],
     [900, True],
     [900, True],
     [1300, True],
     [1300, False]]],
   [10, 20, 30, 40, 50, 50, 60, 50]],
  ['regression: moderate co2',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[800, True], [800, True], [800, True], [800, True], [800, True], [750, True], [750, True]]],
   [10, 20, 30, 35, 35, 28, 28]],
  ['regression: unoccupied high co2',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[1200, False], [1200, False], [1200, True]]],
   [0, 0, 10]],
  ['regression: scenario 1',
   [{'min_pos': 20, 'max_pos': 100, 'co2_low': 600, 'co2_high': 1200},
    [[631, True],
     [545, True],
     [465, True],
     [503, True],
     [568, True],
     [550, True],
     [450, False],
     [459, True],
     [434, True],
     [539, True],
     [480, True],
     [462, False],
     [400, True],
     [400, True]]],
   [10, 20, 20, 20, 20, 20, 10, 20, 20, 20, 20, 10, 20, 20]],
  ['regression: scenario 3',
   [{'min_pos': 10, 'max_pos': 100, 'co2_low': 700, 'co2_high': 1200},
    [[1109, True],
     [1033, False],
     [1170, False],
     [1235, True],
     [1208, True],
     [1230, True],
     [1178, True],
     [1182, True],
     [1206, False],
     [1261, True],
     [1328, True],
     [1474, True]]],
   [10, 0, 0, 10, 20, 30, 40, 50, 40, 50, 60, 70]],
  ['regression: scenario 4',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 600, 'co2_high': 1200},
    [[1028, True],
     [998, True],
     [1129, True],
     [1164, True],
     [1200, True],
     [1276, False],
     [1335, True],
     [1192, True],
     [1105, True],
     [1194, True],
     [1207, True]]],
   [10, 20, 30, 40, 50, 40, 50, 60, 70, 79, 80]]],
 [['regression: moderate co2',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[800, True], [800, True], [800, True], [800, True], [800, True], [750, True], [750, True]]],
   [10, 20, 30, 35, 35, 28, 28]],
  ['regression: scenario 7',
   [{'min_pos': 15, 'max_pos': 100, 'co2_low': 700, 'co2_high': 1200},
    [[675, True],
     [553, False],
     [630, True],
     [746, True],
     [799, False],
     [713, True],
     [783, True],
     [718, True]]],
   [10, 0, 10, 20, 10, 17, 27, 18]],
  ['regression: occupied day',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[650, True],
     [650, True],
     [900, True],
     [900, True],
     [900, True],
     [900, True],
     [1300, True],
     [1300, False]]],
   [10, 20, 30, 40, 50, 50, 60, 50]],
  ['regression: crowd arrives',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, False],
     [1500, False]]],
   [10, 20, 30, 40, 50, 60, 70, 80, 80, 70, 60]],
  ['regression: unoccupied high co2',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[1200, False], [1200, False], [1200, True]]],
   [0, 0, 10]],
  ['control: scenario 1',
   [{'min_pos': 10, 'max_pos': 60, 'co2_low': 700, 'co2_high': 1000},
    [[523, True],
     [506, True],
     [620, False],
     [668, True],
     [557, True],
     [453, True],
     [400, True],
     [400, True],
     [409, True],
     [455, False],
     [443, False],
     [561, True]]],
   [10, 10, 0, 10, 10, 10, 10, 10, 10, 0, 0, 10]],
  ['regression: scenario 2',
   [{'min_pos': 20, 'max_pos': 60, 'co2_low': 600, 'co2_high': 1000},
    [[640, True],
     [668, False],
     [658, True],
     [602, False],
     [640, False],
     [525, False],
     [604, True],
     [456, True],
     [591, True],
     [611, True]]],
   [10, 0, 10, 0, 0, 0, 10, 20, 20, 21]],
  ['regression: scenario 3',
   [{'min_pos': 20, 'max_pos': 60, 'co2_low': 700, 'co2_high': 1000},
    [[1018, True],
     [1052, True],
     [988, True],
     [1071, True],
     [1109, True],
     [1124, True],
     [1196, True],
     [1221, False],
     [1203, True]]],
   [10, 20, 30, 40, 50, 60, 60, 50, 60]]],
 [['regression: unoccupied high co2',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[1200, False], [1200, False], [1200, True]]],
   [0, 0, 10]],
  ['regression: scenario 6',
   [{'min_pos': 15, 'max_pos': 60, 'co2_low': 600, 'co2_high': 1200},
    [[1241, True],
     [1251, True],
     [1129, True],
     [1007, True],
     [865, True],
     [796, True],
     [856, True],
     [908, True],
     [822, True],
     [747, True],
     [773, True],
     [762, True],
     [674, True]]],
   [10, 20, 30, 40, 35, 30, 34, 38, 32, 26, 28, 27, 21]],
  ['regression: occupied day',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[650, True],
     [650, True],
     [900, True],
     [900, True],
     [900, True],
     [900, True],
     [1300, True],
     [1300, False]]],
   [10, 20, 30, 40, 50, 50, 60, 50]],
  ['regression: crowd arrives',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, False],
     [1500, False]]],
   [10, 20, 30, 40, 50, 60, 70, 80, 80, 70, 60]],
  ['regression: moderate co2',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[800, True], [800, True], [800, True], [800, True], [800, True], [750, True], [750, True]]],
   [10, 20, 30, 35, 35, 28, 28]],
  ['regression: scenario 1',
   [{'min_pos': 15, 'max_pos': 60, 'co2_low': 700, 'co2_high': 1200},
    [[1121, True],
     [1144, True],
     [1172, True],
     [1223, True],
     [1138, True],
     [1273, True],
     [1319, True],
     [1227, False],
     [1253, True]]],
   [10, 20, 30, 40, 50, 60, 60, 50, 60]],
  ['regression: scenario 2',
   [{'min_pos': 20, 'max_pos': 60, 'co2_low': 600, 'co2_high': 1200},
    [[570, True],
     [539, True],
     [432, True],
     [498, True],
     [536, True],
     [559, True],
     [607, True],
     [706, False],
     [703, False],
     [767, True],
     [618, False],
     [742, False],
     [796, True]]],
   [10, 20, 20, 20, 20, 20, 20, 10, 0, 10, 0, 0, 10]],
  ['regression: scenario 3',
   [{'min_pos': 20, 'max_pos': 60, 'co2_low': 600, 'co2_high': 1000},
    [[853, True],
     [828, True],
     [845, True],
     [890, False],
     [973, True],
     [895, True],
     [751, True],
     [855, True],
     [839, False],
     [909, True],
     [1031, True],
     [926, True],
     [1032, True]]],
   [10, 20, 30, 20, 30, 40, 35, 45, 35, 45, 55, 53, 60]]],
 [['regression: scenario 1',
   [{'min_pos': 15, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1200},
    [[1383, True],
     [1500, True],
     [1500, True],
     [1483, True],
     [1492, True],
     [1500, False],
     [1500, True],
     [1500, True],
     [1500, False],
     [1465, True],
     [1443, False],
     [1458, False],
     [1430, True]]],
   [10, 20, 30, 40, 50, 40, 50, 60, 50, 60, 50, 40, 50]],
  ['regression: scenario 10',
   [{'min_pos': 15, 'max_pos': 60, 'co2_low': 700, 'co2_high': 1200},
    [[1256, False],
     [1206, True],
     [1065, True],
     [1046, True],
     [1037, True],
     [1140, True],
     [1055, False],
     [1023, True],
     [930, True],
     [795, True],
     [685, False]]],
   [0, 10, 20, 30, 40, 50, 40, 44, 36, 26, 16]],
  ['regression: occupied day',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[650, True],
     [650, True],
     [900, True],
     [900, True],
     [900, True],
     [900, True],
     [1300, True],
     [1300, False]]],
   [10, 20, 30, 40, 50, 50, 60, 50]],
  ['regression: crowd arrives',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, True],
     [1500, False],
     [1500, False]]],
   [10, 20, 30, 40, 50, 60, 70, 80, 80, 70, 60]],
  ['regression: moderate co2',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[800, True], [800, True], [800, True], [800, True], [800, True], [750, True], [750, True]]],
   [10, 20, 30, 35, 35, 28, 28]],
  ['regression: unoccupied high co2',
   [{'min_pos': 20, 'max_pos': 80, 'co2_low': 700, 'co2_high': 1100},
    [[1200, False], [1200, False], [1200, True]]],
   [0, 0, 10]],
  ['regression: scenario 2',
   [{'min_pos': 15, 'max_pos': 100, 'co2_low': 700, 'co2_high': 1000},
    [[788, True],
     [835, True],
     [980, True],
     [906, False],
     [1052, True],
     [960, False],
     [1028, True],
     [1053, False],
     [1100, True],
     [1140, False]]],
   [10, 20, 30, 20, 30, 20, 30, 20, 30, 20]],
  ['regression: scenario 3',
   [{'min_pos': 20, 'max_pos': 100, 'co2_low': 600, 'co2_high': 1200},
    [[1068, True],
     [969, True],
     [993, True],
     [1093, True],
     [1019, True],
     [1021, True],
     [1037, False],
     [990, True],
     [876, False],
     [997, True],
     [984, True],
     [903, False],
     [822, False]]],
   [10, 20, 30, 40, 50, 60, 50, 60, 50, 60, 70, 60, 50]]]]
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 fixtureActualExpectedOutcome
regression: occupied day[10, 20, 30, 40, 50, 50, 60, 50][10, 20, 30, 40, 50, 50, 60, 50]Passed
regression: moderate co2[10, 20, 30, 35, 35, 28, 28][10, 20, 30, 35, 35, 28, 28]Passed
regression: crowd arrives[10, 20, 30, 40, 50, 60, 70, 80, 80, 70, 60][10, 20, 30, 40, 50, 60, 70, 80, 80, 70, 60]Passed
regression: unoccupied high co2[0, 0, 10][0, 0, 10]Passed
regression: scenario 1[10, 20, 30, 40, 48, 54, 64, 72][10, 20, 30, 40, 48, 54, 64, 72]Passed
regression: scenario 2[10, 20, 30, 20, 10, 20, 30, 20][10, 20, 30, 20, 10, 20, 30, 20]Passed
regression: scenario 3[0, 10, 20, 10, 20, 30, 20, 30, 20, 30, 20, 30][0, 10, 20, 10, 20, 30, 20, 30, 20, 30, 20, 30]Passed
regression: scenario 4[10, 20, 30, 40, 45, 35, 45, 35, 25, 15, 10][10, 20, 30, 40, 45, 35, 45, 35, 25, 15, 10]Passed

SHA-256 / baef580bf2545d8babb030373b0c98f43f580e4261abddbdee46dd98dd8208e2

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.385824+00:00.

Case digest / 0eb3f0d994e04c776005b29042862b803341d36a6c82c5f9208d0dea63aca876