FAILURE MAP
← Case archive

FA-67821 / Elevator dispatch scheduling / Open access

Encoder position and door zone detection: pulse unit conversion · case 01

The car position drifts or barely moves with encoder pulses.

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

ROOT CAUSE

Pulse travel is converted to millimetres and then added to a micrometre position.

VERIFIED REPAIR

Accumulate pulse travel in micrometres.

Unsuccessful approach: Dividing the pulse count first discards all counts below 1000.

Case contract

Car position is tracked in micrometres: start_mm*1000, pulses add count*um_per_pulse, a door-zone magnet at floor k resets the position to floor_mm[k]*1000. After every event the position in mm is floor(um/1000); the car is at the nearest floor (ties to the lower index) if within zone_mm inclusive, otherwise None (between floors).

Why this case matters

Lift group controllers make these decisions many times per minute; a wrong answer strands passengers, wastes trips or overrides a safety rule.

1 / The failure

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

N = 1
observations = []
def solve(x):
    table = x['floor_mm']
    pos = x['start_mm'] * 1000
    out = []
    for kind, v in x['events']:
        if kind == 'pulses':
            pos += v * x['um_per_pulse'] // 1000
        else:
            pos = table[v] * 1000
        mm = pos // 1000
        best = min(range(len(table)), key=lambda k: (abs(table[k] - mm), k))
        out.append(best if abs(table[best] - mm) <= x['zone_mm'] else None)
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: encoder slip accumulates', {'floor_mm': [0, 3000, 6000], 'start_mm': 0, 'um_per_pulse': 997, 'zone_mm': 50, 'events': [['pulses', 3000], ['pulses', 3000]]}, [1, 2]), ('regression: sub-millimetre pulses', {'floor_mm': [0, 3000], 'start_mm': 0, 'um_per_pulse': 997, 'zone_mm': 50, 'events': [['pulses', 999], ['pulses', 2]]}, [None, None]), ('regression: magnet correction', {'floor_mm': [0, 3000, 6000], 'start_mm': 0, 'um_per_pulse': 1003, 'zone_mm': 50, 'events': [['pulses', 3000], ['magnet', 1], ['pulses', 3000]]}, [1, 1, 2]), ('regression: zone edge', {'floor_mm': [0, 3000], 'start_mm': 0, 'um_per_pulse': 1000, 'zone_mm': 75, 'events': [['pulses', 2925], ['pulses', 1]]}, [1, 1]), ('regression: six-tenths of a millimetre short of the zone', {'floor_mm': [0, 3000], 'start_mm': 2924, 'um_per_pulse': 600, 'zone_mm': 75, 'events': [['pulses', 1], ['pulses', 1]]}, [None, 1]), ('sampled regression 1', {'floor_mm': [0, 4200, 8400, 11400, 14900], 'start_mm': 20, 'um_per_pulse': 1000, 'zone_mm': 50, 'events': [['magnet', 3], ['pulses', 5000], ['magnet', 4], ['pulses', 2999], ['pulses', 4200], ['pulses', 2999], ['magnet', 4]]}, [3, None, 4, None, None, None, 4]), ('sampled regression 4', {'floor_mm': [0, 3000, 6500, 10000, 13500, 16500, 20000], 'start_mm': 2990, 'um_per_pulse': 1000, 'zone_mm': 75, 'events': [['pulses', 1000], ['pulses', 100]]}, [None, None]), ('sampled regression 7', {'floor_mm': [0, 3500, 7700, 10700, 14200, 17200, 21400], 'start_mm': 2990, 'um_per_pulse': 997, 'zone_mm': 75, 'events': [['magnet', 0], ['pulses', 100], ['pulses', 1000], ['pulses', 100], ['magnet', 2], ['pulses', 3000]]}, [0, None, None, None, 2, 3])], [('regression: magnet correction', {'floor_mm': [0, 3000, 6000], 'start_mm': 0, 'um_per_pulse': 1003, 'zone_mm': 50, 'events': [['pulses', 3000], ['magnet', 1], ['pulses', 3000]]}, [1, 1, 2]), ('sampled regression 6', {'floor_mm': [0, 3000, 6000, 9000, 12500, 16000, 19000, 22500, 26700], 'start_mm': 20, 'um_per_pulse': 1000, 'zone_mm': 50, 'events': [['magnet', 2], ['pulses', 3000], ['pulses', 4200], ['magnet', 2], ['pulses', 5000], ['pulses', 2999], ['pulses', 3500]]}, [2, 3, None, 2, None, None, None]), ('sampled regression 1', {'floor_mm': [0, 4200, 8400, 11400, 14900], 'start_mm': 20, 'um_per_pulse': 1000, 'zone_mm': 50, 'events': [['magnet', 3], ['pulses', 5000], ['magnet', 4], ['pulses', 2999], ['pulses', 4200], ['pulses', 2999], ['magnet', 4]]}, [3, None, 4, None, None, None, 4]), ('regression: zone edge', {'floor_mm': [0, 3000], 'start_mm': 0, 'um_per_pulse': 1000, 'zone_mm': 75, 'events': [['pulses', 2925], ['pulses', 1]]}, [1, 1]), ('regression: sub-millimetre pulses', {'floor_mm': [0, 3000], 'start_mm': 0, 'um_per_pulse': 997, 'zone_mm': 50, 'events': [['pulses', 999], ['pulses', 2]]}, [None, None]), ('sampled regression 12', {'floor_mm': [0, 3000, 6000, 10200, 13200, 17400], 'start_mm': 2990, 'um_per_pulse': 997, 'zone_mm': 75, 'events': [['magnet', 0], ['pulses', 3499], ['pulses', 1000], ['pulses', 3500], ['pulses', 100], ['magnet', 2], ['pulses', 3500]]}, [0, None, None, None, None, 2, None]), ('sampled regression 15', {'floor_mm': [0, 3000, 7200, 11400, 15600, 19100], 'start_mm': 0, 'um_per_pulse': 1000, 'zone_mm': 50, 'events': [['pulses', 2999], ['pulses', 3499]]}, [1, None]), ('sampled regression 18', {'floor_mm': [0, 3000, 7200, 11400, 15600, 19100], 'start_mm': 0, 'um_per_pulse': 1003, 'zone_mm': 75, 'events': [['pulses', 3499], ['pulses', 3000], ['pulses', 3000]]}, [None, None, None])], [('regression: zone edge', {'floor_mm': [0, 3000], 'start_mm': 0, 'um_per_pulse': 1000, 'zone_mm': 75, 'events': [['pulses', 2925], ['pulses', 1]]}, [1, 1]), ('sampled regression 13', {'floor_mm': [0, 3000, 6000, 10200, 13200, 17400, 20900, 25100], 'start_mm': 20, 'um_per_pulse': 1003, 'zone_mm': 50, 'events': [['pulses', 5000], ['pulses', 3499], ['pulses', 4200], ['pulses', 5000]]}, [None, None, None, None]), ('sampled regression 7', {'floor_mm': [0, 3500, 7700, 10700, 14200, 17200, 21400], 'start_mm': 2990, 'um_per_pulse': 997, 'zone_mm': 75, 'events': [['magnet', 0], ['pulses', 100], ['pulses', 1000], ['pulses', 100], ['magnet', 2], ['pulses', 3000]]}, [0, None, None, None, 2, 3]), ('regression: six-tenths of a millimetre short of the zone', {'floor_mm': [0, 3000], 'start_mm': 2924, 'um_per_pulse': 600, 'zone_mm': 75, 'events': [['pulses', 1], ['pulses', 1]]}, [None, 1]), ('regression: fractional millimetre below a floor', {'floor_mm': [0, 3000], 'start_mm': 2924, 'um_per_pulse': 1003, 'zone_mm': 75, 'events': [['pulses', 1]]}, [1]), ('sampled regression 23', {'floor_mm': [0, 4200, 7700, 11200, 15400, 18400, 22600, 25600, 28600], 'start_mm': 0, 'um_per_pulse': 1003, 'zone_mm': 50, 'events': [['pulses', 3500], ['pulses', 3000]]}, [None, None]), ('sampled regression 26', {'floor_mm': [0, 4200, 7200, 11400, 14900, 17900, 21400, 25600], 'start_mm': 0, 'um_per_pulse': 997, 'zone_mm': 75, 'events': [['pulses', 4200], ['pulses', 4200], ['pulses', 3500], ['pulses', 2999], ['pulses', 3499], ['pulses', 2999], ['pulses', 4200]]}, [1, None, None, 4, None, 6, None]), ('sampled regression 29', {'floor_mm': [0, 4200, 8400, 12600, 16100, 20300, 23800, 27300], 'start_mm': 20, 'um_per_pulse': 600, 'zone_mm': 50, 'events': [['magnet', 3], ['pulses', 2999], ['pulses', 3499], ['pulses', 5000], ['magnet', 1], ['pulses', 100]]}, [3, None, None, None, 1, None])], [('regression: sub-millimetre pulses', {'floor_mm': [0, 3000], 'start_mm': 0, 'um_per_pulse': 997, 'zone_mm': 50, 'events': [['pulses', 999], ['pulses', 2]]}, [None, None]), ('sampled regression 20', {'floor_mm': [0, 3500, 7000, 11200, 14700, 17700], 'start_mm': 0, 'um_per_pulse': 1003, 'zone_mm': 50, 'events': [['pulses', 3499], ['pulses', 2999], ['pulses', 1000], ['pulses', 3500]]}, [1, None, None, None]), ('sampled regression 12', {'floor_mm': [0, 3000, 6000, 10200, 13200, 17400], 'start_mm': 2990, 'um_per_pulse': 997, 'zone_mm': 75, 'events': [['magnet', 0], ['pulses', 3499], ['pulses', 1000], ['pulses', 3500], ['pulses', 100], ['magnet', 2], ['pulses', 3500]]}, [0, None, None, None, None, 2, None]), ('regression: encoder slip accumulates', {'floor_mm': [0, 3000, 6000], 'start_mm': 0, 'um_per_pulse': 997, 'zone_mm': 50, 'events': [['pulses', 3000], ['pulses', 3000]]}, [1, 2]), ('regression: magnet correction', {'floor_mm': [0, 3000, 6000], 'start_mm': 0, 'um_per_pulse': 1003, 'zone_mm': 50, 'events': [['pulses', 3000], ['magnet', 1], ['pulses', 3000]]}, [1, 1, 2]), ('sampled regression 34', {'floor_mm': [0, 4200, 7700, 10700, 14200, 17700, 20700, 23700], 'start_mm': 2990, 'um_per_pulse': 600, 'zone_mm': 50, 'events': [['magnet', 5], ['pulses', 5000]]}, [5, 6]), ('sampled regression 37', {'floor_mm': [0, 4200, 7200, 10700, 14200, 17700, 20700], 'start_mm': 20, 'um_per_pulse': 1000, 'zone_mm': 50, 'events': [['pulses', 2999], ['pulses', 1000], ['pulses', 100], ['magnet', 2]]}, [None, None, None, 2]), ('sampled regression 40', {'floor_mm': [0, 4200, 7700, 11900, 15400, 19600, 22600, 26800, 29800], 'start_mm': 20, 'um_per_pulse': 1000, 'zone_mm': 50, 'events': [['pulses', 3000], ['magnet', 0], ['magnet', 8], ['pulses', 5000], ['pulses', 3000], ['pulses', 5000], ['magnet', 4]]}, [None, 0, 8, None, None, None, 4])], [('regression: six-tenths of a millimetre short of the zone', {'floor_mm': [0, 3000], 'start_mm': 2924, 'um_per_pulse': 600, 'zone_mm': 75, 'events': [['pulses', 1], ['pulses', 1]]}, [None, 1]), ('sampled regression 28', {'floor_mm': [0, 4200, 7200, 10700, 14200, 17200, 20700, 24900, 28400], 'start_mm': 2990, 'um_per_pulse': 997, 'zone_mm': 75, 'events': [['magnet', 0], ['pulses', 4200], ['pulses', 3000], ['pulses', 3500]]}, [0, 1, 2, 3]), ('sampled regression 17', {'floor_mm': [0, 3500, 7700, 11200, 14700, 17700], 'start_mm': 20, 'um_per_pulse': 997, 'zone_mm': 50, 'events': [['pulses', 3500], ['pulses', 3000], ['pulses', 3499], ['pulses', 2999], ['magnet', 2], ['pulses', 4200]]}, [1, None, None, None, 2, None]), ('regression: zone edge', {'floor_mm': [0, 3000], 'start_mm': 0, 'um_per_pulse': 1000, 'zone_mm': 75, 'events': [['pulses', 2925], ['pulses', 1]]}, [1, 1]), ('regression: sub-millimetre pulses', {'floor_mm': [0, 3000], 'start_mm': 0, 'um_per_pulse': 997, 'zone_mm': 50, 'events': [['pulses', 999], ['pulses', 2]]}, [None, None]), ('sampled regression 45', {'floor_mm': [0, 3000, 7200, 11400, 15600, 19800, 22800, 26300], 'start_mm': 2990, 'um_per_pulse': 600, 'zone_mm': 75, 'events': [['magnet', 3], ['pulses', 3500], ['pulses', 3500]]}, [3, None, 4]), ('sampled regression 48', {'floor_mm': [0, 3000, 6000, 9000, 13200, 16200, 20400, 23400, 26400], 'start_mm': 0, 'um_per_pulse': 1003, 'zone_mm': 50, 'events': [['magnet', 0], ['pulses', 1000], ['magnet', 2]]}, [0, None, 2]), ('sampled regression 51', {'floor_mm': [0, 4200, 7200, 10700, 14900, 19100], 'start_mm': 2990, 'um_per_pulse': 1003, 'zone_mm': 50, 'events': [['magnet', 0], ['pulses', 100], ['pulses', 100]]}, [0, None, None])]]
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: encoder slip accumulates[0, 0][1, 2]Failed
regression: sub-millimetre pulses[0, 0][None, None]Failed
regression: magnet correction[0, 1, 1][1, 1, 2]Failed
regression: zone edge[0, 0][1, 1]Failed
regression: six-tenths of a millimetre short of the zone[None, None][None, 1]Failed
sampled regression 1[3, 3, 4, 4, 4, 4, 4][3, None, 4, None, None, None, 4]Failed
sampled regression 4[1, 1][None, None]Failed
sampled regression 7[0, 0, 0, 0, 2, 2][0, None, None, None, 2, 3]Failed

