FAILURE MAP
← Case archive

FA-95146 / Warehouse slotting and bin packing / Open access

Re-slot plan: smallest savings accepted first · case 01

The move budget is consumed by the least valuable moves.

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

ROOT CAUSE

Candidates are sorted with reverse order on negated benefit, putting small benefits first.

VERIFIED REPAIR

Sort by benefit descending with sku, from and to as tie-breaks.

Unsuccessful approach: Leaving candidates in input order makes the plan depend on feed order.

Case contract

cands [[sku, from_slot, to_slot, weekly_picks, travel_from, travel_to]]. Weekly benefit = picks*(travel_from - travel_to); keep candidates with benefit >= move_cost; rank by benefit desc, sku, from, to. Greedily accept up to max_moves: each SKU moves once, each target is used once, and a target that is the from_slot of any candidate is occupied unless that slot was already vacated by an accepted move. Return [[sku, to_slot, benefit]].

Why this case matters

Periodic re-slotting moves SKUs whose velocity changed toward better locations.

1 / The failure

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

N = 1
observations = []
def solve(cands, move_cost, max_moves):
    occupied = {c[1] for c in cands}
    ranked = []
    for sku, frm, to, picks, tf, tt in cands:
        benefit = picks * (tf - tt)
        if benefit >= move_cost:
            ranked.append((-benefit, sku, frm, to))
    ranked.sort(reverse=True)
    plan = []
    moved = set()
    targets = set()
    vacated = set()
    for nb, sku, frm, to in ranked:
        if len(plan) >= max_moves:
            break
        if sku in moved or to in targets:
            continue
        if to in occupied and to not in vacated:
            continue
        plan.append([sku, to, -nb])
        moved.add(sku)
        targets.add(to)
        vacated.add(frm)
    return plan
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['limit', [[['A', 'S1', 'S8', 10, 50, 10], ['B', 'S2', 'S9', 10, 40, 10]], 0, 1], [['A', 'S8', 400]]], ['generated mix 4', [[['K3', 'S4', 'S3', 10, 50, 10], ['K4', 'S4', 'S3', 20, 20, 20], ['K3', 'S4', 'S6', 40, 20, 20], ['K4', 'S7', 'S3', 20, 20, 20], ['K4', 'S1', 'S6', 20, 50, 20]], 0, 1], [['K4', 'S6', 600]]], ['threshold equal kept', [[['A', 'S1', 'S9', 10, 30, 20]], 100, 5], [['A', 'S9', 100]]], ['shared target', [[['A', 'S1', 'S9', 10, 50, 10], ['B', 'S2', 'S9', 10, 40, 10]], 0, 5], [['A', 'S9', 400]]], ['occupied target', [[['A', 'S1', 'S9', 10, 30, 10], ['B', 'S2', 'S1', 10, 40, 10]], 0, 5], [['A', 'S9', 200]]], ['negative benefit', [[['A', 'S1', 'S9', 10, 20, 30]], 0, 5], []], ['generated mix 7', [[['K1', 'S7', 'S4', 20, 10, 5], ['K4', 'S2', 'S4', 5, 20, 30], ['K4', 'S3', 'S4', 20, 30, 40], ['K1', 'S1', 'S7', 20, 20, 20]], 200, 2], []], ['generated mix 15', [[['K4', 'S4', 'S1', 10, 20, 20], ['K1', 'S2', 'S3', 10, 30, 5], ['K4', 'S4', 'S2', 20, 30, 20], ['K4', 'S1', 'S7', 40, 20, 20], ['K1', 'S3', 'S4', 5, 10, 30]], 200, 1], []]], [['generated mix 6', [[['K3', 'S1', 'S3', 20, 50, 10], ['K3', 'S4', 'S7', 40, 50, 40]], 400, 2], [['K3', 'S3', 800]]], ['generated mix 42', [[['K3', 'S7', 'S2', 10, 20, 40], ['K1', 'S6', 'S2', 10, 20, 20], ['K2', 'S5', 'S2', 20, 30, 20], ['K4', 'S7', 'S4', 40, 50, 30]], 200, 2], [['K4', 'S4', 800], ['K2', 'S2', 200]]], ['shared target', [[['A', 'S1', 'S9', 10, 50, 10], ['B', 'S2', 'S9', 10, 40, 10]], 0, 5], [['A', 'S9', 400]]], ['occupied target', [[['A', 'S1', 'S9', 10, 30, 10], ['B', 'S2', 'S1', 10, 40, 10]], 0, 5], [['A', 'S9', 200]]], ['threshold equal kept', [[['A', 'S1', 'S9', 10, 30, 20]], 100, 5], [['A', 'S9', 100]]], ['limit', [[['A', 'S1', 'S8', 10, 50, 10], ['B', 'S2', 'S9', 10, 40, 10]], 0, 1], [['A', 'S8', 400]]], ['generated mix 10', [[['K3', 'S4', 'S3', 40, 10, 5], ['K4', 'S7', 'S3', 40, 10, 20], ['K4', 'S2', 'S7', 5, 30, 5], ['K3', 'S2', 'S5', 40, 10, 40], ['K3', 'S2', 'S7', 10, 50, 20]], 400, 3], []], ['generated mix 18', [[['K1', 'S4', 'S3', 5, 50, 30], ['K3', 'S7', 'S3', 10, 20, 5]], 400, 2], []]], [['generated mix 38', [[['K4', 'S1', 'S2', 5, 30, 30], ['K4', 'S3', 'S7', 5, 10, 5], ['K3', 'S3', 'S2', 5, 30, 20], ['K2', 'S7', 'S3', 5, 10, 5], ['K1', 'S6', 'S5', 10, 50, 20], ['K4', 'S7', 'S6', 10, 30, 20]], 0, 3], [['K1', 'S5', 300], ['K4', 'S6', 100], ['K3', 'S2', 50]]], ['generated mix 80', [[['K1', 'S4', 'S6', 20, 50, 10], ['K1', 'S5', 'S1', 40, 50, 10]], 100, 2], [['K1', 'S1', 1600]]], ['sku once', [[['A', 'S1', 'S8', 10, 50, 10], ['A', 'S1', 'S9', 10, 50, 20]], 0, 5], [['A', 'S8', 400]]], ['negative benefit', [[['A', 'S1', 'S9', 10, 20, 30]], 0, 5], []], ['shared target', [[['A', 'S1', 'S9', 10, 50, 10], ['B', 'S2', 'S9', 10, 40, 10]], 0, 5], [['A', 'S9', 400]]], ['occupied target', [[['A', 'S1', 'S9', 10, 30, 10], ['B', 'S2', 'S1', 10, 40, 10]], 0, 5], [['A', 'S9', 200]]], ['generated mix 20', [[['K1', 'S3', 'S7', 5, 50, 40], ['K3', 'S4', 'S5', 20, 10, 10], ['K2', 'S6', 'S5', 5, 30, 30], ['K3', 'S2', 'S5', 40, 50, 20], ['K4', 'S5', 'S7', 10, 10, 30], ['K2', 'S5', 'S4', 40, 30, 5]], 0, 1], [['K1', 'S7', 50]]], ['generated mix 28', [[['K3', 'S4', 'S2', 10, 50, 30], ['K2', 'S1', 'S3', 10, 50, 30], ['K4', 'S1', 'S2', 20, 50, 5]], 400, 2], [['K4', 'S2', 900]]]], [['generated mix 80', [[['K1', 'S4', 'S6', 20, 50, 10], ['K1', 'S5', 'S1', 40, 50, 10]], 100, 2], [['K1', 'S1', 1600]]], ['generated mix 30', [[['K2', 'S4', 'S5', 5, 30, 5], ['K4', 'S3', 'S1', 40, 50, 20], ['K2', 'S6', 'S1', 5, 20, 40]], 0, 1], [['K4', 'S1', 1200]]], ['limit', [[['A', 'S1', 'S8', 10, 50, 10], ['B', 'S2', 'S9', 10, 40, 10]], 0, 1], [['A', 'S8', 400]]], ['chain into vacated', [[['A', 'S1', 'S9', 10, 50, 10], ['B', 'S2', 'S1', 10, 40, 10]], 0, 5], [['A', 'S9', 400], ['B', 'S1', 300]]], ['sku once', [[['A', 'S1', 'S8', 10, 50, 10], ['A', 'S1', 'S9', 10, 50, 20]], 0, 5], [['A', 'S8', 400]]], ['negative benefit', [[['A', 'S1', 'S9', 10, 20, 30]], 0, 5], []], ['generated mix 32', [[['K2', 'S5', 'S1', 10, 30, 5], ['K2', 'S1', 'S3', 5, 10, 40], ['K3', 'S5', 'S4', 20, 10, 10], ['K4', 'S3', 'S5', 10, 50, 40], ['K2', 'S4', 'S6', 40, 10, 40]], 0, 3], []], ['generated mix 40', [[['K3', 'S5', 'S2', 40, 10, 10]], 200, 3], []]], [['generated mix 4', [[['K3', 'S4', 'S3', 10, 50, 10], ['K4', 'S4', 'S3', 20, 20, 20], ['K3', 'S4', 'S6', 40, 20, 20], ['K4', 'S7', 'S3', 20, 20, 20], ['K4', 'S1', 'S6', 20, 50, 20]], 0, 1], [['K4', 'S6', 600]]], ['generated mix 62', [[['K4', 'S4', 'S5', 10, 50, 5], ['K1', 'S3', 'S4', 40, 10, 20], ['K1', 'S5', 'S2', 20, 50, 30], ['K1', 'S7', 'S6', 10, 50, 20], ['K4', 'S3', 'S5', 40, 30, 40], ['K3', 'S4', 'S6', 20, 50, 10]], 200, 1], [['K3', 'S6', 800]]], ['occupied target', [[['A', 'S1', 'S9', 10, 30, 10], ['B', 'S2', 'S1', 10, 40, 10]], 0, 5], [['A', 'S9', 200]]], ['threshold equal kept', [[['A', 'S1', 'S9', 10, 30, 20]], 100, 5], [['A', 'S9', 100]]], ['limit', [[['A', 'S1', 'S8', 10, 50, 10], ['B', 'S2', 'S9', 10, 40, 10]], 0, 1], [['A', 'S8', 400]]], ['chain into vacated', [[['A', 'S1', 'S9', 10, 50, 10], ['B', 'S2', 'S1', 10, 40, 10]], 0, 5], [['A', 'S9', 400], ['B', 'S1', 300]]], ['generated mix 43', [[['K2', 'S6', 'S5', 10, 20, 30]], 200, 2], []], ['generated mix 51', [[['K4', 'S4', 'S5', 10, 50, 5], ['K3', 'S4', 'S7', 10, 50, 40], ['K3', 'S5', 'S3', 10, 50, 40], ['K1', 'S6', 'S1', 40, 20, 30]], 200, 1], []]]]
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
limit[['B', 'S9', 300]][['A', 'S8', 400]]Failed
generated mix 4[['K4', 'S3', 0]][['K4', 'S6', 600]]Failed
threshold equal kept[['A', 'S9', 100]][['A', 'S9', 100]]Passed
shared target[['B', 'S9', 300]][['A', 'S9', 400]]Failed
occupied target[['A', 'S9', 200], ['B', 'S1', 300]][['A', 'S9', 200]]Failed
negative benefit[][]Passed
generated mix 7[][]Passed
generated mix 15[][]Passed

