FAILURE MAP
← Case archive

FA-94656 / Exam timetabling constraints / Open access

Room penalty charged once per room for all exams · case 01

Only the first exam using an unpopular room pays its penalty.

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

ROOT CAUSE

Room charges are deduplicated by room alone.

VERIFIED REPAIR

Charge each exam once per room it uses.

Unsuccessful approach: Deduplicating by room and period lets exams sharing a room-period escape.

Case contract

Assignment rows [exam, room, period] (a split exam has one row per room; rows may repeat). Each exam pays its period penalty once per distinct period it occupies and each room penalty once per distinct (exam, room). Return [period penalty, room penalty, total].

Why this case matters

Period and room preferences are soft costs that must not be multiplied by exam splitting.

1 / The failure

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

N = 1
observations = []
def solve(assign, ppen, rpen):
    seen_exam = set()
    seen_room = set()
    pp = rp = 0
    for ex, r, p in assign:
        if (ex, p) not in seen_exam:
            seen_exam.add((ex, p))
            pp += ppen[p]
        if r not in seen_room:
            seen_room.add(r)
            rp += rpen[r]
    return [pp, rp, pp + rp]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: room charge key 1', [[['A', 'R2', 0], ['B', 'R2', 0]], [2, 5, 0, 0], {'R1': 0, 'R2': 3}],
   [4, 6, 10]),
  ('regression variant: room charge key 2',
   [[['PHYS110', 'R2', 2], ['CHEM120', 'R3', 1], ['MATH101H', 'R2', 3], ['CHEM120', 'R2', 3],
     ['PHYS110', 'R1', 3], ['PHYS110', 'R2', 1]],
    [10, 10, 5, 0], {'R1': 0, 'R2': 3, 'R3': 2}],
   [25, 11, 36]),
  ('partial repair guard 3',
   [[['PHYS110', 'R3', 0], ['MATH101H', 'R3', 0], ['CHEM120', 'R1', 0], ['MATH101H', 'R2', 0],
     ['CHEM120', 'R3', 2]],
    [5, 10, 5, 5], {'R1': 0, 'R2': 1, 'R3': 7}],
   [20, 22, 42]),
  ('boundary control 4', [[['A', 'R1', 1], ['A', 'R2', 1]], [0, 5, 0, 0], {'R1': 0, 'R2': 3}], [5, 3, 8]),
  ('normal control 5',
   [[['MATH101H', 'R3', 1], ['MATH101', 'R1', 2], ['MATH101', 'R2', 1], ['CHEM120', 'R2', 2]], [1, 0, 0, 1],
    {'R1': 0, 'R2': 3, 'R3': 7}],
   [0, 13, 13]),
  ('normal control 6',
   [[['MATH101', 'R2', 2], ['CHEM120', 'R1', 1], ['MATH101H', 'R3', 0], ['MATH101', 'R1', 2],
     ['MATH101', 'R2', 2]],
    [0, 1, 0, 10], {'R1': 0, 'R2': 3, 'R3': 7}],
   [1, 10, 11]),
  ('normal control 7',
   [[['MATH101', 'R1', 2], ['MATH101H', 'R3', 3], ['PHYS110', 'R1', 3], ['MATH101H', 'R3', 2],
     ['MATH101', 'R2', 0]],
    [5, 10, 1, 1], {'R1': 0, 'R2': 3, 'R3': 2}],
   [9, 5, 14]),
  ('normal control 8',
   [[['MATH101H', 'R3', 1], ['CHEM120', 'R2', 0], ['CHEM120', 'R2', 0]], [5, 10, 0, 0],
    {'R1': 0, 'R2': 3, 'R3': 2}],
   [15, 5, 20])],
 [('regression: room charge key 1',
   [[['CHEM120', 'R1', 2], ['CHEM120', 'R3', 2], ['PHYS110', 'R2', 1], ['PHYS110', 'R1', 3],
     ['MATH101', 'R1', 1], ['MATH101H', 'R2', 0]],
    [1, 1, 0, 10], {'R1': 0, 'R2': 3, 'R3': 2}],
   [13, 8, 21]),
  ('regression variant: room charge key 2',
   [[['PHYS110', 'R3', 0], ['PHYS110', 'R1', 2], ['MATH101', 'R1', 2], ['MATH101H', 'R2', 2],
     ['MATH101H', 'R2', 3], ['MATH101', 'R3', 1], ['CHEM120', 'R3', 3], ['PHYS110', 'R3', 0]],
    [1, 1, 5, 10], {'R1': 0, 'R2': 3, 'R3': 7}],
   [37, 24, 61]),
  ('partial repair guard 3',
   [[['MATH101', 'R2', 1], ['PHYS110', 'R3', 1], ['MATH101H', 'R1', 2], ['PHYS110', 'R3', 3]], [1, 5, 10, 0],
    {'R1': 0, 'R2': 1, 'R3': 7}],
   [20, 8, 28]),
  ('boundary control 4', [[['A', 'R1', 1], ['A', 'R2', 1]], [0, 5, 0, 0], {'R1': 0, 'R2': 3}], [5, 3, 8]),
  ('boundary control 5', [[['A', 'R2', 0], ['B', 'R2', 0]], [2, 5, 0, 0], {'R1': 0, 'R2': 3}], [4, 6, 10]),
  ('normal control 6',
   [[['CHEM120', 'R2', 3], ['PHYS110', 'R2', 2], ['PHYS110', 'R2', 2], ['CHEM120', 'R1', 2],
     ['MATH101H', 'R2', 2], ['PHYS110', 'R1', 2], ['MATH101H', 'R2', 2], ['CHEM120', 'R1', 2]],
    [10, 10, 5, 1], {'R1': 0, 'R2': 3, 'R3': 7}],
   [16, 9, 25]),
  ('normal control 7',
   [[['CHEM120', 'R2', 0], ['PHYS110', 'R2', 0]], [10, 10, 1, 10], {'R1': 0, 'R2': 3, 'R3': 2}],
   [20, 6, 26]),
  ('normal control 8',
   [[['CHEM120', 'R3', 3], ['MATH101H', 'R3', 2], ['MATH101H', 'R3', 2], ['MATH101H', 'R2', 3],
     ['MATH101H', 'R3', 2]],
    [5, 0, 5, 5], {'R1': 0, 'R2': 1, 'R3': 7}],
   [15, 15, 30])],
 [('regression: room charge key 1',
   [[['CHEM120', 'R2', 0], ['MATH101H', 'R1', 3], ['PHYS110', 'R2', 3], ['PHYS110', 'R2', 3],
     ['PHYS110', 'R2', 3]],
    [1, 1, 0, 1], {'R1': 0, 'R2': 1, 'R3': 2}],
   [3, 2, 5]),
  ('regression variant: room charge key 2',
   [[['MATH101', 'R2', 1], ['PHYS110', 'R1', 0], ['MATH101', 'R3', 1], ['MATH101', 'R1', 0],
     ['CHEM120', 'R1', 0], ['MATH101H', 'R1', 0], ['MATH101H', 'R3', 1]],
    [0, 1, 10, 5], {'R1': 0, 'R2': 1, 'R3': 2}],
   [2, 5, 7]),
  ('partial repair guard 3',
   [[['MATH101', 'R2', 3], ['MATH101', 'R2', 0], ['PHYS110', 'R1', 2], ['PHYS110', 'R3', 3],
     ['MATH101H', 'R3', 2], ['CHEM120', 'R3', 1]],
    [10, 5, 5, 10], {'R1': 0, 'R2': 3, 'R3': 2}],
   [45, 9, 54]),
  ('boundary control 4', [[['A', 'R1', 1], ['A', 'R2', 1]], [0, 5, 0, 0], {'R1': 0, 'R2': 3}], [5, 3, 8]),
  ('boundary control 5', [[['A', 'R2', 0], ['B', 'R2', 0]], [2, 5, 0, 0], {'R1': 0, 'R2': 3}], [4, 6, 10]),
  ('normal control 6',
   [[['CHEM120', 'R3', 1], ['CHEM120', 'R3', 3], ['PHYS110', 'R1', 3], ['CHEM120', 'R2', 2],
     ['CHEM120', 'R3', 1]],
    [0, 0, 0, 0], {'R1': 0, 'R2': 1, 'R3': 2}],
   [0, 3, 3]),
  ('normal control 7',
   [[['MATH101', 'R2', 1], ['MATH101', 'R1', 0], ['CHEM120', 'R2', 3], ['MATH101H', 'R2', 0],
     ['MATH101', 'R2', 0]],
    [0, 1, 10, 5], {'R1': 0, 'R2': 1, 'R3': 7}],
   [6, 3, 9]),
  ('normal control 8',
   [[['MATH101H', 'R2', 3], ['PHYS110', 'R1', 3], ['MATH101', 'R1', 2], ['CHEM120', 'R2', 3]], [5, 10, 5, 0],
    {'R1': 0, 'R2': 1, 'R3': 7}],
   [5, 2, 7])],
 [('regression: room charge key 1',
   [[['CHEM120', 'R1', 2], ['MATH101', 'R2', 3], ['PHYS110', 'R2', 1], ['CHEM120', 'R1', 2]], [10, 5, 5, 1],
    {'R1': 0, 'R2': 3, 'R3': 7}],
   [11, 6, 17]),
  ('regression variant: room charge key 2',
   [[['PHYS110', 'R1', 1], ['CHEM120', 'R3', 0], ['PHYS110', 'R1', 3], ['PHYS110', 'R3', 0],
     ['CHEM120', 'R2', 1], ['PHYS110', 'R2', 0]],
    [1, 10, 0, 0], {'R1': 0, 'R2': 1, 'R3': 7}],
   [22, 16, 38]),
  ('partial repair guard 3',
   [[['PHYS110', 'R2', 0], ['CHEM120', 'R1', 0], ['MATH101', 'R1', 2], ['MATH101H', 'R1', 0],
     ['PHYS110', 'R2', 2], ['MATH101', 'R1', 0], ['MATH101', 'R3', 3]],
    [10, 10, 5, 0], {'R1': 0, 'R2': 1, 'R3': 7}],
   [50, 8, 58]),
  ('boundary control 4', [[['A', 'R1', 1], ['A', 'R2', 1]], [0, 5, 0, 0], {'R1': 0, 'R2': 3}], [5, 3, 8]),
  ('boundary control 5', [[['A', 'R2', 0], ['B', 'R2', 0]], [2, 5, 0, 0], {'R1': 0, 'R2': 3}], [4, 6, 10]),
  ('normal control 6',
   [[['PHYS110', 'R3', 2], ['MATH101H', 'R2', 1], ['MATH101H', 'R2', 1], ['CHEM120', 'R3', 0],
     ['MATH101', 'R3', 3], ['MATH101', 'R2', 2]],
    [0, 5, 1, 5], {'R1': 0, 'R2': 1, 'R3': 7}],
   [12, 23, 35]),
  ('normal control 7',
   [[['MATH101H', 'R1', 2], ['MATH101H', 'R3', 0], ['MATH101H', 'R1', 0], ['MATH101H', 'R1', 3],
     ['PHYS110', 'R1', 3], ['PHYS110', 'R2', 1]],
    [1, 10, 0, 10], {'R1': 0, 'R2': 3, 'R3': 7}],
   [31, 10, 41]),
  ('normal control 8',
   [[['CHEM120', 'R3', 3], ['PHYS110', 'R1', 2], ['PHYS110', 'R1', 2]], [0, 1, 10, 0],
    {'R1': 0, 'R2': 1, 'R3': 7}],
   [10, 7, 17])],
 [('regression: room charge key 1',
   [[['PHYS110', 'R3', 2], ['CHEM120', 'R1', 2], ['MATH101', 'R1', 2], ['CHEM120', 'R3', 3],
     ['CHEM120', 'R1', 3], ['CHEM120', 'R3', 3]],
    [0, 0, 5, 1], {'R1': 0, 'R2': 3, 'R3': 2}],
   [16, 4, 20]),
  ('regression variant: room charge key 2',
   [[['CHEM120', 'R3', 3], ['MATH101', 'R2', 0], ['PHYS110', 'R2', 1], ['CHEM120', 'R2', 3],
     ['PHYS110', 'R3', 0], ['CHEM120', 'R2', 3], ['MATH101H', 'R1', 3]],
    [1, 10, 10, 5], {'R1': 0, 'R2': 3, 'R3': 2}],
   [22, 13, 35]),
  ('partial repair guard 3',
   [[['PHYS110', 'R1', 2], ['CHEM120', 'R2', 1], ['MATH101H', 'R3', 2], ['MATH101', 'R3', 0],
     ['CHEM120', 'R2', 1], ['MATH101H', 'R3', 1]],
    [10, 0, 10, 0], {'R1': 0, 'R2': 3, 'R3': 2}],
   [30, 7, 37]),
  ('boundary control 4', [[['A', 'R1', 1], ['A', 'R2', 1]], [0, 5, 0, 0], {'R1': 0, 'R2': 3}], [5, 3, 8]),
  ('boundary control 5', [[['A', 'R2', 0], ['B', 'R2', 0]], [2, 5, 0, 0], {'R1': 0, 'R2': 3}], [4, 6, 10]),
  ('normal control 6',
   [[['CHEM120', 'R1', 3], ['MATH101', 'R3', 1], ['MATH101', 'R2', 0], ['MATH101H', 'R1', 1],
     ['MATH101', 'R2', 2]],
    [0, 10, 5, 0], {'R1': 0, 'R2': 1, 'R3': 2}],
   [25, 3, 28]),
  ('normal control 7',
   [[['MATH101H', 'R3', 1], ['MATH101H', 'R1', 1]], [0, 5, 5, 5], {'R1': 0, 'R2': 3, 'R3': 2}], [5, 2, 7]),
  ('normal control 8',
   [[['PHYS110', 'R3', 2], ['MATH101H', 'R2', 1], ['MATH101H', 'R2', 1], ['CHEM120', 'R3', 0],
     ['MATH101', 'R3', 3], ['MATH101', 'R2', 2]],
    [0, 5, 1, 5], {'R1': 0, 'R2': 1, 'R3': 7}],
   [12, 23, 35])]]
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: room charge key 1[4, 3, 7][4, 6, 10]Failed
regression variant: room charge key 2[25, 5, 30][25, 11, 36]Failed
partial repair guard 3[20, 8, 28][20, 22, 42]Failed
boundary control 4[5, 3, 8][5, 3, 8]Passed
normal control 5[0, 10, 10][0, 13, 13]Failed
normal control 6[1, 10, 11][1, 10, 11]Passed
normal control 7[9, 5, 14][9, 5, 14]Passed
normal control 8[15, 5, 20][15, 5, 20]Passed

