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]:
../_images/notebooks_a09_large_windfarm_complex_geometry_8_0.svg

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]:
../_images/notebooks_a09_large_windfarm_complex_geometry_16_0.svg

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.12
Build Date: Jan 19 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/tmpe5p6o69r.pyomo.lp -mipstart /tmp/tmp5_cjfwgv.cbc.soln -stat=1 -solve -solu /tmp/tmpe5p6o69r.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/tmp5_cjfwgv.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 - 0.05 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.20 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.342 seconds - new frequency is 1
Cbc0014I Cut generator 1 (MixedIntegerRounding2) - 2 row cuts average 356.0 elements, 0 column cuts (0 active)  in 0.046 seconds - new frequency is 3
Cbc0014I Cut generator 2 (FlowCover) - 163 row cuts average 16.7 elements, 0 column cuts (0 active)  in 0.025 seconds - new frequency is 1
Cbc0010I After 0 nodes, 1 on tree, 113493.06 best solution, best possible 104895.91 (1.37 seconds)
Cbc0010I After 100 nodes, 58 on tree, 113493.06 best solution, best possible 104955.58 (5.35 seconds)
Cbc0010I After 200 nodes, 112 on tree, 113493.06 best solution, best possible 104955.58 (6.90 seconds)
Cbc0010I After 300 nodes, 161 on tree, 113493.06 best solution, best possible 104955.58 (8.03 seconds)
Cbc0010I After 400 nodes, 214 on tree, 113493.06 best solution, best possible 104955.58 (9.07 seconds)
Cbc0010I After 500 nodes, 266 on tree, 113493.06 best solution, best possible 104955.58 (10.01 seconds)
Cbc0010I After 600 nodes, 318 on tree, 113493.06 best solution, best possible 104955.58 (10.80 seconds)
Cbc0010I After 700 nodes, 348 on tree, 113493.06 best solution, best possible 104955.58 (11.24 seconds)
Cbc0010I After 800 nodes, 341 on tree, 113493.06 best solution, best possible 104955.58 (11.57 seconds)
Cbc0010I After 900 nodes, 346 on tree, 113493.06 best solution, best possible 104955.58 (12.06 seconds)
Cbc0010I After 1000 nodes, 355 on tree, 113493.06 best solution, best possible 104955.58 (12.48 seconds)
Cbc0010I After 1100 nodes, 372 on tree, 113493.06 best solution, best possible 104955.58 (12.95 seconds)
Cbc0010I After 1200 nodes, 381 on tree, 113493.06 best solution, best possible 104955.58 (13.39 seconds)
Cbc0010I After 1300 nodes, 385 on tree, 113493.06 best solution, best possible 104955.58 (13.75 seconds)
Cbc0010I After 1400 nodes, 393 on tree, 113493.06 best solution, best possible 104955.58 (14.07 seconds)
Cbc0010I After 1500 nodes, 394 on tree, 113493.06 best solution, best possible 104955.58 (14.43 seconds)
Cbc0010I After 1600 nodes, 409 on tree, 113493.06 best solution, best possible 104955.58 (14.85 seconds)
Cbc0010I After 1700 nodes, 420 on tree, 113493.06 best solution, best possible 104955.58 (15.17 seconds)
Cbc0010I After 1800 nodes, 428 on tree, 113493.06 best solution, best possible 104955.58 (15.55 seconds)
Cbc0010I After 1900 nodes, 436 on tree, 113493.06 best solution, best possible 104955.58 (15.89 seconds)
Cbc0010I After 2000 nodes, 449 on tree, 113493.06 best solution, best possible 104955.58 (16.19 seconds)
Cbc0010I After 2100 nodes, 446 on tree, 113493.06 best solution, best possible 104955.58 (16.46 seconds)
Cbc0010I After 2200 nodes, 454 on tree, 113493.06 best solution, best possible 104955.58 (16.87 seconds)
Cbc0010I After 2300 nodes, 464 on tree, 113493.06 best solution, best possible 104955.58 (17.23 seconds)
Cbc0010I After 2400 nodes, 471 on tree, 113493.06 best solution, best possible 104955.58 (17.60 seconds)
Cbc0010I After 2500 nodes, 476 on tree, 113493.06 best solution, best possible 104955.58 (17.92 seconds)
Cbc0010I After 2600 nodes, 479 on tree, 113493.06 best solution, best possible 104955.58 (18.30 seconds)
Cbc0010I After 2700 nodes, 492 on tree, 113493.06 best solution, best possible 104955.58 (18.71 seconds)
Cbc0010I After 2800 nodes, 494 on tree, 113493.06 best solution, best possible 104955.58 (19.00 seconds)
Cbc0010I After 2900 nodes, 492 on tree, 113493.06 best solution, best possible 104955.58 (19.35 seconds)
Cbc0010I After 3000 nodes, 500 on tree, 113493.06 best solution, best possible 104955.58 (19.70 seconds)
Cbc0010I After 3100 nodes, 512 on tree, 113493.06 best solution, best possible 104955.58 (20.04 seconds)
Cbc0010I After 3200 nodes, 522 on tree, 113493.06 best solution, best possible 104955.58 (20.37 seconds)
Cbc0010I After 3300 nodes, 518 on tree, 113493.06 best solution, best possible 104955.58 (20.70 seconds)
Cbc0010I After 3400 nodes, 518 on tree, 113493.06 best solution, best possible 104955.58 (20.99 seconds)
Cbc0010I After 3500 nodes, 536 on tree, 113493.06 best solution, best possible 104955.58 (21.33 seconds)
Cbc0010I After 3600 nodes, 547 on tree, 113493.06 best solution, best possible 104955.58 (21.56 seconds)
Cbc0010I After 3700 nodes, 551 on tree, 113493.06 best solution, best possible 104955.58 (21.87 seconds)
Cbc0010I After 3800 nodes, 567 on tree, 113493.06 best solution, best possible 104955.58 (22.20 seconds)
Cbc0010I After 3900 nodes, 570 on tree, 113493.06 best solution, best possible 104955.58 (22.56 seconds)
Cbc0010I After 4000 nodes, 578 on tree, 113493.06 best solution, best possible 104955.58 (22.90 seconds)
Cbc0010I After 4100 nodes, 578 on tree, 113493.06 best solution, best possible 104955.58 (23.21 seconds)
Cbc0010I After 4200 nodes, 609 on tree, 113493.06 best solution, best possible 104955.58 (23.57 seconds)
Cbc0010I After 4300 nodes, 631 on tree, 113493.06 best solution, best possible 104955.58 (23.76 seconds)
Cbc0010I After 4400 nodes, 640 on tree, 113493.06 best solution, best possible 104955.58 (23.94 seconds)
Cbc0010I After 4500 nodes, 645 on tree, 113493.06 best solution, best possible 104955.58 (24.15 seconds)
Cbc0010I After 4600 nodes, 664 on tree, 113493.06 best solution, best possible 104955.58 (24.39 seconds)
Cbc0010I After 4700 nodes, 673 on tree, 113493.06 best solution, best possible 104955.58 (24.56 seconds)
Cbc0010I After 4800 nodes, 671 on tree, 113493.06 best solution, best possible 104955.58 (24.72 seconds)
Cbc0010I After 4900 nodes, 686 on tree, 113493.06 best solution, best possible 104955.58 (24.97 seconds)
Cbc0010I After 5000 nodes, 697 on tree, 113493.06 best solution, best possible 104955.58 (25.28 seconds)
Cbc0010I After 5100 nodes, 704 on tree, 113493.06 best solution, best possible 104955.58 (25.53 seconds)
Cbc0010I After 5200 nodes, 719 on tree, 113493.06 best solution, best possible 104955.58 (25.73 seconds)
Cbc0010I After 5300 nodes, 728 on tree, 113493.06 best solution, best possible 104955.58 (25.90 seconds)
Cbc0010I After 5400 nodes, 738 on tree, 113493.06 best solution, best possible 104955.58 (26.10 seconds)
Cbc0010I After 5500 nodes, 760 on tree, 113493.06 best solution, best possible 104955.58 (26.35 seconds)
Cbc0010I After 5600 nodes, 762 on tree, 113493.06 best solution, best possible 104955.58 (26.49 seconds)
Cbc0010I After 5700 nodes, 772 on tree, 113493.06 best solution, best possible 104955.58 (26.67 seconds)
Cbc0010I After 5800 nodes, 773 on tree, 113493.06 best solution, best possible 104955.58 (26.88 seconds)
Cbc0010I After 5900 nodes, 783 on tree, 113493.06 best solution, best possible 104955.58 (27.14 seconds)
Cbc0010I After 6000 nodes, 778 on tree, 113493.06 best solution, best possible 104955.58 (27.40 seconds)
Cbc0010I After 6100 nodes, 778 on tree, 113493.06 best solution, best possible 104955.58 (27.61 seconds)
Cbc0010I After 6200 nodes, 784 on tree, 113493.06 best solution, best possible 104955.58 (27.88 seconds)
Cbc0010I After 6300 nodes, 783 on tree, 113493.06 best solution, best possible 104955.58 (28.20 seconds)
Cbc0010I After 6400 nodes, 799 on tree, 113493.06 best solution, best possible 104955.58 (28.47 seconds)
Cbc0010I After 6500 nodes, 813 on tree, 113493.06 best solution, best possible 104955.58 (28.58 seconds)
Cbc0010I After 6600 nodes, 792 on tree, 113493.06 best solution, best possible 104955.58 (28.70 seconds)
Cbc0010I After 6700 nodes, 805 on tree, 113493.06 best solution, best possible 104955.58 (29.04 seconds)
Cbc0010I After 6800 nodes, 832 on tree, 113493.06 best solution, best possible 104955.58 (29.38 seconds)
Cbc0010I After 6900 nodes, 857 on tree, 113493.06 best solution, best possible 104955.58 (29.61 seconds)
Cbc0010I After 7000 nodes, 867 on tree, 113493.06 best solution, best possible 104955.58 (29.88 seconds)
Cbc0010I After 7100 nodes, 866 on tree, 113493.06 best solution, best possible 104955.58 (30.14 seconds)
Cbc0010I After 7200 nodes, 865 on tree, 113493.06 best solution, best possible 104955.58 (30.47 seconds)
Cbc0010I After 7300 nodes, 877 on tree, 113493.06 best solution, best possible 104955.58 (30.75 seconds)
Cbc0010I After 7400 nodes, 888 on tree, 113493.06 best solution, best possible 104955.58 (30.98 seconds)
Cbc0010I After 7500 nodes, 898 on tree, 113493.06 best solution, best possible 104955.58 (31.19 seconds)
Cbc0010I After 7600 nodes, 916 on tree, 113493.06 best solution, best possible 104955.58 (31.41 seconds)
Cbc0010I After 7700 nodes, 918 on tree, 113493.06 best solution, best possible 104955.58 (31.52 seconds)
Cbc0010I After 7800 nodes, 920 on tree, 113493.06 best solution, best possible 104955.58 (31.68 seconds)
Cbc0010I After 7900 nodes, 926 on tree, 113493.06 best solution, best possible 104955.58 (31.91 seconds)
Cbc0010I After 8000 nodes, 937 on tree, 113493.06 best solution, best possible 104955.58 (32.15 seconds)
Cbc0010I After 8100 nodes, 942 on tree, 113493.06 best solution, best possible 104955.58 (32.35 seconds)
Cbc0010I After 8200 nodes, 973 on tree, 113493.06 best solution, best possible 104955.58 (32.64 seconds)
Cbc0010I After 8300 nodes, 976 on tree, 113493.06 best solution, best possible 104955.58 (32.91 seconds)
Cbc0010I After 8400 nodes, 1006 on tree, 113493.06 best solution, best possible 104955.58 (33.19 seconds)
Cbc0010I After 8500 nodes, 1014 on tree, 113493.06 best solution, best possible 104955.58 (33.39 seconds)
Cbc0010I After 8600 nodes, 1020 on tree, 113493.06 best solution, best possible 104955.58 (33.63 seconds)
Cbc0010I After 8700 nodes, 1043 on tree, 113493.06 best solution, best possible 104955.58 (33.90 seconds)
Cbc0010I After 8800 nodes, 1057 on tree, 113493.06 best solution, best possible 104955.58 (34.16 seconds)
Cbc0010I After 8900 nodes, 1059 on tree, 113493.06 best solution, best possible 104955.58 (34.42 seconds)
Cbc0010I After 9000 nodes, 1064 on tree, 113493.06 best solution, best possible 104955.58 (34.75 seconds)
Cbc0010I After 9100 nodes, 1065 on tree, 113493.06 best solution, best possible 104955.58 (34.99 seconds)
Cbc0010I After 9200 nodes, 1084 on tree, 113493.06 best solution, best possible 104955.58 (35.18 seconds)
Cbc0010I After 9300 nodes, 1073 on tree, 113493.06 best solution, best possible 104955.58 (35.33 seconds)
Cbc0010I After 9400 nodes, 1099 on tree, 113493.06 best solution, best possible 104955.58 (35.68 seconds)
Cbc0010I After 9500 nodes, 1104 on tree, 113493.06 best solution, best possible 104955.58 (35.84 seconds)
Cbc0010I After 9600 nodes, 1104 on tree, 113493.06 best solution, best possible 104955.58 (36.01 seconds)
Cbc0010I After 9700 nodes, 1106 on tree, 113493.06 best solution, best possible 104955.58 (36.29 seconds)
Cbc0010I After 9800 nodes, 1133 on tree, 113493.06 best solution, best possible 104955.58 (36.51 seconds)
Cbc0010I After 9900 nodes, 1140 on tree, 113493.06 best solution, best possible 104955.58 (36.73 seconds)
Cbc0010I After 10000 nodes, 1141 on tree, 113493.06 best solution, best possible 104955.58 (36.96 seconds)
Cbc0010I After 10100 nodes, 1168 on tree, 113493.06 best solution, best possible 104955.58 (37.20 seconds)
Cbc0010I After 10200 nodes, 1185 on tree, 113493.06 best solution, best possible 104955.58 (37.47 seconds)
Cbc0010I After 10300 nodes, 1191 on tree, 113493.06 best solution, best possible 104955.58 (37.72 seconds)
Cbc0010I After 10400 nodes, 1191 on tree, 113493.06 best solution, best possible 104955.58 (37.97 seconds)
Cbc0010I After 10500 nodes, 1204 on tree, 113493.06 best solution, best possible 104955.58 (38.20 seconds)
Cbc0010I After 10600 nodes, 1218 on tree, 113493.06 best solution, best possible 104955.58 (38.42 seconds)
Cbc0010I After 10700 nodes, 1240 on tree, 113493.06 best solution, best possible 104955.58 (38.62 seconds)
Cbc0010I After 10800 nodes, 1250 on tree, 113493.06 best solution, best possible 104955.58 (38.74 seconds)
Cbc0010I After 10900 nodes, 1253 on tree, 113493.06 best solution, best possible 104955.58 (38.86 seconds)
Cbc0010I After 11000 nodes, 1249 on tree, 113493.06 best solution, best possible 104955.58 (39.00 seconds)
Cbc0010I After 11100 nodes, 1297 on tree, 113493.06 best solution, best possible 105020.1 (40.89 seconds)
Cbc0010I After 11200 nodes, 1347 on tree, 113493.06 best solution, best possible 105049.93 (41.90 seconds)
Cbc0010I After 11300 nodes, 1396 on tree, 113493.06 best solution, best possible 105061.34 (42.75 seconds)
Cbc0010I After 11400 nodes, 1447 on tree, 113493.06 best solution, best possible 105071.62 (43.52 seconds)
Cbc0010I After 11500 nodes, 1496 on tree, 113493.06 best solution, best possible 105077.54 (44.11 seconds)
Cbc0010I After 11600 nodes, 1547 on tree, 113493.06 best solution, best possible 105082.86 (44.74 seconds)
Cbc0010I After 11700 nodes, 1596 on tree, 113493.06 best solution, best possible 105087.41 (45.43 seconds)
Cbc0010I After 11800 nodes, 1646 on tree, 113493.06 best solution, best possible 105090.87 (45.97 seconds)
Cbc0010I After 11900 nodes, 1697 on tree, 113493.06 best solution, best possible 105093.76 (46.58 seconds)
Cbc0010I After 12000 nodes, 1746 on tree, 113493.06 best solution, best possible 105096.99 (47.11 seconds)
Cbc0010I After 12100 nodes, 1796 on tree, 113493.06 best solution, best possible 105099.06 (47.59 seconds)
Cbc0010I After 12200 nodes, 1847 on tree, 113493.06 best solution, best possible 105101.21 (48.30 seconds)
Cbc0010I After 12300 nodes, 1896 on tree, 113493.06 best solution, best possible 105102.76 (48.77 seconds)
Cbc0010I After 12400 nodes, 1947 on tree, 113493.06 best solution, best possible 105104.53 (49.29 seconds)
Cbc0010I After 12500 nodes, 1997 on tree, 113493.06 best solution, best possible 105106.32 (49.83 seconds)
Cbc0010I After 12600 nodes, 2046 on tree, 113493.06 best solution, best possible 105107.68 (50.32 seconds)
Cbc0010I After 12700 nodes, 2096 on tree, 113493.06 best solution, best possible 105109.26 (50.88 seconds)
Cbc0010I After 12800 nodes, 2146 on tree, 113493.06 best solution, best possible 105110.77 (51.39 seconds)
Cbc0010I After 12900 nodes, 2195 on tree, 113493.06 best solution, best possible 105112.58 (51.88 seconds)
Cbc0010I After 13000 nodes, 2246 on tree, 113493.06 best solution, best possible 105113.92 (52.49 seconds)
Cbc0010I After 13100 nodes, 2296 on tree, 113493.06 best solution, best possible 105115.07 (52.95 seconds)
Cbc0010I After 13200 nodes, 2346 on tree, 113493.06 best solution, best possible 105116.05 (53.45 seconds)
Cbc0010I After 13300 nodes, 2396 on tree, 113493.06 best solution, best possible 105117.44 (53.96 seconds)
Cbc0010I After 13400 nodes, 2446 on tree, 113493.06 best solution, best possible 105118.77 (54.53 seconds)
Cbc0010I After 13500 nodes, 2496 on tree, 113493.06 best solution, best possible 105120.07 (55.07 seconds)
Cbc0010I After 13600 nodes, 2546 on tree, 113493.06 best solution, best possible 105121.28 (55.59 seconds)
Cbc0010I After 13700 nodes, 2596 on tree, 113493.06 best solution, best possible 105122.6 (56.18 seconds)
Cbc0010I After 13800 nodes, 2646 on tree, 113493.06 best solution, best possible 105123.06 (56.83 seconds)
Cbc0010I After 13900 nodes, 2695 on tree, 113493.06 best solution, best possible 105125.01 (57.41 seconds)
Cbc0010I After 14000 nodes, 2745 on tree, 113493.06 best solution, best possible 105125.63 (57.91 seconds)
Cbc0010I After 14100 nodes, 2795 on tree, 113493.06 best solution, best possible 105126.56 (58.47 seconds)
Cbc0010I After 14200 nodes, 2846 on tree, 113493.06 best solution, best possible 105127.57 (58.95 seconds)
Cbc0010I After 14300 nodes, 2896 on tree, 113493.06 best solution, best possible 105128.34 (59.42 seconds)
Cbc0030I Thread 0 used 2405 times,  waiting to start 0.45771646,  13903 locks, 0.40449214 locked, 0.038077354 waiting for locks
Cbc0030I Thread 1 used 2476 times,  waiting to start 0.5997951,  14151 locks, 0.40670323 locked, 0.037345886 waiting for locks
Cbc0030I Thread 2 used 2446 times,  waiting to start 0.95887184,  14015 locks, 0.40313816 locked, 0.038774252 waiting for locks
Cbc0030I Thread 3 used 2363 times,  waiting to start 1.1285586,  13558 locks, 0.39360642 locked, 0.036976576 waiting for locks
Cbc0030I Thread 4 used 2339 times,  waiting to start 1.2031939,  13657 locks, 0.38745141 locked, 0.032811403 waiting for locks
Cbc0030I Thread 5 used 2365 times,  waiting to start 1.3394673,  13599 locks, 0.38819408 locked, 0.038659811 waiting for locks
Cbc0030I Main thread 56.499541 waiting for threads,  28948 locks, 0.014279842 locked, 0.076101542 waiting for locks
Cbc0020I Exiting on maximum time
Cbc0005I Partial search - best objective 113493.06 (best possible 105128.34), took 1254311 iterations and 14389 nodes (60.03 seconds)
Cbc0032I Strong branching done 32660 times (1131783 iterations), fathomed 925 nodes and fixed 3118 variables
Cbc0035I Maximum depth 89, 496586 variables fixed on reduced cost
Cuts at root node changed objective from 104281 to 104896
Gomory was tried 5062 times and created 3785 cuts of which 0 were active after adding rounds of cuts (18.331 seconds)
MixedIntegerRounding2 was tried 6863 times and created 3908 cuts of which 0 were active after adding rounds of cuts (8.444 seconds)
FlowCover was tried 5062 times and created 27866 cuts of which 0 were active after adding rounds of cuts (4.072 seconds)

