Base-Stock Controller

For single-sourcing problems over an infinite time horizon, the base-stock controller maintains a fixed target inventory level. When inventory falls below this level due to demand fluctuations, a replenishment order is immediately placed to restore the stock to the target level.

Key Concepts

  • Target Inventory Level: The target inventory level that triggers replenishment orders whenever stock dips below it.

Mathematical Structure

To mathematically describe the optimal order policy of single-sourcing problems (Arrow, Harris, & Marschak, 1951; Scarf & Karlin, 1958), we use \(l\) and \(z^*\) to respectively denote the replenishment lead time and the target inventory-position level (i.e., the target net inventory level plus all items ordered but not received yet). The inventory position of single-sourcing dynamics at time \(t\), \(\tilde{I}_t\), is given by

\[\begin{split}\tilde{I}_t = \begin{cases} I_t & \text{if} \,\, l=0 \\ I_t + \sum_{i=1}^l q_{t-i} & \text{if} \,\, l>0 \,, \end{cases}\end{split}\]

where \(I_t\) and \(q_t\) denote the net inventory at time \(t\) and the replenishment order placed at time \(t\), respectively.

The optimal order quantity is \(q_t=\max\{0, z^*-\tilde{I}_t\}\), where the target level \(z^*\) is the parameter to be determined.

Example Usage

We now present two examples to demonstrate how the BaseStockController can be called and evaluated in idinn.

>>> import torch
>>> from idinn.sourcing_model import SingleSourcingModel
>>> from idinn.single_controller import BaseStockController
>>> from idinn.demand import UniformDemand

>>> # First example
>>> single_sourcing_model = SingleSourcingModel(
...     lead_time=0,
...     holding_cost=5,
...     shortage_cost=495,
...     init_inventory=10,
...     demand_generator=UniformDemand(low=0, high=4),
... )
>>> controller_base = BaseStockController()
>>> # z_star should be 4
>>> controller_base.fit(single_sourcing_model)
>>> print(f"z_star: {controller_base.z_star}")
z_star: 4
>>> # Avg. cost near 10
>>> avg_cost = controller_base.get_average_cost(single_sourcing_model, sourcing_periods=1000, seed=42).mean()
>>> print(f"Average Cost: {avg_cost:.2f}")
Average Cost: 10.39

>>> # Second example
>>> single_sourcing_model = SingleSourcingModel(
...     lead_time=2,
...     holding_cost=5,
...     shortage_cost=495,
...     init_inventory=10,
...     demand_generator=UniformDemand(low=0, high=4),
... )
>>> controller_base = BaseStockController()
>>> controller_base.fit(single_sourcing_model)
>>> # z_star should be 11
>>> print(f"z_star: {controller_base.z_star}")
z_star: 11
>>> # Avg. cost near 29
>>> avg_cost = controller_base.get_average_cost(single_sourcing_model, sourcing_periods=1000, seed=42).mean()
>>> print(f"Average Cost: {avg_cost:.2f}")
Average Cost: 29.53

References

  • Scarf, H., & Karlin, S. (1958). Inventory models of the Arrow-Harris-Marschak type with time lag. In K. J. Arrow, S. Karlin, & H. E. Scarf (Eds.), Studies in the Mathematical Theory of Inventory and Production (Stanford University Press, Stanford, CA).

  • Arrow, K. J., Harris, T., & Marschak, J. (1951). Optimal inventory policy. Econometrica, 19(3), 250–272.