SHA-256 / 96ddb8048e74c9d5d18e3010a6edac8359e83fc376a4cebaaf818f5c4b4bc925

2 / The unsuccessful fix

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

N = 1
observations = []
def solve(assign, ppen, rpen):
    seen_exam = set()
    seen_room = set()
    pp = rp = 0
    for ex, r, p in assign:
        if (ex, p) not in seen_exam:
            seen_exam.add((ex, p))
            pp += ppen[p]
        if (r, p) not in seen_room:
            seen_room.add((r, p))
            rp += rpen[r]
    return [pp, rp, pp + rp]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: room charge key 1', [[['A', 'R2', 0], ['B', 'R2', 0]], [2, 5, 0, 0], {'R1': 0, 'R2': 3}],
   [4, 6, 10]),
  ('regression variant: room charge key 2',
   [[['PHYS110', 'R2', 2], ['CHEM120', 'R3', 1], ['MATH101H', 'R2', 3], ['CHEM120', 'R2', 3],
     ['PHYS110', 'R1', 3], ['PHYS110', 'R2', 1]],
    [10, 10, 5, 0], {'R1': 0, 'R2': 3, 'R3': 2}],
   [25, 11, 36]),
  ('partial repair guard 3',
   [[['PHYS110', 'R3', 0], ['MATH101H', 'R3', 0], ['CHEM120', 'R1', 0], ['MATH101H', 'R2', 0],
     ['CHEM120', 'R3', 2]],
    [5, 10, 5, 5], {'R1': 0, 'R2': 1, 'R3': 7}],
   [20, 22, 42]),
  ('boundary control 4', [[['A', 'R1', 1], ['A', 'R2', 1]], [0, 5, 0, 0], {'R1': 0, 'R2': 3}], [5, 3, 8]),
  ('normal control 5',
   [[['MATH101H', 'R3', 1], ['MATH101', 'R1', 2], ['MATH101', 'R2', 1], ['CHEM120', 'R2', 2]], [1, 0, 0, 1],
    {'R1': 0, 'R2': 3, 'R3': 7}],
   [0, 13, 13]),
  ('normal control 6',
   [[['MATH101', 'R2', 2], ['CHEM120', 'R1', 1], ['MATH101H', 'R3', 0], ['MATH101', 'R1', 2],
     ['MATH101', 'R2', 2]],
    [0, 1, 0, 10], {'R1': 0, 'R2': 3, 'R3': 7}],
   [1, 10, 11]),
  ('normal control 7',
   [[['MATH101', 'R1', 2], ['MATH101H', 'R3', 3], ['PHYS110', 'R1', 3], ['MATH101H', 'R3', 2],
     ['MATH101', 'R2', 0]],
    [5, 10, 1, 1], {'R1': 0, 'R2': 3, 'R3': 2}],
   [9, 5, 14]),
  ('normal control 8',
   [[['MATH101H', 'R3', 1], ['CHEM120', 'R2', 0], ['CHEM120', 'R2', 0]], [5, 10, 0, 0],
    {'R1': 0, 'R2': 3, 'R3': 2}],
   [15, 5, 20])],
 [('regression: room charge key 1',
   [[['CHEM120', 'R1', 2], ['CHEM120', 'R3', 2], ['PHYS110', 'R2', 1], ['PHYS110', 'R1', 3],
     ['MATH101', 'R1', 1], ['MATH101H', 'R2', 0]],
    [1, 1, 0, 10], {'R1': 0, 'R2': 3, 'R3': 2}],
   [13, 8, 21]),
  ('regression variant: room charge key 2',
   [[['PHYS110', 'R3', 0], ['PHYS110', 'R1', 2], ['MATH101', 'R1', 2], ['MATH101H', 'R2', 2],
     ['MATH101H', 'R2', 3], ['MATH101', 'R3', 1], ['CHEM120', 'R3', 3], ['PHYS110', 'R3', 0]],
    [1, 1, 5, 10], {'R1': 0, 'R2': 3, 'R3': 7}],
   [37, 24, 61]),
  ('partial repair guard 3',
   [[['MATH101', 'R2', 1], ['PHYS110', 'R3', 1], ['MATH101H', 'R1', 2], ['PHYS110', 'R3', 3]], [1, 5, 10, 0],
    {'R1': 0, 'R2': 1, 'R3': 7}],
   [20, 8, 28]),
  ('boundary control 4', [[['A', 'R1', 1], ['A', 'R2', 1]], [0, 5, 0, 0], {'R1': 0, 'R2': 3}], [5, 3, 8]),
  ('boundary control 5', [[['A', 'R2', 0], ['B', 'R2', 0]], [2, 5, 0, 0], {'R1': 0, 'R2': 3}], [4, 6, 10]),
  ('normal control 6',
   [[['CHEM120', 'R2', 3], ['PHYS110', 'R2', 2], ['PHYS110', 'R2', 2], ['CHEM120', 'R1', 2],
     ['MATH101H', 'R2', 2], ['PHYS110', 'R1', 2], ['MATH101H', 'R2', 2], ['CHEM120', 'R1', 2]],
    [10, 10, 5, 1], {'R1': 0, 'R2': 3, 'R3': 7}],
   [16, 9, 25]),
  ('normal control 7',
   [[['CHEM120', 'R2', 0], ['PHYS110', 'R2', 0]], [10, 10, 1, 10], {'R1': 0, 'R2': 3, 'R3': 2}],
   [20, 6, 26]),
  ('normal control 8',
   [[['CHEM120', 'R3', 3], ['MATH101H', 'R3', 2], ['MATH101H', 'R3', 2], ['MATH101H', 'R2', 3],
     ['MATH101H', 'R3', 2]],
    [5, 0, 5, 5], {'R1': 0, 'R2': 1, 'R3': 7}],
   [15, 15, 30])],
 [('regression: room charge key 1',
   [[['CHEM120', 'R2', 0], ['MATH101H', 'R1', 3], ['PHYS110', 'R2', 3], ['PHYS110', 'R2', 3],
     ['PHYS110', 'R2', 3]],
    [1, 1, 0, 1], {'R1': 0, 'R2': 1, 'R3': 2}],
   [3, 2, 5]),
  ('regression variant: room charge key 2',
   [[['MATH101', 'R2', 1], ['PHYS110', 'R1', 0], ['MATH101', 'R3', 1], ['MATH101', 'R1', 0],
     ['CHEM120', 'R1', 0], ['MATH101H', 'R1', 0], ['MATH101H', 'R3', 1]],
    [0, 1, 10, 5], {'R1': 0, 'R2': 1, 'R3': 2}],
   [2, 5, 7]),
  ('partial repair guard 3',
   [[['MATH101', 'R2', 3], ['MATH101', 'R2', 0], ['PHYS110', 'R1', 2], ['PHYS110', 'R3', 3],
     ['MATH101H', 'R3', 2], ['CHEM120', 'R3', 1]],
    [10, 5, 5, 10], {'R1': 0, 'R2': 3, 'R3': 2}],
   [45, 9, 54]),
  ('boundary control 4', [[['A', 'R1', 1], ['A', 'R2', 1]], [0, 5, 0, 0], {'R1': 0, 'R2': 3}], [5, 3, 8]),
  ('boundary control 5', [[['A', 'R2', 0], ['B', 'R2', 0]], [2, 5, 0, 0], {'R1': 0, 'R2': 3}], [4, 6, 10]),
  ('normal control 6',
   [[['CHEM120', 'R3', 1], ['CHEM120', 'R3', 3], ['PHYS110', 'R1', 3], ['CHEM120', 'R2', 2],
     ['CHEM120', 'R3', 1]],
    [0, 0, 0, 0], {'R1': 0, 'R2': 1, 'R3': 2}],
   [0, 3, 3]),
  ('normal control 7',
   [[['MATH101', 'R2', 1], ['MATH101', 'R1', 0], ['CHEM120', 'R2', 3], ['MATH101H', 'R2', 0],
     ['MATH101', 'R2', 0]],
    [0, 1, 10, 5], {'R1': 0, 'R2': 1, 'R3': 7}],
   [6, 3, 9]),
  ('normal control 8',
   [[['MATH101H', 'R2', 3], ['PHYS110', 'R1', 3], ['MATH101', 'R1', 2], ['CHEM120', 'R2', 3]], [5, 10, 5, 0],
    {'R1': 0, 'R2': 1, 'R3': 7}],
   [5, 2, 7])],
 [('regression: room charge key 1',
   [[['CHEM120', 'R1', 2], ['MATH101', 'R2', 3], ['PHYS110', 'R2', 1], ['CHEM120', 'R1', 2]], [10, 5, 5, 1],
    {'R1': 0, 'R2': 3, 'R3': 7}],
   [11, 6, 17]),
  ('regression variant: room charge key 2',
   [[['PHYS110', 'R1', 1], ['CHEM120', 'R3', 0], ['PHYS110', 'R1', 3], ['PHYS110', 'R3', 0],
     ['CHEM120', 'R2', 1], ['PHYS110', 'R2', 0]],
    [1, 10, 0, 0], {'R1': 0, 'R2': 1, 'R3': 7}],
   [22, 16, 38]),
  ('partial repair guard 3',
   [[['PHYS110', 'R2', 0], ['CHEM120', 'R1', 0], ['MATH101', 'R1', 2], ['MATH101H', 'R1', 0],
     ['PHYS110', 'R2', 2], ['MATH101', 'R1', 0], ['MATH101', 'R3', 3]],
    [10, 10, 5, 0], {'R1': 0, 'R2': 1, 'R3': 7}],
   [50, 8, 58]),
  ('boundary control 4', [[['A', 'R1', 1], ['A', 'R2', 1]], [0, 5, 0, 0], {'R1': 0, 'R2': 3}], [5, 3, 8]),
  ('boundary control 5', [[['A', 'R2', 0], ['B', 'R2', 0]], [2, 5, 0, 0], {'R1': 0, 'R2': 3}], [4, 6, 10]),
  ('normal control 6',
   [[['PHYS110', 'R3', 2], ['MATH101H', 'R2', 1], ['MATH101H', 'R2', 1], ['CHEM120', 'R3', 0],
     ['MATH101', 'R3', 3], ['MATH101', 'R2', 2]],
    [0, 5, 1, 5], {'R1': 0, 'R2': 1, 'R3': 7}],
   [12, 23, 35]),
  ('normal control 7',
   [[['MATH101H', 'R1', 2], ['MATH101H', 'R3', 0], ['MATH101H', 'R1', 0], ['MATH101H', 'R1', 3],
     ['PHYS110', 'R1', 3], ['PHYS110', 'R2', 1]],
    [1, 10, 0, 10], {'R1': 0, 'R2': 3, 'R3': 7}],
   [31, 10, 41]),
  ('normal control 8',
   [[['CHEM120', 'R3', 3], ['PHYS110', 'R1', 2], ['PHYS110', 'R1', 2]], [0, 1, 10, 0],
    {'R1': 0, 'R2': 1, 'R3': 7}],
   [10, 7, 17])],
 [('regression: room charge key 1',
   [[['PHYS110', 'R3', 2], ['CHEM120', 'R1', 2], ['MATH101', 'R1', 2], ['CHEM120', 'R3', 3],
     ['CHEM120', 'R1', 3], ['CHEM120', 'R3', 3]],
    [0, 0, 5, 1], {'R1': 0, 'R2': 3, 'R3': 2}],
   [16, 4, 20]),
  ('regression variant: room charge key 2',
   [[['CHEM120', 'R3', 3], ['MATH101', 'R2', 0], ['PHYS110', 'R2', 1], ['CHEM120', 'R2', 3],
     ['PHYS110', 'R3', 0], ['CHEM120', 'R2', 3], ['MATH101H', 'R1', 3]],
    [1, 10, 10, 5], {'R1': 0, 'R2': 3, 'R3': 2}],
   [22, 13, 35]),
  ('partial repair guard 3',
   [[['PHYS110', 'R1', 2], ['CHEM120', 'R2', 1], ['MATH101H', 'R3', 2], ['MATH101', 'R3', 0],
     ['CHEM120', 'R2', 1], ['MATH101H', 'R3', 1]],
    [10, 0, 10, 0], {'R1': 0, 'R2': 3, 'R3': 2}],
   [30, 7, 37]),
  ('boundary control 4', [[['A', 'R1', 1], ['A', 'R2', 1]], [0, 5, 0, 0], {'R1': 0, 'R2': 3}], [5, 3, 8]),
  ('boundary control 5', [[['A', 'R2', 0], ['B', 'R2', 0]], [2, 5, 0, 0], {'R1': 0, 'R2': 3}], [4, 6, 10]),
  ('normal control 6',
   [[['CHEM120', 'R1', 3], ['MATH101', 'R3', 1], ['MATH101', 'R2', 0], ['MATH101H', 'R1', 1],
     ['MATH101', 'R2', 2]],
    [0, 10, 5, 0], {'R1': 0, 'R2': 1, 'R3': 2}],
   [25, 3, 28]),
  ('normal control 7',
   [[['MATH101H', 'R3', 1], ['MATH101H', 'R1', 1]], [0, 5, 5, 5], {'R1': 0, 'R2': 3, 'R3': 2}], [5, 2, 7]),
  ('normal control 8',
   [[['PHYS110', 'R3', 2], ['MATH101H', 'R2', 1], ['MATH101H', 'R2', 1], ['CHEM120', 'R3', 0],
     ['MATH101', 'R3', 3], ['MATH101', 'R2', 2]],
    [0, 5, 1, 5], {'R1': 0, 'R2': 1, 'R3': 7}],
   [12, 23, 35])]]
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: room charge key 1[4, 3, 7][4, 6, 10]Failed
regression variant: room charge key 2[25, 11, 36][25, 11, 36]Passed
partial repair guard 3[20, 15, 35][20, 22, 42]Failed
boundary control 4[5, 3, 8][5, 3, 8]Passed
normal control 5[0, 13, 13][0, 13, 13]Passed
normal control 6[1, 10, 11][1, 10, 11]Passed
normal control 7[9, 7, 16][9, 5, 14]Failed
normal control 8[15, 5, 20][15, 5, 20]Passed

SHA-256 / 3368c2a23559ab15e89517ad5c6005d3c369784d4ea3bfc1c6475b4ed37bcd60

3 / The verified repair

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

N = 1
observations = []
def solve(assign, ppen, rpen):
    seen_exam = set()
    seen_room = set()
    pp = rp = 0
    for ex, r, p in assign:
        if (ex, p) not in seen_exam:
            seen_exam.add((ex, p))
            pp += ppen[p]
        if (ex, r) not in seen_room:
            seen_room.add((ex, r))
            rp += rpen[r]
    return [pp, rp, pp + rp]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: room charge key 1', [[['A', 'R2', 0], ['B', 'R2', 0]], [2, 5, 0, 0], {'R1': 0, 'R2': 3}],
   [4, 6, 10]),
  ('regression variant: room charge key 2',
   [[['PHYS110', 'R2', 2], ['CHEM120', 'R3', 1], ['MATH101H', 'R2', 3], ['CHEM120', 'R2', 3],
     ['PHYS110', 'R1', 3], ['PHYS110', 'R2', 1]],
    [10, 10, 5, 0], {'R1': 0, 'R2': 3, 'R3': 2}],
   [25, 11, 36]),
  ('partial repair guard 3',
   [[['PHYS110', 'R3', 0], ['MATH101H', 'R3', 0], ['CHEM120', 'R1', 0], ['MATH101H', 'R2', 0],
     ['CHEM120', 'R3', 2]],
    [5, 10, 5, 5], {'R1': 0, 'R2': 1, 'R3': 7}],
   [20, 22, 42]),
  ('boundary control 4', [[['A', 'R1', 1], ['A', 'R2', 1]], [0, 5, 0, 0], {'R1': 0, 'R2': 3}], [5, 3, 8]),
  ('normal control 5',
   [[['MATH101H', 'R3', 1], ['MATH101', 'R1', 2], ['MATH101', 'R2', 1], ['CHEM120', 'R2', 2]], [1, 0, 0, 1],
    {'R1': 0, 'R2': 3, 'R3': 7}],
   [0, 13, 13]),
  ('normal control 6',
   [[['MATH101', 'R2', 2], ['CHEM120', 'R1', 1], ['MATH101H', 'R3', 0], ['MATH101', 'R1', 2],
     ['MATH101', 'R2', 2]],
    [0, 1, 0, 10], {'R1': 0, 'R2': 3, 'R3': 7}],
   [1, 10, 11]),
  ('normal control 7',
   [[['MATH101', 'R1', 2], ['MATH101H', 'R3', 3], ['PHYS110', 'R1', 3], ['MATH101H', 'R3', 2],
     ['MATH101', 'R2', 0]],
    [5, 10, 1, 1], {'R1': 0, 'R2': 3, 'R3': 2}],
   [9, 5, 14]),
  ('normal control 8',
   [[['MATH101H', 'R3', 1], ['CHEM120', 'R2', 0], ['CHEM120', 'R2', 0]], [5, 10, 0, 0],
    {'R1': 0, 'R2': 3, 'R3': 2}],
   [15, 5, 20])],
 [('regression: room charge key 1',
   [[['CHEM120', 'R1', 2], ['CHEM120', 'R3', 2], ['PHYS110', 'R2', 1], ['PHYS110', 'R1', 3],
     ['MATH101', 'R1', 1], ['MATH101H', 'R2', 0]],
    [1, 1, 0, 10], {'R1': 0, 'R2': 3, 'R3': 2}],
   [13, 8, 21]),
  ('regression variant: room charge key 2',
   [[['PHYS110', 'R3', 0], ['PHYS110', 'R1', 2], ['MATH101', 'R1', 2], ['MATH101H', 'R2', 2],
     ['MATH101H', 'R2', 3], ['MATH101', 'R3', 1], ['CHEM120', 'R3', 3], ['PHYS110', 'R3', 0]],
    [1, 1, 5, 10], {'R1': 0, 'R2': 3, 'R3': 7}],
   [37, 24, 61]),
  ('partial repair guard 3',
   [[['MATH101', 'R2', 1], ['PHYS110', 'R3', 1], ['MATH101H', 'R1', 2], ['PHYS110', 'R3', 3]], [1, 5, 10, 0],
    {'R1': 0, 'R2': 1, 'R3': 7}],
   [20, 8, 28]),
  ('boundary control 4', [[['A', 'R1', 1], ['A', 'R2', 1]], [0, 5, 0, 0], {'R1': 0, 'R2': 3}], [5, 3, 8]),
  ('boundary control 5', [[['A', 'R2', 0], ['B', 'R2', 0]], [2, 5, 0, 0], {'R1': 0, 'R2': 3}], [4, 6, 10]),
  ('normal control 6',
   [[['CHEM120', 'R2', 3], ['PHYS110', 'R2', 2], ['PHYS110', 'R2', 2], ['CHEM120', 'R1', 2],
     ['MATH101H', 'R2', 2], ['PHYS110', 'R1', 2], ['MATH101H', 'R2', 2], ['CHEM120', 'R1', 2]],
    [10, 10, 5, 1], {'R1': 0, 'R2': 3, 'R3': 7}],
   [16, 9, 25]),
  ('normal control 7',
   [[['CHEM120', 'R2', 0], ['PHYS110', 'R2', 0]], [10, 10, 1, 10], {'R1': 0, 'R2': 3, 'R3': 2}],
   [20, 6, 26]),
  ('normal control 8',
   [[['CHEM120', 'R3', 3], ['MATH101H', 'R3', 2], ['MATH101H', 'R3', 2], ['MATH101H', 'R2', 3],
     ['MATH101H', 'R3', 2]],
    [5, 0, 5, 5], {'R1': 0, 'R2': 1, 'R3': 7}],
   [15, 15, 30])],
 [('regression: room charge key 1',
   [[['CHEM120', 'R2', 0], ['MATH101H', 'R1', 3], ['PHYS110', 'R2', 3], ['PHYS110', 'R2', 3],
     ['PHYS110', 'R2', 3]],
    [1, 1, 0, 1], {'R1': 0, 'R2': 1, 'R3': 2}],
   [3, 2, 5]),
  ('regression variant: room charge key 2',
   [[['MATH101', 'R2', 1], ['PHYS110', 'R1', 0], ['MATH101', 'R3', 1], ['MATH101', 'R1', 0],
     ['CHEM120', 'R1', 0], ['MATH101H', 'R1', 0], ['MATH101H', 'R3', 1]],
    [0, 1, 10, 5], {'R1': 0, 'R2': 1, 'R3': 2}],
   [2, 5, 7]),
  ('partial repair guard 3',
   [[['MATH101', 'R2', 3], ['MATH101', 'R2', 0], ['PHYS110', 'R1', 2], ['PHYS110', 'R3', 3],
     ['MATH101H', 'R3', 2], ['CHEM120', 'R3', 1]],
    [10, 5, 5, 10], {'R1': 0, 'R2': 3, 'R3': 2}],
   [45, 9, 54]),
  ('boundary control 4', [[['A', 'R1', 1], ['A', 'R2', 1]], [0, 5, 0, 0], {'R1': 0, 'R2': 3}], [5, 3, 8]),
  ('boundary control 5', [[['A', 'R2', 0], ['B', 'R2', 0]], [2, 5, 0, 0], {'R1': 0, 'R2': 3}], [4, 6, 10]),
  ('normal control 6',
   [[['CHEM120', 'R3', 1], ['CHEM120', 'R3', 3], ['PHYS110', 'R1', 3], ['CHEM120', 'R2', 2],
     ['CHEM120', 'R3', 1]],
    [0, 0, 0, 0], {'R1': 0, 'R2': 1, 'R3': 2}],
   [0, 3, 3]),
  ('normal control 7',
   [[['MATH101', 'R2', 1], ['MATH101', 'R1', 0], ['CHEM120', 'R2', 3], ['MATH101H', 'R2', 0],
     ['MATH101', 'R2', 0]],
    [0, 1, 10, 5], {'R1': 0, 'R2': 1, 'R3': 7}],
   [6, 3, 9]),
  ('normal control 8',
   [[['MATH101H', 'R2', 3], ['PHYS110', 'R1', 3], ['MATH101', 'R1', 2], ['CHEM120', 'R2', 3]], [5, 10, 5, 0],
    {'R1': 0, 'R2': 1, 'R3': 7}],
   [5, 2, 7])],
 [('regression: room charge key 1',
   [[['CHEM120', 'R1', 2], ['MATH101', 'R2', 3], ['PHYS110', 'R2', 1], ['CHEM120', 'R1', 2]], [10, 5, 5, 1],
    {'R1': 0, 'R2': 3, 'R3': 7}],
   [11, 6, 17]),
  ('regression variant: room charge key 2',
   [[['PHYS110', 'R1', 1], ['CHEM120', 'R3', 0], ['PHYS110', 'R1', 3], ['PHYS110', 'R3', 0],
     ['CHEM120', 'R2', 1], ['PHYS110', 'R2', 0]],
    [1, 10, 0, 0], {'R1': 0, 'R2': 1, 'R3': 7}],
   [22, 16, 38]),
  ('partial repair guard 3',
   [[['PHYS110', 'R2', 0], ['CHEM120', 'R1', 0], ['MATH101', 'R1', 2], ['MATH101H', 'R1', 0],
     ['PHYS110', 'R2', 2], ['MATH101', 'R1', 0], ['MATH101', 'R3', 3]],
    [10, 10, 5, 0], {'R1': 0, 'R2': 1, 'R3': 7}],
   [50, 8, 58]),
  ('boundary control 4', [[['A', 'R1', 1], ['A', 'R2', 1]], [0, 5, 0, 0], {'R1': 0, 'R2': 3}], [5, 3, 8]),
  ('boundary control 5', [[['A', 'R2', 0], ['B', 'R2', 0]], [2, 5, 0, 0], {'R1': 0, 'R2': 3}], [4, 6, 10]),
  ('normal control 6',
   [[['PHYS110', 'R3', 2], ['MATH101H', 'R2', 1], ['MATH101H', 'R2', 1], ['CHEM120', 'R3', 0],
     ['MATH101', 'R3', 3], ['MATH101', 'R2', 2]],
    [0, 5, 1, 5], {'R1': 0, 'R2': 1, 'R3': 7}],
   [12, 23, 35]),
  ('normal control 7',
   [[['MATH101H', 'R1', 2], ['MATH101H', 'R3', 0], ['MATH101H', 'R1', 0], ['MATH101H', 'R1', 3],
     ['PHYS110', 'R1', 3], ['PHYS110', 'R2', 1]],
    [1, 10, 0, 10], {'R1': 0, 'R2': 3, 'R3': 7}],
   [31, 10, 41]),
  ('normal control 8',
   [[['CHEM120', 'R3', 3], ['PHYS110', 'R1', 2], ['PHYS110', 'R1', 2]], [0, 1, 10, 0],
    {'R1': 0, 'R2': 1, 'R3': 7}],
   [10, 7, 17])],
 [('regression: room charge key 1',
   [[['PHYS110', 'R3', 2], ['CHEM120', 'R1', 2], ['MATH101', 'R1', 2], ['CHEM120', 'R3', 3],
     ['CHEM120', 'R1', 3], ['CHEM120', 'R3', 3]],
    [0, 0, 5, 1], {'R1': 0, 'R2': 3, 'R3': 2}],
   [16, 4, 20]),
  ('regression variant: room charge key 2',
   [[['CHEM120', 'R3', 3], ['MATH101', 'R2', 0], ['PHYS110', 'R2', 1], ['CHEM120', 'R2', 3],
     ['PHYS110', 'R3', 0], ['CHEM120', 'R2', 3], ['MATH101H', 'R1', 3]],
    [1, 10, 10, 5], {'R1': 0, 'R2': 3, 'R3': 2}],
   [22, 13, 35]),
  ('partial repair guard 3',
   [[['PHYS110', 'R1', 2], ['CHEM120', 'R2', 1], ['MATH101H', 'R3', 2], ['MATH101', 'R3', 0],
     ['CHEM120', 'R2', 1], ['MATH101H', 'R3', 1]],
    [10, 0, 10, 0], {'R1': 0, 'R2': 3, 'R3': 2}],
   [30, 7, 37]),
  ('boundary control 4', [[['A', 'R1', 1], ['A', 'R2', 1]], [0, 5, 0, 0], {'R1': 0, 'R2': 3}], [5, 3, 8]),
  ('boundary control 5', [[['A', 'R2', 0], ['B', 'R2', 0]], [2, 5, 0, 0], {'R1': 0, 'R2': 3}], [4, 6, 10]),
  ('normal control 6',
   [[['CHEM120', 'R1', 3], ['MATH101', 'R3', 1], ['MATH101', 'R2', 0], ['MATH101H', 'R1', 1],
     ['MATH101', 'R2', 2]],
    [0, 10, 5, 0], {'R1': 0, 'R2': 1, 'R3': 2}],
   [25, 3, 28]),
  ('normal control 7',
   [[['MATH101H', 'R3', 1], ['MATH101H', 'R1', 1]], [0, 5, 5, 5], {'R1': 0, 'R2': 3, 'R3': 2}], [5, 2, 7]),
  ('normal control 8',
   [[['PHYS110', 'R3', 2], ['MATH101H', 'R2', 1], ['MATH101H', 'R2', 1], ['CHEM120', 'R3', 0],
     ['MATH101', 'R3', 3], ['MATH101', 'R2', 2]],
    [0, 5, 1, 5], {'R1': 0, 'R2': 1, 'R3': 7}],
   [12, 23, 35])]]
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: room charge key 1[4, 6, 10][4, 6, 10]Passed
regression variant: room charge key 2[25, 11, 36][25, 11, 36]Passed
partial repair guard 3[20, 22, 42][20, 22, 42]Passed
boundary control 4[5, 3, 8][5, 3, 8]Passed
normal control 5[0, 13, 13][0, 13, 13]Passed
normal control 6[1, 10, 11][1, 10, 11]Passed
normal control 7[9, 5, 14][9, 5, 14]Passed
normal control 8[15, 5, 20][15, 5, 20]Passed

SHA-256 / 247d6d04e6647601a3778f076b47b2b84aabb7057b8e63f83249a0c9c7233a1e

Verification & scope

Stipulated toy exam-timetabling rule set for a bounded model; it does not claim conformance with any institution's regulations or a benchmark specification, and it performs no search or optimisation. 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:52:06.477369+00:00.

Case digest / f602dcf54d9ee24764773468d13b5fc47f583ccccc7332aba11336e227c5c133