{
"cells": [
{
"cell_type": "markdown",
"id": "d32c2081-76d0-4c47-98d0-228a14e8073a",
"metadata": {},
"source": [
"## Legacy heuristic examples"
]
},
{
"cell_type": "markdown",
"id": "b306a7d8-a29e-41c5-a537-c20e702133dd",
"metadata": {},
"source": [
"`ClassicEW`, `CPEW`, `NBEW`, and `OBEW` are deprecated legacy heuristic entry points. They will be removed in version 0.3.\n",
"\n",
"Their functionality is now available through the unified `constructor()` heuristic.\n",
"\n",
"This notebook contains examples of each of the legacy entry points usage and the equivalent call to `constructor()`.\n",
"\n",
"The unified heuristic **does not reproduce exactly** the deprecated heuristics, but the properties of the solution should match."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "2ea0ea53-31b1-4099-bab6-d66d62770719",
"metadata": {},
"outputs": [],
"source": [
"import warnings\n",
"\n",
"from optiwindnet.importer import load_repository\n",
"from optiwindnet.mesh import make_planar_embedding\n",
"from optiwindnet.pathfinding import PathFinder\n",
"from optiwindnet.heuristics import ClassicEW, CPEW, NBEW, OBEW, constructor\n",
"from optiwindnet.interarraylib import G_from_S, calcload\n",
"from optiwindnet.svg import svgplot"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "4d4e57f9-ab96-43fc-95ec-9c874c25d02d",
"metadata": {},
"outputs": [],
"source": [
"locations = load_repository()"
]
},
{
"cell_type": "markdown",
"id": "ec84aca7-34f3-49a4-ab3b-ecf93318fec2",
"metadata": {},
"source": [
"### Helper functions"
]
},
{
"cell_type": "markdown",
"id": "dda188d8-bf45-4979-a436-0bcf863ad7d7",
"metadata": {},
"source": [
"The deprecated heuristics in this notebook (`ClassicEW`, `CPEW`, `NBEW`, and `OBEW`) take the location graph **L** as input and return a routed graph **G** directly. Hence, `legacy_solution()` only needs to call the legacy function and then calculate edge loads.\n",
"\n",
"`constructor()` works one level lower in the routing pipeline. It's input is the available-links graph **A** and its return value is the solution topology **S**. That is why `constructor_solution()` first calls `make_planar_embedding(L)` to derive the planar mesh **P** and available links **A**, then calls `constructor(A, ...)`, converts **S** to a tentative graph with `G_from_S(S, A)`, and finally uses `PathFinder(...).create_detours()` to obtain the routed graph **G** used for plotting and comparison."
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "c0dda85f-cede-4643-8478-74e1206c0b71",
"metadata": {},
"outputs": [],
"source": [
"def legacy_solution(fun, L, capacity, **kwargs):\n",
" with warnings.catch_warnings():\n",
" warnings.simplefilter('ignore', DeprecationWarning)\n",
" G = fun(L, capacity=capacity, **kwargs)\n",
" calcload(G)\n",
" return G\n",
"\n",
"def constructor_solution(L, capacity, **kwargs):\n",
" P, A = make_planar_embedding(L)\n",
" S = constructor(A, capacity=capacity, **kwargs)\n",
" G_topology = G_from_S(S, A)\n",
" G = PathFinder(G_topology, planar=P, A=A).create_detours()\n",
" calcload(G)\n",
" return G\n",
"\n",
"def compare(label, legacy, constructed):\n",
" return {\n",
" 'case': label,\n",
" 'legacy_length': round(legacy.size(weight='length')),\n",
" 'constructor_length': round(constructed.size(weight='length')),\n",
" 'legacy_max_load': legacy.graph['max_load'],\n",
" 'constructor_max_load': constructed.graph['max_load'],\n",
" }\n",
"\n",
"def show_pair(label, legacy, constructed):\n",
" print(f'{label}: legacy')\n",
" display(svgplot(legacy))\n",
" print(f'{label}: constructor')\n",
" display(svgplot(constructed))"
]
},
{
"cell_type": "markdown",
"id": "502eb9be-ee46-46fb-862b-e20f3db080ae",
"metadata": {},
"source": [
"### Classic Esau-Williams"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "1006b87e-7598-44b2-920c-64783a33b3e4",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'case': 'ClassicEW',\n",
" 'legacy_length': 59585,\n",
" 'constructor_length': 60145,\n",
" 'legacy_max_load': 9,\n",
" 'constructor_max_load': 9}"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"L = locations.merkur\n",
"capacity = 9\n",
"\n",
"G_classic = legacy_solution(ClassicEW, L, capacity)\n",
"G_constructor_classic = constructor_solution(\n",
" L,\n",
" capacity,\n",
" method='esau_williams',\n",
" weigh_detours=False,\n",
")\n",
"\n",
"compare('ClassicEW', G_classic, G_constructor_classic)"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "d84e40f0-2968-4561-866e-b086848cd991",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"ClassicEW: legacy\n"
]
},
{
"data": {
"image/svg+xml": [
""
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"ClassicEW: constructor\n"
]
},
{
"data": {
"image/svg+xml": [
""
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_pair('ClassicEW', G_classic, G_constructor_classic)"
]
},
{
"cell_type": "markdown",
"id": "289eff1e-3ba1-40a4-bc23-6ca4fce2335c",
"metadata": {},
"source": [
"### Crossing-Preventing Esau-Williams"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "76c702bc-4dcd-4541-b957-99a3905d5229",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'case': 'CPEW',\n",
" 'legacy_length': 59922,\n",
" 'constructor_length': 59902,\n",
" 'legacy_max_load': 9,\n",
" 'constructor_max_load': 9}"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"L = locations.merkur\n",
"capacity = 9\n",
"\n",
"G_cpew = legacy_solution(CPEW, L, capacity)\n",
"G_constructor_cpew = constructor_solution(\n",
" L,\n",
" capacity,\n",
" method='biased_EW',\n",
" straight_feeder_route=True,\n",
" weigh_detours=False,\n",
")\n",
"\n",
"compare('CPEW', G_cpew, G_constructor_cpew)"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "11e6da99-9b15-4824-829d-a145666b75a8",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"CPEW: legacy\n"
]
},
{
"data": {
"image/svg+xml": [
""
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"CPEW: constructor\n"
]
},
{
"data": {
"image/svg+xml": [
""
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_pair('CPEW', G_cpew, G_constructor_cpew)"
]
},
{
"cell_type": "markdown",
"id": "6e97446d-fb53-4a9e-b643-223b080672f5",
"metadata": {},
"source": [
"### Non-Branching Esau-Williams"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "8e973a6b-4b72-4ca6-b833-8a148cc639be",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'case': 'NBEW',\n",
" 'legacy_length': 275479,\n",
" 'constructor_length': 274287,\n",
" 'legacy_max_load': 9,\n",
" 'constructor_max_load': 9}"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"L = locations.sofia\n",
"capacity = 9\n",
"\n",
"G_nbew = legacy_solution(NBEW, L, capacity)\n",
"G_constructor_nbew = constructor_solution(\n",
" L,\n",
" capacity,\n",
" method='radial_EW',\n",
" straight_feeder_route=True,\n",
" weigh_detours=False,\n",
")\n",
"\n",
"compare('NBEW', G_nbew, G_constructor_nbew)"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "4529ec36-d766-4e6e-8e93-3d99cbb6df5e",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"NBEW: legacy\n"
]
},
{
"data": {
"image/svg+xml": [
""
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"NBEW: constructor\n"
]
},
{
"data": {
"image/svg+xml": [
""
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_pair('NBEW', G_nbew, G_constructor_nbew)"
]
},
{
"cell_type": "markdown",
"id": "7a972411-13b3-4af1-8849-dfd82b57debf",
"metadata": {},
"source": [
"### Obstacle-Bypassing Esau-Williams"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "3f294c53-6247-4706-9f71-969b5f592943",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'case': 'OBEW rootlust',\n",
" 'legacy_length': 58916,\n",
" 'constructor_length': 59187,\n",
" 'legacy_max_load': 6,\n",
" 'constructor_max_load': 6}"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"L = locations.borkum2\n",
"capacity = 6\n",
"\n",
"G_obew = legacy_solution(OBEW, L, capacity, rootlust='0.6*cur_capacity/capacity')\n",
"G_constructor_obew = constructor_solution(\n",
" L,\n",
" capacity,\n",
" method='rootlust',\n",
" # matching OBEW's rootlust is capacity-dependent\n",
" rootlust_=(0.0, 0.6 * (capacity - 1) / capacity),\n",
")\n",
"\n",
"compare('OBEW rootlust', G_obew, G_constructor_obew)"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "94e3fa82-7d23-47f9-9458-e7c61b8b3505",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"OBEW rootlust: legacy\n"
]
},
{
"data": {
"image/svg+xml": [
""
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"OBEW rootlust: constructor\n"
]
},
{
"data": {
"image/svg+xml": [
""
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_pair('OBEW rootlust', G_obew, G_constructor_obew)"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "2a9e282b-bb7a-4655-a794-5e64b462508e",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'case': 'OBEW default',\n",
" 'legacy_length': 58275,\n",
" 'constructor_length': 58275,\n",
" 'legacy_max_load': 6,\n",
" 'constructor_max_load': 6}"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"G_obew_default = legacy_solution(OBEW, L, capacity)\n",
"G_constructor_obew_default = constructor_solution(L, capacity, method='biased_EW')\n",
"\n",
"compare('OBEW default', G_obew_default, G_constructor_obew_default)"
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "7805b612-149c-4eb0-9e8d-7f10f3b429dc",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"OBEW default: legacy\n"
]
},
{
"data": {
"image/svg+xml": [
""
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"OBEW default: constructor\n"
]
},
{
"data": {
"image/svg+xml": [
""
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_pair('OBEW default', G_obew_default, G_constructor_obew_default)"
]
}
],
"metadata": {
"language_info": {
"name": "python"
}
},
"nbformat": 4,
"nbformat_minor": 5
}