FAILURE MAP
← Case archive

FA-93176 / EV charging session scheduling / Open access

Demand-response curtailment of a charge plan: percentage rounding stage · case 01

Curtailed setpoints are slightly lower than the stated percentage for odd plans.

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

ROOT CAUSE

The plan is divided by 100 and truncated before multiplying.

VERIFIED REPAIR

Multiply first, then floor-divide by 100.

Unsuccessful approach: Rounding to nearest exceeds the floor contract on half-way values.

Case contract

profile is planned watts per slot. events are [start, end, pct, opt_out]; during [start, end) a non-opted-out event limits power to pct percent of plan (integer floor of p*pct/100), and overlapping events apply the lowest pct. Curtailed power never drops below min(plan, floor_w). Return [new profile, total curtailed watts over slots].

Why this case matters

Depot, workplace and public EV chargers schedule sessions against prices, circuit limits and departure deadlines; a wrong decision silently strands a driver or overloads a feeder.

1 / The failure

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

N = 1
observations = []
def solve(profile, events, floor_w):
    out = []
    for t, p in enumerate(profile):
        pct = 100
        for s, e, q, opt in events:
            if opt:
                continue
            if s <= t < e and q < pct:
                pct = q
        new = p // 100 * pct
        new = max(new, min(p, floor_w))
        out.append(new)
    return [out, sum(profile) - sum(out)]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['boundary: event ends at slot', [[3680, 3680, 3680], [[0, 1, 50, False]], 0],
   [[1840, 3680, 3680], 1840]],
  ['boundary: opted-out event', [[7400, 7400], [[0, 2, 0, True]], 1380], [[7400, 7400], 0]],
  ['boundary: plan below floor', [[1000, 7400], [[0, 2, 0, False]], 1380], [[1000, 1380], 6020]],
  ['regression: percentage rounding stage',
   [[11000, 1000, 7400, 1380, 2345, 1380, 7400, 7400, 1111],
    [[8, 13, 50, False], [5, 8, 60, False]], 2000],
   [[11000, 1000, 7400, 1380, 2345, 1380, 4440, 4440, 1111], 5920]],
  ['regression: percentage rounding stage (partial repair)',
   [[11000, 11000, 2345, 1111, 0, 1380, 11000, 1380, 3680], [[2, 5, 60, False], [6, 8, 60, True]],
    0],
   [[11000, 11000, 1407, 666, 0, 1380, 11000, 1380, 3680], 1383]],
  ['control 1',
   [[1000, 3333, 1111, 1380, 11000], [[1, 2, 75, True], [5, 8, 75, False], [4, 5, 25, False]], 0],
   [[1000, 3333, 1111, 1380, 2750], 8250]],
  ['control 2',
   [[1380, 1000, 1111, 1000, 1000, 3333, 3333, 7400, 1111, 3680, 11000, 1111],
    [[8, 12, 60, False], [5, 7, 0, False]], 2000],
   [[1380, 1000, 1111, 1000, 1000, 2000, 2000, 7400, 1111, 2208, 6600, 1111], 8538]]],
 [['boundary: event ends at slot', [[3680, 3680, 3680], [[0, 1, 50, False]], 0],
   [[1840, 3680, 3680], 1840]],
  ['boundary: opted-out event', [[7400, 7400], [[0, 2, 0, True]], 1380], [[7400, 7400], 0]],
  ['boundary: plan below floor', [[1000, 7400], [[0, 2, 0, False]], 1380], [[1000, 1380], 6020]],
  ['regression: percentage rounding stage', [[3680, 7400, 2345, 1111], [[2, 4, 50, False]], 2000],
   [[3680, 7400, 2000, 1111], 345]],
  ['regression: percentage rounding stage (partial repair)',
   [[3680, 1000, 3680, 1000, 3333, 2345, 1380, 1380, 1000, 3680, 7400],
    [[6, 11, 25, True], [5, 10, 75, False]], 0],
   [[3680, 1000, 3680, 1000, 3333, 1758, 1035, 1035, 750, 2760, 7400], 2447]],
  ['control 1',
   [[7400, 3680, 7400, 3333, 0, 1380, 1111, 3333, 3680, 7400, 1111, 1380],
    [[0, 3, 75, True], [0, 3, 50, False]], 0],
   [[3700, 1840, 3700, 3333, 0, 1380, 1111, 3333, 3680, 7400, 1111, 1380], 9240]],
  ['control 2', [[1380, 0, 3680, 7400, 0, 7400, 2345, 1000, 3680], [[7, 10, 25, False]], 2000],
   [[1380, 0, 3680, 7400, 0, 7400, 2345, 1000, 2000], 1680]]],
 [['boundary: event ends at slot', [[3680, 3680, 3680], [[0, 1, 50, False]], 0],
   [[1840, 3680, 3680], 1840]],
  ['boundary: opted-out event', [[7400, 7400], [[0, 2, 0, True]], 1380], [[7400, 7400], 0]],
  ['boundary: plan below floor', [[1000, 7400], [[0, 2, 0, False]], 1380], [[1000, 1380], 6020]],
  ['regression: percentage rounding stage',
   [[1380, 1380, 1111, 2345, 1380, 2345], [[6, 11, 0, False], [3, 7, 60, False], [3, 6, 0, False]],
    0],
   [[1380, 1380, 1111, 0, 0, 0], 6070]],
  ['regression: percentage rounding stage (partial repair)',
   [[1111, 1111, 2345, 3680, 3333, 1000, 3680, 7400, 7400, 0, 0, 7400],
    [[0, 1, 60, False], [8, 10, 75, False], [3, 5, 60, False]], 0],
   [[666, 1111, 2345, 2208, 1999, 1000, 3680, 7400, 5550, 0, 0, 7400], 5101]],
  ['control 1',
   [[0, 1000, 1000, 2345, 0, 3680, 1380, 3680], [[4, 8, 50, True], [5, 10, 75, True]], 0],
   [[0, 1000, 1000, 2345, 0, 3680, 1380, 3680], 0]],
  ['control 2',
   [[3333, 7400, 1000, 2345, 11000, 2345], [[3, 7, 50, False], [5, 6, 25, True]], 2000],
   [[3333, 7400, 1000, 2000, 5500, 2000], 6190]]],
 [['boundary: event ends at slot', [[3680, 3680, 3680], [[0, 1, 50, False]], 0],
   [[1840, 3680, 3680], 1840]],
  ['boundary: opted-out event', [[7400, 7400], [[0, 2, 0, True]], 1380], [[7400, 7400], 0]],
  ['boundary: plan below floor', [[1000, 7400], [[0, 2, 0, False]], 1380], [[1000, 1380], 6020]],
  ['regression: percentage rounding stage',
   [[0, 3333, 3333, 0, 1380, 2345, 1111, 11000, 0],
    [[7, 11, 25, False], [3, 4, 0, True], [3, 6, 0, True]], 2000],
   [[0, 3333, 3333, 0, 1380, 2345, 1111, 2750, 0], 8250]],
  ['regression: percentage rounding stage (partial repair)',
   [[1111, 1000, 3333, 11000, 1111, 2345, 11000, 11000, 3333],
    [[5, 10, 75, True], [6, 9, 75, False], [3, 5, 25, False]], 2000],
   [[1111, 1000, 3333, 2750, 1111, 2345, 8250, 8250, 2499], 14584]],
  ['control 1',
   [[3680, 3680, 1000, 0, 3333, 1000, 3333, 3680],
    [[1, 5, 0, False], [7, 11, 25, False], [6, 6, 60, False]], 2000],
   [[3680, 2000, 1000, 0, 2000, 1000, 3333, 2000], 4693]],
  ['control 2',
   [[1380, 7400, 7400, 1000, 1111, 2345, 1380], [[4, 8, 0, False], [6, 10, 0, False]], 0],
   [[1380, 7400, 7400, 1000, 0, 0, 0], 4836]]],
 [['boundary: event ends at slot', [[3680, 3680, 3680], [[0, 1, 50, False]], 0],
   [[1840, 3680, 3680], 1840]],
  ['boundary: opted-out event', [[7400, 7400], [[0, 2, 0, True]], 1380], [[7400, 7400], 0]],
  ['boundary: plan below floor', [[1000, 7400], [[0, 2, 0, False]], 1380], [[1000, 1380], 6020]],
  ['regression: percentage rounding stage',
   [[0, 2345, 2345, 1000, 11000, 0, 11000, 0, 11000, 1111, 1380, 0],
    [[5, 10, 60, False], [11, 15, 0, True], [5, 9, 25, False]], 2000],
   [[0, 2345, 2345, 1000, 11000, 0, 2750, 0, 2750, 1111, 1380, 0], 16500]],
  ['regression: percentage rounding stage (partial repair)',
   [[3333, 7400, 1000, 3680, 0, 7400, 1111, 0, 11000], [[6, 10, 50, False]], 0],
   [[3333, 7400, 1000, 3680, 0, 7400, 555, 0, 5500], 6056]],
  ['control 1', [[3333, 0, 1000, 1111, 1380, 7400, 1380, 7400, 3680], [[5, 10, 0, True]], 1380],
   [[3333, 0, 1000, 1111, 1380, 7400, 1380, 7400, 3680], 0]],
  ['control 2', [[2345, 7400, 1111, 3333, 3333, 7400, 3680], [[5, 8, 25, False]], 0],
   [[2345, 7400, 1111, 3333, 3333, 1850, 920], 8310]]]]
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
boundary: event ends at slot[[1800, 3600, 3600], 2040][[1840, 3680, 3680], 1840]Failed
boundary: opted-out event[[7400, 7400], 0][[7400, 7400], 0]Passed
boundary: plan below floor[[1000, 1380], 6020][[1000, 1380], 6020]Passed
regression: percentage rounding stage[[11000, 1000, 7400, 1380, 2300, 1380, 4440, 4440, 1111], 5965][[11000, 1000, 7400, 1380, 2345, 1380, 4440, 4440, 1111], 5920]Failed
regression: percentage rounding stage (partial repair)[[11000, 11000, 1380, 660, 0, 1300, 11000, 1300, 3600], 1656][[11000, 11000, 1407, 666, 0, 1380, 11000, 1380, 3680], 1383]Failed
control 1[[1000, 3300, 1100, 1300, 2750], 8374][[1000, 3333, 1111, 1380, 2750], 8250]Failed
control 2[[1380, 1000, 1111, 1000, 1000, 2000, 2000, 7400, 1111, 2160, 6600, 1111], 8586][[1380, 1000, 1111, 1000, 1000, 2000, 2000, 7400, 1111, 2208, 6600, 1111], 8538]Failed

