FAILURE MAP
← Case archive

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

Pallet build: tare ignored in weight cap · case 01

Weight-limited pallets exceed the gross limit by the pallet tare.

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

ROOT CAUSE

The weight bound divides the gross limit by case weight without subtracting pallet tare.

VERIFIED REPAIR

Subtract the 25 kg tare before computing how many cases the weight limit allows.

Unsuccessful approach: Subtracting one extra case as a safety margin under-fills pallets.

Case contract

case [l, w, h, kg], pallet [L, W]; cases stay upright but may rotate 90 degrees; all layers share one orientation. Pallet base adds 15 height and 25 kg tare. Cases per pallet are bounded by whole layers within max_h and by max_kg (a partial top layer is allowed). Return [per_layer, layers used, cases, height, weight].

Why this case matters

Pallet build limits govern reserve storage heights and floor loading.

1 / The failure

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

N = 1
observations = []
def solve(case, pallet, max_h, max_kg):
    l, w, h, kg = case
    L, W = pallet
    per_layer = max((L // l) * (W // w), (L // w) * (W // l))
    if per_layer == 0:
        return [0, 0, 0, 15, 25]
    layers = (max_h - 15) // h
    by_weight = max_kg // kg
    cases = min(per_layer * layers, by_weight)
    if cases <= 0:
        return [per_layer, 0, 0, 15, 25]
    full = -(-cases // per_layer)
    return [per_layer, full, cases, 15 + full * h, 25 + cases * kg]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['weight bound partial layer', [[40, 30, 25, 20], [120, 100], 190, 425], [9, 3, 20, 90, 425]], ['generated mix 1', [[50, 15, 10, 12], [120, 100], 190, 1025], [16, 6, 83, 75, 1021]], ['listed orientation wins', [[30, 20, 20, 5], [120, 100], 115, 1000], [20, 5, 100, 115, 525]], ['height exact', [[40, 30, 25, 2], [120, 100], 140, 2000], [9, 5, 45, 140, 115]], ['too heavy for one', [[40, 30, 25, 500], [120, 100], 190, 425], [9, 0, 0, 15, 25]], ['rotation wins', [[50, 30, 20, 5], [120, 100], 115, 1000], [8, 5, 40, 115, 225]], ['generated mix 7', [[40, 30, 20, 5], [120, 80], 140, 1025], [8, 6, 48, 135, 265]], ['generated mix 15', [[50, 20, 30, 8], [120, 80], 115, 800], [8, 3, 24, 105, 217]]], [['generated mix 24', [[25, 30, 10, 12], [120, 100], 115, 1025], [16, 6, 83, 75, 1021]], ['generated mix 20', [[20, 20, 25, 20], [120, 100], 115, 1200], [30, 2, 58, 65, 1185]], ['weight bound partial layer', [[40, 30, 25, 20], [120, 100], 190, 425], [9, 3, 20, 90, 425]], ['too heavy for one', [[40, 30, 25, 500], [120, 100], 190, 425], [9, 0, 0, 15, 25]], ['listed orientation wins', [[30, 20, 20, 5], [120, 100], 115, 1000], [20, 5, 100, 115, 525]], ['height exact', [[40, 30, 25, 2], [120, 100], 140, 2000], [9, 5, 45, 140, 115]], ['generated mix 9', [[50, 20, 25, 12], [120, 100], 115, 1200], [12, 4, 48, 115, 601]], ['generated mix 17', [[30, 30, 30, 8], [120, 80], 165, 500], [8, 5, 40, 165, 345]]], [['generated mix 35', [[25, 20, 10, 12], [120, 80], 140, 800], [18, 4, 64, 55, 793]], ['generated mix 29', [[50, 30, 30, 20], [120, 100], 190, 300], [8, 2, 13, 75, 285]], ['square', [[25, 25, 30, 5], [120, 80], 165, 900], [12, 5, 60, 165, 325]], ['rotation wins', [[50, 30, 20, 5], [120, 100], 115, 1000], [8, 5, 40, 115, 225]], ['weight bound partial layer', [[40, 30, 25, 20], [120, 100], 190, 425], [9, 3, 20, 90, 425]], ['too heavy for one', [[40, 30, 25, 500], [120, 100], 190, 425], [9, 0, 0, 15, 25]], ['generated mix 20', [[20, 20, 25, 20], [120, 100], 115, 1200], [30, 2, 58, 65, 1185]], ['generated mix 28', [[20, 30, 20, 12], [120, 80], 140, 800], [16, 4, 64, 95, 793]]], [['generated mix 43', [[25, 20, 20, 12], [120, 100], 140, 1200], [24, 5, 97, 115, 1189]], ['generated mix 36', [[25, 30, 20, 12], [120, 80], 115, 500], [12, 4, 39, 95, 493]], ['height exact', [[40, 30, 25, 2], [120, 100], 140, 2000], [9, 5, 45, 140, 115]], ['too big', [[130, 30, 25, 2], [120, 100], 190, 425], [0, 0, 0, 15, 25]], ['square', [[25, 25, 30, 5], [120, 80], 165, 900], [12, 5, 60, 165, 325]], ['rotation wins', [[50, 30, 20, 5], [120, 100], 115, 1000], [8, 5, 40, 115, 225]], ['generated mix 31', [[40, 15, 25, 5], [120, 100], 190, 1025], [18, 7, 126, 190, 655]], ['generated mix 40', [[20, 15, 30, 20], [120, 80], 190, 500], [32, 1, 23, 45, 485]]], [['generated mix 58', [[50, 25, 10, 12], [120, 100], 140, 500], [8, 5, 39, 65, 493]], ['generated mix 42', [[40, 30, 20, 5], [120, 80], 165, 300], [8, 7, 55, 155, 300]], ['too heavy for one', [[40, 30, 25, 500], [120, 100], 190, 425], [9, 0, 0, 15, 25]], ['listed orientation wins', [[30, 20, 20, 5], [120, 100], 115, 1000], [20, 5, 100, 115, 525]], ['height exact', [[40, 30, 25, 2], [120, 100], 140, 2000], [9, 5, 45, 140, 115]], ['too big', [[130, 30, 25, 2], [120, 100], 190, 425], [0, 0, 0, 15, 25]], ['generated mix 43', [[25, 20, 20, 12], [120, 100], 140, 1200], [24, 5, 97, 115, 1189]], ['generated mix 51', [[25, 15, 10, 8], [120, 80], 165, 500], [24, 3, 59, 45, 497]]]]
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
weight bound partial layer[9, 3, 21, 90, 445][9, 3, 20, 90, 425]Failed
generated mix 1[16, 6, 85, 75, 1045][16, 6, 83, 75, 1021]Failed
listed orientation wins[20, 5, 100, 115, 525][20, 5, 100, 115, 525]Passed
height exact[9, 5, 45, 140, 115][9, 5, 45, 140, 115]Passed
too heavy for one[9, 0, 0, 15, 25][9, 0, 0, 15, 25]Passed
rotation wins[8, 5, 40, 115, 225][8, 5, 40, 115, 225]Passed
generated mix 7[8, 6, 48, 135, 265][8, 6, 48, 135, 265]Passed
generated mix 15[8, 3, 24, 105, 217][8, 3, 24, 105, 217]Passed

SHA-256 / bc9f62e5b3603c81eb67793ba533bb81659cb79dac4e6c6e2cff93a245124da4

2 / The unsuccessful fix

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

N = 1
observations = []
def solve(case, pallet, max_h, max_kg):
    l, w, h, kg = case
    L, W = pallet
    per_layer = max((L // l) * (W // w), (L // w) * (W // l))
    if per_layer == 0:
        return [0, 0, 0, 15, 25]
    layers = (max_h - 15) // h
    by_weight = (max_kg - 25) // kg - 1
    cases = min(per_layer * layers, by_weight)
    if cases <= 0:
        return [per_layer, 0, 0, 15, 25]
    full = -(-cases // per_layer)
    return [per_layer, full, cases, 15 + full * h, 25 + cases * kg]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['weight bound partial layer', [[40, 30, 25, 20], [120, 100], 190, 425], [9, 3, 20, 90, 425]], ['generated mix 1', [[50, 15, 10, 12], [120, 100], 190, 1025], [16, 6, 83, 75, 1021]], ['listed orientation wins', [[30, 20, 20, 5], [120, 100], 115, 1000], [20, 5, 100, 115, 525]], ['height exact', [[40, 30, 25, 2], [120, 100], 140, 2000], [9, 5, 45, 140, 115]], ['too heavy for one', [[40, 30, 25, 500], [120, 100], 190, 425], [9, 0, 0, 15, 25]], ['rotation wins', [[50, 30, 20, 5], [120, 100], 115, 1000], [8, 5, 40, 115, 225]], ['generated mix 7', [[40, 30, 20, 5], [120, 80], 140, 1025], [8, 6, 48, 135, 265]], ['generated mix 15', [[50, 20, 30, 8], [120, 80], 115, 800], [8, 3, 24, 105, 217]]], [['generated mix 24', [[25, 30, 10, 12], [120, 100], 115, 1025], [16, 6, 83, 75, 1021]], ['generated mix 20', [[20, 20, 25, 20], [120, 100], 115, 1200], [30, 2, 58, 65, 1185]], ['weight bound partial layer', [[40, 30, 25, 20], [120, 100], 190, 425], [9, 3, 20, 90, 425]], ['too heavy for one', [[40, 30, 25, 500], [120, 100], 190, 425], [9, 0, 0, 15, 25]], ['listed orientation wins', [[30, 20, 20, 5], [120, 100], 115, 1000], [20, 5, 100, 115, 525]], ['height exact', [[40, 30, 25, 2], [120, 100], 140, 2000], [9, 5, 45, 140, 115]], ['generated mix 9', [[50, 20, 25, 12], [120, 100], 115, 1200], [12, 4, 48, 115, 601]], ['generated mix 17', [[30, 30, 30, 8], [120, 80], 165, 500], [8, 5, 40, 165, 345]]], [['generated mix 35', [[25, 20, 10, 12], [120, 80], 140, 800], [18, 4, 64, 55, 793]], ['generated mix 29', [[50, 30, 30, 20], [120, 100], 190, 300], [8, 2, 13, 75, 285]], ['square', [[25, 25, 30, 5], [120, 80], 165, 900], [12, 5, 60, 165, 325]], ['rotation wins', [[50, 30, 20, 5], [120, 100], 115, 1000], [8, 5, 40, 115, 225]], ['weight bound partial layer', [[40, 30, 25, 20], [120, 100], 190, 425], [9, 3, 20, 90, 425]], ['too heavy for one', [[40, 30, 25, 500], [120, 100], 190, 425], [9, 0, 0, 15, 25]], ['generated mix 20', [[20, 20, 25, 20], [120, 100], 115, 1200], [30, 2, 58, 65, 1185]], ['generated mix 28', [[20, 30, 20, 12], [120, 80], 140, 800], [16, 4, 64, 95, 793]]], [['generated mix 43', [[25, 20, 20, 12], [120, 100], 140, 1200], [24, 5, 97, 115, 1189]], ['generated mix 36', [[25, 30, 20, 12], [120, 80], 115, 500], [12, 4, 39, 95, 493]], ['height exact', [[40, 30, 25, 2], [120, 100], 140, 2000], [9, 5, 45, 140, 115]], ['too big', [[130, 30, 25, 2], [120, 100], 190, 425], [0, 0, 0, 15, 25]], ['square', [[25, 25, 30, 5], [120, 80], 165, 900], [12, 5, 60, 165, 325]], ['rotation wins', [[50, 30, 20, 5], [120, 100], 115, 1000], [8, 5, 40, 115, 225]], ['generated mix 31', [[40, 15, 25, 5], [120, 100], 190, 1025], [18, 7, 126, 190, 655]], ['generated mix 40', [[20, 15, 30, 20], [120, 80], 190, 500], [32, 1, 23, 45, 485]]], [['generated mix 58', [[50, 25, 10, 12], [120, 100], 140, 500], [8, 5, 39, 65, 493]], ['generated mix 42', [[40, 30, 20, 5], [120, 80], 165, 300], [8, 7, 55, 155, 300]], ['too heavy for one', [[40, 30, 25, 500], [120, 100], 190, 425], [9, 0, 0, 15, 25]], ['listed orientation wins', [[30, 20, 20, 5], [120, 100], 115, 1000], [20, 5, 100, 115, 525]], ['height exact', [[40, 30, 25, 2], [120, 100], 140, 2000], [9, 5, 45, 140, 115]], ['too big', [[130, 30, 25, 2], [120, 100], 190, 425], [0, 0, 0, 15, 25]], ['generated mix 43', [[25, 20, 20, 12], [120, 100], 140, 1200], [24, 5, 97, 115, 1189]], ['generated mix 51', [[25, 15, 10, 8], [120, 80], 165, 500], [24, 3, 59, 45, 497]]]]
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
weight bound partial layer[9, 3, 19, 90, 405][9, 3, 20, 90, 425]Failed
generated mix 1[16, 6, 82, 75, 1009][16, 6, 83, 75, 1021]Failed
listed orientation wins[20, 5, 100, 115, 525][20, 5, 100, 115, 525]Passed
height exact[9, 5, 45, 140, 115][9, 5, 45, 140, 115]Passed
too heavy for one[9, 0, 0, 15, 25][9, 0, 0, 15, 25]Passed
rotation wins[8, 5, 40, 115, 225][8, 5, 40, 115, 225]Passed
generated mix 7[8, 6, 48, 135, 265][8, 6, 48, 135, 265]Passed
generated mix 15[8, 3, 24, 105, 217][8, 3, 24, 105, 217]Passed

SHA-256 / dccc728a068662e864e1dfc0d717614e987349c365cd54621871e6508cafc728

3 / The verified repair

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

N = 1
observations = []
def solve(case, pallet, max_h, max_kg):
    l, w, h, kg = case
    L, W = pallet
    per_layer = max((L // l) * (W // w), (L // w) * (W // l))
    if per_layer == 0:
        return [0, 0, 0, 15, 25]
    layers = (max_h - 15) // h
    by_weight = (max_kg - 25) // kg
    cases = min(per_layer * layers, by_weight)
    if cases <= 0:
        return [per_layer, 0, 0, 15, 25]
    full = -(-cases // per_layer)
    return [per_layer, full, cases, 15 + full * h, 25 + cases * kg]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['weight bound partial layer', [[40, 30, 25, 20], [120, 100], 190, 425], [9, 3, 20, 90, 425]], ['generated mix 1', [[50, 15, 10, 12], [120, 100], 190, 1025], [16, 6, 83, 75, 1021]], ['listed orientation wins', [[30, 20, 20, 5], [120, 100], 115, 1000], [20, 5, 100, 115, 525]], ['height exact', [[40, 30, 25, 2], [120, 100], 140, 2000], [9, 5, 45, 140, 115]], ['too heavy for one', [[40, 30, 25, 500], [120, 100], 190, 425], [9, 0, 0, 15, 25]], ['rotation wins', [[50, 30, 20, 5], [120, 100], 115, 1000], [8, 5, 40, 115, 225]], ['generated mix 7', [[40, 30, 20, 5], [120, 80], 140, 1025], [8, 6, 48, 135, 265]], ['generated mix 15', [[50, 20, 30, 8], [120, 80], 115, 800], [8, 3, 24, 105, 217]]], [['generated mix 24', [[25, 30, 10, 12], [120, 100], 115, 1025], [16, 6, 83, 75, 1021]], ['generated mix 20', [[20, 20, 25, 20], [120, 100], 115, 1200], [30, 2, 58, 65, 1185]], ['weight bound partial layer', [[40, 30, 25, 20], [120, 100], 190, 425], [9, 3, 20, 90, 425]], ['too heavy for one', [[40, 30, 25, 500], [120, 100], 190, 425], [9, 0, 0, 15, 25]], ['listed orientation wins', [[30, 20, 20, 5], [120, 100], 115, 1000], [20, 5, 100, 115, 525]], ['height exact', [[40, 30, 25, 2], [120, 100], 140, 2000], [9, 5, 45, 140, 115]], ['generated mix 9', [[50, 20, 25, 12], [120, 100], 115, 1200], [12, 4, 48, 115, 601]], ['generated mix 17', [[30, 30, 30, 8], [120, 80], 165, 500], [8, 5, 40, 165, 345]]], [['generated mix 35', [[25, 20, 10, 12], [120, 80], 140, 800], [18, 4, 64, 55, 793]], ['generated mix 29', [[50, 30, 30, 20], [120, 100], 190, 300], [8, 2, 13, 75, 285]], ['square', [[25, 25, 30, 5], [120, 80], 165, 900], [12, 5, 60, 165, 325]], ['rotation wins', [[50, 30, 20, 5], [120, 100], 115, 1000], [8, 5, 40, 115, 225]], ['weight bound partial layer', [[40, 30, 25, 20], [120, 100], 190, 425], [9, 3, 20, 90, 425]], ['too heavy for one', [[40, 30, 25, 500], [120, 100], 190, 425], [9, 0, 0, 15, 25]], ['generated mix 20', [[20, 20, 25, 20], [120, 100], 115, 1200], [30, 2, 58, 65, 1185]], ['generated mix 28', [[20, 30, 20, 12], [120, 80], 140, 800], [16, 4, 64, 95, 793]]], [['generated mix 43', [[25, 20, 20, 12], [120, 100], 140, 1200], [24, 5, 97, 115, 1189]], ['generated mix 36', [[25, 30, 20, 12], [120, 80], 115, 500], [12, 4, 39, 95, 493]], ['height exact', [[40, 30, 25, 2], [120, 100], 140, 2000], [9, 5, 45, 140, 115]], ['too big', [[130, 30, 25, 2], [120, 100], 190, 425], [0, 0, 0, 15, 25]], ['square', [[25, 25, 30, 5], [120, 80], 165, 900], [12, 5, 60, 165, 325]], ['rotation wins', [[50, 30, 20, 5], [120, 100], 115, 1000], [8, 5, 40, 115, 225]], ['generated mix 31', [[40, 15, 25, 5], [120, 100], 190, 1025], [18, 7, 126, 190, 655]], ['generated mix 40', [[20, 15, 30, 20], [120, 80], 190, 500], [32, 1, 23, 45, 485]]], [['generated mix 58', [[50, 25, 10, 12], [120, 100], 140, 500], [8, 5, 39, 65, 493]], ['generated mix 42', [[40, 30, 20, 5], [120, 80], 165, 300], [8, 7, 55, 155, 300]], ['too heavy for one', [[40, 30, 25, 500], [120, 100], 190, 425], [9, 0, 0, 15, 25]], ['listed orientation wins', [[30, 20, 20, 5], [120, 100], 115, 1000], [20, 5, 100, 115, 525]], ['height exact', [[40, 30, 25, 2], [120, 100], 140, 2000], [9, 5, 45, 140, 115]], ['too big', [[130, 30, 25, 2], [120, 100], 190, 425], [0, 0, 0, 15, 25]], ['generated mix 43', [[25, 20, 20, 12], [120, 100], 140, 1200], [24, 5, 97, 115, 1189]], ['generated mix 51', [[25, 15, 10, 8], [120, 80], 165, 500], [24, 3, 59, 45, 497]]]]
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
weight bound partial layer[9, 3, 20, 90, 425][9, 3, 20, 90, 425]Passed
generated mix 1[16, 6, 83, 75, 1021][16, 6, 83, 75, 1021]Passed
listed orientation wins[20, 5, 100, 115, 525][20, 5, 100, 115, 525]Passed
height exact[9, 5, 45, 140, 115][9, 5, 45, 140, 115]Passed
too heavy for one[9, 0, 0, 15, 25][9, 0, 0, 15, 25]Passed
rotation wins[8, 5, 40, 115, 225][8, 5, 40, 115, 225]Passed
generated mix 7[8, 6, 48, 135, 265][8, 6, 48, 135, 265]Passed
generated mix 15[8, 3, 24, 105, 217][8, 3, 24, 105, 217]Passed

SHA-256 / 3dd194a702769bbffb75ecb7ca0170245886aaf1764f8defe2785c5af11cca9b

Verification & scope

Uniform-case, single-orientation layer model; no interlocking patterns. 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:09.640612+00:00.

Case digest / e5d07377146111e2a1c4dd7860b6ea0bbda8c6ce403571999f55d71e006cd051