You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
MIPLearn/0.2/api/miplearn/solvers/internal.html

1141 lines
48 KiB

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<meta name="generator" content="pdoc 0.7.5" />
<title>miplearn.solvers.internal API documentation</title>
<meta name="description" content="" />
<link href='https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.0/normalize.min.css' rel='stylesheet'>
<link href='https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/8.0.0/sanitize.min.css' rel='stylesheet'>
<link href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/github.min.css" rel="stylesheet">
<style>.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{font-weight:bold}#index h4 + ul{margin-bottom:.6em}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
</head>
<body>
<main>
<article id="content">
<header>
<h1 class="title">Module <code>miplearn.solvers.internal</code></h1>
</header>
<section id="section-intro">
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python"># MIPLearn: Extensible Framework for Learning-Enhanced Mixed-Integer Optimization
# Copyright (C) 2020, UChicago Argonne, LLC. All rights reserved.
# Released under the modified BSD license. See COPYING.md for more details.
import logging
from abc import ABC, abstractmethod
from typing import Any, Dict, List, Optional
from miplearn.instance import Instance
from miplearn.types import (
LPSolveStats,
IterationCallback,
LazyCallback,
MIPSolveStats,
VarIndex,
Solution,
BranchPriorities,
Constraint,
)
logger = logging.getLogger(__name__)
class InternalSolver(ABC):
&#34;&#34;&#34;
Abstract class representing the MIP solver used internally by LearningSolver.
&#34;&#34;&#34;
@abstractmethod
def solve_lp(
self,
tee: bool = False,
) -&gt; LPSolveStats:
&#34;&#34;&#34;
Solves the LP relaxation of the currently loaded instance. After this
method finishes, the solution can be retrieved by calling `get_solution`.
This method should not permanently modify the problem. That is, subsequent
calls to `solve` should solve the original MIP, not the LP relaxation.
Parameters
----------
tee
If true, prints the solver log to the screen.
&#34;&#34;&#34;
pass
@abstractmethod
def solve(
self,
tee: bool = False,
iteration_cb: IterationCallback = None,
lazy_cb: LazyCallback = None,
) -&gt; MIPSolveStats:
&#34;&#34;&#34;
Solves the currently loaded instance. After this method finishes,
the best solution found can be retrieved by calling `get_solution`.
Parameters
----------
iteration_cb: IterationCallback
By default, InternalSolver makes a single call to the native `solve`
method and returns the result. If an iteration callback is provided
instead, InternalSolver enters a loop, where `solve` and `iteration_cb`
are called alternatively. To stop the loop, `iteration_cb` should return
False. Any other result causes the solver to loop again.
lazy_cb: LazyCallback
This function is called whenever the solver finds a new candidate
solution and can be used to add lazy constraints to the model. Only the
following operations within the callback are allowed:
- Querying the value of a variable
- Querying if a constraint is satisfied
- Adding a new constraint to the problem
Additional operations may be allowed by specific subclasses.
tee: bool
If true, prints the solver log to the screen.
&#34;&#34;&#34;
pass
@abstractmethod
def get_solution(self) -&gt; Optional[Solution]:
&#34;&#34;&#34;
Returns current solution found by the solver.
If called after `solve`, returns the best primal solution found during
the search. If called after `solve_lp`, returns the optimal solution
to the LP relaxation. If no primal solution is available, return None.
The solution is a dictionary `sol`, where the optimal value of `var[idx]`
is given by `sol[var][idx]`.
&#34;&#34;&#34;
pass
@abstractmethod
def set_warm_start(self, solution: Solution) -&gt; None:
&#34;&#34;&#34;
Sets the warm start to be used by the solver.
The solution should be a dictionary following the same format as the
one produced by `get_solution`. Only one warm start is supported.
Calling this function when a warm start already exists will
remove the previous warm start.
&#34;&#34;&#34;
pass
@abstractmethod
def set_instance(
self,
instance: Instance,
model: Any = None,
) -&gt; None:
&#34;&#34;&#34;
Loads the given instance into the solver.
Parameters
----------
instance: Instance
The instance to be loaded.
model: Any
The concrete optimization model corresponding to this instance
(e.g. JuMP.Model or pyomo.core.ConcreteModel). If not provided,
it will be generated by calling `instance.to_model()`.
&#34;&#34;&#34;
pass
@abstractmethod
def fix(self, solution: Solution) -&gt; None:
&#34;&#34;&#34;
Fixes the values of a subset of decision variables.
The values should be provided in the dictionary format generated by
`get_solution`. Missing values in the solution indicate variables
that should be left free.
&#34;&#34;&#34;
pass
def set_branching_priorities(self, priorities: BranchPriorities) -&gt; None:
&#34;&#34;&#34;
Sets the branching priorities for the given decision variables.
When the MIP solver needs to decide on which variable to branch, variables
with higher priority are picked first, given that they are fractional.
Ties are solved arbitrarily. By default, all variables have priority zero.
The priorities should be provided in the dictionary format generated by
`get_solution`. Missing values indicate variables whose priorities
should not be modified.
&#34;&#34;&#34;
raise Exception(&#34;Not implemented&#34;)
@abstractmethod
def get_constraint_ids(self) -&gt; List[str]:
&#34;&#34;&#34;
Returns a list of ids which uniquely identify each constraint in the model.
&#34;&#34;&#34;
pass
@abstractmethod
def add_constraint(self, cobj: Constraint) -&gt; None:
&#34;&#34;&#34;
Adds a single constraint to the model.
&#34;&#34;&#34;
pass
@abstractmethod
def extract_constraint(self, cid: str) -&gt; Constraint:
&#34;&#34;&#34;
Removes a given constraint from the model and returns an object `cobj` which
can be used to verify if the removed constraint is still satisfied by
the current solution, using `is_constraint_satisfied(cobj)`, and can potentially
be re-added to the model using `add_constraint(cobj)`.
&#34;&#34;&#34;
pass
@abstractmethod
def is_constraint_satisfied(self, cobj: Constraint) -&gt; bool:
&#34;&#34;&#34;
Returns True if the current solution satisfies the given constraint.
&#34;&#34;&#34;
pass
@abstractmethod
def set_constraint_sense(self, cid: str, sense: str) -&gt; None:
&#34;&#34;&#34;
Modifies the sense of a given constraint.
Parameters
----------
cid: str
The name of the constraint.
sense: str
The new sense (either &#34;&lt;&#34;, &#34;&gt;&#34; or &#34;=&#34;).
&#34;&#34;&#34;
pass
@abstractmethod
def get_constraint_sense(self, cid: str) -&gt; str:
&#34;&#34;&#34;
Returns the sense of a given constraint (either &#34;&lt;&#34;, &#34;&gt;&#34; or &#34;=&#34;).
Parameters
----------
cid: str
The name of the constraint.
&#34;&#34;&#34;
pass
@abstractmethod
def get_value(self, var_name: str, index: VarIndex) -&gt; Optional[float]:
&#34;&#34;&#34;
Returns the value of a given variable in the current solution. If no
solution is available, returns None.
&#34;&#34;&#34;
pass
@abstractmethod
def relax(self) -&gt; None:
&#34;&#34;&#34;
Drops all integrality constraints from the model.
&#34;&#34;&#34;
pass
@abstractmethod
def get_inequality_slacks(self) -&gt; Dict[str, float]:
&#34;&#34;&#34;
Returns a dictionary mapping constraint name to the constraint slack
in the current solution.
&#34;&#34;&#34;
pass
@abstractmethod
def is_infeasible(self) -&gt; bool:
&#34;&#34;&#34;
Returns True if the model has been proved to be infeasible.
Must be called after solve.
&#34;&#34;&#34;
pass
@abstractmethod
def get_dual(self, cid: str) -&gt; float:
&#34;&#34;&#34;
If the model is feasible and has been solved to optimality, returns the
optimal value of the dual variable associated with this constraint. If the
model is infeasible, returns a portion of the infeasibility certificate
corresponding to the given constraint.
Only available for relaxed problems. Must be called after solve.
&#34;&#34;&#34;
pass
@abstractmethod
def get_sense(self) -&gt; str:
&#34;&#34;&#34;
Returns the sense of the problem (either &#34;min&#34; or &#34;max&#34;).
&#34;&#34;&#34;
pass
@abstractmethod
def get_empty_solution(self) -&gt; Dict:
&#34;&#34;&#34;
Returns a dictionary with the same shape as the one produced by
`get_solution`, but with all values set to None. This method is
used by the ML components to query what variables are there in
the model before a solution is available.
&#34;&#34;&#34;
pass</code></pre>
</details>
</section>
<section>
</section>
<section>
</section>
<section>
</section>
<section>
<h2 class="section-title" id="header-classes">Classes</h2>
<dl>
<dt id="miplearn.solvers.internal.InternalSolver"><code class="flex name class">
<span>class <span class="ident">InternalSolver</span></span>
</code></dt>
<dd>
<section class="desc"><p>Abstract class representing the MIP solver used internally by LearningSolver.</p></section>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">class InternalSolver(ABC):
&#34;&#34;&#34;
Abstract class representing the MIP solver used internally by LearningSolver.
&#34;&#34;&#34;
@abstractmethod
def solve_lp(
self,
tee: bool = False,
) -&gt; LPSolveStats:
&#34;&#34;&#34;
Solves the LP relaxation of the currently loaded instance. After this
method finishes, the solution can be retrieved by calling `get_solution`.
This method should not permanently modify the problem. That is, subsequent
calls to `solve` should solve the original MIP, not the LP relaxation.
Parameters
----------
tee
If true, prints the solver log to the screen.
&#34;&#34;&#34;
pass
@abstractmethod
def solve(
self,
tee: bool = False,
iteration_cb: IterationCallback = None,
lazy_cb: LazyCallback = None,
) -&gt; MIPSolveStats:
&#34;&#34;&#34;
Solves the currently loaded instance. After this method finishes,
the best solution found can be retrieved by calling `get_solution`.
Parameters
----------
iteration_cb: IterationCallback
By default, InternalSolver makes a single call to the native `solve`
method and returns the result. If an iteration callback is provided
instead, InternalSolver enters a loop, where `solve` and `iteration_cb`
are called alternatively. To stop the loop, `iteration_cb` should return
False. Any other result causes the solver to loop again.
lazy_cb: LazyCallback
This function is called whenever the solver finds a new candidate
solution and can be used to add lazy constraints to the model. Only the
following operations within the callback are allowed:
- Querying the value of a variable
- Querying if a constraint is satisfied
- Adding a new constraint to the problem
Additional operations may be allowed by specific subclasses.
tee: bool
If true, prints the solver log to the screen.
&#34;&#34;&#34;
pass
@abstractmethod
def get_solution(self) -&gt; Optional[Solution]:
&#34;&#34;&#34;
Returns current solution found by the solver.
If called after `solve`, returns the best primal solution found during
the search. If called after `solve_lp`, returns the optimal solution
to the LP relaxation. If no primal solution is available, return None.
The solution is a dictionary `sol`, where the optimal value of `var[idx]`
is given by `sol[var][idx]`.
&#34;&#34;&#34;
pass
@abstractmethod
def set_warm_start(self, solution: Solution) -&gt; None:
&#34;&#34;&#34;
Sets the warm start to be used by the solver.
The solution should be a dictionary following the same format as the
one produced by `get_solution`. Only one warm start is supported.
Calling this function when a warm start already exists will
remove the previous warm start.
&#34;&#34;&#34;
pass
@abstractmethod
def set_instance(
self,
instance: Instance,
model: Any = None,
) -&gt; None:
&#34;&#34;&#34;
Loads the given instance into the solver.
Parameters
----------
instance: Instance
The instance to be loaded.
model: Any
The concrete optimization model corresponding to this instance
(e.g. JuMP.Model or pyomo.core.ConcreteModel). If not provided,
it will be generated by calling `instance.to_model()`.
&#34;&#34;&#34;
pass
@abstractmethod
def fix(self, solution: Solution) -&gt; None:
&#34;&#34;&#34;
Fixes the values of a subset of decision variables.
The values should be provided in the dictionary format generated by
`get_solution`. Missing values in the solution indicate variables
that should be left free.
&#34;&#34;&#34;
pass
def set_branching_priorities(self, priorities: BranchPriorities) -&gt; None:
&#34;&#34;&#34;
Sets the branching priorities for the given decision variables.
When the MIP solver needs to decide on which variable to branch, variables
with higher priority are picked first, given that they are fractional.
Ties are solved arbitrarily. By default, all variables have priority zero.
The priorities should be provided in the dictionary format generated by
`get_solution`. Missing values indicate variables whose priorities
should not be modified.
&#34;&#34;&#34;
raise Exception(&#34;Not implemented&#34;)
@abstractmethod
def get_constraint_ids(self) -&gt; List[str]:
&#34;&#34;&#34;
Returns a list of ids which uniquely identify each constraint in the model.
&#34;&#34;&#34;
pass
@abstractmethod
def add_constraint(self, cobj: Constraint) -&gt; None:
&#34;&#34;&#34;
Adds a single constraint to the model.
&#34;&#34;&#34;
pass
@abstractmethod
def extract_constraint(self, cid: str) -&gt; Constraint:
&#34;&#34;&#34;
Removes a given constraint from the model and returns an object `cobj` which
can be used to verify if the removed constraint is still satisfied by
the current solution, using `is_constraint_satisfied(cobj)`, and can potentially
be re-added to the model using `add_constraint(cobj)`.
&#34;&#34;&#34;
pass
@abstractmethod
def is_constraint_satisfied(self, cobj: Constraint) -&gt; bool:
&#34;&#34;&#34;
Returns True if the current solution satisfies the given constraint.
&#34;&#34;&#34;
pass
@abstractmethod
def set_constraint_sense(self, cid: str, sense: str) -&gt; None:
&#34;&#34;&#34;
Modifies the sense of a given constraint.
Parameters
----------
cid: str
The name of the constraint.
sense: str
The new sense (either &#34;&lt;&#34;, &#34;&gt;&#34; or &#34;=&#34;).
&#34;&#34;&#34;
pass
@abstractmethod
def get_constraint_sense(self, cid: str) -&gt; str:
&#34;&#34;&#34;
Returns the sense of a given constraint (either &#34;&lt;&#34;, &#34;&gt;&#34; or &#34;=&#34;).
Parameters
----------
cid: str
The name of the constraint.
&#34;&#34;&#34;
pass
@abstractmethod
def get_value(self, var_name: str, index: VarIndex) -&gt; Optional[float]:
&#34;&#34;&#34;
Returns the value of a given variable in the current solution. If no
solution is available, returns None.
&#34;&#34;&#34;
pass
@abstractmethod
def relax(self) -&gt; None:
&#34;&#34;&#34;
Drops all integrality constraints from the model.
&#34;&#34;&#34;
pass
@abstractmethod
def get_inequality_slacks(self) -&gt; Dict[str, float]:
&#34;&#34;&#34;
Returns a dictionary mapping constraint name to the constraint slack
in the current solution.
&#34;&#34;&#34;
pass
@abstractmethod
def is_infeasible(self) -&gt; bool:
&#34;&#34;&#34;
Returns True if the model has been proved to be infeasible.
Must be called after solve.
&#34;&#34;&#34;
pass
@abstractmethod
def get_dual(self, cid: str) -&gt; float:
&#34;&#34;&#34;
If the model is feasible and has been solved to optimality, returns the
optimal value of the dual variable associated with this constraint. If the
model is infeasible, returns a portion of the infeasibility certificate
corresponding to the given constraint.
Only available for relaxed problems. Must be called after solve.
&#34;&#34;&#34;
pass
@abstractmethod
def get_sense(self) -&gt; str:
&#34;&#34;&#34;
Returns the sense of the problem (either &#34;min&#34; or &#34;max&#34;).
&#34;&#34;&#34;
pass
@abstractmethod
def get_empty_solution(self) -&gt; Dict:
&#34;&#34;&#34;
Returns a dictionary with the same shape as the one produced by
`get_solution`, but with all values set to None. This method is
used by the ML components to query what variables are there in
the model before a solution is available.
&#34;&#34;&#34;
pass</code></pre>
</details>
<h3>Ancestors</h3>
<ul class="hlist">
<li>abc.ABC</li>
</ul>
<h3>Subclasses</h3>
<ul class="hlist">
<li><a title="miplearn.solvers.gurobi.GurobiSolver" href="gurobi.html#miplearn.solvers.gurobi.GurobiSolver">GurobiSolver</a></li>
<li><a title="miplearn.solvers.pyomo.base.BasePyomoSolver" href="pyomo/base.html#miplearn.solvers.pyomo.base.BasePyomoSolver">BasePyomoSolver</a></li>
</ul>
<h3>Methods</h3>
<dl>
<dt id="miplearn.solvers.internal.InternalSolver.add_constraint"><code class="name flex">
<span>def <span class="ident">add_constraint</span></span>(<span>self, cobj)</span>
</code></dt>
<dd>
<section class="desc"><p>Adds a single constraint to the model.</p></section>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@abstractmethod
def add_constraint(self, cobj: Constraint) -&gt; None:
&#34;&#34;&#34;
Adds a single constraint to the model.
&#34;&#34;&#34;
pass</code></pre>
</details>
</dd>
<dt id="miplearn.solvers.internal.InternalSolver.extract_constraint"><code class="name flex">
<span>def <span class="ident">extract_constraint</span></span>(<span>self, cid)</span>
</code></dt>
<dd>
<section class="desc"><p>Removes a given constraint from the model and returns an object <code>cobj</code> which
can be used to verify if the removed constraint is still satisfied by
the current solution, using <code>is_constraint_satisfied(cobj)</code>, and can potentially
be re-added to the model using <code>add_constraint(cobj)</code>.</p></section>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@abstractmethod
def extract_constraint(self, cid: str) -&gt; Constraint:
&#34;&#34;&#34;
Removes a given constraint from the model and returns an object `cobj` which
can be used to verify if the removed constraint is still satisfied by
the current solution, using `is_constraint_satisfied(cobj)`, and can potentially
be re-added to the model using `add_constraint(cobj)`.
&#34;&#34;&#34;
pass</code></pre>
</details>
</dd>
<dt id="miplearn.solvers.internal.InternalSolver.fix"><code class="name flex">
<span>def <span class="ident">fix</span></span>(<span>self, solution)</span>
</code></dt>
<dd>
<section class="desc"><p>Fixes the values of a subset of decision variables.</p>
<p>The values should be provided in the dictionary format generated by
<code>get_solution</code>. Missing values in the solution indicate variables
that should be left free.</p></section>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@abstractmethod
def fix(self, solution: Solution) -&gt; None:
&#34;&#34;&#34;
Fixes the values of a subset of decision variables.
The values should be provided in the dictionary format generated by
`get_solution`. Missing values in the solution indicate variables
that should be left free.
&#34;&#34;&#34;
pass</code></pre>
</details>
</dd>
<dt id="miplearn.solvers.internal.InternalSolver.get_constraint_ids"><code class="name flex">
<span>def <span class="ident">get_constraint_ids</span></span>(<span>self)</span>
</code></dt>
<dd>
<section class="desc"><p>Returns a list of ids which uniquely identify each constraint in the model.</p></section>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@abstractmethod
def get_constraint_ids(self) -&gt; List[str]:
&#34;&#34;&#34;
Returns a list of ids which uniquely identify each constraint in the model.
&#34;&#34;&#34;
pass</code></pre>
</details>
</dd>
<dt id="miplearn.solvers.internal.InternalSolver.get_constraint_sense"><code class="name flex">
<span>def <span class="ident">get_constraint_sense</span></span>(<span>self, cid)</span>
</code></dt>
<dd>
<section class="desc"><p>Returns the sense of a given constraint (either "&lt;", "&gt;" or "=").</p>
<h2 id="parameters">Parameters</h2>
<dl>
<dt><strong><code>cid</code></strong> :&ensp;<code>str</code></dt>
<dd>The name of the constraint.</dd>
</dl></section>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@abstractmethod
def get_constraint_sense(self, cid: str) -&gt; str:
&#34;&#34;&#34;
Returns the sense of a given constraint (either &#34;&lt;&#34;, &#34;&gt;&#34; or &#34;=&#34;).
Parameters
----------
cid: str
The name of the constraint.
&#34;&#34;&#34;
pass</code></pre>
</details>
</dd>
<dt id="miplearn.solvers.internal.InternalSolver.get_dual"><code class="name flex">
<span>def <span class="ident">get_dual</span></span>(<span>self, cid)</span>
</code></dt>
<dd>
<section class="desc"><p>If the model is feasible and has been solved to optimality, returns the
optimal value of the dual variable associated with this constraint. If the
model is infeasible, returns a portion of the infeasibility certificate
corresponding to the given constraint.</p>
<p>Only available for relaxed problems. Must be called after solve.</p></section>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@abstractmethod
def get_dual(self, cid: str) -&gt; float:
&#34;&#34;&#34;
If the model is feasible and has been solved to optimality, returns the
optimal value of the dual variable associated with this constraint. If the
model is infeasible, returns a portion of the infeasibility certificate
corresponding to the given constraint.
Only available for relaxed problems. Must be called after solve.
&#34;&#34;&#34;
pass</code></pre>
</details>
</dd>
<dt id="miplearn.solvers.internal.InternalSolver.get_empty_solution"><code class="name flex">
<span>def <span class="ident">get_empty_solution</span></span>(<span>self)</span>
</code></dt>
<dd>
<section class="desc"><p>Returns a dictionary with the same shape as the one produced by
<code>get_solution</code>, but with all values set to None. This method is
used by the ML components to query what variables are there in
the model before a solution is available.</p></section>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@abstractmethod
def get_empty_solution(self) -&gt; Dict:
&#34;&#34;&#34;
Returns a dictionary with the same shape as the one produced by
`get_solution`, but with all values set to None. This method is
used by the ML components to query what variables are there in
the model before a solution is available.
&#34;&#34;&#34;
pass</code></pre>
</details>
</dd>
<dt id="miplearn.solvers.internal.InternalSolver.get_inequality_slacks"><code class="name flex">
<span>def <span class="ident">get_inequality_slacks</span></span>(<span>self)</span>
</code></dt>
<dd>
<section class="desc"><p>Returns a dictionary mapping constraint name to the constraint slack
in the current solution.</p></section>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@abstractmethod
def get_inequality_slacks(self) -&gt; Dict[str, float]:
&#34;&#34;&#34;
Returns a dictionary mapping constraint name to the constraint slack
in the current solution.
&#34;&#34;&#34;
pass</code></pre>
</details>
</dd>
<dt id="miplearn.solvers.internal.InternalSolver.get_sense"><code class="name flex">
<span>def <span class="ident">get_sense</span></span>(<span>self)</span>
</code></dt>
<dd>
<section class="desc"><p>Returns the sense of the problem (either "min" or "max").</p></section>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@abstractmethod
def get_sense(self) -&gt; str:
&#34;&#34;&#34;
Returns the sense of the problem (either &#34;min&#34; or &#34;max&#34;).
&#34;&#34;&#34;
pass</code></pre>
</details>
</dd>
<dt id="miplearn.solvers.internal.InternalSolver.get_solution"><code class="name flex">
<span>def <span class="ident">get_solution</span></span>(<span>self)</span>
</code></dt>
<dd>
<section class="desc"><p>Returns current solution found by the solver.</p>
<p>If called after <code>solve</code>, returns the best primal solution found during
the search. If called after <code>solve_lp</code>, returns the optimal solution
to the LP relaxation. If no primal solution is available, return None.</p>
<p>The solution is a dictionary <code>sol</code>, where the optimal value of <code>var[idx]</code>
is given by <code>sol[var][idx]</code>.</p></section>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@abstractmethod
def get_solution(self) -&gt; Optional[Solution]:
&#34;&#34;&#34;
Returns current solution found by the solver.
If called after `solve`, returns the best primal solution found during
the search. If called after `solve_lp`, returns the optimal solution
to the LP relaxation. If no primal solution is available, return None.
The solution is a dictionary `sol`, where the optimal value of `var[idx]`
is given by `sol[var][idx]`.
&#34;&#34;&#34;
pass</code></pre>
</details>
</dd>
<dt id="miplearn.solvers.internal.InternalSolver.get_value"><code class="name flex">
<span>def <span class="ident">get_value</span></span>(<span>self, var_name, index)</span>
</code></dt>
<dd>
<section class="desc"><p>Returns the value of a given variable in the current solution. If no
solution is available, returns None.</p></section>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@abstractmethod
def get_value(self, var_name: str, index: VarIndex) -&gt; Optional[float]:
&#34;&#34;&#34;
Returns the value of a given variable in the current solution. If no
solution is available, returns None.
&#34;&#34;&#34;
pass</code></pre>
</details>
</dd>
<dt id="miplearn.solvers.internal.InternalSolver.is_constraint_satisfied"><code class="name flex">
<span>def <span class="ident">is_constraint_satisfied</span></span>(<span>self, cobj)</span>
</code></dt>
<dd>
<section class="desc"><p>Returns True if the current solution satisfies the given constraint.</p></section>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@abstractmethod
def is_constraint_satisfied(self, cobj: Constraint) -&gt; bool:
&#34;&#34;&#34;
Returns True if the current solution satisfies the given constraint.
&#34;&#34;&#34;
pass</code></pre>
</details>
</dd>
<dt id="miplearn.solvers.internal.InternalSolver.is_infeasible"><code class="name flex">
<span>def <span class="ident">is_infeasible</span></span>(<span>self)</span>
</code></dt>
<dd>
<section class="desc"><p>Returns True if the model has been proved to be infeasible.
Must be called after solve.</p></section>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@abstractmethod
def is_infeasible(self) -&gt; bool:
&#34;&#34;&#34;
Returns True if the model has been proved to be infeasible.
Must be called after solve.
&#34;&#34;&#34;
pass</code></pre>
</details>
</dd>
<dt id="miplearn.solvers.internal.InternalSolver.relax"><code class="name flex">
<span>def <span class="ident">relax</span></span>(<span>self)</span>
</code></dt>
<dd>
<section class="desc"><p>Drops all integrality constraints from the model.</p></section>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@abstractmethod
def relax(self) -&gt; None:
&#34;&#34;&#34;
Drops all integrality constraints from the model.
&#34;&#34;&#34;
pass</code></pre>
</details>
</dd>
<dt id="miplearn.solvers.internal.InternalSolver.set_branching_priorities"><code class="name flex">
<span>def <span class="ident">set_branching_priorities</span></span>(<span>self, priorities)</span>
</code></dt>
<dd>
<section class="desc"><p>Sets the branching priorities for the given decision variables.</p>
<p>When the MIP solver needs to decide on which variable to branch, variables
with higher priority are picked first, given that they are fractional.
Ties are solved arbitrarily. By default, all variables have priority zero.</p>
<p>The priorities should be provided in the dictionary format generated by
<code>get_solution</code>. Missing values indicate variables whose priorities
should not be modified.</p></section>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def set_branching_priorities(self, priorities: BranchPriorities) -&gt; None:
&#34;&#34;&#34;
Sets the branching priorities for the given decision variables.
When the MIP solver needs to decide on which variable to branch, variables
with higher priority are picked first, given that they are fractional.
Ties are solved arbitrarily. By default, all variables have priority zero.
The priorities should be provided in the dictionary format generated by
`get_solution`. Missing values indicate variables whose priorities
should not be modified.
&#34;&#34;&#34;
raise Exception(&#34;Not implemented&#34;)</code></pre>
</details>
</dd>
<dt id="miplearn.solvers.internal.InternalSolver.set_constraint_sense"><code class="name flex">
<span>def <span class="ident">set_constraint_sense</span></span>(<span>self, cid, sense)</span>
</code></dt>
<dd>
<section class="desc"><p>Modifies the sense of a given constraint.</p>
<h2 id="parameters">Parameters</h2>
<dl>
<dt><strong><code>cid</code></strong> :&ensp;<code>str</code></dt>
<dd>The name of the constraint.</dd>
<dt><strong><code>sense</code></strong> :&ensp;<code>str</code></dt>
<dd>The new sense (either "&lt;", "&gt;" or "=").</dd>
</dl></section>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@abstractmethod
def set_constraint_sense(self, cid: str, sense: str) -&gt; None:
&#34;&#34;&#34;
Modifies the sense of a given constraint.
Parameters
----------
cid: str
The name of the constraint.
sense: str
The new sense (either &#34;&lt;&#34;, &#34;&gt;&#34; or &#34;=&#34;).
&#34;&#34;&#34;
pass</code></pre>
</details>
</dd>
<dt id="miplearn.solvers.internal.InternalSolver.set_instance"><code class="name flex">
<span>def <span class="ident">set_instance</span></span>(<span>self, instance, model=None)</span>
</code></dt>
<dd>
<section class="desc"><p>Loads the given instance into the solver.</p>
<h2 id="parameters">Parameters</h2>
<dl>
<dt><strong><code>instance</code></strong> :&ensp;<code>Instance</code></dt>
<dd>The instance to be loaded.</dd>
<dt><strong><code>model</code></strong> :&ensp;<code>Any</code></dt>
<dd>The concrete optimization model corresponding to this instance
(e.g. JuMP.Model or pyomo.core.ConcreteModel). If not provided,
it will be generated by calling <code>instance.to_model()</code>.</dd>
</dl></section>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@abstractmethod
def set_instance(
self,
instance: Instance,
model: Any = None,
) -&gt; None:
&#34;&#34;&#34;
Loads the given instance into the solver.
Parameters
----------
instance: Instance
The instance to be loaded.
model: Any
The concrete optimization model corresponding to this instance
(e.g. JuMP.Model or pyomo.core.ConcreteModel). If not provided,
it will be generated by calling `instance.to_model()`.
&#34;&#34;&#34;
pass</code></pre>
</details>
</dd>
<dt id="miplearn.solvers.internal.InternalSolver.set_warm_start"><code class="name flex">
<span>def <span class="ident">set_warm_start</span></span>(<span>self, solution)</span>
</code></dt>
<dd>
<section class="desc"><p>Sets the warm start to be used by the solver.</p>
<p>The solution should be a dictionary following the same format as the
one produced by <code>get_solution</code>. Only one warm start is supported.
Calling this function when a warm start already exists will
remove the previous warm start.</p></section>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@abstractmethod
def set_warm_start(self, solution: Solution) -&gt; None:
&#34;&#34;&#34;
Sets the warm start to be used by the solver.
The solution should be a dictionary following the same format as the
one produced by `get_solution`. Only one warm start is supported.
Calling this function when a warm start already exists will
remove the previous warm start.
&#34;&#34;&#34;
pass</code></pre>
</details>
</dd>
<dt id="miplearn.solvers.internal.InternalSolver.solve"><code class="name flex">
<span>def <span class="ident">solve</span></span>(<span>self, tee=False, iteration_cb=None, lazy_cb=None)</span>
</code></dt>
<dd>
<section class="desc"><p>Solves the currently loaded instance. After this method finishes,
the best solution found can be retrieved by calling <code>get_solution</code>.</p>
<h2 id="parameters">Parameters</h2>
<dl>
<dt><strong><code>iteration_cb</code></strong> :&ensp;<code>IterationCallback</code></dt>
<dd>By default, InternalSolver makes a single call to the native <code>solve</code>
method and returns the result. If an iteration callback is provided
instead, InternalSolver enters a loop, where <code>solve</code> and <code>iteration_cb</code>
are called alternatively. To stop the loop, <code>iteration_cb</code> should return
False. Any other result causes the solver to loop again.</dd>
<dt><strong><code>lazy_cb</code></strong> :&ensp;<code>LazyCallback</code></dt>
<dd>This function is called whenever the solver finds a new candidate
solution and can be used to add lazy constraints to the model. Only the
following operations within the callback are allowed:
- Querying the value of a variable
- Querying if a constraint is satisfied
- Adding a new constraint to the problem
Additional operations may be allowed by specific subclasses.</dd>
<dt><strong><code>tee</code></strong> :&ensp;<code>bool</code></dt>
<dd>If true, prints the solver log to the screen.</dd>
</dl></section>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@abstractmethod
def solve(
self,
tee: bool = False,
iteration_cb: IterationCallback = None,
lazy_cb: LazyCallback = None,
) -&gt; MIPSolveStats:
&#34;&#34;&#34;
Solves the currently loaded instance. After this method finishes,
the best solution found can be retrieved by calling `get_solution`.
Parameters
----------
iteration_cb: IterationCallback
By default, InternalSolver makes a single call to the native `solve`
method and returns the result. If an iteration callback is provided
instead, InternalSolver enters a loop, where `solve` and `iteration_cb`
are called alternatively. To stop the loop, `iteration_cb` should return
False. Any other result causes the solver to loop again.
lazy_cb: LazyCallback
This function is called whenever the solver finds a new candidate
solution and can be used to add lazy constraints to the model. Only the
following operations within the callback are allowed:
- Querying the value of a variable
- Querying if a constraint is satisfied
- Adding a new constraint to the problem
Additional operations may be allowed by specific subclasses.
tee: bool
If true, prints the solver log to the screen.
&#34;&#34;&#34;
pass</code></pre>
</details>
</dd>
<dt id="miplearn.solvers.internal.InternalSolver.solve_lp"><code class="name flex">
<span>def <span class="ident">solve_lp</span></span>(<span>self, tee=False)</span>
</code></dt>
<dd>
<section class="desc"><p>Solves the LP relaxation of the currently loaded instance. After this
method finishes, the solution can be retrieved by calling <code>get_solution</code>.</p>
<p>This method should not permanently modify the problem. That is, subsequent
calls to <code>solve</code> should solve the original MIP, not the LP relaxation.</p>
<h2 id="parameters">Parameters</h2>
<dl>
<dt><strong><code>tee</code></strong></dt>
<dd>If true, prints the solver log to the screen.</dd>
</dl></section>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@abstractmethod
def solve_lp(
self,
tee: bool = False,
) -&gt; LPSolveStats:
&#34;&#34;&#34;
Solves the LP relaxation of the currently loaded instance. After this
method finishes, the solution can be retrieved by calling `get_solution`.
This method should not permanently modify the problem. That is, subsequent
calls to `solve` should solve the original MIP, not the LP relaxation.
Parameters
----------
tee
If true, prints the solver log to the screen.
&#34;&#34;&#34;
pass</code></pre>
</details>
</dd>
</dl>
</dd>
</dl>
</section>
</article>
<nav id="sidebar">
<h1>Index</h1>
<div class="toc">
<ul></ul>
</div>
<ul id="index">
<li><h3>Super-module</h3>
<ul>
<li><code><a title="miplearn.solvers" href="index.html">miplearn.solvers</a></code></li>
</ul>
</li>
<li><h3><a href="#header-classes">Classes</a></h3>
<ul>
<li>
<h4><code><a title="miplearn.solvers.internal.InternalSolver" href="#miplearn.solvers.internal.InternalSolver">InternalSolver</a></code></h4>
<ul class="">
<li><code><a title="miplearn.solvers.internal.InternalSolver.add_constraint" href="#miplearn.solvers.internal.InternalSolver.add_constraint">add_constraint</a></code></li>
<li><code><a title="miplearn.solvers.internal.InternalSolver.extract_constraint" href="#miplearn.solvers.internal.InternalSolver.extract_constraint">extract_constraint</a></code></li>
<li><code><a title="miplearn.solvers.internal.InternalSolver.fix" href="#miplearn.solvers.internal.InternalSolver.fix">fix</a></code></li>
<li><code><a title="miplearn.solvers.internal.InternalSolver.get_constraint_ids" href="#miplearn.solvers.internal.InternalSolver.get_constraint_ids">get_constraint_ids</a></code></li>
<li><code><a title="miplearn.solvers.internal.InternalSolver.get_constraint_sense" href="#miplearn.solvers.internal.InternalSolver.get_constraint_sense">get_constraint_sense</a></code></li>
<li><code><a title="miplearn.solvers.internal.InternalSolver.get_dual" href="#miplearn.solvers.internal.InternalSolver.get_dual">get_dual</a></code></li>
<li><code><a title="miplearn.solvers.internal.InternalSolver.get_empty_solution" href="#miplearn.solvers.internal.InternalSolver.get_empty_solution">get_empty_solution</a></code></li>
<li><code><a title="miplearn.solvers.internal.InternalSolver.get_inequality_slacks" href="#miplearn.solvers.internal.InternalSolver.get_inequality_slacks">get_inequality_slacks</a></code></li>
<li><code><a title="miplearn.solvers.internal.InternalSolver.get_sense" href="#miplearn.solvers.internal.InternalSolver.get_sense">get_sense</a></code></li>
<li><code><a title="miplearn.solvers.internal.InternalSolver.get_solution" href="#miplearn.solvers.internal.InternalSolver.get_solution">get_solution</a></code></li>
<li><code><a title="miplearn.solvers.internal.InternalSolver.get_value" href="#miplearn.solvers.internal.InternalSolver.get_value">get_value</a></code></li>
<li><code><a title="miplearn.solvers.internal.InternalSolver.is_constraint_satisfied" href="#miplearn.solvers.internal.InternalSolver.is_constraint_satisfied">is_constraint_satisfied</a></code></li>
<li><code><a title="miplearn.solvers.internal.InternalSolver.is_infeasible" href="#miplearn.solvers.internal.InternalSolver.is_infeasible">is_infeasible</a></code></li>
<li><code><a title="miplearn.solvers.internal.InternalSolver.relax" href="#miplearn.solvers.internal.InternalSolver.relax">relax</a></code></li>
<li><code><a title="miplearn.solvers.internal.InternalSolver.set_branching_priorities" href="#miplearn.solvers.internal.InternalSolver.set_branching_priorities">set_branching_priorities</a></code></li>
<li><code><a title="miplearn.solvers.internal.InternalSolver.set_constraint_sense" href="#miplearn.solvers.internal.InternalSolver.set_constraint_sense">set_constraint_sense</a></code></li>
<li><code><a title="miplearn.solvers.internal.InternalSolver.set_instance" href="#miplearn.solvers.internal.InternalSolver.set_instance">set_instance</a></code></li>
<li><code><a title="miplearn.solvers.internal.InternalSolver.set_warm_start" href="#miplearn.solvers.internal.InternalSolver.set_warm_start">set_warm_start</a></code></li>
<li><code><a title="miplearn.solvers.internal.InternalSolver.solve" href="#miplearn.solvers.internal.InternalSolver.solve">solve</a></code></li>
<li><code><a title="miplearn.solvers.internal.InternalSolver.solve_lp" href="#miplearn.solvers.internal.InternalSolver.solve_lp">solve_lp</a></code></li>
</ul>
</li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc"><cite>pdoc</cite> 0.7.5</a>.</p>
</footer>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js"></script>
<script>hljs.initHighlightingOnLoad()</script>
</body>
</html>