eoq Module

Overview

The eoq module contains code for solving the economic order quantity (EOQ) problem and some of its variants.

Note

The notation and references (equations, sections, examples, etc.) used below refer to Snyder and Shen, Fundamentals of Supply Chain Theory (FoSCT), 2nd edition (2019).

See Also

For an overview of single-echelon inventory optimization in Stockpyl, see the tutorial page for single-echelon inventory optimization.

API Reference

economic_order_quantity(fixed_cost, holding_cost, demand_rate, order_quantity=None)[source]

Solve the economic order quantity (EOQ) problem, or (if order_quantity is supplied) calculate cost of given solution.

Parameters
  • fixed_cost (float) – Fixed cost per order. [\(K\)]

  • holding_cost (float) – Holding cost per item per unit time. [\(h\)]

  • demand_rate (float) – Demand (items) per unit time. [\(\lambda\)]

  • order_quantity (float, optional) – Order quantity for cost evaluation. If supplied, no optimization will be performed. [\(Q\)]

Returns

  • order_quantity (float) – Optimal order quantity (or order quantity supplied) (items). [\(Q^*\)]

  • cost (float) – Cost per unit time attained by order_quantity. [\(g^*\)]

Equations Used (equations (3.4) and (3.5)):

\[ \begin{align}\begin{aligned}Q^* = \sqrt{\frac{2K\lambda}{h}}\\g^* = \sqrt{2K\lambda h}\end{aligned}\end{align} \]

or

\[g(Q) = \frac{K\lambda}{Q} + \frac{hQ}{2}\]

Example (Example 3.1):

>>> economic_order_quantity(8, 0.225, 1300)
(304.0467800264368, 68.41052550594829)
economic_order_quantity_with_backorders(fixed_cost, holding_cost, stockout_cost, demand_rate, order_quantity=None, stockout_fraction=None)[source]

Solve the economic order quantity with backorders (EOQB) problem, or (if order_quantity and stockout_fraction are supplied) calculate cost of given solution.

Parameters
  • fixed_cost (float) – Fixed cost per order. [\(K\)]

  • holding_cost (float) – Holding cost per item per unit time. [\(h\)]

  • stockout_cost (float) – Stockout cost per item per unit time. [\(p\)]

  • demand_rate (float) – Demand (items) per unit time. [\(\lambda\)]

  • order_quantity (float, optional) – Order quantity for cost evaluation. If supplied, no optimization will be performed. [\(Q\)]

  • stockout_fraction (float, optional) – Stockout fraction for cost evaluation. If supplied, no optimization will be performed. [\(x\)]

Returns

  • order_quantity (float) – Optimal order quantity (or order quantity supplied) (items). [\(Q^*\)]

  • stockout_fraction (float) – Optimal stockout fraction (or stockout fraction supplied) (items). [\(x^*\)]

  • cost (float) – Cost per unit time attained by order_quantity and stockout_fraction. [\(g^*\)]

Equations Used (equations (3.27)–(3.29)):

\[ \begin{align}\begin{aligned}Q^* = \sqrt{\frac{2K\lambda(h+p)}{hp}}\\x^* = \frac{h}{h+p}\\g^* = \sqrt{\frac{2K\lambda hp}{h+p}}\end{aligned}\end{align} \]

or

\[g(Q,x) = \frac{hQ(1-x)^2}{2} + \frac{pQx^2}{2} + \frac{K\lambda}{Q}\]

Example (Example 3.8):

>>> economic_order_quantity_with_backorders(8, 0.225, 5, 1300)
(310.81255515896464, 0.0430622009569378, 66.92136355097325)
economic_production_quantity(fixed_cost, holding_cost, demand_rate, production_rate, order_quantity=None)[source]

Solve the economic production quantity (EPQ) problem, or (if order_quantity is supplied) calculate cost of given solution.

Parameters
  • fixed_cost (float) – Fixed cost per order. [\(K\)]

  • holding_cost (float) – Holding cost per item per unit time. [\(h\)]

  • demand_rate (float) – Demand (items) per unit time. [\(\lambda\)]

  • production_rate (float) – Production quantity (items) per unit time. [\(\mu\)]

  • order_quantity (float, optional) – Order quantity for cost evaluation. If supplied, no optimization will be performed. [\(Q\)]

Returns

  • order_quantity (float) – Optimal order quantity (or order quantity supplied) (items). [\(Q^*\)]

  • cost (float) – Cost per unit time attained by order_quantity. [\(g^*\)]

Equations Used (equations (3.31) and (3.32)):

\[ \begin{align}\begin{aligned}Q^* = \sqrt{\frac{2K\lambda}{h(1-\rho)}}\\g^* = \sqrt{2K\lambda h(1-\rho)}\end{aligned}\end{align} \]

or

\[g(Q) = \frac{K\lambda}{Q} + \frac{h(1 - \rho)Q}{2}\]

where \(\rho = \lambda/\mu\).

Example:

>>> economic_production_quantity(8, 0.225, 1300, 1700)
(626.8084945889684, 33.183979125298336)
joint_replenishment_problem_silver_heuristic(shared_fixed_cost, individual_fixed_costs, holding_costs, demand_rates)[source]

Solve the joint replenishment problem (JRP) using Silver’s (1976) heuristic.

Parameters
  • shared_fixed_cost (float) – Shared fixed cost per order. [\(K\)]

  • individual_fixed_costs (list of floats) – Individual fixed cost if product n is included in order. [\(k_n\)]

  • holding_costs (list of floats) – Holding cost per item per unit time for product n. [\(h_n\)]

  • demand_rates (list of floats) – Demand (items) per unit time for product n. [\(\lambda_n\)]

Returns

  • order_quantities (list of floats) – Order quantities (items). [\(Q_n\)]

  • base_cycle_time (float) – Interval between consecutive orders. [\(T\)]

  • order_multiples (list of ints) – Product n is included in every order_multiples[n] orders. [\(m_n\)]

  • cost (float) – Cost per unit time. [\(g\)]

Equations Used:

\[ \begin{align}\begin{aligned}\hat{n} = n \text{ that minimizes } k_n / h_n\lambda_n\\m_{\hat{n}} = 1\\m_n = \sqrt{\frac{k_n}{h_n\lambda_n} \times \frac{h_{\hat{n}}\lambda_{\hat{n}}}{K+k_{\hat{n}}}} \text{ (rounded)}\\T = \sqrt{\frac{2(K+\sum_{n=1}^N \frac{k_n}{m_n}}{\sum_{n=1}^N h_nm_n\lambda_n}}\\Q_n = Tm_n\lambda_n\\g = \frac{K + \sum_{n=1}^N \frac{k_n}{m_n}}{T} + \frac{T}{2}\sum_{n=1}^N h_nm_n\lambda_n\end{aligned}\end{align} \]

Example:

>>> shared_fixed_cost = 600
>>> individual_fixed_costs = [120, 840, 300]
>>> holding_costs = [160, 20, 50]
>>> demand_rates = [1, 1, 1]
>>> joint_replenishment_problem_silver_heuristic(shared_fixed_cost, individual_fixed_costs, holding_costs, demand_rates)
([3.103164454170876, 9.309493362512628, 3.103164454170876], 3.103164454170876, [1, 3, 1], 837.8544026261366)