A Large and Complex Wind Farm¶
This notebook demonstrates how to apply OptiWindNet to optimize electrical network (cable routing) for a large-scale wind farm with 122 turbines and 2 substations, set in a concave area containing an internal obstacle. We will use EWRouter for warm-starting, then run MILPRouter with the COIN-OR CBC solver to find a high-quality branched cable network. The process covers loading real-world location data, generating and visualizing warm-start solutions, configuring solver and model
options, and plotting the final optimized network.
Note: Any additional geometric complexity will have negligible impact on solving time, as they do not increase the number of variables in the MILP optimization model.
This notebook uses COIN-OR CBC as solver, but examples for other solvers (gurobi, cplex, ortools, scip, highs) can be found in the MILPRouter notebooks. Gurobi and IBM ILOG CPLEX are comercial solvers (academic license available). Google’s OR-Tools, COIN-OR CBC, SCIP and HiGHS are open-source software.
[1]:
from optiwindnet.api import WindFarmNetwork, EWRouter, MILPRouter, ModelOptions, load_repository
Load input data¶
Note: the
load_repository()functionality of OptiWindNet is used to load a prebuilt Networkx.Graph of the avaible locations. For more details on this functionality look into the notebook about Load repositories containing location data.
[2]:
locations = load_repository()
The example location from https://onlinelibrary.wiley.com/doi/abs/10.1049/rpg2.12593 (Taylor_2023) provides suitable specifications for our purpose; a large wind farm with multiple substations and complex geometry.
[3]:
wfn = WindFarmNetwork(
L=locations.taylor_2023,
cables=[(5, 1800.0), (8, 2200.0)],
)
Note: To view output plots, trust this notebook first.
[4]:
wfn
[4]:
There are two options for generating an initial solution to warm-start the MILPRouter:
heuristic:
EWRouter()meta-heuristic:
HGSRouter()
EWRouter has the downside of not limiting the number of feeders, thus the model to be warm-started must also have an unlimited number of feeders. This is usually not a problem, as most cable route sets produced by the MILPRouter uses the minimum number of feeders or only one more than the minimum.
Generate the warm-start solution¶
To generate a warm-start solution, simply run wfn.optimize() with the desired solver e.g.:
wfn.optimize(router=warmstart_router)
In this example, we use EWRouter to warm-start the optimization model. Alternatively, HGSRouter() can be used for the same purpose.
The resulting solution is stored within the wfn object. The next time wfn.optimize() is called, the stored solution (S which contains selected-links) will be reused as a warm start; provided that the solver in MILPRouter supports warm-starting.
[5]:
warmstart_router = EWRouter()
res_warmstart= wfn.optimize(router=warmstart_router)
[6]:
wfn.length()
[6]:
113587.95387324075
Visualizing the warm-start solution¶
S can be visualized using wfn.plot_selected_links().
Check the plotting tutorial for details on the available plots.
[7]:
wfn
[7]:
MILP Router¶
Create an instance of MILPRouter and choose COIN-OR Branch and Cut (CBC) as solver.
When initializing a MILPRouter three arguments are required to be given:
solver name
time limit
gap
Solver options, including those set by OptiWindNet as well as additional configurable parameters, can be modified by creating a dictionary and passing it to the router. The same approach applies to model options. For a detailed explanation about model_options and solver_options of MILP routers see the notebook about ModelOptions vs SolverOptions.
[8]:
solver_options=dict( # these are in addition to the default solver.options
# if repeatable results are desired, set the seed
RandomCbcSeed=1234567,
# CBC works better if the number threads is set to the number of physical cores
threads=6,
)
model_options = ModelOptions(
topology='branched',
feeder_limit='unlimited',
feeder_route='segmented',
)
milp_router = MILPRouter(
solver_name='cbc',
time_limit=60,
mip_gap=0.005,
solver_options=solver_options,
model_options=model_options,
)
Run optimization with MILP router¶
[9]:
# Set logging level to INFO to display messages about solver options
import logging
logging.basicConfig(level=logging.INFO)
# run optimization with the milp router (Set verbose=True to display messages about solver progress)
res = wfn.optimize(router=milp_router, verbose=True)
INFO:optiwindnet.MILP.pyomo:>>> pyomo.cbc solver options <<<
Dins: 'on'
RandomCbcSeed: 1234567
Rens: 'on'
Rins: 'on'
VndVariableNeighborhoodSearch: 'on'
cliqueCuts: 'off'
flowCoverCuts: 'on'
gomoryCuts: 'on'
knapsackCuts: 'off'
liftAndProjectCuts: 'off'
mixedIntegerRoundingCuts: 'on'
nodeStrategy: 'downFewest'
pivotAndComplement: 'off'
probingCuts: 'off'
proximitySearch: 'off'
ratioGap: 0.005
residualCapacityCuts: 'off'
seconds: 60
threads: 6
timeMode: 'elapsed'
twoMirCuts: 'off'
zeroHalfCuts: 'off'
Welcome to the CBC MILP Solver
Version: 2.10.13
Build Date: Apr 1 2026
command line - /usr/bin/cbc -threads 6 -timeMode elapsed -nodeStrategy downFewest -Dins on -VndVariableNeighborhoodSearch on -Rens on -Rins on -pivotAndComplement off -proximitySearch off -gomoryCuts on -mixedIntegerRoundingCuts on -flowCoverCuts on -cliqueCuts off -twoMirCuts off -knapsackCuts off -probingCuts off -zeroHalfCuts off -liftAndProjectCuts off -residualCapacityCuts off -RandomCbcSeed 1234567 -seconds 60 -ratioGap 0.005 -printingOptions all -import /tmp/tmpzrnuowmq.pyomo.lp -mipstart /tmp/tmp6ns_4g1b.cbc.soln -stat=1 -solve -solu /tmp/tmpzrnuowmq.pyomo.soln (default strategy 1)
threads was changed from 0 to 6
Option for timeMode changed from cpu to elapsed
Option for nodeStrategy changed from fewest to downfewest
Option for Dins changed from off to on
Option for VndVariableNeighborhoodSearch changed from off to on
Option for Rens changed from off to on
Option for gomoryCuts changed from ifmove to on
Option for mixedIntegerRoundingCuts changed from ifmove to on
Option for flowCoverCuts changed from ifmove to on
Option for cliqueCuts changed from ifmove to off
Option for twoMirCuts changed from root to off
Option for knapsackCuts changed from ifmove to off
Option for probingCuts changed from on to off
Option for zeroHalfCuts changed from ifmove to off
randomCbcSeed was changed from -1 to 1234567
seconds was changed from 1e+100 to 60
ratioGap was changed from 0 to 0.005
Option for printingOptions changed from normal to all
opening mipstart file /tmp/tmp6ns_4g1b.cbc.soln.
MIPStart values read for 244 variables.
Presolve 4314 (-2) rows, 2891 (-1) columns and 14858 (-1442) elements
Statistics for presolved model
Original problem has 2892 integers (1446 of which binary)
Presolved problem has 2891 integers (1445 of which binary)
==== 1446 zero objective 840 different
==== absolute objective values 840 different
==== for integers 1446 zero objective 840 different
==== for integers absolute objective values 840 different
===== end objective counts
Problem has 4314 rows, 2891 columns (1445 with objective) and 14858 elements
Column breakdown:
0 of type 0.0->inf, 1446 of type 0.0->up, 0 of type lo->inf,
0 of type lo->up, 0 of type free, 0 of type fixed,
0 of type -inf->0.0, 0 of type -inf->up, 1445 of type 0.0->1.0
Row breakdown:
0 of type E 0.0, 243 of type E 1.0, 0 of type E -1.0,
1 of type E other, 0 of type G 0.0, 0 of type G 1.0,
1 of type G other, 2891 of type L 0.0, 1054 of type L 1.0,
124 of type L other, 0 of type Range 0.0->1.0, 0 of type Range other,
0 of type Free
Continuous objective value is 104281 - 1.24 seconds
Cgl0003I 0 fixed, 0 tightened bounds, 528 strengthened rows, 0 substitutions
Cgl0003I 0 fixed, 0 tightened bounds, 528 strengthened rows, 0 substitutions
Cgl0003I 0 fixed, 0 tightened bounds, 202 strengthened rows, 0 substitutions
Cgl0003I 0 fixed, 0 tightened bounds, 121 strengthened rows, 0 substitutions
Cgl0004I processed model has 3881 rows, 2892 columns (2892 integer (1446 of which binary)) and 15680 elements
Cbc0045I MIPStart provided solution with cost 113493
Cbc0012I Integer solution of 113493.06 found by Reduced search after 0 iterations and 0 nodes (0.25 seconds)
Cbc0038I Full problem 3882 rows 2892 columns, reduced to 264 rows 154 columns
Cbc0038I Full problem 3882 rows 2892 columns, reduced to 264 rows 154 columns
Cbc0038I Full problem 3882 rows 2892 columns, reduced to 264 rows 154 columns
Cbc0038I Full problem 3881 rows 2892 columns, reduced to 412 rows 230 columns
Cbc0038I Full problem 3882 rows 2892 columns, reduced to 305 rows 188 columns
Cbc0038I Full problem 3882 rows 2892 columns, reduced to 305 rows 188 columns
Cbc0038I Full problem 3882 rows 2892 columns, reduced to 305 rows 188 columns
Cbc0031I 88 added rows had average density of 88.568182
Cbc0013I At root node, 88 cuts changed objective from 104281.43 to 104895.91 in 19 passes
Cbc0014I Cut generator 0 (Gomory) - 230 row cuts average 346.8 elements, 0 column cuts (0 active) in 0.382 seconds - new frequency is 1
Cbc0014I Cut generator 1 (MixedIntegerRounding2) - 2 row cuts average 356.0 elements, 0 column cuts (0 active) in 0.055 seconds - new frequency is 3
Cbc0014I Cut generator 2 (FlowCover) - 163 row cuts average 16.7 elements, 0 column cuts (0 active) in 0.028 seconds - new frequency is 1
Cbc0010I After 0 nodes, 1 on tree, 113493.06 best solution, best possible 104895.91 (1.51 seconds)
Cbc0010I After 100 nodes, 56 on tree, 113493.06 best solution, best possible 104955.58 (5.29 seconds)
Cbc0010I After 200 nodes, 109 on tree, 113493.06 best solution, best possible 104955.58 (6.71 seconds)
Cbc0010I After 300 nodes, 163 on tree, 113493.06 best solution, best possible 104955.58 (7.65 seconds)
Cbc0010I After 400 nodes, 215 on tree, 113493.06 best solution, best possible 104955.58 (8.41 seconds)
Cbc0010I After 500 nodes, 250 on tree, 113493.06 best solution, best possible 104955.58 (8.94 seconds)
Cbc0010I After 600 nodes, 293 on tree, 113493.06 best solution, best possible 104955.58 (9.32 seconds)
Cbc0010I After 700 nodes, 310 on tree, 113493.06 best solution, best possible 104955.58 (9.60 seconds)
Cbc0010I After 800 nodes, 318 on tree, 113493.06 best solution, best possible 104955.58 (9.90 seconds)
Cbc0010I After 900 nodes, 317 on tree, 113493.06 best solution, best possible 104955.58 (10.11 seconds)
Cbc0010I After 1000 nodes, 324 on tree, 113493.06 best solution, best possible 104955.58 (10.33 seconds)
Cbc0010I After 1100 nodes, 329 on tree, 113493.06 best solution, best possible 104955.58 (10.56 seconds)
Cbc0010I After 1200 nodes, 336 on tree, 113493.06 best solution, best possible 104955.58 (10.82 seconds)
Cbc0010I After 1300 nodes, 343 on tree, 113493.06 best solution, best possible 104955.58 (11.01 seconds)
Cbc0010I After 1400 nodes, 345 on tree, 113493.06 best solution, best possible 104955.58 (11.21 seconds)
Cbc0010I After 1500 nodes, 338 on tree, 113493.06 best solution, best possible 104955.58 (11.41 seconds)
Cbc0010I After 1600 nodes, 340 on tree, 113493.06 best solution, best possible 104955.58 (11.57 seconds)
Cbc0010I After 1700 nodes, 338 on tree, 113493.06 best solution, best possible 104955.58 (11.69 seconds)
Cbc0010I After 1800 nodes, 334 on tree, 113493.06 best solution, best possible 104955.58 (11.82 seconds)
Cbc0010I After 1900 nodes, 333 on tree, 113493.06 best solution, best possible 104955.58 (11.99 seconds)
Cbc0010I After 2000 nodes, 345 on tree, 113493.06 best solution, best possible 104955.58 (12.18 seconds)
Cbc0010I After 2100 nodes, 354 on tree, 113493.06 best solution, best possible 104955.58 (12.39 seconds)
Cbc0010I After 2200 nodes, 345 on tree, 113493.06 best solution, best possible 104955.58 (12.55 seconds)
Cbc0010I After 2300 nodes, 340 on tree, 113493.06 best solution, best possible 104955.58 (12.68 seconds)
Cbc0010I After 2400 nodes, 359 on tree, 113493.06 best solution, best possible 104955.58 (12.83 seconds)
Cbc0010I After 2500 nodes, 338 on tree, 113493.06 best solution, best possible 104955.58 (12.96 seconds)
Cbc0010I After 2600 nodes, 356 on tree, 113493.06 best solution, best possible 104955.58 (13.13 seconds)
Cbc0010I After 2700 nodes, 360 on tree, 113493.06 best solution, best possible 104955.58 (13.25 seconds)
Cbc0010I After 2800 nodes, 346 on tree, 113493.06 best solution, best possible 104955.58 (13.39 seconds)
Cbc0010I After 2900 nodes, 356 on tree, 113493.06 best solution, best possible 104955.58 (13.51 seconds)
Cbc0010I After 3000 nodes, 340 on tree, 113493.06 best solution, best possible 104955.58 (13.68 seconds)
Cbc0010I After 3100 nodes, 346 on tree, 113493.06 best solution, best possible 104955.58 (13.90 seconds)
Cbc0010I After 3200 nodes, 344 on tree, 113493.06 best solution, best possible 104955.58 (14.07 seconds)
Cbc0010I After 3300 nodes, 338 on tree, 113493.06 best solution, best possible 104955.58 (14.26 seconds)
Cbc0010I After 3400 nodes, 331 on tree, 113493.06 best solution, best possible 104955.58 (14.40 seconds)
Cbc0010I After 3500 nodes, 331 on tree, 113493.06 best solution, best possible 104955.58 (14.57 seconds)
Cbc0010I After 3600 nodes, 340 on tree, 113493.06 best solution, best possible 104955.58 (14.75 seconds)
Cbc0010I After 3700 nodes, 346 on tree, 113493.06 best solution, best possible 104955.58 (14.98 seconds)
Cbc0010I After 3800 nodes, 341 on tree, 113493.06 best solution, best possible 104955.58 (15.16 seconds)
Cbc0010I After 3900 nodes, 341 on tree, 113493.06 best solution, best possible 104955.58 (15.27 seconds)
Cbc0010I After 4000 nodes, 337 on tree, 113493.06 best solution, best possible 104955.58 (15.43 seconds)
Cbc0010I After 4100 nodes, 334 on tree, 113493.06 best solution, best possible 104955.58 (15.60 seconds)
Cbc0010I After 4200 nodes, 337 on tree, 113493.06 best solution, best possible 104955.58 (15.82 seconds)
Cbc0010I After 4300 nodes, 332 on tree, 113493.06 best solution, best possible 104955.58 (16.03 seconds)
Cbc0010I After 4400 nodes, 350 on tree, 113493.06 best solution, best possible 104955.58 (16.25 seconds)
Cbc0010I After 4500 nodes, 346 on tree, 113493.06 best solution, best possible 104955.58 (16.49 seconds)
Cbc0010I After 4600 nodes, 350 on tree, 113493.06 best solution, best possible 104955.58 (16.63 seconds)
Cbc0010I After 4700 nodes, 351 on tree, 113493.06 best solution, best possible 104955.58 (16.79 seconds)
Cbc0010I After 4800 nodes, 358 on tree, 113493.06 best solution, best possible 104955.58 (17.02 seconds)
Cbc0010I After 4900 nodes, 397 on tree, 113493.06 best solution, best possible 104955.58 (17.27 seconds)
Cbc0010I After 5000 nodes, 417 on tree, 113493.06 best solution, best possible 104955.58 (17.53 seconds)
Cbc0010I After 5100 nodes, 435 on tree, 113493.06 best solution, best possible 104955.58 (17.70 seconds)
Cbc0010I After 5200 nodes, 442 on tree, 113493.06 best solution, best possible 104955.58 (17.85 seconds)
Cbc0010I After 5300 nodes, 450 on tree, 113493.06 best solution, best possible 104955.58 (18.06 seconds)
Cbc0010I After 5400 nodes, 454 on tree, 113493.06 best solution, best possible 104955.58 (18.24 seconds)
Cbc0010I After 5500 nodes, 467 on tree, 113493.06 best solution, best possible 104955.58 (18.48 seconds)
Cbc0010I After 5600 nodes, 480 on tree, 113493.06 best solution, best possible 104955.58 (18.74 seconds)
Cbc0010I After 5700 nodes, 501 on tree, 113493.06 best solution, best possible 104955.58 (18.92 seconds)
Cbc0010I After 5800 nodes, 502 on tree, 113493.06 best solution, best possible 104955.58 (19.09 seconds)
Cbc0010I After 5900 nodes, 517 on tree, 113493.06 best solution, best possible 104955.58 (19.25 seconds)
Cbc0010I After 6000 nodes, 519 on tree, 113493.06 best solution, best possible 104955.58 (19.34 seconds)
Cbc0010I After 6100 nodes, 516 on tree, 113493.06 best solution, best possible 104955.58 (19.47 seconds)
Cbc0010I After 6200 nodes, 517 on tree, 113493.06 best solution, best possible 104955.58 (19.65 seconds)
Cbc0010I After 6300 nodes, 544 on tree, 113493.06 best solution, best possible 104955.58 (19.87 seconds)
Cbc0010I After 6400 nodes, 548 on tree, 113493.06 best solution, best possible 104955.58 (20.07 seconds)
Cbc0010I After 6500 nodes, 549 on tree, 113493.06 best solution, best possible 104955.58 (20.27 seconds)
Cbc0010I After 6600 nodes, 560 on tree, 113493.06 best solution, best possible 104955.58 (20.47 seconds)
Cbc0010I After 6700 nodes, 563 on tree, 113493.06 best solution, best possible 104955.58 (20.73 seconds)
Cbc0010I After 6800 nodes, 578 on tree, 113493.06 best solution, best possible 104955.58 (20.97 seconds)
Cbc0010I After 6900 nodes, 579 on tree, 113493.06 best solution, best possible 104955.58 (21.10 seconds)
Cbc0010I After 7000 nodes, 593 on tree, 113493.06 best solution, best possible 104955.58 (21.29 seconds)
Cbc0010I After 7100 nodes, 627 on tree, 113493.06 best solution, best possible 104955.58 (21.47 seconds)
Cbc0010I After 7200 nodes, 642 on tree, 113493.06 best solution, best possible 104955.58 (21.64 seconds)
Cbc0010I After 7300 nodes, 649 on tree, 113493.06 best solution, best possible 104955.58 (21.80 seconds)
Cbc0010I After 7400 nodes, 640 on tree, 113493.06 best solution, best possible 104955.58 (21.94 seconds)
Cbc0010I After 7500 nodes, 650 on tree, 113493.06 best solution, best possible 104955.58 (22.09 seconds)
Cbc0010I After 7600 nodes, 645 on tree, 113493.06 best solution, best possible 104955.58 (22.25 seconds)
Cbc0010I After 7700 nodes, 634 on tree, 113493.06 best solution, best possible 104955.58 (22.42 seconds)
Cbc0010I After 7800 nodes, 644 on tree, 113493.06 best solution, best possible 104955.58 (22.54 seconds)
Cbc0010I After 7900 nodes, 637 on tree, 113493.06 best solution, best possible 104955.58 (22.63 seconds)
Cbc0010I After 8000 nodes, 630 on tree, 113493.06 best solution, best possible 104955.58 (22.74 seconds)
Cbc0010I After 8100 nodes, 641 on tree, 113493.06 best solution, best possible 104955.58 (22.96 seconds)
Cbc0010I After 8200 nodes, 655 on tree, 113493.06 best solution, best possible 104955.58 (23.15 seconds)
Cbc0010I After 8300 nodes, 672 on tree, 113493.06 best solution, best possible 104955.58 (23.28 seconds)
Cbc0010I After 8400 nodes, 673 on tree, 113493.06 best solution, best possible 104955.58 (23.40 seconds)
Cbc0010I After 8500 nodes, 671 on tree, 113493.06 best solution, best possible 104955.58 (23.51 seconds)
Cbc0010I After 8600 nodes, 684 on tree, 113493.06 best solution, best possible 104955.58 (23.61 seconds)
Cbc0010I After 8700 nodes, 679 on tree, 113493.06 best solution, best possible 104955.58 (23.69 seconds)
Cbc0010I After 8800 nodes, 670 on tree, 113493.06 best solution, best possible 104955.58 (23.81 seconds)
Cbc0010I After 8900 nodes, 666 on tree, 113493.06 best solution, best possible 104955.58 (23.92 seconds)
Cbc0010I After 9000 nodes, 669 on tree, 113493.06 best solution, best possible 104955.58 (24.04 seconds)
Cbc0010I After 9100 nodes, 657 on tree, 113493.06 best solution, best possible 104955.58 (24.19 seconds)
Cbc0010I After 9200 nodes, 664 on tree, 113493.06 best solution, best possible 104955.58 (24.37 seconds)
Cbc0010I After 9300 nodes, 679 on tree, 113493.06 best solution, best possible 104955.58 (24.46 seconds)
Cbc0010I After 9400 nodes, 677 on tree, 113493.06 best solution, best possible 104955.58 (24.55 seconds)
Cbc0010I After 9500 nodes, 672 on tree, 113493.06 best solution, best possible 104955.58 (24.62 seconds)
Cbc0010I After 9600 nodes, 663 on tree, 113493.06 best solution, best possible 104955.58 (24.71 seconds)
Cbc0010I After 9700 nodes, 670 on tree, 113493.06 best solution, best possible 104955.58 (24.81 seconds)
Cbc0010I After 9800 nodes, 671 on tree, 113493.06 best solution, best possible 104955.58 (24.89 seconds)
Cbc0010I After 9900 nodes, 655 on tree, 113493.06 best solution, best possible 104955.58 (25.04 seconds)
Cbc0010I After 10000 nodes, 667 on tree, 113493.06 best solution, best possible 104955.58 (25.15 seconds)
Cbc0010I After 10100 nodes, 662 on tree, 113493.06 best solution, best possible 104955.58 (25.24 seconds)
Cbc0010I After 10200 nodes, 671 on tree, 113493.06 best solution, best possible 104955.58 (25.34 seconds)
Cbc0010I After 10300 nodes, 662 on tree, 113493.06 best solution, best possible 104955.58 (25.50 seconds)
Cbc0010I After 10400 nodes, 676 on tree, 113493.06 best solution, best possible 104955.58 (25.65 seconds)
Cbc0010I After 10500 nodes, 678 on tree, 113493.06 best solution, best possible 104955.58 (25.83 seconds)
Cbc0010I After 10600 nodes, 667 on tree, 113493.06 best solution, best possible 104955.58 (26.04 seconds)
Cbc0010I After 10700 nodes, 675 on tree, 113493.06 best solution, best possible 104955.58 (26.24 seconds)
Cbc0010I After 10800 nodes, 680 on tree, 113493.06 best solution, best possible 104955.58 (26.40 seconds)
Cbc0010I After 10900 nodes, 693 on tree, 113493.06 best solution, best possible 104955.58 (26.55 seconds)
Cbc0010I After 11000 nodes, 693 on tree, 113493.06 best solution, best possible 104955.58 (26.70 seconds)
Cbc0010I After 11100 nodes, 742 on tree, 113493.06 best solution, best possible 104991.32 (28.81 seconds)
Cbc0010I After 11200 nodes, 790 on tree, 113493.06 best solution, best possible 105011.32 (30.08 seconds)
Cbc0010I After 11300 nodes, 841 on tree, 113493.06 best solution, best possible 105022.26 (31.32 seconds)
Cbc0010I After 11400 nodes, 892 on tree, 113493.06 best solution, best possible 105031.78 (32.33 seconds)
Cbc0010I After 11500 nodes, 940 on tree, 113493.06 best solution, best possible 105037.9 (33.34 seconds)
Cbc0010I After 11600 nodes, 992 on tree, 113493.06 best solution, best possible 105043.82 (34.17 seconds)
Cbc0010I After 11700 nodes, 1041 on tree, 113493.06 best solution, best possible 105048.23 (34.90 seconds)
Cbc0010I After 11800 nodes, 1091 on tree, 113493.06 best solution, best possible 105051.8 (35.63 seconds)
Cbc0010I After 11900 nodes, 1142 on tree, 113493.06 best solution, best possible 105054.67 (36.33 seconds)
Cbc0010I After 12000 nodes, 1191 on tree, 113493.06 best solution, best possible 105059.11 (36.97 seconds)
Cbc0010I After 12100 nodes, 1241 on tree, 113493.06 best solution, best possible 105061.41 (37.70 seconds)
Cbc0010I After 12200 nodes, 1291 on tree, 113493.06 best solution, best possible 105064.36 (38.30 seconds)
Cbc0010I After 12300 nodes, 1341 on tree, 113493.06 best solution, best possible 105066.92 (38.96 seconds)
Cbc0010I After 12400 nodes, 1391 on tree, 113493.06 best solution, best possible 105068.51 (39.56 seconds)
Cbc0010I After 12500 nodes, 1440 on tree, 113493.06 best solution, best possible 105071.32 (40.19 seconds)
Cbc0010I After 12600 nodes, 1491 on tree, 113493.06 best solution, best possible 105073.43 (40.74 seconds)
Cbc0010I After 12700 nodes, 1541 on tree, 113493.06 best solution, best possible 105075.31 (41.36 seconds)
Cbc0010I After 12800 nodes, 1592 on tree, 113493.06 best solution, best possible 105077.11 (41.85 seconds)
Cbc0010I After 12900 nodes, 1641 on tree, 113493.06 best solution, best possible 105079.22 (42.37 seconds)
Cbc0010I After 13000 nodes, 1692 on tree, 113493.06 best solution, best possible 105080.72 (42.91 seconds)
Cbc0010I After 13100 nodes, 1741 on tree, 113493.06 best solution, best possible 105082.24 (43.41 seconds)
Cbc0010I After 13200 nodes, 1791 on tree, 113493.06 best solution, best possible 105083.53 (44.04 seconds)
Cbc0010I After 13300 nodes, 1840 on tree, 113493.06 best solution, best possible 105085.01 (44.49 seconds)
Cbc0010I After 13400 nodes, 1890 on tree, 113493.06 best solution, best possible 105085.89 (45.02 seconds)
Cbc0010I After 13500 nodes, 1940 on tree, 113493.06 best solution, best possible 105087.02 (45.56 seconds)
Cbc0010I After 13600 nodes, 1990 on tree, 113493.06 best solution, best possible 105088.34 (46.04 seconds)
Cbc0010I After 13700 nodes, 2039 on tree, 113493.06 best solution, best possible 105089.38 (46.58 seconds)
Cbc0010I After 13800 nodes, 2089 on tree, 113493.06 best solution, best possible 105090.61 (47.20 seconds)
Cbc0010I After 13900 nodes, 2139 on tree, 113493.06 best solution, best possible 105091.37 (47.67 seconds)
Cbc0010I After 14000 nodes, 2190 on tree, 113493.06 best solution, best possible 105092.37 (48.15 seconds)
Cbc0010I After 14100 nodes, 2240 on tree, 113493.06 best solution, best possible 105093.13 (48.59 seconds)
Cbc0010I After 14200 nodes, 2289 on tree, 113493.06 best solution, best possible 105093.91 (49.08 seconds)
Cbc0010I After 14300 nodes, 2340 on tree, 113493.06 best solution, best possible 105094.71 (49.51 seconds)
Cbc0010I After 14400 nodes, 2389 on tree, 113493.06 best solution, best possible 105095.7 (49.98 seconds)
Cbc0010I After 14500 nodes, 2439 on tree, 113493.06 best solution, best possible 105096.22 (50.50 seconds)
Cbc0010I After 14600 nodes, 2489 on tree, 113493.06 best solution, best possible 105097.14 (51.01 seconds)
Cbc0010I After 14700 nodes, 2539 on tree, 113493.06 best solution, best possible 105098.05 (51.48 seconds)
Cbc0010I After 14800 nodes, 2589 on tree, 113493.06 best solution, best possible 105098.78 (51.96 seconds)
Cbc0010I After 14900 nodes, 2639 on tree, 113493.06 best solution, best possible 105099.47 (52.47 seconds)
Cbc0010I After 15000 nodes, 2690 on tree, 113493.06 best solution, best possible 105100.11 (52.95 seconds)
Cbc0010I After 15100 nodes, 2739 on tree, 113493.06 best solution, best possible 105100.88 (53.48 seconds)
Cbc0010I After 15200 nodes, 2789 on tree, 113493.06 best solution, best possible 105101.48 (53.94 seconds)
Cbc0010I After 15300 nodes, 2839 on tree, 113493.06 best solution, best possible 105102.13 (54.50 seconds)
Cbc0010I After 15400 nodes, 2889 on tree, 113493.06 best solution, best possible 105102.97 (55.03 seconds)
Cbc0010I After 15500 nodes, 2939 on tree, 113493.06 best solution, best possible 105103.51 (55.53 seconds)
Cbc0010I After 15600 nodes, 2990 on tree, 113493.06 best solution, best possible 105104.16 (56.06 seconds)
Cbc0010I After 15700 nodes, 3038 on tree, 113493.06 best solution, best possible 105104.68 (56.54 seconds)
Cbc0010I After 15800 nodes, 3088 on tree, 113493.06 best solution, best possible 105105.58 (57.06 seconds)
Cbc0010I After 15900 nodes, 3139 on tree, 113493.06 best solution, best possible 105106.2 (57.52 seconds)
Cbc0010I After 16000 nodes, 3189 on tree, 113493.06 best solution, best possible 105106.81 (58.02 seconds)
Cbc0010I After 16100 nodes, 3239 on tree, 113493.06 best solution, best possible 105107.34 (58.47 seconds)
Cbc0010I After 16200 nodes, 3288 on tree, 113493.06 best solution, best possible 105108.03 (58.97 seconds)
Cbc0010I After 16300 nodes, 3340 on tree, 113493.06 best solution, best possible 105108.52 (59.49 seconds)
Cbc0030I Thread 0 used 2811 times, waiting to start 0.60903478, 16178 locks, 0.47207999 locked, 0.061329126 waiting for locks
Cbc0030I Thread 1 used 2699 times, waiting to start 0.64490891, 15731 locks, 0.45184684 locked, 0.060606003 waiting for locks
Cbc0030I Thread 2 used 2748 times, waiting to start 1.0223918, 15789 locks, 0.45806575 locked, 0.061781645 waiting for locks
Cbc0030I Thread 3 used 2663 times, waiting to start 1.1283371, 15371 locks, 0.44218516 locked, 0.058873415 waiting for locks
Cbc0030I Thread 4 used 2718 times, waiting to start 1.2782054, 15693 locks, 0.45033574 locked, 0.06493783 waiting for locks
Cbc0030I Thread 5 used 2743 times, waiting to start 1.4361572, 15793 locks, 0.46110439 locked, 0.061211109 waiting for locks
Cbc0030I Main thread 56.102583 waiting for threads, 32946 locks, 0.016206026 locked, 0.12429452 waiting for locks
Cbc0020I Exiting on maximum time
Cbc0005I Partial search - best objective 113493.06 (best possible 105108.52), took 1162855 iterations and 16377 nodes (60.06 seconds)
Cbc0032I Strong branching done 36962 times (1043579 iterations), fathomed 1810 nodes and fixed 4615 variables
Cbc0035I Maximum depth 101, 333990 variables fixed on reduced cost
Cuts at root node changed objective from 104281 to 104896
Gomory was tried 5688 times and created 5409 cuts of which 0 were active after adding rounds of cuts (18.316 seconds)
MixedIntegerRounding2 was tried 8005 times and created 4059 cuts of which 0 were active after adding rounds of cuts (10.955 seconds)
FlowCover was tried 5686 times and created 27650 cuts of which 0 were active after adding rounds of cuts (4.672 seconds)
Result - Stopped on time limit
Objective value: 113493.05766610
Lower bound: 105108.517
Gap: 0.08
Enumerated nodes: 16377
Total iterations: 1162855
Time (CPU seconds): 343.85
Time (Wallclock seconds): 60.08
Total time (CPU seconds): 344.24 (Wallclock seconds): 60.11
INFO:optiwindnet.MILP.pyomo:>>> Solution <<<
SolutionInfo(runtime=60.11, bound=105108.52, objective=113493.0576661, relgap=0.07387709731786019, termination='maxTimeLimit')
[10]:
wfn.solution_info()
[10]:
{'router': 'MILPRouter',
'capacity': 8,
'solver_name': 'pyomo.cbc',
'mip_gap': 0.005,
'time_limit': 60,
'topology': <Topology.BRANCHED: 'branched'>,
'feeder_route': <FeederRoute.SEGMENTED: 'segmented'>,
'feeder_limit': <FeederLimit.UNLIMITED: 'unlimited'>,
'balanced': False,
'runtime': 60.11,
'bound': 105108.52,
'objective': 113493.0576661,
'relgap': 0.07387709731786019,
'termination': 'maxTimeLimit'}
[11]:
wfn.G.size(weight='length')
[11]:
113587.95387324075
[12]:
wfn.length()
[12]:
113587.95387324075
A topology-aware TerseLinks object is returned by wfn.optimize(). It behaves like a NumPy array and carries the solution architecture in its topology attribute. If the result is not assigned to a variable (for example, res), it remains available through wfn.terse_links().
[13]:
res
[13]:
TerseLinks(scope='topology', topology='branched', T=122, R=2, links=122)
Plot the optimized network graph¶
[14]:
wfn
[14]: