FAILURE MAP
← Case archive

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

Re-slot plan: move into a still-occupied slot · case 01

A SKU is moved into a slot whose resident SKU is not being moved out.

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

ROOT CAUSE

The plan ignores that a target slot may still hold another candidate SKU.

THE FAILURE

The plan ignores that a target slot may still hold another candidate SKU.

Unsuccessful approach: Treating every occupied slot as unavailable forbids legitimate chained moves into vacated slots.

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()
    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
        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 = [[['occupied target', [[['A', 'S1', 'S9', 10, 30, 10], ['B', 'S2', 'S1', 10, 40, 10]], 0, 5], [['A', 'S9', 200]]], ['generated mix 9', [[['K1', 'S6', 'S1', 20, 20, 20], ['K3', 'S5', 'S6', 40, 20, 20]], 0, 3], [['K1', 'S1', 0], ['K3', 'S6', 0]]], ['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]]], ['negative benefit', [[['A', 'S1', 'S9', 10, 20, 30]], 0, 5], []], ['generated mix 6', [[['K3', 'S1', 'S3', 20, 50, 10], ['K3', 'S4', 'S7', 40, 50, 40]], 400, 2], [['K3', 'S3', 800]]], ['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 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 9', [[['K1', 'S6', 'S1', 20, 20, 20], ['K3', 'S5', 'S6', 40, 20, 20]], 0, 3], [['K1', 'S1', 0], ['K3', 'S6', 0]]], ['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 49', [[['K1', 'S2', 'S1', 5, 50, 10], ['K3', 'S1', 'S7', 5, 10, 10]], 200, 2], []], ['generated mix 9', [[['K1', 'S6', 'S1', 20, 20, 20], ['K3', 'S5', 'S6', 40, 20, 20]], 0, 3], [['K1', 'S1', 0], ['K3', 'S6', 0]]], ['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 21', [[['K2', 'S6', 'S5', 5, 20, 10], ['K1', 'S3', 'S4', 40, 30, 20], ['K2', 'S4', 'S7', 40, 30, 20], ['K3', 'S1', 'S5', 10, 20, 10], ['K3', 'S5', 'S3', 40, 10, 5]], 200, 1], [['K2', 'S7', 400]]], ['generated mix 29', [[['K4', 'S6', 'S5', 40, 50, 20], ['K3', 'S6', 'S3', 20, 50, 40], ['K4', 'S6', 'S2', 20, 10, 40]], 200, 1], [['K4', 'S5', 1200]]]], [['generated mix 63', [[['K2', 'S7', 'S1', 20, 30, 40], ['K4', 'S2', 'S7', 40, 20, 5], ['K1', 'S4', 'S3', 10, 30, 5], ['K4', 'S2', 'S4', 20, 50, 40], ['K4', 'S6', 'S3', 5, 30, 30], ['K1', 'S3', 'S2', 5, 30, 20]], 200, 2], []], ['generated mix 9', [[['K1', 'S6', 'S1', 20, 20, 20], ['K3', 'S5', 'S6', 40, 20, 20]], 0, 3], [['K1', 'S1', 0], ['K3', 'S6', 0]]], ['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 3', [[['K1', 'S6', 'S3', 10, 30, 10], ['K1', 'S2', 'S5', 10, 50, 20], ['K2', 'S3', 'S4', 5, 30, 40], ['K4', 'S6', 'S4', 40, 20, 5], ['K1', 'S3', 'S6', 40, 50, 10], ['K3', 'S4', 'S7', 5, 20, 5]], 50, 3], [['K1', 'S5', 300], ['K3', 'S7', 75]]], ['generated mix 9', [[['K1', 'S6', 'S1', 20, 20, 20], ['K3', 'S5', 'S6', 40, 20, 20]], 0, 3], [['K1', 'S1', 0], ['K3', 'S6', 0]]], ['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 44', [[['K3', 'S5', 'S2', 40, 20, 30], ['K3', 'S6', 'S2', 5, 50, 5], ['K3', 'S2', 'S3', 10, 20, 20], ['K4', 'S3', 'S1', 20, 50, 20], ['K4', 'S7', 'S1', 10, 30, 5]], 0, 2], [['K4', 'S1', 600], ['K3', 'S3', 0]]], ['generated mix 52', [[['K1', 'S1', 'S2', 20, 10, 10], ['K1', 'S2', 'S5', 5, 10, 5]], 100, 2], []]]]
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
occupied target[['B', 'S1', 300], ['A', 'S9', 200]][['A', 'S9', 200]]Failed
generated mix 9[['K1', 'S1', 0], ['K3', 'S6', 0]][['K1', 'S1', 0], ['K3', 'S6', 0]]Passed
threshold equal kept[['A', 'S9', 100]][['A', 'S9', 100]]Passed
limit[['A', 'S8', 400]][['A', 'S8', 400]]Passed
chain into vacated[['A', 'S9', 400], ['B', 'S1', 300]][['A', 'S9', 400], ['B', 'S1', 300]]Passed
negative benefit[][]Passed
generated mix 6[['K3', 'S3', 800]][['K3', 'S3', 800]]Passed
generated mix 15[['K1', 'S3', 250]][]Failed

SHA-256 / 3bd24ef66a906aa0721913cfaccd4ab301df8f01637fc9d1ebd922751e3bf29b

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))
    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:
            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 = [[['occupied target', [[['A', 'S1', 'S9', 10, 30, 10], ['B', 'S2', 'S1', 10, 40, 10]], 0, 5], [['A', 'S9', 200]]], ['generated mix 9', [[['K1', 'S6', 'S1', 20, 20, 20], ['K3', 'S5', 'S6', 40, 20, 20]], 0, 3], [['K1', 'S1', 0], ['K3', 'S6', 0]]], ['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]]], ['negative benefit', [[['A', 'S1', 'S9', 10, 20, 30]], 0, 5], []], ['generated mix 6', [[['K3', 'S1', 'S3', 20, 50, 10], ['K3', 'S4', 'S7', 40, 50, 40]], 400, 2], [['K3', 'S3', 800]]], ['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 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 9', [[['K1', 'S6', 'S1', 20, 20, 20], ['K3', 'S5', 'S6', 40, 20, 20]], 0, 3], [['K1', 'S1', 0], ['K3', 'S6', 0]]], ['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 49', [[['K1', 'S2', 'S1', 5, 50, 10], ['K3', 'S1', 'S7', 5, 10, 10]], 200, 2], []], ['generated mix 9', [[['K1', 'S6', 'S1', 20, 20, 20], ['K3', 'S5', 'S6', 40, 20, 20]], 0, 3], [['K1', 'S1', 0], ['K3', 'S6', 0]]], ['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 21', [[['K2', 'S6', 'S5', 5, 20, 10], ['K1', 'S3', 'S4', 40, 30, 20], ['K2', 'S4', 'S7', 40, 30, 20], ['K3', 'S1', 'S5', 10, 20, 10], ['K3', 'S5', 'S3', 40, 10, 5]], 200, 1], [['K2', 'S7', 400]]], ['generated mix 29', [[['K4', 'S6', 'S5', 40, 50, 20], ['K3', 'S6', 'S3', 20, 50, 40], ['K4', 'S6', 'S2', 20, 10, 40]], 200, 1], [['K4', 'S5', 1200]]]], [['generated mix 63', [[['K2', 'S7', 'S1', 20, 30, 40], ['K4', 'S2', 'S7', 40, 20, 5], ['K1', 'S4', 'S3', 10, 30, 5], ['K4', 'S2', 'S4', 20, 50, 40], ['K4', 'S6', 'S3', 5, 30, 30], ['K1', 'S3', 'S2', 5, 30, 20]], 200, 2], []], ['generated mix 9', [[['K1', 'S6', 'S1', 20, 20, 20], ['K3', 'S5', 'S6', 40, 20, 20]], 0, 3], [['K1', 'S1', 0], ['K3', 'S6', 0]]], ['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 3', [[['K1', 'S6', 'S3', 10, 30, 10], ['K1', 'S2', 'S5', 10, 50, 20], ['K2', 'S3', 'S4', 5, 30, 40], ['K4', 'S6', 'S4', 40, 20, 5], ['K1', 'S3', 'S6', 40, 50, 10], ['K3', 'S4', 'S7', 5, 20, 5]], 50, 3], [['K1', 'S5', 300], ['K3', 'S7', 75]]], ['generated mix 9', [[['K1', 'S6', 'S1', 20, 20, 20], ['K3', 'S5', 'S6', 40, 20, 20]], 0, 3], [['K1', 'S1', 0], ['K3', 'S6', 0]]], ['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 44', [[['K3', 'S5', 'S2', 40, 20, 30], ['K3', 'S6', 'S2', 5, 50, 5], ['K3', 'S2', 'S3', 10, 20, 20], ['K4', 'S3', 'S1', 20, 50, 20], ['K4', 'S7', 'S1', 10, 30, 5]], 0, 2], [['K4', 'S1', 600], ['K3', 'S3', 0]]], ['generated mix 52', [[['K1', 'S1', 'S2', 20, 10, 10], ['K1', 'S2', 'S5', 5, 10, 5]], 100, 2], []]]]
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
occupied target[['A', 'S9', 200]][['A', 'S9', 200]]Passed
generated mix 9[['K1', 'S1', 0]][['K1', 'S1', 0], ['K3', 'S6', 0]]Failed
threshold equal kept[['A', 'S9', 100]][['A', 'S9', 100]]Passed
limit[['A', 'S8', 400]][['A', 'S8', 400]]Passed
chain into vacated[['A', 'S9', 400]][['A', 'S9', 400], ['B', 'S1', 300]]Failed
negative benefit[][]Passed
generated mix 6[['K3', 'S3', 800]][['K3', 'S3', 800]]Passed
generated mix 15[][]Passed

SHA-256 / 920f7135d718345cd90c22a2be3c550cd9d130de1c4d90f90360bb9f693ba967

HELD IN THE MEMBER ARCHIVE

The verified repair and its recorded checks are member-only.

This mechanism has 8 recorded checks per implementation. The open-access tier publishes the failure and the unsuccessful fix; the repaired source that passes every check, and the observations that prove it, are available to members.

Every case sharing this mechanism uses the same contract and the same repair, so this one record is held back for all of them.

Member access is invitation-based. Sign in with your invited account to inspect the repair.

Sign in to the archive ↗

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.035706+00:00.

Case digest / e74fcc217724cd56409881cfacdb726c648d585ce502c37bb67f4a4398966503