Skip to content

Instantly share code, notes, and snippets.

@jGaboardi
Created June 1, 2022 15:30
Show Gist options
  • Save jGaboardi/9128fc7cda3e04d1840fd9c64c24e759 to your computer and use it in GitHub Desktop.
Save jGaboardi/9128fc7cda3e04d1840fd9c64c24e759 to your computer and use it in GitHub Desktop.
check_feasibility
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"metadata": {
"ExecuteTime": {
"start_time": "2022-06-01T15:30:28.021205Z",
"end_time": "2022-06-01T15:30:29.807847Z"
},
"trusted": true,
"scrolled": true
},
"cell_type": "code",
"source": "from spopt.locate.coverage import LSCP\nfrom spopt.locate.util import simulated_geo_points\n\nimport numpy\nimport geopandas\nimport pulp\nimport spaghetti\nfrom shapely.geometry import Point\nimport matplotlib.pyplot as plt",
"execution_count": 1,
"outputs": [
{
"output_type": "stream",
"text": "/Users/the-gaboardi/miniconda3/envs/py310_spopt/lib/python3.10/site-packages/spaghetti/network.py:36: FutureWarning: The next major release of pysal/spaghetti (2.0.0) will drop support for all ``libpysal.cg`` geometries. This change is a first step in refactoring ``spaghetti`` that is expected to result in dramatically reduced runtimes for network instantiation and operations. Users currently requiring network and point pattern input as ``libpysal.cg`` geometries should prepare for this simply by converting to ``shapely`` geometries.\n warnings.warn(f\"{dep_msg}\", FutureWarning)\n",
"name": "stderr"
}
]
},
{
"metadata": {
"ExecuteTime": {
"start_time": "2022-06-01T15:30:29.810478Z",
"end_time": "2022-06-01T15:30:29.814206Z"
},
"trusted": true
},
"cell_type": "code",
"source": "CLIENT_COUNT = 2 # quantity demand points\nFACILITY_COUNT = 1 # quantity supply points\n\nSERVICE_THRESHOLD = 2 # maximum service radius in meters\n\n# Random seeds for reproducibility\nCLIENT_SEED = 5 \nFACILITY_SEED = 6 \n\nsolver = pulp.PULP_CBC_CMD(msg=True, warmStart=True)",
"execution_count": 2,
"outputs": []
},
{
"metadata": {
"ExecuteTime": {
"start_time": "2022-06-01T15:30:29.817254Z",
"end_time": "2022-06-01T15:30:29.857333Z"
},
"trusted": true
},
"cell_type": "code",
"source": "lattice = spaghetti.regular_lattice((0, 0, 10, 10), 9, exterior=True)\nntw = spaghetti.Network(in_data=lattice)",
"execution_count": 3,
"outputs": []
},
{
"metadata": {
"ExecuteTime": {
"start_time": "2022-06-01T15:30:29.859494Z",
"end_time": "2022-06-01T15:30:29.997204Z"
},
"trusted": true
},
"cell_type": "code",
"source": "street = spaghetti.element_as_gdf(ntw, arcs=True)\nstreet_buffered = geopandas.GeoDataFrame(\n geopandas.GeoSeries(street[\"geometry\"].buffer(0.2).unary_union),\n crs=street.crs,\n columns=[\"geometry\"],\n)",
"execution_count": 4,
"outputs": []
},
{
"metadata": {
"ExecuteTime": {
"start_time": "2022-06-01T15:30:30.000423Z",
"end_time": "2022-06-01T15:30:30.008817Z"
},
"trusted": true
},
"cell_type": "code",
"source": "client_points = simulated_geo_points(\n street_buffered, needed=CLIENT_COUNT, seed=CLIENT_SEED\n)\nfacility_points = simulated_geo_points(\n street_buffered, needed=FACILITY_COUNT, seed=FACILITY_SEED\n)",
"execution_count": 5,
"outputs": []
},
{
"metadata": {
"ExecuteTime": {
"start_time": "2022-06-01T15:30:30.010380Z",
"end_time": "2022-06-01T15:30:30.040793Z"
},
"trusted": true
},
"cell_type": "code",
"source": "ntw.snapobservations(client_points, \"clients\", attribute=True)\nclients_snapped = spaghetti.element_as_gdf(\n ntw, pp_name=\"clients\", snapped=True\n)\n\nntw.snapobservations(facility_points, \"facilities\", attribute=True)\nfacilities_snapped = spaghetti.element_as_gdf(\n ntw, pp_name=\"facilities\", snapped=True\n)",
"execution_count": 6,
"outputs": []
},
{
"metadata": {
"ExecuteTime": {
"start_time": "2022-06-01T15:30:30.043588Z",
"end_time": "2022-06-01T15:30:30.441031Z"
},
"trusted": true
},
"cell_type": "code",
"source": "fig, ax = plt.subplots(figsize=(6, 6))\nstreet.plot(ax=ax, alpha=0.8, zorder=1, label=\"streets\")\nfacilities_snapped.plot(\n ax=ax,\n color=\"red\",\n zorder=2,\n label=f\"facility candidate sites ($n$={FACILITY_COUNT})\"\n)\nclients_snapped.plot(\n ax=ax, color=\"black\", label=f\"clients points ($n$={CLIENT_COUNT})\"\n)\nplt.legend(loc=\"upper left\", bbox_to_anchor=(1.05, 1));",
"execution_count": 7,
"outputs": [
{
"output_type": "display_data",
"data": {
"text/plain": "<Figure size 432x432 with 1 Axes>",
"image/png": "iVBORw0KGgoAAAANSUhEUgAABGQAAALKCAYAAAB0sodhAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/YYfK9AAAACXBIWXMAABYlAAAWJQFJUiTwAABhZElEQVR4nO3deXxV9Z0//vdJQgJJCLIEEURB3HEZEtC6gYqt1BatWqvT2mmr1fZnra1L7WKxrWM7OipWbWdqXbtN67jVulRBtFBm3Ai1CloVl3EBZQkIYQkkOb8/kviNrAGSc+Hm+Xw88rjhnu39PjcJua98zuckaZoGAAAAANkpyHUBAAAAAF2NQAYAAAAgYwIZAAAAgIwJZAAAAAAyJpABAAAAyJhABgAAACBjAhkAAACAjAlkAAAAADImkAEAAADImEAGAAAAIGMCGQAAAICMCWQAAAAAMlaU6wI6Q5Ikr0dERUS8keNSAADYNg2JiKVpmg7NdSEAdE15GchEREWPHj367LPPPn1yXQgAANueF198MVauXJnrMgDowvI1kHljn3326VNTU5PrOgAA2AZVV1fHzJkz38h1HQB0XeaQAQAAAMiYQAYAAAAgYwIZAAAAgIwJZAAAAAAyJpABAAAAyJhABgAAACBjAhkAAACAjBXlugAAAGDjampqekTEaRFxTETsFhHdclsRQJe2JiJei4hHI+IP1dXVK7dkJwIZAADYhrWEMdcVFhaOKSws7FNQUNAjIpJc1wXQhaVNTU27NzY2jmxsbDykpqbmG1sSyghkAABg23ZaYWHhmB49euw4YMCAd8vLy1cUFhY25boogK6qsbGxoK6urvTdd98dsHLlyjGNjY2nRcRtm7sfc8gAAMC27ZjCwsI+AwYMeLdXr151whiA3CosLGzq1atX3Y477vheYWFhn2i+nHSzCWQAAGDbtltBQUGP8vLyFbkuBID/p2fPnstbLiMduiXbC2QAAGDb1i0iEiNjALYtBQUFTdE8p1fxFm3fseUAAAAA5L8k2br51QUyAAAAABkTyAAAAABkTCADAAAAkDGBDAAAkDcOOuigvZIkqc51HRvywAMP9EySpPqCCy4YmOtagNwSyAAAAABkTCADAAAAkDGBDAAAsF343e9+1+uQQw7Zs7Ky8oDi4uKq/v37HzBq1Ki9rrjiisqXXnqpOEmS6meeeaY8IiJJkurWj4MOOmiv1n0MGjRo/0GDBu1fW1tb8OUvf3nnQYMG7V9UVFTV9hKiv/3tb91PPvnkIQMGDDiguLi4qm/fvgeOHz9+6N///veS9dW1bNmygu9+97sD9t5773179OgxorS0dMQ//dM/7X3jjTf2abveySefPGT8+PF7RkRce+21O7Wt8YEHHugZEbFq1ark8ssv77/vvvvuU1FR8U89evQYMWjQoP3Hjh077I9//GPPzjivQG4U5boAAACATbn66qv7fetb39q1X79+a4455pj3+/bt27BgwYKiF154ofS3v/1tvy9/+cu1559//rw77rij79y5c4vPP//8ea3bDhkypL7tvtasWZOMHj16ryVLlhSNHj16ac+ePRuHDh1aHxFx1113VXz+858ftmbNmuToo49+f7fddqt/5513uk2aNKn3X/7yl15//vOfXz788MNXtO5r4cKFhaNHj97zxRdfLN13331XfOYzn1nY1NSUTJ06teKrX/3q0NmzZ3e//vrr50ZEfOpTn1oSEXHPPff0HTVqVN3hhx++rHU/e+yxR31ExCmnnDLkgQce6LPHHnusPPnkkxf16NGjad68ed2eeeaZng899FCvT33qU8sCyAsdEsgkSfLpiBgTEf8UEQdGRM+I+F2apqdvZJtDI+L7EfGRiOgeEXMi4taIuCFN08aOqAsAAMgPt912W2W3bt3SZ5999oVBgwY1tF02b968on79+jVOnDhx7vTp03vOnTu3eOLEiXM3tK8FCxZ023333Vf97//+70sVFRVNbZ4vPOOMM3br3r170/Tp01+qrq5e1bpsxowZ80aPHr3P2WefvesLL7zwYuvzX/nKVwa/+OKLpZdccsnbl19++Xutz69YsSI59thjd//Zz36202mnnbb40EMPXfn5z39+Se/evRvvueeevocffviytWtctGhR4YMPPthn+PDhK5599tkXi4o+/Hbt3XffLdyikwdskzpqhMz3ozmIqYuItyNi742tnCTJCRFxd0Ssiog7IqI2IsZHxLURcVhEnNJBdQEAQN775bRX+9054+3KXNexIaeM3HnB2aOHLdza/RQWFqbFxcXp2s/vtNNODetbf2Ouueaat9qGMRERv/jFL/ouW7as8Cc/+cmbbcOYiIiRI0eu+ud//ueFt956a/+ampru1dXVq959993C++67r+/w4cNXtA1jIiJKS0vTf//3f3/70EMP3ffXv/5130MPPfTtTdWUJEmapmkUFxenBQXrzi4xYMAAf7iGPNJRgcz50RzEzInmkTKPb2jFJEkqIuKmiGiMiCPTNJ3R8vyEiHgsIj6dJMlpaZr+oYNqAwAAtnOnnHJK7Y9+9KOdhw8fPnz8+PGLjzzyyGVjx46tGzhw4GaHMSUlJenBBx+8cu3nn3rqqfKIiOeee650fbelfvXVV0siIp5//vnu1dXVq6ZPn17W2NgYSZLE+tZfs2ZNEhHx8ssvd29PXX369Gk66qij3n/88cd77bPPPvuOHz9+8ZgxY+qOPPLI5T179mza9B6A7UmHBDJpmn4QwCRJsqnVPx0RlRHx69YwpmUfq5Ik+X5ETImI/y8iBDIAAEBERPzwhz98r1+/fg033XRT5e23397/1ltv7Z8kSYwaNWrZVVdd9fbo0aNXbHovzfr06bNmfSNQamtrCyMi/vCHP/Tb2PbLli0rjIhYsGBBUUTErFmzSmfNmlW6ofWXL1/e7pup/OlPf3r10ksv3emee+7pc8011wy85pproqSkJB03btziG2644a3BgwdvdgAFbJtyManv0S2PD69n2bSIWBERhyZJUpKmaf161gEAANo4e/SwhR1xSdC27txzz1107rnnLlq4cGHhlClTyu+9994d7rzzzn7HH3/8nrNnz5619twyG7KhPyJXVFQ0RkQ8+eSTL6xvBM3adthhh8aIiDPPPPO9m2++eZOXJLVHeXl5OnHixLkTJ06cO2fOnG6TJ0/u+Zvf/Kbvfffd1+ett94qrqmpeakjjgPkXi4CmdZbzr289oI0TRuSJHk9IoZHxG4R8eLa67SVJEnNBhZtdA6bzvRfT70Zv3/6zVwdPlPDKsvj1QV1uS4jE3rNX12pX73mr67Ur17z1z8ftEt89uBdcl0G24l+/fo1nnrqqe+feuqp7zc1NcWdd97Zb/LkyeVf/OIXlxQWFqYREQ0NDbH2pLibctBBBy1/5JFHej/22GPl7QlkRo8evbygoCCefPLJdt+OuqioKI2IaGzc9HQwu++++5rdd9+99uyzz64dNmzYfjNnzix/9913C80lA/mh3UPnOlCvlsf3N7C89fkdOr+UjvVfT70ZT79eG7XLV+e6lE5Xu3x1vLFwuV7zTFfqNaJr9avX/NWV+tVr/qpdvjqefr02/uuprvFHLbbMXXfdVbFmzZp1nl+4cGG3iIjS0tKmiIjevXs3RETMmTOneHOPcc455yzs2bNn41VXXTXw8ccfX+cSpMbGxnjggQc+CF8GDRrUcPzxxy+aPXt26be+9a2d1lff7NmzS/7xj398UEtlZWVDRMRbb721Tn1z584teuyxx8rWfn7p0qUFy5cvLygsLExLSkrWmdQY2D7lYoTMprSOH9zkD5o0TavXu4PmkTNVHVlUe/z+6TejdvnqqF2+OvqUbfbP/+1K7fLVsby+IeobmvSaR7pSrxFdq1+95q+u1K9e81ft8tXxzBu18eqCOqNk2KAvfelLu5WUlKQjR45ctssuu6xO0zSefPLJnrNmzSodPnz4ihNOOGFZRMRRRx219M9//nPvE088cfdjjjnm/R49ejTtuuuu9V/72tdqN3WMAQMGNP7mN7959XOf+9zuY8eO3ecjH/nI0r333ntVQUFB+vbbbxfPnDmz/P333y+qr6+f2brNLbfc8ubrr7/e/eqrrx5455139h01alRd//7918ybN6/bK6+80mPWrFmlN95442t777336oiIAw88cFX//v3XPPDAA31OO+20dPDgwauTJIkvf/nLixYuXFg4duzYvXfbbbdV++2334qdd9559dKlSwunTJnSa+HChd2++MUvzu/du7fJfSFP5CKQaR0B02sDyyvWWm+70qesOPqUFcf9Xz8816V0qvE3TP/gc73mj67Ua0TX6lev+asr9avX/NW2X9iQCRMmvDN58uSKWbNmlU2dOrVXcXFxOnDgwNWXXHLJ2xdeeOGC1pEj559//sL/+7//K/njH//Y5z//8z93bGxsTEaNGlXXnkAmIuKEE05YVlNTM/vHP/7xgKlTp1bU1NT07NatW1pZWbn60EMPXXbyyScvbrt+nz59mp588smXJk6c2O/OO+/s+/DDD+9QX19f0Ldv3zVDhgyp/9GPfvTW8ccfv7R1/aKiovjv//7vOd/5znd2fvDBB3svX768ME3TGD16dN1HPvKRFRdeeOHc6dOn93ziiSd6LlmypKhXr14NQ4cOrf/BD37wzllnndWuHoDtQy4CmZciYmRE7BkRH5oDJkmSoogYGhENEfFa9qUBAADboosvvnjBxRdfvGBT6xUVFcXPfvazd372s5+9s77l77zzzvOb2sdee+21+te//nW7r6Hr3r17+r3vfW/B9773vU3WFxExZsyYFU888cQ6c2pGRFx99dXzImJee48NbL9yMYfMYy2P49azbHRElEbE/7rDEgAAAJCvchHI3BURCyPitCRJRrY+mSRJ94i4vOWf/5mDugAAAAAy0SGXLCVJ8qmI+FTLPwe0PB6SJMntLZ8vTNP0ooiINE2XJklyVjQHM39JkuQPEVEbEcdH8y2x74qIOzqiLgAAAIBtUUfNIfNPEfGFtZ7breUjIuL/IuKi1gVpmv4xSZIxEXFJRJwcEd0jYk5EXBAR16dp6lZuAAAAQN7qkEAmTdMfRsQPN3Ob/4mI4zri+AAAAADbk1zMIQMAAADQpQlkAAAAADImkAEAAADImEAGAAAAIGMCGQAAAICMCWQAAAAAMiaQAQAAAMiYQAYAAAAgYwIZAAAAgIwJZAAAAAAyJpABAAC2K5dffnn/YcOGDe/evXtVkiTVl112Wf/OPN5LL71UnCRJ9cknnzxkY89t7HnWNWjQoP0HDRq0f9vntvT8rW9f+WB7/Ho68cQTh/Tp0+fApUuXbnd5w1//+tfSJEmqr7322n5ZHG+7O0EAAEDX9ctf/rL3hAkTBpeUlDSdeeaZ751//vnzDjvssOW5rmtjtsc31V3R9vI6bct1Tps2rfS+++7re955571bUVHRlOt6brvttt5f+MIXBldXV+9VXl4+IkmS6hNOOGHohtY/4ogjVhxzzDFLfvKTnwx8//33Oz0vKersAwAAAHSUBx98cIeIiIceemjOkCFD1mRxzCFDhqyZOXPm7D59+jR25Lqsy/n7sO3tfHz3u98dVFZW1njRRRfNz3UtERFXXnnlTi+99FKP0tLSph133HH166+/3n1T23zve9+bd/TRR+/zb//2b/2vuOKKdzuzPoEMAADQbMaM7vHwwxWxdGlhVFQ0xrhxS2PkyFW5Lqut9957r1tE8xvVrI5ZUlKSjhgxol3nYXPWZV3O34dtT+fjueeeK3niiScqTj311IXl5eVpruuJiLjqqqveGjJkyOrhw4fXP/TQQz3Hjx+/56a2Oeqoo1YMHTp01a9//evKyy+//N2ios6LTVyyBAAAXd199/WMUaP2ilGjhseECYPjqqsGxoQJg2PUqOExatRecd99PXNd4gUXXDAwSZLqp556qmdERJIk1a0fretcf/31fY899thhO++88/7du3evKi8vH1FVVbX3f/zHf/TZ0H4ff/zx0k984hO79e/f/4Di4uKqysrKAw477LA9br755t6t62zOJSJrr3vBBRcM3HvvvfePiLjnnnv6tq37+uuv7/u3v/2te5Ik1R/5yEc2+EZxzz333LeoqKjqzTffbNc7w/b0FLH556ttby+99FLxJz/5yd169+59YElJSdV+++23z+9///tea2/T1NQUP/nJTyp333334SUlJVX9+/c/4F/+5V92WbRoUWF7zt/W7Gtz+tvU69S63mOPPVY2bty43fr163dgt27dqgYMGHDAZz/72V3feOONbuurYUN+97vf9TrkkEP2rKysPKC4uLiqf//+B4waNWqvK664onJj56O9dW5ure2tZ2N+8Ytf9EvTNE477bTa9S2/9957K5Ikqf7a17426Jlnnuk+fvz4oX379j2wtLR0xIgRI/Z+7LHHytp7rPYaP378sv3337++oGDzoo8TTzyxdt68ecX33XdfRUfX1JYRMgAA0JVde22/uOiiXaNpA9M9zJhRHiedtGdcc80b8c1vLsq2uP/n6KOPXhYRcccdd/SdO3du8fnnnz9v7XUuvvjiXYcNG7by4IMPXjZgwIA1tbW1RY899livr33ta0Nfeuml7tddd93ctutfc801/b797W/vWlBQkI4dO3bJsGHD6hcsWFD097//veyXv/xl/y9/+cuLO6LuJUuWFN52223999prr5XHHXfcktZlI0eOXDFixIhVBx988LKnnnqq53PPPVdywAEH1LfdfvLkyWWvvPJKj2OPPXbxLrvs0rCp421OT5t7vlq9/fbbxYcccsg+gwcPrj/ppJNqFy9eXPjggw/2Of3003cvLy9/efz48cta1z3zzDMH33777f0rKyvX/PM///OCbt26pY888sgOY8aMKVuzZk3SrVu3do+k2Nx9bU5/m3qdIiKuu+66vhdeeOGQbt26NR1zzDFLBg0atObVV18tueOOO/o9+uijvf7nf/7nH3vsscfqTfVx9dVX9/vWt761a79+/dYcc8wx7/ft27dhwYIFRS+88ELpb3/7237f+c53Fmxo2/bUubm1bk09bU2bNq2isLAwjjrqqPXO6VRTU9MjImLOnDndjzjiiH0PPfTQpaeccsqif/zjH92nTp3a65RTTtl9zpw5z/fu3Tvnc88cccQRdRMnToxHHnmk4uSTT17aWccRyAAAQFd13309NxrGtGpqirjwwiExdOjqOOGEZRtfuXN88pOfXPbJT35y2fTp03vOnTu3eOLEieuEBTU1NbOHDx/+oUBj1apVyVFHHbXHz3/+8wHf/OY3FwwdOnRNy7rdv/3tb+9SVlbWOGXKlH+MXOvSrFdffXWzRjxsrO499tij/rbbbus/fPjwFeur+ytf+cqCp556qufPfvazyl/+8pdvt132i1/8orJlnYWbOtbm9rQ556utp59+uucFF1ww95prrvkgFLv77rtrP/3pT+9x9dVX79gayEyePLns9ttv7z948OD6Z5555sUdd9yxMSJixYoV7xx66KF7LViwoNvAgQM3GWBs6b42p79NvU7PPfdcyUUXXbTrwIED66dOnfpS2/Pypz/9qeeJJ5645znnnDN48uTJr26ql9tuu62yW7du6bPPPvvCoEGDPhSyzZs3b6Pv0dvz9bS5tW5NPa2WLl1a8I9//KN0t912W7mhyXyfffbZsoiIZ555pvzRRx/9x+GHH/5BgHTssccOmzRp0g5PPfVU6bhx4+pan7/sssv6L1mypN25xYgRI1Z8/vOfX9Le9TfkiCOOWBER8cQTT3Tq6ECBDAAAdFWXXz5wk2FMq6amiB//eGCccMJLnVvUllv7zXdERPfu3dOvfvWr85988smeDz74YMW55567KCLi+uuvr2xsbEwuuOCCuWsHFxERw4YNy2yOmtNPP33xt7/97TV33nln3+uuu+6dHj16pBERCxcuLHzooYd6Dx48uP6EE07Y5F/pN7enzTlfbQ0cOHD1lVde+aERSieffPLSnXbaafVzzz33wWUnt9xyS7+IiAsvvHBea4ASEVFaWppefvnl77RnPo+t2deW9rc+1113Xf+Ghobk3//9399aO6Q6/vjjlx199NFLHn/88R0WL15c0J4RHoWFhWlxcfE6o4N22mmnTY6C6oxat7aeN954o1tjY2NUVlZu8Ptm1qxZpRER//Ef//FG2zAmImKvvfZaOWnSpB1Wrlz5oWuLbrzxxh3nzp1b3J4aIiJOOumkRR0RyPTt27expKQknTdvXruPvSUEMgAA0BXNmNE9Zswo36xtnnmmPGbM6L6tTfTb6pVXXim+7LLLBkyfPr3nu+++W7xq1aoPvbl75513PhghUlNTUx4Rcfzxx3fa5Qjt1a1bt/jc5z638Kc//elOv/rVr3p/9atfrY2IuPHGG/uuWrWq4F/+5V8WtGcOjM3taXPOV1v77LPPivVNdLrTTjutfvbZZz/4mnr++edLIyI++tGPrjOqaty4ccsKCwvbfbnSluxrS/tbnxkzZpRFRPzlL3/p+fTTT68z18miRYu6NTY2xqxZs7q3jq7YkFNOOaX2Rz/60c7Dhw8fPn78+MVHHnnksrFjx9YNHDhwq8OYLam1I+qZP39+UUTEDjvssN67Qb3//vsFb731VslOO+20+jOf+cz7ay9//fXXSyIi9tprrw/9bHnnnXeeb28NHa2ioqKhtra2Q0bKbYhABgAAuqKHH96yySoffrhiWwxkXnjhheLDDjtsn6VLlxZVV1fXjRkzZmmvXr0aCwsL4//+7/+K77nnnr719fUfvCFftmxZYUTEkCFD2nXJTGc777zzFtxwww0DbrnllsrWQOZXv/pVv27duqXnnHNOu0ZxbE5Pm3u+2urVq9d633QXFhZGU5sRV6317Lzzzuu8sS8qKtrgm/f12dx9bU1/69N62cyNN96448bWW7p06Sb3+cMf/vC9fv36Ndx0002Vt99+e/9bb721f5IkMWrUqGVXXXXV26NHj95ooNPRtXZEPaWlpU0RzZeErW/5k08+WdrU1BSjR49eur5wcdasWaXl5eWNe++99zbx/RgRUV9fX1BSUtKp89kIZAAAoCtaunS9d6bptO062RVXXDFgyZIlRdddd90b55133ocCjBtvvLHPPffc86E70PTs2bMxIuKNN94o7t27d84DpqFDh645+uij3588efIOM2fO7L5o0aLCV155pccnPvGJxe0dqbA5PW3u+doSrfW8/fbbRfvuu++H3mg3NDTEkiVLCnfcccd2veHd3H11dH+tx1+0aNHf+vTps9Vv0s8999xF55577qKFCxcWTpkypfzee+/d4c477+x3/PHH7zl79uxZa8/l0tm1bm09rV+jG5rv5ZlnnimNiKiqqlon3Fm8eHHBm2++2X3kyJHL1g5rcjWHTGNjYyxbtqxw0KBB61z21pEEMgAA0BVVVLR7dEKHbNfJWi95+PznP7/OnZGmTp26zqVZ1dXVdbNnzy7905/+VDFixIhODWRaL6dpbGxc7+iBVuecc878yZMn7/Dzn/+8csmSJYURzRP+tvc4m9PT5p6vLbH//vuveOGFF0onT57cc9999/1QKPLwww/33NT52Jp9bUl/G3udqqqqls+ePbt00qRJPU877bR1LrnZUv369Ws89dRT3z/11FPfb2pqijvvvLPf5MmTy7/4xS8u2dA2m/p62ppat6SeiIhddtllTe/evRtee+217utb/uyzz5ZGRHzkIx9Z5w5MraNnDjzwwHXCmlzNIfP3v/+9e5qmse+++67c2n1tzObdjBu6mNmzZ8frU++KVx75Vbw+9a6YPXt2rksCAOgY48Zt2dwpW7pdJxs8eHB9RMSf//znD90V5e6776747//+78q11z/vvPMWFBYWphMnThxYU1OzzpvIjrrLUkREZWVlY5Ik8c4772z0jeXxxx+/bNddd62/6667+j700EO9d9111/q2t5DelM3paXPP15Y444wzFkZEXHPNNTu99957H4ysWrFiRfL9739/UGfua0v629jrdP75588vKipKv/Od7wx+7rnnStZevmrVquThhx9uV5B11113VaxZs+7ctwsXLuwW8f8u/9mQTX09bW6tW1tPRERBQUEcdNBBy5YsWVI0a9asdY75/PPPl3br1i096KCD1gk4nn766Q2OnnnnnXeeT9O0pr0fd9999xubqrU9/vrXv5ZFRIwZM6ZTf94ZIQPrMWXKlLjsssti2rRpH3p+v7uvi9GjR8ell14aY8eOzVF1AAAdYOTIVTFyZN1mTew7alTdtjh/TETEN77xjQV33XVXvy996UvD/vCHPyweOHDgmhdffLH7X//6117HHXfc4gcffLB32/Wrq6tXXXnllW9efPHFux5yyCH7HnPMMUuGDRtWv2jRosLnnnuurKysrPGpp556uSNq69WrV9MBBxywvKampvz4448fuscee6wqLCyMk08+ecnBBx/8wRvUgoKC+NKXvjT/hz/84eCIiC9+8YvtHh2zuT1t7vnaEh/72MeWf+ELX5j/q1/9qv/+++8//LjjjlvcrVu39JFHHtmhoqKicWN35NnafW1Jf5t6na677ro3vvGNbwypqqoaPnr06KXDhg1btWbNmuTtt98unjFjRs/evXuvef311zf5F9wvfelLu5WUlKQjR45ctssuu6xO0zSefPLJnrNmzSodPnz4ihM2cWv5TdU5YsSIVZtT69bW0+rEE09c8sgjj/S+//77K/bbb78PvnZXrlyZvPbaa9333HPPld27d19n8uWZM2eWRUQccsgh64ye2Vq/+c1vdvjjH/+4Q0TE/Pnzu7Ue7+STTx4SEdG3b9+GtW81HxHx6KOPVhQWFsZnPvOZJR1dU1sCGVjLLbfcEmefffaHJiRra9q0afGxj30sbrrppjjjjDMyrg4AoAN9//tz46ST9mzXra8LCiIuuWRu5xe1ZQ4++OCVDz744EsTJkwY9Je//KVXY2Njsvfee6/41a9+9Wrv3r0b1/cG/MILL1x44IEHrrzqqqsGPPnkkz0nT568Q+/evRv22muvla0jMjrKb3/729fPO++8wdOmTev1wAMP9EnTNHbeeefVbQOZiIhzzjln0WWXXTa4qKgo/epXv7rZNbS3py05X1vi1ltvfWvPPfdcdfPNN/f/r//6r8oddtih4dhjj13y05/+9J0DDjhg387a15b2t7HX6ZxzzqkdOXLkyiuvvHLHJ554ouf06dMrevTo0dS/f/81xx133OLTTjuttj19TJgw4Z3JkydXzJo1q2zq1Km9iouL04EDB66+5JJL3r7wwgsXlJSUbPLuU5v6etqcWjuinoiIL3zhC4svueSSwb///e/7fve73/0gkJkxY0aPhoaGZH2XJEU0j54pLS1t2m+//Tp8vpa//e1vpWvPF/T222+XvP322yURzbdwj4gPBTKLFi0qnDx5cu8jjzxyye67797u0HBLJGna7juNbTeSJKmpqqqqqqmpyfS442+Y/sHn93/98EyPnbV87XXKlCnxsY99bINhTFsFBQUxadKkvBopk6+v64Z0pX71mr+6Ur96zV+56Le6ujpmzpw5M03T6kwOuBVqampmdO/efZ/hw4e/2CkHuPbafnHRRbtuNJQpKIi45po34pvfbNfdfthyDzzwQM/x48fvecIJJ9T+8Y9/fD3X9cDm+O53vzvgiiuuGDR9+vQXDjvssE6df6Wz/PjHP+7//e9/f/Cf//znl8aNG1e3qfVnz569z6pVq16srq4eubnHMocMtHHZZZe1K4yJiGhqaop//dd/7eSKAAA62fnnL4x77nk5Ro1a/xuPUaPq4p57XhbGZOOqq67aMSLivPPOm5/rWmBzTZgw4b2ddtpp9YQJEzZrjqBtRV1dXXLdddcNOPbYYxe3J4zZWi5ZghazZ89eZ86YTZk6dWrMnj07hg8f3klVAQBk4IQTlsUJJ7wUM2Z0j4cfroilSwujoqIxxo1buq3OGZNPnn766R733ntvr7/97W+l06ZN63XUUUe9f/TRR3f4fBrQ2UpLS9Nbbrnl9UcffbTn0qVLCyoqKrb6FuFZevnll0tOP/30hV/5ylc69JLFDRHIQIspU6Zs8XYCGQAgLzRP9CuAydiTTz5ZesUVVwwqLy9v/PjHP774lltueTPXNcGW+vjHP1738Y9/vNNHl3SGqqqqVVVVVZnNlSWQgRZLl27ZHc22dDsAAIiIOO+88xadd955LgmDLsYcMtCioqIi0+0AAADougQy0GJL75aUT3dZAgAAIBsCGWgxfPjwGD169GZtM2bMGPPHAAAAsNkEMtDGpZdeGgUF7fu2KCgoiAkTJnRyRQAAAOQjgQy0MXbs2PjlL3+5yVCmoKAgbrrpJpcrAQAAsEUEMrCWM888MyZNmhRjxoxZ7/IxY8bEpEmT4owzzsi4MgAAAPKF217DeowdOzbGjh0bs2fPjlN/cFM0rFoeRd3L4o4fnWXOGAAAALaaQAY2Yvjw4TF0zKc/9G8AAADYWi5ZAgAAAMiYQAYAAAAgYwIZAAAAgIwJZAAAAAAyJpABAAAAyJhABgAAyCsvvfRScZIk1SeffPKQ9jxP+2yv5+/EE08c0qdPnwOXLl263b3//etf/1qaJEn1tdde2y/XtdDxtrsvSAAAgO3N9hpmdIYsz8W0adNK77vvvr7nnXfeuxUVFU2dfbyNeffddwsnTpzY76Mf/eiwXXbZZb/u3btX9ezZ85+qq6v3uvbaa/s1Njaus80RRxyx4phjjlnyk5/8ZOD777/v/XueKcp1AQAAAFkYMmTImpkzZ87u06fPuu982aTt8fx997vfHVRWVtZ40UUXzc91Lb/+9a/7fPvb396lsrJyzUc+8pFlgwcPXjx//vxuDz/88A4XXHDBro888kjFQw899FpBwYdzl+9973vzjj766H3+7d/+rf8VV1zxbo7KpxMIZAAAgIiImDFjRveHH364YunSpYUVFRWN48aNWzpy5MhVua6ro5SUlKQjRozIm36ytr2dv+eee67kiSeeqDj11FMXlpeXp7muZ++99171u9/9bs6pp576fmFh4QfPv/nmm0UHH3zwPo888kjvX//61zt88YtfXNJ2u6OOOmrF0KFDV/3617+uvPzyy98tKvI2Pl8Y8gQAAF3cfffd13PUqFF7jRo1aviECRMGX3XVVQMnTJgweNSoUcNHjRq113333dcz1zW29fjjj5d+4hOf2K1///4HFBcXV1VWVh5w2GGH7XHzzTf33th2m7pU5rHHHisbN27cbv369TuwW7duVQMGDDjgs5/97K5vvPFGtw3t56WXXir+5Cc/uVvv3r0PLCkpqdpvv/32+f3vf9+r7foXXHDBwL333nv/iIh77rmnb5Ik1a0f119/fd+IiN/97ne9DjnkkD0rKysPKC4ururfv/8Bo0aN2uuKK66obM85aVvT3/72t+7HHHPMsF69ev1Tjx49RlRXV+91zz33VGxo25tvvrn3yJEj9+rZs+c/de/evWrPPffc97vf/e6AlStXJu05f5tzPtpzLjrifERE/OIXv+iXpmmcdtpptetbfu+991YkSVL9ta99bdAzzzzTffz48UP79u17YGlp6YgRI0bs/dhjj5W191jtcfzxxy/77Gc/+6EwJiJil112afjCF76wICLi8ccfX+/32oknnlg7b9684vvuu2+DryPbH4EMAAB0Yddee22/k046ac8ZM2aUr2/5jBkzyk866aQ9f/rTn/Zd3/KsXXPNNf0++tGP7jN58uQdqqur684+++z3jj766PcXLVrU7Ze//GX/Ld3vdddd1/djH/vY3lOnTu11yCGHLD3zzDPn77///svvuOOOfgcddNA+r7zySvHa27z99tvFhxxyyD5vvfVW8UknnVT7iU98ovaVV17pcfrpp+9+//33f/DG+uijj172pS99aX5ExF577bXy/PPPn9f6MXLkyBVXX311v9NPP333OXPmdD/mmGPeP/vss9876qij3l+1alXBb3/7282azPXNN98sGTNmzN6LFy8uOv300xccd9xxi2fPnl12yimn7HHTTTetE1ide+65g84666zdXn311e7HH3987Re+8IX5aZomV1xxxaAxY8bsWV9fn6zvOOvTnvOxqXMREdFR52PatGkVhYWFcdRRRy1f3/KampoeERFz5szpfsQRR+y7fPnywlNOOWXRQQcdtOzZZ58tO+WUU3ZfvHhxJu+Zu3XrlkZEbGj0yxFHHFEXEfHII48IZPKIsU4drHb56qhdvjrG3zA916V0qjnz66KkqCDqG5r0mke6Uq8RXatfveavrtSvXvPXnPl10aesOPqUrfN+l05233339bzooot2bWra+FynTU1NceGFFw4ZOnTo6hNOOGFZRuWto6ampvu3v/3tXcrKyhqnTJnyj7Uvp3r11Ve7bWjbjXnuuedKLrrool0HDhxYP3Xq1JeGDh26pnXZn/70p54nnnjinuecc87gyZMnv9p2u6effrrnBRdcMPeaa66Z1/rc3XffXfvpT396j6uvvnrH8ePHL4uI+OQnP7lsjz32qL/tttv6Dx8+fMXEiRPntt3PWWedNaRbt27ps88++8KgQYMa2i6bN2/eZr1nmzFjRvnZZ5/93o033vh263PTpk2bf/TRR+994YUX7nryySe/36dPn6aIiEcffbTs5z//+YABAwasfuqpp17cZZddGiIi1qxZ8/axxx67++OPP97rBz/4wY7tnbekPedjU+ciIuK2226r3NrzsXTp0oJ//OMfpbvtttvKDU3m++yzz5ZFRDzzzDPljz766D8OP/zwFa3Ljj322GGTJk3a4amnniodN25cXUTEZZdd1n/JkiXtfj1GjBix4vOf//ySTa23Zs2auOOOO/pGRBx33HHvr2+dI444YkVExBNPPLFNjVZj6whkOtCwyvIoTJbH8vqGTa+8nSspKojykqKI0Gs+6Uq9RnStfvWav7pSv3rNXyVFBVFZXhJD+nXo1QG0w+WXXz5wU2FMq6ampvjxj3888IQTTnipk8vaoOuvv76ysbExueCCC+aub26bYcOGrVnfdpty3XXX9W9oaEj+/d///a22YUxE82UmRx999JLHH398h8WLFxf07t37gxM2cODA1VdeeeW8tuuffPLJS3faaafVzz333GZ9QRcWFqbFxcXrzHOy0047bdYPgvLy8sYrrrjiQyHH6NGjV5xwwgm199xzT9/f/e53vb/+9a8vioi4+eab+0VEXHjhhfNaw5iIiG7dusVPf/rTt0aMGNHrt7/9bWV7A5lt6Xy88cYb3RobG6OysnKDXxOzZs0qjYj4j//4jzfahjERzaN3Jk2atMPKlSs/GCFz44037jh37tx2J8cnnXTSovYEMl/72td2fuWVV3qMGTPm/ZNPPnnp+tbp27dvY0lJSTpv3jzJdR4RyHSgVxfURe3y1VHfkNO7qWWiuccGveaZrtRrRNfqV6/5qyv1q9f8Vd/QFAvq6qMxzfmcm13KjBkzum/oMqUNeeaZZ8pnzJjRPVcT/dbU1JRHRBx//PHrfdO6pWbMmFEWEfGXv/yl59NPP71OcLBo0aJujY2NMWvWrO6tIxUiIvbZZ58V67vEZKeddlr97LPPtvvcnnLKKbU/+tGPdh4+fPjw8ePHLz7yyCOXjR07tm7gwIGbncoOHz58RdvQqNWYMWOW3XPPPX3/9re/lUbEooiI559/vjQiYty4ceuMejrggAPqd9xxx9XvvPNO8cKFCwv79eu3yTsrbUvnY/78+UURETvssMN6637//fcL3nrrrZKddtpp9Wc+85l1RqW8/vrrJRERe+211wdf6++8887z7T1+e11++eX9b7rpph2HDh266o477nh9Y+tWVFQ01NbWbtEoMLZNApkO1jrc9v6vH57rUjpV2+HT+dzr7Nmz49Qf3BWrVi2Pou5lccVpZ8Xw4cNzXVan6Sqva6uu1K9e81dX6lev+asrXJa1LXr44Ye3aC6Khx9+uCJXgcyyZcsKIyKGDBmyuiP323oZyo033rjjxtZbunTph+YT6dWr13rf7BcWFkZ7Rx5FRPzwhz98r1+/fg033XRT5e23397/1ltv7Z8kSYwaNWrZVVdd9fbo0aNXbHovzTY0ImTgwIFrWnr4YEbZ1vO5yy67rHebysrKNfPmzSuura1tVyCzLZ2P0tLSpoiIVatWrXcOnCeffLK0qakpRo8evXTt20xHNI+eKS8vb9x777079GutrX/7t3+rnDBhwuBhw4ateuyxx17acccdN3qO6+vrC0pKSrpGUt9FCGRgPaZMmRKXXXZZTJs27UPP73f3dTF69Oi49NJLY+zYsTmqDgBg67V9Y57Fdh2hZ8+ejRERb7zxRnHv3r07LBRq3e+iRYv+1jq/StbOPffcReeee+6ihQsXFk6ZMqX83nvv3eHOO+/sd/zxx+85e/bsWWvPpbIhCxYsWO8Iirlz53aLiKioqPjgTX9r32+99Va34cOH129oX3369NlkGNPRtvZ8tI6m2dCcL88880xpRERVVdU64c7ixYsL3nzzze4jR45c1jas6cg5ZC677LL+P/jBDwbvscceKx9//PGXN9VPY2NjLFu2rHDQoEHrvE5svwQysJZbbrklzj777A2m+NOmTYuPfexjcdNNN8UZZ5yRcXUAAB2j7RvzLLbrCNXV1XWzZ88u/dOf/lQxYsSIDgtkqqqqls+ePbt00qRJPU877bT1Tqq6tQoLC9OIiMbGxo3etahfv36Np5566vunnnrq+01NTXHnnXf2mzx5cvkXv/jFJe05zuzZs0vXnusmImLq1Kk9I5pDgtbn9ttvvxUvvPBC6aRJk3quHcjMmjWr5L333iseNGjQ6vaMjtkc7T0XEVt+PnbZZZc1vXv3bnjttde6r2/5s88+WxoR8ZGPfGSdOzC1jp458MADPxTWdNQcMpdccsmAn/zkJ4P23nvvlY899tjL7ZkX5+9//3v3NE1j3333Xdne47Ptc9traGPKlCkbDWNaNTU1xVlnnRVTpkzJqDIAgI41bty4LZqHZUu36wjnnXfegsLCwnTixIkDa2pq1nmjvaV3WTr//PPnFxUVpd/5zncGP/fccyVrL1+1alXy8MMPb9Z8O2urrKxsTJIk3nnnnXXe0N91110Va9ase9XQwoULu0X8v8tv2qOurq7wO9/5zsC2z02bNq30vvvu61NeXt74uc99bnHr81/+8pcXRkRcffXVO82dO/eDP9Y3NDTEN7/5zZ2bmpric5/73IL2Hru9NnYuIjrmfBQUFMRBBx20bMmSJUWzZs1a5zV9/vnnS7t165YedNBB6wQcTz/99HpHz7zzzjvPp2la096Pu++++4219/2tb31rp5/85CeDhg8fvuIvf/nLS+2dpPivf/1rWUTEmDFjcvb9R8czQgbauOyyy9p9fWtTU1P867/+q0uXAIDt0siRI1eNHDmybnMm9h01alRdruaPiYiorq5edeWVV7558cUX73rIIYfse8wxxywZNmxY/aJFiwqfe+65srKyssannnrq5c3d74gRI1Zdd911b3zjG98YUlVVNXz06NFLhw0btmrNmjXJ22+/XTxjxoyevXv3XvP666/P3tLae/Xq1XTAAQcsr6mpKT/++OOH7rHHHqsKCwvj5JNPXvKlL31pt5KSknTkyJHLdtlll9VpmsaTTz7Zc9asWaXDhw9fsTm3Gh85cmTd73//+341NTVlBx98cN27777b7cEHH+yTpmkyceLE/2t7SdZHP/rR5V/96lff/cUvfjFg//33H37cccctLisra3rssccqXnnllR5VVVV1P/rRj97b0p635FwcfPDBKzvqfJx44olLHnnkkd73339/xX777fdBsLRy5crktdde677nnnuu7N69+zqzic+cObMsIuKQQw5ZZ/TM1rjhhhv6Xn311QMLCwvj4IMPrrvyyivXmbNoyJAh9eedd96itZ9/9NFHKwoLC+Mzn/nMko6sidwSyECL2bNnrzNnzKZMnTo1Zs+endcT/QIA+ev73//+3JNOOmnP9vxBqqCgIC655JK5m1yxk1144YULDzzwwJVXXXXVgCeffLLn5MmTd+jdu3fDXnvttfKMM85YuKX7Peecc2pHjhy58sorr9zxiSee6Dl9+vSKHj16NPXv33/Ncccdt/i0006r3draf/vb375+3nnnDZ42bVqvBx54oE+aprHzzjuvnjBhwjuTJ0+umDVrVtnUqVN7FRcXpwMHDlx9ySWXvH3hhRcuKCkpafctyHbZZZf6G2+88f++9a1vDfrNb35TuWbNmmTfffddcckll8xd3y2V//M///OdESNGrLjxxhv733PPPX0bGhqSwYMH11988cXv/OAHP3hvfYFFR9jQuTj44INXdtT5+MIXvrD4kksuGfz73/++73e/+90PApkZM2b0aGhoSNa+JKnV888/X1paWtq03377deh8La13bmpsbIxbb721//rWGTVqVN3agcyiRYsKJ0+e3PvII49csvvuu2/Rrd3ZNglkoMWWXn40ZcoUgQwAsF064YQTll199dX/d9FFF+26sVCmoKAgrrnmmjc2Z6RGZzrmmGOWH3PMMa9uaPlee+21Ok3TmvY+3+qggw5aub7LTDZ3P08//fRL63t+v/32q3/sscfmrG/ZxRdf3GGXBlVVVa2aMmXKBs/P2s4+++zFZ5999uJNrbel53V952NT56Ijzkf37t3Ts846670rrrhi0P/8z//0OOyww1ZGRBxxxBErNlbva6+9tsUjoTZm4sSJcydOnLjZoeYvfvGLvvX19clFF13U4aOVyC1zyECLpUu37HLMLd0OAGBbcP755y+85557Xh41alTd+paPGjWq7p577nn5m9/85jqXUcC2bsKECe/ttNNOqydMmDAo17Vsibq6uuS6664bcOyxxy4eN27cer9H2X4ZIQMtKioqMt0OAGBbccIJJyw74YQTXpoxY0b3hx9+uGLp0qWFFRUVjePGjVuayzljYGuVlpamt9xyy+uPPvpoz6VLlxZUVFTk5LbmW+rll18uOf300xd+5Stf2eLL8dh2CWSgxZZOzmtSXwAgX7RM9CuAIa98/OMfr/v4xz++XY4uqaqqWlVVVZXzuZvoHAIZaDF8+PAYPXr0Zk3sO2bMGPPH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\n"
},
"metadata": {
"image/png": {
"width": 562,
"height": 357
},
"needs_background": "light"
}
}
]
},
{
"metadata": {
"ExecuteTime": {
"start_time": "2022-06-01T15:30:30.443186Z",
"end_time": "2022-06-01T15:30:30.495864Z"
},
"trusted": true
},
"cell_type": "code",
"source": "cost_matrix = ntw.allneighbordistances(\n sourcepattern=ntw.pointpatterns[\"clients\"],\n destpattern=ntw.pointpatterns[\"facilities\"],\n)",
"execution_count": 8,
"outputs": []
},
{
"metadata": {
"ExecuteTime": {
"start_time": "2022-06-01T15:30:30.498155Z",
"end_time": "2022-06-01T15:30:30.502024Z"
},
"trusted": true
},
"cell_type": "code",
"source": "cost_matrix",
"execution_count": 9,
"outputs": [
{
"output_type": "execute_result",
"execution_count": 9,
"data": {
"text/plain": "array([[12.60302601],\n [13.10096347]])"
},
"metadata": {}
}
]
},
{
"metadata": {
"ExecuteTime": {
"start_time": "2022-06-01T15:30:30.503760Z",
"end_time": "2022-06-01T15:30:30.507608Z"
},
"trusted": true
},
"cell_type": "code",
"source": "cost_matrix <= SERVICE_THRESHOLD",
"execution_count": 10,
"outputs": [
{
"output_type": "execute_result",
"execution_count": 10,
"data": {
"text/plain": "array([[False],\n [False]])"
},
"metadata": {}
}
]
},
{
"metadata": {
"ExecuteTime": {
"start_time": "2022-06-01T15:30:30.509274Z",
"end_time": "2022-06-01T15:30:30.529692Z"
},
"trusted": true
},
"cell_type": "code",
"source": "lscp_from_cost_matrix = LSCP.from_cost_matrix(cost_matrix, SERVICE_THRESHOLD)\nlscp_from_cost_matrix = lscp_from_cost_matrix.solve(solver)",
"execution_count": 11,
"outputs": [
{
"output_type": "stream",
"text": "Welcome to the CBC MILP Solver \nVersion: 2.10.3 \nBuild Date: Dec 15 2019 \n\ncommand line - /Users/the-gaboardi/miniconda3/envs/py310_spopt/lib/python3.10/site-packages/pulp/apis/../solverdir/cbc/osx/64/cbc /var/folders/71/bk36jbtj26n_v5fhw9tnzzl00000gn/T/d0c7c3ea2fd54522a81327a021929fa5-pulp.mps mips /var/folders/71/bk36jbtj26n_v5fhw9tnzzl00000gn/T/d0c7c3ea2fd54522a81327a021929fa5-pulp.mst timeMode elapsed branch printingOptions all solution /var/folders/71/bk36jbtj26n_v5fhw9tnzzl00000gn/T/d0c7c3ea2fd54522a81327a021929fa5-pulp.sol (default strategy 1)\nAt line 2 NAME MODEL\nAt line 3 ROWS\nAt line 7 COLUMNS\nAt line 11 RHS\nAt line 14 BOUNDS\nAt line 16 ENDATA\nProblem MODEL has 2 rows, 1 columns and 0 elements\nCoin0008I MODEL read with 0 errors\nopening mipstart file /var/folders/71/bk36jbtj26n_v5fhw9tnzzl00000gn/T/d0c7c3ea2fd54522a81327a021929fa5-pulp.mst.\nMIPStart values read for 1 variables.\nOption for timeMode changed from cpu to elapsed\nProblem is infeasible - 0.00 seconds\nOption for printingOptions changed from normal to all\nTotal time (CPU seconds): 0.00 (Wallclock seconds): 0.00\n\n",
"name": "stdout"
}
]
},
{
"metadata": {
"ExecuteTime": {
"start_time": "2022-06-01T15:30:30.535194Z",
"end_time": "2022-06-01T15:30:30.539468Z"
},
"trusted": true
},
"cell_type": "code",
"source": "lscp_from_cost_matrix.problem.status",
"execution_count": 12,
"outputs": [
{
"output_type": "execute_result",
"execution_count": 12,
"data": {
"text/plain": "-1"
},
"metadata": {}
}
]
},
{
"metadata": {
"ExecuteTime": {
"start_time": "2022-06-01T15:30:30.541397Z",
"end_time": "2022-06-01T15:30:30.545676Z"
},
"trusted": true
},
"cell_type": "code",
"source": "STATUS_CODES = {\n 1: \"Optimal\", \n 0: \"Not Solved\", \n -1: \"Infeasible\", \n -2: \"Unbounded\", \n -3: \"Undefined\", \n}\nSTATUS_CODES",
"execution_count": 13,
"outputs": [
{
"output_type": "execute_result",
"execution_count": 13,
"data": {
"text/plain": "{1: 'Optimal',\n 0: 'Not Solved',\n -1: 'Infeasible',\n -2: 'Unbounded',\n -3: 'Undefined'}"
},
"metadata": {}
}
]
},
{
"metadata": {
"ExecuteTime": {
"start_time": "2022-06-01T15:30:30.547363Z",
"end_time": "2022-06-01T15:30:30.550493Z"
},
"trusted": true
},
"cell_type": "code",
"source": "def check_status(code):\n if code != 1:\n status = STATUS_CODES[code]\n msg = (\n f\"Model is not solved: {status}. \"\n \"See ``pulp.constants.LpStatus`` for more information.\"\n )\n raise RuntimeError(msg)",
"execution_count": 14,
"outputs": []
},
{
"metadata": {
"ExecuteTime": {
"start_time": "2022-06-01T15:30:30.552245Z",
"end_time": "2022-06-01T15:30:30.920676Z"
},
"trusted": true
},
"cell_type": "code",
"source": "check_status(lscp_from_cost_matrix.problem.status)",
"execution_count": 15,
"outputs": [
{
"output_type": "error",
"ename": "RuntimeError",
"evalue": "Model is not solved: Infeasible. See ``pulp.constants.LpStatus`` for more information.",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mRuntimeError\u001b[0m Traceback (most recent call last)",
"Input \u001b[0;32mIn [15]\u001b[0m, in \u001b[0;36m<cell line: 1>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mcheck_status\u001b[49m\u001b[43m(\u001b[49m\u001b[43mlscp_from_cost_matrix\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mproblem\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mstatus\u001b[49m\u001b[43m)\u001b[49m\n",
"Input \u001b[0;32mIn [14]\u001b[0m, in \u001b[0;36mcheck_status\u001b[0;34m(code)\u001b[0m\n\u001b[1;32m 3\u001b[0m status \u001b[38;5;241m=\u001b[39m STATUS_CODES[code]\n\u001b[1;32m 4\u001b[0m msg \u001b[38;5;241m=\u001b[39m (\n\u001b[1;32m 5\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mModel is not solved: \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mstatus\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m. \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 6\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mSee ``pulp.constants.LpStatus`` for more information.\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 7\u001b[0m )\n\u001b[0;32m----> 8\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mRuntimeError\u001b[39;00m(msg)\n",
"\u001b[0;31mRuntimeError\u001b[0m: Model is not solved: Infeasible. See ``pulp.constants.LpStatus`` for more information."
]
}
]
}
],
"metadata": {
"_draft": {
"nbviewer_url": "https://gist.github.com/121d060cd01f794e7f0a66ab40c5d381"
},
"gist": {
"id": "121d060cd01f794e7f0a66ab40c5d381",
"data": {
"description": "check_feasibility",
"public": true
}
},
"interpreter": {
"hash": "9f3289f6e4e90b4baed353b79a064837546fd68cb0fc59ed00ca81208aac8b4f"
},
"kernelspec": {
"name": "conda-env-py310_spopt-py",
"display_name": "Python [conda env:py310_spopt]",
"language": "python"
},
"language_info": {
"name": "python",
"version": "3.10.4",
"mimetype": "text/x-python",
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"pygments_lexer": "ipython3",
"nbconvert_exporter": "python",
"file_extension": ".py"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment