{ "cells": [ { "cell_type": "markdown", "id": "0e2b76a4-f1d7-4dd5-88c1-0d622df5bd49", "metadata": {}, "source": [ "# 3.6.2 Cazzaro and Pisinger 2022 Fig. 6" ] }, { "cell_type": "markdown", "id": "7da558c5-033b-4fa8-9841-4b7f7b75d138", "metadata": {}, "source": [ "This is used in the paper **Flexible cable routing framework for wind farm collection system optimization**." ] }, { "cell_type": "code", "execution_count": 1, "id": "2278cd98-3fcb-428b-842b-802f13af7c2e", "metadata": {}, "outputs": [], "source": [ "import pickle\n", "from importlib.resources import files\n", "from matplotlib import pyplot as plt" ] }, { "cell_type": "code", "execution_count": 2, "id": "c69dd56e-dc8e-43cd-bcc5-b284c2a18300", "metadata": {}, "outputs": [], "source": [ "from optiwindnet.interarraylib import G_from_S\n", "from optiwindnet.svg import svgplot, svgpplot\n", "from optiwindnet.mesh import make_planar_embedding\n", "from optiwindnet.baselines.hgs import hgs_cvrp\n", "from optiwindnet.importer import L_from_yaml\n", "from optiwindnet.pathfinding import PathFinder\n", "from optiwindnet.MILP import solver_factory, ModelOptions" ] }, { "cell_type": "code", "execution_count": 3, "id": "70241594-b980-4588-8e68-2981e1a4850a", "metadata": {}, "outputs": [], "source": [ "%config InlineBackend.figure_formats = ['svg']\n", "plt.rcParams['svg.fonttype'] = 'none'" ] }, { "cell_type": "markdown", "id": "fcf076a3-3b88-4805-8c4b-b542ce88a555", "metadata": {}, "source": [ "## Reference solution" ] }, { "cell_type": "markdown", "id": "1a7e6518-c670-45ca-a610-9b263c442bea", "metadata": {}, "source": [ "Cazzaro, D., & Pisinger, D. (2022). Balanced cable routing for offshore wind farms with obstacles. Networks, 80(4), 386–406. https://doi.org/10.1002/net.22100" ] }, { "cell_type": "code", "execution_count": 4, "id": "e978d022-7efc-4a65-9d28-61879eee3134", "metadata": {}, "outputs": [], "source": [ "G_ref = pickle.load(open('data/cazzaro_2022_paper_routeset.pkl', 'rb'))" ] }, { "cell_type": "code", "execution_count": 5, "id": "4c5be888-9dae-4a34-9eda-8b3fe90aed23", "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "Σλ = 9.9398 m(+0) [-1]: 9κ = 6, T = 50" ], "text/plain": [ "" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "svgplot(G_ref)" ] }, { "cell_type": "markdown", "id": "2386ab9b-0570-4206-8262-af30725d06a7", "metadata": {}, "source": [ "## Start here" ] }, { "cell_type": "code", "execution_count": 6, "id": "7fbfa19d-98e9-4183-9959-f71919aff71a", "metadata": {}, "outputs": [], "source": [ "solver = solver_factory('gurobi')" ] }, { "cell_type": "code", "execution_count": 7, "id": "c282d7c0-7f50-423f-9e4e-a69d13518d04", "metadata": {}, "outputs": [], "source": [ "L = L_from_yaml(files('optiwindnet.data') / 'Cazzaro-2022.yaml')" ] }, { "cell_type": "code", "execution_count": 8, "id": "bc633875-a777-42a1-8130-d6931eef88d1", "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "" ], "text/plain": [ "" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "svgplot(L)" ] }, { "cell_type": "code", "execution_count": 9, "id": "91bf5be2-adb5-4bd9-9b5e-a06eb2b26157", "metadata": {}, "outputs": [], "source": [ "P, A = make_planar_embedding(L)" ] }, { "cell_type": "code", "execution_count": 10, "id": "ea6f4cc9-873a-456d-9fbf-67eaf9c1f896", "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "" ], "text/plain": [ "" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "svgplot(A)" ] }, { "cell_type": "code", "execution_count": 11, "id": "b792422a-2397-410e-8d77-a68a8d57a36e", "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "" ], "text/plain": [ "" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "svgpplot(P, A)" ] }, { "cell_type": "markdown", "id": "f2850052-f689-41ee-9e0f-f48501d142b2", "metadata": {}, "source": [ "## Pre-solve" ] }, { "cell_type": "code", "execution_count": 12, "id": "5a063194-a673-4788-9a2a-9a6fa1f70471", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.47" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Sʹ = hgs_cvrp(A, capacity=6, time_limit=0.5, balanced=True)\n", "Sʹ.graph['solution_time']" ] }, { "cell_type": "code", "execution_count": 13, "id": "2420dff2-7dbc-4e75-b412-d2d33a0d86e8", "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "Σλ = 9.6719 m(+0) [-1]: 9κ = 6, T = 50" ], "text/plain": [ "" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Gʹ = G_from_S(Sʹ, A)\n", "svgplot(Gʹ)" ] }, { "cell_type": "code", "execution_count": 14, "id": "fe415c00-e060-4bb4-ba61-1496112791ae", "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "Σλ = 9.8049 m(+0) [-1]: 9κ = 6, T = 50" ], "text/plain": [ "" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Hʹ = PathFinder(Gʹ, planar=P, A=A).create_detours()\n", "svgplot(Hʹ)" ] }, { "cell_type": "code", "execution_count": 15, "id": "06df5315-38d3-4e26-afbb-fbcdab3b1b6a", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.013578500078660682" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "1 - Hʹ.size(weight='length')/G_ref.size(weight='length')" ] }, { "cell_type": "code", "execution_count": 16, "id": "5770c9ba-aba5-48f9-99fb-f6c25893dd1f", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Set parameter WLSAccessID\n", "Set parameter WLSSecret\n", "Set parameter LicenseID to value 937681\n", "Set parameter MIPFocus to value 1\n", "Academic license 937681 - for non-commercial use only - registered to ma___@dtu.dk\n" ] } ], "source": [ "solver.set_problem(\n", " P, A,\n", " capacity=6,\n", " model_options=ModelOptions(\n", " topology=\"radial\",\n", " feeder_route=\"segmented\",\n", " feeder_limit=\"minimum\",\n", " balanced=True,\n", " ),\n", " warmstart=Sʹ,\n", ")" ] }, { "cell_type": "code", "execution_count": 17, "id": "fc0c57c8-62bb-481f-8192-72b692e75789", "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Set parameter MIPFocus to value 2\n", "Set parameter PoolGap to value 0.015\n", "Set parameter PoolSearchMode to value 2\n", "Set parameter PoolSolutions to value 20\n", "Set parameter TimeLimit to value 35\n", "Set parameter MIPGap to value 0.005\n", "Gurobi Optimizer version 13.0.2 build v13.0.2rc1 (linux64 - \"Debian GNU/Linux forky/sid\")\n", "\n", "CPU model: 11th Gen Intel(R) Core(TM) i7-11850H @ 2.50GHz, instruction set [SSE2|AVX|AVX2|AVX512]\n", "Thread count: 8 physical cores, 16 logical processors, using up to 16 threads\n", "\n", "Non-default parameters:\n", "TimeLimit 35\n", "MIPGap 0.005\n", "MIPFocus 2\n", "PoolSolutions 20\n", "PoolSearchMode 2\n", "PoolGap 0.015\n", "\n", "Academic license 937681 - for non-commercial use only - registered to ma___@dtu.dk\n", "Optimize a model with 1442 rows, 872 columns and 5342 nonzeros (Min)\n", "Model fingerprint: 0x1b77179f\n", "Model has 436 linear objective coefficients\n", "Variable types: 0 continuous, 872 integer (436 binary)\n", "Coefficient statistics:\n", " Matrix range [1e+00, 6e+00]\n", " Objective range [6e-02, 1e+00]\n", " Bounds range [1e+00, 6e+00]\n", " RHS range [1e+00, 5e+01]\n", "\n", "Loaded user MIP start with objective 9.67192\n", "\n", "Presolve removed 192 rows and 0 columns\n", "Presolve time: 0.01s\n", "Presolved: 1250 rows, 872 columns, 4908 nonzeros\n", "Variable types: 0 continuous, 872 integer (436 binary)\n", "Root relaxation presolved: 1248 rows, 872 columns, 4876 nonzeros\n", "\n", "\n", "Root relaxation: objective 8.948966e+00, 1052 iterations, 0.02 seconds (0.02 work units)\n", "\n", " Nodes | Current Node | Objective Bounds | Work\n", " Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time\n", "\n", " 0 0 8.94897 0 123 9.67192 8.94897 7.47% - 0s\n", " 0 0 9.23090 0 194 9.67192 9.23090 4.56% - 0s\n", " 0 0 9.30911 0 205 9.67192 9.30911 3.75% - 0s\n", " 0 0 9.30911 0 215 9.67192 9.30911 3.75% - 0s\n", " 0 0 9.30911 0 215 9.67192 9.30911 3.75% - 0s\n", " 0 0 9.34235 0 237 9.67192 9.34235 3.41% - 0s\n", " 0 0 9.34235 0 238 9.67192 9.34235 3.41% - 0s\n", " 0 0 9.34235 0 232 9.67192 9.34235 3.41% - 0s\n", " 0 0 9.34975 0 230 9.67192 9.34975 3.33% - 0s\n", " 0 0 9.40534 0 259 9.67192 9.40534 2.76% - 0s\n", " 0 0 9.40629 0 257 9.67192 9.40629 2.75% - 0s\n", " 0 0 9.40629 0 259 9.67192 9.40629 2.75% - 0s\n", " 0 0 9.40677 0 261 9.67192 9.40677 2.74% - 0s\n", " 0 0 9.40805 0 225 9.67192 9.40805 2.73% - 0s\n", " 0 0 9.40829 0 252 9.67192 9.40829 2.73% - 0s\n", " 0 0 9.40833 0 242 9.67192 9.40833 2.73% - 0s\n", " 0 0 9.40833 0 245 9.67192 9.40833 2.73% - 0s\n", " 0 0 9.41188 0 252 9.67192 9.41188 2.69% - 1s\n", " 0 0 9.41232 0 266 9.67192 9.41232 2.68% - 1s\n", " 0 0 9.41232 0 274 9.67192 9.41232 2.68% - 1s\n", " 0 0 9.41232 0 274 9.67192 9.41232 2.68% - 1s\n", " 0 0 9.42500 0 258 9.67192 9.42500 2.55% - 1s\n", " 0 0 9.42500 0 266 9.67192 9.42500 2.55% - 1s\n", " 0 0 9.42500 0 259 9.67192 9.42500 2.55% - 1s\n", " 0 0 9.42516 0 268 9.67192 9.42516 2.55% - 1s\n", " 0 0 9.43718 0 275 9.67192 9.43718 2.43% - 1s\n", " 0 0 9.43872 0 271 9.67192 9.43872 2.41% - 1s\n", " 0 0 9.43872 0 274 9.67192 9.43872 2.41% - 1s\n", " 0 0 9.44535 0 249 9.67192 9.44535 2.34% - 1s\n", " 0 0 9.44535 0 252 9.67192 9.44535 2.34% - 1s\n", " 0 0 9.44535 0 249 9.67192 9.44535 2.34% - 1s\n", " 0 0 9.44730 0 265 9.67192 9.44730 2.32% - 1s\n", " 0 0 9.44730 0 278 9.67192 9.44730 2.32% - 1s\n", " 0 0 9.44977 0 276 9.67192 9.44977 2.30% - 2s\n", " 0 0 9.44977 0 276 9.67192 9.44977 2.30% - 2s\n", " 0 0 9.44977 0 276 9.67192 9.44977 2.30% - 2s\n", " 0 2 9.44977 0 276 9.67192 9.44977 2.30% - 2s\n", " 1614 1024 9.56562 14 276 9.67192 9.49893 1.79% 66.5 5s\n", " 1818 1168 9.61927 21 238 9.67192 9.51213 1.65% 73.6 10s\n", " 7772 4656 infeasible 30 9.67192 9.60852 0.66% 89.0 15s\n", " 14810 9113 9.75092 24 222 9.67192 9.65409 0.18% 93.4 20s\n", "\n", "Optimal solution found at node 18667 - now completing solution pool...\n", "\n", " Nodes | Current Node | Pool Obj. Bounds | Work\n", " | | Worst |\n", " Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time\n", "\n", " 18667 9980 9.77549 29 206 9.79597 9.67198 1.27% 92.5 22s\n", " 24630 5530 9.70718 29 137 9.74255 9.68556 0.59% 85.8 25s\n", "\n", "Cutting planes:\n", " Gomory: 24\n", " Lift-and-project: 11\n", " Cover: 41\n", " Implied bound: 14\n", " Projected implied bound: 1\n", " Clique: 3\n", " MIR: 218\n", " StrongCG: 5\n", " Flow cover: 223\n", " Flow path: 3\n", " GUB cover: 2\n", " Inf proof: 3\n", " Zero half: 82\n", " Network: 28\n", " RLT: 7\n", " Relax-and-lift: 20\n", " BQP: 4\n", "\n", "Explored 25555 nodes (2173334 simplex iterations) in 25.23 seconds (29.77 work units)\n", "Thread count was 16 (of 16 available processors)\n", "\n", "Solution count 20: 9.67192 9.68346 9.69748 ... 9.73763\n", "No other solutions better than 9.73763\n", "\n", "Optimal solution found (tolerance 5.00e-03)\n", "Best objective 9.671920168636e+00, best bound 9.671920168636e+00, gap 0.0000%\n" ] }, { "data": { "text/plain": [ "SolutionInfo(runtime=25.23669409751892, bound=9.671920168635916, objective=9.671920168635916, relgap=0.0, termination='optimal')" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "solver.solve(\n", " mip_gap=0.005,\n", " time_limit=35,\n", " verbose=True,\n", " options=dict(\n", " mipfocus=2,\n", " poolgap=0.015,\n", " poolsearchmode=2,\n", " poolsolutions=20\n", " ),\n", ")" ] }, { "cell_type": "code", "execution_count": 18, "id": "0d3fb568-f260-420e-98d4-5e9761edb63e", "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "Σλ = 9.6967 m(+0) [-1]: 9κ = 6, T = 50" ], "text/plain": [ "" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "S, G = solver.get_solution()\n", "svgplot(G)" ] }, { "cell_type": "code", "execution_count": 19, "id": "e12d9cac-f140-4d1c-91df-e97608e8f4ae", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.024457285866890444" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "1 - G.size(weight='length')/G_ref.size(weight='length')" ] }, { "cell_type": "code", "execution_count": 20, "id": "58bf3009-3ebd-4730-a3a2-696ed3e5aaf4", "metadata": {}, "outputs": [], "source": [ "with open('cazzaro_2022_comparison_κ_6_radial_balanced.pkl', 'wb') as outfile:\n", " pickle.dump(G, outfile)" ] } ], "metadata": { "language_info": { "name": "python" } }, "nbformat": 4, "nbformat_minor": 5 }