{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Robust Lot Sizing" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Consider the problem of Lot Sizing, where you need to decide how much to produce or order in each time period to meet demand and minimize costs. This involves planning for a fixed period with known demand and various costs such as setup, production, holding inventory, and handling backorders. The main goal is to create a production plan that meets demand efficiently. In its robust form, this problem also accounts for uncertainties in production yields, which can vary within a certain range." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In the example taken from [1, Section 3.3] we consider a single item multi period uncapacitated lot sizing problem with backorder and production yield that determine the quantity to produce in each time period of the finite planning horizon $T$.\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The problem we want to solve is the uncertain linear optimization problem of the form:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "$$\n", "\\begin{array}{ll}\n", "\\text{minimize} & \\sum_{t = 1}^T\\left(s_t^Ty_t + v_t^Tx_t + {k}_t\\right) \\\\\n", "\\text{subject to} & k_t \\geq h_t\\left( p_t^Tx_t - d_t\\right) \\quad t =1,\\dots,T \\quad \\forall p_t \\in \\mathcal{U}\\\\ \n", " & k_t \\geq -b_t\\left( p_t^Tx_t - d_t\\right) \\quad t =1,\\dots,T \\quad \\forall p_t \\in \\mathcal{U}\\\\\n", " & x_t \\leq {m_t}^T{y_t} \\quad t =1,\\dots,T \\\\\n", " & x \\geq \\mathbf{0}\\\\\n", " & {h'} \\geq \\mathbf{0}\n", "\\end{array}\n", "$$\n", "\n", "where $s$ denotes the setup cost, $h$ denotes the inventory holding cost , $b$ denotes the backorder cost $b$, $x$ denotes the lot size to be produced, and $d$ denotes the demand for each time period in $T$. $h'$ is independently defined for each period as the highest cost between the worst inventory cost and the worst backorder cost under the uncertainty set. The model contains the decision variables $X$, the lot size to be produced, and the setup decision $Y$. The strictly positive uncertain production yield is defined as $p$. $m$ denotes the upper bound on production quantity." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To solve this problem, we first import the required packages." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import lropt\n", "import cvxpy as cp" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We start by defining the relevant constants and creating variables. " ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "np.random.seed(1)\n", "T = 5 \n", "RHO = 2\n", "s = np.random.rand(T) \n", "v = np.random.rand(T) \n", "h = np.random.rand(T) \n", "b = np.random.rand(T) \n", "d = np.random.randint(10, 20, size=T) \n", "\n", "# Large positive number for setup constraint\n", "m = np.full(T, 1000)\n", "x = cp.Variable(T, nonneg=True)\n", "y = cp.Variable(T, boolean=True) \n", "k = cp.Variable(T, nonneg=True) " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In the following we define the parameter $p$ as an uncertain parameter that belongs a Budget Uncertainty set. The budget uncertainty is defined as:\n", "$$\n", " \\mathcal{U}_{\\text{budg}} = \\{z \\ | \\ \\|z \\|_\\infty \\le \\rho_1,\n", " \\|z \\|_1 \\leq \\rho_2\\}\n", "$$" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "p = lropt.UncertainParameter(T, uncertainty_set = lropt.Budget(rho1 = RHO, rho2= RHO), nonneg = True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We define our objective and constraints." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "objective = cp.Minimize(cp.sum(s @ y + v @ x + k))\n", "constraints = [\n", "k >= h * cp.sum(p @ x - d),\n", "k >= (-b) * cp.sum(p @ x - d),\n", "x <= m@y\n", "]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Finally, we solve the problem and get the optimal value." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Set parameter Username\n", "Academic license - for non-commercial use only - expires 2025-08-14\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "/Users/mj5676/Desktop/miniconda3/envs/lropt_v3/lib/python3.12/site-packages/cvxpy/utilities/torch_utils.py:61: UserWarning: torch.sparse.SparseTensor(indices, values, shape, *, device=) is deprecated. Please use torch.sparse_coo_tensor(indices, values, shape, dtype=, device=). (Triggered internally at /Users/runner/work/pytorch/pytorch/pytorch/torch/csrc/utils/tensor_new.cpp:643.)\n", " return torch.sparse.FloatTensor(i, v, torch.Size(value_coo.shape)).to(dtype)\n" ] } ], "source": [ "prob = lropt.RobustProblem(objective, constraints)\n", "prob.solve()" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The robust optimal values for the total cost using Budget uncertainty are 6.034E+01, 3.756E+01, 5.028E+01, 1.263E+01, 1.783E+01\n" ] } ], "source": [ "formatted_values = [f\"{value:.3E}\" for value in np.array(k.value)]\n", "print(f\"The robust optimal values for the total cost using Budget uncertainty are {', '.join(formatted_values)}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## References\n", "\n", "1. Metzker, P., Thevenin, S., Adulyasak, Y., & Dolgui, A. (2023). Robust optimization for lot-sizing problems under yield uncertainty. https://doi.org/10.1016/j.cor.2022.106025" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.4" } }, "nbformat": 4, "nbformat_minor": 4 }