SCIP example¶

[1]:
from optiwindnet.importer import load_repository
from optiwindnet.svg import svgplot
from optiwindnet.mesh import make_planar_embedding
from optiwindnet.interarraylib import G_from_S
from optiwindnet.heuristics import constructor
from optiwindnet.MILP import solver_factory, ModelOptions

Initialize Sheringham Shoal¶

[2]:
locations = load_repository()
[3]:
L = locations.sheringham
capacity = 6
[4]:
svgplot(L)
[4]:
../_images/notebooks_25-MILP_scip_example_5_0.svg
[5]:
solver = solver_factory('scip')

Optimize Sheringham Shoal¶

[6]:
P, A = make_planar_embedding(L)

Initial heuristic solution to warm-start the solver:

[7]:
Sʹ = constructor(A, capacity=capacity)
Gʹ = G_from_S(Sʹ, A)
svgplot(Gʹ)
[7]:
../_images/notebooks_25-MILP_scip_example_10_0.svg
[8]:
solver = solver_factory('scip')

If SCIP was compiled with multi-threading capability, multiple concurrent solver instances are started. OptiWindNet’s default options prioritize launching feasibility-focused instances, but the choice of emphasis can be tuned by setting different weights.

OptiWindNet sets the maximum number of concurrent threads ('parallel/maxnthreads') to the number of physical cores by default; assign a different value to solver.options['parallel/maxnthreads'] before set_problem() to override. SCIP may still use a lower number than requested to limit RAM usage.

[9]:
solver.options
[9]:
{'parallel/maxnthreads': 8,
 'concurrent/scip-feas/prefprio': 0.6,
 'concurrent/scip/prefprio': 0.3,
 'concurrent/scip-cpsolver/prefprio': 0,
 'concurrent/scip-easycip/prefprio': 0,
 'concurrent/scip-opti/prefprio': 0}

The latest SCIP Optimization Suite precompiled packages include multi-threading, but the PySCIPOpt wheel must be built on top of the library distributed in that package (see instructions). Latest versions at the time of writing: SCIP 10.0.0, PySCIPOpt 6.0. The conda-forge pyscipopt was at version 5.6.0 and was not concurrency-enabled for all platforms at the time (check latest version).

[10]:
solver.set_problem(
    P, A,
    capacity=Sʹ.graph['capacity'],
    model_options=ModelOptions(
        topology="branched",
        feeder_route="segmented",
        feeder_limit="unlimited",
    ),
    warmstart=Sʹ,
)
[11]:
solver.solve(
    mip_gap=0.005,
    time_limit=60,
)
initializing seeds to 1963210296 in concurrent solver 'scip-2'
initializing seeds to 1332858414 in concurrent solver 'scip-feas-1'
initializing seeds to 1541326760 in concurrent solver 'scip-feas-2'
initializing seeds to 247360965 in concurrent solver 'scip-feas-3'
initializing seeds to 387742462 in concurrent solver 'scip-feas-4'
initializing seeds to 520723434 in concurrent solver 'scip-feas-5'
initializing seeds to 1176648445 in concurrent solver 'scip-3'
starting solve in concurrent solver 'scip-1'
starting solve in concurrent solver 'scip-2'
starting solve in concurrent solver 'scip-feas-1'
starting solve in concurrent solver 'scip-feas-2'
starting solve in concurrent solver 'scip-feas-3'
starting solve in concurrent solver 'scip-feas-4'
starting solve in concurrent solver 'scip-feas-5'
starting solve in concurrent solver 'scip-3'
 60.0s: concurrent solver 'scip-2' stopped with status time limit reached
 60.0s: concurrent solver 'scip-3' stopped with status time limit reached
 60.0s: concurrent solver 'scip-feas-4' stopped with status time limit reached
 60.0s: concurrent solver 'scip-feas-1' stopped with status time limit reached
 60.0s: concurrent solver 'scip-feas-3' stopped with status time limit reached
 60.0s: concurrent solver 'scip-1' stopped with status time limit reached
 60.0s: concurrent solver 'scip-feas-2' stopped with status time limit reached
 60.0s: concurrent solver 'scip-feas-5' stopped with status time limit reached
[11]:
SolutionInfo(runtime=60.487473, bound=60497.94224317833, objective=62598.45029400818, relgap=0.033555272390359936, termination='timelimit')

Note: If SCIP lacks multi-threading capability, a warning will be displayed and it will fall back to the single-threaded solver. The warning about the lack of concurrent capability looks like this:

.../optiwindnet/MILP/scip.py:96: UserWarning: SCIP was compiled without task processing interface. Parallel solve not possible - using optimize() instead of solveConcurrent()
  model.solveConcurrent()
[12]:
S, G = solver.get_solution()
svgplot(G)
[12]:
../_images/notebooks_25-MILP_scip_example_18_0.svg