From eb1f2e1da8c7c06549d5e68f38f4eafb762bcfca Mon Sep 17 00:00:00 2001 From: Rudy Celekli <47457359+rudycelekli@users.noreply.github.com> Date: Mon, 5 Oct 2026 12:40:05 -0400 Subject: [PATCH] Choose the lower-cost integer EOQ in Supply Chain Strategist Signed-off-by: Rudy Celekli <47457359+rudycelekli@users.noreply.github.com> --- specialized/supply-chain-strategist.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/specialized/supply-chain-strategist.md b/specialized/supply-chain-strategist.md index b2dc5bfb..cc3e544a 100644 --- a/specialized/supply-chain-strategist.md +++ b/specialized/supply-chain-strategist.md @@ -92,10 +92,13 @@ class InventoryManager: raise ValueError("Discrete-unit EOQ requires positive annual demand") s = self.params.order_cost h = self.params.unit_price * self.params.holding_cost_rate + if not np.isfinite([d, s, h]).all() or s < 0 or h <= 0: + raise ValueError("EOQ needs finite demand/costs and positive holding cost") eoq = np.sqrt(2 * d * s / h) - # This discrete-unit example must order at least one unit when demand - # is positive; rounding a small EOQ to zero breaks the annual report. - return max(1, round(eoq)) + # Minimize the actual discrete ordering + holding objective. Nearest + # integer rounding is not equivalent (the boundary is sqrt(n*(n+1))). + candidates = {max(1, int(np.floor(eoq))), max(1, int(np.ceil(eoq)))} + return min(candidates, key=lambda q: (d * s / q + h * q / 2, q)) def calculate_safety_stock(self) -> float: """