{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# TP2 - Modeling using docplex" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 1. The `docplex` python package\n", "\n", "`DOcplex` is a python package developped by IBM — It provides easy-to-use API for IBM solvers Cplex and Cpoptimizer.\n", "\n", "DOcplex documentation for mathematical programming can be found here: http://ibmdecisionoptimization.github.io/docplex-doc/#mathematical-programming-modeling-for-python-using-docplex-mp-docplex-mp" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 2. Solving TSP using `docplex`\n", "\n", "### 2.1. TSP model using `docplex`\n", "\n", "**Exercice:** Using `docplex`, create a model for the travelling salesman problem using the MTZ or Flow formulation and compare them." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from docplex.mp.model import Model\n", "import tsp.data as data\n", "\n", "distances = data.grid42\n", "N = len(distances)\n", "\n", "tsp = Model(\"TSP\")\n", "tsp.log_output = True\n", "\n", "... # TODO\n", "\n", "solution = tsp.solve()\n", "print(\"z* =\", solution.objective_value)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The largest set of distances contains 42 nodes, and should be easily solved by `docplex`.\n", "\n", "### 2.2. Generating random TSP instances\n", "\n", "**Question:** What method could you implement to generate a realistic set of distances for $n$ customers?\n", "\n", "**Exercice:** Implement the method proposed above and test it." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import scipy.spatial.distance\n", "\n", "\n", "def generate_distances(n: int):\n", " ... # TODO\n", "\n", "\n", "from docplex.mp.model import Model\n", "\n", "distances = generate_distances(50)\n", "print(distances)\n", "\n", "N = len(distances)\n", "\n", "tsp = Model(\"TSP\")\n", "tsp.log_output = True\n", "\n", "... # TODO: Copy your model from the first question here.\n", "\n", "solution = tsp.solve()\n", "print(\"z* =\", solution.objective_value)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 3. Solving Warehouse Allocation using Benders decomposition with `docplex`\n", "\n", "### 3.1. The warehouse problem\n", "\n", "A company needs to supply a set of $n$ clients and needs to open new warehouses (from a\n", "set of $m$ possible warehouses).\n", "Opening a warehouse $j$ costs $f_j$ and supplying a client $i$ from a warehouse $j$ costs $c_{ij}$ per supply unit.\n", "Which warehouses should be opened in order to satisfy all clients while minimizing the total cost?\n", "\n", "### 3.2. Solving the warehouse problem with a single ILP\n", "\n", "- $y_{j} = 1$ if and only if warehouse $j$ is opened.\n", "- $x_{ij}$ is the fraction supplied from warehouse $j$ to customer $i$.\n", "\n", "$\n", "\\begin{align}\n", " \\text{min.} \\quad & \\sum_{i=1}^{n} \\sum_{j=1}^{m} c_{ij} x_{ij} + \\sum_{j=1}^{m} f_{j} y_{j} & \\\\\n", " \\text{s.t.} \\quad & \\sum_{j=1}^{m} x_{ij} = 1, & \\forall i \\in\\{1,\\ldots,n\\}\\\\\n", " & x_{ij} \\leq y_{j}, & \\forall i\\in\\{1,\\ldots,n\\},\\forall j\\in\\{1,\\ldots,m\\}\\\\\n", " & y_{j} \\in \\left\\{0,~1\\right\\}, & \\forall j \\in \\left\\{1,~\\ldots,~m\\right\\}\\\\\n", " & x_{ij} \\geq 0, & \\forall i \\in \\left\\{1,~\\ldots,~n\\right\\}, \\forall j \\in \\left\\{1,~\\ldots,~m\\right\\}\n", "\\end{align}\n", "$\n", "\n", "\n", "**Exercice:** Implement the ILP model for the warehouse allocation problem and test it on the given instance." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from docplex.mp.model import Model\n", "\n", "# We will start with a small instances with 3 warehouses and 3 clients:\n", "N = 3\n", "M = 3\n", "\n", "# Opening and distribution costs:\n", "f = [20, 20, 20]\n", "c = [[15, 1, 2], [1, 16, 3], [4, 1, 17]]\n", "\n", "wa = Model(\"Warehouse Allocation\")\n", "wa.log_output = True\n", "\n", "... # TODO: Model for the warehouse allocation.\n", "\n", "solution = wa.solve()\n", "print(\"z* =\", solution.objective_value)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 3.3. Benders' decomposition for the Warehouse Allocation problem\n", "\n", "We are going to use Benders' decomposition to solve the Warehouse Allocation problem. \n", "\n", "#### Dual subproblem\n", "\n", "$\n", "\\begin{align*}\n", "\\text{max.} \\quad & \\sum_{i=1}^{n} v_{i} - \\sum_{i=1}^{n}\\sum_{j=1}^{m} \\bar{y}_{j} u_{ij} & \\\\\n", "\\text{s.t.} \\quad & v_{i} - u_{ij} \\leq c_{ij}, & \\forall i\\in\\{1,\\ldots,n\\},\\forall j\\in\\{1,\\ldots,m\\}\\\\\n", " & v_{i} \\in\\mathbb{R},\\ u_{ij} \\geq 0 & \\forall i \\in\\{1,\\ldots,n\\}, \\forall j\\in\\{1,\\ldots,m\\}\n", "\\end{align*}\n", "$\n", "\n", "#### Master problem\n", "\n", "$\n", "\\begin{align*}\n", " \\text{min.} \\quad & \\sum_{j=1}^{m} f_j y_j + z & \\\\\n", " \\text{s.t.} \\quad & z \\geq \\sum_{i=1}^{n}v_i^p - \\sum_{i=1}^{n} \\sum_{j=1}^{m} u_{ij}^p y_j, & \\forall p\\in l_1\\\\\n", " & 0 \\geq \\sum_{i=1}^{n}v_i^r - \\sum_{i=1}^{n} \\sum_{j=1}^{n} u_{ij}^r y_j, & \\forall r\\in l_2\\\\\n", " & y_{j} \\in\\{0,1\\}, & \\forall j\\in\\{1,\\ldots,m\\}\n", "\\end{align*}\n", "$" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Exercice:** Implement the method `create_master_problem` that creates the initial master problem (without feasibility or optimality constraints) for the warehouse allocation problem.\n", "\n", "