{ "cells": [ { "cell_type": "markdown", "metadata": { "id": "P4JBokiOpGaW", "pycharm": {}, "tags": [ "CBC", "Machine_Shop", "GDP", "DIsjunctive_programming", "Scheduling" ] }, "source": [ "# Machine Bottleneck\n", "\n", "This notebook demonstrates the formulation and solution of the a machine bottleneck problem using Pyomo. The task is to schedule a set of jobs on a single machine given the release time, duration, and due time for each job. Date for the example problem is from Christelle Gueret, Christian Prins, Marc Sevaux, \"Applications of Optimization with Xpress-MP,\" Chapter 5, Dash Optimization, 2000." ] }, { "cell_type": "markdown", "metadata": { "id": "XAcD6ucWNWux" }, "source": [ "## Imports" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 598 }, "executionInfo": { "elapsed": 23847, "status": "ok", "timestamp": 1603385294032, "user": { "displayName": "Jeffrey Kantor", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14Gg_n8V7bVINy02QRuRgOoMo11Ri7NKU3OUKdC1bkQ=s64", "userId": "09038942003589296665" }, "user_tz": 240 }, "id": "ziXXmrrlplII", "outputId": "d8d3f604-60e1-4851-a668-2bac7a487961", "pycharm": {} }, "outputs": [], "source": [ "%matplotlib inline\n", "import matplotlib.pyplot as plt\n", "from IPython.display import display\n", "import pandas as pd\n", "\n", "import shutil\n", "import sys\n", "import os.path\n", "\n", "if not shutil.which(\"pyomo\"):\n", " !pip install -q pyomo\n", " assert(shutil.which(\"pyomo\"))\n", "\n", "if not (shutil.which(\"cbc\") or os.path.isfile(\"cbc\")):\n", " if \"google.colab\" in sys.modules:\n", " !apt-get install -y -qq coinor-cbc\n", " else:\n", " try:\n", " !conda install -c conda-forge coincbc \n", " except:\n", " pass\n", "\n", "assert(shutil.which(\"cbc\") or os.path.isfile(\"cbc\"))\n", "\n", "from pyomo.environ import *\n", "from pyomo.gdp import *" ] }, { "cell_type": "markdown", "metadata": { "id": "vMSeL4YrpGaa", "pycharm": {} }, "source": [ "## Example\n", "\n", "The problem is to schedule a sequence of jobs for a single machine. The data consists of a Python dictionary of jobs. Each job is labeled by a key, and an associated data dictionary provides the time at which the job is released to the for machine processing, the expected duration of the job, and the due date. The problem is to sequence the jobs on the machine to meet the due dates, or show that no such sequence is possible." ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 136 }, "executionInfo": { "elapsed": 20996, "status": "ok", "timestamp": 1603385294033, "user": { "displayName": "Jeffrey Kantor", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14Gg_n8V7bVINy02QRuRgOoMo11Ri7NKU3OUKdC1bkQ=s64", "userId": "09038942003589296665" }, "user_tz": 240 }, "id": "booOXANJpGac", "outputId": "b8ecc630-e77c-4126-fbe7-2f3b01e47e32", "pycharm": {} }, "outputs": [ { "data": { "text/plain": [ "{'A': {'release': 2, 'duration': 5, 'due': 10},\n", " 'B': {'release': 5, 'duration': 6, 'due': 21},\n", " 'C': {'release': 4, 'duration': 8, 'due': 15},\n", " 'D': {'release': 0, 'duration': 4, 'due': 10},\n", " 'E': {'release': 0, 'duration': 2, 'due': 5},\n", " 'F': {'release': 8, 'duration': 3, 'due': 15},\n", " 'G': {'release': 9, 'duration': 2, 'due': 22}}" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "JOBS = {\n", " 'A': {'release': 2, 'duration': 5, 'due': 10},\n", " 'B': {'release': 5, 'duration': 6, 'due': 21},\n", " 'C': {'release': 4, 'duration': 8, 'due': 15},\n", " 'D': {'release': 0, 'duration': 4, 'due': 10},\n", " 'E': {'release': 0, 'duration': 2, 'due': 5},\n", " 'F': {'release': 8, 'duration': 3, 'due': 15},\n", " 'G': {'release': 9, 'duration': 2, 'due': 22},\n", "}\n", "JOBS" ] }, { "cell_type": "markdown", "metadata": { "id": "PqufljBrpGam", "pycharm": {} }, "source": [ "### Gantt chart\n", "\n", "A traditional means of visualizing scheduling data in the form of a Gantt chart. The next cell presents a function `gantt` that plots a Gantt chart given JOBS and SCHEDULE information. Two charts are presented showing job schedule and machine schedule. If no machine information is contained in SCHEDULE, then it assumed to be a single machine operation." ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 344 }, "executionInfo": { "elapsed": 6881, "status": "ok", "timestamp": 1603385294403, "user": { "displayName": "Jeffrey Kantor", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14Gg_n8V7bVINy02QRuRgOoMo11Ri7NKU3OUKdC1bkQ=s64", "userId": "09038942003589296665" }, "user_tz": 240 }, "id": "PmlDAe6upGan", "outputId": "7420432f-1567-4acb-f4de-1ad7518c523f", "pycharm": {} }, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "def gantt(JOBS, SCHEDULE={}):\n", " bw = 0.3\n", " plt.figure(figsize=(12, 0.7*(len(JOBS.keys()))))\n", " idx = 0\n", " for j in sorted(JOBS.keys()):\n", " x = JOBS[j]['release']\n", " y = JOBS[j]['due']\n", " plt.fill_between([x,y],[idx-bw,idx-bw],[idx+bw,idx+bw], color='cyan', alpha=0.6)\n", " if j in SCHEDULE.keys():\n", " x = SCHEDULE[j]['start']\n", " y = SCHEDULE[j]['finish']\n", " plt.fill_between([x,y],[idx-bw,idx-bw],[idx+bw,idx+bw], color='red', alpha=0.5)\n", " plt.plot([x,y,y,x,x], [idx-bw,idx-bw,idx+bw,idx+bw,idx-bw],color='k')\n", " plt.text((SCHEDULE[j]['start'] + SCHEDULE[j]['finish'])/2.0,idx,\n", " 'Job ' + j, color='white', weight='bold',\n", " horizontalalignment='center', verticalalignment='center')\n", " idx += 1\n", "\n", " plt.ylim(-0.5, idx-0.5)\n", " plt.title('Job Schedule')\n", " plt.xlabel('Time')\n", " plt.ylabel('Jobs')\n", " plt.yticks(range(len(JOBS)), JOBS.keys())\n", " plt.grid()\n", " xlim = plt.xlim()\n", " \n", " if SCHEDULE:\n", " for j in SCHEDULE.keys():\n", " if 'machine' not in SCHEDULE[j].keys():\n", " SCHEDULE[j]['machine'] = 1\n", " MACHINES = sorted(set([SCHEDULE[j]['machine'] for j in SCHEDULE.keys()]))\n", "\n", " plt.figure(figsize=(12, 0.7*len(MACHINES)))\n", " for j in sorted(SCHEDULE.keys()):\n", " idx = MACHINES.index(SCHEDULE[j]['machine'])\n", " x = SCHEDULE[j]['start']\n", " y = SCHEDULE[j]['finish']\n", " plt.fill_between([x,y],[idx-bw,idx-bw],[idx+bw,idx+bw], color='red', alpha=0.5)\n", " plt.plot([x,y,y,x,x], [idx-bw,idx-bw,idx+bw,idx+bw,idx-bw],color='k')\n", " plt.text((SCHEDULE[j]['start'] + SCHEDULE[j]['finish'])/2.0,idx,\n", " 'Job ' + j, color='white', weight='bold',\n", " horizontalalignment='center', verticalalignment='center')\n", " plt.xlim(xlim)\n", " plt.ylim(-0.5, len(MACHINES)-0.5)\n", " plt.title('Machine Schedule')\n", " plt.yticks(range(len(MACHINES)), MACHINES)\n", " plt.ylabel('Machines')\n", " plt.grid()\n", "\n", "gantt(JOBS)" ] }, { "cell_type": "markdown", "metadata": { "id": "FQiyELEmpGai", "pycharm": {} }, "source": [ "## The machine scheduling problem\n", "\n", "A schedule consists of a dictionary listing the start and finish times for each job. Once the order of jobs has been determined, the start time can be no earlier than when the job is released for processing, and no earlier than the finish of the previous job.\n", "\n", "The following cell presents a function which, given the JOBS data and an order list of jobs indices, computes the start and finish times for all jobs on a single machine. We use this to determine the schedule if the jobs are executed in alphabetical order." ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 136 }, "executionInfo": { "elapsed": 5405, "status": "ok", "timestamp": 1603385294404, "user": { "displayName": "Jeffrey Kantor", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14Gg_n8V7bVINy02QRuRgOoMo11Ri7NKU3OUKdC1bkQ=s64", "userId": "09038942003589296665" }, "user_tz": 240 }, "id": "YAIW7XIspGaj", "outputId": "69075a3e-a28d-4a70-d7e7-27dc05b52ec7", "pycharm": {} }, "outputs": [ { "data": { "text/plain": [ "{'A': {'start': 2, 'finish': 7},\n", " 'B': {'start': 7, 'finish': 13},\n", " 'C': {'start': 13, 'finish': 21},\n", " 'D': {'start': 21, 'finish': 25},\n", " 'E': {'start': 25, 'finish': 27},\n", " 'F': {'start': 27, 'finish': 30},\n", " 'G': {'start': 30, 'finish': 32}}" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def schedule(JOBS, order=sorted(JOBS.keys())):\n", " \"\"\"Schedule a dictionary of JOBS on a single machine in a specified order.\"\"\"\n", " start = 0\n", " finish = 0\n", " SCHEDULE = {}\n", " for job in order:\n", " start = max(JOBS[job]['release'], finish)\n", " finish = start + JOBS[job]['duration']\n", " SCHEDULE[job] = {'start': start, 'finish': finish}\n", " return SCHEDULE \n", "\n", "SCHEDULE = schedule(JOBS)\n", "SCHEDULE" ] }, { "cell_type": "markdown", "metadata": { "id": "1TG6LgB2NWvC" }, "source": [ "Here we demonstrate a 'partial schedule'." ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 429 }, "executionInfo": { "elapsed": 3871, "status": "ok", "timestamp": 1603385294719, "user": { "displayName": "Jeffrey Kantor", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14Gg_n8V7bVINy02QRuRgOoMo11Ri7NKU3OUKdC1bkQ=s64", "userId": "09038942003589296665" }, "user_tz": 240 }, "id": "nOA_XMvoNWvC", "outputId": "ac857c77-0b8f-45d4-a732-df9e1979991e" }, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "gantt(JOBS, schedule(JOBS, ['E', 'D', 'A', 'C', 'B']))" ] }, { "cell_type": "markdown", "metadata": { "id": "vnjkfEQINWvG" }, "source": [ "Here's a schedule where jobs are done in alphabetical order." ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 429 }, "executionInfo": { "elapsed": 1482, "status": "ok", "timestamp": 1603385299636, "user": { "displayName": "Jeffrey Kantor", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14Gg_n8V7bVINy02QRuRgOoMo11Ri7NKU3OUKdC1bkQ=s64", "userId": "09038942003589296665" }, "user_tz": 240 }, "id": "zSVHLsSTNWvH", "outputId": "097e58af-6e19-4c59-88fc-80c3cb7e12ca" }, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAsgAAAFHCAYAAAC8pbrmAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/YYfK9AAAACXBIWXMAAAsTAAALEwEAmpwYAAArxElEQVR4nO3df5RV533f+/eXYUbDIIkjgwT6gRhkMURmGo2tkW8I+jFxFMeK7VoWqirT2zppb6hum3utddeK7birKzi3SZQ2brWSlvqOGxe7DXZzYxtJDiWOrRx+XcsSkpAVZEACRsjGA0ZoBAOMQDPP/WMfxIbhx4DmnH1m5v1a66w5Z599nud7Hm/NfPzw7L0jpYQkSZKkzKSiC5AkSZLqiQFZkiRJyjEgS5IkSTkGZEmSJCnHgCxJkiTlGJAlSZKkHAOyJFVJRKSIuLHKfSyLiP8+Sm11RcSPR3tfSRprDMiSdIEiohwR/9sot1mKiC9HRG9EHIqI7RHxmdHsQ5I0MpOLLkCSBMB/AKYCNwFvAG1Ae6EVSdIE5QyyJL0DEfGbEfFyRByIiMci4prTdvm1iNgZEfsj4t9FxNl+794KrEwpvZ5SGkopbU0p/WWunwUR8TeVfvZGxOdyn22KiK9WZp63RERn7nPXRMQ3IuJnEbErIv7P3HtTImJFRLweES9Wash/t1OWiFT2/TdnGYez9iNJY40BWZIuUkR8APhD4H7gauAV4Oun7fZxoBN4H/Ax4J+epbkngd+PiN+IiHmn9XMZ8F1gDXANcCPwvdwuf7/Sbwl4DPiPlc9NAh4HngeuBX4ZeCgifrXyud8F3l15/CrwyRF/+VPrO18/kjSmGJAl6eL9I+DLKaVnU0pvAr8DLIyI1tw+f5RSOpBS2g08AnziLG39H8CfA78FvFiZlb678t5HgN6U0hdSSgMppUMppR/kPrshpbQ6pTQI/Dfg5sr2W4ErU0q/l1I6llLaCXwJeKDy/v3A71fqexX4k4sch/P1I0ljimuQJeniXQM8e+JFSqk/Il4jm0XtqWx+Nbf/K5XPDJNSOgr8AfAHEXE58Fng/42I64HZwI5z1NGbe34EaI6IycAc4JqI6Mu93wCsz9V/en0X43z9SNKY4gyyJF28PWThEICImApMB36S22d27vn1lc+cU0rpIFlYngrMJQux776I+l4FdqWUSrnHZSmlX6u8/9Mz1Jd3BGjJvZ51kf1I0phiQJaki7cS+I2I6IiIS8hC7Q9SSj25fX47Iq6IiNnAp4D/caaGIuJfR8StEdEUEc2VffuAbcC3gVkR8VBEXBIRl0XE/zKC+p4CDkbEZyon5DVERHtEnDgZ7y+A36nUdx3ZMo+8zcCSyuc+BNx5kf1I0phiQJaki5NSSt8D/jXwDbLZ2HczfN3to8AzZGHzr4A/O1t7wH8F9pPNMv8K8OGUUn9K6VDl9UfJllO8BPzSCAocrHymA9hVafu/ANMqu3yebFnFLuA7ZOuX8z5V+Xwf2XrrVRfZjySNKZFSKroGSRpTIuJZ4PdSSquKrkWSNPqcQZakCxARC8hu5vFc0bVIkqrDgCxJIxQRf0S2FOEzKaWLveKDJKnOucRCkiRJynEGWZIkScqpuxuFzJgxI7W2tta838OHDzN16tSa96uM418cx744jn1xHPviOPbFceyHe+aZZ/anlK48fXvdBeTW1lY2bdpU837L5TJdXV0171cZx784jn1xHPviOPbFceyL49gPFxFnPJ/EJRaSJElSjgFZkiRJyjEgS5IkSTkGZEmSJCnHgCxJkiTl1N1VLCRJkjS6uru7Wb58OaVSqehShlmyZAlLly4tuoxTGJClMejXgd5Ramsx8PAotaUL49gXp17HfhawougiNC6tXLmSl196ic7LLiu6lFNsPnAAdu40IEt653qBOaPU1iWj2JYujGNfnHod+zNekFUaJTfOnk35gQeKLuMUXStWwMBA0WUM4xpkSZIkKceALEmSJOUYkCVJkqQcA7IkSZKUY0CWJEmScryKhSRJ0kS2bBns2wfLl599n3vugY4O6O6GPXvO32ZnJ9x6K0yfDsePw89+Bn/7t7Br1ygVXV1VnUGOiJkRsTIidkbEMxHx/Yj4eDX7lCRJUoG6uuAjH4GmJvje97JgfPQoXHdd0ZWNWNVmkCMigFXAV1JKSyrb5gB/v1p9SpIk6SI1NMBdd0F7OzQ2Qk8PrF4NBw+e3Ke9He6/H1KCxx4bPiPc2AiLFsFbb8GKFfDGG9n2p57K3hsjqjmD/AHgWErpiyc2pJReSSn9aRX7lCRJ0sW44w5YuBB27IANG6CtDRYvPnWfa6+FjRuhpQXuvTcL1XlXXZUF4f37s3Acke3b0gKTxs6pb9Vcg7wAeHYkO0bEUmApwMyZMymXy1Us68z6+/sL6VcZx//CLCa7E9homNrfzyLHvhCOfXHqdew7gXLRRVSZv++L0dfXx2BDA+X584e91wUcbmpiqL2dS4eGWLdtG2loiPe+9hrT5sxh/YIFzLv8cmYBm3fsoO/gQX5uzx5mzZ3L052dHO7re7uty971Lm4BDl1yCc/Mn8+lpRKdd9+d1bB3L5ufeOLUulpaoLm57o6Jmp2kFxH/CbiNbFb51vx7KaVuoBugs7MzdXV11aqst5XLZYroVxnH/8I8zOjdJndRucxGx74Qjn1x6nXsXwHWFF1Elfn7vhilUom+3l66tm074/tTjx3LlkUAd27fDoOD2VIJ4PaXXoJ58wDoePXVbFnFggUA3NrTA3v3nmyosRE+8AEuu+wyuvbsyfY9eBD+4T+kdPTosP5LR47AwEDdHRPVnOveArzvxIuU0r8Efhm4sop9SpIk6WJs354tg/jIR7JwfN112TrkY8dO7nPnndnVKebPh0OHsqUUecePZ0swJk+GT34yu/LFtGm1/BajopozyE8AfxAR/3tK6T9XtrVUsT9JkiRdiClTsp8DA7B+PTQ3Z7PDN92UBebVq0/df/duuO227KoUjz6azTSfrlyGw4fh/e+HD34Q3nwzm0netKnqX2e0VC0gp5RSRNwD/IeI+DTwM+Aw8Jlq9SlJkqQRmjs3uyQbZMF3cBDWrMkep1u1KnsAnLaO+Iyefjp7jFFVXYOcUvop8EA1+5AkSdJFuP56mDEDnnsO1q0rupq64p30JEmSJqK1a7OHhhk7F6STJEmSasCALEmSJOUYkCVJkqQcA7IkSZKU40l6kiRJ49zaysl4XStWFFvIaTb39tJRKhVdxjAGZGkMmkV2S9rR0DmKbenCOPbFqdexn1V0ARr/BgaKruAUHaUSSzo6ii5jGAOyNAatGMW2ysAZLgmvGijj2BeljGOviSWlRLlcpuvEjUF0Tq5BliRJknIMyJIkSVKOAVmSJEnKMSBLkiRJOQZkSZIkKceALEmSJOUYkCVJkqQcA7IkSZKUY0CWJEmScgzIkiRJUo4BWZIkScoxIEuSJEk5k4suQJIkqUjd3d2sXLmy6DKq7pZbbqGrq6voMsYEA7JUI78O9BZdxBksBh4uuogJ6oGiC5AEwMqVK9n85JN0lEpFl1I1mw8coG/vXvjCF4ouZUwwIEs10gvMKbqIM7iE+qxrIjhedAGS3tZRKlF+8MGiy6iarhUr6Eup6DLGDNcgS5IkSTkGZEmSJCnHgCxJkiTlGJAlSZKkHAOyJEmSlONVLCRJkt6pZctg3z5Yvvzs+9xzD3R0QHc37Nlz7vYeeghOv+zcF78IvfV4wdDxp+oBOSIGgRdym+5JKfVUu19JkqQx7a23YNWqk6/7+oqqZMKpxQzy0ZRSRw36kSRJKlZDA9x1F7S3Q2Mj9PTA6tVw8ODJfdrb4f77ISV47DHYtevMbQ0Nwc6dJ18PDFS1dJ3kGmRJkqTRcscdsHAh7NgBGzZAWxssXnzqPtdeCxs3QksL3HtvFqrPpKkJPv3pkw/VTC1mkKdExObK810ppY/XoE9JkqTamzcvm/l9/HEYHMwC8pw5Wdg9oVzOZo2vuw5uvhlmzIC9e4e3dfw4fO1rNStdJ9XFEouIWAosBZg5cyblcrkGZZ2qv7+/kH6VmQjjv5jsts71Zmp/P4vG+djXq5YJcNzXq4nwO6de1ePY9/X1QalEef78i26jCzjc1MRQQwOXAuva2khDQ7x3yhSmAevnzWPe5ZczC9g8ezZ9TU3cNG0aM4GnW1s5fNoJeb8weTKNwPrGxpMb30F9fS0tDEbU3djXq7q4ikVKqRvoBujs7ExdXV01r6FcLlNEv8pMhPF/GJhTdBFnsKhcZuM4H/t61Vkuc59jX4iJ8DunXtXj2JdKJdi6la5t295RO1OPHYMXX4SuLu5sa4P9+2H6dOjp4fYtW7LZZaDjhhvg6FG4+mo4dIhbN23KZpvz7r4bmprecU0nlI4coa+5ue7Gvl7VRUCWJEkas6ZMyX4ODMD69dDcDAsWwE03wfbt2Ul6ebt3w223ZSH50UeHh2MVzoAsSZJ0sebOhROzsrt3Z2F3zZrscbpVq05etu2JJ87d7iOPjF6NumBVv4pFSunSavchSZJUiOuvz06ye+45WLeu6Go0SpxBliRJulhr12YPjSteB1mSJEnKMSBLkiRJOQZkSZIkKceALEmSJOV4kp4kSZrQ1lZOsutasaLYQqpoc28vra2tRZcxZhiQpRqZBbxSdBFn0El91jURLCy6AEmnGhgouoKq6SiVuGXRoqLLGDMMyFKNrCi6gLMoA2e4nL1qoFx0AZIASCkVXUJNlMvloksYM1yDLEmSJOUYkCVJkqQcA7IkSZKUY0CWJEmScgzIkiRJUo4BWZIkScoxIEuSJEk5BmRJkiQpx4AsSZIk5RiQJUmSpBwDsiRJkpRjQJYkSZJyJhddgCRJmhi6u7tZvnw5pVKp6FKGWbJkCUuXLi26DNUJA3JFD/ChoouYwB4ougBJUtWtXLmSl196ic7LLiu6lFNsPnAAdu40IOttBuSK48CcoouYwI4XXYAkqSZunD2b8gP1NS3StWIFDAwUXYbqiGuQJUmSpBwDsiRJkpRjQJYkSZJyDMiSJElSjgFZkiRJyvEqFpIkqXjLlsG+fbB8+dn3uece6OiA7m7Ys+fc7T30EJx+veUvfhF6e99RmZoYqh6QI2IQeCG36esppYer3a8kSZrg3noLVq06+bqvr6hKNMbUYgb5aEqpowb9SJKksa6hAe66C9rbobERenpg9Wo4ePDkPu3tcP/9kBI89hjs2nXmtoaGYOfOk6+91rFGyDXIkiSpftxxByxcCDt2wIYN0NYGixefus+118LGjdDSAvfem4XqM2lqgk9/+uRDGqFazCBPiYjNudd/mFL6HzXoV5IkjTXz5mUzv48/DoODWUCeMycLuyeUy9ms8XXXwc03w4wZsHfv8LaOH4evfa1mpWv8qIslFhGxFFgKMHPmTMrlcg3KOtUV/f0sKqBfZVr6+wv5313Q79gXxrEvjmNfjL6+PgYbGijPnz/svS7gcFMTQw0NXAqsa2sjDQ3x3ilTmAasnzePeZdfzixg8+zZ9DU1cdO0acwEnm5t5fBpJ+T9wuTJNALrGxtPbjxDvwB9LS3Q3DzujwmP+5Gri6tYpJS6gW6Azs7O1NXVVfMavlQus6mAfpXpLJe5z/EvRLlcpoj/5uTYF8mxL0apVKKvt5eubdvO+P7UY8fgxRehq4s729pg/36YPh16erh9y5ZsdhnouOEGOHoUrr4aDh3i1k2bstnmvLvvhuZmuvIB+ZVX4NCh4XUdOQIDA+P+mPC4H7m6CMiSJGkCmzIl+zkwAOvXQ3MzLFgAN90E27dnJ+nl7d4Nt92WheRHHx0ejk+YPBnuu+/k669/HbZurc530LhSxBrkNSmlz9agX0mSVO/mzoUTs5q7d2dhd82a7HG6VatOXrbtiSfO3e4jj4xejZpwqh6QU0pnObVUkiRNeNdfn51k99xzsG5d0dVIgEssJElSkdauzR5SHfE6yJIkSVKOAVmSJEnKMSBLkiRJOQZkSZIkKceT9CRJUk2srZyM17ViRbGFnGZzby8dp92JTxObAbmiEXil6CImsIVFFyBJqp2BgaIrOEVHqcSSjo6iy1AdMSBXtAJnuCS5aqRcdAGSpKpLKXm7Y40JrkGWJEmScgzIkiRJUo4BWZIkScoxIEuSJEk5BmRJkiQpx4AsSZIk5RiQJUmSpBwDsiRJkpRjQJYkSZJyDMiSJElSjgFZkiRJyjEgS5IkSTmTiy5AkqSxqru7m5UrVxZdxphyyy230NXVVXQZ0jkZkCt6gA8VXcQEthh4uOgiJqgHii5AGsNWrlzJ5iefpKNUKrqUMWHzgQP07d0LX/hC0aVI52RArjgOzCm6iAnsEhz/ohwvugBpjOsolSg/+GDRZYwJXStW0JdS0WVI5+UaZEmSJCnHgCxJkiTlnDcgR8SnIuLyyPxZRDwbER+sRXGSJElSrY1kBvmfppQOAh8ErgR+A8+nkiRJ0jg1koAclZ+/BvzXlNLzuW2SJEnSuDKSq1g8ExHfAeYCvxMRlwFD1S1LkiS9bdky2LcPli8/+z733AMdHdDdDXv2nLu9hx6CUgkGB2FgAHp7Yf166OkZrYqlMW0kM8j/DPgscGtK6QjQRLbM4pwiYjAiNkfEloh4PiL+r4jwpEBJkurBW2/BqlXw7LMwezb8k38Cc+cWXZVUF847g5xSGoqIVuB/jYgEbEgpfWsEbR9NKXUARMRVwEpgGvC7F1+uJEkTWEMD3HUXtLdDY2M247t6NRw8eHKf9na4/35ICR57DHbtOnNbQ0PwwgvZ8337YPFiuP32s+8vTSAjuYrFcuBB4AXg74B/HhH/6UI6SSntA5YCvxURrl+WJOli3HEHLFwIO3bAhg3Q1pYF27xrr4WNG6GlBe69NwvV5/PSS9nPWbNGv2ZpDBrJGuQ7gfaUslvfRMRXyMLyBUkp7awssbgK2Huhn5ckacKbNy+b+X388Wz9cFsbzJkDTU0n9ymXs1ng666Dm2+GGTNg73n+7J6Yu/IudxIwsoC8DbgeeKXyejbww4vs74yzxxGxlGyGmZkzZ1Iuly+y+Yt3RX8/iwroV5mpjn9hWvr7C/lvTtDv2BdmtMa+r68PSiXK8+e/47bOpQs43NTEUEMDlwLr2tpIQ0O8d8oUpgHr581j3uWXMwvYPHs2fU1N3DRtGjOBp1tbOVwqndLeL0yeTGME6yt1XzVnDu8BXj90iOer+F36WloYjPC4L4i/c0burAE5Ih4HEtm64R9FxFOVt94P/H8X2lFE3AAMAvtOfy+l1A10A3R2dqaurq4Lbf4d+1K5zKYC+lVmUbnMRse/EJ3lMvc59oUol8sU8ftOozf2pVIJtm6la9u2d9zW+Uw9dgxefBG6urizrQ3274fp06Gnh9u3bMlml4GOG26Ao0fh6qvh0CFu3bQpm23Ou/tuaG6mq6kJrrwSOjthaIgr/vqv6ariGuTSkSP0NTd73BfE3zkjd64Z5D8erU4i4krgi8B/PLFUQ5IkjcCUKdnPgYHsUmzNzbBgAdx0E2zfnp2kl7d7N9x2WxaSH310eDg+YfLk7NJwAwPw6quwbh288sqZ95UmmLMG5JTS2hPPI2ImcGvl5VOVk+7OZ0pEbAYagbeA/wb8+4svVZKkCWbuXDgx47d7dxZ216zJHqdbtSp7ADzxxLnbfeSR0atRGofOuwY5Iu4H/h1QJltD/KcR8dsppb881+dSSiM4bVaSJJ3V9ddnJ9k991w2wyupJkZykt6/IrtJyD54e7nEd4FzBmRJkvQOrV2bPSTV1EjubDfptCUVr43wc5IkSdKYM5IZ5DUR8dfA1yqvHwD+Z/VKkiRJkoozkltN/3ZE3AssIluD/MWU0qpqFyZJkiQV4VzXQT5Edh1kOPUGH78ZEQPADuBfpZS+V8X6JEmSpJo612XeLjvbexHRALQDf175KUnShLO2cgJd14oVxRYyRmzu7aW1tbXoMqTzGska5GFSSoPA8xHxp6NcT2EaOXkvbdVeJ45/URYWXYA0HgwMFF3BmNBRKnHLokVFlyGd10UF5BNSSv/PaBVStFbgDJddV42UcfyLUi66AGkM8+awF65cLhddgnReXq5NkiRJyjEgS5IkSTkGZEmSJCnHgCxJkiTlGJAlSZKkHAOyJEmSlGNAliRJknIMyJIkSVKOAVmSJEnKMSBLkiRJOQZkSZIkKceALEmSJOVMLroASaqm7u5uVq5cWXQZZ9TX10epVCq6jAlpNMd+yZIlLF26dFTaklQfDMi6KL8O9I5ie4uBh0exPY3ceB/7p1au5M0nn+TGOgyiQ6USbN1adBkT0yiN/eYDB2DnTgOyNM4YkHVReoE5o9jeJaPcnkZuvI/9D4HWUonPP/hg0aUMc3z+fO7dtq3oMiak8vz5dI3C2HetWAEDA++8IEl1xTXIkiRJUo4BWZIkScoxIEuSJEk5BmRJkiQpx4AsSZIk5XgVC0kaz5Ytg337YPnys+9zzz3Q0QHd3bBnz/nbvPVWeP/74Yor4OhR2LYNvv3tUSpYkopX9RnkiJgVEV+PiB0R8WJErI6Itmr3K0mqgq4u+PCHYdIk+M534Pvfh5kzi65KkkZVVWeQIyKAbwFfSSk9UNnWAcwEtlezb0lSTkMD3HUXtLdDYyP09MDq1XDw4Ml92tvh/vshJXjsMdi169Q2Ghth0SJ46y346lfhjTey7d//fs2+hiTVQrVnkH8JOJ5S+uKJDSmlzSml9VXuV5KUd8cdsHAh7NgBGzZAWxssXnzqPtdeCxs3QksL3HtvFqrzrroqC8n7958Mx5AFakkaR6q9BrkdeKbKfUiSzmfePBgagscfh8HBLCDPmQNNTSf3KZezWePrroObb4YZM2Dv3uFtGYgljXN1cZJeRCwFlgLMnDmTcrlc8xr6+/sL6XesWkx2i+LRMrW/n0WOfyHG+9iv6+vjeKnE0Pz5RZcyzKRLLqFc5bq6gMNNTQw1NHApsK6tjTQ0xHunTGEasH7ePOZdfjmzgM2zZ9PX1MRN06YxE3i6tZXDpdLJehsaWPTWW8RVV/GDjg7ePHq0qrVXU/8ojX1fSws0N/v34wL497Y4jv3IVTsgbwHuO99OKaVuoBugs7MzdXV1Vbms4crlMkX0O1Y9DMwZxfYWlctsdPwLMd7H/o1SiVlbtzJp27aiSxnm+Pz5dNWgrqnHjsGLL0JXF3e2tWVLJKZPh54ebt+yJZtdBjpuuCG7KsXVV8OhQ9y6aVM225x31VXQ1cXC226DH/wAJk+Gm26CL3+56t9jNJVHaexLR47AwIB/Py6Af2+L49iPXLUD8hPAH0TEb6aUvgQQEbcCLSmltVXuW5ImtilTsp8DA7B+PTQ3w4IFWaDdvj07SS9v92647bYsJD/66PBwDNkyjCNHsku9fehDJy/zJknjSFUDckopRcTHgUci4rPAANADPFTNfiVpwps7N7skG2TBd3AQ1qzJHqdbtSp7ADzxxPnbfuqp7CFJ41TV1yCnlPYA91e7H0lSzvXXZyfZPfccrFtXdDWSNKbUxUl6kqRRtnZt9pAkXbCq30lPkiRJGksMyJIkSVKOAVmSJEnKMSBLkiRJOZ6kJ2lc++natfwU+NyKFUWXMkxqaeFPjhwpuowJqa+lJbvJxzu0ubeXjtzdBiWNDwZkXZRZwCuj2F7nKLenkZsoYz9pYKDoEoYZam7ObuKh2hulse8olVjS0fHO65FUVwzIuigrRrm9MnCG2xeoBsqM87FPqegKzsrbvhbHsZd0Lq5BliRJknIMyJIkSVKOAVmSJEnKMSBLkiRJOQZkSZIkKceALEmSJOUYkCVJkqQcA7IkSZKUY0CWJEmScgzIkiRJUo4BWZIkScoxIEuSJEk5k4suQKpX3d3drFy5sugyqq6vr49SqVR0GVW1ZMkSli5dWnQZkqQxwoCsutADfKjoIk7z1MqVvPnkk9w4zsPjUKnE61u3Fl1G1ew4cIB9O3fyzToMyIuBh4suYoIazbGfBawYpbYk1QcDsurCcWBO0UWc5odAa6nE5x98sOhSqmpo/nwmbdtWdBlV87kVK2gcGKi74wvgEurvuJ8oRnPsXxmldiTVD9cgS5IkSTkGZEmSJCnHgCxJkiTlGJAlSZKkHAOyJEmSlONVLKRx5KPLlnFw3z7WLl9+1n067rmH2R0drOvu5o09e87Z3i8/9BAtlcvcHR8Y4I3eXl74q7+i/2c/G82yJUmqK1WdQY6IwYjYHBHPR8SzEfGL1exP0ugbfOstnvnLv+SVZ55hRmsr7/mVXym6JEmSqqraM8hHU0odABHxq8AfAndWuU9pwpvU0MBNd93FNe3tNDQ28lpPDy+sXs3AwYNv73Ntezud999PmjyZHx47xv5du87YVhoaYv/OnRw/epQbFy0iJrkyS5I0vtXyL93lwOs17E+asObdcQc3LFzIz3bs4OUNG5jZ1sb7Fi8+ZZ/StdeyY+NGmi65hPfeey+TGhrO2NbkpiZ+9dOf5hf+8T9maGiIl9evr8VXkCSpMNUOyFMqSyy2Av8F+L+r3J8k4Kp580hDQ/zw8cd5ecMGXv/xj5k+Zw4NTU1v77O9XKbn6afp/fGPab7sMqbOmHHGtgaPH+f7X/0qz33rW6TBQdp+6Zdq9TUkSSpELZdYLAS+GhHtKaWU3ykilgJLAWbOnEm5XK5yWcP19/cX0q8yV/T3s6jOxn9dXx/HSyWG5s8vupQL09QEldngobY2hoaGSFOmZK/nzSNdfnn2fPZshnL7ptZWhion5L1t8mQSsK+xEQYGaH3jDWa0thLveQ+Dg4O1+kbvSGpp4Xhzc90dXwBT6/C4nyhGc+w7gdFpaWLw721xHPuRq9lVLFJK34+IGcCVwL7T3usGugE6OztTV1dXrcp6W7lcpoh+lflSucymOhv/N0olZm3dyqRt24ou5cIcO8beF1+k1NXFzW1t9O/fz7umT+e1nh7Sli3EvHkA/NwNN7Dn6FFmXX01A4cOcWTTJiadHnrvvptobua6xkaaL7uMaVdcwZv9/aQXXxwz14iMI0doHBhgY50dXwCLyuW6rGsiGM2xfwVYMyotTQz+vS2OYz9yNQvIEfFzQAPwWq36lCaSxsos8VsDA7y8fj2Nzc1cs2ABV990E3u3b+eF1atP2f/A7t3ceNttHH/zTZ7/5jcZOsuMcMPkydxy330MHj/OoX372PKd71T9u0iSVKRqB+QpEbG58jyAT6aUxsa/y0pjyPS5c5lfmRV4bfduhgYH2bJmDVvWDJ/X2rxqFZtXrQJg6xNPMDR/PpPOcgWL7z3ySJUqliSpflU1IKeUznxavKRRNf3667l0xgx2P/ccL61bV3Q5kiSNad5JTxoHtq9dy/a1a4suQ5KkcWGsnGcjSZIk1YQBWZIkScoxIEuSJEk5BmRJkiQpx5P0pLP46dq1/BT43IoVRZdSVamlhThypOgyqmZXby9tp98hUJKkczAgqy40kt2Nqh5NGhgouoSqGmpuHtff8d2lErd0dNTl8dVJ/R73491ojv2sUWpHUv0wIKsutFKHt2pNqegKasJbjxanTB0e9xNEGcde0tm5BlmSJEnKMSBLkiRJOQZkSZIkKceALEmSJOUYkCVJkqQcA7IkSZKUY0CWJEmScgzIkiRJUo4BWZIkScoxIEuSJEk5BmRJkiQpx4AsSZIk5UwuugCdXXd3NytXriy6jJro6+ujVCoVXcYwS5YsYenSpUWXIUmSasiAXMdWrlzJpief5N11GBxH21CpxOtbtxZdxil2HDjAvp07+eY4D8gPFF2AJEl1xoBc595dKvFvHnyw6DKqbmj+fCZt21Z0Gaf43IoVNA4MMKfoQqrseNEFSJJUZ1yDLEmSJOUYkCVJkqQcA7IkSZKUY0CWJEmScgzIkiRJUo4BWZIkScoxIGvEPrpsGXf+i39xzn067rmHjy5bxrRrrhlRm5deeSUfXbaMj33iE1x/yy2jUaYkSdI7UvWAHBEfj4gUET9X7b409lzb3g5AGhrimgULCq5GkiSpNjcK+QSwgeyGXctq0J+qbFJDAzfddRfXtLfT0NjIaz09vLB6NQMHD769z7Xt7XTefz+kxPOPPcb+XbvO2NY1CxZw9OBBXnv9da5pbaVp6lSOHT5cq68iSZI0TFVnkCPiUmAR8M/wjrbjxrw77uCGhQv52Y4dvLxhAzPb2njf4sWn7FO69lp2bNxIY0sL7733XiY1NAxr5/KZM7l0xgx++qMfsWf3biZNmsTV73lPrb6GJEnSGVV7BvkeYE1KaXtEHIiI96WUnj19p4hYCiwFmDlzJuVyucplDdff319Iv+fS19fHUKnE0Pz5RZdyUlMTV7W3k4aG2LxtG0NDQ1z12mtMnzOHWLCAdPnlAGzdsYP9Bw9S2rOH2XPn0tLZycG+vlOauvrnfx6A1wcH6R8YYHBwkGs6O9mVm4kuUmpp4XhzM4vq7LgYbS11eOxPFPX4e2eicOyL49gXx7EfuWoH5E8Aj1Sef73yelhATil1A90AnZ2dqaurq8plDVculymi33MplUq8vnUrk7ZtK7qUk44dg7feAmDS9u0wOEgsWpS9fuklYt687PmrrzJp1y6isq44enqYtHfvKU1d88EPAnDLL/7i29umX3klU37yE97s76/6VzmfOHKExoEBNtbZcTHaOstl7hvn37Fe1ePvnYnCsS+OY18cx37kqhaQI2I68AGgPSIS0ACkiPh0SilVq19V397t2yldcw1/7yMfoX//fq647jpe6+lh8Nixt/dpu/NOLp0xg5nz5zNw6BCH9+8/pY1pV1/NpdOn07ttG68+9xxD11zDuyKYd/vtXP2e99Dz1FO1/lqSJElAddcg3wd8NaU0J6XUmlKaDewCbqtin6qSxilTAHhrYICX169n55NPctWNNzLv9tvZu307z37zm6fsf2D3bm687TaOHz3Kc9/8JkODg6e8f+KKFT/evJnerVvp/clP2Pnkk6SU3r6yhSRJUhGqucTiE8DDp237BrAEWF/FfjXKps+dy/zKP8m8tns3Q4ODbFmzhi1r1gzbd/OqVWxetQqArU88cdY2f/Td7/Kj7373lG3HDh/m25///KjVLUmSdDGqFpBTSl1n2PYn1epP1TP9+uu5dMYMdj/3HC+tW1d0OZIkSVVVi+sga4zbvnYt29euLboMSZKkmvBW05IkSVKOAVmSJEnKMSBLkiRJOa5BrmNrK+t+P7diRbGF1EBqaSGOHCm6jFPs6u2lrVQqugxJklRjBuQxYNLAQNElVN1Qc3Pdfc93l0rc0tHBK0UXUmULiy5AkqQ6Y0CuYxPphoPe/rI45aILkCSpzrgGWZIkScoxIEuSJEk5BmRJkiQpx4AsSZIk5RiQJUmSpBwDsiRJkpQT9XYpsYj4GRRy6dkZwP4C+lXG8S+OY18cx744jn1xHPviOPbDzUkpXXn6xroLyEWJiE0ppc6i65ioHP/iOPbFceyL49gXx7EvjmM/ci6xkCRJknIMyJIkSVKOAfmk7qILmOAc/+I49sVx7Ivj2BfHsS+OYz9CrkGWJEmScpxBliRJknIMyJIkSVKOARmIiA9FxLaIeDkiPlt0PRNJRPRExAsRsTkiNhVdz3gWEV+OiH0R8Xe5be+KiL+JiJcqP68ossbx6ixjvywiflI59jdHxK8VWeN4FRGzI+JvI+JHEbElIj5V2e6xX2XnGHuP/SqLiOaIeCoinq+M/ecr2z3uR2jCr0GOiAZgO/ArwI+Bp4FPpJReLLSwCSIieoDOlJIXLq+yiLgD6Ae+mlJqr2z7t8CBlNLDlf9zeEVK6TNF1jkenWXslwH9KaU/LrK28S4irgauTik9GxGXAc8A9wC/jsd+VZ1j7O/HY7+qIiKAqSml/ohoBDYAnwLuxeN+RJxBhvcDL6eUdqaUjgFfBz5WcE3SqEsprQMOnLb5Y8BXKs+/QvbHS6PsLGOvGkgp/TSl9Gzl+SHgR8C1eOxX3TnGXlWWMv2Vl42VR8LjfsQMyNl/rK/mXv8Y/wOupQR8JyKeiYilRRczAc1MKf0Usj9mwFUF1zPR/FZE/LCyBMN/6qyyiGgF3gv8AI/9mjpt7MFjv+oioiEiNgP7gL9JKXncXwADMsQZtk3sdSe1tSil9D7gbuBfVv4pWpoI/jPwbqAD+CnwhUKrGeci4lLgG8BDKaWDRdczkZxh7D32ayClNJhS6gCuA94fEe0FlzSmGJCzGePZudfXAXsKqmXCSSntqfzcB3yLbMmLamdvZZ3gifWC+wquZ8JIKe2t/AEbAr6Ex37VVNZgfgP485TSNyubPfZr4Exj77FfWymlPqAMfAiP+xEzIGcn5c2LiLkR0QQ8ADxWcE0TQkRMrZy4QURMBT4I/N25P6VR9hjwycrzTwKPFljLhHLij1TFx/HYr4rKyUp/BvwopfTvc2957FfZ2cbeY7/6IuLKiChVnk8B7gK24nE/YhP+KhYAlUvMPAI0AF9OKf1+sRVNDBFxA9msMcBkYKVjXz0R8TWgC5gB7AV+F1gF/AVwPbAb+AcpJU8mG2VnGfsusn9iTkAP8M9PrA3U6ImI24D1wAvAUGXz58jWwnrsV9E5xv4TeOxXVUT8PNlJeA1kk6F/kVL6vYiYjsf9iBiQJUmSpByXWEiSJEk5BmRJkiQpx4AsSZIk5RiQJUmSpBwDsiRJkpRjQJakOhMR0yNic+XRGxE/qTzvj4jlRdcnSeOdl3mTpDoWEcuA/pTSHxddiyRNFM4gS9IYERFdEfHtyvNlEfGViPhORPRExL0R8W8j4oWIWFO5xS8RcUtErI2IZyLir0+7i5kk6QwMyJI0dr0b+DDwMeC/A3+bUvp7wFHgw5WQ/KfAfSmlW4AvA96tUpLOY3LRBUiSLtr/TCkdj4gXyG4pu6ay/QWgFZgPtAN/ExFU9vGWvpJ0HgZkSRq73gRIKQ1FxPF08qSSIbLf7wFsSSktLKpASRqLXGIhSePXNuDKiFgIEBGNEbGg4Jokqe4ZkCVpnEopHQPuA/4oIp4HNgO/WGhRkjQGeJk3SZIkKccZZEmSJCnHgCxJkiTlGJAlSZKkHAOyJEmSlGNAliRJknIMyJIkSVKOAVmSJEnK+f8BA6waD56B4jgAAAAASUVORK5CYII=\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "gantt(JOBS, SCHEDULE)" ] }, { "cell_type": "markdown", "metadata": { "id": "y--tDDDxpGar", "pycharm": {} }, "source": [ "### Key performance indicators\n", "\n", "As presented above, a given schedule may not meet all of the due time requirements. In fact, a schedule meeting all of the requirements might not even be possible. So given a schedule, it is useful to have a function that computes key performance indicators." ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 119 }, "executionInfo": { "elapsed": 524, "status": "ok", "timestamp": 1603385301308, "user": { "displayName": "Jeffrey Kantor", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14Gg_n8V7bVINy02QRuRgOoMo11Ri7NKU3OUKdC1bkQ=s64", "userId": "09038942003589296665" }, "user_tz": 240 }, "id": "8qKLYYF8pGar", "outputId": "0cf06c2e-3cc9-4361-eac3-f1a3f2e4cbc7", "pycharm": {} }, "outputs": [ { "data": { "text/plain": [ "{'Makespan': 32,\n", " 'Max Pastdue': 22,\n", " 'Sum of Pastdue': 68,\n", " 'Number Pastdue': 5,\n", " 'Number on Time': 2,\n", " 'Fraction on Time': 0.2857142857142857}" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def kpi(JOBS, SCHEDULE):\n", " KPI = {}\n", " KPI['Makespan'] = max(SCHEDULE[job]['finish'] for job in SCHEDULE)\n", " KPI['Max Pastdue'] = max(max(0, SCHEDULE[job]['finish'] - JOBS[job]['due']) for job in SCHEDULE)\n", " KPI['Sum of Pastdue'] = sum(max(0, SCHEDULE[job]['finish'] - JOBS[job]['due']) for job in SCHEDULE)\n", " KPI['Number Pastdue'] = sum(SCHEDULE[job]['finish'] > JOBS[job]['due'] for job in SCHEDULE)\n", " KPI['Number on Time'] = sum(SCHEDULE[job]['finish'] <= JOBS[job]['due'] for job in SCHEDULE)\n", " KPI['Fraction on Time'] = KPI['Number on Time']/len(SCHEDULE)\n", " return KPI\n", "\n", "kpi(JOBS, SCHEDULE)" ] }, { "cell_type": "markdown", "metadata": { "id": "vn2kf3_qpGau", "pycharm": {} }, "source": [ "### Exercise\n", "\n", "Show the Gantt chart and key performance metrics if the jobs are executed in reverse alphabetical order." ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 531 }, "executionInfo": { "elapsed": 862, "status": "ok", "timestamp": 1603385303234, "user": { "displayName": "Jeffrey Kantor", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14Gg_n8V7bVINy02QRuRgOoMo11Ri7NKU3OUKdC1bkQ=s64", "userId": "09038942003589296665" }, "user_tz": 240 }, "id": "8PGHGwEgpGaw", "outputId": "08f7af52-d1eb-4242-96d6-1b1592a29e61", "pycharm": {} }, "outputs": [ { "data": { "text/plain": [ "{'Makespan': 39,\n", " 'Max Pastdue': 29,\n", " 'Sum of Pastdue': 76,\n", " 'Number Pastdue': 5,\n", " 'Number on Time': 2,\n", " 'Fraction on Time': 0.2857142857142857}" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "order = sorted(JOBS, reverse=True)\n", "gantt(JOBS, schedule(JOBS,order))\n", "kpi(JOBS, schedule(JOBS,order))" ] }, { "cell_type": "markdown", "metadata": { "id": "Z7FBdS3opGa0", "pycharm": {} }, "source": [ "## Empirical scheduling\n", "\n", "There are a number of commonly encountered empirical rules for scheduling jobs on a single machine. These include:\n", "\n", "* First-In First-Out (FIFO)\n", "* Last-In, First-Out (LIFO)\n", "* Shortest Processing Time First (SPT)\n", "* Earliest Due Data (EDD)" ] }, { "cell_type": "markdown", "metadata": { "id": "KmRNSyD5pGa1", "pycharm": {} }, "source": [ "### First-in first-out\n", "\n", " As an example, we'll first look at 'First-In-First-Out' scheduling which executes job in the order they are released. The following function sorts jobs by release time, then schedules the jobs to execute in that order. A job can only be started no earlier than when it is released." ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 531 }, "executionInfo": { "elapsed": 1093, "status": "ok", "timestamp": 1603385306288, "user": { "displayName": "Jeffrey Kantor", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14Gg_n8V7bVINy02QRuRgOoMo11Ri7NKU3OUKdC1bkQ=s64", "userId": "09038942003589296665" }, "user_tz": 240 }, "id": "95ttjNF8pGa2", "outputId": "a75db9e6-aa58-4578-fd9f-f0673bc13310", "pycharm": {} }, "outputs": [ { "data": { "text/plain": [ "{'Makespan': 30,\n", " 'Max Pastdue': 13,\n", " 'Sum of Pastdue': 31,\n", " 'Number Pastdue': 6,\n", " 'Number on Time': 1,\n", " 'Fraction on Time': 0.14285714285714285}" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAscAAABVCAYAAAClx0lPAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/YYfK9AAAACXBIWXMAAAsTAAALEwEAmpwYAAAUtElEQVR4nO3dfbRVdZ3H8ffHC8iD2kURRBSuEpjAKCWiBdq11DAtzczRZsyssZxsyrWmh5lWD9jUGmvljGsqdajMp6BxluZDWorlFXRKhcRMBVFEQZSr4uXhAsKF7/yx943j9T4cYJ+z973n81rrrPO0H76//du/vX/nd377txURmJmZmZkZ7JF3AGZmZmZmReHKsZmZmZlZypVjMzMzM7OUK8dmZmZmZilXjs3MzMzMUq4cm5mZmZmlXDk2M8uIpGslfaeb7zdIOrSaMXVHUpOkf8hoWTMl3Zj1tGZm1ebKsZnVDEnLJW2RNKzD54skhaSGSq4/IvaKiGVZL1fSREn3SHpdUoukhZI+mPV6zMxqgSvHZlZrngPObX8j6W+AQfmFk4k7gLnACGA48AVgXa4RmZn1Uq4cm1mtuQH4RMn784HrSyeQdKqkRyWtk7RC0swO30+X9H9pK+0KSZ8s+XqopDslrZf0kKSxJfOFpLenr6+V9ONupn2HpLmS1khaIunszhKTtoIfAvwkIrakjwcj4oGSaU5PW8fXSXpW0oySRYyR9GAawz2lreqSji1J52OSGku+O0TS/el8c4HS+RolrewQ53JJJ3aRhi7XY2ZWba4cm1mt+SOwj6TDJdUBfwt07P/aSlKBrgdOBf5R0hkAkkYDvwF+COwPTAYWlcx7LnApMBR4BvhuN7F0Oq2kISQtwbNJWoLPBa6UNLGTZbyWznujpDMkjSj9UtJUksr/l9P0HA8sL5nk48AF6XoGAF9K5xsF3Al8B9g3/fxmSfun880GFpJUiv+N5EfGTitjPWZmVeXKsZnVovbW45OAxcCLpV9GRFNEPB4R2yPiz8Ac4L3p138H3BsRcyJia0S8FhGLSma/JSIejog24BckleeudDXtacDyiPh5RLRFxJ+Am4GzOi4gIgI4gaTCeznwkqR5ksalk3wauCYi5qbpeTEiFpcs4ucR8XREbAJuKonh74G7IuKudL65wALgg+kPhKOBb0TEGxExj6Rrx67ocj27uDwzs93iyrGZ1aIbSFpMP0mHLhUAko6RdJ+kVyStBS5iR7eBg4Fnu1n2yyWvNwJ77cK0Y4Bj0m4GLZJaSCrlB3S2kIhYGRGfj4ix6bytJena1XjHAB/rEMN0YCRwIPB6RLSWzPt8N+voTnfrMTOrun55B2BmVm0R8byk50haJz/dySSzgR8Bp0TEZklXsKNyvAKYWuEQVwD3R8RJOztjRKyQ9GOS1u72ZY3tZpbuYrghIi7s+IWkMSR9q4eUVJBHA5G+bgUGl0xfR9IFZafWY2aWB7ccm1mt+jTwvg6tn+32BtakFeOpJK3M7X4BnCjpbEn9JO0naXLGsf0aGC/pPEn908fRkg7vOKGkoZIulfR2SXukF9R9iqRvNcDPgAskvT/9fpSkd5QRw43AhyR9QFKdpIHphXYHRcTzJF0fLpU0QNJ04EMl8z4NDEwvbOwPfB3Yc2fXU86GMjPLmivHZlaTIuLZiFjQxdefA74taT3wTZK+uO3zvUDS4vzPwBqSi/GOzDi29cDJwDnAKpKuD9+j8wrmFqABuJdk+La/AG+QdBkhIh4mueDuP4G1wP0kXRl6imEFcDrwNeAVkhbeL7PjvPFx4BiSbfAtSrqnRMRakm34U5L+3K3Am0av2In1mJlVlZJrOczMzMzMzL/MzczMzMxSrhybmZmZmaVcOTYzMzMzS5VVOZb0MUl7p6+/LukWSe+qbGhmZmZmZtVVbsvxNyJifTpczweA64CrKheWmZmZmVn1lXsTkG3p86nAVRFxm6SZWQczbNiwaGhoyHqxPWptbWXIkCFVX691zXlSTM6X4nGeFJPzpXicJ8WUV74sXLjw1Yjo9OZE5VaOX5T038CJwPck7UkF+is3NDSwYEFXw45WTlNTE42NjVVfr3XNeVJMzpficZ4Uk/OleJwnxZRXvkjq8pb35VZwzwbuBmZERAuwL8kg7WZmZmZmfUZZleOI2Ag0A9PTj9qApZUKyszMzMwsD+WOVvEt4KvAv6Yf9QdurFRQZmZmZmZ5KLdbxUeADwOtABGxCti7UkGZmZmZmeWh3AvytkRESAoASX3mcs9Zs2Zx5ZVXUl9fn3covdaqVauQxMiRIzNbZktLS6Z58tJLLxERHHjggZktsxZlmS+V2G9qUdZlpRZV4vjgfCmWVatWsWnTJsaOHZt3KFXTW46xRx11VOEulCy3cnxTOlpFvaQLgU8BP6lcWNUze/Zsnlm6lCl7uyF8Vy1rboYIRq5dm91C6+th8eLMFvdsGuOB69ZltsyalGG+VGS/qUUZl5VaVJHjg/OlUJY1NxMSY7duzTuUqukNx9hFa9bQsno1XH553qG8SVmV44j4gaSTgHXAYcA3I2JuRSOrorcffDBN55yTdxi9Vv1ll8GWLTRddFFmy2w67DAalyzJbHmViLEWZZkvzpNsZF1WalFvOIbZ7qm/7DLapJo63vSGY2zjtdfSEpF3GG9RbssxaWW4z1SIzczMzMw6Kne0ijMlLZW0VtI6Sesl+f9pMzMzM+tTym05/j7woYh4qpLBmJmZmZnlqdyh3Fa7YmxmZmZmfV25LccLJP0PcCvwRvuHEXFLJYIyMzMzM8tDuZXjfYCNwMklnwXgyvHOmjkTmpvhyiu7nuaMM2DyZJg1C1at6n55l1ySDBm0bRts3gwvvwzz58Py5VlFnI2dTXdP2tNd6uqrk/T3JlnvDwD77w8XX5y8vuMOWLgwg0CtarIuKwBHHw1Tp8LQobBpEyxZAr/+dQbBWmFU6twCO84td94Jr7ySSbi9WiW3dbtqnM8qcf6ZMiU53uy3H2zdmuwv990Hzz2XUdDVUe5Qbhfs7IIlXQOcBjRHxKSdnd92Qlsb3HYbDB8OxxwDn/gE3HBDr9sZd1pbG9x66473LS15RVIsk9Litn07TJzoynGta2xMHq+9BvfcA/36weGH5x2V9Qbtx9iRI2HaNDjpJJg9O++o+qa+cD5rP9a8/jr87ndJo93YsXDQQb2uPtJt5VjSVyLi+5J+SNJS/CYR8YVuZr8W+BFw/W5F2FfV1cGJJyYVmf79k5beu+6C0kHoJ02Cs8+GCLj99q53ru3b4fHHk9fNzfDRj8JxxxVzZywz3ccecQTMmNFzupct2/F+8+aKhl5RWe4PEycm873wAkyYAEOGQGtrVZJhGcqirPTvn1Rq2trg+uuh/WYAf/hD1ZJhVZb1uWXZsuTfhmnTYI9yL1OqEZXY1u2qeT7LIh2lx5prr91xrHn44eS7XqanPb39IrwFwMJOHl2KiHnAmt0NsM86/nh497vh2WfhgQdg/PikUltq1Ch48EEYPBjOPDPZgXuydGnyfMAB2cechTLT/cLixT2ne8AA+MpXdjx6s6z2hxEjYNgweOopeOKJ5GQ2YUJ10mDZyqKsDB+enJhefXXHyQqSE5z1TVmeW9qPseedl1Te5s+vfPy9SSW2dR7nsyzS0fFYIyXTDh7cK39UddtyHBF3pM/XVSecGjJuXHKwueOO5K+H8eNhzJikgLRrakp+nR10EBx5ZFLpWb26++VKyXNRT35lpnvVgAGM79+/+3Rv3Qpz5lQv9krKan9o71KxcmVykGprS1qSH3mkakmxjGRZVop6PLDsZXluaT/G7r03nHYanHBC0ipoiUps6zxkmY72Y82IEdB+Z77ly3vdflNWn2NJ44EvAQ2l80TE+3Y3AEmfAT4DMGLECJqamnZ3kTulpaWFbXV1NB12WFXW1wi0DhjA9ro69gLmjR9PbN/OOwcN4m3A/HHjGLfPPhwALDr4YFoGDODwt72NEcAjDQ20dui0f2y/fvSXmJ/GP3zMGCYAr69fz2NVSlNbXR3suWe327CRnUv3hpYWVveUbmB+6d813ay/nBjz0Ei2+8PUyZMZDG/61R+jR/OHI49kSwZ/023IcBsWNU/y1kh2ZWWPujqmtbWh4cN5aPJk3ti0KY8kFV4l9sUsy0o5GqnAuYX0GLt5M+9au5Z9GhqYN2EC27dtq1q6stJWV0dAJnnSSAW3dbsM4uxpv84yHaXHmj9Onsy2rVsZOn8+k447jpZBg1jURQwtgwezTap63a8n5Y5W8b/A1cBPgUxLRUTMAmYBTJkyJRobG7NcfI/q6+tpefllGpcsqdo6h2zZAk8+CY2NvHf8+KSFb7/9YPlyjnviieRXHDD50EOTvl4jR8L69Ry9YEHyq67UKafAwIE0DhiQjFIwZQps387Qu++msUp9jvtt2wZbtvS4DXcm3YNffZUR5aS79GDy/POwfv1uxZiHzPaHkSOTFp4lS+DRR5PPRo1Cxx3He/bcEx57bLdjbTrssMy2YZHzJG+ZlpXhw6GxkXdPnw4PPbTjgrxrrskhZcVUiX0xy7JSroqcW/r3T44rQ4fChg0c/+STVU1TVvpt20ablFmeZL6tBwzIfH8pZ7/ONB3pseY906cnfY3Ta13qN23qMob6jRtpGTiQatf9elJu5bgtIq6qaCS1YNCg5Hnz5qTv1sCByV/ehx8OTz+ddIAv9cILMH16skPedttbd8R2/folw61s3gwrVsC8eUlFsSh2Id2jjzqqvHSfddaO97/8JSxeXJk0VELW+8PEicnzokU7tsOKFck8kyYlBysrtkqUlaYm2LgxGV5pxowdQ7lZ31HJc8tZZyV/+Tc3J6Od1LpKbetqq0Q6mpqSCvHUqXDyyfDGG0lXjAULKp6crPU0WsW+6cs7JH0O+BVvvglIlxfcSZpD0mo/TNJK4FsR8bPdjri3OuSQZIgTSHaybdvgt79NHh3deuuOIV1+//vul3vFFdnFWAm7mO4/vvhi97+ii57unlRif7j33uRRqrUVLr00g4Ct4ipVViD5YeQfR31TrZ5b8tBXtnWl0gHJ9S194BqXnlqOF5IM4ZZe5cWXS74L4NCuZoyIc3cvtD5m9OikA/ujjyYtu7WiVtPdE28X68j7hO0K7zfV01e2dV9JRwX1NFrFIdUKpM+7//7kUWtqNd098XaxjrxP2K7wflM9fWVb95V0VFBZg89JulhSfcn7oWk3CzMzMzOzPqPckZkvjIiW9jcR8TpwYUUiMjMzMzPLSbmV4z2k9rtLgKQ6YEA305uZmZmZ9TrlDuV2N3CTpKtJLsS7COjkskYzMzMzs95LUcZtRSXtAXwWeD/JyBX3AD+NiEwH7JsyZUosqPJ4eO0N4u8dM6aq6+1L7k/HVM5yG7YMHkz9xo2ZLa8SMdaiLPPFeZKNrMtKLeoNxzDbPbV4vOkNaV708ss0NDSwKId7FEhaGBFTOvuurJbjiNgOXJU++qYMbq1b87LchgMHViZPnM+7pxL54jzZPZUqK7WoNxzDbPfUYp4UOM2T6+s5atq0vMN4i7Iqx5LGAf8OTAAGtn8eEV2Oc9xbRARNTU2Fu3VhrXOeFJPzpXicJ8XkfCke50kxNTU15R3CW5R7Qd7PSVqN24ATgOuBGyoVlJmZmZlZHsqtHA+KiN+R9FF+PiJmAu+rXFhmZmZmZtVX7mgVm9OL8pZK+jzwIjC8cmGZmZmZmVVfuS3HlwCDgS8ARwHnAedXKCYzMzMzs1yUO1rFI+nLDcAFlQvHzMzMzCw/3VaOJd3e3fcR8eFswzEzMzMzy0+3NwGR9AqwApgDPERyA5C/ioj7Mw0mWd/zWS6zTMOAV3NYr3XNeVJMzpficZ4Uk/OleJwnxZRXvoyJiP07+6KnynEdcBJwLnAEcCcwJyKeqESUeZG0oKu7pFg+nCfF5HwpHudJMTlfisd5UkxFzJduL8iLiG0R8duIOB84FngGaJL0T1WJzszMzMysinq8IE/SnsCpJK3HDcB/AbdUNiwzMzMzs+rr6YK864BJwG+ASyPiL1WJqvpm5R2AvYXzpJicL8XjPCkm50vxOE+KqXD50lOf4+1Aa/q2dEIBERH7VDA2MzMzM7Oq6rZybGZmZmZWS8q9Q16fJGmGpCWSnpH0L3nHYwlJyyU9LmmRpAV5x1OrJF0jqVnSX0o+21fSXElL0+ehecZYa7rIk5mSXkzLyyJJH8wzxloj6WBJ90l6StITkr6Yfu6ykqNu8sXlJSeSBkp6WNJjaZ5cmn5euLJSsy3H6TB1T5MMVbcSeAQ4NyKezDUwQ9JyYEpEeDzKHEk6nuSumNdHxKT0s+8DayLisvQH5dCI+GqecdaSLvJkJrAhIn6QZ2y1StJIYGRE/EnS3sBC4Azgk7is5KabfDkbl5dcSBIwJCI2SOoPPAB8ETiTgpWVWm45ngo8ExHLImIL8Evg9JxjMiuMiJgHrOnw8enAdenr60hONlYlXeSJ5SgiXoqIP6Wv1wNPAaNwWclVN/liOYnEhvRt//QRFLCs1HLleBTJ3f/arcQFpygCuEfSQkmfyTsYe5MREfESJCcfYHjO8Vji85L+nHa7yP0vyVolqQF4J8kdZV1WCqJDvoDLS24k1UlaBDQDcyOikGWllivH6uSz2uxjUjzTIuJdwCnAxelfyWbWuauAscBk4CXg8lyjqVGS9gJuBi6JiHV5x2OJTvLF5SVH6c3lJgMHAVMlTco5pE7VcuV4JXBwyfuDgFU5xWIlImJV+twM/IqkC4wVw+q0L197n77mnOOpeRGxOj3hbAd+gstL1aX9J28GfhER7TfJclnJWWf54vJSDBHRAjQBMyhgWanlyvEjwDhJh0gaAJwD3J5zTDVP0pD04gkkDQFOBvrqzWd6o9uB89PX5wO35RiL8deTSbuP4PJSVelFRj8DnoqI/yj5ymUlR13li8tLfiTtL6k+fT0IOBFYTAHLSs2OVgGQDuFyBVAHXBMR3803IpN0KElrMSR3cJztfMmHpDlAIzAMWA18C7gVuAkYDbwAfCwifIFYlXSRJ40kfxEHsBz4bHv/Pas8SdOB+cDjwPb046+R9G91WclJN/lyLi4vuZB0BMkFd3UkjbM3RcS3Je1HwcpKTVeOzczMzMxK1XK3CjMzMzOzN3Hl2MzMzMws5cqxmZmZmVnKlWMzMzMzs5Qrx2ZmZmZmKVeOzczMzMxSrhybmZmZmaVcOTYzMzMzS/0/UpH+hfn4r3sAAAAASUVORK5CYII=\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "def fifo(JOBS):\n", " order_by_release = sorted(JOBS, key=lambda job: JOBS[job]['release'])\n", " return schedule(JOBS, order_by_release)\n", "\n", "SCHEDULE = fifo(JOBS)\n", "gantt(JOBS, SCHEDULE)\n", "kpi(JOBS, SCHEDULE)" ] }, { "cell_type": "markdown", "metadata": { "id": "dhRIVrjKpGa6", "pycharm": {} }, "source": [ "### Last-in, first-out" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 531 }, "executionInfo": { "elapsed": 787, "status": "ok", "timestamp": 1603385306596, "user": { "displayName": "Jeffrey Kantor", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14Gg_n8V7bVINy02QRuRgOoMo11Ri7NKU3OUKdC1bkQ=s64", "userId": "09038942003589296665" }, "user_tz": 240 }, "id": "BVPua9cQpGa7", "outputId": "c74ffd88-628a-46b2-d19f-220d378cbfaa", "pycharm": {} }, "outputs": [ { "data": { "text/plain": [ "{'Makespan': 30,\n", " 'Max Pastdue': 25,\n", " 'Sum of Pastdue': 47,\n", " 'Number Pastdue': 4,\n", " 'Number on Time': 3,\n", " 'Fraction on Time': 0.42857142857142855}" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "def lifo(JOBS):\n", " unfinished_jobs = set(JOBS.keys())\n", " start = 0\n", " while len(unfinished_jobs) > 0:\n", " start = max(start, min(JOBS[job]['release'] for job in unfinished_jobs))\n", " lifo = {job:JOBS[job]['release'] for job in unfinished_jobs if JOBS[job]['release'] <= start}\n", " job = max(lifo, key=lifo.get)\n", " finish = start + JOBS[job]['duration']\n", " unfinished_jobs.remove(job)\n", " SCHEDULE[job] = {'machine': 1, 'start': start, 'finish': finish}\n", " start = finish\n", " return SCHEDULE \n", " \n", "gantt(JOBS, lifo(JOBS))\n", "kpi(JOBS, lifo(JOBS))" ] }, { "cell_type": "markdown", "metadata": { "id": "11O2fUV-pGa-", "pycharm": {} }, "source": [ "### Earliest due date" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 531 }, "executionInfo": { "elapsed": 1353, "status": "ok", "timestamp": 1603385308221, "user": { "displayName": "Jeffrey Kantor", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14Gg_n8V7bVINy02QRuRgOoMo11Ri7NKU3OUKdC1bkQ=s64", "userId": "09038942003589296665" }, "user_tz": 240 }, "id": "CAIP4BXkpGbA", "outputId": "f3c3d5c9-eb05-498b-b3ab-533210bf624d", "pycharm": {} }, "outputs": [ { "data": { "text/plain": [ "{'Makespan': 30,\n", " 'Max Pastdue': 8,\n", " 'Sum of Pastdue': 23,\n", " 'Number Pastdue': 4,\n", " 'Number on Time': 3,\n", " 'Fraction on Time': 0.42857142857142855}" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAscAAABVCAYAAAClx0lPAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/YYfK9AAAACXBIWXMAAAsTAAALEwEAmpwYAAAUiElEQVR4nO3de5AdZZnH8e+PyT0EJxASQoBMgCSSZCVKCCoBBwUEQUFUFtxFRBdlxVWq1suupQKu1qolu9SqwEZFbiYuWyAXQQkoA4FVSCJB5BougYRAAoRJwiQhmeTZP7rHHMJcziTdp3vm/D5Vp+bcuvt5++n3nPe88/bbigjMzMzMzAx2KToAMzMzM7OycOPYzMzMzCzlxrGZmZmZWcqNYzMzMzOzlBvHZmZmZmYpN47NzMzMzFJuHJuZZUTSFZK+3c3rr0nav5YxdUdSi6R/yGhdF0i6Juv3mpnVmhvHZlY3JC2VtEnSqO2eXywpJDXluf2I2DUins56vZKmSpon6VVJrZIWSfpA1tsxM6sHbhybWb15Bji944GkvwGGFhdOJm4GbgfGAKOBLwBrC43IzKyPcuPYzOrN1cAnKh6fCVxV+QZJJ0h6QNJaScskXbDd67Mk/V/aS7tM0icrXh4p6RZJ6yTdJ+mAiuVC0oHp/Ssk/bib975V0u2SVkt6XNKpnRUm7QWfAPwkIjalt3sj4p6K95yU9o6vlfSUpOMqVjFe0r1pDPMqe9UlvbOinA9Kaq54bYKku9Llbgcql2uWtHy7OJdKOrqLMnS5HTOzWnPj2MzqzR+B3SQdJKkB+Ftg+/GvbSQN6EbgBOAfJZ0MIGk/4DfAD4E9genA4oplTwcuBEYCTwLf6SaWTt8raThJT/Ackp7g04FLJE3tZB2vpMteI+lkSWMqX5Q0k6Tx/+W0PEcCSyve8nHgrHQ7g4AvpcuNA24Bvg3snj5/naQ90+XmAItIGsX/RvIjo9eq2I6ZWU25cWxm9aij9/gY4DHg+coXI6IlIh6KiK0R8WdgLvCe9OW/A+6IiLkRsTkiXomIxRWLXx8R90dEO/ALksZzV7p674nA0oj4eUS0R8SfgOuAj26/gogI4CiSBu9FwAuS7pY0MX3Lp4HLI+L2tDzPR8RjFav4eUQ8EREbgGsrYvh74NaIuDVd7nZgIfCB9AfCocA3IuL1iLibZGjHjuhyOzu4PjOzneLGsZnVo6tJekw/yXZDKgAkHSbpTkkvSVoDnMO2YQP7Ak91s+4XK+6vB3bdgfeOBw5Lhxm0SmolaZTv1dlKImJ5RHw+Ig5Il22rKNeOxjse+Nh2McwCxgJ7A69GRFvFss92s43udLcdM7OaG1B0AGZmtRYRz0p6hqR38tOdvGUO8CPg+IjYKOlitjWOlwEzcw5xGXBXRBzT2wUjYpmkH5P0dnes64BuFukuhqsj4uztX5A0nmRs9fCKBvJ+QKT324BhFe9vIBmC0qvtmJkVwT3HZlavPg28d7vezw4jgNVpw3gmSS9zh18AR0s6VdIASXtImp5xbL8GJkk6Q9LA9HaopIO2f6OkkZIulHSgpF3SE+o+RTK2GuBnwFmS3pe+Pk7SW6uI4Rrgg5LeL6lB0pD0RLt9IuJZkqEPF0oaJGkW8MGKZZ8AhqQnNg4Evg4M7u12qtlRZmZZc+PYzOpSRDwVEQu7ePlzwLckrQO+STIWt2O550h6nP8ZWE1yMt7BGce2DjgWOA1YQTL04Xt03sDcBDQBd5BM3/YX4HWSISNExP0kJ9z9J7AGuItkKENPMSwDTgK+BrxE0sP7ZbZ9b3wcOIxkH5xPxfCUiFhDsg9/SjKeuw14w+wVvdiOmVlNKTmXw8zMzMzM/MvczMzMzCzlxrGZmZmZWcqNYzMzMzOzVFWNY0kfkzQivf91SddLeke+oZmZmZmZ1Va1PcffiIh16XQ97weuBC7NLywzMzMzs9qr9iIgW9K/JwCXRsSNki7IOphRo0ZFU1NT1qvtUVtbG8OHD6/5dq1rzkk5OS/l45yUk/NSPs5JORWVl0WLFr0cEZ1enKjaxvHzkv4bOBr4nqTB5DBeuampiYULu5p2ND8tLS00NzfXfLvWNeeknJyX8nFOysl5KR/npJyKyoukLi95X20D91TgNuC4iGgFdieZpN3MzMzMrN+oqnEcEeuBVcCs9Kl2YEleQZmZmZmZFaHa2SrOB74K/Gv61EDgmryCMjMzMzMrQrXDKj4MfAhoA4iIFcCIvIIyMzMzMytCtSfkbYqIkBQAkvrN6Z6zZ8/mkksuobGxsehQuvTCCy8QEey9995Fh1Izra2tmeakHvdhHrLMy4oVK5DE2LFjM1lfX5DHcZh1XbFslDkv9fp5WOac5KGvfMYecsghpTtRstrG8bXpbBWNks4GPgX8JL+wamfOnDk8uWQJM0aUtyP8qVWrIIK9164tOpTaaWyExx7LbHV1uQ/zkGFenk5zMnbNmkzW1xfkchxmXFcsIyXOS91+HpY4J3noC5+xi1evpnXlSrjooqJDeYOqGscR8QNJxwBrgcnANyPi9lwjq6ED992XltNOKzqMLjV+97uwaRMt55xTdCg10zJ5Ms2PP57Z+upxH+Yhy7zUY07yKHPWdcWyUea81GPdg3LnJA99Ic/NV1xBa0TRYbxJtT3HpI3hftMgNjMzMzPbXrWzVZwiaYmkNZLWSlonqc7+H2NmZmZm/V21PcffBz4YEY/mGYyZmZmZWZGqncptpRvGZmZmZtbfVdtzvFDS/wA3AK93PBkR1+cRlJmZmZlZEaptHO8GrAeOrXgugPpoHF9wAaxaBZdc0vV7Tj4Zpk+H2bNhxYru13feecmUMpUuuwxefHGnwsxMXuXdsgU2bkzKOX8+LF2aVcR9V9b7GmDPPeHcc5P7N98MixZlEGjJ1Vsd7U/yqAOHHgozZ8LIkbBhAzz+OPz61xkFbKWQZ53v+J665RZ46aVMwi2lPOrejBlJ/dtjD9i8Odl/d94JzzyTUdC1Ue1Ubmf1dsWSLgdOBFZFxLTeLt/vtbfDDTdse9zaWlQktdHeDjfeCKNHw2GHwSc+AVdf3ecqTJ8wLa1uW7fC1Kn10TjOQ73V0f6iuTm5vfIKzJsHAwbAQQcVHZX1BR11fuxYOPxwOOYYmDOn6Kj6jo669+qr8LvfJR1iBxwA++zT577ru20cS/pKRHxf0g9JeorfICK+0M3iVwA/Aq7aqQjLpKEBjj46aXwMHJj0fN56K1ROpD5tGpx6KkTATTd1fUBs3QpPP73t8caNuYa+Q7Iu70MPJfdXrYKPfASOOKLPVZjcZLmvp05NlnvuOZgyBYYPh7a2mhSjcPVWR/uTLHI3cGDSqGlvh6uugo6LH/zhDzUrhtVYL46bwwYMgE2beq7zGzYkx9Eu1Z6W1cdlXfeuuGJb3bv//uS1PqanzHechLcQWNTJrUsRcTewemcDLJUjj4R3vQueegruuQcmTUoaeZXGjYN774Vhw+CUU5KDrjODBsFXvrLtVkZZlrfSkiXJ3732yj7mviqrfT1mDIwaBY8+Cg8/nHy4T5lSmzKUQb3V0f4ki9yNHp18Eb/88rYvZ0i+0K1/6sVxM3Dw4Orq/BlnJA3l+fPzj78M8qh7UvLeYcP65I+MbnuOI+Lm9O+VtQmn5CZOTCrMzTcn/y6YNAnGj08qVIeWluQX1T77wMEHJw2VlSvfvK7Nm2Hu3JqFvkOyLG8lKfnrL6xtstrXHUMqli9PPqTa25Oe5AULalaUQtVbHe1PssydP1vqRy+Om5enTGGvCRN6rvMjRsCJJ8JRRyW9oP1dHnVvzBjouDLf0qV9bj9WNeZY0iTgS0BT5TIR8d6dDUDSZ4DPAIwZM4aWlpadXWWvtLa2sqWhgZbJk7t8TzPQNmgQWxsa2BW4e9IkYutW3j50KG8B5k+cyMTddmMvYPG++9I6aBAHveUtjAEWNDXRtt2JPe8cMICBwPzKfzV0s/32hgYYPLjbGLPUTA7llZifxj96/HimAK+uW8eDXZTptYzLW+t9WK1mst3XM6dPZxi84Vd/7Lcffzj4YDZlMCwgy7xkmZNmiq2j1crjOMy6rtRaM9nlbpeGBg5vb0ejR3Pf9Om8vmFDEUUCyp2Xsn4e9kYzvT9uDkx7O3us8xs38o41a9itqYm7p0xh65YtNS1bVnrKczP51L0/Tp/Ols2bGTl/PtOOOILWoUNZ3EUMrcOGsUWqeduvJ9XOVvG/wGXAT4FMj5KImA3MBpgxY0Y0NzdnufoeNTY20vriiz1eb334pk3wyCPQ3Mx7Jk1KeuX22AOWLuWIhx9OfnkB0/ffPxmvNHYsrFvHoQsXJr/EKh1/PAwZQnPlF++zz8K6dZ1ue8CWLbBpU02vCZ9LeQcNSmZSmDEDtm5l5G230dzF2K+WyZMzLW8R+7Bame3rsWOTHo/HH4cHHkieGzcOHXEE7x48GB58cKdjzTIvWeck82N20KDMj5c8jsOs60oRMs3d6NHQ3My7Zs2C++7bdkLe5ZfXtExlzkuZPw97o7fHTXu138sjRiQznbz2Gkc+8kgBJctGNXnOo+69e9asZKxxeq5L44YNXcbQuH49rUOGUOu2X0+qbRy3R8SluUZSVkOHJn83bkzGHw0Zkvyb+qCD4IknkkHrlZ57DmbNSg6iG29888HTYcAA+OhHtz3+5S/hscfyKUNv5Fnek09O1rtsGdx9d/KDoJ5lva+nTk3+Ll687VhatixZZtq05MOqP8rrmLX85ZG7lhZYvz6ZTuq447ZN5Wb9xw4eN+2vv86A66/v+Xt58+bkxPF58/ItR5Hyqnttbck0isceC6+/ngzFWLgw9+JkrafZKnZP794s6XPAr3jjRUC6POFO0lySXvtRkpYD50fEz3Y64lqaMCGZlgSSA2PLFvjtb5Pb9m64Ydu0T7//fffrvfji7GLMUr2Vt0h57Os77khuldra4MILMwi4pHzM9l155Q6SH4L99cdgvduJ4+aPkyd3+d/Kuqrzeda9BQv6xTkuPfUcLyKZwi09g4ovV7wWwP5dLRgRp+9caCWw337JoPMHHkh6Ovu7eitvkbyvs+H92Hc5d7YjfNzsPO/DHvU0W8WEWgVSSnfdldzqRb2Vt0je19nwfuy7nDvbET5udp73YY+qmnxO0rmSGisej0yHWZiZmZmZ9RvVzsx8dkS0djyIiFeBs3OJyMzMzMysINU2jneROq7cAJIagEHdvN/MzMzMrM+pdiq324BrJV1GciLeOUAnpzWamZmZmfVdiiousylpF+CzwPtIZq6YB/w0IjKdIHTGjBmxsMbz4XV0iL9n/Piabrc37krnAy5zjFlrHTaMxvXrM1tfPe7DPGSZl3rMSR5lzrquWDbKnJd6rHtQ7pzkoS/kefGLL9LU1MTiAq7zIGlRRMzo7LWqeo4jYitwaXrrnzK4tG7u+kKMWRkyJJ/y1tM+zEMeeanHnGRZ5rzqiu2cvpCXsseXtb6QkzyUuMzTGxs55PDDiw7jTapqHEuaCPw7MAUY0vF8RHQ5z3FfERG0tLSU7tKF9c45KSfnpXyck3JyXsrHOSmnlpaWokN4k2pPyPs5Sa9xO3AUcBVwdV5BmZmZmZkVodrG8dCI+B3JGOVnI+IC4L35hWVmZmZmVnvVzlaxMT0pb4mkzwPPA6PzC8vMzMzMrPaq7Tk+DxgGfAE4BDgDODOnmMzMzMzMClHtbBUL0ruvAWflF46ZmZmZWXG6bRxLuqm71yPiQ9mGY2ZmZmZWnG4vAiLpJWAZMBe4j+QCIH8VEXdlGkyyvWezXGeVRgEvF7Bd65pzUk7OS/k4J+XkvJSPc1JOReVlfETs2dkLPTWOG4BjgNOBtwG3AHMj4uE8oiyKpIVdXSXFiuGclJPzUj7OSTk5L+XjnJRTGfPS7Ql5EbElIn4bEWcC7wSeBFok/VNNojMzMzMzq6EeT8iTNBg4gaT3uAn4L+D6fMMyMzMzM6u9nk7IuxKYBvwGuDAi/lKTqGpvdtEB2Js4J+XkvJSPc1JOzkv5OCflVLq89DTmeCvQlj6sfKOAiIjdcozNzMzMzKymum0cm5mZmZnVk2qvkNcvSTpO0uOSnpT0L0XHYwlJSyU9JGmxpIVFx1OvJF0uaZWkv1Q8t7uk2yUtSf+OLDLGetNFTi6Q9HxaXxZL+kCRMdYbSftKulPSo5IelvTF9HnXlQJ1kxfXl4JIGiLpfkkPpjm5MH2+dHWlbnuO02nqniCZqm45sAA4PSIeKTQwQ9JSYEZEeD7KAkk6kuSqmFdFxLT0ue8DqyPiu+kPypER8dUi46wnXeTkAuC1iPhBkbHVK0ljgbER8SdJI4BFwMnAJ3FdKUw3eTkV15dCSBIwPCJekzQQuAf4InAKJasr9dxzPBN4MiKejohNwC+BkwqOyaw0IuJuYPV2T58EXJnev5Lky8ZqpIucWIEi4oWI+FN6fx3wKDAO15VCdZMXK0gkXksfDkxvQQnrSj03jseRXP2vw3JcccoigHmSFkn6TNHB2BuMiYgXIPnyAUYXHI8lPi/pz+mwi8L/JVmvJDUBbye5oqzrSklslxdwfSmMpAZJi4FVwO0RUcq6Us+NY3XyXH2OMSmfwyPiHcDxwLnpv5LNrHOXAgcA04EXgIsKjaZOSdoVuA44LyLWFh2PJTrJi+tLgdKLy00H9gFmSppWcEidqufG8XJg34rH+wArCorFKkTEivTvKuBXJENgrBxWpmP5Osb0rSo4nroXESvTL5ytwE9wfam5dPzkdcAvIqLjIlmuKwXrLC+uL+UQEa1AC3AcJawr9dw4XgBMlDRB0iDgNOCmgmOqe5KGpydPIGk4cCzQXy8+0xfdBJyZ3j8TuLHAWIy/fpl0+DCuLzWVnmT0M+DRiPiPipdcVwrUVV5cX4ojaU9Jjen9ocDRwGOUsK7U7WwVAOkULhcDDcDlEfGdYiMySfuT9BZDcgXHOc5LMSTNBZqBUcBK4HzgBuBaYD/gOeBjEeETxGqki5w0k/yLOIClwGc7xu9Z/iTNAuYDDwFb06e/RjK+1XWlIN3k5XRcXwoh6W0kJ9w1kHTOXhsR35K0ByWrK3XdODYzMzMzq1TPwyrMzMzMzN7AjWMzMzMzs5Qbx2ZmZmZmKTeOzczMzMxSbhybmZmZmaXcODYzMzMzS7lxbGZmZmaWcuPYzMzMzCz1/32rGd43fjn6AAAAAElFTkSuQmCC\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "def edd(JOBS):\n", " unfinished_jobs = set(JOBS.keys())\n", " start = 0\n", " while len(unfinished_jobs) > 0:\n", " start = max(start, min(JOBS[job]['release'] for job in unfinished_jobs))\n", " edd = {job:JOBS[job]['due'] for job in unfinished_jobs if JOBS[job]['release'] <= start}\n", " job = min(edd, key=edd.get)\n", " finish = start + JOBS[job]['duration']\n", " unfinished_jobs.remove(job)\n", " SCHEDULE[job] = {'machine': 1, 'start': start, 'finish': finish}\n", " start = finish\n", " return SCHEDULE \n", " \n", "gantt(JOBS, edd(JOBS))\n", "kpi(JOBS, edd(JOBS))" ] }, { "cell_type": "markdown", "metadata": { "id": "OoMSnsympGbE", "pycharm": {} }, "source": [ "### Shortest processing time" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 531 }, "executionInfo": { "elapsed": 1147, "status": "ok", "timestamp": 1603385309261, "user": { "displayName": "Jeffrey Kantor", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14Gg_n8V7bVINy02QRuRgOoMo11Ri7NKU3OUKdC1bkQ=s64", "userId": "09038942003589296665" }, "user_tz": 240 }, "id": "h8zmg5DqpGbF", "outputId": "162b6989-56a2-41ca-e051-94ebf651cefd", "pycharm": {} }, "outputs": [ { "data": { "text/plain": [ "{'Makespan': 30,\n", " 'Max Pastdue': 15,\n", " 'Sum of Pastdue': 18,\n", " 'Number Pastdue': 4,\n", " 'Number on Time': 3,\n", " 'Fraction on Time': 0.42857142857142855}" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "def spt(JOBS):\n", " unfinished_jobs = set(JOBS.keys())\n", " start = 0\n", " while len(unfinished_jobs) > 0:\n", " start = max(start, min(JOBS[job]['release'] for job in unfinished_jobs))\n", " spt = {job:JOBS[job]['duration'] for job in unfinished_jobs if JOBS[job]['release'] <= start}\n", " job = min(spt, key=spt.get)\n", " finish = start + JOBS[job]['duration']\n", " unfinished_jobs.remove(job)\n", " SCHEDULE[job] = {'machine': 1, 'start': start, 'finish': finish}\n", " start = finish\n", " return SCHEDULE \n", " \n", "gantt(JOBS, spt(JOBS))\n", "kpi(JOBS, spt(JOBS))" ] }, { "cell_type": "markdown", "metadata": { "id": "FcC5atVkpGbH", "pycharm": {} }, "source": [ "\n", "## Modeling" ] }, { "cell_type": "markdown", "metadata": { "id": "7FTxxYi8NWvf", "pycharm": {} }, "source": [ "### Data \n", "\n", "The data for this problem consists of a list of jobs. Each job is tagged with a unique ID along with numerical data giving the time at which the job will be released for machine processing, the expected duration, and the time at which it is due.\n", "\n", "| Symbol | Description \n", "| ------ | :---------- \n", "| $\\text{ID}_{j}$ | Unique ID for task $j$ \n", "| $\\text{due}_{j}$ | Due time for task $j$ \n", "| $\\text{duration}_{j}$ | Duration of task $j$ \n", "| $\\text{release}_{j}$ | Time task $j$ becomes available for processing " ] }, { "cell_type": "markdown", "metadata": { "id": "a0wt065kNWvg", "pycharm": {} }, "source": [ "### Decision variables\n", "\n", "For a single machine, the essential decision variable is the start time at which the job begins processing.\n", "\n", "| Symbol | Description |\n", "| ------ | :---------- |\n", "| $\\text{start}_{j}$ | Start of task $j$\n", "| $\\text{makespan}$ | Time to complete *all* jobs.\n", "| $\\text{pastdue}_{j}$ | Time by which task $j$ is past due\n", "| $\\text{early}_{j}$ | Time by which task $j$ is finished early\n", "\n", "A job cannot start until it is released for processing\n", "\n", "$$\n", "\\begin{align*}\n", "\\text{start}_{j} & \\geq \\text{release}_{j}\\\\\n", "\\end{align*}\n", "$$\n", "\n", "Once released for processing, we assume the processing continues until the job is finished. The finish time is compared to the due time, and the result stored in either the early or pastdue decision variables. These decision variables are needed to handle cases where it might not be possible to complete all jobs by the time they are due.\n", "\n", "$$\n", "\\begin{align*}\n", "\\text{start}_{j} + \\text{duration}_{j} + \\text{early}_{j} & = \\text{due}_{j} + \\text{pastdue}_{j}\\\\\n", "\\text{early}_{j} & \\geq 0 \\\\\n", "\\text{pastdue}_{j} & \\geq 0\n", "\\end{align*}\n", "$$\n", "\n", "Finally, we include a single decision variable measuring the overall makespan for all jobs.\n", "\n", "$$\n", "\\begin{align*}\n", "\\text{start}_{j} +\\text{duration}_{j} \\leq \\text{makespan}\n", "\\end{align*}\n", "$$\n", "\n", "The final set of constraints requires that, for any given pair of jobs $j$ and $k$, that either $j$ starts before $k$ finishes, or $k$ finishes before $j$ starts. The boolean variable $y_{j,k} = 0$ indicates $j$ finishes before $k$ starts, and is 1 for the opposing case. Note that we only need to consider cases $j > k$\n", "\n", "$$\n", "\\begin{align*}\n", "\\text{start}_{j}+\\text{duration}_{j} & \\leq \\text{start}_{k} + M y_{j, k}\\\\\n", "\\text{start}_{k}+\\text{duration}_{k} & \\leq \\text{start}_{j} + M (1 - y_{j,k})\n", "\\end{align*}\n", "$$\n", "\n", "where $M$ is a sufficiently large enough to assure the relaxed constraint is satisfied for all plausible values of the decision variables." ] }, { "cell_type": "markdown", "metadata": { "id": "EWahDDF8NWvh" }, "source": [ "## Big-M model\n", "\n", "We'll take a step-by-step approach to the construction of a \"Big-M\" model." ] }, { "cell_type": "markdown", "metadata": { "id": "EnGf_n3bNWvh" }, "source": [ "### Step 1. An incomplete bare-bones model\n", "\n", "We'll start this model building exercise with just enough variables and constraints to get an answer. This is not a complete model and will therefore give non-physical answers. But it does give a scaffold for further model building.\n", "\n", "This first model includes decision variables for the start and finish of each job, a decision variable for makespan, and constraints that define the relationships among these decision variables. The objective function is to minimize makespan." ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 531 }, "executionInfo": { "elapsed": 1554, "status": "ok", "timestamp": 1603385314372, "user": { "displayName": "Jeffrey Kantor", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14Gg_n8V7bVINy02QRuRgOoMo11Ri7NKU3OUKdC1bkQ=s64", "userId": "09038942003589296665" }, "user_tz": 240 }, "id": "MGiFz8RQNWvi", "outputId": "5edce33b-72c4-4e81-e3bc-5f8670d1aa3d" }, "outputs": [ { "data": { "text/plain": [ "{'Makespan': 8.0,\n", " 'Max Pastdue': 0,\n", " 'Sum of Pastdue': 0,\n", " 'Number Pastdue': 0,\n", " 'Number on Time': 7,\n", " 'Fraction on Time': 1.0}" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "def opt_schedule(JOBS):\n", "\n", " # create model\n", " m = ConcreteModel()\n", " \n", " # index set to simplify notation\n", " m.JOBS = Set(initialize=JOBS.keys())\n", "\n", " # decision variables\n", " m.start = Var(m.JOBS, domain=NonNegativeReals)\n", " m.finish = Var(m.JOBS, domain=NonNegativeReals)\n", " \n", " # additional decision variables for use in the objecive\n", " m.makespan = Var(domain=NonNegativeReals)\n", " \n", " # objective function\n", " m.OBJ = Objective(expr = m.makespan, sense = minimize)\n", " \n", " # constraints\n", " m.c = ConstraintList()\n", " for j in m.JOBS:\n", " m.c.add(m.finish[j] == m.start[j] + JOBS[j]['duration'])\n", " m.c.add(m.finish[j] <= m.makespan)\n", "\n", " SolverFactory('cbc').solve(m)\n", " \n", " SCHEDULE = {}\n", " for j in m.JOBS:\n", " SCHEDULE[j] = {'machine': 1, 'start': m.start[j](), 'finish': m.start[j]() + JOBS[j]['duration']}\n", " \n", " return SCHEDULE\n", "\n", "SCHEDULE = opt_schedule(JOBS)\n", "gantt(JOBS, SCHEDULE)\n", "kpi(JOBS, SCHEDULE)" ] }, { "cell_type": "markdown", "metadata": { "id": "4ZrRzf2JNWvk" }, "source": [ "### Step 2. Add release time information\n", "\n", "Obviously some jobs are being started before they are released for processing. The next version of the model adds that constraint." ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 531 }, "executionInfo": { "elapsed": 1069, "status": "ok", "timestamp": 1603385314835, "user": { "displayName": "Jeffrey Kantor", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14Gg_n8V7bVINy02QRuRgOoMo11Ri7NKU3OUKdC1bkQ=s64", "userId": "09038942003589296665" }, "user_tz": 240 }, "id": "a66vUj_8NWvl", "outputId": "10c3adb0-05ca-4315-9fc4-64ccc872b4d0" }, "outputs": [ { "data": { "text/plain": [ "{'Makespan': 12.0,\n", " 'Max Pastdue': 0,\n", " 'Sum of Pastdue': 0,\n", " 'Number Pastdue': 0,\n", " 'Number on Time': 7,\n", " 'Fraction on Time': 1.0}" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "def opt_schedule(JOBS):\n", "\n", " # create model\n", " m = ConcreteModel()\n", " \n", " # index set to simplify notation\n", " m.JOBS = Set(initialize=JOBS.keys())\n", "\n", " # decision variables\n", " m.start = Var(m.JOBS, domain=NonNegativeReals)\n", " m.finish = Var(m.JOBS, domain=NonNegativeReals)\n", " \n", " # additional decision variables for use in the objecive\n", " m.makespan = Var(domain=NonNegativeReals)\n", " \n", " # objective function\n", " m.OBJ = Objective(expr = m.makespan, sense = minimize)\n", " \n", " # constraints\n", " m.c = ConstraintList()\n", " for j in m.JOBS:\n", " m.c.add(m.finish[j] == m.start[j] + JOBS[j]['duration'])\n", " m.c.add(m.finish[j] <= m.makespan)\n", " m.c.add(m.start[j] >= JOBS[j]['release'])\n", "\n", " SolverFactory('cbc').solve(m)\n", " \n", " SCHEDULE = {}\n", " for j in m.JOBS:\n", " SCHEDULE[j] = {'machine': 1, 'start': m.start[j](), 'finish': m.start[j]() + JOBS[j]['duration']}\n", " \n", " return SCHEDULE\n", "\n", "SCHEDULE = opt_schedule(JOBS)\n", "gantt(JOBS, SCHEDULE)\n", "kpi(JOBS, SCHEDULE)" ] }, { "cell_type": "markdown", "metadata": { "id": "lizCuCEONWvo" }, "source": [ "### Step 3. Machine conflict constraints" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 531 }, "executionInfo": { "elapsed": 1776, "status": "ok", "timestamp": 1603385316081, "user": { "displayName": "Jeffrey Kantor", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14Gg_n8V7bVINy02QRuRgOoMo11Ri7NKU3OUKdC1bkQ=s64", "userId": "09038942003589296665" }, "user_tz": 240 }, "id": "dY37StTkNWvo", "outputId": "0501bae9-7876-494a-e080-5e839aa5384a" }, "outputs": [ { "data": { "text/plain": [ "{'Makespan': 30.0,\n", " 'Max Pastdue': 15.0,\n", " 'Sum of Pastdue': 31.0,\n", " 'Number Pastdue': 4,\n", " 'Number on Time': 3,\n", " 'Fraction on Time': 0.42857142857142855}" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "def opt_schedule(JOBS):\n", "\n", " # create model\n", " m = ConcreteModel()\n", " \n", " # index set to simplify notation\n", " m.JOBS = Set(initialize=JOBS.keys())\n", " m.PAIRS = Set(initialize = m.JOBS * m.JOBS, dimen=2, filter=lambda m, j, k : j < k)\n", "\n", " # decision variables\n", " m.start = Var(m.JOBS, domain=NonNegativeReals)\n", " m.finish = Var(m.JOBS, domain=NonNegativeReals)\n", " m.y = Var(m.PAIRS, domain=Boolean)\n", " \n", " # additional decision variables for use in the objecive\n", " m.makespan = Var(domain=NonNegativeReals)\n", " \n", " # objective function\n", " m.OBJ = Objective(expr = m.makespan, sense = minimize)\n", " \n", " # constraints\n", " m.c = ConstraintList()\n", " for j in m.JOBS:\n", " m.c.add(m.finish[j] == m.start[j] + JOBS[j]['duration'])\n", " m.c.add(m.finish[j] <= m.makespan)\n", " m.c.add(m.start[j] >= JOBS[j]['release'])\n", " \n", " M = 100.0\n", " for j,k in m.PAIRS:\n", " m.c.add(m.finish[j] <= m.start[k] + M*m.y[j,k])\n", " m.c.add(m.finish[k] <= m.start[j] + M*(1 - m.y[j,k]))\n", "\n", " SolverFactory('cbc').solve(m)\n", " \n", " SCHEDULE = {}\n", " for j in m.JOBS:\n", " SCHEDULE[j] = {'machine': 1, 'start': m.start[j](), 'finish': m.start[j]() + JOBS[j]['duration']}\n", " \n", " return SCHEDULE\n", "\n", "SCHEDULE = opt_schedule(JOBS)\n", "gantt(JOBS, SCHEDULE)\n", "kpi(JOBS, SCHEDULE)" ] }, { "cell_type": "markdown", "metadata": { "id": "ppUqTYRNNWvr" }, "source": [ "### Step 4. Improve the objective function" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 531 }, "executionInfo": { "elapsed": 2248, "status": "ok", "timestamp": 1603385318147, "user": { "displayName": "Jeffrey Kantor", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14Gg_n8V7bVINy02QRuRgOoMo11Ri7NKU3OUKdC1bkQ=s64", "userId": "09038942003589296665" }, "user_tz": 240 }, "id": "NneMXj3FNWvr", "outputId": "c4b3c4da-7f4c-4620-890d-cc39218a17c9" }, "outputs": [ { "data": { "text/plain": [ "{'Makespan': 30.0,\n", " 'Max Pastdue': 15.0,\n", " 'Sum of Pastdue': 16.0,\n", " 'Number Pastdue': 2,\n", " 'Number on Time': 5,\n", " 'Fraction on Time': 0.7142857142857143}" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "def opt_schedule(JOBS):\n", "\n", " # create model\n", " m = ConcreteModel()\n", " \n", " # index set to simplify notation\n", " m.JOBS = Set(initialize=JOBS.keys())\n", " m.PAIRS = Set(initialize = m.JOBS * m.JOBS, dimen=2, filter=lambda m, j, k : j < k)\n", "\n", " # decision variables\n", " m.start = Var(m.JOBS, domain=NonNegativeReals)\n", " m.finish = Var(m.JOBS, domain=NonNegativeReals)\n", " m.pastdue = Var(m.JOBS, domain=NonNegativeReals)\n", " m.y = Var(m.PAIRS, domain=Boolean)\n", " \n", " # additional decision variables for use in the objecive\n", " m.makespan = Var(domain=NonNegativeReals)\n", " \n", " # objective function\n", " m.OBJ = Objective(expr = sum(m.pastdue[j] for j in m.JOBS), sense = minimize)\n", " \n", " # constraints\n", " m.c = ConstraintList()\n", " for j in m.JOBS:\n", " m.c.add(m.finish[j] == m.start[j] + JOBS[j]['duration'])\n", " m.c.add(m.finish[j] <= m.makespan)\n", " m.c.add(m.start[j] >= JOBS[j]['release'])\n", " m.c.add(m.finish[j] <= JOBS[j]['due'] + m.pastdue[j])\n", " \n", " M = 100.0\n", " for j,k in m.PAIRS:\n", " m.c.add(m.finish[j] <= m.start[k] + M*m.y[j,k])\n", " m.c.add(m.finish[k] <= m.start[j] + M*(1 - m.y[j,k]))\n", "\n", " SolverFactory('cbc').solve(m)\n", " \n", " SCHEDULE = {}\n", " for j in m.JOBS:\n", " SCHEDULE[j] = {'machine': 1, 'start': m.start[j](), 'finish': m.start[j]() + JOBS[j]['duration']}\n", " \n", " return SCHEDULE\n", "\n", "SCHEDULE = opt_schedule(JOBS)\n", "gantt(JOBS, SCHEDULE)\n", "kpi(JOBS, SCHEDULE)" ] }, { "cell_type": "markdown", "metadata": { "id": "359pH_kYpGbI", "pycharm": {} }, "source": [ "## Pyomo model" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 1000 }, "executionInfo": { "elapsed": 1958, "status": "ok", "timestamp": 1603385318472, "user": { "displayName": "Jeffrey Kantor", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14Gg_n8V7bVINy02QRuRgOoMo11Ri7NKU3OUKdC1bkQ=s64", "userId": "09038942003589296665" }, "user_tz": 240 }, "id": "_k6LYB3opGbJ", "outputId": "f664d653-a89f-4dfd-b5de-0576fc36fa86", "pycharm": {} }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "WARNING: DEPRECATED: The 'gdp.chull' name is deprecated. Please use the more\n", " apt 'gdp.hull' instead. (deprecated in 5.7) (called from /var/folders/cm/\n", " z3t28j296f98jdp1vqyplkz00000gn/T/ipykernel_40244/3310811304.py:38)\n", "# ==========================================================\n", "# = Solver Results =\n", "# ==========================================================\n", "# ----------------------------------------------------------\n", "# Problem Information\n", "# ----------------------------------------------------------\n", "Problem: \n", "- Name: unknown\n", " Lower bound: 16.0\n", " Upper bound: 16.0\n", " Number of objectives: 1\n", " Number of constraints: 133\n", " Number of variables: 77\n", " Number of binary variables: 49\n", " Number of integer variables: 49\n", " Number of nonzeros: 7\n", " Sense: minimize\n", "# ----------------------------------------------------------\n", "# Solver Information\n", "# ----------------------------------------------------------\n", "Solver: \n", "- Status: ok\n", " User time: -1.0\n", " System time: 0.35\n", " Wallclock time: 0.36\n", " Termination condition: optimal\n", " Termination message: Model was solved to optimality (subject to tolerances), and an optimal solution is available.\n", " Statistics: \n", " Branch and bound: \n", " Number of bounded subproblems: 30\n", " Number of created subproblems: 30\n", " Black box: \n", " Number of iterations: 4834\n", " Error rc: 0\n", " Time: 0.39235997200012207\n", "# ----------------------------------------------------------\n", "# Solution Information\n", "# ----------------------------------------------------------\n", "Solution: \n", "- number of solutions: 0\n", " number of solutions displayed: 0\n" ] }, { "data": { "text/plain": [ "{'Makespan': 30.0,\n", " 'Max Pastdue': 15.0,\n", " 'Sum of Pastdue': 16.0,\n", " 'Number Pastdue': 2,\n", " 'Number on Time': 5,\n", " 'Fraction on Time': 0.7142857142857143}" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "def opt_schedule(JOBS):\n", "\n", " # create model\n", " m = ConcreteModel()\n", " \n", " # index set to simplify notation\n", " m.J = Set(initialize=JOBS.keys())\n", " m.PAIRS = Set(initialize = m.J * m.J, dimen=2, filter=lambda m, j, k : j < k)\n", "\n", " # upper bounds on how long it would take to process all jobs\n", " tmax = max([JOBS[j]['release'] for j in m.J]) + sum([JOBS[j]['duration'] for j in m.J])\n", "\n", " # decision variables\n", " m.start = Var(m.J, domain=NonNegativeReals, bounds=(0, tmax))\n", " m.pastdue = Var(m.J, domain=NonNegativeReals, bounds=(0, tmax))\n", " m.early = Var(m.J, domain=NonNegativeReals, bounds=(0, tmax))\n", " \n", " # additional decision variables for use in the objecive\n", " m.makespan = Var(domain=NonNegativeReals, bounds=(0, tmax))\n", " m.maxpastdue = Var(domain=NonNegativeReals, bounds=(0, tmax))\n", " m.ispastdue = Var(m.J, domain=Binary)\n", "\n", " # objective function\n", " m.OBJ = Objective(expr = sum([m.pastdue[j] for j in m.J]), sense = minimize)\n", "\n", " # constraints\n", " m.c1 = Constraint(m.J, rule=lambda m, j: m.start[j] >= JOBS[j]['release'])\n", " m.c2 = Constraint(m.J, rule=lambda m, j: \n", " m.start[j] + JOBS[j]['duration'] + m.early[j] == JOBS[j]['due'] + m.pastdue[j])\n", " m.c3 = Disjunction(m.PAIRS, rule=lambda m, j, k:\n", " [m.start[j] + JOBS[j]['duration'] <= m.start[k], \n", " m.start[k] + JOBS[k]['duration'] <= m.start[j]]) \n", " \n", " m.c4 = Constraint(m.J, rule=lambda m, j: m.pastdue[j] <= m.maxpastdue)\n", " m.c5 = Constraint(m.J, rule=lambda m, j: m.start[j] + JOBS[j]['duration'] <= m.makespan)\n", " m.c6 = Constraint(m.J, rule=lambda m, j: m.pastdue[j] <= tmax*m.ispastdue[j])\n", " \n", " TransformationFactory('gdp.chull').apply_to(m)\n", " SolverFactory('cbc').solve(m).write()\n", " \n", " SCHEDULE = {}\n", " for j in m.J:\n", " SCHEDULE[j] = {'machine': 1, 'start': m.start[j](), 'finish': m.start[j]() + JOBS[j]['duration']}\n", " \n", " return SCHEDULE\n", "\n", "SCHEDULE = opt_schedule(JOBS)\n", "gantt(JOBS, SCHEDULE)\n", "kpi(JOBS, SCHEDULE)" ] }, { "cell_type": "markdown", "metadata": { "id": "dsoH5DREpGbO", "pycharm": {} }, "source": [ "## Multiple machines\n", "\n", "The case of multiple machines requires a modest extension of model described above. Given a set $M$ of machines, we introduce an additional decision binary variable $z_{j,m}$ indicating if job $j$ has been assigned to machine $m$. The additional constraints\n", "\n", "$$\n", "\\begin{align*}\n", "\\sum_{m\\in M}z_{j,m} & = 1 & \\forall j\n", "\\end{align*}\n", "$$\n", "\n", "require each job to be assigned to exactly one machine for processing. \n", "\n", "If both jobs $j$ and $k$ have been assigned to machine $m$, then the disjunctive ordering constraints must apply. This logic is equivalent to the following constraints for $j < k$.\n", "\n", "$$\n", "\\begin{align*}\n", "\\text{start}_{j}+\\text{duration}_{j} & \\leq \\text{start}_{k}+My_{j,k} + M(1-z_{j,m}) + M(1-z_{k,m})\\\\\n", "\\text{start}_{k}+\\text{duration}_{k} & \\leq \\text{start}_{j}+M(1-y_{j,k}) + M(1-z_{j,m}) + M(1-z_{k,m}))\n", "\\end{align*}\n", "$$" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 1000 }, "executionInfo": { "elapsed": 1512, "status": "ok", "timestamp": 1603385569239, "user": { "displayName": "Jeffrey Kantor", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14Gg_n8V7bVINy02QRuRgOoMo11Ri7NKU3OUKdC1bkQ=s64", "userId": "09038942003589296665" }, "user_tz": 240 }, "id": "e-TSDVXUpGbO", "outputId": "683b0fec-d322-416f-cb09-045f1942189a", "pycharm": {} }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "# ==========================================================\n", "# = Solver Results =\n", "# ==========================================================\n", "# ----------------------------------------------------------\n", "# Problem Information\n", "# ----------------------------------------------------------\n", "Problem: \n", "- Name: unknown\n", " Lower bound: -15.0\n", " Upper bound: -15.0\n", " Number of objectives: 1\n", " Number of constraints: 98\n", " Number of variables: 50\n", " Number of binary variables: 42\n", " Number of integer variables: 42\n", " Number of nonzeros: 15\n", " Sense: minimize\n", "# ----------------------------------------------------------\n", "# Solver Information\n", "# ----------------------------------------------------------\n", "Solver: \n", "- Status: ok\n", " User time: -1.0\n", " System time: 0.39\n", " Wallclock time: 0.42\n", " Termination condition: optimal\n", " Termination message: Model was solved to optimality (subject to tolerances), and an optimal solution is available.\n", " Statistics: \n", " Branch and bound: \n", " Number of bounded subproblems: 128\n", " Number of created subproblems: 128\n", " Black box: \n", " Number of iterations: 2921\n", " Error rc: 0\n", " Time: 0.44847798347473145\n", "# ----------------------------------------------------------\n", "# Solution Information\n", "# ----------------------------------------------------------\n", "Solution: \n", "- number of solutions: 0\n", " number of solutions displayed: 0\n" ] }, { "data": { "text/plain": [ "{'Makespan': 15.0,\n", " 'Max Pastdue': 0,\n", " 'Sum of Pastdue': 0,\n", " 'Number Pastdue': 0,\n", " 'Number on Time': 7,\n", " 'Fraction on Time': 1.0}" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "MACHINES = ['A','B']\n", "\n", "def schedule_machines(JOBS, MACHINES):\n", " \n", " # create model\n", " m = ConcreteModel()\n", " \n", " # index set to simplify notation\n", " m.J = Set(initialize=JOBS.keys())\n", " m.M = Set(initialize=MACHINES)\n", " m.PAIRS = Set(initialize = m.J * m.J, dimen=2, filter=lambda m, j, k : j < k)\n", "\n", " # decision variables\n", " m.start = Var(m.J, bounds=(0, 1000))\n", " m.makespan = Var(domain=NonNegativeReals)\n", " m.pastdue = Var(m.J, domain=NonNegativeReals)\n", " m.early = Var(m.J, domain=NonNegativeReals)\n", " \n", " # additional decision variables for use in the objecive\n", " m.ispastdue = Var(m.J, domain=Binary)\n", " m.maxpastdue = Var(domain=NonNegativeReals)\n", " \n", " # for binary assignment of jobs to machines\n", " m.z = Var(m.J, m.M, domain=Binary)\n", "\n", " # for modeling disjunctive constraints\n", " m.y = Var(m.PAIRS, domain=Binary)\n", " BigM = max([JOBS[j]['release'] for j in m.J]) + sum([JOBS[j]['duration'] for j in m.J])\n", "\n", " m.OBJ = Objective(expr = sum(m.pastdue[j] for j in m.J) + m.makespan - sum(m.early[j] for j in m.J), sense = minimize)\n", "\n", " m.c1 = Constraint(m.J, rule=lambda m, j: \n", " m.start[j] >= JOBS[j]['release'])\n", " m.c2 = Constraint(m.J, rule=lambda m, j:\n", " m.start[j] + JOBS[j]['duration'] + m.early[j] == JOBS[j]['due'] + m.pastdue[j])\n", " m.c3 = Constraint(m.J, rule=lambda m, j: \n", " sum(m.z[j,mach] for mach in m.M) == 1)\n", " m.c4 = Constraint(m.J, rule=lambda m, j: \n", " m.pastdue[j] <= BigM*m.ispastdue[j])\n", " m.c5 = Constraint(m.J, rule=lambda m, j: \n", " m.pastdue[j] <= m.maxpastdue)\n", " m.c6 = Constraint(m.J, rule=lambda m, j: \n", " m.start[j] + JOBS[j]['duration'] <= m.makespan)\n", " m.d1 = Constraint(m.M, m.PAIRS, rule = lambda m, mach, j, k:\n", " m.start[j] + JOBS[j]['duration'] <= m.start[k] + BigM*(m.y[j,k] + (1-m.z[j,mach]) + (1-m.z[k,mach])))\n", " m.d2 = Constraint(m.M, m.PAIRS, rule = lambda m, mach, j, k: \n", " m.start[k] + JOBS[k]['duration'] <= m.start[j] + BigM*((1-m.y[j,k]) + (1-m.z[j,mach]) + (1-m.z[k,mach])))\n", " \n", " SolverFactory('cbc').solve(m).write()\n", " \n", " SCHEDULE = {}\n", " for j in m.J:\n", " SCHEDULE[j] = {\n", " 'start': m.start[j](), \n", " 'finish': m.start[j]() + JOBS[j]['duration'],\n", " 'machine': [mach for mach in MACHINES if m.z[j,mach]()][0]\n", " }\n", " \n", " return SCHEDULE\n", " \n", "SCHEDULE = schedule_machines(JOBS,MACHINES)\n", "gantt(JOBS, SCHEDULE)\n", "kpi(JOBS, SCHEDULE)" ] }, { "cell_type": "markdown", "metadata": { "id": "R_TiaDliNWv3" }, "source": [ "## Disjunctive Version" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 1000 }, "executionInfo": { "elapsed": 3717, "status": "ok", "timestamp": 1603386106835, "user": { "displayName": "Jeffrey Kantor", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14Gg_n8V7bVINy02QRuRgOoMo11Ri7NKU3OUKdC1bkQ=s64", "userId": "09038942003589296665" }, "user_tz": 240 }, "id": "Ulg_ACa9NWv3", "outputId": "25e05260-b897-4662-973e-65d2ed18dc98" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "# ==========================================================\n", "# = Solver Results =\n", "# ==========================================================\n", "# ----------------------------------------------------------\n", "# Problem Information\n", "# ----------------------------------------------------------\n", "Problem: \n", "- Name: unknown\n", " Lower bound: -15.0\n", " Upper bound: -15.0\n", " Number of objectives: 1\n", " Number of constraints: 637\n", " Number of variables: 435\n", " Number of binary variables: 133\n", " Number of integer variables: 133\n", " Number of nonzeros: 15\n", " Sense: minimize\n", "# ----------------------------------------------------------\n", "# Solver Information\n", "# ----------------------------------------------------------\n", "Solver: \n", "- Status: ok\n", " User time: -1.0\n", " System time: 0.8\n", " Wallclock time: 0.81\n", " Termination condition: optimal\n", " Termination message: Model was solved to optimality (subject to tolerances), and an optimal solution is available.\n", " Statistics: \n", " Branch and bound: \n", " Number of bounded subproblems: 83\n", " Number of created subproblems: 83\n", " Black box: \n", " Number of iterations: 2981\n", " Error rc: 0\n", " Time: 0.837306022644043\n", "# ----------------------------------------------------------\n", "# Solution Information\n", "# ----------------------------------------------------------\n", "Solution: \n", "- number of solutions: 0\n", " number of solutions displayed: 0\n" ] }, { "data": { "text/plain": [ "{'Makespan': 15.0,\n", " 'Max Pastdue': 0,\n", " 'Sum of Pastdue': 0,\n", " 'Number Pastdue': 0,\n", " 'Number on Time': 7,\n", " 'Fraction on Time': 1.0}" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "MACHINES = ['A','B']\n", "\n", "def schedule_machines(JOBS, MACHINES):\n", " \n", " # create model\n", " m = ConcreteModel()\n", " \n", " # index set to simplify notation\n", " m.J = Set(initialize=JOBS.keys())\n", " m.M = Set(initialize=MACHINES)\n", " m.PAIRS = Set(initialize = m.J * m.J, dimen=2, filter=lambda m, j, k : j < k)\n", "\n", " # decision variables\n", " m.start = Var(m.J, bounds=(0, 1000))\n", " m.makespan = Var(domain=NonNegativeReals)\n", " m.pastdue = Var(m.J, bounds=(0, 1000))\n", " m.early = Var(m.J, bounds=(0, 10000))\n", " \n", " # additional decision variables for use in the objecive\n", " m.ispastdue = Var(m.J, domain=Binary)\n", " m.maxpastdue = Var(domain=NonNegativeReals)\n", " \n", " # for binary assignment of jobs to machines\n", " m.z = Var(m.J, m.M, domain=Binary)\n", "\n", " # for modeling disjunctive constraints\n", " BigM = max([JOBS[j]['release'] for j in m.J]) + sum([JOBS[j]['duration'] for j in m.J])\n", "\n", " m.OBJ = Objective(expr = sum(m.pastdue[j] for j in m.J) + m.makespan - sum(m.early[j] for j in m.J), sense = minimize)\n", "\n", " # job starts after it is released\n", " m.c1 = Constraint(m.J, rule=lambda m, j: m.start[j] >= JOBS[j]['release'])\n", "\n", " # defines early and pastdue\n", " m.c2 = Constraint(m.J, rule=lambda m, j: m.start[j] + JOBS[j]['duration'] + m.early[j] == JOBS[j]['due'] + m.pastdue[j])\n", " m.d1 = Disjunction(m.J, rule=lambda m, j: [m.early[j]==0, m.pastdue[j]==0])\n", "\n", " # each job is assigned to one and only one machine\n", " m.c3 = Constraint(m.J, rule=lambda m, j: sum(m.z[j, mach] for mach in m.M) == 1)\n", "\n", " # defines a binary variable indicating if a job is past due\n", " m.c4 = Disjunction(m.J, rule=lambda m, j: [m.pastdue[j] == 0, m.ispastdue[j] == 1])\n", "\n", " # all jobs must be finished before max pastdue\n", " m.c5 = Constraint(m.J, rule=lambda m, j: m.pastdue[j] <= m.maxpastdue)\n", "\n", " # defining make span\n", " m.c6 = Constraint(m.J, rule=lambda m, j: m.start[j] + JOBS[j]['duration'] <= m.makespan)\n", " \n", " # disjuctions\n", " m.d0 = Disjunction(m.M, m.PAIRS, rule = lambda m, mach, j, k: \n", " [m.start[j] + JOBS[j]['duration'] <= m.start[k] + BigM*((1-m.z[j, mach]) + (1-m.z[k, mach])),\n", " m.start[k] + JOBS[k]['duration'] <= m.start[j] + BigM*((1-m.z[j, mach]) + (1-m.z[k, mach]))])\n", " \n", " transform = TransformationFactory('gdp.hull')\n", " transform.apply_to(m)\n", "\n", " SolverFactory('cbc').solve(m).write()\n", " \n", " SCHEDULE = {}\n", " for j in m.J:\n", " SCHEDULE[j] = {\n", " 'start': m.start[j](), \n", " 'finish': m.start[j]() + JOBS[j]['duration'],\n", " 'machine': [mach for mach in MACHINES if m.z[j,mach]()][0]\n", " }\n", " \n", " return SCHEDULE\n", " \n", "SCHEDULE = schedule_machines(JOBS,MACHINES)\n", "gantt(JOBS, SCHEDULE)\n", "kpi(JOBS, SCHEDULE)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "nFs4fzouNWv6" }, "outputs": [], "source": [] } ], "metadata": { "celltoolbar": "Tags", "colab": { "collapsed_sections": [], "name": "04.02-Machine-Bottleneck.ipynb", "provenance": [], "toc_visible": true }, "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.9.7" } }, "nbformat": 4, "nbformat_minor": 4 }