SHA-256 / 7f49921024715d1105433dc4026f0c65a45b81cd2dc105f00f417767e5301abe

2 / The unsuccessful fix

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

N = 1
observations = []
def solve(cands, move_cost, max_moves):
    occupied = {c[1] for c in cands}
    ranked = []
    for sku, frm, to, picks, tf, tt in cands:
        benefit = picks * (tf - tt)
        if benefit >= move_cost:
            ranked.append((-benefit, sku, frm, to))
    plan = []
    moved = set()
    targets = set()
    vacated = set()
    for nb, sku, frm, to in ranked:
        if len(plan) >= max_moves:
            break
        if sku in moved or to in targets:
            continue
        if to in occupied and to not in vacated:
            continue
        plan.append([sku, to, -nb])
        moved.add(sku)
        targets.add(to)
        vacated.add(frm)
    return plan
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['limit', [[['A', 'S1', 'S8', 10, 50, 10], ['B', 'S2', 'S9', 10, 40, 10]], 0, 1], [['A', 'S8', 400]]], ['generated mix 4', [[['K3', 'S4', 'S3', 10, 50, 10], ['K4', 'S4', 'S3', 20, 20, 20], ['K3', 'S4', 'S6', 40, 20, 20], ['K4', 'S7', 'S3', 20, 20, 20], ['K4', 'S1', 'S6', 20, 50, 20]], 0, 1], [['K4', 'S6', 600]]], ['threshold equal kept', [[['A', 'S1', 'S9', 10, 30, 20]], 100, 5], [['A', 'S9', 100]]], ['shared target', [[['A', 'S1', 'S9', 10, 50, 10], ['B', 'S2', 'S9', 10, 40, 10]], 0, 5], [['A', 'S9', 400]]], ['occupied target', [[['A', 'S1', 'S9', 10, 30, 10], ['B', 'S2', 'S1', 10, 40, 10]], 0, 5], [['A', 'S9', 200]]], ['negative benefit', [[['A', 'S1', 'S9', 10, 20, 30]], 0, 5], []], ['generated mix 7', [[['K1', 'S7', 'S4', 20, 10, 5], ['K4', 'S2', 'S4', 5, 20, 30], ['K4', 'S3', 'S4', 20, 30, 40], ['K1', 'S1', 'S7', 20, 20, 20]], 200, 2], []], ['generated mix 15', [[['K4', 'S4', 'S1', 10, 20, 20], ['K1', 'S2', 'S3', 10, 30, 5], ['K4', 'S4', 'S2', 20, 30, 20], ['K4', 'S1', 'S7', 40, 20, 20], ['K1', 'S3', 'S4', 5, 10, 30]], 200, 1], []]], [['generated mix 6', [[['K3', 'S1', 'S3', 20, 50, 10], ['K3', 'S4', 'S7', 40, 50, 40]], 400, 2], [['K3', 'S3', 800]]], ['generated mix 42', [[['K3', 'S7', 'S2', 10, 20, 40], ['K1', 'S6', 'S2', 10, 20, 20], ['K2', 'S5', 'S2', 20, 30, 20], ['K4', 'S7', 'S4', 40, 50, 30]], 200, 2], [['K4', 'S4', 800], ['K2', 'S2', 200]]], ['shared target', [[['A', 'S1', 'S9', 10, 50, 10], ['B', 'S2', 'S9', 10, 40, 10]], 0, 5], [['A', 'S9', 400]]], ['occupied target', [[['A', 'S1', 'S9', 10, 30, 10], ['B', 'S2', 'S1', 10, 40, 10]], 0, 5], [['A', 'S9', 200]]], ['threshold equal kept', [[['A', 'S1', 'S9', 10, 30, 20]], 100, 5], [['A', 'S9', 100]]], ['limit', [[['A', 'S1', 'S8', 10, 50, 10], ['B', 'S2', 'S9', 10, 40, 10]], 0, 1], [['A', 'S8', 400]]], ['generated mix 10', [[['K3', 'S4', 'S3', 40, 10, 5], ['K4', 'S7', 'S3', 40, 10, 20], ['K4', 'S2', 'S7', 5, 30, 5], ['K3', 'S2', 'S5', 40, 10, 40], ['K3', 'S2', 'S7', 10, 50, 20]], 400, 3], []], ['generated mix 18', [[['K1', 'S4', 'S3', 5, 50, 30], ['K3', 'S7', 'S3', 10, 20, 5]], 400, 2], []]], [['generated mix 38', [[['K4', 'S1', 'S2', 5, 30, 30], ['K4', 'S3', 'S7', 5, 10, 5], ['K3', 'S3', 'S2', 5, 30, 20], ['K2', 'S7', 'S3', 5, 10, 5], ['K1', 'S6', 'S5', 10, 50, 20], ['K4', 'S7', 'S6', 10, 30, 20]], 0, 3], [['K1', 'S5', 300], ['K4', 'S6', 100], ['K3', 'S2', 50]]], ['generated mix 80', [[['K1', 'S4', 'S6', 20, 50, 10], ['K1', 'S5', 'S1', 40, 50, 10]], 100, 2], [['K1', 'S1', 1600]]], ['sku once', [[['A', 'S1', 'S8', 10, 50, 10], ['A', 'S1', 'S9', 10, 50, 20]], 0, 5], [['A', 'S8', 400]]], ['negative benefit', [[['A', 'S1', 'S9', 10, 20, 30]], 0, 5], []], ['shared target', [[['A', 'S1', 'S9', 10, 50, 10], ['B', 'S2', 'S9', 10, 40, 10]], 0, 5], [['A', 'S9', 400]]], ['occupied target', [[['A', 'S1', 'S9', 10, 30, 10], ['B', 'S2', 'S1', 10, 40, 10]], 0, 5], [['A', 'S9', 200]]], ['generated mix 20', [[['K1', 'S3', 'S7', 5, 50, 40], ['K3', 'S4', 'S5', 20, 10, 10], ['K2', 'S6', 'S5', 5, 30, 30], ['K3', 'S2', 'S5', 40, 50, 20], ['K4', 'S5', 'S7', 10, 10, 30], ['K2', 'S5', 'S4', 40, 30, 5]], 0, 1], [['K1', 'S7', 50]]], ['generated mix 28', [[['K3', 'S4', 'S2', 10, 50, 30], ['K2', 'S1', 'S3', 10, 50, 30], ['K4', 'S1', 'S2', 20, 50, 5]], 400, 2], [['K4', 'S2', 900]]]], [['generated mix 80', [[['K1', 'S4', 'S6', 20, 50, 10], ['K1', 'S5', 'S1', 40, 50, 10]], 100, 2], [['K1', 'S1', 1600]]], ['generated mix 30', [[['K2', 'S4', 'S5', 5, 30, 5], ['K4', 'S3', 'S1', 40, 50, 20], ['K2', 'S6', 'S1', 5, 20, 40]], 0, 1], [['K4', 'S1', 1200]]], ['limit', [[['A', 'S1', 'S8', 10, 50, 10], ['B', 'S2', 'S9', 10, 40, 10]], 0, 1], [['A', 'S8', 400]]], ['chain into vacated', [[['A', 'S1', 'S9', 10, 50, 10], ['B', 'S2', 'S1', 10, 40, 10]], 0, 5], [['A', 'S9', 400], ['B', 'S1', 300]]], ['sku once', [[['A', 'S1', 'S8', 10, 50, 10], ['A', 'S1', 'S9', 10, 50, 20]], 0, 5], [['A', 'S8', 400]]], ['negative benefit', [[['A', 'S1', 'S9', 10, 20, 30]], 0, 5], []], ['generated mix 32', [[['K2', 'S5', 'S1', 10, 30, 5], ['K2', 'S1', 'S3', 5, 10, 40], ['K3', 'S5', 'S4', 20, 10, 10], ['K4', 'S3', 'S5', 10, 50, 40], ['K2', 'S4', 'S6', 40, 10, 40]], 0, 3], []], ['generated mix 40', [[['K3', 'S5', 'S2', 40, 10, 10]], 200, 3], []]], [['generated mix 4', [[['K3', 'S4', 'S3', 10, 50, 10], ['K4', 'S4', 'S3', 20, 20, 20], ['K3', 'S4', 'S6', 40, 20, 20], ['K4', 'S7', 'S3', 20, 20, 20], ['K4', 'S1', 'S6', 20, 50, 20]], 0, 1], [['K4', 'S6', 600]]], ['generated mix 62', [[['K4', 'S4', 'S5', 10, 50, 5], ['K1', 'S3', 'S4', 40, 10, 20], ['K1', 'S5', 'S2', 20, 50, 30], ['K1', 'S7', 'S6', 10, 50, 20], ['K4', 'S3', 'S5', 40, 30, 40], ['K3', 'S4', 'S6', 20, 50, 10]], 200, 1], [['K3', 'S6', 800]]], ['occupied target', [[['A', 'S1', 'S9', 10, 30, 10], ['B', 'S2', 'S1', 10, 40, 10]], 0, 5], [['A', 'S9', 200]]], ['threshold equal kept', [[['A', 'S1', 'S9', 10, 30, 20]], 100, 5], [['A', 'S9', 100]]], ['limit', [[['A', 'S1', 'S8', 10, 50, 10], ['B', 'S2', 'S9', 10, 40, 10]], 0, 1], [['A', 'S8', 400]]], ['chain into vacated', [[['A', 'S1', 'S9', 10, 50, 10], ['B', 'S2', 'S1', 10, 40, 10]], 0, 5], [['A', 'S9', 400], ['B', 'S1', 300]]], ['generated mix 43', [[['K2', 'S6', 'S5', 10, 20, 30]], 200, 2], []], ['generated mix 51', [[['K4', 'S4', 'S5', 10, 50, 5], ['K3', 'S4', 'S7', 10, 50, 40], ['K3', 'S5', 'S3', 10, 50, 40], ['K1', 'S6', 'S1', 40, 20, 30]], 200, 1], []]]]
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
limit[['A', 'S8', 400]][['A', 'S8', 400]]Passed
generated mix 4[['K3', 'S3', 400]][['K4', 'S6', 600]]Failed
threshold equal kept[['A', 'S9', 100]][['A', 'S9', 100]]Passed
shared target[['A', 'S9', 400]][['A', 'S9', 400]]Passed
occupied target[['A', 'S9', 200], ['B', 'S1', 300]][['A', 'S9', 200]]Failed
negative benefit[][]Passed
generated mix 7[][]Passed
generated mix 15[][]Passed