SHA-256 / 801200682d9356cc452749e8b01279bffad74692fc2f12f914bb161b2e6a39f4

2 / The unsuccessful fix

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

N = 1
observations = []
def solve(profile, events, floor_w):
    out = []
    for t, p in enumerate(profile):
        pct = 100
        for s, e, q, opt in events:
            if opt:
                continue
            if s <= t < e and q < pct:
                pct = q
        new = round(p * pct / 100)
        new = max(new, min(p, floor_w))
        out.append(new)
    return [out, sum(profile) - sum(out)]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['boundary: event ends at slot', [[3680, 3680, 3680], [[0, 1, 50, False]], 0],
   [[1840, 3680, 3680], 1840]],
  ['boundary: opted-out event', [[7400, 7400], [[0, 2, 0, True]], 1380], [[7400, 7400], 0]],
  ['boundary: plan below floor', [[1000, 7400], [[0, 2, 0, False]], 1380], [[1000, 1380], 6020]],
  ['regression: percentage rounding stage',
   [[11000, 1000, 7400, 1380, 2345, 1380, 7400, 7400, 1111],
    [[8, 13, 50, False], [5, 8, 60, False]], 2000],
   [[11000, 1000, 7400, 1380, 2345, 1380, 4440, 4440, 1111], 5920]],
  ['regression: percentage rounding stage (partial repair)',
   [[11000, 11000, 2345, 1111, 0, 1380, 11000, 1380, 3680], [[2, 5, 60, False], [6, 8, 60, True]],
    0],
   [[11000, 11000, 1407, 666, 0, 1380, 11000, 1380, 3680], 1383]],
  ['control 1',
   [[1000, 3333, 1111, 1380, 11000], [[1, 2, 75, True], [5, 8, 75, False], [4, 5, 25, False]], 0],
   [[1000, 3333, 1111, 1380, 2750], 8250]],
  ['control 2',
   [[1380, 1000, 1111, 1000, 1000, 3333, 3333, 7400, 1111, 3680, 11000, 1111],
    [[8, 12, 60, False], [5, 7, 0, False]], 2000],
   [[1380, 1000, 1111, 1000, 1000, 2000, 2000, 7400, 1111, 2208, 6600, 1111], 8538]]],
 [['boundary: event ends at slot', [[3680, 3680, 3680], [[0, 1, 50, False]], 0],
   [[1840, 3680, 3680], 1840]],
  ['boundary: opted-out event', [[7400, 7400], [[0, 2, 0, True]], 1380], [[7400, 7400], 0]],
  ['boundary: plan below floor', [[1000, 7400], [[0, 2, 0, False]], 1380], [[1000, 1380], 6020]],
  ['regression: percentage rounding stage', [[3680, 7400, 2345, 1111], [[2, 4, 50, False]], 2000],
   [[3680, 7400, 2000, 1111], 345]],
  ['regression: percentage rounding stage (partial repair)',
   [[3680, 1000, 3680, 1000, 3333, 2345, 1380, 1380, 1000, 3680, 7400],
    [[6, 11, 25, True], [5, 10, 75, False]], 0],
   [[3680, 1000, 3680, 1000, 3333, 1758, 1035, 1035, 750, 2760, 7400], 2447]],
  ['control 1',
   [[7400, 3680, 7400, 3333, 0, 1380, 1111, 3333, 3680, 7400, 1111, 1380],
    [[0, 3, 75, True], [0, 3, 50, False]], 0],
   [[3700, 1840, 3700, 3333, 0, 1380, 1111, 3333, 3680, 7400, 1111, 1380], 9240]],
  ['control 2', [[1380, 0, 3680, 7400, 0, 7400, 2345, 1000, 3680], [[7, 10, 25, False]], 2000],
   [[1380, 0, 3680, 7400, 0, 7400, 2345, 1000, 2000], 1680]]],
 [['boundary: event ends at slot', [[3680, 3680, 3680], [[0, 1, 50, False]], 0],
   [[1840, 3680, 3680], 1840]],
  ['boundary: opted-out event', [[7400, 7400], [[0, 2, 0, True]], 1380], [[7400, 7400], 0]],
  ['boundary: plan below floor', [[1000, 7400], [[0, 2, 0, False]], 1380], [[1000, 1380], 6020]],
  ['regression: percentage rounding stage',
   [[1380, 1380, 1111, 2345, 1380, 2345], [[6, 11, 0, False], [3, 7, 60, False], [3, 6, 0, False]],
    0],
   [[1380, 1380, 1111, 0, 0, 0], 6070]],
  ['regression: percentage rounding stage (partial repair)',
   [[1111, 1111, 2345, 3680, 3333, 1000, 3680, 7400, 7400, 0, 0, 7400],
    [[0, 1, 60, False], [8, 10, 75, False], [3, 5, 60, False]], 0],
   [[666, 1111, 2345, 2208, 1999, 1000, 3680, 7400, 5550, 0, 0, 7400], 5101]],
  ['control 1',
   [[0, 1000, 1000, 2345, 0, 3680, 1380, 3680], [[4, 8, 50, True], [5, 10, 75, True]], 0],
   [[0, 1000, 1000, 2345, 0, 3680, 1380, 3680], 0]],
  ['control 2',
   [[3333, 7400, 1000, 2345, 11000, 2345], [[3, 7, 50, False], [5, 6, 25, True]], 2000],
   [[3333, 7400, 1000, 2000, 5500, 2000], 6190]]],
 [['boundary: event ends at slot', [[3680, 3680, 3680], [[0, 1, 50, False]], 0],
   [[1840, 3680, 3680], 1840]],
  ['boundary: opted-out event', [[7400, 7400], [[0, 2, 0, True]], 1380], [[7400, 7400], 0]],
  ['boundary: plan below floor', [[1000, 7400], [[0, 2, 0, False]], 1380], [[1000, 1380], 6020]],
  ['regression: percentage rounding stage',
   [[0, 3333, 3333, 0, 1380, 2345, 1111, 11000, 0],
    [[7, 11, 25, False], [3, 4, 0, True], [3, 6, 0, True]], 2000],
   [[0, 3333, 3333, 0, 1380, 2345, 1111, 2750, 0], 8250]],
  ['regression: percentage rounding stage (partial repair)',
   [[1111, 1000, 3333, 11000, 1111, 2345, 11000, 11000, 3333],
    [[5, 10, 75, True], [6, 9, 75, False], [3, 5, 25, False]], 2000],
   [[1111, 1000, 3333, 2750, 1111, 2345, 8250, 8250, 2499], 14584]],
  ['control 1',
   [[3680, 3680, 1000, 0, 3333, 1000, 3333, 3680],
    [[1, 5, 0, False], [7, 11, 25, False], [6, 6, 60, False]], 2000],
   [[3680, 2000, 1000, 0, 2000, 1000, 3333, 2000], 4693]],
  ['control 2',
   [[1380, 7400, 7400, 1000, 1111, 2345, 1380], [[4, 8, 0, False], [6, 10, 0, False]], 0],
   [[1380, 7400, 7400, 1000, 0, 0, 0], 4836]]],
 [['boundary: event ends at slot', [[3680, 3680, 3680], [[0, 1, 50, False]], 0],
   [[1840, 3680, 3680], 1840]],
  ['boundary: opted-out event', [[7400, 7400], [[0, 2, 0, True]], 1380], [[7400, 7400], 0]],
  ['boundary: plan below floor', [[1000, 7400], [[0, 2, 0, False]], 1380], [[1000, 1380], 6020]],
  ['regression: percentage rounding stage',
   [[0, 2345, 2345, 1000, 11000, 0, 11000, 0, 11000, 1111, 1380, 0],
    [[5, 10, 60, False], [11, 15, 0, True], [5, 9, 25, False]], 2000],
   [[0, 2345, 2345, 1000, 11000, 0, 2750, 0, 2750, 1111, 1380, 0], 16500]],
  ['regression: percentage rounding stage (partial repair)',
   [[3333, 7400, 1000, 3680, 0, 7400, 1111, 0, 11000], [[6, 10, 50, False]], 0],
   [[3333, 7400, 1000, 3680, 0, 7400, 555, 0, 5500], 6056]],
  ['control 1', [[3333, 0, 1000, 1111, 1380, 7400, 1380, 7400, 3680], [[5, 10, 0, True]], 1380],
   [[3333, 0, 1000, 1111, 1380, 7400, 1380, 7400, 3680], 0]],
  ['control 2', [[2345, 7400, 1111, 3333, 3333, 7400, 3680], [[5, 8, 25, False]], 0],
   [[2345, 7400, 1111, 3333, 3333, 1850, 920], 8310]]]]
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
boundary: event ends at slot[[1840, 3680, 3680], 1840][[1840, 3680, 3680], 1840]Passed
boundary: opted-out event[[7400, 7400], 0][[7400, 7400], 0]Passed
boundary: plan below floor[[1000, 1380], 6020][[1000, 1380], 6020]Passed
regression: percentage rounding stage[[11000, 1000, 7400, 1380, 2345, 1380, 4440, 4440, 1111], 5920][[11000, 1000, 7400, 1380, 2345, 1380, 4440, 4440, 1111], 5920]Passed
regression: percentage rounding stage (partial repair)[[11000, 11000, 1407, 667, 0, 1380, 11000, 1380, 3680], 1382][[11000, 11000, 1407, 666, 0, 1380, 11000, 1380, 3680], 1383]Failed
control 1[[1000, 3333, 1111, 1380, 2750], 8250][[1000, 3333, 1111, 1380, 2750], 8250]Passed
control 2[[1380, 1000, 1111, 1000, 1000, 2000, 2000, 7400, 1111, 2208, 6600, 1111], 8538][[1380, 1000, 1111, 1000, 1000, 2000, 2000, 7400, 1111, 2208, 6600, 1111], 8538]Passed

