{ "cells": [ { "cell_type": "markdown", "metadata": { "pycharm": {} }, "source": [ "\n", "*This notebook contains course material from [CBE40455](https://jckantor.github.io/CBE40455) by\n", "Jeffrey Kantor (jeff at nd.edu); the content is available [on Github](https://github.com/jckantor/CBE40455.git).\n", "The text is released under the [CC-BY-NC-ND-4.0 license](https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode),\n", "and code is released under the [MIT license](https://opensource.org/licenses/MIT).*" ] }, { "cell_type": "markdown", "metadata": { "pycharm": {} }, "source": [ "\n", "< [Scheduling](http://nbviewer.jupyter.org/github/jckantor/CBE40455/blob/master/notebooks/04.00-Scheduling.ipynb) | [Contents](toc.ipynb) | [Machine Bottleneck](http://nbviewer.jupyter.org/github/jckantor/CBE40455/blob/master/notebooks/04.02-Machine-Bottleneck.ipynb) >

\"Open

\"Download\"" ] }, { "cell_type": "markdown", "metadata": { "pycharm": {} }, "source": [ "# Critical Path Method" ] }, { "cell_type": "markdown", "metadata": { "pycharm": {} }, "source": [ "This notebook demonstrates the Critical Path Method using GLPK/MathProg." ] }, { "cell_type": "markdown", "metadata": { "pycharm": {} }, "source": [ "## Background" ] }, { "cell_type": "markdown", "metadata": { "pycharm": {} }, "source": [ "The Critical Path Method is a technique for calculating the shortest time span needed to complete a series of tasks. The tasks are represented by nodes, each labelled with the duration. The precedence order of the task is given by a set of arcs.\n", "\n", "Here we demonstrate the representation and calculation of the critical path. Decision variables are introduced for\n", "\n", "* Earliest Start\n", "* Earliest Finish\n", "* Latest Start\n", "* Latest Finish\n", "* Slack = Earliest Finish - Earliest Start = Latest Finish - Earliest Finish\n", "\n", "Tasks on the Critical Path have zero slack." ] }, { "cell_type": "markdown", "metadata": { "pycharm": {} }, "source": [ "## MathProg Model" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false, "pycharm": {} }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Overwriting ProjectCPM.mod\n" ] } ], "source": [ "%%writefile ProjectCPM.mod\n", "\n", "# Example: ProjectCPM.mod\n", "\n", "set TASKS;\n", "set ARCS within {TASKS cross TASKS};\n", "\n", "/* Parameters are the durations for each task */\n", "param dur{TASKS} >= 0;\n", "param desc{TASKS} symbolic;\n", "\n", "/* Decision Variables associated with each task*/\n", "var Tes{TASKS} >= 0; # Earliest Start\n", "var Tef{TASKS} >= 0; # Earliest Finish\n", "var Tls{TASKS} >= 0; # Latest Start\n", "var Tlf{TASKS} >= 0; # Latest Finish\n", "var Tsl{TASKS} >= 0; # Slacks\n", "\n", "/* Global finish time */\n", "var Tf >= 0;\n", "\n", "/* Minimize the global finish time and, secondarily, maximize slacks */\n", "minimize ProjectFinish : card(TASKS)*Tf - sum {j in TASKS} Tsl[j];\n", "\n", "/* Finish is the least upper bound on the finish time for all tasks */\n", "s.t. Efnsh {j in TASKS} : Tef[j] <= Tf;\n", "s.t. Lfnsh {j in TASKS} : Tlf[j] <= Tf;\n", "\n", "/* Relationship between start and finish times for each task */\n", "s.t. Estrt {j in TASKS} : Tef[j] = Tes[j] + dur[j];\n", "s.t. Lstrt {j in TASKS} : Tlf[j] = Tls[j] + dur[j];\n", "\n", "/* Slacks */\n", "s.t. Slack {j in TASKS} : Tsl[j] = Tls[j] - Tes[j];\n", "\n", "/* Task ordering */\n", "s.t. Eordr {(i,j) in ARCS} : Tef[i] <= Tes[j];\n", "s.t. Lordr {(j,k) in ARCS} : Tlf[j] <= Tls[k];\n", "\n", "/* Compute Solution */\n", "solve;\n", "\n", "/* Print Report */\n", "printf 'PROJECT LENGTH = %8g\\n',Tf;\n", "\n", "/* Critical Tasks are those with zero slack */\n", "\n", "/* Rank-order tasks on the critical path by earliest start time */\n", "param r{j in TASKS : Tsl[j] = 0} := sum{k in TASKS : Tsl[k] = 0}\n", " if (Tes[k] <= Tes[j]) then 1;\n", "\n", "printf '\\nCRITICAL PATH\\n';\n", "printf ' TASK DUR Start Finish Description\\n';\n", "printf {k in 1..card(TASKS), j in TASKS : Tsl[j]=0 && k==r[j]}\n", " '%6s %4g %8g %8g %-25s\\n', j, dur[j], Tes[j], Tef[j], desc[j];\n", "\n", "/* Noncritical Tasks have positive slack */\n", "\n", "/* Rank-order tasks not on the critical path by earliest start time */\n", "param s{j in TASKS : Tsl[j] > 0} := sum{k in TASKS : Tsl[k] = 0}\n", " if (Tes[k] <= Tes[j]) then 1;\n", "\n", "printf '\\nNON-CRITICAL TASKS\\n';\n", "printf ' Earliest Earliest Latest Latest \\n';\n", "printf ' TASK DUR Start Finish Start Finish Slack Description\\n';\n", "printf {k in 1..card(TASKS), j in TASKS : Tsl[j] > 0 && k==s[j]}\n", " '%6s %4g %8g %8g %8g %8g %8g %-25s\\n', \n", " j,dur[j],Tes[j],Tef[j],Tls[j],Tlf[j],Tsl[j],desc[j];\n", "printf '\\n';\n", "\n", "end;\n" ] }, { "cell_type": "markdown", "metadata": { "pycharm": {} }, "source": [ "## Example: Stadium Construction" ] }, { "cell_type": "markdown", "metadata": { "pycharm": {} }, "source": [ "Stadium Construction, [Example 7.1.1](http://www.maximalsoftware.com/modellib/modXpressMP.html) from [Christelle Gueret, Christian Prins, Marc Sevaux, \"Applications of Optimization with Xpress-MP,\" Chapter 7, Dash Optimization, 2000](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.69.9634&rep=rep1&type=pdf)." ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false, "pycharm": {} }, "outputs": [], "source": [ "%%script glpsol -m ProjectCPM.mod -d /dev/stdin -y ProjectCPM.txt --out output\n", "\n", "param : TASKS : dur desc :=\n", " T01 2.0 'Installing the contruction site'\n", " T02 16.0 'Terracing'\n", " T03 9.0 'Constructing the foundations'\n", " T04 8.0 'Access roads and other networks'\n", " T05 10.0 'Erecting the basement'\n", " T06 6.0 'Main floor'\n", " T07 2.0 'Dividing up the changing rooms'\n", " T08 2.0 'Electrifying the terraces'\n", " T09 9.0 'Constructing the roof'\n", " T10 5.0 'Lighting the stadium'\n", " T11 3.0 'Installing the terraces'\n", " T12 2.0 'Sealing the roof'\n", " T13 1.0 'Finishing the changing rooms'\n", " T14 7.0 'Constructing the ticket office'\n", " T15 4.0 'Secondary access roads'\n", " T16 3.0 'Means of signaling'\n", " T17 9.0 'Lawn and sports accessories'\n", " T18 1.0 'Handing over the building' ;\n", "\n", "set ARCS := \n", " T01 T02\n", " T02 T03\n", " T02 T04\n", " T02 T14\n", " T03 T05\n", " T04 T07\n", " T04 T10\n", " T04 T09\n", " T04 T06\n", " T04 T15\n", " T05 T06\n", " T06 T09\n", " T06 T11\n", " T06 T08\n", " T07 T13\n", " T08 T16\n", " T09 T12\n", " T11 T16\n", " T12 T17\n", " T14 T16\n", " T14 T15\n", " T17 T18 ;\n", "\n", "end;\n" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false, "pycharm": {} }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "PROJECT LENGTH = 64\n", "\n", "CRITICAL PATH\n", " TASK DUR Start Finish Description\n", " T01 2 0 2 Installing the contruction site\n", " T02 16 2 18 Terracing \n", " T03 9 18 27 Constructing the foundations\n", " T05 10 27 37 Erecting the basement \n", " T06 6 37 43 Main floor \n", " T09 9 43 52 Constructing the roof \n", " T12 2 52 54 Sealing the roof \n", " T17 9 54 63 Lawn and sports accessories\n", " T18 1 63 64 Handing over the building\n", "\n", "NON-CRITICAL TASKS\n", " Earliest Earliest Latest Latest \n", " TASK DUR Start Finish Start Finish Slack Description\n", " T04 8 18 26 29 37 11 Access roads and other networks\n", " T07 2 26 28 61 63 35 Dividing up the changing rooms\n", " T10 5 26 31 59 64 33 Lighting the stadium \n", " T14 7 18 25 53 60 35 Constructing the ticket office\n", " T15 4 26 30 60 64 34 Secondary access roads \n", " T13 1 28 29 63 64 35 Finishing the changing rooms\n", " T08 2 43 45 59 61 16 Electrifying the terraces\n", " T11 3 43 46 58 61 15 Installing the terraces \n", " T16 3 46 49 61 64 15 Means of signaling \n", "\n", "\n" ] } ], "source": [ "f = open('ProjectCPM.txt')\n", "print f.read()\n", "f.close()" ] }, { "cell_type": "markdown", "metadata": { "pycharm": {} }, "source": [ "## Visualization" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false, "pycharm": {} }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/Users/jeff/anaconda/lib/python2.7/site-packages/matplotlib/collections.py:650: FutureWarning: elementwise comparison failed; returning scalar instead, but in the future will perform elementwise comparison\n", " if self._edgecolors_original != str('face'):\n", "/Users/jeff/anaconda/lib/python2.7/site-packages/matplotlib/collections.py:590: FutureWarning: elementwise comparison failed; returning scalar instead, but in the future will perform elementwise comparison\n", " if self._edgecolors == str('face'):\n" ] }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAd8AAAFBCAYAAAA2bKVrAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzt3Xtc1FX+P/DXIANyV0bQwLuWCRoDrnlJstTWNhUVNOlq\nWUlhYt6WLpb7TdvVn0miiWGpbfZ1sJXR4GvZN7Uky7aviKhgl2VUMFIJZRCFmYE5vz8UVlaQuX7m\nwuv5eMzDXebz+cz7Y8XrnDPnc45MCCFAREREkvFwdAFERETtDcOXiIhIYgxfIiIiiTF8iYiIJMbw\nJSIikhjDl4iISGIMXyIiIokxfImIiCTG8CUiIpIYw5eIiEhiDF8iIiKJMXyJiIgkxvAlIiKSGMOX\niIhIYgxfIiIiiTF8iYiIJMbwJSIikhjDl4iISGIMXyIiIokxfImIiCTG8CUiIpIYw5eIiEhiDF8i\nIiKJMXyJiIgkxvAlIiKSGMOXiIhIYgxfIiIiiTF8iYiIJMbwJSIikhjDl4iISGIMXyIiIokxfImI\niCTG8CUiIpIYw5eIiEhiDF8iIiKJMXyJiIgkxvAlIiKSGMOXiIhIYgxfIiIiiTF8iYiIJMbwJSIi\nkhjDl4iISGIMXyIiIokxfImIiCTG8CUiIpIYw5eIiEhiDF8iIiKJMXyJiIgkxvAlIiKSGMOXiIhI\nYgxfIiIiiTF8iYiIJMbwJSIikhjDl4iISGIMXyIiIokxfImIiCTG8CUiIpKYp6MLICJyRVqtFpWV\nlQAAhUKBoKAgB1dEroQ9XyIiE+l0OqhUKsQqlQgPCcHYqCiMjYpCeEgIYpVKqFQq6PV6R5dJLkAm\nhBCOLoKIyNltz8rCvKQkDBYCyZcvYxL+PXRoAJALIMPfHyc8PJCemYkZiYmOK5acHsOXiKgNa9PS\n8PaSJdhZW4shbRybD2Cqry8WLVuGlAULpCiPXBDDl4joFrZnZWHxrFk4WFuLniaeUwpglK8vVm3a\nxB4wtYjhS0TUCp1Oh16hofisuhoxZp6bD2BCYCBKKyrg5eVlj/LIhXHCFdmcVquFRqOBRqOBVqt1\ndDlEFlOr1RhkNJodvAAwBECk0Qi1Wm3rssgNMHzJJjgL1LHY4LGPjJUrkVxTY/H5yTU1yFi50oYV\nkbvgsDNZjbNAHUOn00GtViNj5UoUFBcjxNsbAFCh0yE6IgLJqalISEjgkKeFtFotwkNCUGUwWLwg\nggFAZ7kcv1ZU8DlgaoY9X7LK2rQ0LJ41C7urq/Hl5cuYiuYrt8gBxAPYW1OD3dXVWPzMM1ibluaY\nYt3I9qws9AoNxeakJCwoLESVwYBTNTU4VVODSwYD5hcWYtPs2egZEoLtWVmOLtclVVZWIsTb26qV\niOQAunh54eLFi7Yqi9wEV7gii23PysLbS5aYPAt0CICDV69i1Ouvo2tYGHvAFmp87GV3K4+9NDZ4\n4mtqrj328swzOF9ezsdeiJwIh53JIpwF6hh87EU6jcPOlwwGyC28BoedqTUcdiaLcBao9HQ6HeYl\nJWGXGcELAD0B7Lx6FfOSkjjpzQy+vr7oFx6OXCuukQMgJjKSwUs3YfiSRTgLVHps8EijuLgYixcv\nRs+ePVErlyP9+kQ2S2QEBCA5NdWG1ZG7YPiS2bRaLQqKixFnxTXiABwpKuJjMWZgg8d+qqqq8N57\n72HYsGF44IEH4Onpia+//hrHjx/HT97eOGLBNfMBFMlkiI+Pt3W55AYYvmQ2zgKVHhs8tmc0GrF3\n7148+uij6N27N/bt24elS5fizJkz+Nvf/oYBAwbA29sb6ZmZmOLjg1Izrl2Ka+s7p2dmcl4DtYiz\nnYlcQFODx2Cw+Bo3Nnja83eQGo0GH374If7+979DoVDg6aefxrp166BQKFo8fkZiIs6Xl2OUBRsr\ncIIbtYbhS2ZTKBSo0OlgAKyaBfq7Xo/g4GAbVkbUsitXrmDHjh3YsmULioqK8NhjjyEnJwdRUVEm\nnZ+yYAG6hoVhQlISBhmNSK6pQRyaLyaTg2vf8RbJZFxMhtrER43IIrFKJeYXFsLSb7OyAaQrlcgr\nKLBlWW7LHR970Wq1qKysBHCtQWfrmoQQ+O6777BlyxZkZ2fjnnvuwdNPP41JkyZZPBSs1+ubVhU7\nUlSELtev87tej5jISCSnpiI+Pp5DzdQmhi9ZRKVSYdPs2dhr4QSgsQEBeG7jRiSyd2Ayd2jwSLEk\n5q+//oqPPvoIH374ITw8PPD000/jiSeewG233War2wBwrfHQOGchODjYKRo05EIEkQXq6upE18BA\nkQ8IYebrMCC6BgYKnU7n6NtwKdu2bRNj/f3N/vtufI0JCBAqlcph9WepVKJrYKAYFxAg1IAw3FCb\nHhDZgBjr7y+6BgaKLDPrrKurE9u3bxcPPvig6Ny5s3juuefEoUOHhNFotNPdEFmH4UsWy1KpRA8f\nH3HGjAA4A4iuHTqIbdu2Obp8l+PKDZ701atFDx8fcdjEWnv4+or01atveU2j0Sjy8/PFiy++KBQK\nhRgzZozYunWruHLlikR3RWQ5PmpEFpuRmIhFy5djlI8P8k04Ph/AKB8fBPbsiQMHDkDwGw+zuOpj\nLzeuAd7WTGHg32uAv/366y1uClFRUYE1a9ZAqVQiPj4eCoUC//d//4d9+/bh8ccfh6+vr83vgcjm\nHJ3+5PoahxPH+vuL7BaGE3dcH/JsHE6srq4Ww4cPF3PnzuWwoAXSV68WXTt0sGkv0l5s1Vs3GAwi\nNzdXTJ06VQQFBYnHH39c7Nu3TzQ0NDjkvoisxfAlm9DpdEKlUolYpVL4yeWil5+f6OXnJ3w8PMTt\n3boJlUrVbMjz0qVLYsiQIWLRokUMYDOp1WrRNTRUhAYEmNzgcRRrv6e+z9dXTJw4UXTr1k0MHz5c\nZGZmiqqqKofdD5GtcLYz2dyNs0Dz8vKgVqvx6aef3nTcxYsXMWbMGEyaNAnLli2TukyXVF5ejpiY\nGOzatQsxMTFO/9iLLWZop4aGIvfrrzFw4EBblkbkUAxfsiuNRoPRo0ejrKysxfcrKipw33334ZFH\nHsGSJUskrs61GI1GPPjgg7jnnnuwdOnSZu8542Mvjc8mVxkMFq/m42zPJhPZCle4Irvq06cPLl++\njAsXLiA0NPSm90NCQrBv3z6MHj0a3t7eWLx4sQOqdA1r165FTU0NXnvttZveCwoKcrpw4pKYRK1j\n+JJdyWQyREdHo6CgAOPHj2/xmG7dumH//v1NAZySktLicfZeEcmZHTt2DG+99Rb++c9/wtOT/9kS\nuTo+akR2FxMTgyNHbr0pW3h4OPbt24e0tDRkZmY2/Vyn00GlUiFWqUR4SAjGRkVhbFQUwkNCEKtU\nQqVSuf0G8XV1dXjsscewatUq9O3b19HlmOzGNcAtxTXAyV2xCS2R9txra5wg1JZevXph3759uO++\n++Dl5QVfHx/MS0rCYCGw4PJlTAKahjANAHILC5ExezbmP/+8Wy9k//LLL+POO+/EzJkzHV2KyYQQ\n+OWXX9Ctc2fkXrhg8YSrHAAxkZHt6r8XaiccOtfazdXV1Ylt27aJUVFRwk8uF739/UVvf3/hJ5eL\nUVFRYtu2be1iicXi4mLRr18/k4//8ccfRXBgoAjz8nKJZ1nt6YsvvhDdu3cXlZWVji6lTQ0NDeLb\nb78VCxYsEL169RL9+/cXcXFx4j5fX5ddEpPIXhi+dmLPdWxdTX19vfDz8xOXLl0y6fgslUp079jR\n7GUre/j6utXfZUVFhQgLCxN79+51dCmtqq+vF1999ZWYM2eOCAsLE5GRkeKNN94QhYWFwmg0uvSS\nmET2xPC1A3usY+vqRo4cKb766qs2j+Mv62uMRqOYMmWKWLRokaNLuYlerxdffPGFeO6550RISIiI\njo4Wy5cvFydPnmzxeEvXAHe3xhTRjRi+NsZfNC178cUXxWoTGhhW79zj7+8Ww5Tvv/++UCqVoq6u\nztGlCCGEqK2tFTk5OWLmzJkiODhYDBs2TKxatUqUlJSYdD4bpETNMXxtiL221m3evFk89thjbR43\nKipKZFsYvALXllWMVSoluCP7+fnnn0WXLl1EUVGRQ+u4cuWK2LFjh3jkkUdEp06dxL333ivS09NF\naWmpRdczdw1wInfG8LUh9tpad/ToUTFw4MBbHlNVVSX85PJmv5TNfekB4SeXu+z6v3q9XgwdOlSs\nW7fOIZ+v1WrFtm3bREJCgggMDBTjxo0TGzZsEL/99ptNrt/aGuB+crmIVSpvWgOcyF1xeUkbssU6\ntulKJfIKCmxZllMwGAwICgpCRUUF/Pz8WjxGo9FgbFQUTtXUWPVZvf388NXx4+jTp49V13GE119/\nHfn5+di9ezdkMpkkn3np0iXk5OQgOzsbX3/9NWJjY5GQkIDJkydDoVDY7XOdcUlMIqnwOV8b0Wq1\nKCguRpwV14gDMLOoCFqt1u1+EcnlckRGRqKwsBAjR450dDlO6eDBg/jggw9QUFBg9+CtqKjArl27\nsGPHDnz//fcYM2YMHn74YXz00Ufo1KmTXT+7kTMuiUkkFYavjXAd27Y1rnTVWvjeuCKS3MLPcNUV\nkbRaLZ544gls3LgR3bp1s8tnlJeXQ61WIzs7GwUFBXjwwQfx7LPPIjs7G/7+/nb5TCJqGZeXdDIN\nDQ0oLy+H0Wh0dCk2FxMTg++//x4ajQYajQZarbbZ+0FBQYiOiECuFZ/hqisizZ07F+PHj8ekSZNs\net0zZ84gLS0N99xzDwYNGoQffvgBL730En777TdkZWVh+vTpDF4iB+B3vjbSuH3aJYPBql5bgEyG\nTqGhuHz5Mvr374877rij6TVgwADccccdLter0+l0UKvVeHvpUhT98gtuu/7LvkKnQ3REBJJTU5GQ\nkAAvLy+oVCpsmj0bey383ndsQACe27gRiU621OStlhfdvn073njjDRw5cqTV78PN8csvvyA7OxvZ\n2dk4ffo0Jk+ejISEBIwdO9ahe/sS0b8xfG3IlhOuqqur8csvv+Dnn39u9vrpp5/g5eXVLJQbX7ff\nfjt8fHxseUtW256V1bQ+c3Lj+szX3zMAyAWQ4e+PEx4eSM/MxJSpU9ErNBSfVVcjxszPygcwITAQ\npRUVThEyjY2OjJUrUVBcjBBvbwDNGx133303RowYgc8//xxDhgyx6HOEECguLm4K3AsXLmDq1KlI\nSEjA6NGjuQsSkRNi+NqQFL02IQQuXLjQLIwb/7dGo0HXrl1bDOZevXpJ/kt4bVoa3l6yBDtra9FW\nrOQDmOrri0XLlqFrWBgWz5qFg7W16GniZ5UCGOXri1WbNjnFBgumNjr+WVuLidOmQZWVZdb1hRA4\nevQoduzYgezsbFy9ehXx8fGYNm0aRowYgQ4dOtj4jojIlhi+NqTT6Rzaa6uvr0dpaWmLveXz58+j\nb9++LQZz165dbT67dntWllUBer683KLgTlmwwLrCbcDsRoePDxYtX95m7UajET/88ENTD1cmk2Ha\ntGlISEjA0KFDJXs0iYisx/C1MWtDx169ttraWvzrX/+6KZh//vln6HS6Zt8p3ziMHRgYaPZn2aoR\nslOtxrykJAwyGpFcU4M4NO895gDICAhAkUzmNFsK2vqff0NDA7799ltkZ2dDrVYjICAACQkJSEhI\nQFRUFAOXyEUxfO3Akp7PUy+9hKeefdYhe/1evHixxVD+5ZdfEBgYeNOErzvuuAN9+/ZttYdu9fC7\nvz+ee/99JCYmQq/XN31veqSoCF28vHDlyhXUenoiZtAgJKemIj4+3mm+47VFo8PDwwNff/01srOz\nsXPnTnTr1q0pcCMiIuxROhFJjOFrJ8kvvICPNm7EcF/fVntt6R07okCvhwHAbb6+AFqeAewoRqMR\n5eXlLX6/XFZWhu7du7c4G/vRiRMx/9gxm6/01bgi0r333ovc3FwolUqr79GWrG10jPbxgcewYTh+\n/Dj69u3bFLj9+/e3caVE5GgMXzv49ddfER0djd27d6OkpKRZrw0AKurq4C0Ewr288HpdHeJx6xnA\nzjCc+p/0ej1OnTp1U2/55MmTuHT+PK7A8hVcDAA6y+X4taKixVGAu+66C1u3bkVUVJQ1t2Bztpjt\nviQsDF8cOoSePU0dtCYiV8TwtTEhBCZOnIi7774bS5cubfp5Y6/tww8+wKa0NHxaV+dyE4lModFo\nMPauu3DqyhWrrnObpyf+9MQTUCgU8PT0hFwuh6enJzw9PZGZmYm4uDjcfvvtTT9r63Xj+Za+bvX9\nauNz3lUGg90aHUTkPvgAoI39/e9/R3l5OV599dVmPw8KCsKezz/HlnfewXd1dSZNxhkC4ODVqxj1\n+uvoGhbmVD3ghoYGnD9/HmVlZSgrK8PZs2dRVlaGH3/8EbW1tVZf38PDA2FhYQgMDER9fX3Tq66u\nDsC1pRJlMlmz91p6GQyGNo8x5fyGhgZ06NCh1WAWQsCvvt6q/6DcfXlRIvo39nxt6OzZs4iOjsbe\nvXtvGhJ19GNI5jAajU3B2hiqjX82/u9z584hODgY3bt3R48ePZr+VCgUmJuUhKr6eqtW+rpVD3DK\nlCmYOXMmpk6datV9mkMIgYaGhlZDWqPR4Ik//Qlnrl616nNceUcmIjIde742IoTAc889h7lz57b4\nXaRarcYgo9Hs4AWu9YAjjUao1Wqrl000Go24cOHCTWF645+//fYbOnXqhB49ejQL1ujo6Kb/Hx4e\n3mpDYMvatci14rvPHAADevdu9TEnPz8/XLFyWNtcMpmsqZfbkoCAAFQaDO1yUwgiMh/D10a2bNmC\n8+fP45VXXmnx/YyVKzHfin1qk2tqkL5y5S3D12g0oqKiotXeallZGcrLyxEUFNQsVHv06IGoqKhm\nwep9fSlEi2pNTUXG7NmIt/B+13h746xWi5iYGLzwwgt49NFHmy3+74jwvRWDwYC8vDx09vFBrsFg\nVaPDFTeFICLzcdjZBsrKyhATE4N9+/bhrrvuuul9m03G8fTE7r17UVVV1WLAlpeXIyAgoFmw/uef\n4eHh6Nixo1X32xZbDLGfPn8eBw4cwIYNG5CXl4dHH30UL7zwAiIjI7FgwQKEh4dj4cKF9ijfZCdO\nnMCHH36Ijz/+GP3798fAgQOhUamwz8KGgbNuCkFEtseer5Uah5tTUlJaDF7Adnv9+tTX4/nnn0f/\n/v2bwnT8+PHNgtUZNlbw9va+tkmCBSs9TfX1RXpmJjp27Ijx48dj/PjxKCsrw/vvv49x48bhjjvu\ngEKhQEBAgD1voVWVlZVQqVT48MMPcf78eTz55JPIy8vDHXfcgcLCQtyzeTOOABY1OopkMsTHW9pv\nJiKXIsgqH3zwgYiJiRF6vb7VY0pKSkRvf38hAKtevfz8hEajkfDurJO+erXo4eMjDptwb4cB0cPX\nV6SvXt3q9fR6vfjkk09E3759ha+vr3j11VfF6dOn7X4fBoNB/M///I+YNm2aCAoKEo8++qj43//9\nX1FfXy+EEKKhoUGkp6cLhUIhnn3mGdHDx0ecMeOf65nr956lUtn9XojIOTB8rVBaWiq6dOkijh07\ndsvjqqqqhJ9cLvRWBK8eEH5yuaiqqpLo7mwjS6USXQMDxVh/f5ENCMN/3NMOQIwJCBBdAwNNDp91\n69aJRx55RKSkpIjg4GAxceJEsXv37qYwtJUTJ06IRYsWiW7duokRI0aIzMxMcenSpWbHlJWViXHj\nxolhw4aJn3/+WQhh+0YHEbkfhm8bqqqqRElJiSgpKWkWfEajUfzxj38Uy5cvN+k6o6KiRLYV4bsD\nELFKpb1u0650Op1QqVQiVqkUfnK56OXnJ3r5+Qk/uVzEKpVCpVIJnU5n8vU2b94sZs6cKYQQoqam\nRnzwwQdiyJAhok+fPmLFihXiwoULFtdaWVkp1q9fL4YOHSrCwsLEyy+/LH788ccWj83KyhIhISHi\nzTffFAaDofl7JjQ6Yr29zWp0EJH7YPi2oK6uTmzbtk2MiooSfnK56O3vL3r7+ws/uVyMiooS27Zt\nExkZGWLIkCE3/dJtzV/+8hcxskMHi8N3TECAULnBL+mqqiqh0WiERqMxqxd/YyNoy5YtYtq0aTcd\n88MPP4innnpKBAUFiccee0wcPHhQGI3GNq9tMBjE7t27xfTp00VQUJBITEwUe/bsabUnffHiRfHo\no4+KAQMGiB9++KHV696q0RHVt6/o3bu3qKurM/nvgIjcB8P3PzT2WMYFBAh1Cz2WbEDc7+cnfGUy\nser//b9bXqu+vl5kZ2eLESNGiN69e4vOHTuKfAuC9zAgugYGmtU7dAetNYJ8O3QQYQEBYtu2bS3+\nnVRWVoq0tDRx++23i8GDB4uMjAxRXV1903FFRUXiz3/+s7jtttvEsGHDxIYNG8TFixdvWdPevXtF\njx49xIsvviiuXLli8r38Z6OjoaFB9O7d+5bhTUTui+F7A1t9V3flyhWxfv160a9fPzFs2DCxY8cO\nUV9fL7JUKk7GMZEpjaCx/v63HLZtaGgQX375pYiPjxedO3cWL7zwgjh48KDIyMgQd999t7jttttE\namqqKC4ubrOeq1evipdeekmEh4eLPXv22OQe//a3v4lZs2bZ5FpE5FoYvtfZIhjPnTsnlixZIkJC\nQsSUKVNaHPbkZJy22frvqL6+XmzdulVERkYKmUwmunTpIhYvXixqampMqufIkSMiIiJCTJ8+Xfz+\n+++2uk1x7tw5ERQUdNMkLiJyfwxfcW14s2tgoMVDwiH+/uLpp59u6l01znptjT1mALsLW44OnDx5\nUqSmpoqwsDAxdOhQsX79enHu3DmRnZ0txo0bJ0JDQ0Vqamqrj2/V19eLv/71ryIkJER8/PHHJn1/\nbK4ZM2aIdevW2fy6ROTcGL5CiG3btomxVjyHe7dMJqZPny4qKipM/kxbzwB2B9Y2groGBorz58+L\n9957TwwfPlx069ZNLF68WJw4caLFz/vpp5/EggULhEKhEA899JDIzc1tmmRVUlIi7rnnHnH//feL\nM2fO2O2ev/rqKxEZGWmXYCci58XlJWGbTdDTlUrkFRRYdH7jXr8AEBwc3G7X9lWpVNg0ezb2Wrgm\n9EhPTxyVyzFhwgQ89dRTGD9+fKsbIdyotrYW27dvx4YNG3Du3DkMGTIEBw4cwGuvvYaXXnoJHh4e\nFtVjCiEEBg4ciA8++ACjRo2y2+cQkXNp9+HLTdCdhy0aQasHDcJ3x49bdP6FCxfw8MMP4/jx4zAY\nDJgwYQJeeOEFxMbGQiaTWVhV29asWYPDhw/j448/tttnEJFzsV+T3kU0rbtsxTVu3ASdLKPValFQ\nXIw4K64RB+DYTz9Bq9WafW5ubi6ioqIwfPhwlJeXo7S0FCNGjEBSUhIGDx6M9evXo7q62orqWvfk\nk09i9+7d+P333+1yfSJyPu0+fMk5OKoRVFNTg9mzZyMlJQWffPIJVqxYAW9vb3Tq1AkpKSkoLi7G\nu+++iwMHDqBXr15ISkrC0aNHrajyZsHBwZg8eTI+/PBDm16XiJxXuw9fhUKBCp0Olu83xE3QXdV3\n330HpVKJ+vp6FBYWIjY29qZjZDIZ7rvvPnzyyScoLi5Gjx49MGnSJIwcORJbt25FXV2dTWp5/vnn\nkZmZCaPRaJPrEZFza/fhGxQUhOiICORacY0cAAFyOTZs2ICTJ0+inX+NbpGgoCBcqKuTpBGk1+ux\nZMkSxMfHY9WqVdi8eTMCAwPbvP5tt92GJUuW4NSpU0hNTcV///d/o2fPnli8eDFKSkqsqBwYNmwY\n/Pz8sH//fgDXhuE1Gg00Go1Fw+hE5NzaffgCQHJqKjL8/S0+P8PfH0/Pm4eysjL88Y9/xIABA7Bo\n0SJ88803aGhosGGl7uXy5cvIzs7GzJkzMWDAAPh7elrdCIqJjLzlpLeTJ09ixIgROHr0KI4ePYqp\nU6ea/Tmenp6YPHky9uzZg0OHDkEmk2H48OF48MEH8emnn6K+vt7sa8pkMjzzzDN47bXXEKtUIjwk\nBGOjojA2KgrhISGIVSqhUqmg1+vNvjYROSFHPufkLGzxfGnjM7lGo1Hk5+eLN954QyiVStGlSxcx\nc+ZMoVarTV5RyZ2VlpaK9evXi/Hjx4uAgAAxfvx48e6774ozZ86Y/Lx1FSBKrr+qbvj5rTafuHHP\n3ffee8/mz9XW1taKjz76SIwYMUL06NFDLFu2TPz2228mn5+lUonQgAAxDLB4OU0ich0M3+vste7y\n6dOnxbp168S4ceNEQECAmDBhgti4caMoLy+X8O5a3xrR3oxGozh8+LB44403RHR0tFAoFOLJJ58U\n//jHP4RWq2127K0aQXWA2AaIUYDwA0Tv6y+/6z9bDojQgIAWFyZpac9deyooKBCzZ88WnTp1EtOn\nTxf79++/ZdhzyVGi9ofhewN7/xK8dOmSUKlUIjExUXTq1EkMGzZMvPXWW+LEiRN2WeHIlK0R7bGK\nVm1trdi9e7d4/vnnRXh4uBgwYIBYtGiRyMvLa3MLxpYaQVmA6AqIcbfoFQ4DRLCPz00NoVvtuWtv\nVVVV4t133xWRkZFi4MCBIj09/aZ1nLnZBlH7xPD9D1Ktu6zT6cSXX34pXnzxRdGzZ0/Rr18/MX/+\nfPH111/bJCRssSuQOS5cuCC2bNkipk6dKgIDA0VsbKxYtWpVqxvR38qNjaB0QPS43tgxp0Fk6p67\nUjAajeLAgQNNja5nn31W5Ofn2/TrDiJyLQzfFki97rLRaBQFBQXiv/7rv0RMTIxQKBTiiSeeEDt2\n7GhxH9q2SDGMaTQaRXFxsVixYoUYOXKkCAoKEtOmTRMfffSRTXb+yVKpRFDHjiL0ek/PnF5huLe3\nUAQHm73nrhTOnTsn/vrXvzY1uO719jY7eJu+4/b3b/U7biJybu1+ecm2OGLd5bKyMuTm5uLTTz/F\noUOHMGrUKEyePBmTJk1CWFjYLc/dnpWFxbNm4WBtLXqa+HmlAEb5+mLVpk2YkZjY6nH19fU4ePAg\ncnJykJubC51Oh7i4OMTFxWH06NHw9vY2/SbboNPp0Cs0FJ9VVyPGzHPzAYz39UX5pUvw8vKyWU22\n1NDQgJivDHN+AAAUXElEQVTbb8fSU6cctqY4ETkOw9fJVVdXY8+ePfj000/x+eefo3///oiLi8Pk\nyZMxaNCgZmsOWxtYEwIDUVpR0SywtFotvvjiC+Tk5ODzzz9H3759MWnSJMTFxSEqKspuax5bu8nC\nWH9/PPf++0i8RWPCkbimOFH7xvB1IQaDAd988w1ycnLw6aefQiaTNQVxbGws/vGPf9gksIYPH47c\n3Fzk5OTgn//8J2JjYxEXF4eJEyciPDzcxnfVMkfvNGVvGo0GY6OicMrCf1aNevv54avjx9GnTx8b\nVUZEUmD4uighBI4fP94UxBqNBv5GI96pqrIqsF7o2BEICMDEiRMRFxeHBx54AH5+frYsvU3toVfI\n8CVq3xi+buLkyZMYMngwqhsarAqsTp6eKDt/3mbrVBsMBtTV1Zn1Onv2LDatWIGzVq7m5MzB1NjA\nuGQwQG7hNZy9gUFErbNmExlyIt7e3ujq4wNPK3pScgCdO3TA2rVr4e/vb3ZotvQSQsDHxwcdO3Zs\n8dXSezqdDu7eJmxaU9yKoXVTltMkIufE8KVmGhoaUFJSgq5duzaFYadOnVoNz7Zenp7m/yum1WoR\nnpUFA2BVr9DZd5pKTk1FxuzZiLewwZQREIDk1FQbV0VEUuCws5twt2FMd59wBVg/O/3+Dh3wbUEB\nBg8ebI/yiMiOuKuRm7DV1ojOMoxp9U5TLtAr9Pb2RnpmJqb4+KDUjPNKAUz18cGURx7B/fffj1df\nfRVXr161V5lEZAcMXzfiToEVHx+PEx4eOGLBufkAimQyxMdb2m+WzozERCxavhyjfHyQb8Lx+bi2\nIMqi5cvx0datOHbsGE6fPo2IiAjs2rXL7b8rJ3Ib0i+qRfbibmsFt6dNB6xdU3zfvn3izjvvFA89\n9JD417/+5YA7ICJzMHzdjLsFVnvabs/aNcV1Op1YsWKFUCgUYunSpeLq1asSVk9E5mD4uiF3Cyyp\ndppyJlVVVUKj0QiNRmP2/stnzpwRCQkJom/fvmL37t12qpCIrMHZzm5qe1YW5iUlYZDRiOSaGsTh\n38+VGXBtclVGQACKZDKkZ2beckMFZ6DX66FWq7F0wQKUnj+Prj4+AK49ThQTGYnk1FTEx8c77UYK\njrBnzx7MnTsXgwYNwpo1a9CrVy9Hl0RE1zF83VhjYGWsXIkjRUXocj2YXDmw/vSnP+Hxxx/HyJEj\nAUi305Srqqurw6pVq7BmzRosXLgQCxcutOnuU0RkGYZvO+GIrRFtrb6+HgqFAiUlJejSpYujy3Ep\np06dwrx58/DTTz9h/fr1GDdunKNLImrXGL7kMvLz8zFz5kycOHHC0aW4rNzcXKSkpODuu+/G6tWr\n0b17d0eXRNQu8Tlfchl5eXm49957HV2GS5s0aRKKioowYMAAKJVKvP322zAYDI4ui6jdYfiSy2D4\n2oavry/efPNNHDp0CHv37kV0dDQOHDjg6LKI2hUOO5NLMBqNCA0NRWFhIcLDwx1djtsQQkCtVmP+\n/Pm499578fbbb6Nbt26OLovI7bHnSy7h5MmT6NSpE4PXxmQyGRISEnDy5El0794dgwcPxtq1a1Ff\nX+/o0ojcGsOXXEJeXh5iY2MdXYbb8vPzw4oVK5CXl4ddu3bhD3/4A7777jtHl0Xkthi+5BL4fa80\nBg4ciH379uHll1/G9OnTMWvWLFRUVDi6LCK3w/AlpyeEYPhKSCaTITExsWmoPzIyEu+99x4aGhoc\nXRqR2+CEK3J6JSUluPfee3H27FnIZDJHl9PuHD9+HMnJyairq0NGRgaGDh3q6JKIXB57vuT0Gnu9\nDF7HGDx4MPLy8jB37lzExcXh+eefb1otjYgsw/Alp8chZ8eTyWR48skncfLkSXh6eiIiIgKbNm2C\n0Wh0dGlELonDzuT0+vXrh5ycHERGRjq6FLruyJEjSE5OhoeHBzIyMqBUKh1dEpFLYc+XnNrZs2eh\n1WoxcOBAR5dCN4iJicF3332HWbNmYfz48UhJSUFVVZWjyyJyGQxfcmrffPMNYmNj4eHBf1WdjYeH\nB5599lkUFxejrq4OERER2Lp1KywZTNNqtdBoNNBoNNBqtXaolsi58DcaOTV+3+v8FAoFNm7ciJ07\nd2LNmjW47777TNp5SqfTQaVSIVapRHhICMZGRWFsVBTCQ0IQq1RCpVJBr9dLcAdE0mP4klNj+LqO\nYcOG4YcffsCMGTNw//33Y+HChbh8+XKLx27PykKv0FBsTkrCgsJCVBkMOFVTg1M1NbhkMGB+YSE2\nzZ6NniEh2J6VJfGdENkfw5ecVkVFBc6ePYuoqChHl0Im6tChA5KTk1FUVISLFy9i4MCB2L59e7Oh\n6LVpaVg8axZ2V1fjy8uXMRWA5w3XkAOIB7C3pga7q6ux+JlnsDYtTeI7IbIvznYmp7Vz505s3LgR\nn3/+uaNLIQsdPHgQc+bMQUhICN59910UHj2KxbNm4WBtLXqaeI1SAKN8fbFq0ybMSEy0Z7lEkmH4\nklPRarWorKwEAKxevRrdu3fHK6+84uCqyBr19fVYv349li1bhvrLl7Ffr0eMmdfIBzAhMBClFRXw\n8vKyR5lEkvJs+xAi+9LpdFCr1chYuRIFxcUI8fYGAPx25Qoi+vVD7969kZCQwF+6LsrT0xPz5s2D\nXC7Hf8+bZ3bwAsAQAJFGI9RqNRLZ+yU3wJ4vOdT2rCzMS0rCYCGQfPkyJuHfLUIDgFwAGf7+OOHh\ngfTMTA47urBYpRLzCwsRb+H52QDSlUrkFRTYsiwih2D4ksOsTUvD20uWYGdtLYa0cWw+gKm+vli0\nbBlSFiyQojyyIa1Wi/CQEFQZDBYPtxkAdJbL8WtFBYKCgmxZHpHkONuZHGJ7VhbeXrIEB00IXuDa\nsOPBq1fx9uuv89ETF1RZWYkQb2+rvueSA+ji5cVNHcgtMHxJcjqdDvOSkrDLjBmvANATwM6rVzEv\nKYmLLxCRS2P4kuTUajUGGY1WT7wh16FQKFCh08FgxTUMAH7X6xEcHGyrsogchuFLkstYuRLJNTUW\nn59cU4OMlSttWBHZW1BQEKIjIpBrxTVyAMRERvL7XnILDF+SlFarRUFxMeKsuEYcgCNFRVyA38Uk\np6Yiw9/f4vMzAgKQnJpqw4qIHIfhS5LixJv2Kz4+Hic8PHDEgnPzARQYDJg0aZKtyyJyCIYvEUnC\n29sb6ZmZmOLjg1IzzisFMKVjR4T3748RI0bg4MGD9iqRSDIMX5IUJ960bzMSE7Fo+XKM8vFBvgnH\n5+Paus6L33oLx44dw5IlS5CYmIinnnoKFy5csHe5RHbD8CVJceINpSxYgFWbN2NCYCDG+ftDDaD+\nhvcNuLaa1diAAEwIDMSqTZuQsmABZDIZHn74YZw8eRIKhQKDBg3Chg0b0NDQ4JgbIbICV7giyalU\nKmyaPRt7LZzxPDYgAM9t3Mg1fl2cXq9vWtP7SFERulxfu/t3vR4xkZFITk1FfHx8q2t6Hz9+HMnJ\nyairq0NGRgaGDh0qZflEVmH4kuR0Oh16hYbis+pq7m5DAK7Ngm+cQBccHGzyqIYQAlu3bkVqaiqm\nTJmCt956i19HkEvgsDNJzpqJN1N9fZGemcngdTNBQUHo06cP+vTpY9bXCTKZDE8++SSKi4vh4eGB\niIgIbNmyBUaj0Y7VElmPPV9yGG6sQLZ2+PBhJCcnw8vLCxkZGbjrrrscXRJRi9jzJYexdOINUWv+\n8Ic/4NChQ3jiiScwbtw4zJ8/H9XV1Y4ui+gmDF9yqBmJiSitqMCz77+PNUolOsnl6O3nh95+fugs\nlyNdqcRzGzeitKKCe/mSSTp06ICkpCQUXV8FbeDAgcjKygIH+ciZcNiZnIqlE2+IWvPtt98iOTkZ\nXbp0wfr163HnnXc6uiQihi8Rub/6+nqsX78ey5Ytw+zZs/Haa6/Bz8/P0WVRO8ZhZyJye56enpg3\nbx6OHTuG06dPIzIyErt27eJQNDkMe75E1O7s378fc+bMQb9+/bB27Vr07dvX0SVRO8OeLxG1O2PG\njEFhYSFGjRqFu+++G2+++Sbq6uocXRa1IwxfImqXvLy88PLLLyM/Px8FBQUYPHgw9uzZ4+iyqJ3g\nsDMREYDPPvsMc+fORXR0NN555x306NHD0SWRG2PPl4gIwEMPPYQTJ05g0KBBiI6OxqpVq2AwmL75\npVarhUajgUajgVartWOl5A4YvkRE1/n4+OAvf/kLvv/+e+zfvx9KpRIHDhxo9XidTgeVSoVYpRLh\nISEYGxWFsVFRCA8JQaxSCZVKBb1eL+EdkKvgsDMRUQuEENi5cydeeukljB49GqtWrUK3bt2a3t+e\nlYV5SUkYLASSL1/GJACe198zAMgFkOHvjxMeHkjPzOQKbdQMe75ERC2QyWSIj49HcXExwsLCMHjw\nYKxbtw719fVYm5aGxbNmYXd1Nb68fBlT8e/gBQA5gHgAe2tqsLu6GoufeQZr09IccyPklNjzJSIy\nQXFxMZKTk3H61CnUnz+P73Q69DTx3FIAo3x9sWrTJvaACQDDl4jIZHV1dQgPDsaXtbWIMfPcfAAT\nAgNRWlHB/aiJw85ERKbauXMnojt0MDt4AWAIgEijEWq12tZlkQtiz5eIyESxSiXmFxYi3sLzswGk\nK5XIKyiwZVnkghi+REQm0Gq1CA8JQZXB0GxylTkMADrL5fi1ooLbZbZzHHYmIjJBZWUlQry9LQ5e\n4Nos6C5eXk17VlP7xfAlIiKSGMOXiMgECoUCFTodTF9w8mYGAL/r9QgODrZVWeSiGL5ERCYICgpC\ndEQEcq24Rg6AmMhIft9LDF8iIlMlp6Yiw9/f4vPf7tABcY89ZsOKyFVxtjMRkYl0Oh16hYbis+pq\nixbZeKBjR3j4+WHWrFl444034G9FkJNrY8+XiMhE3t7eSM/MxBQfH5SacV4pgKm+vtiwZQuKiopw\n4cIFDBw4EJ988gnY/2mf2PMlIjLT2rQ0vL1kCXbW1mJIG8fm41rwLlq2DCkLFjT9/JtvvsGcOXPQ\ntWtXrFu3Dnfeeaddaybnwp4vEZGZUhYswKrNmzEhMBDj/P2hBlB/w/sGXFvNamxAACYEBmLVpk3N\nghcAYmNjceTIEUycOBGxsbF45ZVXcOXKFQnvghyJPV8iIgvp9Xqo1WpkrFyJI0VF6HJ9w4Tf9XrE\nREYiOTUV8fHxbW6k8Ntvv+HPf/4zDhw4gHfeeQfx8fGQyWRS3AI5CMOXiMgGtFpt08pVwcHBFj1O\ndODAAcyZMwfdu3fHunXrcPvtt9u6THISHHYmIrKBoKAg9OnTB3369LH4Od7Ro0ejoKAADzzwAEaM\nGIElS5bg6tWrNq6UnAHDl4jIicjlcixcuBCFhYUoKSlBREQEdu3axVnRbobDzkRETmz//v2YM2cO\n+vbti7Vr16Jfv35mna/ValFZWQng2hKZXF3LObDnS0TkxMaMGYPCwkKMHj0aw4YNw9KlS1FbW3vL\nc3Q6HVQqFWKVSoSHhGBsVBTGRkUhPCQEsUolVCoV9Hq9RHdALWHPl4jIRZSVlWHhwoU4fPgw1q5d\ni4kTJ950zPasLMxLSsJgIZB8+TImAU3bIBoA5ALI8PfHCQ8PpGdmYkZiooR3QI0YvkRELubLL7/E\niy++iAEDBiA9PR19+vQBYJvFP0gaDF8iIhek0+mQlpaG1atXIyUlBX369MFrSUk4WFuLniZeoxTA\nKF9frNq0iT1giTF8iYhcWGlpKVJSUrA3Jwd5Qli04cOEwECUVlS0uRgI2Q4nXBERubCePXtixowZ\n+EPHjmYHLwAMARBpNEKtVtu6NLoF9nyJiFxcrFKJ+YWFiLfw/GwA6Uol8goKbFkW3QLDl4jIhWm1\nWoSHhKDKYGia1WwuA4DOcjl+rajgc8AS4bAzEZELq6ysRIi3t8XBCwByAF28vJrWpib7Y/gSERFJ\njOFLROTCFAoFKnQ6GKy4hgHXtkEMDg62VVnUBoYvEZELCwoKQnREBHKtuEYOgJjISH7fKyGGLxGR\ni0tOTUWGv7/F52cEBCA5NdWGFVFbONuZiMjF6XQ69AoNxWfV1Vxkw0Ww50tE5OK8vb2RnpmJKT4+\nKDXjvFJcW985PTOTwSsxhi8RkRuYkZiIRcuXY5SPD/JNOD4f19Z1XrRsGdd1dgAOOxMRuZHGLQUH\nGY1IrqlBHJpvKZiDa9/xFslk3FLQgRi+RERuRq/XQ61WI2PlShwpKkKX60PKv+v1iImMRHJqKuLj\n4znU7EAMXyIiN6bVaptWrgoODubjRE6C4UtERCQxTrgiIiKSGMOXiIhIYgxfIiIiiTF8iYiIJMbw\nJSIikhjDl4iISGIMXyIiIokxfImIiCTG8CUiIpIYw5eIiEhiDF8iIiKJMXyJiIgkxvAlIiKSGMOX\niIhIYgxfIiIiiTF8iYiIJMbwJSIikhjDl4iISGIMXyIiIokxfImIiCTG8CUiIpIYw5eIiEhiDF8i\nIiKJMXyJiIgkxvAlIiKSGMOXiIhIYgxfIiIiiTF8iYiIJMbwJSIikhjDl4iISGIMXyIiIokxfImI\niCTG8CUiIpIYw5eIiEhiDF8iIiKJMXyJiIgkxvAlIiKSGMOXiIhIYgxfIiIiiTF8iYiIJMbwJSIi\nkhjDl4iISGIMXyIiIokxfImIiCTG8CUiIpIYw5eIiEhiDF8iIiKJMXyJiIgkxvAlIiKSGMOXiIhI\nYgxfIiIiiTF8iYiIJMbwJSIikhjDl4iISGIMXyIiIokxfImIiCTG8CUiIpIYw5eIiEhiDF8iIiKJ\nMXyJiIgkxvAlIiKSGMOXiIhIYgxfIiIiiTF8iYiIJMbwJSIikhjDl4iISGIMXyIiIokxfImIiCTG\n8CUiIpIYw5eIiEhiDF8iIiKJMXyJiIgkxvAlIiKSGMOXiIhIYgxfIiIiiTF8iYiIJMbwJSIikhjD\nl4iISGIMXyIiIokxfImIiCTG8CUiIpIYw5eIiEhiDF8iIiKJ/X/kFn9lfLbNFAAAAABJRU5ErkJg\ngg==\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import networkx as nx\n", "import matplotlib.pyplot as plt\n", "%matplotlib inline\n", "\n", "G=nx.Graph()\n", "G.add_nodes_from(['T01','T02','T03','T04','T05','T06','T07','T08',\\\n", " 'T09','T10','T11','T12','T13','T14','T15','T16','T18'])\n", "\n", "G.add_edge('T01','T02')\n", "G.add_edge('T02','T03')\n", "G.add_edge('T02','T04')\n", "G.add_edge('T02','T14')\n", "G.add_edge('T03','T05')\n", "G.add_edge('T04','T07')\n", "G.add_edge('T04','T10')\n", "G.add_edge('T04','T09')\n", "G.add_edge('T04','T06')\n", "G.add_edge('T04','T15')\n", "G.add_edge('T05','T06')\n", "G.add_edge('T06','T09')\n", "G.add_edge('T06','T11')\n", "G.add_edge('T06','T08')\n", "G.add_edge('T07','T13')\n", "G.add_edge('T08','T16')\n", "G.add_edge('T09','T12')\n", "G.add_edge('T11','T16')\n", "G.add_edge('T12','T17')\n", "G.add_edge('T14','T16')\n", "G.add_edge('T14','T15')\n", "G.add_edge('T17','T18') ;\n", "\n", "nx.draw(G)\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "pycharm": {} }, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true, "pycharm": {} }, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": { "pycharm": {} }, "source": [ "\n", "< [Scheduling](http://nbviewer.jupyter.org/github/jckantor/CBE40455/blob/master/notebooks/04.00-Scheduling.ipynb) | [Contents](toc.ipynb) | [Machine Bottleneck](http://nbviewer.jupyter.org/github/jckantor/CBE40455/blob/master/notebooks/04.02-Machine-Bottleneck.ipynb) >

\"Open

\"Download\"" ] } ], "metadata": { "kernelspec": { "display_name": "Python 2", "language": "python", "name": "python2" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 2 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", "version": "2.7.10" } }, "nbformat": 4, "nbformat_minor": 0 }