{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "In Lecture 32 of MCS 320, we consider polyhedral and unconstrained optimization." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 1. Polyhedra" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Every polyhedron can be defined in two ways:\n", "\n", "1. As the convex hull of a list of points.\n", "\n", "2. As the intersection of half spaces." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let us generate 10 random points with integer coordinates between 10 and 99." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "set_random_seed(20220722)" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[48, 77, 47, 60, 12, 36, 91, 28, 41, 70]" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "xvals = [ZZ.random_element(x=10, y=99) for _ in range(10)]\n", "xvals" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[16, 10, 47, 27, 79, 53, 94, 73, 77, 37]" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "yvals = [ZZ.random_element(x=10, y=99) for _ in range(10)]\n", "yvals" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[[48, 16],\n", " [77, 10],\n", " [47, 47],\n", " [60, 27],\n", " [12, 79],\n", " [36, 53],\n", " [91, 94],\n", " [28, 73],\n", " [41, 77],\n", " [70, 37]]" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pts = [[x, y] for (x,y) in zip(xvals,yvals)]\n", "pts" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "scrolled": true }, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXYAAAGGCAYAAABvzKp8AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8QVMy6AAAACXBIWXMAAA9hAAAPYQGoP6dpAAArxklEQVR4nO3dfZRddX3v8fd3Jg88mIRImUwIaGMFWggPBVGgrdFqoLbqLX1SUir2erVlwS0sWsBErbSFItGraStUVi2FqmiXV5ZeS70rwJW0GkgymRnyCIQQHkKSIYAkIQnDPHzvH3ufzM6Zk8mcOfuc/dt7f15r7TUze+85851J8snOPp/zi7k7IiJSHG1ZDyAiIulSsIuIFIyCXUSkYBTsIiIFo2AXESkYBbuISMEo2EVECkbBLiJSMMEFu0Wmm5llPYuISB5NynqAGqYBu4EZwJ46P1cvoxWRIhvXBW9wV+wiItIYBbuISMEo2EVECkbBLiISiB//GM48E047Db773Yk/joW2bK+ZTSd+8tTd9eSpiJTC/v0waxa89lr08eTJ8PTTcNJJh5w2ridPg2nFmNlVwFXoXxEiUnADA7BpE/T0RNua7kG6u2H/vkmHnLNjx6hgHxddsYuINNHevbB27UiIr+4eYNOGNgYH2gGY/HPPMNCxCjp7YOPvw85zATjrLFi5Eo466pCHG9cVu4JdRCQlO3dCb28c4r3O6q4Bnt06GXfD2gdo79zEYMfqKMQ7e6HzMZj62sgDHJgOt/2MhQvb+Md/hOnTR32JfN2KERHJi+Fh2LJlJMTXdA+zpmeIl1+cDED70a/hs3oZntUFZ/bC7B785zYxOGlg7Ad+dS7QxtVX1wz1cVOwi4iMob8fNmwYCfGu7kHWroX9r0XxOem4PoY6uvBf7Ib39EJnD0Mzt47z2rrKrjMAOP30xmZWsIuIxHbvjgI8CnFndfcAT2yaxNBgG9gwk094moGO1XBB5VZKL4Nv2pXeALtOp2P2G8yYMaWhh1Gwi0jpuMP27dEVeG8vdHc7Xd0DPP9sFKhtk9+grXM9gyd0wSVxiM9ay8CU/c0dbNc8zprX3vDDKNhFpNCGhmDz5pEQX9M9RHfPMD97Ob4ffsxufFYPwyeugXOjEB/+uccZbh9q+ayTXz6bMz9QoGBXj11EGnXgAKxfPxLiq9cMsH5dG68fiKuFM7czMGs1zOuB2VGID814bmL3w9M2cBQDL53c8P11CCjY3f124PZE3VFE5LBeeWXkCc3eXmdV1wBPbZ7E8FAb2BCTZj3F4Amr4dd64nrhYwwc80rWYx/eS6eBt3PGGY0/VDDBLiJSizs8/3zyfvgwq7sH2bEtvh8+5XWscx1DHV3wgfhKvGM9g5Nfz3bweqXUiIEJBLuZTQP+BrgU6AB6gGvcfXV83IDPA58CZgIrgavcfUPj44pIkQ0OwhNPjIR415ohenqH2fNqdD980pt+xtCsNfhbuuFd0ZX48PGboW0428HTkFIjBiZ2xf51YB7wR8B24HLgQTM73d1fAG4ArgM+DjwJfBZ4wMxOc/e9DU8sIoWwbx+sWzcS4qvWDLBxfRtv9Mf3w49/Pnqp/S/3RrdSZvcwOG17GPfDmyGlRgzUGexmdjTwu8B/c/f/jHffZGa/DVxpZp8DrgVucff74s+5AugDFgJ3pjK1iOTKrl2j74dv3TKZ4WHD2gdp73iSwY5V0Qt8ZvfArMcYOLpcT7Wl1YiB+q/YJwHtQPXNqwPArwJzgU5gWeWAu/eb2XLgIhTsIoXmDlu3joR4d88wXd2DvLgjur3QftR+mPUYQ7O64IO90NmDd2xgcNIbmc6duRQbMVBnsLv7XjN7BPicmW0iuhK/DHgXsJko1In3J/UBb631mGY2FZia2DWtnplEJBsDA7BxY3K9lEF6e+G1vfFL7ae/FN0P/4U18Cu9MLuHoZlboE1r9Y2SYiMGJnaP/Y+Au4AXgCGgG7gXODdxTvWvnNXYV7GI6MlWEQnUEZeePeEZBk5YBe+svNS+h8Fp1dd3clgpNmJgAsHu7luA+WZ2LDDd3XeY2b8BW4Gd8WmdwI7Ep3Uw+iq+4lbgy4mPpwHb6p1LRNKxc2eiWtjjdK05zNKz7x9ZenYgufSs1C/FRgw00GN3933APjObCVxC1IaphPsCohokZjYFmA/ceJjH6Qf6Kx9HbUkRabbK0rMjL7VPaelZqV+KjRiYWI/9EqJbK08Abwe+GL//L+7uZrYUWGxmm4nuuy8G9hPdrhGRDFQvPbt6TbT07IF9TVh6VuqWZiMGJnbFPoPo9slJwCvA94DPuHvlr/ElwNHAHYy8QOliddhFWqN66dlVawZ48vEaS89e2KSlZ6U+KTdiQP81nkhu1Vp6dvWaAbY9V2Pp2dkjS8/S7KVnpT47zoY7e1mxAi688Ihn67/GEymKcS89O2cNnJft0rNSp5QbMRBQsGvZXpHIuJae7eiCed3hLT0r9Uu5EQMBBbuW7ZUyKtzSs1K/lBsxEFCwixRZcunZaCvo0rNSt7QbMaBgF0ldcunZ6KX2JVp6VurThEYMKNhFGpJcerbyUvsxl57t7GVw+gu6Hy6RlNeIqVCwi4xTcunZnp6oWqilZ6UhTWjEgIJdZJTqpWejl9pr6VlpgiY0YkDBLiVXvfRs15pBeh+DfVp6VlqhCY0YCCjY1WOXZtu7Fx57bCTEV60Z4PGN7QwORL/lDi49e35v3A/X0rPSXM1oxEBAwa4eu6Rp/EvP9o70w7X0rLRSkxoxEFCwi0xEzaVnu4d4eZeWnpXANakRAwp2yZHK0rMjL7U/dOnZycf1MdjRhf9SN7y3V0vPStia1IgBBbsEqrL07MGX2o9aenZr1A9PLD07oKVnJU+a1IgBBbtkLLn0bLIfXnPp2UtGlp4d0NKzkndNasSAgl1aKLn0bE8PdPcMsaZ7mFdf0dKzUj7NasRAQMGuumOxJJee7emBru5B1q+z0UvPnqmlZ6WEmtiIgYCCXXXH/EouPVu5lZJcenbyrKcY0NKzIiOa2IiBgIJdwucOzz2XDPHxLT07oKVnRQ7VxEYMKNjlMAYH4fHHk+ulaOlZkdQ0sREDCnYhWnp27drEeindA2zQ0rMizdPERgwo2Etn166RF/hU7oc//VTlpfZaelakFZrZiAEFe2FVlp495KX2h1t69kO90dKzJ2xkcHJ/pnOLFF6TGzGgYC+EytKzlRDX0rMiAWtyIwYCCnb12MdHS8+K5FyTGzEQULCrxz5a9dKzq7sGeHZrdCtFS8+K5FSTGzEQULCXWXLp2eil9mMsPXtWr5aeFcmzJjdioM5gN7NJwE3AHwKdwA7gbuBmdx+OzzHg88CngJnASuAqd9+Q2tQ5NqGlZ497RvfDRQqi2Y0YqP+K/UbgT4ErgA3AO4B/Ibp18nfxOTcA1wEfB54EPgs8YGanufveFGbOjVdfje6Ha+lZEQFa0oiB+oP9QuAH7n5//PEzZnYZUcBXrtavBW5x9/vifVcAfcBC4M40hg6NO7zwwuj1Ug5ZenbWhuh+uJaeFSmvFjRioP5g/wnwp2Z2qrs/aWZnA79KFOYAc4lu0SyrfIK795vZcuAiChDsR156dg/e2cPwnC4tPSsih2pBIwbqD/bbgBnA42Y2BLQDn3H3b8fHO+O31f26PuCttR7QzKYCUxO7ptU5U9McOADr1iVfaq+lZ0WkAS1oxED9wf4R4HKi2yobgHOApWa23d3vSZxX/Uyf1dhXsYjoydZMvfLK6Jfaa+lZEUlVCxoxUH+wfxH4grt/J/54nZm9lSic7wF2xvsrjZmKDkZfxVfcCnw58fE0YFudc9W0Zw9cc030qswPfQg++9nRS892dw/T1TPG0rOdvTBrnZaeFZGGtaIRA/UH+zFA9bqsQ4y8WnQrUbgvAHoAzGwKMJ+oUTOKu/cDBxcoiZ5/Tcc118Ddd0fvr1oF3/zWMNt3DLN3d/xS+1FLz/YyfPyTWnpWRNLXokYM1B/sPwQ+Y2bPEd2K+WWiauNdAO7uZrYUWGxmm4HNwGJgP3BvWkOP18aNh378xK7NcO43tfSsiLReixoxUH+w/0/gb4A7iG6vbCdquvx14pwlwNHxOZUXKF2cRYf9Qx+KrtQjDh/8E5i7vNVjiIi0rBEDYO5hvaIxsVbMDHffU+enj/pm/vVf4cEH4RvfAD78CTj3rjTGFBGpz0M30/HU9fRtb6gRM657DIVfSfFjH4vC/aOXDdP+4yXwejBtShEpkxY1YiCgYDezq8xsI7DqiCdPwJLb2pg0cBz81+JmPLyIyJgmv3w2Z5Yt2N39dnc/HXhnMx7/5JPh0ze207byz+GVuc34EiIitbWwEQMBBXsrXH89nHAC2INfzHoUESmTFjZioGTBfuyx8KUlk/GNvwvPvDvrcUSkLFrYiIGSBTvAwoVw3vmDtC/7Bxgu3bcvIlk4uEZMa75c6ZKtrQ2++veTGNp+FvR+POtxRKQMWtiIgRIGO8AFF6j+KCKt08pGDJQ02EH1RxFpkRY3YiCgYG92j72a6o8i0hItbsRAQMHe7B57Lao/ikjTtbgRAwEFexZUfxSRpmtxIwZKHuyg+qOINFmLGzGgYFf9UUSaqtWNGFCwA6o/ikiTZNCIAQX7Qao/ikjqMmjEQEDB3uq6YzXVH0UkdRk0YiCgYM+i7lhN9UcRSVUGjRgIKNhDoPqjiKQqg0YMKNhHUf1RRNKSRSMGFOyjqP4oIqnIqBEDCvaaVH8UkYZl1IgBBfthqf4oIg3JqBEDCvbDUv1RRBqSUSMGAgr2rHvstaj+KCITllEjBgIK9hB67NVUfxSRicqqEQMBBXuoVH8Ukbpl2IiBOoPdzJ4xM6+x3R4fNzO7ycy2m9kBM3vYzDJ4Tjg9qj+KSN0ybMRA/Vfs5wOzE9uCeP9347c3ANcBV8fn7gQeMLNcdwZVfxSRumTYiIE6g93dd7n7zsoGfBDYAiw3MwOuBW5x9/vcfT1wBXAMsDDluVtO9UcRGbcMGzHQwD12M5sCXA7c5e4OzAU6gWWVc9y9H1gOXNTgnJlT/VFExi3DRgw09uTpbwPHAXfHH3fGb/uqzutLHBvFzKaa2fTKBgR7r0P1RxEZjywbMdBYsH8C+JG7b6/a71UfW419SYuA3YltWwMzNZXqjyJyRBk3YmCCwW5mbwXeD3w9sXtn/Lb66ryD0VfxSbcCMxLbSROZqVVUfxSRMWXciIGJX7H/MfAicH9i31aicK80ZSr34ecDKw73QO7e7+57Khuwd4IztYTqjyIypowbMTCBYDezNqJgv8fdByv74ydQlwKLzexSM5tHdP99P3BvKtMGQvVHETmsjBsxMLEr9vcDbwHuqnFsCVG43wF0AXOAi9096KvwiVD9UURqyrgRAxMIdndf5u7m7k/WOObufpO7z3b3o9x9ftxnLxzVH0WklqwbMaC1Yhqi+qOIHCKARgwEFOwhLtt7JMceC//ri6o/ikgsgEYMBBTsIS7bOx6XXab6o4jEAmjEQEDBnleqP4rIQQE0YkDBngrVH0UECKIRAwr21Kj+KCIhNGJAwZ4a1R9FSi6QRgwo2FOl+qNIiQXSiAEFe6pUfxQpsUAaMRBQsOexx16L6o8iJRVIIwYCCva89tirqf4oUlKBNGIgoGAvkkr9cdKPb1P9UaQkQmnEgIK9aZbc1kb7wEzVH0XKIKBGDCjYm0b1R5ESCagRAwr2plL9UaQkAmrEgIK9qVR/FCmJgBoxEFCwF6XuWE31R5ESCKgRAwEFe1HqjtVUfxQpvpAaMRBQsBeZ6o8iBRZYIwYU7C2j+qNIQQXWiAEFe8uo/ihSUIE1YkDB3lKqP4oUUGCNGFCwt5TqjyIFFFgjBhTsLaf6o0ixhNaIgYCCvag99mqqP4oUSICNGAgo2IvaY69F9UeRggiwEQMBBXvZqP4oUgABNmJgAsFuZnPM7Jtm9rKZ7TezXjM7L3HczOwmM9tuZgfM7GEzC+zvs+yp/ihSAAE2YqDOYDezmcBPgQHgA8DpwJ8DryZOuwG4DrgaOB/YCTxgZrrnUEX1R5GcC7ARA/Vfsd8IPO/uf+zuq9z9GXd/yN23QHS1DlwL3OLu97n7euAK4BhgYZqDF4HqjyL5FmIjBuoP9g8DXWb2XTN70cx6zOyTieNzgU5gWWWHu/cDy4GLGp62gFR/FMmpQBsxUH+wvw24EtgMXAJ8Dfh7M/tYfLwzfttX9Xl9iWOHMLOpZja9sgGlumWj+qNITgXaiIH6g70N6Hb3xe7e4+53Av9EFPZJXvWx1dhXsQjYndi21TlT7qn+KJJDgTZioP5g3wFsrNq3CXhL/P7O+G311XkHo6/iK24FZiS2k+qcqRBUfxTJmUAbMVB/sP8UOK1q36nAs/H7W4nCfUHloJlNAeYDK2o9oLv3u/ueygbsrXOmQlD9USRnAm3EQP3B/hXgAjNbbGZvN7OFwKeA2wHc3YGlwGIzu9TM5gF3A/uBe1ObuqBUfxTJj1AbMVBnsLv7auBS4DJgPfA54Fp3/1bitCVE4X4H0AXMAS5291JeiddD9UeRnAi4EQNg0UV2OOJmzG5gRnxrph5hfTMTMDwM77xgkN4XNjL0P34Z2oazHklEqu04G+7sZcUKuPDCln5lG89JKk4HRvVHkRwIuBEDAQV7WZbtHQ/VH0UCF3AjBgIK9jIt2zseqj+KBCzgRgwEFOxyKNUfRcIVciMGFOxBU/1RJECBN2JAwR401R9FAhTwGjEVCvbAafVHkcAE3ogBBXvwVH8UCUzgjRhQsOfCBRfAZQtVfxQJQuCNGAgo2NVjH9ttX1D9USQEoTdiIKBgV499bKo/igQgB40YCCjY5chUfxTJWA4aMaBgzxXVH0UyloNGDCjYc0f1R5EM5aARAwr23FH9USRDOWjEgII9l1R/FMlGHhoxoGDPLdUfRVosJ40YCCjY1WOvj+qPIi2Wk0YMBBTs6rHXT/VHkRbKSSMGAgp2qZ/qjyItlJNGDCjYc0/1R5EWyUkjBhTsuaf6o0hr5KURAwr2QlD9UaTJctSIAQV7Yaj+KNJEOWrEQEDBrrpjY1R/FGmiHDViIKBgV92xcao/ijRJjhoxEFCwS+NUfxRpkhw1YqDOYDezm8zMq7adieMWn7PdzA6Y2cNmlpO7UsWg+qNI+vLUiIGJXbFvAGYntjMTx24ArgOuBs4HdgIPmJmqGi2i+qNIynLWiIGJBfugu+9MbLsguloHrgVucff73H09cAVwDLAwtYnliFR/FElRzhoxMLFgPyW+1bLVzL5jZm+L988FOoFllRPdvR9YDlzU+KhSD9UfRVKSs0YM1B/sK4GPAZcAnyQK8hVmdnz8PkBf1ef0JY6NYmZTzWx6ZQN0iZkC1R9FUpKzRgzUGezu/iN3/567r3P3B4Hfig9dkTyt6tOsxr6kRcDuxLatnpnk8FR/FElBzhox0GDd0d33AeuAU4ieKIXRV+cdjL6KT7oVmJHYTmpkJhmh+qNI4/LWiIEGg93MpgK/BOwAthKF+4LE8SnAfGDF4R7D3fvdfU9lA/Y2MpMcSvVHkQbksBED9ffYv2Rm881srpm9C/jfwHTgHnd3YCmw2MwuNbN5wN3AfuDedMeW8VL9UaQBOWzEQP1X7CcB3waeAO4D3gAucPdn4+NLiML9DqALmANc7O66Cs+Q6o8iE5TDRgyARRfa4YibMbuBGfGtmXqE9c0E5Pnn4ZRTh+g/74uwYFHW44jkw0M30/HU9fRtn5L1JBU2npN007UkVH8UmYAcNmIgoGDXsr3Np/qjSH3y2IiBgIJdy/Y2n+qPInXIaSMGAgp2aQ3VH0XGKaeNGFCwl47qjyLjlNNGDCjYS0n1R5FxyOEaMRUK9pLS6o8iR5DTRgwo2EtL9UeRseW1EQMK9lK74Qbo6FD9UWSUHDdiIKBgV4+99Y45Br60RPVHkVFy3IiBgIJdPfZsqP4oUkOOGzEQULBLNlR/FKkhx40YULALqj+KjJLjRgwo2CWm+qPIiDw3YkDBLjHVH0ViOW/EgIJdElR/FCH3jRhQsEuC6o8i5L4RAwEFu3rsYVD9UUov540YCCjY1WMPg+qPUno5b8RAQMEu4VD9Ucos740YULDLYaj+KKVUgEYMKNjlMFR/lFIqQCMGFOwyBtUfpXQK0IgBBbuMQfVHKZ0CNGIgoGBX3TFMqj9KqRSgEQMBBbvqjmFS/VHKpAiNGAgo2CVcqj9KKRSkEQMNBruZLTIzN7OliX1mZjeZ2XYzO2BmD5tZzp9jloP1x58synoUkeYoSCMGGgh2Mzsf+BSwturQDcB1wNXA+cBO4AEz06Vejh2sPz76F6o/SjEVpBEDEwx2M3sT8C3gk8DPEvsNuBa4xd3vc/f1wBXAMcDChqeVTKn+KIVWkEYMTPyK/Xbgfnd/sGr/XKATWFbZ4e79wHLgogl+LQmE6o9SaAVpxMAEgt3MPgqcC9S62doZv+2r2t+XOFb9eFPNbHplA3TLJmCqP0pRFaURA3UGu5mdDPwdcLm7vz7GqV79qTX2VSwCdie2bfXMJK2l+qMUUoEaMVD/Fft5QAewxswGzWwQmA/8Wfx+5Uq9+uq8g9FX8RW3AjMS20l1ziQtpvqjFE6BGjFQf7A/BJwJnJPYuoieSD0HeJqoBbOg8glmNoUo/FfUekB373f3PZUN2FvnTJIB1R+lUArUiIE6g93d97r7+uQG7ANejj92YCmw2MwuNbN5wN3AfuDelGeXDKn+KIVSoEYMNOeVp0uIwv0Ooqv5OcDF7q4r8YJR/VEKo0CNGEgh2N39Pe5+beJjd/eb3H22ux/l7vPjK3spGNUfpSiK1IgBrRUjDVL9UXKvYI0YCCjYtWxvPqn+KLlXsEYMBBTsWrY3v1R/lFzbFV2q64pdpIrqj5Jbu85g1onFacSAgl1Sovqj5NaueZx5RnGeOAUFu6RI9UfJo8kvn1WoRgwo2CVFqj9K7gxMZeCltxTqiVNQsEvKVH+UXHnpF8HbC/XEKSjYJWWqP0quFLARAwEFu3rsxaH6o+RGARsxEFCwq8deLKo/Si4UsBEDAQW7FIvqj5IHRWzEgIJdmkj1RwlaQRsxoGCXJlL9UYJW0EYMKNilyVR/lGAVtBEDCnZpMtUfJVgFbcSAgl1aQPVHCVJBGzEQULCrx15sqj9KaIraiIGAgl099mJT/VGCUuBGDAQU7FJ8qj9KMArciAEFu7SQ6o8SjAI3YkDBLi2m+qMEocCNGFCwS4up/ihBKHAjBhTskgHVHyVrRW7EQEDBrrpjuaj+KJkpeCMGAgp21R3LRfVHyUzBGzEQULBL+aj+KJkoeCMG6gx2M7vSzNaa2Z54e8TMPpA4bmZ2k5ltN7MDZvawmRX4HzzSCNUfJRMFb8RA/Vfs24BPA++It/8H/CAR3jcA1wFXA+cDO4EHzEzPkElNqj9KyxW8EQN1Bru7/9Dd/8Pdn4y3zwCvAReYmQHXAre4+33uvh64AjgGWJj24FIMqj9KqxW9EQMN3GM3s3Yz+yhwLPAIMBfoBJZVznH3fmA5cFGDc0qBqf4oLVOCRgxMINjN7Ewzew3oB74GXOruG4lCHaCv6lP6EsdqPd5UM5te2QD9yS4h1R+lJUrQiIGJXbE/AZwDXAD8I3CPmSV/TF51vtXYl7QI2J3Ytk1gJsk51R+lJUrQiIEJBLu7v+HuT7l7l7svAh4DriF6ohRGX513MPoqPulWYEZiO6nemaQYVH+UpitBIwbS6bEbMBXYShTuCw4eMJsCzAdWHO6T3b3f3fdUNmBvCjNJDqn+KE1XgkYM1N9j/1sz+zUz+/n4XvstwHuAb7m7A0uBxWZ2qZnNA+4G9gP3pju2FJXqj9JMZWjEQP1X7LOAbxDdZ38IeBfwG+7+QHx8CVG43wF0AXOAi91dV+EyLqo/StOUpBEDYNGFdjjiZsxuYEZ8a6YeYX0zMmEL/3CY7/7wFQavehscpesCScGOs+HOXlasgAsvzHqYCbPxnKR/60qQVH+U1JWkEQMBBbuW7ZUk1R8ldSVpxEBAwa5le6Wa6o+SqpI0YiCgYBeppvqjpKksjRhQsEvgVH+UVJSoEQMKdgmc6o+SipKsEVOhYJfgafVHaViJGjGgYJecUP1RGlKiRgwo2CUnTj4ZFn1a9UeZoBI1YiCgYFePXY7k+utVf5SJKVMjBgIKdvXY5UhUf5QJKVkjBgIKdpHxUP1R6layRgwo2CVnVH+UupWsEQMKdskh1R+lLiVrxICCXXJK9UcZt5I1YkDBLjml+qOMV9kaMaBglxxT/VGOqISNGAgo2NVjl3qp/ihHVMJGDAQU7Oqxy0So/ihjKmEjBgIKdpGJUP1RxlTCRgwo2KUAVH+UwyphIwYU7FIQqj9KLWVsxICCXQpC9UcZpaSNGFCwS4Go/iiHKGkjBgIKdtUdpVGqP8ohStqIgYCCXXVHSYPqj3JQSRsxEFCwi6RB9Uc5qKSNGFCwSwGp/ihQ3kYM1BnsZrbIzFab2V4ze9HMvm9mp1WdY2Z2k5ltN7MDZvawmZXweWnJkuqPJVfiRgzUf8U+H7gduABYAEwClpnZsYlzbgCuA64Gzgd2Ag+YmS6dpGVUfyy5EjdiAMzdJ/7JZicALwLz3f0/zcyA7cBSd78tPmcq0Afc6O53juMxpwO7gRnuvqfOkSb+zUjh7N8Pv3DKAH3H/R/8D34v63GkldZeBvfdy6uvUrQnT208JzV6j73yI3slfjsX6ASWVU5w935gOXBRrQcws6lmNr2yAbqyl1So/lhiJW7EQAPBHl+dfxn4ibuvj3d3xm/7qk7vSxyrtojoCr2ybZvoTCLVVH8sqRI3YqCxK/avAmcBl9U4Vn1LxGrsq7iV6Mq/sp3UwEwih1D9sZzK3IiBCQa7mf0D8GHgve6evMLeGb+tvjrvYPRVPBDdqnH3PZUN2DuRmUQOR/XHkil5IwbqrzuamX0V+B3g1919a9UpW4nCfUHic6YQtWlWNDiryISp/lgiJW/EQP1X7LcDlwMLgb1m1hlvRwN4VLFZCiw2s0vNbB5wN7AfuDe1qUXqpPpjiZR4jZiKeoP9SqL74A8DOxLbRxLnLCEK9zuALmAOcLG76xaLZEqrP5ZEyRsxUGewu7sdZrs7cY67+03uPtvdj3L3+YnWjEhmVH8siZI3YkBrxUjJqP5YfGVvxEBAwa712KUVVH8sODVigICCXeuxS6uo/lhgasQAAQW7SCup/lhQasQACnYpKdUfC0qNGEDBLiV2SP1xeFyL5kno1IgBFOxSYsccAzf8RVx//OtB+Ob98MbRWY8lDVAjJqJgl1JbvrzyXhs89Zuw/C+1qn9eqRFz0KSsB6gws6uAq9BfNtJCr75ateOnn2bS2k8x1PkofuIqmLMaTlwNb9qVxXhSDzViDmrof1BqBv0PStJK3/8+/P7vw+AgzJwJN98MO3bAylVDrFw1zJ5XJwMwaeZ2BjtXjAT9iWvgqHp/e0pTFfd/TUoa15NBCnYpvU2b4PHHo3777Nkj+91h61ZYvTraHl05yJpu4/X90T3cyR1bGOhcEQX9nNXQ2QuTX8/mmxB46GZmbbmenS9MyXqSZlKwi6RtaCj6S6AS9o+sHGDd2nYGB9qw9kHaZ21isPORkSv7jg3QPpj12OXwne/z/pM/yAPLCv3kqYJdpBXeeAPWrq2EvfPIqgGe3DSZ4WGjbXI/NvsxhmY/MnJl/+bN0KbfqmmbfPvTXH35XL785awnaSoFu0hW9u2Dnp6RsF/x6ADPbo1uEbQf/Rre2cXwiStHwn7Gc+P8Iys1DUyFv93H1/+pnU98IuthmkrBLhKSn/0MurqisF+1aphHVg3y4o4o7CdNe5mhzpVq4kzUjrPhzl5WrIALL8x6mKZSsIuEbseOkfv1auI0oByNGMhbsFf12E9DwS4ldKQmzqSOLVHYq4lzqHI0YiBvwV6hK3aRQ6mJMw7laMSAgl2kuNTEOVRJGjGgYBcpl2QTZ9Vq55HqJs7s1QzPXjlyZT/j+WI0ccrTiAEFu4gcsYkzO14Tp3Jlf+xLGU88AeVpxICCXURqGauJM/nNLzAw65F8NXHK04gBBbuIjEfumzjlacRA3oJddUeRcOSqiVOeRgzkLdgrdMUuEqZRTZyVAzz5eLKJ08vQ7Edb3sQpUSMGFOwi0mxjN3H24rO7mtvEKVcjBhTsIpKFljZxytWIgWYFu5m9G7geOA+YDVzq7t9PHDfg88CngJnASuAqd98wzsdXsIsUzBGbOMknZ2evgaP2ju+By9WIgSYG+weAXwG6ge8xOthvBD4DfBx4Evgs8G7gNHc/4q+Wgl2k+MZs4tgwk094Ogr7yi2czl6Y3H/ogwy3wf23c8K2/86LO0vRiIFW3IoxMycR7PHV+nZgqbvfFu+bCvQBN7r7neN4TAW7SAkdsYnTuZHBWY9GYT+rFx5cAs+8FzPn2982PvKRrL+Dlsgk2N8GbAHOdfeexHk/AF519ytqPMZUYGpi1zRgGwp2kdIbq4mTNGcObNuW0ZCtNa5gb0v5i3bGb/uq9vcljlVbRHSFXtnK8csjIkc0ZQq84x1w5ZVw113Gpg1T2LPH+PznDz3PirDmTYrSDvaK6itnq7Gv4lZgRmI7qUkziUgBHHssLF4M73tf9PHUqfCVr2Q7U2gmpfx4O+O3ncCOxP4ORl/FA+Du/cDBZ0VMf/WKyBFMmQLLlsGWLfDmN8Pxx2c9UVjSvmLfShTuCyo7zGwKMB9YkfLXEpESa2uDU05RqNdS9xW7mb0JeHti11wzOwd4xd2fM7OlwGIz2wxsBhYD+4F7Gx9XRESOZCK3Yt4B/DjxcWWFhnuIuutLgKOBOxh5gdLF4+mwi4hI44q2pICISOmFGOxG1GXf66ENJyKSA8EFu4iINKZZPXYREcmIgl1EpGAU7CIiBaNgFxEpGAW7iEjBKNhFRApGwS4iUjAKdhGRglGwi4gUjIJdRKRg0v6PNjKTWGNGRKTIjriOVmGCnSjUd2c9hIhIk80Axlz5tjCLgB3hin0V8M4xPr2R42Mdm0b0n3OfBNRaj15z1TdXI4+tudKda6zjmqu5c5Xnij3+Rmv+LWZmw2Ot7d7I8SMcq7y7t9Y5mqu+uRp5bM2V7lxjHddcrZ2rlrI8eXp7E48f6XOb9XWPdLyIczX62Jqrvsdu9PhEP1dzNfi5hbkVE6JQ/zcozVUfzVUfzVWfZsxVliv2rPQDfxW/DYnmqo/mqo/mqk/qc+mKXUSkYHTFLiJSMAp2EZGCUbCLiBSMgl1EpGAU7A0ys0VmttrM9prZi2b2fTM7reocM7ObzGy7mR0ws4fN7Iwmz3Wlma01sz3x9oiZfSDLmQ4z5yIzczNbmuVs8dfzqm1nljMlvvYcM/ummb1sZvvNrNfMzstyNjN7psbPy83s9qxmir/uJDO72cy2xl/3aTP7SzNrS5yT1WzTzGypmT0bf90VZnZ+U+Zyd20NbMD/BT4OnAGcDfw78CxwbOKcG4leFfs7wDzgO8B2YFoT5/oQ8JvAqfF2C/AGcEZWM9WY8XxgK/AYsDTjn9dNwHqgM7GdkOVM8dedCTwD/AvRS8p/Hngf8AsZ/7xOqPpZvR9w4D0Z/7w+A7wE/Fb8s/o9opfpXxPAr+W/ARuAdwNvj3/P7QbmpD1X076Jsm7xb3gH3h1/bMAO4MbEOVOBV4E/afFsrwCfCGEm4E3Ak3EgPFwJ9qxmi/+Q9R7mWGY/L+ALwH+NcTzzX8v4ay4FnornyfLn9e/AP1ft+x7wjYx/fx0NDAK/VbW/F7g57bl0KyZ9M+K3r8Rv5xJd0SyrnODu/cBy4KJWDGRm7Wb2UeBY4JEQZiJ6ifT97v5g1f4sZzsl/mfwVjP7jpm9LYCZPgx0mdl341t9PWb2ycTxzH8tzWwKcDlwl0eJlOVMPwHeZ2anxrOdDfwq8B/x8axmmwS0A69X7T8Qz5fqXAr2FJmZAV8GfuLu6+PdnfHbvqrT+xLHmjXPmWb2GtEr2r4GXOruG7OcKZ7ro8C5wKIah7OabSXwMeAS4JPx11phZsdnOBPA24Argc3xbF8D/t7MPhYfz/TXMvbbwHHA3fHHWc50G/Bt4HEzGwB6iP41+O0sZ3P3vUQXVZ8zsxPji63LgXcBs9OeqzCrOwbiq8BZRH8DV6t+ia/V2Je2J4BziP7Q/S5wj5nNz3ImMzsZ+DvgYnevvnpJauls7v6jxIfrzOwRYAtwBfBoFjPF2oAud18cf9wTP6F2JfCvifOymK3iE8CP3H171f4sZvoI0b8eFhLdzz4HWGpm2939noxn+yPgLuAFYAjoBu4lushJdS5dsafEzP6B6J/N73X3bYlDlWZF9d+6HYz+2zlV7v6Guz/l7l3uvojoScprspwJOC/+OmvMbNDMBoH5wJ/F71e+fhazHeTu+4B1wClk+/PaAWys2rcJeEv8fpazYWZvJXqe5OuJ3VnO9EXgC+7+HXdf5+7fAL7CyL8Os/zzuMXd5xM9v3Syu78TmExUIEh1LgV7g+KK0leJnsn+dXffWnVK5RdtQeJzphCF2YqWDRp/aaInZLKc6SHgTKIrqcrWBXwrfv/pDGc7yMymAr9EFKxZ/rx+CpxWte9UouYVGc8G8MfAi8D9iX1ZznQMMFy1b4iRrMv654W773P3HWY2k+j22g9Sn6uZz1CXYQPuIHrmej6H1r+OTpxzY3zOpUQ1pntpfh3tb4FfI6p8nUlUdxwCFmQ10xizPszoumOrf15fin8N5xLd9/whUfXsrVn+vIgqoQPAYqKK3EJgH/CHWf684q/bRvQXzBdqHMtqpruJ/jeiSt3xUmAXcFsAs10C/Eb8e2wBUSNmJTA57bma9k2UZSO6/1Vr+3jiHCOq0+0gelZ8OTCvyXP9M1H/uZ/oiupB4lDPaqYxZn2YQ4M9i59XpTP8BtE90O8Bp4fw8wI+SHRb6HWi2zCfrDqeyWzAxfHv9VNrHMtqpmlE1ctniRonW4jqhFMCmO0P4nn646/9VaI12FOfS8v2iogUjO6xi4gUjIJdRKRgFOwiIgWjYBcRKRgFu4hIwSjYRUQKRsEuIlIwCnYRkYJRsIuIFIyCXUSkYBTsIiIFo2AXESmY/w9PrrdDmjnriQAAAABJRU5ErkJggg==\n", "text/plain": [ "Graphics object consisting of 6 graphics primitives" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "P = Polyhedron(vertices=pts)\n", "P.plot()" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(A vertex at (12, 79),\n", " A vertex at (91, 94),\n", " A vertex at (77, 10),\n", " A vertex at (48, 16))" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "P.Vrepresentation()" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(An inequality (7, 4) x - 400 >= 0,\n", " An inequality (6, 29) x - 752 >= 0,\n", " An inequality (-6, 1) x + 452 >= 0,\n", " An inequality (15, -79) x + 6061 >= 0)" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "P.Hrepresentation()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 2. Linear Programming" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Linear programming deals with optimizing linear functions\n", "subject to linear constraints. We consider an example of the documentation." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "6.666666666666666" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "p = MixedIntegerLinearProgram(maximization=True)\n", "x = p.new_variable(nonnegative=True)\n", "p.set_objective(x[1] + 5*x[2])\n", "p.add_constraint(x[1] + 0.2*x[2], max=4)\n", "p.add_constraint(1.5*x[1] + 3*x[2], max=4)\n", "p.solve()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "What is returned is the value of the objective function. To see the values of the coordinates at the optimal solution, we do the following." ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{1: 0.0, 2: 1.3333333333333333}" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "p.get_values(x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This problem can be solved interactively, in a step by step fashion." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We first convert the problem to its standard form." ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "Graphics object consisting of 16 graphics primitives" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "A = ([1, 0.2], [1.5, 3])\n", "b = (4, 4)\n", "c = (1, 5)\n", "P = InteractiveLPProblem(A, b, c, [\"x1\", \"x2\"], problem_type=\"max\", constraint_type=\"<=\", variable_type=\">=\")\n", "P.plot().show(figsize=5)" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "LP problem (use 'view(...)' or '%display typeset' for details)" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "F = P.standard_form()\n", "F" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\begin{array}{l}\n", "\\begin{array}{lcrcrcl}\n", " \\max \\mspace{-6mu}&\\mspace{-6mu} \\mspace{-6mu}&\\mspace{-6mu} x_{1} \\mspace{-6mu}&\\mspace{-6mu} + \\mspace{-6mu}&\\mspace{-6mu} 5.00000000000000 x_{2} \\mspace{-6mu}&\\mspace{-6mu} \\mspace{-6mu}&\\mspace{-6mu} \\\\\n", " \\mspace{-6mu}&\\mspace{-6mu} \\mspace{-6mu}&\\mspace{-6mu} x_{1} \\mspace{-6mu}&\\mspace{-6mu} + \\mspace{-6mu}&\\mspace{-6mu} 0.200000000000000 x_{2} \\mspace{-6mu}&\\mspace{-6mu} \\leq \\mspace{-6mu}&\\mspace{-6mu} 4.00000000000000 \\\\\n", " \\mspace{-6mu}&\\mspace{-6mu} \\mspace{-6mu}&\\mspace{-6mu} 1.50000000000000 x_{1} \\mspace{-6mu}&\\mspace{-6mu} + \\mspace{-6mu}&\\mspace{-6mu} 3.00000000000000 x_{2} \\mspace{-6mu}&\\mspace{-6mu} \\leq \\mspace{-6mu}&\\mspace{-6mu} 4.00000000000000 \\\\\n", "\\end{array} \\\\\n", "x_{1}, x_{2} \\geq 0\n", "\\end{array}$$" ], "text/plain": [ "LP problem (use 'view(...)' or '%display typeset' for details)" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%display typeset\n", "F" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "scrolled": true }, "outputs": [ { "data": { "text/html": [ "\\begin{equation*}\n", "\\renewcommand{\\arraystretch}{1.5} %notruncate\n", "\\begin{array}{|rcrcrcr|}\n", "\\hline\n", "x_{3} \\mspace{-6mu}&\\mspace{-6mu} = \\mspace{-6mu}&\\mspace{-6mu} 4.00000000000000 \\mspace{-6mu}&\\mspace{-6mu} - \\mspace{-6mu}&\\color{green}{\\mspace{-6mu} x_{1} \\mspace{-6mu}}&\\mspace{-6mu} - \\mspace{-6mu}&\\mspace{-6mu} 0.200000000000000 x_{2}\\\\\n", "\\color{red}{x_{4} \\mspace{-6mu}}&\\color{red}{\\mspace{-6mu} = \\mspace{-6mu}}&\\color{red}{\\mspace{-6mu} 4.00000000000000 \\mspace{-6mu}}&\\color{red}{\\mspace{-6mu} - \\mspace{-6mu}}&\\color{blue}{{\\mspace{-6mu} 1.50000000000000 x_{1} \\mspace{-6mu}}}&\\color{red}{\\mspace{-6mu} - \\mspace{-6mu}}&\\color{red}{\\mspace{-6mu} 3.00000000000000 x_{2}}\\\\\n", "\\hline\n", "z \\mspace{-6mu}&\\mspace{-6mu} = \\mspace{-6mu}&\\mspace{-6mu} 0 \\mspace{-6mu}&\\mspace{-6mu} + \\mspace{-6mu}&\\color{green}{\\mspace{-6mu} x_{1} \\mspace{-6mu}}&\\mspace{-6mu} + \\mspace{-6mu}&\\mspace{-6mu} 5.00000000000000 x_{2}\\\\\n", "\\hline\n", "\\end{array}\n", "\\end{equation*}\n", "Entering: $x_{1}$. Leaving: $x_{4}$. \n", "\\begin{equation*}\n", "\\renewcommand{\\arraystretch}{1.5} %notruncate\n", "\\begin{array}{|rcrcrcr|}\n", "\\hline\n", "x_{3} \\mspace{-6mu}&\\mspace{-6mu} = \\mspace{-6mu}&\\mspace{-6mu} 1.33333333333333 \\mspace{-6mu}&\\mspace{-6mu} + \\mspace{-6mu}&\\mspace{-6mu} 0.666666666666667 x_{4} \\mspace{-6mu}&\\mspace{-6mu} + \\mspace{-6mu}&\\color{green}{\\mspace{-6mu} 1.80000000000000 x_{2}}\\\\\n", "\\color{red}{x_{1} \\mspace{-6mu}}&\\color{red}{\\mspace{-6mu} = \\mspace{-6mu}}&\\color{red}{\\mspace{-6mu} 2.66666666666667 \\mspace{-6mu}}&\\color{red}{\\mspace{-6mu} - \\mspace{-6mu}}&\\color{red}{\\mspace{-6mu} 0.666666666666667 x_{4} \\mspace{-6mu}}&\\color{red}{\\mspace{-6mu} - \\mspace{-6mu}}&\\color{blue}{{\\mspace{-6mu} 2.00000000000000 x_{2}}}\\\\\n", "\\hline\n", "z \\mspace{-6mu}&\\mspace{-6mu} = \\mspace{-6mu}&\\mspace{-6mu} 2.66666666666667 \\mspace{-6mu}&\\mspace{-6mu} - \\mspace{-6mu}&\\mspace{-6mu} 0.666666666666667 x_{4} \\mspace{-6mu}&\\mspace{-6mu} + \\mspace{-6mu}&\\color{green}{\\mspace{-6mu} 3.00000000000000 x_{2}}\\\\\n", "\\hline\n", "\\end{array}\n", "\\end{equation*}\n", "Entering: $x_{2}$. Leaving: $x_{1}$. \n", "\\begin{equation*}\n", "\\renewcommand{\\arraystretch}{1.5} %notruncate\n", "\\begin{array}{|rcrcrcr|}\n", "\\hline\n", "x_{3} \\mspace{-6mu}&\\mspace{-6mu} = \\mspace{-6mu}&\\mspace{-6mu} 3.73333333333333 \\mspace{-6mu}&\\mspace{-6mu} + \\mspace{-6mu}&\\mspace{-6mu} 0.0666666666666667 x_{4} \\mspace{-6mu}&\\mspace{-6mu} - \\mspace{-6mu}&\\mspace{-6mu} 0.900000000000000 x_{1}\\\\\n", "x_{2} \\mspace{-6mu}&\\mspace{-6mu} = \\mspace{-6mu}&\\mspace{-6mu} 1.33333333333333 \\mspace{-6mu}&\\mspace{-6mu} - \\mspace{-6mu}&\\mspace{-6mu} 0.333333333333333 x_{4} \\mspace{-6mu}&\\mspace{-6mu} - \\mspace{-6mu}&\\mspace{-6mu} 0.500000000000000 x_{1}\\\\\n", "\\hline\n", "z \\mspace{-6mu}&\\mspace{-6mu} = \\mspace{-6mu}&\\mspace{-6mu} 6.66666666666667 \\mspace{-6mu}&\\mspace{-6mu} - \\mspace{-6mu}&\\mspace{-6mu} 1.66666666666667 x_{4} \\mspace{-6mu}&\\mspace{-6mu} - \\mspace{-6mu}&\\mspace{-6mu} 1.50000000000000 x_{1}\\\\\n", "\\hline\n", "\\end{array}\n", "\\end{equation*}\n", "The optimal value: $6.66666666666667$. An optimal solution: $\\left(0.000000000000000,\\,1.33333333333333\\right)$." ], "text/plain": [ "\\begin{equation*}\n", "\\renewcommand{\\arraystretch}{1.5} %notruncate\n", "\\begin{array}{|rcrcrcr|}\n", "\\hline\n", "x_{3} \\mspace{-6mu}&\\mspace{-6mu} = \\mspace{-6mu}&\\mspace{-6mu} 4.00000000000000 \\mspace{-6mu}&\\mspace{-6mu} - \\mspace{-6mu}&\\color{green}{\\mspace{-6mu} x_{1} \\mspace{-6mu}}&\\mspace{-6mu} - \\mspace{-6mu}&\\mspace{-6mu} 0.200000000000000 x_{2}\\\\\n", "\\color{red}{x_{4} \\mspace{-6mu}}&\\color{red}{\\mspace{-6mu} = \\mspace{-6mu}}&\\color{red}{\\mspace{-6mu} 4.00000000000000 \\mspace{-6mu}}&\\color{red}{\\mspace{-6mu} - \\mspace{-6mu}}&\\color{blue}{{\\mspace{-6mu} 1.50000000000000 x_{1} \\mspace{-6mu}}}&\\color{red}{\\mspace{-6mu} - \\mspace{-6mu}}&\\color{red}{\\mspace{-6mu} 3.00000000000000 x_{2}}\\\\\n", "\\hline\n", "z \\mspace{-6mu}&\\mspace{-6mu} = \\mspace{-6mu}&\\mspace{-6mu} 0 \\mspace{-6mu}&\\mspace{-6mu} + \\mspace{-6mu}&\\color{green}{\\mspace{-6mu} x_{1} \\mspace{-6mu}}&\\mspace{-6mu} + \\mspace{-6mu}&\\mspace{-6mu} 5.00000000000000 x_{2}\\\\\n", "\\hline\n", "\\end{array}\n", "\\end{equation*}\n", "Entering: $x_{1}$. Leaving: $x_{4}$. \n", "\\begin{equation*}\n", "\\renewcommand{\\arraystretch}{1.5} %notruncate\n", "\\begin{array}{|rcrcrcr|}\n", "\\hline\n", "x_{3} \\mspace{-6mu}&\\mspace{-6mu} = \\mspace{-6mu}&\\mspace{-6mu} 1.33333333333333 \\mspace{-6mu}&\\mspace{-6mu} + \\mspace{-6mu}&\\mspace{-6mu} 0.666666666666667 x_{4} \\mspace{-6mu}&\\mspace{-6mu} + \\mspace{-6mu}&\\color{green}{\\mspace{-6mu} 1.80000000000000 x_{2}}\\\\\n", "\\color{red}{x_{1} \\mspace{-6mu}}&\\color{red}{\\mspace{-6mu} = \\mspace{-6mu}}&\\color{red}{\\mspace{-6mu} 2.66666666666667 \\mspace{-6mu}}&\\color{red}{\\mspace{-6mu} - \\mspace{-6mu}}&\\color{red}{\\mspace{-6mu} 0.666666666666667 x_{4} \\mspace{-6mu}}&\\color{red}{\\mspace{-6mu} - \\mspace{-6mu}}&\\color{blue}{{\\mspace{-6mu} 2.00000000000000 x_{2}}}\\\\\n", "\\hline\n", "z \\mspace{-6mu}&\\mspace{-6mu} = \\mspace{-6mu}&\\mspace{-6mu} 2.66666666666667 \\mspace{-6mu}&\\mspace{-6mu} - \\mspace{-6mu}&\\mspace{-6mu} 0.666666666666667 x_{4} \\mspace{-6mu}&\\mspace{-6mu} + \\mspace{-6mu}&\\color{green}{\\mspace{-6mu} 3.00000000000000 x_{2}}\\\\\n", "\\hline\n", "\\end{array}\n", "\\end{equation*}\n", "Entering: $x_{2}$. Leaving: $x_{1}$. \n", "\\begin{equation*}\n", "\\renewcommand{\\arraystretch}{1.5} %notruncate\n", "\\begin{array}{|rcrcrcr|}\n", "\\hline\n", "x_{3} \\mspace{-6mu}&\\mspace{-6mu} = \\mspace{-6mu}&\\mspace{-6mu} 3.73333333333333 \\mspace{-6mu}&\\mspace{-6mu} + \\mspace{-6mu}&\\mspace{-6mu} 0.0666666666666667 x_{4} \\mspace{-6mu}&\\mspace{-6mu} - \\mspace{-6mu}&\\mspace{-6mu} 0.900000000000000 x_{1}\\\\\n", "x_{2} \\mspace{-6mu}&\\mspace{-6mu} = \\mspace{-6mu}&\\mspace{-6mu} 1.33333333333333 \\mspace{-6mu}&\\mspace{-6mu} - \\mspace{-6mu}&\\mspace{-6mu} 0.333333333333333 x_{4} \\mspace{-6mu}&\\mspace{-6mu} - \\mspace{-6mu}&\\mspace{-6mu} 0.500000000000000 x_{1}\\\\\n", "\\hline\n", "z \\mspace{-6mu}&\\mspace{-6mu} = \\mspace{-6mu}&\\mspace{-6mu} 6.66666666666667 \\mspace{-6mu}&\\mspace{-6mu} - \\mspace{-6mu}&\\mspace{-6mu} 1.66666666666667 x_{4} \\mspace{-6mu}&\\mspace{-6mu} - \\mspace{-6mu}&\\mspace{-6mu} 1.50000000000000 x_{1}\\\\\n", "\\hline\n", "\\end{array}\n", "\\end{equation*}\n", "The optimal value: $6.66666666666667$. An optimal solution: $\\left(0.000000000000000,\\,1.33333333333333\\right)$." ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%display typeset\n", "F.run_simplex_method()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also run the simplex method step-by-step." ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\begin{equation*}\n", "\\renewcommand{\\arraystretch}{1.5} %notruncate\n", "\\begin{array}{|rcrcrcr|}\n", "\\hline\n", "x_{3} \\mspace{-6mu}&\\mspace{-6mu} = \\mspace{-6mu}&\\mspace{-6mu} 4.00000000000000 \\mspace{-6mu}&\\mspace{-6mu} - \\mspace{-6mu}&\\mspace{-6mu} x_{1} \\mspace{-6mu}&\\mspace{-6mu} - \\mspace{-6mu}&\\mspace{-6mu} 0.200000000000000 x_{2}\\\\\n", "x_{4} \\mspace{-6mu}&\\mspace{-6mu} = \\mspace{-6mu}&\\mspace{-6mu} 4.00000000000000 \\mspace{-6mu}&\\mspace{-6mu} - \\mspace{-6mu}&\\mspace{-6mu} 1.50000000000000 x_{1} \\mspace{-6mu}&\\mspace{-6mu} - \\mspace{-6mu}&\\mspace{-6mu} 3.00000000000000 x_{2}\\\\\n", "\\hline\n", "z \\mspace{-6mu}&\\mspace{-6mu} = \\mspace{-6mu}&\\mspace{-6mu} 0 \\mspace{-6mu}&\\mspace{-6mu} + \\mspace{-6mu}&\\mspace{-6mu} x_{1} \\mspace{-6mu}&\\mspace{-6mu} + \\mspace{-6mu}&\\mspace{-6mu} 5.00000000000000 x_{2}\\\\\n", "\\hline\n", "\\end{array}\n", "\\end{equation*}" ], "text/plain": [ "LP problem dictionary (use 'view(...)' or '%display typeset' for details)" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "D = F.initial_dictionary()\n", "show(D)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We ask for the solution, whether the solution is optional,\n", "and the value of the objective function." ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(0.000000000000000,\\,0.000000000000000\\right)$$" ], "text/plain": [ "(0.000000000000000, 0.000000000000000)" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "D.basic_solution()" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\mathrm{False}$$" ], "text/plain": [ "False" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "D.is_optimal()" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}0$$" ], "text/plain": [ "0" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "D.objective_value()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The simplex algorithm consists in swapping variables.\n", "Variables in the basis are swapped with variables not in the basis.\n", "We can ask for the possible variables which can enter the basis." ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(x_{3},\\,x_{4}\\right)$$" ], "text/plain": [ "(x3, x4)" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "D.basic_variables()" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(x_{1},\\,x_{2}\\right)$$" ], "text/plain": [ "(x1, x2)" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "D.nonbasic_variables()" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[x_{1}, x_{2}\\right]$$" ], "text/plain": [ "[x1, x2]" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "etr = D.possible_entering()\n", "etr" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We select the first of the possible entering variables.\n", "After setting the entering variable, we ask for the possible variables\n", "which can leave the basis." ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[x_{4}\\right]$$" ], "text/plain": [ "[x4]" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "D.enter(etr[0])\n", "lev = D.possible_leaving()\n", "lev" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We select the leaving variable and update the dictionary." ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\begin{equation*}\n", "\\renewcommand{\\arraystretch}{1.5} %notruncate\n", "\\begin{array}{|rcrcrcr|}\n", "\\hline\n", "x_{3} \\mspace{-6mu}&\\mspace{-6mu} = \\mspace{-6mu}&\\mspace{-6mu} 1.33333333333333 \\mspace{-6mu}&\\mspace{-6mu} + \\mspace{-6mu}&\\mspace{-6mu} 0.666666666666667 x_{4} \\mspace{-6mu}&\\mspace{-6mu} + \\mspace{-6mu}&\\mspace{-6mu} 1.80000000000000 x_{2}\\\\\n", "x_{1} \\mspace{-6mu}&\\mspace{-6mu} = \\mspace{-6mu}&\\mspace{-6mu} 2.66666666666667 \\mspace{-6mu}&\\mspace{-6mu} - \\mspace{-6mu}&\\mspace{-6mu} 0.666666666666667 x_{4} \\mspace{-6mu}&\\mspace{-6mu} - \\mspace{-6mu}&\\mspace{-6mu} 2.00000000000000 x_{2}\\\\\n", "\\hline\n", "z \\mspace{-6mu}&\\mspace{-6mu} = \\mspace{-6mu}&\\mspace{-6mu} 2.66666666666667 \\mspace{-6mu}&\\mspace{-6mu} - \\mspace{-6mu}&\\mspace{-6mu} 0.666666666666667 x_{4} \\mspace{-6mu}&\\mspace{-6mu} + \\mspace{-6mu}&\\mspace{-6mu} 3.00000000000000 x_{2}\\\\\n", "\\hline\n", "\\end{array}\n", "\\end{equation*}" ], "text/plain": [ "LP problem dictionary (use 'view(...)' or '%display typeset' for details)" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "D.leave(lev[0])\n", "D.update()\n", "show(D)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Should we continue? Let us check if the dictionary is optimal\n", "and what the objective value is." ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\mathrm{False}$$" ], "text/plain": [ "False" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "D.is_optimal()" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}2.66666666666667$$" ], "text/plain": [ "2.66666666666667" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "D.objective_value()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To continue, let us ask for the possible variables which may enter." ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[x_{2}\\right]$$" ], "text/plain": [ "[x2]" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "etr = D.possible_entering()\n", "etr" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "After selecting the entering variable,\n", "we ask for the possible variables which may leave." ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[x_{1}\\right]$$" ], "text/plain": [ "[x1]" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "D.enter(etr[0])\n", "lev = D.possible_leaving()\n", "lev" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "After selecting the leaving variable, we update the basis." ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\begin{equation*}\n", "\\renewcommand{\\arraystretch}{1.5} %notruncate\n", "\\begin{array}{|rcrcrcr|}\n", "\\hline\n", "x_{3} \\mspace{-6mu}&\\mspace{-6mu} = \\mspace{-6mu}&\\mspace{-6mu} 3.73333333333333 \\mspace{-6mu}&\\mspace{-6mu} + \\mspace{-6mu}&\\mspace{-6mu} 0.0666666666666667 x_{4} \\mspace{-6mu}&\\mspace{-6mu} - \\mspace{-6mu}&\\mspace{-6mu} 0.900000000000000 x_{1}\\\\\n", "x_{2} \\mspace{-6mu}&\\mspace{-6mu} = \\mspace{-6mu}&\\mspace{-6mu} 1.33333333333333 \\mspace{-6mu}&\\mspace{-6mu} - \\mspace{-6mu}&\\mspace{-6mu} 0.333333333333333 x_{4} \\mspace{-6mu}&\\mspace{-6mu} - \\mspace{-6mu}&\\mspace{-6mu} 0.500000000000000 x_{1}\\\\\n", "\\hline\n", "z \\mspace{-6mu}&\\mspace{-6mu} = \\mspace{-6mu}&\\mspace{-6mu} 6.66666666666667 \\mspace{-6mu}&\\mspace{-6mu} - \\mspace{-6mu}&\\mspace{-6mu} 1.66666666666667 x_{4} \\mspace{-6mu}&\\mspace{-6mu} - \\mspace{-6mu}&\\mspace{-6mu} 1.50000000000000 x_{1}\\\\\n", "\\hline\n", "\\end{array}\n", "\\end{equation*}" ], "text/plain": [ "LP problem dictionary (use 'view(...)' or '%display typeset' for details)" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "D.leave(lev[0])\n", "D.update()\n", "show(D)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Then we check again for optimality." ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\mathrm{True}$$" ], "text/plain": [ "True" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "D.is_optimal()" ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}6.66666666666667$$" ], "text/plain": [ "6.66666666666667" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "D.objective_value()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 3. Unconstrained Minimization" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To introduce minimization without constraints, we take a sum of squares function." ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n" ], "text/plain": [ "Graphics3d Object" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "x, y = var('x,y')\n", "f(x,y) = (3+x-y^2)^2 + (x - 1)^2 + (y - 1)^2\n", "pf = plot3d(f(x,y), (x, -2, 3), (y, -2, 3), adaptive=True, color='automatic',opacity=0.5, aspect_ratio=[5,5,1])\n", "pf.show(figsize=3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can look for a minimum. We need to give an initial guess." ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Optimization terminated successfully.\n", " Current function value: 0.882789\n", " Iterations: 10\n", " Function evaluations: 13\n", " Gradient evaluations: 13\n", "minimum at (0.7660442023843989, 1.8793852106252493) with value 0.8827888082854147\n" ] } ], "source": [ "p = minimize(f, x0=[0.0, 0.0], verbose=True)\n", "print('minimum at', p, 'with value', f(p[0], p[1]))" ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n" ], "text/plain": [ "Graphics3d Object" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "pt = point((p[0], p[1], f(p[0],p[1])), size=500, color='black')\n", "(pt+pf).show(figsize=4)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Even though this problem was defined to be straighforward, observe that the optimum lies in a valley." ] } ], "metadata": { "kernelspec": { "display_name": "SageMath 10.3", "language": "sage", "name": "sagemath" }, "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.10" } }, "nbformat": 4, "nbformat_minor": 4 }