diff --git a/model.ipynb b/model.ipynb
index 147b9c1..516cec9 100644
--- a/model.ipynb
+++ b/model.ipynb
@@ -4,31 +4,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "# Lost Luggage Distribution Problem\n",
- "\n",
- "## Objective and Prerequisites\n",
- "\n",
- "In this example, you’ll learn how to use mathematical optimization to solve a vehicle routing problem with time windows, which involves helping a company figure out the minimum number of trucks required to deliver pieces of lost or delayed baggage to their rightful owners and determining the optimal assignment of trucks to customers.\n",
- "\n",
- "This model is example 27 from the fifth edition of Model Building in Mathematical Programming by H. Paul Williams on pages 287-289 and 343-344.\n",
- "\n",
- "This modeling example is at the advanced level, where we assume that you know Python and the Gurobi Python API and that you have advanced knowledge of building mathematical optimization models. Typically, the objective function and/or constraints of these examples are complex or require advanced features of the Gurobi Python API.\n",
- "\n",
- "**Download the Repository** \n",
- "You can download the repository containing this and other examples by clicking [here](https://github.com/Gurobi/modeling-examples/archive/master.zip). \n",
- "\n",
- "**Gurobi License** \n",
- "In order to run this Jupyter Notebook properly, you must have a Gurobi license. If you do not have one, you can request an [evaluation license](https://www.gurobi.com/downloads/request-an-evaluation-license/?utm_source=3PW&utm_medium=OT&utm_campaign=WW-MU-MUI-OR-O_LEA-PR_NO-Q3_FY20_WW_JPME_Lost_Luggage_Distribution_COM_EVAL_GitHub&utm_term=Lost%20Luggage%20Distribution&utm_content=C_JPM) as a *commercial user*, or download a [free license](https://www.gurobi.com/academia/academic-program-and-licenses/?utm_source=3PW&utm_medium=OT&utm_campaign=WW-MU-EDU-OR-O_LEA-PR_NO-Q3_FY20_WW_JPME_Lost_Luggage_Distribution_COM_EVAL_GitHub&utm_term=Lost%20Luggage%20Distribution&utm_content=C_JPM) as an *academic user*."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Problem Description\n",
- "\n",
- "A small company with six trucks has a contract with a number of airlines to pick up lost or delayed baggage, belonging to customers in the London area, from Heathrow airport at 6 p.m. each evening. The contract stipulates that each customer must have their baggage delivered by 8 p.m. The company requires a model to advise them what is the minimum number of trucks they need to use and to which customers each van should deliver and in what order. There is no practical capacity limitation on each van. Each van can hold all baggage that needs to be delivered in a two-hour period. To solve this problem, we can formulate an optimization model that minimizes the number of trucks that need to be used.\n",
- "\n"
+ "# Model"
]
},
{
@@ -81,11 +57,9 @@
"\n",
"**Depot**: Depot is visited by every truck used. \n",
"\n",
- "\n",
- "\n",
- "$$\\sum{y_{0k}}=K$$\n",
+ "\\begin{equation}\n",
+ "\\sum_{k \\in V} y_{0,k} \\geq \\sum_{k \\in V} z_k\n",
+ "\\end{equation}\n",
"\n",
"**Arriving at a location**: If location $j$ is visited by truck $k$, then the truck is coming from another location $i$.\n",
"\n",
@@ -113,8 +87,9 @@
"**Timeline**: keep track of time to avoid subtours via big $M$ and either-or\n",
"$$s_i+d_{ij}-s_j \\leq M(1-x_{ijk})$$\n",
"\n",
- "**max time contraint**:\n",
- "$$C_N = T_{max}$$"
+ "**max time contraint**: this is simplified at the moment, we are assuming each vehicle only takes 1 tour.\n",
+ "\n",
+ "$$C_0 = T_{max}$$"
]
},
{
@@ -128,7 +103,7 @@
},
{
"cell_type": "code",
- "execution_count": 1,
+ "execution_count": 138,
"metadata": {},
"outputs": [],
"source": [
@@ -138,6 +113,7 @@
"from itertools import permutations\n",
"import gurobipy as gp\n",
"from gurobipy import GRB\n",
+ "import matplotlib.pyplot as plt\n",
"\n",
"# tested with Python 3.7.0 & Gurobi 9.1.0"
]
@@ -152,18 +128,20 @@
},
{
"cell_type": "code",
- "execution_count": 2,
+ "execution_count": 139,
"metadata": {},
"outputs": [],
"source": [
"# number of locations, including the depot. The index of the depot is 0\n",
- "n = 17\n",
+ "n = 5\n",
"locations = [*range(n)]\n",
"\n",
"# number of trucks\n",
- "K = 6\n",
+ "K = 3\n",
"trucks = [*range(K)]\n",
"\n",
+ "\n",
+ "\n",
"# Create n random points\n",
"# Depot is located at (0,0) coordinates\n",
"random.seed(1)\n",
@@ -180,6 +158,38 @@
"M = 1000 #TODO: to be changes"
]
},
+ {
+ "cell_type": "code",
+ "execution_count": 140,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ ""
+ ]
+ },
+ "execution_count": 140,
+ "metadata": {},
+ "output_type": "execute_result"
+ },
+ {
+ "data": {
+ "image/png": "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",
+ "text/plain": [
+ "