SHA-256 / cfdcc3d7a2dea428129c67b8f9111565751fdcd92e05c31db02dbaf9b7fbbb97

3 / The verified repair

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

N = 1
observations = []
def solve(profile, events, floor_w):
    out = []
    for t, p in enumerate(profile):
        pct = 100
        for s, e, q, opt in events:
            if opt:
                continue
            if s <= t < e and q < pct:
                pct = q
        new = p * pct // 100
        new = max(new, min(p, floor_w))
        out.append(new)
    return [out, sum(profile) - sum(out)]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['boundary: event ends at slot', [[3680, 3680, 3680], [[0, 1, 50, False]], 0],
   [[1840, 3680, 3680], 1840]],
  ['boundary: opted-out event', [[7400, 7400], [[0, 2, 0, True]], 1380], [[7400, 7400], 0]],
  ['boundary: plan below floor', [[1000, 7400], [[0, 2, 0, False]], 1380], [[1000, 1380], 6020]],
  ['regression: percentage rounding stage',
   [[11000, 1000, 7400, 1380, 2345, 1380, 7400, 7400, 1111],
    [[8, 13, 50, False], [5, 8, 60, False]], 2000],
   [[11000, 1000, 7400, 1380, 2345, 1380, 4440, 4440, 1111], 5920]],
  ['regression: percentage rounding stage (partial repair)',
   [[11000, 11000, 2345, 1111, 0, 1380, 11000, 1380, 3680], [[2, 5, 60, False], [6, 8, 60, True]],
    0],
   [[11000, 11000, 1407, 666, 0, 1380, 11000, 1380, 3680], 1383]],
  ['control 1',
   [[1000, 3333, 1111, 1380, 11000], [[1, 2, 75, True], [5, 8, 75, False], [4, 5, 25, False]], 0],
   [[1000, 3333, 1111, 1380, 2750], 8250]],
  ['control 2',
   [[1380, 1000, 1111, 1000, 1000, 3333, 3333, 7400, 1111, 3680, 11000, 1111],
    [[8, 12, 60, False], [5, 7, 0, False]], 2000],
   [[1380, 1000, 1111, 1000, 1000, 2000, 2000, 7400, 1111, 2208, 6600, 1111], 8538]]],
 [['boundary: event ends at slot', [[3680, 3680, 3680], [[0, 1, 50, False]], 0],
   [[1840, 3680, 3680], 1840]],
  ['boundary: opted-out event', [[7400, 7400], [[0, 2, 0, True]], 1380], [[7400, 7400], 0]],
  ['boundary: plan below floor', [[1000, 7400], [[0, 2, 0, False]], 1380], [[1000, 1380], 6020]],
  ['regression: percentage rounding stage', [[3680, 7400, 2345, 1111], [[2, 4, 50, False]], 2000],
   [[3680, 7400, 2000, 1111], 345]],
  ['regression: percentage rounding stage (partial repair)',
   [[3680, 1000, 3680, 1000, 3333, 2345, 1380, 1380, 1000, 3680, 7400],
    [[6, 11, 25, True], [5, 10, 75, False]], 0],
   [[3680, 1000, 3680, 1000, 3333, 1758, 1035, 1035, 750, 2760, 7400], 2447]],
  ['control 1',
   [[7400, 3680, 7400, 3333, 0, 1380, 1111, 3333, 3680, 7400, 1111, 1380],
    [[0, 3, 75, True], [0, 3, 50, False]], 0],
   [[3700, 1840, 3700, 3333, 0, 1380, 1111, 3333, 3680, 7400, 1111, 1380], 9240]],
  ['control 2', [[1380, 0, 3680, 7400, 0, 7400, 2345, 1000, 3680], [[7, 10, 25, False]], 2000],
   [[1380, 0, 3680, 7400, 0, 7400, 2345, 1000, 2000], 1680]]],
 [['boundary: event ends at slot', [[3680, 3680, 3680], [[0, 1, 50, False]], 0],
   [[1840, 3680, 3680], 1840]],
  ['boundary: opted-out event', [[7400, 7400], [[0, 2, 0, True]], 1380], [[7400, 7400], 0]],
  ['boundary: plan below floor', [[1000, 7400], [[0, 2, 0, False]], 1380], [[1000, 1380], 6020]],
  ['regression: percentage rounding stage',
   [[1380, 1380, 1111, 2345, 1380, 2345], [[6, 11, 0, False], [3, 7, 60, False], [3, 6, 0, False]],
    0],
   [[1380, 1380, 1111, 0, 0, 0], 6070]],
  ['regression: percentage rounding stage (partial repair)',
   [[1111, 1111, 2345, 3680, 3333, 1000, 3680, 7400, 7400, 0, 0, 7400],
    [[0, 1, 60, False], [8, 10, 75, False], [3, 5, 60, False]], 0],
   [[666, 1111, 2345, 2208, 1999, 1000, 3680, 7400, 5550, 0, 0, 7400], 5101]],
  ['control 1',
   [[0, 1000, 1000, 2345, 0, 3680, 1380, 3680], [[4, 8, 50, True], [5, 10, 75, True]], 0],
   [[0, 1000, 1000, 2345, 0, 3680, 1380, 3680], 0]],
  ['control 2',
   [[3333, 7400, 1000, 2345, 11000, 2345], [[3, 7, 50, False], [5, 6, 25, True]], 2000],
   [[3333, 7400, 1000, 2000, 5500, 2000], 6190]]],
 [['boundary: event ends at slot', [[3680, 3680, 3680], [[0, 1, 50, False]], 0],
   [[1840, 3680, 3680], 1840]],
  ['boundary: opted-out event', [[7400, 7400], [[0, 2, 0, True]], 1380], [[7400, 7400], 0]],
  ['boundary: plan below floor', [[1000, 7400], [[0, 2, 0, False]], 1380], [[1000, 1380], 6020]],
  ['regression: percentage rounding stage',
   [[0, 3333, 3333, 0, 1380, 2345, 1111, 11000, 0],
    [[7, 11, 25, False], [3, 4, 0, True], [3, 6, 0, True]], 2000],
   [[0, 3333, 3333, 0, 1380, 2345, 1111, 2750, 0], 8250]],
  ['regression: percentage rounding stage (partial repair)',
   [[1111, 1000, 3333, 11000, 1111, 2345, 11000, 11000, 3333],
    [[5, 10, 75, True], [6, 9, 75, False], [3, 5, 25, False]], 2000],
   [[1111, 1000, 3333, 2750, 1111, 2345, 8250, 8250, 2499], 14584]],
  ['control 1',
   [[3680, 3680, 1000, 0, 3333, 1000, 3333, 3680],
    [[1, 5, 0, False], [7, 11, 25, False], [6, 6, 60, False]], 2000],
   [[3680, 2000, 1000, 0, 2000, 1000, 3333, 2000], 4693]],
  ['control 2',
   [[1380, 7400, 7400, 1000, 1111, 2345, 1380], [[4, 8, 0, False], [6, 10, 0, False]], 0],
   [[1380, 7400, 7400, 1000, 0, 0, 0], 4836]]],
 [['boundary: event ends at slot', [[3680, 3680, 3680], [[0, 1, 50, False]], 0],
   [[1840, 3680, 3680], 1840]],
  ['boundary: opted-out event', [[7400, 7400], [[0, 2, 0, True]], 1380], [[7400, 7400], 0]],
  ['boundary: plan below floor', [[1000, 7400], [[0, 2, 0, False]], 1380], [[1000, 1380], 6020]],
  ['regression: percentage rounding stage',
   [[0, 2345, 2345, 1000, 11000, 0, 11000, 0, 11000, 1111, 1380, 0],
    [[5, 10, 60, False], [11, 15, 0, True], [5, 9, 25, False]], 2000],
   [[0, 2345, 2345, 1000, 11000, 0, 2750, 0, 2750, 1111, 1380, 0], 16500]],
  ['regression: percentage rounding stage (partial repair)',
   [[3333, 7400, 1000, 3680, 0, 7400, 1111, 0, 11000], [[6, 10, 50, False]], 0],
   [[3333, 7400, 1000, 3680, 0, 7400, 555, 0, 5500], 6056]],
  ['control 1', [[3333, 0, 1000, 1111, 1380, 7400, 1380, 7400, 3680], [[5, 10, 0, True]], 1380],
   [[3333, 0, 1000, 1111, 1380, 7400, 1380, 7400, 3680], 0]],
  ['control 2', [[2345, 7400, 1111, 3333, 3333, 7400, 3680], [[5, 8, 25, False]], 0],
   [[2345, 7400, 1111, 3333, 3333, 1850, 920], 8310]]]]
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
boundary: event ends at slot[[1840, 3680, 3680], 1840][[1840, 3680, 3680], 1840]Passed
boundary: opted-out event[[7400, 7400], 0][[7400, 7400], 0]Passed
boundary: plan below floor[[1000, 1380], 6020][[1000, 1380], 6020]Passed
regression: percentage rounding stage[[11000, 1000, 7400, 1380, 2345, 1380, 4440, 4440, 1111], 5920][[11000, 1000, 7400, 1380, 2345, 1380, 4440, 4440, 1111], 5920]Passed
regression: percentage rounding stage (partial repair)[[11000, 11000, 1407, 666, 0, 1380, 11000, 1380, 3680], 1383][[11000, 11000, 1407, 666, 0, 1380, 11000, 1380, 3680], 1383]Passed
control 1[[1000, 3333, 1111, 1380, 2750], 8250][[1000, 3333, 1111, 1380, 2750], 8250]Passed
control 2[[1380, 1000, 1111, 1000, 1000, 2000, 2000, 7400, 1111, 2208, 6600, 1111], 8538][[1380, 1000, 1111, 1000, 1000, 2000, 2000, 7400, 1111, 2208, 6600, 1111], 8538]Passed

SHA-256 / 860297782823e60b46e20e736a159ba0b13f13f50928fd43f7f16abc45d7c798

Verification & scope

Deterministic stipulated toy contract for teaching; no claim of conformance with any standard, vendor protocol or production controller. 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:52.710355+00:00.

Case digest / a25d36b23a23bdb9ad4fd85f221cfc3bac65a16545116d9e05c1467475d64cbc