SHA-256 / b7ffa94c17daf89e27a275feaf7369e472fba5ea0aa5dced5b344df8cf46ef46

3 / The verified repair

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

N = 1
observations = []
def solve(cands, move_cost, max_moves):
    occupied = {c[1] for c in cands}
    ranked = []
    for sku, frm, to, picks, tf, tt in cands:
        benefit = picks * (tf - tt)
        if benefit >= move_cost:
            ranked.append((-benefit, sku, frm, to))
    ranked.sort()
    plan = []
    moved = set()
    targets = set()
    vacated = set()
    for nb, sku, frm, to in ranked:
        if len(plan) >= max_moves:
            break
        if sku in moved or to in targets:
            continue
        if to in occupied and to not in vacated:
            continue
        plan.append([sku, to, -nb])
        moved.add(sku)
        targets.add(to)
        vacated.add(frm)
    return plan
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['limit', [[['A', 'S1', 'S8', 10, 50, 10], ['B', 'S2', 'S9', 10, 40, 10]], 0, 1], [['A', 'S8', 400]]], ['generated mix 4', [[['K3', 'S4', 'S3', 10, 50, 10], ['K4', 'S4', 'S3', 20, 20, 20], ['K3', 'S4', 'S6', 40, 20, 20], ['K4', 'S7', 'S3', 20, 20, 20], ['K4', 'S1', 'S6', 20, 50, 20]], 0, 1], [['K4', 'S6', 600]]], ['threshold equal kept', [[['A', 'S1', 'S9', 10, 30, 20]], 100, 5], [['A', 'S9', 100]]], ['shared target', [[['A', 'S1', 'S9', 10, 50, 10], ['B', 'S2', 'S9', 10, 40, 10]], 0, 5], [['A', 'S9', 400]]], ['occupied target', [[['A', 'S1', 'S9', 10, 30, 10], ['B', 'S2', 'S1', 10, 40, 10]], 0, 5], [['A', 'S9', 200]]], ['negative benefit', [[['A', 'S1', 'S9', 10, 20, 30]], 0, 5], []], ['generated mix 7', [[['K1', 'S7', 'S4', 20, 10, 5], ['K4', 'S2', 'S4', 5, 20, 30], ['K4', 'S3', 'S4', 20, 30, 40], ['K1', 'S1', 'S7', 20, 20, 20]], 200, 2], []], ['generated mix 15', [[['K4', 'S4', 'S1', 10, 20, 20], ['K1', 'S2', 'S3', 10, 30, 5], ['K4', 'S4', 'S2', 20, 30, 20], ['K4', 'S1', 'S7', 40, 20, 20], ['K1', 'S3', 'S4', 5, 10, 30]], 200, 1], []]], [['generated mix 6', [[['K3', 'S1', 'S3', 20, 50, 10], ['K3', 'S4', 'S7', 40, 50, 40]], 400, 2], [['K3', 'S3', 800]]], ['generated mix 42', [[['K3', 'S7', 'S2', 10, 20, 40], ['K1', 'S6', 'S2', 10, 20, 20], ['K2', 'S5', 'S2', 20, 30, 20], ['K4', 'S7', 'S4', 40, 50, 30]], 200, 2], [['K4', 'S4', 800], ['K2', 'S2', 200]]], ['shared target', [[['A', 'S1', 'S9', 10, 50, 10], ['B', 'S2', 'S9', 10, 40, 10]], 0, 5], [['A', 'S9', 400]]], ['occupied target', [[['A', 'S1', 'S9', 10, 30, 10], ['B', 'S2', 'S1', 10, 40, 10]], 0, 5], [['A', 'S9', 200]]], ['threshold equal kept', [[['A', 'S1', 'S9', 10, 30, 20]], 100, 5], [['A', 'S9', 100]]], ['limit', [[['A', 'S1', 'S8', 10, 50, 10], ['B', 'S2', 'S9', 10, 40, 10]], 0, 1], [['A', 'S8', 400]]], ['generated mix 10', [[['K3', 'S4', 'S3', 40, 10, 5], ['K4', 'S7', 'S3', 40, 10, 20], ['K4', 'S2', 'S7', 5, 30, 5], ['K3', 'S2', 'S5', 40, 10, 40], ['K3', 'S2', 'S7', 10, 50, 20]], 400, 3], []], ['generated mix 18', [[['K1', 'S4', 'S3', 5, 50, 30], ['K3', 'S7', 'S3', 10, 20, 5]], 400, 2], []]], [['generated mix 38', [[['K4', 'S1', 'S2', 5, 30, 30], ['K4', 'S3', 'S7', 5, 10, 5], ['K3', 'S3', 'S2', 5, 30, 20], ['K2', 'S7', 'S3', 5, 10, 5], ['K1', 'S6', 'S5', 10, 50, 20], ['K4', 'S7', 'S6', 10, 30, 20]], 0, 3], [['K1', 'S5', 300], ['K4', 'S6', 100], ['K3', 'S2', 50]]], ['generated mix 80', [[['K1', 'S4', 'S6', 20, 50, 10], ['K1', 'S5', 'S1', 40, 50, 10]], 100, 2], [['K1', 'S1', 1600]]], ['sku once', [[['A', 'S1', 'S8', 10, 50, 10], ['A', 'S1', 'S9', 10, 50, 20]], 0, 5], [['A', 'S8', 400]]], ['negative benefit', [[['A', 'S1', 'S9', 10, 20, 30]], 0, 5], []], ['shared target', [[['A', 'S1', 'S9', 10, 50, 10], ['B', 'S2', 'S9', 10, 40, 10]], 0, 5], [['A', 'S9', 400]]], ['occupied target', [[['A', 'S1', 'S9', 10, 30, 10], ['B', 'S2', 'S1', 10, 40, 10]], 0, 5], [['A', 'S9', 200]]], ['generated mix 20', [[['K1', 'S3', 'S7', 5, 50, 40], ['K3', 'S4', 'S5', 20, 10, 10], ['K2', 'S6', 'S5', 5, 30, 30], ['K3', 'S2', 'S5', 40, 50, 20], ['K4', 'S5', 'S7', 10, 10, 30], ['K2', 'S5', 'S4', 40, 30, 5]], 0, 1], [['K1', 'S7', 50]]], ['generated mix 28', [[['K3', 'S4', 'S2', 10, 50, 30], ['K2', 'S1', 'S3', 10, 50, 30], ['K4', 'S1', 'S2', 20, 50, 5]], 400, 2], [['K4', 'S2', 900]]]], [['generated mix 80', [[['K1', 'S4', 'S6', 20, 50, 10], ['K1', 'S5', 'S1', 40, 50, 10]], 100, 2], [['K1', 'S1', 1600]]], ['generated mix 30', [[['K2', 'S4', 'S5', 5, 30, 5], ['K4', 'S3', 'S1', 40, 50, 20], ['K2', 'S6', 'S1', 5, 20, 40]], 0, 1], [['K4', 'S1', 1200]]], ['limit', [[['A', 'S1', 'S8', 10, 50, 10], ['B', 'S2', 'S9', 10, 40, 10]], 0, 1], [['A', 'S8', 400]]], ['chain into vacated', [[['A', 'S1', 'S9', 10, 50, 10], ['B', 'S2', 'S1', 10, 40, 10]], 0, 5], [['A', 'S9', 400], ['B', 'S1', 300]]], ['sku once', [[['A', 'S1', 'S8', 10, 50, 10], ['A', 'S1', 'S9', 10, 50, 20]], 0, 5], [['A', 'S8', 400]]], ['negative benefit', [[['A', 'S1', 'S9', 10, 20, 30]], 0, 5], []], ['generated mix 32', [[['K2', 'S5', 'S1', 10, 30, 5], ['K2', 'S1', 'S3', 5, 10, 40], ['K3', 'S5', 'S4', 20, 10, 10], ['K4', 'S3', 'S5', 10, 50, 40], ['K2', 'S4', 'S6', 40, 10, 40]], 0, 3], []], ['generated mix 40', [[['K3', 'S5', 'S2', 40, 10, 10]], 200, 3], []]], [['generated mix 4', [[['K3', 'S4', 'S3', 10, 50, 10], ['K4', 'S4', 'S3', 20, 20, 20], ['K3', 'S4', 'S6', 40, 20, 20], ['K4', 'S7', 'S3', 20, 20, 20], ['K4', 'S1', 'S6', 20, 50, 20]], 0, 1], [['K4', 'S6', 600]]], ['generated mix 62', [[['K4', 'S4', 'S5', 10, 50, 5], ['K1', 'S3', 'S4', 40, 10, 20], ['K1', 'S5', 'S2', 20, 50, 30], ['K1', 'S7', 'S6', 10, 50, 20], ['K4', 'S3', 'S5', 40, 30, 40], ['K3', 'S4', 'S6', 20, 50, 10]], 200, 1], [['K3', 'S6', 800]]], ['occupied target', [[['A', 'S1', 'S9', 10, 30, 10], ['B', 'S2', 'S1', 10, 40, 10]], 0, 5], [['A', 'S9', 200]]], ['threshold equal kept', [[['A', 'S1', 'S9', 10, 30, 20]], 100, 5], [['A', 'S9', 100]]], ['limit', [[['A', 'S1', 'S8', 10, 50, 10], ['B', 'S2', 'S9', 10, 40, 10]], 0, 1], [['A', 'S8', 400]]], ['chain into vacated', [[['A', 'S1', 'S9', 10, 50, 10], ['B', 'S2', 'S1', 10, 40, 10]], 0, 5], [['A', 'S9', 400], ['B', 'S1', 300]]], ['generated mix 43', [[['K2', 'S6', 'S5', 10, 20, 30]], 200, 2], []], ['generated mix 51', [[['K4', 'S4', 'S5', 10, 50, 5], ['K3', 'S4', 'S7', 10, 50, 40], ['K3', 'S5', 'S3', 10, 50, 40], ['K1', 'S6', 'S1', 40, 20, 30]], 200, 1], []]]]
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
limit[['A', 'S8', 400]][['A', 'S8', 400]]Passed
generated mix 4[['K4', 'S6', 600]][['K4', 'S6', 600]]Passed
threshold equal kept[['A', 'S9', 100]][['A', 'S9', 100]]Passed
shared target[['A', 'S9', 400]][['A', 'S9', 400]]Passed
occupied target[['A', 'S9', 200]][['A', 'S9', 200]]Passed
negative benefit[][]Passed
generated mix 7[][]Passed
generated mix 15[][]Passed

SHA-256 / f57d610ed928ecd0b46dbae62b9d89d1b02cb1dc7c4fe689707dd00b5e30e83d

Verification & scope

Greedy stipulated planner; no swap sequencing or labour scheduling. 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:11.076220+00:00.

Case digest / e6122790bf9bdccb0d87082b3bd6cb53416d61e298dc056b4017abef3b8d2dbd