SHA-256 / 5c8452b8f444b91f869438f835566ef27465490a0cf51b9f4b738b89286a6bed

2 / The unsuccessful fix

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

N = 1
observations = []
def solve(x):
    table = x['floor_mm']
    pos = x['start_mm'] * 1000
    out = []
    for kind, v in x['events']:
        if kind == 'pulses':
            pos += v // 1000 * x['um_per_pulse']
        else:
            pos = table[v] * 1000
        mm = pos // 1000
        best = min(range(len(table)), key=lambda k: (abs(table[k] - mm), k))
        out.append(best if abs(table[best] - mm) <= x['zone_mm'] else None)
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: encoder slip accumulates', {'floor_mm': [0, 3000, 6000], 'start_mm': 0, 'um_per_pulse': 997, 'zone_mm': 50, 'events': [['pulses', 3000], ['pulses', 3000]]}, [1, 2]), ('regression: sub-millimetre pulses', {'floor_mm': [0, 3000], 'start_mm': 0, 'um_per_pulse': 997, 'zone_mm': 50, 'events': [['pulses', 999], ['pulses', 2]]}, [None, None]), ('regression: magnet correction', {'floor_mm': [0, 3000, 6000], 'start_mm': 0, 'um_per_pulse': 1003, 'zone_mm': 50, 'events': [['pulses', 3000], ['magnet', 1], ['pulses', 3000]]}, [1, 1, 2]), ('regression: zone edge', {'floor_mm': [0, 3000], 'start_mm': 0, 'um_per_pulse': 1000, 'zone_mm': 75, 'events': [['pulses', 2925], ['pulses', 1]]}, [1, 1]), ('regression: six-tenths of a millimetre short of the zone', {'floor_mm': [0, 3000], 'start_mm': 2924, 'um_per_pulse': 600, 'zone_mm': 75, 'events': [['pulses', 1], ['pulses', 1]]}, [None, 1]), ('sampled regression 1', {'floor_mm': [0, 4200, 8400, 11400, 14900], 'start_mm': 20, 'um_per_pulse': 1000, 'zone_mm': 50, 'events': [['magnet', 3], ['pulses', 5000], ['magnet', 4], ['pulses', 2999], ['pulses', 4200], ['pulses', 2999], ['magnet', 4]]}, [3, None, 4, None, None, None, 4]), ('sampled regression 4', {'floor_mm': [0, 3000, 6500, 10000, 13500, 16500, 20000], 'start_mm': 2990, 'um_per_pulse': 1000, 'zone_mm': 75, 'events': [['pulses', 1000], ['pulses', 100]]}, [None, None]), ('sampled regression 7', {'floor_mm': [0, 3500, 7700, 10700, 14200, 17200, 21400], 'start_mm': 2990, 'um_per_pulse': 997, 'zone_mm': 75, 'events': [['magnet', 0], ['pulses', 100], ['pulses', 1000], ['pulses', 100], ['magnet', 2], ['pulses', 3000]]}, [0, None, None, None, 2, 3])], [('regression: magnet correction', {'floor_mm': [0, 3000, 6000], 'start_mm': 0, 'um_per_pulse': 1003, 'zone_mm': 50, 'events': [['pulses', 3000], ['magnet', 1], ['pulses', 3000]]}, [1, 1, 2]), ('sampled regression 6', {'floor_mm': [0, 3000, 6000, 9000, 12500, 16000, 19000, 22500, 26700], 'start_mm': 20, 'um_per_pulse': 1000, 'zone_mm': 50, 'events': [['magnet', 2], ['pulses', 3000], ['pulses', 4200], ['magnet', 2], ['pulses', 5000], ['pulses', 2999], ['pulses', 3500]]}, [2, 3, None, 2, None, None, None]), ('sampled regression 1', {'floor_mm': [0, 4200, 8400, 11400, 14900], 'start_mm': 20, 'um_per_pulse': 1000, 'zone_mm': 50, 'events': [['magnet', 3], ['pulses', 5000], ['magnet', 4], ['pulses', 2999], ['pulses', 4200], ['pulses', 2999], ['magnet', 4]]}, [3, None, 4, None, None, None, 4]), ('regression: zone edge', {'floor_mm': [0, 3000], 'start_mm': 0, 'um_per_pulse': 1000, 'zone_mm': 75, 'events': [['pulses', 2925], ['pulses', 1]]}, [1, 1]), ('regression: sub-millimetre pulses', {'floor_mm': [0, 3000], 'start_mm': 0, 'um_per_pulse': 997, 'zone_mm': 50, 'events': [['pulses', 999], ['pulses', 2]]}, [None, None]), ('sampled regression 12', {'floor_mm': [0, 3000, 6000, 10200, 13200, 17400], 'start_mm': 2990, 'um_per_pulse': 997, 'zone_mm': 75, 'events': [['magnet', 0], ['pulses', 3499], ['pulses', 1000], ['pulses', 3500], ['pulses', 100], ['magnet', 2], ['pulses', 3500]]}, [0, None, None, None, None, 2, None]), ('sampled regression 15', {'floor_mm': [0, 3000, 7200, 11400, 15600, 19100], 'start_mm': 0, 'um_per_pulse': 1000, 'zone_mm': 50, 'events': [['pulses', 2999], ['pulses', 3499]]}, [1, None]), ('sampled regression 18', {'floor_mm': [0, 3000, 7200, 11400, 15600, 19100], 'start_mm': 0, 'um_per_pulse': 1003, 'zone_mm': 75, 'events': [['pulses', 3499], ['pulses', 3000], ['pulses', 3000]]}, [None, None, None])], [('regression: zone edge', {'floor_mm': [0, 3000], 'start_mm': 0, 'um_per_pulse': 1000, 'zone_mm': 75, 'events': [['pulses', 2925], ['pulses', 1]]}, [1, 1]), ('sampled regression 13', {'floor_mm': [0, 3000, 6000, 10200, 13200, 17400, 20900, 25100], 'start_mm': 20, 'um_per_pulse': 1003, 'zone_mm': 50, 'events': [['pulses', 5000], ['pulses', 3499], ['pulses', 4200], ['pulses', 5000]]}, [None, None, None, None]), ('sampled regression 7', {'floor_mm': [0, 3500, 7700, 10700, 14200, 17200, 21400], 'start_mm': 2990, 'um_per_pulse': 997, 'zone_mm': 75, 'events': [['magnet', 0], ['pulses', 100], ['pulses', 1000], ['pulses', 100], ['magnet', 2], ['pulses', 3000]]}, [0, None, None, None, 2, 3]), ('regression: six-tenths of a millimetre short of the zone', {'floor_mm': [0, 3000], 'start_mm': 2924, 'um_per_pulse': 600, 'zone_mm': 75, 'events': [['pulses', 1], ['pulses', 1]]}, [None, 1]), ('regression: fractional millimetre below a floor', {'floor_mm': [0, 3000], 'start_mm': 2924, 'um_per_pulse': 1003, 'zone_mm': 75, 'events': [['pulses', 1]]}, [1]), ('sampled regression 23', {'floor_mm': [0, 4200, 7700, 11200, 15400, 18400, 22600, 25600, 28600], 'start_mm': 0, 'um_per_pulse': 1003, 'zone_mm': 50, 'events': [['pulses', 3500], ['pulses', 3000]]}, [None, None]), ('sampled regression 26', {'floor_mm': [0, 4200, 7200, 11400, 14900, 17900, 21400, 25600], 'start_mm': 0, 'um_per_pulse': 997, 'zone_mm': 75, 'events': [['pulses', 4200], ['pulses', 4200], ['pulses', 3500], ['pulses', 2999], ['pulses', 3499], ['pulses', 2999], ['pulses', 4200]]}, [1, None, None, 4, None, 6, None]), ('sampled regression 29', {'floor_mm': [0, 4200, 8400, 12600, 16100, 20300, 23800, 27300], 'start_mm': 20, 'um_per_pulse': 600, 'zone_mm': 50, 'events': [['magnet', 3], ['pulses', 2999], ['pulses', 3499], ['pulses', 5000], ['magnet', 1], ['pulses', 100]]}, [3, None, None, None, 1, None])], [('regression: sub-millimetre pulses', {'floor_mm': [0, 3000], 'start_mm': 0, 'um_per_pulse': 997, 'zone_mm': 50, 'events': [['pulses', 999], ['pulses', 2]]}, [None, None]), ('sampled regression 20', {'floor_mm': [0, 3500, 7000, 11200, 14700, 17700], 'start_mm': 0, 'um_per_pulse': 1003, 'zone_mm': 50, 'events': [['pulses', 3499], ['pulses', 2999], ['pulses', 1000], ['pulses', 3500]]}, [1, None, None, None]), ('sampled regression 12', {'floor_mm': [0, 3000, 6000, 10200, 13200, 17400], 'start_mm': 2990, 'um_per_pulse': 997, 'zone_mm': 75, 'events': [['magnet', 0], ['pulses', 3499], ['pulses', 1000], ['pulses', 3500], ['pulses', 100], ['magnet', 2], ['pulses', 3500]]}, [0, None, None, None, None, 2, None]), ('regression: encoder slip accumulates', {'floor_mm': [0, 3000, 6000], 'start_mm': 0, 'um_per_pulse': 997, 'zone_mm': 50, 'events': [['pulses', 3000], ['pulses', 3000]]}, [1, 2]), ('regression: magnet correction', {'floor_mm': [0, 3000, 6000], 'start_mm': 0, 'um_per_pulse': 1003, 'zone_mm': 50, 'events': [['pulses', 3000], ['magnet', 1], ['pulses', 3000]]}, [1, 1, 2]), ('sampled regression 34', {'floor_mm': [0, 4200, 7700, 10700, 14200, 17700, 20700, 23700], 'start_mm': 2990, 'um_per_pulse': 600, 'zone_mm': 50, 'events': [['magnet', 5], ['pulses', 5000]]}, [5, 6]), ('sampled regression 37', {'floor_mm': [0, 4200, 7200, 10700, 14200, 17700, 20700], 'start_mm': 20, 'um_per_pulse': 1000, 'zone_mm': 50, 'events': [['pulses', 2999], ['pulses', 1000], ['pulses', 100], ['magnet', 2]]}, [None, None, None, 2]), ('sampled regression 40', {'floor_mm': [0, 4200, 7700, 11900, 15400, 19600, 22600, 26800, 29800], 'start_mm': 20, 'um_per_pulse': 1000, 'zone_mm': 50, 'events': [['pulses', 3000], ['magnet', 0], ['magnet', 8], ['pulses', 5000], ['pulses', 3000], ['pulses', 5000], ['magnet', 4]]}, [None, 0, 8, None, None, None, 4])], [('regression: six-tenths of a millimetre short of the zone', {'floor_mm': [0, 3000], 'start_mm': 2924, 'um_per_pulse': 600, 'zone_mm': 75, 'events': [['pulses', 1], ['pulses', 1]]}, [None, 1]), ('sampled regression 28', {'floor_mm': [0, 4200, 7200, 10700, 14200, 17200, 20700, 24900, 28400], 'start_mm': 2990, 'um_per_pulse': 997, 'zone_mm': 75, 'events': [['magnet', 0], ['pulses', 4200], ['pulses', 3000], ['pulses', 3500]]}, [0, 1, 2, 3]), ('sampled regression 17', {'floor_mm': [0, 3500, 7700, 11200, 14700, 17700], 'start_mm': 20, 'um_per_pulse': 997, 'zone_mm': 50, 'events': [['pulses', 3500], ['pulses', 3000], ['pulses', 3499], ['pulses', 2999], ['magnet', 2], ['pulses', 4200]]}, [1, None, None, None, 2, None]), ('regression: zone edge', {'floor_mm': [0, 3000], 'start_mm': 0, 'um_per_pulse': 1000, 'zone_mm': 75, 'events': [['pulses', 2925], ['pulses', 1]]}, [1, 1]), ('regression: sub-millimetre pulses', {'floor_mm': [0, 3000], 'start_mm': 0, 'um_per_pulse': 997, 'zone_mm': 50, 'events': [['pulses', 999], ['pulses', 2]]}, [None, None]), ('sampled regression 45', {'floor_mm': [0, 3000, 7200, 11400, 15600, 19800, 22800, 26300], 'start_mm': 2990, 'um_per_pulse': 600, 'zone_mm': 75, 'events': [['magnet', 3], ['pulses', 3500], ['pulses', 3500]]}, [3, None, 4]), ('sampled regression 48', {'floor_mm': [0, 3000, 6000, 9000, 13200, 16200, 20400, 23400, 26400], 'start_mm': 0, 'um_per_pulse': 1003, 'zone_mm': 50, 'events': [['magnet', 0], ['pulses', 1000], ['magnet', 2]]}, [0, None, 2]), ('sampled regression 51', {'floor_mm': [0, 4200, 7200, 10700, 14900, 19100], 'start_mm': 2990, 'um_per_pulse': 1003, 'zone_mm': 50, 'events': [['magnet', 0], ['pulses', 100], ['pulses', 100]]}, [0, None, None])]]
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: encoder slip accumulates[0, 0][1, 2]Failed
regression: sub-millimetre pulses[0, 0][None, None]Failed
regression: magnet correction[0, 1, 1][1, 1, 2]Failed
regression: zone edge[0, 0][1, 1]Failed
regression: six-tenths of a millimetre short of the zone[None, None][None, 1]Failed
sampled regression 1[3, 3, 4, 4, 4, 4, 4][3, None, 4, None, None, None, 4]Failed
sampled regression 4[1, 1][None, None]Failed
sampled regression 7[0, 0, 0, 0, 2, 2][0, None, None, None, 2, 3]Failed