Result - Stopped on time limit

Objective value:                113493.05766610
Lower bound:                    105128.335
Gap:                            0.08
Enumerated nodes:               14389
Total iterations:               1254311
Time (CPU seconds):             344.27
Time (Wallclock seconds):       60.05

Total time (CPU seconds):       344.28   (Wallclock seconds):       60.07

INFO:optiwindnet.MILP.pyomo:>>> Solution <<<
SolutionInfo(runtime=60.07, bound=105128.34, objective=113493.0576661, relgap=0.07370246108541056, 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.07,
 'bound': 105128.34,
 'objective': 113493.0576661,
 'relgap': 0.07370246108541056,
 'termination': 'maxTimeLimit'}
[11]:
wfn.G.size(weight='length')
[11]:
113587.95387324075
[12]:
wfn.length()
[12]:
113587.95387324075

Terse link of the optimized network is returned as output of wfn.optimize(). If not assigned to a variable (e.g. res), it can be easily accessed via wfn.terse_links().

[13]:
res
[13]:
array([  6,   0,   1,  10,   3,  -2,   5,  14,   7,  10,  11,  20,  -2,
        12,  13,  16,  17,  18,  19,  29,  -2,  14,  31,  15,  25,  26,
        27,  28,  -2,  -2,  -2,  41,  42,  34,  35,  36,  37,  38,  -2,
        -2,  -2,  42,  53,  44,  45,  55,  56,  46,  47,  39,  40,  50,
        64,  54,  66,  67,  68,  69,  59,  49,  -2,  60,  51,  62,  65,
        77,  -1,  -1,  81,  70,  83,  59,  60,  61,  73,  63,  75,  78,
        79,  80,  -1,  -1,  -1,  82,  83,  84,  85,  74,  87,  90,  91,
        -1,  -1,  -1,  93,  94,  95,  96,  87, 100, 101,  92,  -1,  94,
       103, 104, 114, 106, 100,  -1, 102, 110, 111, 112, 113, 109, 115,
       121, 117, 118, 116, 120])

Plot the optimized network graph¶

[14]:
wfn
[14]:
../_images/notebooks_a09_large_windfarm_complex_geometry_30_0.svg