FA-94906 / Warehouse slotting and bin packing / Open access
Replenishment: partial reserve case requested · case 01
A task requests more units than exist as full cases in reserve, forcing a case to be broken in reserve.
ROOT CAUSE
The reserve limit uses the raw unit count instead of full cases available.
VERIFIED REPAIR
Cap quantity at the number of full cases in reserve times the case pack.
Unsuccessful approach: Dividing reserve by case pack without multiplying back compares cases against units.
Case contract
faces [[loc, on_hand, min, max, case_pack, reserve_units]], min >= 1. Replenish when on_hand <= min. Quantity is the largest number of full cases that keeps on_hand <= max, limited to full cases available in reserve. A stocked-out face whose max leaves no room for a full case still gets one case if reserve has one. Zero-quantity tasks are dropped. Tasks are ordered by on_hand/min ascending, then loc.
Why this case matters
Min/max replenishment keeps forward pick faces stocked from reserve.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
from fractions import Fraction
N = 1
observations = []
def solve(faces):
tasks = []
for loc, oh, mn, mx, cp, reserve in faces:
if oh > mn:
continue
avail = reserve
qty = (mx - oh) // cp * cp
qty = min(qty, avail)
if qty == 0 and oh == 0 and avail >= cp:
qty = cp
if qty == 0:
continue
tasks.append((Fraction(oh, mn), loc, qty))
tasks.sort()
return [[loc, qty] for _, loc, qty in tasks]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['reserve partial case', [[['A', 0, 5, 30, 12, 20]]], [['A', 12]]], ['at min triggers', [[['A', 10, 10, 34, 12, 100]]], [['A', 24]]], ['stockout small max', [[['B', 0, 2, 5, 6, 12]]], [['B', 6]]], ['priority by ratio', [[['X', 5, 10, 40, 5, 100], ['Y', 2, 8, 40, 5, 100], ['Z', 0, 6, 40, 5, 100]]], [['Z', 40], ['Y', 35], ['X', 35]]], ['above min idle', [[['A', 11, 10, 34, 12, 100]]], []], ['stockout no reserve', [[['B', 0, 2, 20, 6, 5]]], []], ['generated mix 8', [[['F0', 0, 12, 15, 6, 0], ['F1', 1, 10, 22, 6, 12]]], [['F1', 12]]], ['generated mix 16', [[['F0', 6, 6, 36, 1, 0], ['F1', 1, 10, 22, 1, 3], ['F2', 5, 4, 16, 6, 24], ['F3', 7, 6, 36, 6, 24]]], [['F1', 3]]]], [['generated mix 44', [[['F0', 4, 4, 4, 6, 3], ['F1', 11, 10, 10, 1, 48], ['F2', 11, 12, 24, 4, 48], ['F3', 3, 6, 9, 4, 3]]], [['F2', 12]]], ['generated mix 4', [[['F0', 1, 12, 42, 12, 24]]], [['F0', 24]]], ['stockout small max', [[['B', 0, 2, 5, 6, 12]]], [['B', 6]]], ['priority by ratio', [[['X', 5, 10, 40, 5, 100], ['Y', 2, 8, 40, 5, 100], ['Z', 0, 6, 40, 5, 100]]], [['Z', 40], ['Y', 35], ['X', 35]]], ['above min idle', [[['A', 11, 10, 34, 12, 100]]], []], ['generated mix 10', [[['F0', 0, 4, 4, 12, 12], ['F1', 5, 6, 12, 12, 24]]], [['F0', 12]]], ['generated mix 18', [[['F0', 5, 6, 9, 6, 24], ['F1', 1, 12, 15, 4, 3], ['F2', 3, 12, 15, 12, 0], ['F3', 7, 6, 30, 6, 24]]], []], ['generated mix 26', [[['F0', 7, 6, 6, 12, 48], ['F1', 0, 4, 28, 6, 12], ['F2', 0, 6, 30, 6, 0], ['F3', 1, 6, 6, 1, 3]]], [['F1', 12], ['F3', 3]]]], [['generated mix 66', [[['F0', 12, 12, 42, 1, 48], ['F1', 0, 12, 15, 6, 3], ['F2', 1, 4, 28, 12, 12]]], [['F2', 12], ['F0', 30]]], ['generated mix 10', [[['F0', 0, 4, 4, 12, 12], ['F1', 5, 6, 12, 12, 24]]], [['F0', 12]]], ['at min triggers', [[['A', 10, 10, 34, 12, 100]]], [['A', 24]]], ['reserve partial case', [[['A', 0, 5, 30, 12, 20]]], [['A', 12]]], ['stockout no reserve', [[['B', 0, 2, 20, 6, 5]]], []], ['generated mix 21', [[['F0', 0, 4, 16, 1, 24], ['F1', 11, 10, 22, 6, 12], ['F2', 0, 6, 18, 4, 24], ['F3', 3, 4, 34, 6, 48], ['F4', 12, 12, 24, 12, 100]]], [['F0', 16], ['F2', 16], ['F3', 30], ['F4', 12]]], ['generated mix 29', [[['F0', 1, 12, 36, 1, 100], ['F1', 0, 4, 16, 1, 100], ['F2', 3, 12, 18, 4, 24], ['F3', 7, 6, 6, 1, 48]]], [['F1', 16], ['F0', 35], ['F2', 12]]], ['generated mix 37', [[['F0', 0, 4, 7, 12, 48]]], [['F0', 12]]]], [['generated mix 23', [[['F0', 0, 12, 24, 12, 3], ['F1', 0, 4, 10, 12, 24]]], [['F1', 12]]], ['generated mix 17', [[['F0', 1, 12, 24, 4, 12], ['F1', 12, 12, 18, 4, 24], ['F2', 11, 12, 24, 1, 12], ['F3', 11, 10, 40, 12, 100]]], [['F0', 12], ['F2', 12], ['F1', 4]]], ['stockout small max', [[['B', 0, 2, 5, 6, 12]]], [['B', 6]]], ['priority by ratio', [[['X', 5, 10, 40, 5, 100], ['Y', 2, 8, 40, 5, 100], ['Z', 0, 6, 40, 5, 100]]], [['Z', 40], ['Y', 35], ['X', 35]]], ['above min idle', [[['A', 11, 10, 34, 12, 100]]], []], ['generated mix 33', [[['F0', 13, 12, 36, 12, 48], ['F1', 5, 4, 10, 6, 100], ['F2', 4, 4, 10, 12, 24]]], []], ['generated mix 41', [[['F0', 0, 4, 16, 1, 12], ['F1', 7, 6, 30, 1, 100], ['F2', 5, 6, 18, 12, 24]]], [['F0', 12], ['F2', 12]]], ['generated mix 49', [[['F0', 1, 12, 36, 6, 100], ['F1', 0, 12, 18, 12, 12], ['F2', 0, 10, 10, 1, 48], ['F3', 1, 6, 18, 1, 100]]], [['F1', 12], ['F2', 10], ['F0', 30], ['F3', 17]]]], [['generated mix 51', [[['F0', 4, 4, 28, 6, 12], ['F1', 1, 6, 30, 12, 0], ['F2', 9, 10, 34, 6, 3]]], [['F0', 12]]], ['generated mix 24', [[['F0', 3, 10, 10, 4, 48], ['F1', 0, 6, 9, 4, 12], ['F2', 0, 10, 13, 12, 100], ['F3', 6, 6, 6, 4, 12]]], [['F1', 8], ['F2', 12], ['F0', 4]]], ['at min triggers', [[['A', 10, 10, 34, 12, 100]]], [['A', 24]]], ['reserve partial case', [[['A', 0, 5, 30, 12, 20]]], [['A', 12]]], ['stockout no reserve', [[['B', 0, 2, 20, 6, 5]]], []], ['generated mix 43', [[['F0', 0, 6, 18, 4, 24], ['F1', 3, 4, 34, 4, 48], ['F2', 1, 4, 10, 12, 0], ['F3', 1, 4, 34, 12, 12]]], [['F0', 16], ['F3', 12], ['F1', 28]]], ['generated mix 52', [[['F0', 11, 10, 16, 6, 3], ['F1', 10, 10, 13, 4, 24], ['F2', 0, 4, 28, 1, 100], ['F3', 12, 12, 42, 4, 0]]], [['F2', 28]]], ['generated mix 60', [[['F0', 0, 10, 40, 1, 24], ['F1', 3, 6, 30, 4, 100], ['F2', 4, 4, 4, 6, 100]]], [['F0', 24], ['F1', 24]]]]]
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| reserve partial case | [['A', 20]] | [['A', 12]] | Failed |
| at min triggers | [['A', 24]] | [['A', 24]] | Passed |
| stockout small max | [['B', 6]] | [['B', 6]] | Passed |
| priority by ratio | [['Z', 40], ['Y', 35], ['X', 35]] | [['Z', 40], ['Y', 35], ['X', 35]] | Passed |
| above min idle | [] | [] | Passed |
| stockout no reserve | [['B', 5]] | [] | Failed |
| generated mix 8 | [['F1', 12]] | [['F1', 12]] | Passed |
| generated mix 16 | [['F1', 3]] | [['F1', 3]] | Passed |
SHA-256 / b9efffeae6fc2ee78fafe23bedcd92d5736d46faeeeb96cf03796eb18b1fc0c6
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
from fractions import Fraction
N = 1
observations = []
def solve(faces):
tasks = []
for loc, oh, mn, mx, cp, reserve in faces:
if oh > mn:
continue
avail = reserve // cp
qty = (mx - oh) // cp * cp
qty = min(qty, avail)
if qty == 0 and oh == 0 and avail >= cp:
qty = cp
if qty == 0:
continue
tasks.append((Fraction(oh, mn), loc, qty))
tasks.sort()
return [[loc, qty] for _, loc, qty in tasks]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['reserve partial case', [[['A', 0, 5, 30, 12, 20]]], [['A', 12]]], ['at min triggers', [[['A', 10, 10, 34, 12, 100]]], [['A', 24]]], ['stockout small max', [[['B', 0, 2, 5, 6, 12]]], [['B', 6]]], ['priority by ratio', [[['X', 5, 10, 40, 5, 100], ['Y', 2, 8, 40, 5, 100], ['Z', 0, 6, 40, 5, 100]]], [['Z', 40], ['Y', 35], ['X', 35]]], ['above min idle', [[['A', 11, 10, 34, 12, 100]]], []], ['stockout no reserve', [[['B', 0, 2, 20, 6, 5]]], []], ['generated mix 8', [[['F0', 0, 12, 15, 6, 0], ['F1', 1, 10, 22, 6, 12]]], [['F1', 12]]], ['generated mix 16', [[['F0', 6, 6, 36, 1, 0], ['F1', 1, 10, 22, 1, 3], ['F2', 5, 4, 16, 6, 24], ['F3', 7, 6, 36, 6, 24]]], [['F1', 3]]]], [['generated mix 44', [[['F0', 4, 4, 4, 6, 3], ['F1', 11, 10, 10, 1, 48], ['F2', 11, 12, 24, 4, 48], ['F3', 3, 6, 9, 4, 3]]], [['F2', 12]]], ['generated mix 4', [[['F0', 1, 12, 42, 12, 24]]], [['F0', 24]]], ['stockout small max', [[['B', 0, 2, 5, 6, 12]]], [['B', 6]]], ['priority by ratio', [[['X', 5, 10, 40, 5, 100], ['Y', 2, 8, 40, 5, 100], ['Z', 0, 6, 40, 5, 100]]], [['Z', 40], ['Y', 35], ['X', 35]]], ['above min idle', [[['A', 11, 10, 34, 12, 100]]], []], ['generated mix 10', [[['F0', 0, 4, 4, 12, 12], ['F1', 5, 6, 12, 12, 24]]], [['F0', 12]]], ['generated mix 18', [[['F0', 5, 6, 9, 6, 24], ['F1', 1, 12, 15, 4, 3], ['F2', 3, 12, 15, 12, 0], ['F3', 7, 6, 30, 6, 24]]], []], ['generated mix 26', [[['F0', 7, 6, 6, 12, 48], ['F1', 0, 4, 28, 6, 12], ['F2', 0, 6, 30, 6, 0], ['F3', 1, 6, 6, 1, 3]]], [['F1', 12], ['F3', 3]]]], [['generated mix 66', [[['F0', 12, 12, 42, 1, 48], ['F1', 0, 12, 15, 6, 3], ['F2', 1, 4, 28, 12, 12]]], [['F2', 12], ['F0', 30]]], ['generated mix 10', [[['F0', 0, 4, 4, 12, 12], ['F1', 5, 6, 12, 12, 24]]], [['F0', 12]]], ['at min triggers', [[['A', 10, 10, 34, 12, 100]]], [['A', 24]]], ['reserve partial case', [[['A', 0, 5, 30, 12, 20]]], [['A', 12]]], ['stockout no reserve', [[['B', 0, 2, 20, 6, 5]]], []], ['generated mix 21', [[['F0', 0, 4, 16, 1, 24], ['F1', 11, 10, 22, 6, 12], ['F2', 0, 6, 18, 4, 24], ['F3', 3, 4, 34, 6, 48], ['F4', 12, 12, 24, 12, 100]]], [['F0', 16], ['F2', 16], ['F3', 30], ['F4', 12]]], ['generated mix 29', [[['F0', 1, 12, 36, 1, 100], ['F1', 0, 4, 16, 1, 100], ['F2', 3, 12, 18, 4, 24], ['F3', 7, 6, 6, 1, 48]]], [['F1', 16], ['F0', 35], ['F2', 12]]], ['generated mix 37', [[['F0', 0, 4, 7, 12, 48]]], [['F0', 12]]]], [['generated mix 23', [[['F0', 0, 12, 24, 12, 3], ['F1', 0, 4, 10, 12, 24]]], [['F1', 12]]], ['generated mix 17', [[['F0', 1, 12, 24, 4, 12], ['F1', 12, 12, 18, 4, 24], ['F2', 11, 12, 24, 1, 12], ['F3', 11, 10, 40, 12, 100]]], [['F0', 12], ['F2', 12], ['F1', 4]]], ['stockout small max', [[['B', 0, 2, 5, 6, 12]]], [['B', 6]]], ['priority by ratio', [[['X', 5, 10, 40, 5, 100], ['Y', 2, 8, 40, 5, 100], ['Z', 0, 6, 40, 5, 100]]], [['Z', 40], ['Y', 35], ['X', 35]]], ['above min idle', [[['A', 11, 10, 34, 12, 100]]], []], ['generated mix 33', [[['F0', 13, 12, 36, 12, 48], ['F1', 5, 4, 10, 6, 100], ['F2', 4, 4, 10, 12, 24]]], []], ['generated mix 41', [[['F0', 0, 4, 16, 1, 12], ['F1', 7, 6, 30, 1, 100], ['F2', 5, 6, 18, 12, 24]]], [['F0', 12], ['F2', 12]]], ['generated mix 49', [[['F0', 1, 12, 36, 6, 100], ['F1', 0, 12, 18, 12, 12], ['F2', 0, 10, 10, 1, 48], ['F3', 1, 6, 18, 1, 100]]], [['F1', 12], ['F2', 10], ['F0', 30], ['F3', 17]]]], [['generated mix 51', [[['F0', 4, 4, 28, 6, 12], ['F1', 1, 6, 30, 12, 0], ['F2', 9, 10, 34, 6, 3]]], [['F0', 12]]], ['generated mix 24', [[['F0', 3, 10, 10, 4, 48], ['F1', 0, 6, 9, 4, 12], ['F2', 0, 10, 13, 12, 100], ['F3', 6, 6, 6, 4, 12]]], [['F1', 8], ['F2', 12], ['F0', 4]]], ['at min triggers', [[['A', 10, 10, 34, 12, 100]]], [['A', 24]]], ['reserve partial case', [[['A', 0, 5, 30, 12, 20]]], [['A', 12]]], ['stockout no reserve', [[['B', 0, 2, 20, 6, 5]]], []], ['generated mix 43', [[['F0', 0, 6, 18, 4, 24], ['F1', 3, 4, 34, 4, 48], ['F2', 1, 4, 10, 12, 0], ['F3', 1, 4, 34, 12, 12]]], [['F0', 16], ['F3', 12], ['F1', 28]]], ['generated mix 52', [[['F0', 11, 10, 16, 6, 3], ['F1', 10, 10, 13, 4, 24], ['F2', 0, 4, 28, 1, 100], ['F3', 12, 12, 42, 4, 0]]], [['F2', 28]]], ['generated mix 60', [[['F0', 0, 10, 40, 1, 24], ['F1', 3, 6, 30, 4, 100], ['F2', 4, 4, 4, 6, 100]]], [['F0', 24], ['F1', 24]]]]]
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| reserve partial case | [['A', 1]] | [['A', 12]] | Failed |
| at min triggers | [['A', 8]] | [['A', 24]] | Failed |
| stockout small max | [] | [['B', 6]] | Failed |
| priority by ratio | [['Z', 20], ['Y', 20], ['X', 20]] | [['Z', 40], ['Y', 35], ['X', 35]] | Failed |
| above min idle | [] | [] | Passed |
| stockout no reserve | [] | [] | Passed |
| generated mix 8 | [['F1', 2]] | [['F1', 12]] | Failed |
| generated mix 16 | [['F1', 3]] | [['F1', 3]] | Passed |
SHA-256 / 910d69bdd2dfac8df0f3de239a048df9c41d0de02953c04c5f15fd3ae457bd5a
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
from fractions import Fraction
N = 1
observations = []
def solve(faces):
tasks = []
for loc, oh, mn, mx, cp, reserve in faces:
if oh > mn:
continue
avail = reserve // cp * cp
qty = (mx - oh) // cp * cp
qty = min(qty, avail)
if qty == 0 and oh == 0 and avail >= cp:
qty = cp
if qty == 0:
continue
tasks.append((Fraction(oh, mn), loc, qty))
tasks.sort()
return [[loc, qty] for _, loc, qty in tasks]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['reserve partial case', [[['A', 0, 5, 30, 12, 20]]], [['A', 12]]], ['at min triggers', [[['A', 10, 10, 34, 12, 100]]], [['A', 24]]], ['stockout small max', [[['B', 0, 2, 5, 6, 12]]], [['B', 6]]], ['priority by ratio', [[['X', 5, 10, 40, 5, 100], ['Y', 2, 8, 40, 5, 100], ['Z', 0, 6, 40, 5, 100]]], [['Z', 40], ['Y', 35], ['X', 35]]], ['above min idle', [[['A', 11, 10, 34, 12, 100]]], []], ['stockout no reserve', [[['B', 0, 2, 20, 6, 5]]], []], ['generated mix 8', [[['F0', 0, 12, 15, 6, 0], ['F1', 1, 10, 22, 6, 12]]], [['F1', 12]]], ['generated mix 16', [[['F0', 6, 6, 36, 1, 0], ['F1', 1, 10, 22, 1, 3], ['F2', 5, 4, 16, 6, 24], ['F3', 7, 6, 36, 6, 24]]], [['F1', 3]]]], [['generated mix 44', [[['F0', 4, 4, 4, 6, 3], ['F1', 11, 10, 10, 1, 48], ['F2', 11, 12, 24, 4, 48], ['F3', 3, 6, 9, 4, 3]]], [['F2', 12]]], ['generated mix 4', [[['F0', 1, 12, 42, 12, 24]]], [['F0', 24]]], ['stockout small max', [[['B', 0, 2, 5, 6, 12]]], [['B', 6]]], ['priority by ratio', [[['X', 5, 10, 40, 5, 100], ['Y', 2, 8, 40, 5, 100], ['Z', 0, 6, 40, 5, 100]]], [['Z', 40], ['Y', 35], ['X', 35]]], ['above min idle', [[['A', 11, 10, 34, 12, 100]]], []], ['generated mix 10', [[['F0', 0, 4, 4, 12, 12], ['F1', 5, 6, 12, 12, 24]]], [['F0', 12]]], ['generated mix 18', [[['F0', 5, 6, 9, 6, 24], ['F1', 1, 12, 15, 4, 3], ['F2', 3, 12, 15, 12, 0], ['F3', 7, 6, 30, 6, 24]]], []], ['generated mix 26', [[['F0', 7, 6, 6, 12, 48], ['F1', 0, 4, 28, 6, 12], ['F2', 0, 6, 30, 6, 0], ['F3', 1, 6, 6, 1, 3]]], [['F1', 12], ['F3', 3]]]], [['generated mix 66', [[['F0', 12, 12, 42, 1, 48], ['F1', 0, 12, 15, 6, 3], ['F2', 1, 4, 28, 12, 12]]], [['F2', 12], ['F0', 30]]], ['generated mix 10', [[['F0', 0, 4, 4, 12, 12], ['F1', 5, 6, 12, 12, 24]]], [['F0', 12]]], ['at min triggers', [[['A', 10, 10, 34, 12, 100]]], [['A', 24]]], ['reserve partial case', [[['A', 0, 5, 30, 12, 20]]], [['A', 12]]], ['stockout no reserve', [[['B', 0, 2, 20, 6, 5]]], []], ['generated mix 21', [[['F0', 0, 4, 16, 1, 24], ['F1', 11, 10, 22, 6, 12], ['F2', 0, 6, 18, 4, 24], ['F3', 3, 4, 34, 6, 48], ['F4', 12, 12, 24, 12, 100]]], [['F0', 16], ['F2', 16], ['F3', 30], ['F4', 12]]], ['generated mix 29', [[['F0', 1, 12, 36, 1, 100], ['F1', 0, 4, 16, 1, 100], ['F2', 3, 12, 18, 4, 24], ['F3', 7, 6, 6, 1, 48]]], [['F1', 16], ['F0', 35], ['F2', 12]]], ['generated mix 37', [[['F0', 0, 4, 7, 12, 48]]], [['F0', 12]]]], [['generated mix 23', [[['F0', 0, 12, 24, 12, 3], ['F1', 0, 4, 10, 12, 24]]], [['F1', 12]]], ['generated mix 17', [[['F0', 1, 12, 24, 4, 12], ['F1', 12, 12, 18, 4, 24], ['F2', 11, 12, 24, 1, 12], ['F3', 11, 10, 40, 12, 100]]], [['F0', 12], ['F2', 12], ['F1', 4]]], ['stockout small max', [[['B', 0, 2, 5, 6, 12]]], [['B', 6]]], ['priority by ratio', [[['X', 5, 10, 40, 5, 100], ['Y', 2, 8, 40, 5, 100], ['Z', 0, 6, 40, 5, 100]]], [['Z', 40], ['Y', 35], ['X', 35]]], ['above min idle', [[['A', 11, 10, 34, 12, 100]]], []], ['generated mix 33', [[['F0', 13, 12, 36, 12, 48], ['F1', 5, 4, 10, 6, 100], ['F2', 4, 4, 10, 12, 24]]], []], ['generated mix 41', [[['F0', 0, 4, 16, 1, 12], ['F1', 7, 6, 30, 1, 100], ['F2', 5, 6, 18, 12, 24]]], [['F0', 12], ['F2', 12]]], ['generated mix 49', [[['F0', 1, 12, 36, 6, 100], ['F1', 0, 12, 18, 12, 12], ['F2', 0, 10, 10, 1, 48], ['F3', 1, 6, 18, 1, 100]]], [['F1', 12], ['F2', 10], ['F0', 30], ['F3', 17]]]], [['generated mix 51', [[['F0', 4, 4, 28, 6, 12], ['F1', 1, 6, 30, 12, 0], ['F2', 9, 10, 34, 6, 3]]], [['F0', 12]]], ['generated mix 24', [[['F0', 3, 10, 10, 4, 48], ['F1', 0, 6, 9, 4, 12], ['F2', 0, 10, 13, 12, 100], ['F3', 6, 6, 6, 4, 12]]], [['F1', 8], ['F2', 12], ['F0', 4]]], ['at min triggers', [[['A', 10, 10, 34, 12, 100]]], [['A', 24]]], ['reserve partial case', [[['A', 0, 5, 30, 12, 20]]], [['A', 12]]], ['stockout no reserve', [[['B', 0, 2, 20, 6, 5]]], []], ['generated mix 43', [[['F0', 0, 6, 18, 4, 24], ['F1', 3, 4, 34, 4, 48], ['F2', 1, 4, 10, 12, 0], ['F3', 1, 4, 34, 12, 12]]], [['F0', 16], ['F3', 12], ['F1', 28]]], ['generated mix 52', [[['F0', 11, 10, 16, 6, 3], ['F1', 10, 10, 13, 4, 24], ['F2', 0, 4, 28, 1, 100], ['F3', 12, 12, 42, 4, 0]]], [['F2', 28]]], ['generated mix 60', [[['F0', 0, 10, 40, 1, 24], ['F1', 3, 6, 30, 4, 100], ['F2', 4, 4, 4, 6, 100]]], [['F0', 24], ['F1', 24]]]]]
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| reserve partial case | [['A', 12]] | [['A', 12]] | Passed |
| at min triggers | [['A', 24]] | [['A', 24]] | Passed |
| stockout small max | [['B', 6]] | [['B', 6]] | Passed |
| priority by ratio | [['Z', 40], ['Y', 35], ['X', 35]] | [['Z', 40], ['Y', 35], ['X', 35]] | Passed |
| above min idle | [] | [] | Passed |
| stockout no reserve | [] | [] | Passed |
| generated mix 8 | [['F1', 12]] | [['F1', 12]] | Passed |
| generated mix 16 | [['F1', 3]] | [['F1', 3]] | Passed |
SHA-256 / 01d2c341a826fcf59a0442617fc8094b43806f04aae23a23b15403cdd3bf742f
Verification & scope
Stipulated min/max policy with whole-case moves only. 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:08.756759+00:00.
Case digest / dea417fcef2c524c31a6195e0571e6e8dff73bbeebe9de1e356d79365f4cdb8b