FA-92821 / HVAC thermostat control / Open access
Zoned system never serves a minority mode · case 01
A single zone calling heat waits indefinitely while two zones keep calling cooling.
ROOT CAUSE
The forced switch after max_run also requires the other mode to have at least as many calls.
VERIFIED REPAIR
Switch whenever the opposite mode is waiting and max_run has elapsed.
Unsuccessful approach: Switching one minute later than max_run still starves the waiting zone.
Case contract
Zoned single-unit system arbitration per minute; each sample maps zone -> heat, cool or None. When idle the system picks the mode with more calling zones (ties go to heat). A mode ends when no zone calls for it, and a new mode may be chosen in the same minute. If zones call for the opposite mode, the system switches once the current mode has run max_run minutes, restarting the run timer. Dampers open only for zones calling the active mode. Return [mode, sorted open zones] 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(max_run, samples):
mode = None
since = 0
out = []
for minute, calls in enumerate(samples):
heat = sorted(z for z, c in calls.items() if c == 'heat')
cool = sorted(z for z, c in calls.items() if c == 'cool')
want = {'heat': heat, 'cool': cool}
if mode is not None:
other = 'cool' if mode == 'heat' else 'heat'
if not want[mode]:
mode = None
elif want[other] and minute - since >= max_run and len(want[other]) >= len(want[mode]):
mode = other
since = minute
if mode is None and (heat or cool):
mode = 'heat' if len(heat) >= len(cool) else 'cool'
since = minute
out.append([mode, want[mode] if mode else []])
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: scenario 1',
[5,
[{'z1': 'cool', 'z3': None, 'z4': None},
{'z1': 'heat', 'z2': 'heat', 'z3': None, 'z4': 'cool'},
{'z1': 'heat', 'z2': 'heat', 'z3': 'heat', 'z4': 'cool'},
{'z1': 'heat', 'z2': 'heat', 'z3': 'heat', 'z4': 'cool'},
{'z1': 'heat', 'z2': 'cool', 'z3': 'cool', 'z4': 'cool'},
{'z1': 'heat', 'z2': 'cool', 'z3': 'cool', 'z4': 'cool'},
{'z1': 'heat', 'z2': 'cool', 'z4': 'cool'},
{'z1': 'heat', 'z2': 'cool', 'z3': None, 'z4': 'cool'},
{'z2': 'cool', 'z4': 'heat'},
{'z1': None, 'z2': 'cool', 'z3': 'heat', 'z4': 'heat'}]],
[['cool', ['z1']],
['cool', ['z4']],
['cool', ['z4']],
['cool', ['z4']],
['cool', ['z2', 'z3', 'z4']],
['heat', ['z1']],
['heat', ['z1']],
['heat', ['z1']],
['heat', ['z4']],
['heat', ['z3', 'z4']]]],
['regression: majority then forced switch',
[3,
[{'a': 'heat', 'b': 'cool', 'c': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat'},
{}]],
[['cool', ['b', 'c']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']], ['heat', ['a']], [None, []]]],
['control: tie goes to heat',
[2, [{'a': 'heat', 'b': 'cool'}, {'a': 'heat', 'b': 'cool'}, {'b': 'cool'}]],
[['heat', ['a']], ['heat', ['a']], ['cool', ['b']]]],
['regression: ping pong guard',
[2,
[{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'}]],
[['heat', ['a']],
['heat', ['a']],
['cool', ['b']],
['cool', ['b']],
['heat', ['a']],
['heat', ['a']],
['cool', ['b']]]],
['control: satisfied then opposite',
[5, [{'a': 'cool'}, {'a': 'cool', 'b': 'heat'}, {'b': 'heat'}, {'b': 'heat'}]],
[['cool', ['a']], ['cool', ['a']], ['heat', ['b']], ['heat', ['b']]]],
['control: first minute call',
[3, [{'a': 'cool'}, {'a': 'cool'}, {}]],
[['cool', ['a']], ['cool', ['a']], [None, []]]],
['regression: scenario 2',
[5,
[{'z1': 'cool', 'z2': None, 'z3': 'cool'},
{'z1': 'cool', 'z2': None, 'z3': 'cool'},
{'z1': 'cool', 'z3': 'cool'},
{'z1': 'cool', 'z2': None, 'z3': 'cool'},
{'z1': 'cool', 'z2': None, 'z3': 'cool'},
{'z1': 'cool', 'z3': 'heat', 'z4': None},
{'z1': 'cool', 'z2': None, 'z3': 'heat'},
{'z1': 'cool', 'z2': None, 'z3': 'heat'},
{'z1': 'heat'},
{'z1': 'heat', 'z2': None, 'z4': None},
{'z1': 'heat', 'z4': None},
{'z1': 'heat', 'z2': None, 'z4': None},
{'z1': 'heat', 'z3': 'heat', 'z4': None}]],
[['cool', ['z1', 'z3']],
['cool', ['z1', 'z3']],
['cool', ['z1', 'z3']],
['cool', ['z1', 'z3']],
['cool', ['z1', 'z3']],
['heat', ['z3']],
['heat', ['z3']],
['heat', ['z3']],
['heat', ['z1']],
['heat', ['z1']],
['heat', ['z1']],
['heat', ['z1']],
['heat', ['z1', 'z3']]]],
['regression: scenario 3',
[2,
[{'z1': 'cool', 'z2': 'heat', 'z3': 'cool', 'z4': None},
{'z2': 'cool', 'z3': 'cool', 'z4': None},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': None},
{'z1': 'cool', 'z2': 'heat', 'z3': 'cool'},
{'z1': 'cool', 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z3': 'cool', 'z4': None},
{'z1': 'cool', 'z3': 'heat', 'z4': None},
{'z1': 'cool', 'z2': None, 'z3': 'heat'},
{'z1': 'cool', 'z3': 'heat'}]],
[['cool', ['z1', 'z3']],
['cool', ['z2', 'z3']],
['cool', ['z1', 'z2', 'z3']],
['heat', ['z2']],
['heat', ['z2', 'z4']],
['cool', ['z1', 'z2', 'z3']],
['cool', ['z1', 'z3']],
['heat', ['z3']],
['heat', ['z3']],
['cool', ['z1']]]]],
[['regression: scenario 2',
[3,
[{'z1': None, 'z2': 'cool', 'z3': 'heat', 'z4': 'heat'},
{'z3': 'heat', 'z4': 'heat'},
{'z1': None, 'z2': None, 'z3': 'cool', 'z4': 'cool'},
{'z3': 'cool'},
{'z2': None, 'z3': 'cool', 'z4': None},
{'z1': 'heat', 'z2': 'cool', 'z3': 'cool'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': None},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z4': 'heat'},
{'z1': 'heat', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'heat', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'}]],
[['heat', ['z3', 'z4']],
['heat', ['z3', 'z4']],
['cool', ['z3', 'z4']],
['cool', ['z3']],
['cool', ['z3']],
['heat', ['z1']],
['cool', ['z1', 'z2', 'z3']],
['cool', ['z1', 'z2', 'z3']],
['cool', ['z1', 'z2', 'z3']],
['heat', ['z4']],
['heat', ['z4']],
['heat', ['z4']],
['cool', ['z1', 'z2']],
['cool', ['z2', 'z3']],
['cool', ['z2', 'z3']]]],
['regression: ping pong guard',
[2,
[{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'}]],
[['heat', ['a']],
['heat', ['a']],
['cool', ['b']],
['cool', ['b']],
['heat', ['a']],
['heat', ['a']],
['cool', ['b']]]],
['regression: majority then forced switch',
[3,
[{'a': 'heat', 'b': 'cool', 'c': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat'},
{}]],
[['cool', ['b', 'c']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']], ['heat', ['a']], [None, []]]],
['control: tie goes to heat',
[2, [{'a': 'heat', 'b': 'cool'}, {'a': 'heat', 'b': 'cool'}, {'b': 'cool'}]],
[['heat', ['a']], ['heat', ['a']], ['cool', ['b']]]],
['control: satisfied then opposite',
[5, [{'a': 'cool'}, {'a': 'cool', 'b': 'heat'}, {'b': 'heat'}, {'b': 'heat'}]],
[['cool', ['a']], ['cool', ['a']], ['heat', ['b']], ['heat', ['b']]]],
['control: first minute call',
[3, [{'a': 'cool'}, {'a': 'cool'}, {}]],
[['cool', ['a']], ['cool', ['a']], [None, []]]],
['regression: scenario 1',
[3,
[{'z1': 'heat', 'z2': 'cool', 'z3': 'heat', 'z4': 'heat'},
{'z1': 'heat', 'z3': 'heat', 'z4': 'heat'},
{'z1': 'heat', 'z2': None, 'z3': 'heat', 'z4': 'heat'},
{'z1': None, 'z2': None, 'z3': 'heat', 'z4': 'heat'},
{'z1': 'heat', 'z3': 'heat', 'z4': 'heat'},
{'z1': 'heat', 'z2': None, 'z3': 'heat', 'z4': 'heat'},
{'z1': 'heat', 'z2': None, 'z3': 'heat', 'z4': 'cool'},
{'z1': 'heat', 'z2': None, 'z3': 'heat', 'z4': None},
{'z1': 'heat', 'z3': 'heat', 'z4': None},
{'z1': 'heat', 'z3': 'heat', 'z4': 'heat'},
{'z1': 'heat', 'z2': None, 'z3': 'heat', 'z4': 'heat'},
{'z1': 'heat', 'z2': 'heat', 'z4': 'heat'},
{'z1': 'heat', 'z2': 'heat'},
{'z1': 'heat', 'z2': 'heat', 'z3': 'heat'},
{'z1': 'heat', 'z2': 'heat', 'z3': 'cool'}]],
[['heat', ['z1', 'z3', 'z4']],
['heat', ['z1', 'z3', 'z4']],
['heat', ['z1', 'z3', 'z4']],
['heat', ['z3', 'z4']],
['heat', ['z1', 'z3', 'z4']],
['heat', ['z1', 'z3', 'z4']],
['cool', ['z4']],
['heat', ['z1', 'z3']],
['heat', ['z1', 'z3']],
['heat', ['z1', 'z3', 'z4']],
['heat', ['z1', 'z3', 'z4']],
['heat', ['z1', 'z2', 'z4']],
['heat', ['z1', 'z2']],
['heat', ['z1', 'z2', 'z3']],
['cool', ['z3']]]],
['regression: scenario 3',
[3,
[{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z1': None, 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z2': 'cool', 'z3': 'heat', 'z4': 'heat'},
{'z1': None, 'z2': 'cool', 'z3': 'heat', 'z4': 'heat'},
{'z2': 'cool', 'z3': 'heat', 'z4': 'heat'},
{'z1': None, 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
{'z1': None, 'z2': 'heat', 'z3': 'cool', 'z4': 'cool'}]],
[['cool', ['z1', 'z2', 'z3']],
['cool', ['z1', 'z2', 'z3']],
['cool', ['z1', 'z2', 'z3']],
['heat', ['z4']],
['heat', ['z4']],
['heat', ['z4']],
['cool', ['z2']],
['cool', ['z2']],
['cool', ['z2']],
['heat', ['z4']],
['heat', ['z2', 'z4']],
['heat', ['z2']]]]],
[['regression: scenario 3',
[2,
[{'z1': 'heat', 'z2': 'cool', 'z3': 'heat', 'z4': None},
{'z1': 'heat', 'z2': 'cool', 'z3': 'heat'},
{'z1': 'heat', 'z2': 'cool', 'z3': 'cool'},
{'z1': 'heat', 'z2': 'cool', 'z3': 'cool', 'z4': None},
{'z2': 'cool', 'z3': 'cool'},
{'z2': 'cool', 'z3': 'cool', 'z4': None},
{'z1': None, 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z2': 'heat', 'z3': 'cool', 'z4': 'cool'},
{'z1': None, 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'}]],
[['heat', ['z1', 'z3']],
['heat', ['z1', 'z3']],
['cool', ['z2', 'z3']],
['cool', ['z2', 'z3']],
['cool', ['z2', 'z3']],
['cool', ['z2', 'z3']],
['heat', ['z4']],
['heat', ['z4']],
['cool', ['z2', 'z3']],
['cool', ['z3', 'z4']],
['heat', ['z2', 'z4']]]],
['regression: scenario 1',
[3,
[{'z1': 'heat', 'z2': 'heat', 'z3': None, 'z4': 'cool'},
{'z1': 'heat', 'z2': 'heat', 'z3': 'cool', 'z4': 'cool'},
{'z1': 'heat', 'z2': 'heat', 'z3': 'cool', 'z4': 'cool'},
{'z1': 'heat', 'z2': 'heat', 'z3': 'cool', 'z4': 'cool'},
{'z1': 'heat', 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'heat', 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'heat', 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'heat', 'z2': 'heat', 'z3': None},
{'z1': 'heat', 'z2': 'heat'},
{'z1': 'heat', 'z2': 'heat', 'z3': None, 'z4': 'cool'},
{'z1': 'heat', 'z2': 'heat', 'z3': None, 'z4': None}]],
[['heat', ['z1', 'z2']],
['heat', ['z1', 'z2']],
['heat', ['z1', 'z2']],
['cool', ['z3', 'z4']],
['cool', ['z3']],
['cool', ['z3']],
['heat', ['z1', 'z2', 'z4']],
['heat', ['z1', 'z2']],
['heat', ['z1', 'z2']],
['cool', ['z4']],
['heat', ['z1', 'z2']]]],
['regression: majority then forced switch',
[3,
[{'a': 'heat', 'b': 'cool', 'c': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat'},
{}]],
[['cool', ['b', 'c']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']], ['heat', ['a']], [None, []]]],
['control: tie goes to heat',
[2, [{'a': 'heat', 'b': 'cool'}, {'a': 'heat', 'b': 'cool'}, {'b': 'cool'}]],
[['heat', ['a']], ['heat', ['a']], ['cool', ['b']]]],
['regression: ping pong guard',
[2,
[{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'}]],
[['heat', ['a']],
['heat', ['a']],
['cool', ['b']],
['cool', ['b']],
['heat', ['a']],
['heat', ['a']],
['cool', ['b']]]],
['control: satisfied then opposite',
[5, [{'a': 'cool'}, {'a': 'cool', 'b': 'heat'}, {'b': 'heat'}, {'b': 'heat'}]],
[['cool', ['a']], ['cool', ['a']], ['heat', ['b']], ['heat', ['b']]]],
['control: first minute call',
[3, [{'a': 'cool'}, {'a': 'cool'}, {}]],
[['cool', ['a']], ['cool', ['a']], [None, []]]],
['regression: scenario 2',
[2,
[{'z1': 'heat', 'z3': 'cool', 'z4': 'cool'},
{'z1': 'cool', 'z2': None, 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': None, 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z4': 'heat'},
{'z1': None, 'z2': 'cool', 'z3': None, 'z4': 'heat'},
{'z1': None, 'z2': 'cool', 'z3': None, 'z4': 'heat'},
{'z2': 'cool', 'z4': 'heat'},
{'z3': None}]],
[['cool', ['z3', 'z4']],
['cool', ['z1', 'z3']],
['heat', ['z4']],
['heat', ['z4']],
['cool', ['z2']],
['cool', ['z2']],
['heat', ['z4']],
[None, []]]]],
[['regression: scenario 7',
[2,
[{'z1': 'cool', 'z2': 'cool', 'z3': None, 'z4': 'cool'},
{'z1': 'cool', 'z2': 'cool', 'z4': 'cool'},
{'z1': 'heat', 'z2': 'cool', 'z3': None, 'z4': 'cool'},
{'z1': 'heat', 'z2': 'cool', 'z3': None, 'z4': 'cool'},
{'z1': 'heat', 'z2': 'cool', 'z3': None, 'z4': 'cool'},
{'z1': 'heat', 'z2': 'cool', 'z3': None, 'z4': 'cool'},
{'z1': 'heat', 'z2': 'cool', 'z4': 'cool'},
{'z1': 'heat', 'z2': 'cool', 'z3': 'heat', 'z4': 'cool'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'heat', 'z4': None},
{'z1': None, 'z2': 'cool', 'z3': 'heat'},
{'z1': 'heat', 'z2': None, 'z3': 'heat', 'z4': None},
{'z1': 'heat', 'z3': 'cool'},
{'z1': 'heat', 'z2': None, 'z3': None, 'z4': 'heat'},
{'z1': None}]],
[['cool', ['z1', 'z2', 'z4']],
['cool', ['z1', 'z2', 'z4']],
['heat', ['z1']],
['heat', ['z1']],
['cool', ['z2', 'z4']],
['cool', ['z2', 'z4']],
['heat', ['z1']],
['heat', ['z1', 'z3']],
['cool', ['z1', 'z2']],
['cool', ['z2']],
['heat', ['z1', 'z3']],
['heat', ['z1']],
['heat', ['z1', 'z4']],
[None, []]]],
['regression: scenario 3',
[5,
[{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'heat', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z2': 'cool', 'z3': 'cool', 'z4': 'heat'}]],
[['cool', ['z1', 'z2', 'z3']],
['cool', ['z1', 'z2', 'z3']],
['cool', ['z1', 'z2', 'z3']],
['cool', ['z1', 'z2', 'z3']],
['cool', ['z1', 'z3']],
['heat', ['z4']],
['heat', ['z4']],
['heat', ['z4']],
['heat', ['z4']],
['heat', ['z1', 'z4']],
['cool', ['z2', 'z3']]]],
['regression: majority then forced switch',
[3,
[{'a': 'heat', 'b': 'cool', 'c': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat'},
{}]],
[['cool', ['b', 'c']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']], ['heat', ['a']], [None, []]]],
['control: tie goes to heat',
[2, [{'a': 'heat', 'b': 'cool'}, {'a': 'heat', 'b': 'cool'}, {'b': 'cool'}]],
[['heat', ['a']], ['heat', ['a']], ['cool', ['b']]]],
['regression: ping pong guard',
[2,
[{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'}]],
[['heat', ['a']],
['heat', ['a']],
['cool', ['b']],
['cool', ['b']],
['heat', ['a']],
['heat', ['a']],
['cool', ['b']]]],
['control: satisfied then opposite',
[5, [{'a': 'cool'}, {'a': 'cool', 'b': 'heat'}, {'b': 'heat'}, {'b': 'heat'}]],
[['cool', ['a']], ['cool', ['a']], ['heat', ['b']], ['heat', ['b']]]],
['control: first minute call',
[3, [{'a': 'cool'}, {'a': 'cool'}, {}]],
[['cool', ['a']], ['cool', ['a']], [None, []]]],
['regression: scenario 1',
[5,
[{'z1': 'cool', 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
{'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
{'z1': None, 'z3': 'cool', 'z4': 'heat'},
{'z1': None, 'z3': 'cool', 'z4': 'heat'},
{'z1': None, 'z2': None, 'z3': 'cool', 'z4': 'heat'},
{'z1': None, 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'heat', 'z4': 'heat'},
{'z1': None, 'z2': 'heat', 'z4': 'heat'},
{'z2': 'heat', 'z3': 'cool', 'z4': 'cool'},
{'z2': 'heat', 'z3': 'cool', 'z4': 'cool'},
{'z2': 'heat', 'z3': 'heat', 'z4': 'cool'}]],
[['heat', ['z2', 'z4']],
['heat', ['z2', 'z4']],
['heat', ['z4']],
['heat', ['z4']],
['heat', ['z4']],
['cool', ['z3']],
['cool', ['z1']],
['heat', ['z2', 'z4']],
['heat', ['z2']],
['heat', ['z2']],
['heat', ['z2', 'z3']]]]],
[['regression: scenario 8',
[5,
[{'z4': 'cool'},
{'z1': 'cool', 'z2': 'cool', 'z4': 'cool'},
{'z1': 'cool', 'z2': 'cool', 'z4': 'cool'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'heat', 'z4': 'cool'},
{'z1': 'cool', 'z2': 'heat', 'z3': 'heat', 'z4': 'cool'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'heat', 'z4': 'cool'},
{'z1': 'cool', 'z2': 'cool', 'z3': None, 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z3': None, 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'}]],
[['cool', ['z4']],
['cool', ['z1', 'z2', 'z4']],
['cool', ['z1', 'z2', 'z4']],
['cool', ['z1', 'z2', 'z4']],
['cool', ['z1', 'z4']],
['heat', ['z3']],
['heat', ['z4']],
['heat', ['z4']],
['heat', ['z4']],
['heat', ['z4']],
['cool', ['z1', 'z2', 'z3']],
['cool', ['z1', 'z2', 'z3']]]],
['regression: scenario 3',
[2,
[{'z1': 'heat', 'z2': 'cool', 'z3': 'cool', 'z4': 'cool'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'cool'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'cool'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'cool'},
{'z2': 'cool', 'z3': 'cool', 'z4': 'cool'},
{'z1': None, 'z2': 'cool', 'z3': 'heat', 'z4': 'cool'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'heat', 'z4': 'cool'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'heat', 'z4': 'cool'},
{'z1': 'cool', 'z3': 'heat', 'z4': 'cool'},
{'z1': 'cool', 'z3': 'heat', 'z4': 'cool'}]],
[['cool', ['z2', 'z3', 'z4']],
['cool', ['z1', 'z2', 'z3', 'z4']],
['cool', ['z1', 'z2', 'z3', 'z4']],
['cool', ['z1', 'z2', 'z3', 'z4']],
['cool', ['z2', 'z3', 'z4']],
['heat', ['z3']],
['heat', ['z3']],
['cool', ['z1', 'z2', 'z4']],
['cool', ['z1', 'z4']],
['heat', ['z3']]]],
['regression: majority then forced switch',
[3,
[{'a': 'heat', 'b': 'cool', 'c': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat'},
{}]],
[['cool', ['b', 'c']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']], ['heat', ['a']], [None, []]]],
['control: tie goes to heat',
[2, [{'a': 'heat', 'b': 'cool'}, {'a': 'heat', 'b': 'cool'}, {'b': 'cool'}]],
[['heat', ['a']], ['heat', ['a']], ['cool', ['b']]]],
['regression: ping pong guard',
[2,
[{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'}]],
[['heat', ['a']],
['heat', ['a']],
['cool', ['b']],
['cool', ['b']],
['heat', ['a']],
['heat', ['a']],
['cool', ['b']]]],
['control: satisfied then opposite',
[5, [{'a': 'cool'}, {'a': 'cool', 'b': 'heat'}, {'b': 'heat'}, {'b': 'heat'}]],
[['cool', ['a']], ['cool', ['a']], ['heat', ['b']], ['heat', ['b']]]],
['control: first minute call',
[3, [{'a': 'cool'}, {'a': 'cool'}, {}]],
[['cool', ['a']], ['cool', ['a']], [None, []]]],
['regression: scenario 1',
[3,
[{'z1': 'heat', 'z2': 'heat', 'z3': 'heat', 'z4': 'heat'},
{'z1': 'heat', 'z2': 'heat', 'z3': 'heat'},
{'z1': 'heat', 'z2': 'heat', 'z3': 'heat', 'z4': 'heat'},
{'z1': 'heat', 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'heat', 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
{'z2': 'heat'},
{'z2': 'heat', 'z4': 'heat'},
{'z1': None, 'z2': 'heat', 'z3': None, 'z4': 'heat'},
{'z2': 'heat', 'z3': None, 'z4': 'heat'}]],
[['heat', ['z1', 'z2', 'z3', 'z4']],
['heat', ['z1', 'z2', 'z3']],
['heat', ['z1', 'z2', 'z3', 'z4']],
['cool', ['z3']],
['cool', ['z3']],
['heat', ['z2']],
['heat', ['z2', 'z4']],
['heat', ['z2', 'z4']],
['heat', ['z2', 'z4']]]]]]
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: scenario 1 | [['cool', ['z1']], ['cool', ['z4']], ['cool', ['z4']], ['cool', ['z4']], ['cool', ['z2', 'z3', 'z4']], ['cool', ['z2', 'z3', 'z4']], ['cool', ['z2', 'z4']], ['cool', ['z2', 'z4']], ['heat', ['z4']], ['heat', ['z3', 'z4']]] | [['cool', ['z1']], ['cool', ['z4']], ['cool', ['z4']], ['cool', ['z4']], ['cool', ['z2', 'z3', 'z4']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z4']], ['heat', ['z3', 'z4']]] | Failed |
| regression: majority then forced switch | [['cool', ['b', 'c']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']], ['heat', ['a']], [None, []]] | [['cool', ['b', 'c']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']], ['heat', ['a']], [None, []]] | Passed |
| control: tie goes to heat | [['heat', ['a']], ['heat', ['a']], ['cool', ['b']]] | [['heat', ['a']], ['heat', ['a']], ['cool', ['b']]] | Passed |
| regression: ping pong guard | [['heat', ['a']], ['heat', ['a']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']], ['heat', ['a']], ['cool', ['b']]] | [['heat', ['a']], ['heat', ['a']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']], ['heat', ['a']], ['cool', ['b']]] | Passed |
| control: satisfied then opposite | [['cool', ['a']], ['cool', ['a']], ['heat', ['b']], ['heat', ['b']]] | [['cool', ['a']], ['cool', ['a']], ['heat', ['b']], ['heat', ['b']]] | Passed |
| control: first minute call | [['cool', ['a']], ['cool', ['a']], [None, []]] | [['cool', ['a']], ['cool', ['a']], [None, []]] | Passed |
| regression: scenario 2 | [['cool', ['z1', 'z3']], ['cool', ['z1', 'z3']], ['cool', ['z1', 'z3']], ['cool', ['z1', 'z3']], ['cool', ['z1', 'z3']], ['heat', ['z3']], ['heat', ['z3']], ['heat', ['z3']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z1', 'z3']]] | [['cool', ['z1', 'z3']], ['cool', ['z1', 'z3']], ['cool', ['z1', 'z3']], ['cool', ['z1', 'z3']], ['cool', ['z1', 'z3']], ['heat', ['z3']], ['heat', ['z3']], ['heat', ['z3']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z1', 'z3']]] | Passed |
| regression: scenario 3 | [['cool', ['z1', 'z3']], ['cool', ['z2', 'z3']], ['cool', ['z1', 'z2', 'z3']], ['cool', ['z1', 'z3']], ['heat', ['z2', 'z4']], ['heat', ['z4']], ['cool', ['z1', 'z3']], ['cool', ['z1']], ['heat', ['z3']], ['heat', ['z3']]] | [['cool', ['z1', 'z3']], ['cool', ['z2', 'z3']], ['cool', ['z1', 'z2', 'z3']], ['heat', ['z2']], ['heat', ['z2', 'z4']], ['cool', ['z1', 'z2', 'z3']], ['cool', ['z1', 'z3']], ['heat', ['z3']], ['heat', ['z3']], ['cool', ['z1']]] | Failed |
SHA-256 / 32bd6a9b5044b3305987cbc98243c60860d6d7559b517d3cc0c6033963058fb6
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(max_run, samples):
mode = None
since = 0
out = []
for minute, calls in enumerate(samples):
heat = sorted(z for z, c in calls.items() if c == 'heat')
cool = sorted(z for z, c in calls.items() if c == 'cool')
want = {'heat': heat, 'cool': cool}
if mode is not None:
other = 'cool' if mode == 'heat' else 'heat'
if not want[mode]:
mode = None
elif want[other] and minute - since > max_run:
mode = other
since = minute
if mode is None and (heat or cool):
mode = 'heat' if len(heat) >= len(cool) else 'cool'
since = minute
out.append([mode, want[mode] if mode else []])
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: scenario 1',
[5,
[{'z1': 'cool', 'z3': None, 'z4': None},
{'z1': 'heat', 'z2': 'heat', 'z3': None, 'z4': 'cool'},
{'z1': 'heat', 'z2': 'heat', 'z3': 'heat', 'z4': 'cool'},
{'z1': 'heat', 'z2': 'heat', 'z3': 'heat', 'z4': 'cool'},
{'z1': 'heat', 'z2': 'cool', 'z3': 'cool', 'z4': 'cool'},
{'z1': 'heat', 'z2': 'cool', 'z3': 'cool', 'z4': 'cool'},
{'z1': 'heat', 'z2': 'cool', 'z4': 'cool'},
{'z1': 'heat', 'z2': 'cool', 'z3': None, 'z4': 'cool'},
{'z2': 'cool', 'z4': 'heat'},
{'z1': None, 'z2': 'cool', 'z3': 'heat', 'z4': 'heat'}]],
[['cool', ['z1']],
['cool', ['z4']],
['cool', ['z4']],
['cool', ['z4']],
['cool', ['z2', 'z3', 'z4']],
['heat', ['z1']],
['heat', ['z1']],
['heat', ['z1']],
['heat', ['z4']],
['heat', ['z3', 'z4']]]],
['regression: majority then forced switch',
[3,
[{'a': 'heat', 'b': 'cool', 'c': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat'},
{}]],
[['cool', ['b', 'c']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']], ['heat', ['a']], [None, []]]],
['control: tie goes to heat',
[2, [{'a': 'heat', 'b': 'cool'}, {'a': 'heat', 'b': 'cool'}, {'b': 'cool'}]],
[['heat', ['a']], ['heat', ['a']], ['cool', ['b']]]],
['regression: ping pong guard',
[2,
[{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'}]],
[['heat', ['a']],
['heat', ['a']],
['cool', ['b']],
['cool', ['b']],
['heat', ['a']],
['heat', ['a']],
['cool', ['b']]]],
['control: satisfied then opposite',
[5, [{'a': 'cool'}, {'a': 'cool', 'b': 'heat'}, {'b': 'heat'}, {'b': 'heat'}]],
[['cool', ['a']], ['cool', ['a']], ['heat', ['b']], ['heat', ['b']]]],
['control: first minute call',
[3, [{'a': 'cool'}, {'a': 'cool'}, {}]],
[['cool', ['a']], ['cool', ['a']], [None, []]]],
['regression: scenario 2',
[5,
[{'z1': 'cool', 'z2': None, 'z3': 'cool'},
{'z1': 'cool', 'z2': None, 'z3': 'cool'},
{'z1': 'cool', 'z3': 'cool'},
{'z1': 'cool', 'z2': None, 'z3': 'cool'},
{'z1': 'cool', 'z2': None, 'z3': 'cool'},
{'z1': 'cool', 'z3': 'heat', 'z4': None},
{'z1': 'cool', 'z2': None, 'z3': 'heat'},
{'z1': 'cool', 'z2': None, 'z3': 'heat'},
{'z1': 'heat'},
{'z1': 'heat', 'z2': None, 'z4': None},
{'z1': 'heat', 'z4': None},
{'z1': 'heat', 'z2': None, 'z4': None},
{'z1': 'heat', 'z3': 'heat', 'z4': None}]],
[['cool', ['z1', 'z3']],
['cool', ['z1', 'z3']],
['cool', ['z1', 'z3']],
['cool', ['z1', 'z3']],
['cool', ['z1', 'z3']],
['heat', ['z3']],
['heat', ['z3']],
['heat', ['z3']],
['heat', ['z1']],
['heat', ['z1']],
['heat', ['z1']],
['heat', ['z1']],
['heat', ['z1', 'z3']]]],
['regression: scenario 3',
[2,
[{'z1': 'cool', 'z2': 'heat', 'z3': 'cool', 'z4': None},
{'z2': 'cool', 'z3': 'cool', 'z4': None},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': None},
{'z1': 'cool', 'z2': 'heat', 'z3': 'cool'},
{'z1': 'cool', 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z3': 'cool', 'z4': None},
{'z1': 'cool', 'z3': 'heat', 'z4': None},
{'z1': 'cool', 'z2': None, 'z3': 'heat'},
{'z1': 'cool', 'z3': 'heat'}]],
[['cool', ['z1', 'z3']],
['cool', ['z2', 'z3']],
['cool', ['z1', 'z2', 'z3']],
['heat', ['z2']],
['heat', ['z2', 'z4']],
['cool', ['z1', 'z2', 'z3']],
['cool', ['z1', 'z3']],
['heat', ['z3']],
['heat', ['z3']],
['cool', ['z1']]]]],
[['regression: scenario 2',
[3,
[{'z1': None, 'z2': 'cool', 'z3': 'heat', 'z4': 'heat'},
{'z3': 'heat', 'z4': 'heat'},
{'z1': None, 'z2': None, 'z3': 'cool', 'z4': 'cool'},
{'z3': 'cool'},
{'z2': None, 'z3': 'cool', 'z4': None},
{'z1': 'heat', 'z2': 'cool', 'z3': 'cool'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': None},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z4': 'heat'},
{'z1': 'heat', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'heat', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'}]],
[['heat', ['z3', 'z4']],
['heat', ['z3', 'z4']],
['cool', ['z3', 'z4']],
['cool', ['z3']],
['cool', ['z3']],
['heat', ['z1']],
['cool', ['z1', 'z2', 'z3']],
['cool', ['z1', 'z2', 'z3']],
['cool', ['z1', 'z2', 'z3']],
['heat', ['z4']],
['heat', ['z4']],
['heat', ['z4']],
['cool', ['z1', 'z2']],
['cool', ['z2', 'z3']],
['cool', ['z2', 'z3']]]],
['regression: ping pong guard',
[2,
[{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'}]],
[['heat', ['a']],
['heat', ['a']],
['cool', ['b']],
['cool', ['b']],
['heat', ['a']],
['heat', ['a']],
['cool', ['b']]]],
['regression: majority then forced switch',
[3,
[{'a': 'heat', 'b': 'cool', 'c': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat'},
{}]],
[['cool', ['b', 'c']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']], ['heat', ['a']], [None, []]]],
['control: tie goes to heat',
[2, [{'a': 'heat', 'b': 'cool'}, {'a': 'heat', 'b': 'cool'}, {'b': 'cool'}]],
[['heat', ['a']], ['heat', ['a']], ['cool', ['b']]]],
['control: satisfied then opposite',
[5, [{'a': 'cool'}, {'a': 'cool', 'b': 'heat'}, {'b': 'heat'}, {'b': 'heat'}]],
[['cool', ['a']], ['cool', ['a']], ['heat', ['b']], ['heat', ['b']]]],
['control: first minute call',
[3, [{'a': 'cool'}, {'a': 'cool'}, {}]],
[['cool', ['a']], ['cool', ['a']], [None, []]]],
['regression: scenario 1',
[3,
[{'z1': 'heat', 'z2': 'cool', 'z3': 'heat', 'z4': 'heat'},
{'z1': 'heat', 'z3': 'heat', 'z4': 'heat'},
{'z1': 'heat', 'z2': None, 'z3': 'heat', 'z4': 'heat'},
{'z1': None, 'z2': None, 'z3': 'heat', 'z4': 'heat'},
{'z1': 'heat', 'z3': 'heat', 'z4': 'heat'},
{'z1': 'heat', 'z2': None, 'z3': 'heat', 'z4': 'heat'},
{'z1': 'heat', 'z2': None, 'z3': 'heat', 'z4': 'cool'},
{'z1': 'heat', 'z2': None, 'z3': 'heat', 'z4': None},
{'z1': 'heat', 'z3': 'heat', 'z4': None},
{'z1': 'heat', 'z3': 'heat', 'z4': 'heat'},
{'z1': 'heat', 'z2': None, 'z3': 'heat', 'z4': 'heat'},
{'z1': 'heat', 'z2': 'heat', 'z4': 'heat'},
{'z1': 'heat', 'z2': 'heat'},
{'z1': 'heat', 'z2': 'heat', 'z3': 'heat'},
{'z1': 'heat', 'z2': 'heat', 'z3': 'cool'}]],
[['heat', ['z1', 'z3', 'z4']],
['heat', ['z1', 'z3', 'z4']],
['heat', ['z1', 'z3', 'z4']],
['heat', ['z3', 'z4']],
['heat', ['z1', 'z3', 'z4']],
['heat', ['z1', 'z3', 'z4']],
['cool', ['z4']],
['heat', ['z1', 'z3']],
['heat', ['z1', 'z3']],
['heat', ['z1', 'z3', 'z4']],
['heat', ['z1', 'z3', 'z4']],
['heat', ['z1', 'z2', 'z4']],
['heat', ['z1', 'z2']],
['heat', ['z1', 'z2', 'z3']],
['cool', ['z3']]]],
['regression: scenario 3',
[3,
[{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z1': None, 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z2': 'cool', 'z3': 'heat', 'z4': 'heat'},
{'z1': None, 'z2': 'cool', 'z3': 'heat', 'z4': 'heat'},
{'z2': 'cool', 'z3': 'heat', 'z4': 'heat'},
{'z1': None, 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
{'z1': None, 'z2': 'heat', 'z3': 'cool', 'z4': 'cool'}]],
[['cool', ['z1', 'z2', 'z3']],
['cool', ['z1', 'z2', 'z3']],
['cool', ['z1', 'z2', 'z3']],
['heat', ['z4']],
['heat', ['z4']],
['heat', ['z4']],
['cool', ['z2']],
['cool', ['z2']],
['cool', ['z2']],
['heat', ['z4']],
['heat', ['z2', 'z4']],
['heat', ['z2']]]]],
[['regression: scenario 3',
[2,
[{'z1': 'heat', 'z2': 'cool', 'z3': 'heat', 'z4': None},
{'z1': 'heat', 'z2': 'cool', 'z3': 'heat'},
{'z1': 'heat', 'z2': 'cool', 'z3': 'cool'},
{'z1': 'heat', 'z2': 'cool', 'z3': 'cool', 'z4': None},
{'z2': 'cool', 'z3': 'cool'},
{'z2': 'cool', 'z3': 'cool', 'z4': None},
{'z1': None, 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z2': 'heat', 'z3': 'cool', 'z4': 'cool'},
{'z1': None, 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'}]],
[['heat', ['z1', 'z3']],
['heat', ['z1', 'z3']],
['cool', ['z2', 'z3']],
['cool', ['z2', 'z3']],
['cool', ['z2', 'z3']],
['cool', ['z2', 'z3']],
['heat', ['z4']],
['heat', ['z4']],
['cool', ['z2', 'z3']],
['cool', ['z3', 'z4']],
['heat', ['z2', 'z4']]]],
['regression: scenario 1',
[3,
[{'z1': 'heat', 'z2': 'heat', 'z3': None, 'z4': 'cool'},
{'z1': 'heat', 'z2': 'heat', 'z3': 'cool', 'z4': 'cool'},
{'z1': 'heat', 'z2': 'heat', 'z3': 'cool', 'z4': 'cool'},
{'z1': 'heat', 'z2': 'heat', 'z3': 'cool', 'z4': 'cool'},
{'z1': 'heat', 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'heat', 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'heat', 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'heat', 'z2': 'heat', 'z3': None},
{'z1': 'heat', 'z2': 'heat'},
{'z1': 'heat', 'z2': 'heat', 'z3': None, 'z4': 'cool'},
{'z1': 'heat', 'z2': 'heat', 'z3': None, 'z4': None}]],
[['heat', ['z1', 'z2']],
['heat', ['z1', 'z2']],
['heat', ['z1', 'z2']],
['cool', ['z3', 'z4']],
['cool', ['z3']],
['cool', ['z3']],
['heat', ['z1', 'z2', 'z4']],
['heat', ['z1', 'z2']],
['heat', ['z1', 'z2']],
['cool', ['z4']],
['heat', ['z1', 'z2']]]],
['regression: majority then forced switch',
[3,
[{'a': 'heat', 'b': 'cool', 'c': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat'},
{}]],
[['cool', ['b', 'c']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']], ['heat', ['a']], [None, []]]],
['control: tie goes to heat',
[2, [{'a': 'heat', 'b': 'cool'}, {'a': 'heat', 'b': 'cool'}, {'b': 'cool'}]],
[['heat', ['a']], ['heat', ['a']], ['cool', ['b']]]],
['regression: ping pong guard',
[2,
[{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'}]],
[['heat', ['a']],
['heat', ['a']],
['cool', ['b']],
['cool', ['b']],
['heat', ['a']],
['heat', ['a']],
['cool', ['b']]]],
['control: satisfied then opposite',
[5, [{'a': 'cool'}, {'a': 'cool', 'b': 'heat'}, {'b': 'heat'}, {'b': 'heat'}]],
[['cool', ['a']], ['cool', ['a']], ['heat', ['b']], ['heat', ['b']]]],
['control: first minute call',
[3, [{'a': 'cool'}, {'a': 'cool'}, {}]],
[['cool', ['a']], ['cool', ['a']], [None, []]]],
['regression: scenario 2',
[2,
[{'z1': 'heat', 'z3': 'cool', 'z4': 'cool'},
{'z1': 'cool', 'z2': None, 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': None, 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z4': 'heat'},
{'z1': None, 'z2': 'cool', 'z3': None, 'z4': 'heat'},
{'z1': None, 'z2': 'cool', 'z3': None, 'z4': 'heat'},
{'z2': 'cool', 'z4': 'heat'},
{'z3': None}]],
[['cool', ['z3', 'z4']],
['cool', ['z1', 'z3']],
['heat', ['z4']],
['heat', ['z4']],
['cool', ['z2']],
['cool', ['z2']],
['heat', ['z4']],
[None, []]]]],
[['regression: scenario 7',
[2,
[{'z1': 'cool', 'z2': 'cool', 'z3': None, 'z4': 'cool'},
{'z1': 'cool', 'z2': 'cool', 'z4': 'cool'},
{'z1': 'heat', 'z2': 'cool', 'z3': None, 'z4': 'cool'},
{'z1': 'heat', 'z2': 'cool', 'z3': None, 'z4': 'cool'},
{'z1': 'heat', 'z2': 'cool', 'z3': None, 'z4': 'cool'},
{'z1': 'heat', 'z2': 'cool', 'z3': None, 'z4': 'cool'},
{'z1': 'heat', 'z2': 'cool', 'z4': 'cool'},
{'z1': 'heat', 'z2': 'cool', 'z3': 'heat', 'z4': 'cool'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'heat', 'z4': None},
{'z1': None, 'z2': 'cool', 'z3': 'heat'},
{'z1': 'heat', 'z2': None, 'z3': 'heat', 'z4': None},
{'z1': 'heat', 'z3': 'cool'},
{'z1': 'heat', 'z2': None, 'z3': None, 'z4': 'heat'},
{'z1': None}]],
[['cool', ['z1', 'z2', 'z4']],
['cool', ['z1', 'z2', 'z4']],
['heat', ['z1']],
['heat', ['z1']],
['cool', ['z2', 'z4']],
['cool', ['z2', 'z4']],
['heat', ['z1']],
['heat', ['z1', 'z3']],
['cool', ['z1', 'z2']],
['cool', ['z2']],
['heat', ['z1', 'z3']],
['heat', ['z1']],
['heat', ['z1', 'z4']],
[None, []]]],
['regression: scenario 3',
[5,
[{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'heat', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z2': 'cool', 'z3': 'cool', 'z4': 'heat'}]],
[['cool', ['z1', 'z2', 'z3']],
['cool', ['z1', 'z2', 'z3']],
['cool', ['z1', 'z2', 'z3']],
['cool', ['z1', 'z2', 'z3']],
['cool', ['z1', 'z3']],
['heat', ['z4']],
['heat', ['z4']],
['heat', ['z4']],
['heat', ['z4']],
['heat', ['z1', 'z4']],
['cool', ['z2', 'z3']]]],
['regression: majority then forced switch',
[3,
[{'a': 'heat', 'b': 'cool', 'c': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat'},
{}]],
[['cool', ['b', 'c']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']], ['heat', ['a']], [None, []]]],
['control: tie goes to heat',
[2, [{'a': 'heat', 'b': 'cool'}, {'a': 'heat', 'b': 'cool'}, {'b': 'cool'}]],
[['heat', ['a']], ['heat', ['a']], ['cool', ['b']]]],
['regression: ping pong guard',
[2,
[{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'}]],
[['heat', ['a']],
['heat', ['a']],
['cool', ['b']],
['cool', ['b']],
['heat', ['a']],
['heat', ['a']],
['cool', ['b']]]],
['control: satisfied then opposite',
[5, [{'a': 'cool'}, {'a': 'cool', 'b': 'heat'}, {'b': 'heat'}, {'b': 'heat'}]],
[['cool', ['a']], ['cool', ['a']], ['heat', ['b']], ['heat', ['b']]]],
['control: first minute call',
[3, [{'a': 'cool'}, {'a': 'cool'}, {}]],
[['cool', ['a']], ['cool', ['a']], [None, []]]],
['regression: scenario 1',
[5,
[{'z1': 'cool', 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
{'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
{'z1': None, 'z3': 'cool', 'z4': 'heat'},
{'z1': None, 'z3': 'cool', 'z4': 'heat'},
{'z1': None, 'z2': None, 'z3': 'cool', 'z4': 'heat'},
{'z1': None, 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'heat', 'z4': 'heat'},
{'z1': None, 'z2': 'heat', 'z4': 'heat'},
{'z2': 'heat', 'z3': 'cool', 'z4': 'cool'},
{'z2': 'heat', 'z3': 'cool', 'z4': 'cool'},
{'z2': 'heat', 'z3': 'heat', 'z4': 'cool'}]],
[['heat', ['z2', 'z4']],
['heat', ['z2', 'z4']],
['heat', ['z4']],
['heat', ['z4']],
['heat', ['z4']],
['cool', ['z3']],
['cool', ['z1']],
['heat', ['z2', 'z4']],
['heat', ['z2']],
['heat', ['z2']],
['heat', ['z2', 'z3']]]]],
[['regression: scenario 8',
[5,
[{'z4': 'cool'},
{'z1': 'cool', 'z2': 'cool', 'z4': 'cool'},
{'z1': 'cool', 'z2': 'cool', 'z4': 'cool'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'heat', 'z4': 'cool'},
{'z1': 'cool', 'z2': 'heat', 'z3': 'heat', 'z4': 'cool'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'heat', 'z4': 'cool'},
{'z1': 'cool', 'z2': 'cool', 'z3': None, 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z3': None, 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'}]],
[['cool', ['z4']],
['cool', ['z1', 'z2', 'z4']],
['cool', ['z1', 'z2', 'z4']],
['cool', ['z1', 'z2', 'z4']],
['cool', ['z1', 'z4']],
['heat', ['z3']],
['heat', ['z4']],
['heat', ['z4']],
['heat', ['z4']],
['heat', ['z4']],
['cool', ['z1', 'z2', 'z3']],
['cool', ['z1', 'z2', 'z3']]]],
['regression: scenario 3',
[2,
[{'z1': 'heat', 'z2': 'cool', 'z3': 'cool', 'z4': 'cool'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'cool'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'cool'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'cool'},
{'z2': 'cool', 'z3': 'cool', 'z4': 'cool'},
{'z1': None, 'z2': 'cool', 'z3': 'heat', 'z4': 'cool'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'heat', 'z4': 'cool'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'heat', 'z4': 'cool'},
{'z1': 'cool', 'z3': 'heat', 'z4': 'cool'},
{'z1': 'cool', 'z3': 'heat', 'z4': 'cool'}]],
[['cool', ['z2', 'z3', 'z4']],
['cool', ['z1', 'z2', 'z3', 'z4']],
['cool', ['z1', 'z2', 'z3', 'z4']],
['cool', ['z1', 'z2', 'z3', 'z4']],
['cool', ['z2', 'z3', 'z4']],
['heat', ['z3']],
['heat', ['z3']],
['cool', ['z1', 'z2', 'z4']],
['cool', ['z1', 'z4']],
['heat', ['z3']]]],
['regression: majority then forced switch',
[3,
[{'a': 'heat', 'b': 'cool', 'c': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat'},
{}]],
[['cool', ['b', 'c']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']], ['heat', ['a']], [None, []]]],
['control: tie goes to heat',
[2, [{'a': 'heat', 'b': 'cool'}, {'a': 'heat', 'b': 'cool'}, {'b': 'cool'}]],
[['heat', ['a']], ['heat', ['a']], ['cool', ['b']]]],
['regression: ping pong guard',
[2,
[{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'}]],
[['heat', ['a']],
['heat', ['a']],
['cool', ['b']],
['cool', ['b']],
['heat', ['a']],
['heat', ['a']],
['cool', ['b']]]],
['control: satisfied then opposite',
[5, [{'a': 'cool'}, {'a': 'cool', 'b': 'heat'}, {'b': 'heat'}, {'b': 'heat'}]],
[['cool', ['a']], ['cool', ['a']], ['heat', ['b']], ['heat', ['b']]]],
['control: first minute call',
[3, [{'a': 'cool'}, {'a': 'cool'}, {}]],
[['cool', ['a']], ['cool', ['a']], [None, []]]],
['regression: scenario 1',
[3,
[{'z1': 'heat', 'z2': 'heat', 'z3': 'heat', 'z4': 'heat'},
{'z1': 'heat', 'z2': 'heat', 'z3': 'heat'},
{'z1': 'heat', 'z2': 'heat', 'z3': 'heat', 'z4': 'heat'},
{'z1': 'heat', 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'heat', 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
{'z2': 'heat'},
{'z2': 'heat', 'z4': 'heat'},
{'z1': None, 'z2': 'heat', 'z3': None, 'z4': 'heat'},
{'z2': 'heat', 'z3': None, 'z4': 'heat'}]],
[['heat', ['z1', 'z2', 'z3', 'z4']],
['heat', ['z1', 'z2', 'z3']],
['heat', ['z1', 'z2', 'z3', 'z4']],
['cool', ['z3']],
['cool', ['z3']],
['heat', ['z2']],
['heat', ['z2', 'z4']],
['heat', ['z2', 'z4']],
['heat', ['z2', 'z4']]]]]]
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: scenario 1 | [['cool', ['z1']], ['cool', ['z4']], ['cool', ['z4']], ['cool', ['z4']], ['cool', ['z2', 'z3', 'z4']], ['cool', ['z2', 'z3', 'z4']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z4']], ['heat', ['z3', 'z4']]] | [['cool', ['z1']], ['cool', ['z4']], ['cool', ['z4']], ['cool', ['z4']], ['cool', ['z2', 'z3', 'z4']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z4']], ['heat', ['z3', 'z4']]] | Failed |
| regression: majority then forced switch | [['cool', ['b', 'c']], ['cool', ['b']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']], [None, []]] | [['cool', ['b', 'c']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']], ['heat', ['a']], [None, []]] | Failed |
| control: tie goes to heat | [['heat', ['a']], ['heat', ['a']], ['cool', ['b']]] | [['heat', ['a']], ['heat', ['a']], ['cool', ['b']]] | Passed |
| regression: ping pong guard | [['heat', ['a']], ['heat', ['a']], ['heat', ['a']], ['cool', ['b']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']]] | [['heat', ['a']], ['heat', ['a']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']], ['heat', ['a']], ['cool', ['b']]] | Failed |
| control: satisfied then opposite | [['cool', ['a']], ['cool', ['a']], ['heat', ['b']], ['heat', ['b']]] | [['cool', ['a']], ['cool', ['a']], ['heat', ['b']], ['heat', ['b']]] | Passed |
| control: first minute call | [['cool', ['a']], ['cool', ['a']], [None, []]] | [['cool', ['a']], ['cool', ['a']], [None, []]] | Passed |
| regression: scenario 2 | [['cool', ['z1', 'z3']], ['cool', ['z1', 'z3']], ['cool', ['z1', 'z3']], ['cool', ['z1', 'z3']], ['cool', ['z1', 'z3']], ['cool', ['z1']], ['heat', ['z3']], ['heat', ['z3']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z1', 'z3']]] | [['cool', ['z1', 'z3']], ['cool', ['z1', 'z3']], ['cool', ['z1', 'z3']], ['cool', ['z1', 'z3']], ['cool', ['z1', 'z3']], ['heat', ['z3']], ['heat', ['z3']], ['heat', ['z3']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z1', 'z3']]] | Failed |
| regression: scenario 3 | [['cool', ['z1', 'z3']], ['cool', ['z2', 'z3']], ['cool', ['z1', 'z2', 'z3']], ['heat', ['z2']], ['heat', ['z2', 'z4']], ['heat', ['z4']], ['cool', ['z1', 'z3']], ['cool', ['z1']], ['cool', ['z1']], ['heat', ['z3']]] | [['cool', ['z1', 'z3']], ['cool', ['z2', 'z3']], ['cool', ['z1', 'z2', 'z3']], ['heat', ['z2']], ['heat', ['z2', 'z4']], ['cool', ['z1', 'z2', 'z3']], ['cool', ['z1', 'z3']], ['heat', ['z3']], ['heat', ['z3']], ['cool', ['z1']]] | Failed |
SHA-256 / f0fd7e97dc401eb7194f2019a5846d74dac504ff71e952cd05bf8d6dcd248b8d
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(max_run, samples):
mode = None
since = 0
out = []
for minute, calls in enumerate(samples):
heat = sorted(z for z, c in calls.items() if c == 'heat')
cool = sorted(z for z, c in calls.items() if c == 'cool')
want = {'heat': heat, 'cool': cool}
if mode is not None:
other = 'cool' if mode == 'heat' else 'heat'
if not want[mode]:
mode = None
elif want[other] and minute - since >= max_run:
mode = other
since = minute
if mode is None and (heat or cool):
mode = 'heat' if len(heat) >= len(cool) else 'cool'
since = minute
out.append([mode, want[mode] if mode else []])
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: scenario 1',
[5,
[{'z1': 'cool', 'z3': None, 'z4': None},
{'z1': 'heat', 'z2': 'heat', 'z3': None, 'z4': 'cool'},
{'z1': 'heat', 'z2': 'heat', 'z3': 'heat', 'z4': 'cool'},
{'z1': 'heat', 'z2': 'heat', 'z3': 'heat', 'z4': 'cool'},
{'z1': 'heat', 'z2': 'cool', 'z3': 'cool', 'z4': 'cool'},
{'z1': 'heat', 'z2': 'cool', 'z3': 'cool', 'z4': 'cool'},
{'z1': 'heat', 'z2': 'cool', 'z4': 'cool'},
{'z1': 'heat', 'z2': 'cool', 'z3': None, 'z4': 'cool'},
{'z2': 'cool', 'z4': 'heat'},
{'z1': None, 'z2': 'cool', 'z3': 'heat', 'z4': 'heat'}]],
[['cool', ['z1']],
['cool', ['z4']],
['cool', ['z4']],
['cool', ['z4']],
['cool', ['z2', 'z3', 'z4']],
['heat', ['z1']],
['heat', ['z1']],
['heat', ['z1']],
['heat', ['z4']],
['heat', ['z3', 'z4']]]],
['regression: majority then forced switch',
[3,
[{'a': 'heat', 'b': 'cool', 'c': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat'},
{}]],
[['cool', ['b', 'c']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']], ['heat', ['a']], [None, []]]],
['control: tie goes to heat',
[2, [{'a': 'heat', 'b': 'cool'}, {'a': 'heat', 'b': 'cool'}, {'b': 'cool'}]],
[['heat', ['a']], ['heat', ['a']], ['cool', ['b']]]],
['regression: ping pong guard',
[2,
[{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'}]],
[['heat', ['a']],
['heat', ['a']],
['cool', ['b']],
['cool', ['b']],
['heat', ['a']],
['heat', ['a']],
['cool', ['b']]]],
['control: satisfied then opposite',
[5, [{'a': 'cool'}, {'a': 'cool', 'b': 'heat'}, {'b': 'heat'}, {'b': 'heat'}]],
[['cool', ['a']], ['cool', ['a']], ['heat', ['b']], ['heat', ['b']]]],
['control: first minute call',
[3, [{'a': 'cool'}, {'a': 'cool'}, {}]],
[['cool', ['a']], ['cool', ['a']], [None, []]]],
['regression: scenario 2',
[5,
[{'z1': 'cool', 'z2': None, 'z3': 'cool'},
{'z1': 'cool', 'z2': None, 'z3': 'cool'},
{'z1': 'cool', 'z3': 'cool'},
{'z1': 'cool', 'z2': None, 'z3': 'cool'},
{'z1': 'cool', 'z2': None, 'z3': 'cool'},
{'z1': 'cool', 'z3': 'heat', 'z4': None},
{'z1': 'cool', 'z2': None, 'z3': 'heat'},
{'z1': 'cool', 'z2': None, 'z3': 'heat'},
{'z1': 'heat'},
{'z1': 'heat', 'z2': None, 'z4': None},
{'z1': 'heat', 'z4': None},
{'z1': 'heat', 'z2': None, 'z4': None},
{'z1': 'heat', 'z3': 'heat', 'z4': None}]],
[['cool', ['z1', 'z3']],
['cool', ['z1', 'z3']],
['cool', ['z1', 'z3']],
['cool', ['z1', 'z3']],
['cool', ['z1', 'z3']],
['heat', ['z3']],
['heat', ['z3']],
['heat', ['z3']],
['heat', ['z1']],
['heat', ['z1']],
['heat', ['z1']],
['heat', ['z1']],
['heat', ['z1', 'z3']]]],
['regression: scenario 3',
[2,
[{'z1': 'cool', 'z2': 'heat', 'z3': 'cool', 'z4': None},
{'z2': 'cool', 'z3': 'cool', 'z4': None},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': None},
{'z1': 'cool', 'z2': 'heat', 'z3': 'cool'},
{'z1': 'cool', 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z3': 'cool', 'z4': None},
{'z1': 'cool', 'z3': 'heat', 'z4': None},
{'z1': 'cool', 'z2': None, 'z3': 'heat'},
{'z1': 'cool', 'z3': 'heat'}]],
[['cool', ['z1', 'z3']],
['cool', ['z2', 'z3']],
['cool', ['z1', 'z2', 'z3']],
['heat', ['z2']],
['heat', ['z2', 'z4']],
['cool', ['z1', 'z2', 'z3']],
['cool', ['z1', 'z3']],
['heat', ['z3']],
['heat', ['z3']],
['cool', ['z1']]]]],
[['regression: scenario 2',
[3,
[{'z1': None, 'z2': 'cool', 'z3': 'heat', 'z4': 'heat'},
{'z3': 'heat', 'z4': 'heat'},
{'z1': None, 'z2': None, 'z3': 'cool', 'z4': 'cool'},
{'z3': 'cool'},
{'z2': None, 'z3': 'cool', 'z4': None},
{'z1': 'heat', 'z2': 'cool', 'z3': 'cool'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': None},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z4': 'heat'},
{'z1': 'heat', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'heat', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'}]],
[['heat', ['z3', 'z4']],
['heat', ['z3', 'z4']],
['cool', ['z3', 'z4']],
['cool', ['z3']],
['cool', ['z3']],
['heat', ['z1']],
['cool', ['z1', 'z2', 'z3']],
['cool', ['z1', 'z2', 'z3']],
['cool', ['z1', 'z2', 'z3']],
['heat', ['z4']],
['heat', ['z4']],
['heat', ['z4']],
['cool', ['z1', 'z2']],
['cool', ['z2', 'z3']],
['cool', ['z2', 'z3']]]],
['regression: ping pong guard',
[2,
[{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'}]],
[['heat', ['a']],
['heat', ['a']],
['cool', ['b']],
['cool', ['b']],
['heat', ['a']],
['heat', ['a']],
['cool', ['b']]]],
['regression: majority then forced switch',
[3,
[{'a': 'heat', 'b': 'cool', 'c': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat'},
{}]],
[['cool', ['b', 'c']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']], ['heat', ['a']], [None, []]]],
['control: tie goes to heat',
[2, [{'a': 'heat', 'b': 'cool'}, {'a': 'heat', 'b': 'cool'}, {'b': 'cool'}]],
[['heat', ['a']], ['heat', ['a']], ['cool', ['b']]]],
['control: satisfied then opposite',
[5, [{'a': 'cool'}, {'a': 'cool', 'b': 'heat'}, {'b': 'heat'}, {'b': 'heat'}]],
[['cool', ['a']], ['cool', ['a']], ['heat', ['b']], ['heat', ['b']]]],
['control: first minute call',
[3, [{'a': 'cool'}, {'a': 'cool'}, {}]],
[['cool', ['a']], ['cool', ['a']], [None, []]]],
['regression: scenario 1',
[3,
[{'z1': 'heat', 'z2': 'cool', 'z3': 'heat', 'z4': 'heat'},
{'z1': 'heat', 'z3': 'heat', 'z4': 'heat'},
{'z1': 'heat', 'z2': None, 'z3': 'heat', 'z4': 'heat'},
{'z1': None, 'z2': None, 'z3': 'heat', 'z4': 'heat'},
{'z1': 'heat', 'z3': 'heat', 'z4': 'heat'},
{'z1': 'heat', 'z2': None, 'z3': 'heat', 'z4': 'heat'},
{'z1': 'heat', 'z2': None, 'z3': 'heat', 'z4': 'cool'},
{'z1': 'heat', 'z2': None, 'z3': 'heat', 'z4': None},
{'z1': 'heat', 'z3': 'heat', 'z4': None},
{'z1': 'heat', 'z3': 'heat', 'z4': 'heat'},
{'z1': 'heat', 'z2': None, 'z3': 'heat', 'z4': 'heat'},
{'z1': 'heat', 'z2': 'heat', 'z4': 'heat'},
{'z1': 'heat', 'z2': 'heat'},
{'z1': 'heat', 'z2': 'heat', 'z3': 'heat'},
{'z1': 'heat', 'z2': 'heat', 'z3': 'cool'}]],
[['heat', ['z1', 'z3', 'z4']],
['heat', ['z1', 'z3', 'z4']],
['heat', ['z1', 'z3', 'z4']],
['heat', ['z3', 'z4']],
['heat', ['z1', 'z3', 'z4']],
['heat', ['z1', 'z3', 'z4']],
['cool', ['z4']],
['heat', ['z1', 'z3']],
['heat', ['z1', 'z3']],
['heat', ['z1', 'z3', 'z4']],
['heat', ['z1', 'z3', 'z4']],
['heat', ['z1', 'z2', 'z4']],
['heat', ['z1', 'z2']],
['heat', ['z1', 'z2', 'z3']],
['cool', ['z3']]]],
['regression: scenario 3',
[3,
[{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z1': None, 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z2': 'cool', 'z3': 'heat', 'z4': 'heat'},
{'z1': None, 'z2': 'cool', 'z3': 'heat', 'z4': 'heat'},
{'z2': 'cool', 'z3': 'heat', 'z4': 'heat'},
{'z1': None, 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
{'z1': None, 'z2': 'heat', 'z3': 'cool', 'z4': 'cool'}]],
[['cool', ['z1', 'z2', 'z3']],
['cool', ['z1', 'z2', 'z3']],
['cool', ['z1', 'z2', 'z3']],
['heat', ['z4']],
['heat', ['z4']],
['heat', ['z4']],
['cool', ['z2']],
['cool', ['z2']],
['cool', ['z2']],
['heat', ['z4']],
['heat', ['z2', 'z4']],
['heat', ['z2']]]]],
[['regression: scenario 3',
[2,
[{'z1': 'heat', 'z2': 'cool', 'z3': 'heat', 'z4': None},
{'z1': 'heat', 'z2': 'cool', 'z3': 'heat'},
{'z1': 'heat', 'z2': 'cool', 'z3': 'cool'},
{'z1': 'heat', 'z2': 'cool', 'z3': 'cool', 'z4': None},
{'z2': 'cool', 'z3': 'cool'},
{'z2': 'cool', 'z3': 'cool', 'z4': None},
{'z1': None, 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z2': 'heat', 'z3': 'cool', 'z4': 'cool'},
{'z1': None, 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'}]],
[['heat', ['z1', 'z3']],
['heat', ['z1', 'z3']],
['cool', ['z2', 'z3']],
['cool', ['z2', 'z3']],
['cool', ['z2', 'z3']],
['cool', ['z2', 'z3']],
['heat', ['z4']],
['heat', ['z4']],
['cool', ['z2', 'z3']],
['cool', ['z3', 'z4']],
['heat', ['z2', 'z4']]]],
['regression: scenario 1',
[3,
[{'z1': 'heat', 'z2': 'heat', 'z3': None, 'z4': 'cool'},
{'z1': 'heat', 'z2': 'heat', 'z3': 'cool', 'z4': 'cool'},
{'z1': 'heat', 'z2': 'heat', 'z3': 'cool', 'z4': 'cool'},
{'z1': 'heat', 'z2': 'heat', 'z3': 'cool', 'z4': 'cool'},
{'z1': 'heat', 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'heat', 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'heat', 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'heat', 'z2': 'heat', 'z3': None},
{'z1': 'heat', 'z2': 'heat'},
{'z1': 'heat', 'z2': 'heat', 'z3': None, 'z4': 'cool'},
{'z1': 'heat', 'z2': 'heat', 'z3': None, 'z4': None}]],
[['heat', ['z1', 'z2']],
['heat', ['z1', 'z2']],
['heat', ['z1', 'z2']],
['cool', ['z3', 'z4']],
['cool', ['z3']],
['cool', ['z3']],
['heat', ['z1', 'z2', 'z4']],
['heat', ['z1', 'z2']],
['heat', ['z1', 'z2']],
['cool', ['z4']],
['heat', ['z1', 'z2']]]],
['regression: majority then forced switch',
[3,
[{'a': 'heat', 'b': 'cool', 'c': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat'},
{}]],
[['cool', ['b', 'c']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']], ['heat', ['a']], [None, []]]],
['control: tie goes to heat',
[2, [{'a': 'heat', 'b': 'cool'}, {'a': 'heat', 'b': 'cool'}, {'b': 'cool'}]],
[['heat', ['a']], ['heat', ['a']], ['cool', ['b']]]],
['regression: ping pong guard',
[2,
[{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'}]],
[['heat', ['a']],
['heat', ['a']],
['cool', ['b']],
['cool', ['b']],
['heat', ['a']],
['heat', ['a']],
['cool', ['b']]]],
['control: satisfied then opposite',
[5, [{'a': 'cool'}, {'a': 'cool', 'b': 'heat'}, {'b': 'heat'}, {'b': 'heat'}]],
[['cool', ['a']], ['cool', ['a']], ['heat', ['b']], ['heat', ['b']]]],
['control: first minute call',
[3, [{'a': 'cool'}, {'a': 'cool'}, {}]],
[['cool', ['a']], ['cool', ['a']], [None, []]]],
['regression: scenario 2',
[2,
[{'z1': 'heat', 'z3': 'cool', 'z4': 'cool'},
{'z1': 'cool', 'z2': None, 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': None, 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z4': 'heat'},
{'z1': None, 'z2': 'cool', 'z3': None, 'z4': 'heat'},
{'z1': None, 'z2': 'cool', 'z3': None, 'z4': 'heat'},
{'z2': 'cool', 'z4': 'heat'},
{'z3': None}]],
[['cool', ['z3', 'z4']],
['cool', ['z1', 'z3']],
['heat', ['z4']],
['heat', ['z4']],
['cool', ['z2']],
['cool', ['z2']],
['heat', ['z4']],
[None, []]]]],
[['regression: scenario 7',
[2,
[{'z1': 'cool', 'z2': 'cool', 'z3': None, 'z4': 'cool'},
{'z1': 'cool', 'z2': 'cool', 'z4': 'cool'},
{'z1': 'heat', 'z2': 'cool', 'z3': None, 'z4': 'cool'},
{'z1': 'heat', 'z2': 'cool', 'z3': None, 'z4': 'cool'},
{'z1': 'heat', 'z2': 'cool', 'z3': None, 'z4': 'cool'},
{'z1': 'heat', 'z2': 'cool', 'z3': None, 'z4': 'cool'},
{'z1': 'heat', 'z2': 'cool', 'z4': 'cool'},
{'z1': 'heat', 'z2': 'cool', 'z3': 'heat', 'z4': 'cool'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'heat', 'z4': None},
{'z1': None, 'z2': 'cool', 'z3': 'heat'},
{'z1': 'heat', 'z2': None, 'z3': 'heat', 'z4': None},
{'z1': 'heat', 'z3': 'cool'},
{'z1': 'heat', 'z2': None, 'z3': None, 'z4': 'heat'},
{'z1': None}]],
[['cool', ['z1', 'z2', 'z4']],
['cool', ['z1', 'z2', 'z4']],
['heat', ['z1']],
['heat', ['z1']],
['cool', ['z2', 'z4']],
['cool', ['z2', 'z4']],
['heat', ['z1']],
['heat', ['z1', 'z3']],
['cool', ['z1', 'z2']],
['cool', ['z2']],
['heat', ['z1', 'z3']],
['heat', ['z1']],
['heat', ['z1', 'z4']],
[None, []]]],
['regression: scenario 3',
[5,
[{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'heat', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z2': 'cool', 'z3': 'cool', 'z4': 'heat'}]],
[['cool', ['z1', 'z2', 'z3']],
['cool', ['z1', 'z2', 'z3']],
['cool', ['z1', 'z2', 'z3']],
['cool', ['z1', 'z2', 'z3']],
['cool', ['z1', 'z3']],
['heat', ['z4']],
['heat', ['z4']],
['heat', ['z4']],
['heat', ['z4']],
['heat', ['z1', 'z4']],
['cool', ['z2', 'z3']]]],
['regression: majority then forced switch',
[3,
[{'a': 'heat', 'b': 'cool', 'c': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat'},
{}]],
[['cool', ['b', 'c']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']], ['heat', ['a']], [None, []]]],
['control: tie goes to heat',
[2, [{'a': 'heat', 'b': 'cool'}, {'a': 'heat', 'b': 'cool'}, {'b': 'cool'}]],
[['heat', ['a']], ['heat', ['a']], ['cool', ['b']]]],
['regression: ping pong guard',
[2,
[{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'}]],
[['heat', ['a']],
['heat', ['a']],
['cool', ['b']],
['cool', ['b']],
['heat', ['a']],
['heat', ['a']],
['cool', ['b']]]],
['control: satisfied then opposite',
[5, [{'a': 'cool'}, {'a': 'cool', 'b': 'heat'}, {'b': 'heat'}, {'b': 'heat'}]],
[['cool', ['a']], ['cool', ['a']], ['heat', ['b']], ['heat', ['b']]]],
['control: first minute call',
[3, [{'a': 'cool'}, {'a': 'cool'}, {}]],
[['cool', ['a']], ['cool', ['a']], [None, []]]],
['regression: scenario 1',
[5,
[{'z1': 'cool', 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
{'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
{'z1': None, 'z3': 'cool', 'z4': 'heat'},
{'z1': None, 'z3': 'cool', 'z4': 'heat'},
{'z1': None, 'z2': None, 'z3': 'cool', 'z4': 'heat'},
{'z1': None, 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'heat', 'z4': 'heat'},
{'z1': None, 'z2': 'heat', 'z4': 'heat'},
{'z2': 'heat', 'z3': 'cool', 'z4': 'cool'},
{'z2': 'heat', 'z3': 'cool', 'z4': 'cool'},
{'z2': 'heat', 'z3': 'heat', 'z4': 'cool'}]],
[['heat', ['z2', 'z4']],
['heat', ['z2', 'z4']],
['heat', ['z4']],
['heat', ['z4']],
['heat', ['z4']],
['cool', ['z3']],
['cool', ['z1']],
['heat', ['z2', 'z4']],
['heat', ['z2']],
['heat', ['z2']],
['heat', ['z2', 'z3']]]]],
[['regression: scenario 8',
[5,
[{'z4': 'cool'},
{'z1': 'cool', 'z2': 'cool', 'z4': 'cool'},
{'z1': 'cool', 'z2': 'cool', 'z4': 'cool'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'heat', 'z4': 'cool'},
{'z1': 'cool', 'z2': 'heat', 'z3': 'heat', 'z4': 'cool'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'heat', 'z4': 'cool'},
{'z1': 'cool', 'z2': 'cool', 'z3': None, 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z3': None, 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'}]],
[['cool', ['z4']],
['cool', ['z1', 'z2', 'z4']],
['cool', ['z1', 'z2', 'z4']],
['cool', ['z1', 'z2', 'z4']],
['cool', ['z1', 'z4']],
['heat', ['z3']],
['heat', ['z4']],
['heat', ['z4']],
['heat', ['z4']],
['heat', ['z4']],
['cool', ['z1', 'z2', 'z3']],
['cool', ['z1', 'z2', 'z3']]]],
['regression: scenario 3',
[2,
[{'z1': 'heat', 'z2': 'cool', 'z3': 'cool', 'z4': 'cool'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'cool'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'cool'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'cool'},
{'z2': 'cool', 'z3': 'cool', 'z4': 'cool'},
{'z1': None, 'z2': 'cool', 'z3': 'heat', 'z4': 'cool'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'heat', 'z4': 'cool'},
{'z1': 'cool', 'z2': 'cool', 'z3': 'heat', 'z4': 'cool'},
{'z1': 'cool', 'z3': 'heat', 'z4': 'cool'},
{'z1': 'cool', 'z3': 'heat', 'z4': 'cool'}]],
[['cool', ['z2', 'z3', 'z4']],
['cool', ['z1', 'z2', 'z3', 'z4']],
['cool', ['z1', 'z2', 'z3', 'z4']],
['cool', ['z1', 'z2', 'z3', 'z4']],
['cool', ['z2', 'z3', 'z4']],
['heat', ['z3']],
['heat', ['z3']],
['cool', ['z1', 'z2', 'z4']],
['cool', ['z1', 'z4']],
['heat', ['z3']]]],
['regression: majority then forced switch',
[3,
[{'a': 'heat', 'b': 'cool', 'c': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat'},
{}]],
[['cool', ['b', 'c']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']], ['heat', ['a']], [None, []]]],
['control: tie goes to heat',
[2, [{'a': 'heat', 'b': 'cool'}, {'a': 'heat', 'b': 'cool'}, {'b': 'cool'}]],
[['heat', ['a']], ['heat', ['a']], ['cool', ['b']]]],
['regression: ping pong guard',
[2,
[{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'},
{'a': 'heat', 'b': 'cool'}]],
[['heat', ['a']],
['heat', ['a']],
['cool', ['b']],
['cool', ['b']],
['heat', ['a']],
['heat', ['a']],
['cool', ['b']]]],
['control: satisfied then opposite',
[5, [{'a': 'cool'}, {'a': 'cool', 'b': 'heat'}, {'b': 'heat'}, {'b': 'heat'}]],
[['cool', ['a']], ['cool', ['a']], ['heat', ['b']], ['heat', ['b']]]],
['control: first minute call',
[3, [{'a': 'cool'}, {'a': 'cool'}, {}]],
[['cool', ['a']], ['cool', ['a']], [None, []]]],
['regression: scenario 1',
[3,
[{'z1': 'heat', 'z2': 'heat', 'z3': 'heat', 'z4': 'heat'},
{'z1': 'heat', 'z2': 'heat', 'z3': 'heat'},
{'z1': 'heat', 'z2': 'heat', 'z3': 'heat', 'z4': 'heat'},
{'z1': 'heat', 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
{'z1': 'heat', 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
{'z2': 'heat'},
{'z2': 'heat', 'z4': 'heat'},
{'z1': None, 'z2': 'heat', 'z3': None, 'z4': 'heat'},
{'z2': 'heat', 'z3': None, 'z4': 'heat'}]],
[['heat', ['z1', 'z2', 'z3', 'z4']],
['heat', ['z1', 'z2', 'z3']],
['heat', ['z1', 'z2', 'z3', 'z4']],
['cool', ['z3']],
['cool', ['z3']],
['heat', ['z2']],
['heat', ['z2', 'z4']],
['heat', ['z2', 'z4']],
['heat', ['z2', 'z4']]]]]]
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: scenario 1 | [['cool', ['z1']], ['cool', ['z4']], ['cool', ['z4']], ['cool', ['z4']], ['cool', ['z2', 'z3', 'z4']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z4']], ['heat', ['z3', 'z4']]] | [['cool', ['z1']], ['cool', ['z4']], ['cool', ['z4']], ['cool', ['z4']], ['cool', ['z2', 'z3', 'z4']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z4']], ['heat', ['z3', 'z4']]] | Passed |
| regression: majority then forced switch | [['cool', ['b', 'c']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']], ['heat', ['a']], [None, []]] | [['cool', ['b', 'c']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']], ['heat', ['a']], [None, []]] | Passed |
| control: tie goes to heat | [['heat', ['a']], ['heat', ['a']], ['cool', ['b']]] | [['heat', ['a']], ['heat', ['a']], ['cool', ['b']]] | Passed |
| regression: ping pong guard | [['heat', ['a']], ['heat', ['a']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']], ['heat', ['a']], ['cool', ['b']]] | [['heat', ['a']], ['heat', ['a']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']], ['heat', ['a']], ['cool', ['b']]] | Passed |
| control: satisfied then opposite | [['cool', ['a']], ['cool', ['a']], ['heat', ['b']], ['heat', ['b']]] | [['cool', ['a']], ['cool', ['a']], ['heat', ['b']], ['heat', ['b']]] | Passed |
| control: first minute call | [['cool', ['a']], ['cool', ['a']], [None, []]] | [['cool', ['a']], ['cool', ['a']], [None, []]] | Passed |
| regression: scenario 2 | [['cool', ['z1', 'z3']], ['cool', ['z1', 'z3']], ['cool', ['z1', 'z3']], ['cool', ['z1', 'z3']], ['cool', ['z1', 'z3']], ['heat', ['z3']], ['heat', ['z3']], ['heat', ['z3']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z1', 'z3']]] | [['cool', ['z1', 'z3']], ['cool', ['z1', 'z3']], ['cool', ['z1', 'z3']], ['cool', ['z1', 'z3']], ['cool', ['z1', 'z3']], ['heat', ['z3']], ['heat', ['z3']], ['heat', ['z3']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z1', 'z3']]] | Passed |
| regression: scenario 3 | [['cool', ['z1', 'z3']], ['cool', ['z2', 'z3']], ['cool', ['z1', 'z2', 'z3']], ['heat', ['z2']], ['heat', ['z2', 'z4']], ['cool', ['z1', 'z2', 'z3']], ['cool', ['z1', 'z3']], ['heat', ['z3']], ['heat', ['z3']], ['cool', ['z1']]] | [['cool', ['z1', 'z3']], ['cool', ['z2', 'z3']], ['cool', ['z1', 'z2', 'z3']], ['heat', ['z2']], ['heat', ['z2', 'z4']], ['cool', ['z1', 'z2', 'z3']], ['cool', ['z1', 'z3']], ['heat', ['z3']], ['heat', ['z3']], ['cool', ['z1']]] | Passed |
SHA-256 / c1a86f58ffbe2d7e2de9fdc20c8ad4d10740780e265611f4cd36bb0096ae72d6
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:49.411382+00:00.
Case digest / 6abc41d9f3fd8d83cac3ebd43326b6ccf67ea4d727ece62a041e0fcbf83aaa2a