SHA-256 / 6ce9f146b8ad3d5b3d43436d36d0eccb9b0feb6a92cd541e1c49f4e289af6744

3 / The verified repair

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

N = 1
observations = []
def solve(x):
    table = x['floor_mm']
    pos = x['start_mm'] * 1000
    out = []
    for kind, v in x['events']:
        if kind == 'pulses':
            pos += v * x['um_per_pulse']
        else:
            pos = table[v] * 1000
        mm = pos // 1000
        best = min(range(len(table)), key=lambda k: (abs(table[k] - mm), k))
        out.append(best if abs(table[best] - mm) <= x['zone_mm'] else None)
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: encoder slip accumulates', {'floor_mm': [0, 3000, 6000], 'start_mm': 0, 'um_per_pulse': 997, 'zone_mm': 50, 'events': [['pulses', 3000], ['pulses', 3000]]}, [1, 2]), ('regression: sub-millimetre pulses', {'floor_mm': [0, 3000], 'start_mm': 0, 'um_per_pulse': 997, 'zone_mm': 50, 'events': [['pulses', 999], ['pulses', 2]]}, [None, None]), ('regression: magnet correction', {'floor_mm': [0, 3000, 6000], 'start_mm': 0, 'um_per_pulse': 1003, 'zone_mm': 50, 'events': [['pulses', 3000], ['magnet', 1], ['pulses', 3000]]}, [1, 1, 2]), ('regression: zone edge', {'floor_mm': [0, 3000], 'start_mm': 0, 'um_per_pulse': 1000, 'zone_mm': 75, 'events': [['pulses', 2925], ['pulses', 1]]}, [1, 1]), ('regression: six-tenths of a millimetre short of the zone', {'floor_mm': [0, 3000], 'start_mm': 2924, 'um_per_pulse': 600, 'zone_mm': 75, 'events': [['pulses', 1], ['pulses', 1]]}, [None, 1]), ('sampled regression 1', {'floor_mm': [0, 4200, 8400, 11400, 14900], 'start_mm': 20, 'um_per_pulse': 1000, 'zone_mm': 50, 'events': [['magnet', 3], ['pulses', 5000], ['magnet', 4], ['pulses', 2999], ['pulses', 4200], ['pulses', 2999], ['magnet', 4]]}, [3, None, 4, None, None, None, 4]), ('sampled regression 4', {'floor_mm': [0, 3000, 6500, 10000, 13500, 16500, 20000], 'start_mm': 2990, 'um_per_pulse': 1000, 'zone_mm': 75, 'events': [['pulses', 1000], ['pulses', 100]]}, [None, None]), ('sampled regression 7', {'floor_mm': [0, 3500, 7700, 10700, 14200, 17200, 21400], 'start_mm': 2990, 'um_per_pulse': 997, 'zone_mm': 75, 'events': [['magnet', 0], ['pulses', 100], ['pulses', 1000], ['pulses', 100], ['magnet', 2], ['pulses', 3000]]}, [0, None, None, None, 2, 3])], [('regression: magnet correction', {'floor_mm': [0, 3000, 6000], 'start_mm': 0, 'um_per_pulse': 1003, 'zone_mm': 50, 'events': [['pulses', 3000], ['magnet', 1], ['pulses', 3000]]}, [1, 1, 2]), ('sampled regression 6', {'floor_mm': [0, 3000, 6000, 9000, 12500, 16000, 19000, 22500, 26700], 'start_mm': 20, 'um_per_pulse': 1000, 'zone_mm': 50, 'events': [['magnet', 2], ['pulses', 3000], ['pulses', 4200], ['magnet', 2], ['pulses', 5000], ['pulses', 2999], ['pulses', 3500]]}, [2, 3, None, 2, None, None, None]), ('sampled regression 1', {'floor_mm': [0, 4200, 8400, 11400, 14900], 'start_mm': 20, 'um_per_pulse': 1000, 'zone_mm': 50, 'events': [['magnet', 3], ['pulses', 5000], ['magnet', 4], ['pulses', 2999], ['pulses', 4200], ['pulses', 2999], ['magnet', 4]]}, [3, None, 4, None, None, None, 4]), ('regression: zone edge', {'floor_mm': [0, 3000], 'start_mm': 0, 'um_per_pulse': 1000, 'zone_mm': 75, 'events': [['pulses', 2925], ['pulses', 1]]}, [1, 1]), ('regression: sub-millimetre pulses', {'floor_mm': [0, 3000], 'start_mm': 0, 'um_per_pulse': 997, 'zone_mm': 50, 'events': [['pulses', 999], ['pulses', 2]]}, [None, None]), ('sampled regression 12', {'floor_mm': [0, 3000, 6000, 10200, 13200, 17400], 'start_mm': 2990, 'um_per_pulse': 997, 'zone_mm': 75, 'events': [['magnet', 0], ['pulses', 3499], ['pulses', 1000], ['pulses', 3500], ['pulses', 100], ['magnet', 2], ['pulses', 3500]]}, [0, None, None, None, None, 2, None]), ('sampled regression 15', {'floor_mm': [0, 3000, 7200, 11400, 15600, 19100], 'start_mm': 0, 'um_per_pulse': 1000, 'zone_mm': 50, 'events': [['pulses', 2999], ['pulses', 3499]]}, [1, None]), ('sampled regression 18', {'floor_mm': [0, 3000, 7200, 11400, 15600, 19100], 'start_mm': 0, 'um_per_pulse': 1003, 'zone_mm': 75, 'events': [['pulses', 3499], ['pulses', 3000], ['pulses', 3000]]}, [None, None, None])], [('regression: zone edge', {'floor_mm': [0, 3000], 'start_mm': 0, 'um_per_pulse': 1000, 'zone_mm': 75, 'events': [['pulses', 2925], ['pulses', 1]]}, [1, 1]), ('sampled regression 13', {'floor_mm': [0, 3000, 6000, 10200, 13200, 17400, 20900, 25100], 'start_mm': 20, 'um_per_pulse': 1003, 'zone_mm': 50, 'events': [['pulses', 5000], ['pulses', 3499], ['pulses', 4200], ['pulses', 5000]]}, [None, None, None, None]), ('sampled regression 7', {'floor_mm': [0, 3500, 7700, 10700, 14200, 17200, 21400], 'start_mm': 2990, 'um_per_pulse': 997, 'zone_mm': 75, 'events': [['magnet', 0], ['pulses', 100], ['pulses', 1000], ['pulses', 100], ['magnet', 2], ['pulses', 3000]]}, [0, None, None, None, 2, 3]), ('regression: six-tenths of a millimetre short of the zone', {'floor_mm': [0, 3000], 'start_mm': 2924, 'um_per_pulse': 600, 'zone_mm': 75, 'events': [['pulses', 1], ['pulses', 1]]}, [None, 1]), ('regression: fractional millimetre below a floor', {'floor_mm': [0, 3000], 'start_mm': 2924, 'um_per_pulse': 1003, 'zone_mm': 75, 'events': [['pulses', 1]]}, [1]), ('sampled regression 23', {'floor_mm': [0, 4200, 7700, 11200, 15400, 18400, 22600, 25600, 28600], 'start_mm': 0, 'um_per_pulse': 1003, 'zone_mm': 50, 'events': [['pulses', 3500], ['pulses', 3000]]}, [None, None]), ('sampled regression 26', {'floor_mm': [0, 4200, 7200, 11400, 14900, 17900, 21400, 25600], 'start_mm': 0, 'um_per_pulse': 997, 'zone_mm': 75, 'events': [['pulses', 4200], ['pulses', 4200], ['pulses', 3500], ['pulses', 2999], ['pulses', 3499], ['pulses', 2999], ['pulses', 4200]]}, [1, None, None, 4, None, 6, None]), ('sampled regression 29', {'floor_mm': [0, 4200, 8400, 12600, 16100, 20300, 23800, 27300], 'start_mm': 20, 'um_per_pulse': 600, 'zone_mm': 50, 'events': [['magnet', 3], ['pulses', 2999], ['pulses', 3499], ['pulses', 5000], ['magnet', 1], ['pulses', 100]]}, [3, None, None, None, 1, None])], [('regression: sub-millimetre pulses', {'floor_mm': [0, 3000], 'start_mm': 0, 'um_per_pulse': 997, 'zone_mm': 50, 'events': [['pulses', 999], ['pulses', 2]]}, [None, None]), ('sampled regression 20', {'floor_mm': [0, 3500, 7000, 11200, 14700, 17700], 'start_mm': 0, 'um_per_pulse': 1003, 'zone_mm': 50, 'events': [['pulses', 3499], ['pulses', 2999], ['pulses', 1000], ['pulses', 3500]]}, [1, None, None, None]), ('sampled regression 12', {'floor_mm': [0, 3000, 6000, 10200, 13200, 17400], 'start_mm': 2990, 'um_per_pulse': 997, 'zone_mm': 75, 'events': [['magnet', 0], ['pulses', 3499], ['pulses', 1000], ['pulses', 3500], ['pulses', 100], ['magnet', 2], ['pulses', 3500]]}, [0, None, None, None, None, 2, None]), ('regression: encoder slip accumulates', {'floor_mm': [0, 3000, 6000], 'start_mm': 0, 'um_per_pulse': 997, 'zone_mm': 50, 'events': [['pulses', 3000], ['pulses', 3000]]}, [1, 2]), ('regression: magnet correction', {'floor_mm': [0, 3000, 6000], 'start_mm': 0, 'um_per_pulse': 1003, 'zone_mm': 50, 'events': [['pulses', 3000], ['magnet', 1], ['pulses', 3000]]}, [1, 1, 2]), ('sampled regression 34', {'floor_mm': [0, 4200, 7700, 10700, 14200, 17700, 20700, 23700], 'start_mm': 2990, 'um_per_pulse': 600, 'zone_mm': 50, 'events': [['magnet', 5], ['pulses', 5000]]}, [5, 6]), ('sampled regression 37', {'floor_mm': [0, 4200, 7200, 10700, 14200, 17700, 20700], 'start_mm': 20, 'um_per_pulse': 1000, 'zone_mm': 50, 'events': [['pulses', 2999], ['pulses', 1000], ['pulses', 100], ['magnet', 2]]}, [None, None, None, 2]), ('sampled regression 40', {'floor_mm': [0, 4200, 7700, 11900, 15400, 19600, 22600, 26800, 29800], 'start_mm': 20, 'um_per_pulse': 1000, 'zone_mm': 50, 'events': [['pulses', 3000], ['magnet', 0], ['magnet', 8], ['pulses', 5000], ['pulses', 3000], ['pulses', 5000], ['magnet', 4]]}, [None, 0, 8, None, None, None, 4])], [('regression: six-tenths of a millimetre short of the zone', {'floor_mm': [0, 3000], 'start_mm': 2924, 'um_per_pulse': 600, 'zone_mm': 75, 'events': [['pulses', 1], ['pulses', 1]]}, [None, 1]), ('sampled regression 28', {'floor_mm': [0, 4200, 7200, 10700, 14200, 17200, 20700, 24900, 28400], 'start_mm': 2990, 'um_per_pulse': 997, 'zone_mm': 75, 'events': [['magnet', 0], ['pulses', 4200], ['pulses', 3000], ['pulses', 3500]]}, [0, 1, 2, 3]), ('sampled regression 17', {'floor_mm': [0, 3500, 7700, 11200, 14700, 17700], 'start_mm': 20, 'um_per_pulse': 997, 'zone_mm': 50, 'events': [['pulses', 3500], ['pulses', 3000], ['pulses', 3499], ['pulses', 2999], ['magnet', 2], ['pulses', 4200]]}, [1, None, None, None, 2, None]), ('regression: zone edge', {'floor_mm': [0, 3000], 'start_mm': 0, 'um_per_pulse': 1000, 'zone_mm': 75, 'events': [['pulses', 2925], ['pulses', 1]]}, [1, 1]), ('regression: sub-millimetre pulses', {'floor_mm': [0, 3000], 'start_mm': 0, 'um_per_pulse': 997, 'zone_mm': 50, 'events': [['pulses', 999], ['pulses', 2]]}, [None, None]), ('sampled regression 45', {'floor_mm': [0, 3000, 7200, 11400, 15600, 19800, 22800, 26300], 'start_mm': 2990, 'um_per_pulse': 600, 'zone_mm': 75, 'events': [['magnet', 3], ['pulses', 3500], ['pulses', 3500]]}, [3, None, 4]), ('sampled regression 48', {'floor_mm': [0, 3000, 6000, 9000, 13200, 16200, 20400, 23400, 26400], 'start_mm': 0, 'um_per_pulse': 1003, 'zone_mm': 50, 'events': [['magnet', 0], ['pulses', 1000], ['magnet', 2]]}, [0, None, 2]), ('sampled regression 51', {'floor_mm': [0, 4200, 7200, 10700, 14900, 19100], 'start_mm': 2990, 'um_per_pulse': 1003, 'zone_mm': 50, 'events': [['magnet', 0], ['pulses', 100], ['pulses', 100]]}, [0, None, None])]]
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: encoder slip accumulates[1, 2][1, 2]Passed
regression: sub-millimetre pulses[None, None][None, None]Passed
regression: magnet correction[1, 1, 2][1, 1, 2]Passed
regression: zone edge[1, 1][1, 1]Passed
regression: six-tenths of a millimetre short of the zone[None, 1][None, 1]Passed
sampled regression 1[3, None, 4, None, None, None, 4][3, None, 4, None, None, None, 4]Passed
sampled regression 4[None, None][None, None]Passed
sampled regression 7[0, None, None, None, 2, 3][0, None, None, None, 2, 3]Passed

SHA-256 / eb92fd145de5576a745b669e0049afe8cf01928bf6bae79554a24f15dee3d617

Verification & scope

Stipulated toy lift-control contract for a bounded teaching model; it makes no claim of conformance to any lift code or vendor dispatcher and omits real safety cases. 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:47:56.495024+00:00.

Case digest / ad5978fcbb94a78af1ed2fcc296fc4f7368facbad841d864cf898f8dc612e3c3