Update 0.2 docs

This commit is contained in:
2021-01-21 20:33:01 -06:00
parent ed15ffe119
commit 894f4b4668
74 changed files with 21842 additions and 33 deletions

View File

@@ -0,0 +1,928 @@
<!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.0" />
<title>miplearn.solvers.gurobi 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.gurobi</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
import re
import sys
from io import StringIO
from random import randint
from typing import List, Any, Dict, Optional
from miplearn.instance import Instance
from miplearn.solvers import _RedirectOutput
from miplearn.solvers.internal import (
InternalSolver,
LPSolveStats,
IterationCallback,
LazyCallback,
MIPSolveStats,
)
from miplearn.types import VarIndex, SolverParams, Solution
logger = logging.getLogger(__name__)
class GurobiSolver(InternalSolver):
&#34;&#34;&#34;
An InternalSolver backed by Gurobi&#39;s Python API (without Pyomo).
Parameters
----------
params: Optional[SolverParams]
Parameters to pass to Gurobi. For example, `params={&#34;MIPGap&#34;: 1e-3}`
sets the gap tolerance to 1e-3.
lazy_cb_frequency: int
If 1, calls lazy constraint callbacks whenever an integer solution
is found. If 2, calls it also at every node, after solving the
LP relaxation of that node.
&#34;&#34;&#34;
def __init__(
self,
params: Optional[SolverParams] = None,
lazy_cb_frequency: int = 1,
) -&gt; None:
import gurobipy
if params is None:
params = {}
params[&#34;InfUnbdInfo&#34;] = True
self.gp = gurobipy
self.instance: Optional[Instance] = None
self.model: Optional[&#34;gurobipy.Model&#34;] = None
self.params: SolverParams = params
self._all_vars: Dict = {}
self._bin_vars: Optional[Dict[str, Dict[VarIndex, &#34;gurobipy.Var&#34;]]] = None
self.cb_where: Optional[int] = None
assert lazy_cb_frequency in [1, 2]
if lazy_cb_frequency == 1:
self.lazy_cb_where = [self.gp.GRB.Callback.MIPSOL]
else:
self.lazy_cb_where = [
self.gp.GRB.Callback.MIPSOL,
self.gp.GRB.Callback.MIPNODE,
]
def set_instance(
self,
instance: Instance,
model: Any = None,
) -&gt; None:
self._raise_if_callback()
if model is None:
model = instance.to_model()
assert isinstance(model, self.gp.Model)
self.instance = instance
self.model = model
self.model.update()
self._update_vars()
def _raise_if_callback(self) -&gt; None:
if self.cb_where is not None:
raise Exception(&#34;method cannot be called from a callback&#34;)
def _update_vars(self) -&gt; None:
assert self.model is not None
self._all_vars = {}
self._bin_vars = {}
idx: VarIndex
for var in self.model.getVars():
m = re.search(r&#34;([^[]*)\[(.*)]&#34;, var.varName)
if m is None:
name = var.varName
idx = [0]
else:
name = m.group(1)
parts = m.group(2).split(&#34;,&#34;)
idx = [int(k) if k.isdecimal else k for k in parts]
if len(idx) == 1:
idx = idx[0]
if name not in self._all_vars:
self._all_vars[name] = {}
self._all_vars[name][idx] = var
if var.vtype != &#34;C&#34;:
if name not in self._bin_vars:
self._bin_vars[name] = {}
self._bin_vars[name][idx] = var
def _apply_params(self, streams: List[Any]) -&gt; None:
assert self.model is not None
with _RedirectOutput(streams):
for (name, value) in self.params.items():
self.model.setParam(name, value)
if &#34;seed&#34; not in [k.lower() for k in self.params.keys()]:
self.model.setParam(&#34;Seed&#34;, randint(0, 1_000_000))
def solve_lp(
self,
tee: bool = False,
) -&gt; LPSolveStats:
self._raise_if_callback()
streams: List[Any] = [StringIO()]
if tee:
streams += [sys.stdout]
self._apply_params(streams)
assert self.model is not None
assert self._bin_vars is not None
for (varname, vardict) in self._bin_vars.items():
for (idx, var) in vardict.items():
var.vtype = self.gp.GRB.CONTINUOUS
var.lb = 0.0
var.ub = 1.0
with _RedirectOutput(streams):
self.model.optimize()
for (varname, vardict) in self._bin_vars.items():
for (idx, var) in vardict.items():
var.vtype = self.gp.GRB.BINARY
log = streams[0].getvalue()
opt_value = None
if not self.is_infeasible():
opt_value = self.model.objVal
return {
&#34;Optimal value&#34;: opt_value,
&#34;Log&#34;: log,
}
def solve(
self,
tee: bool = False,
iteration_cb: IterationCallback = None,
lazy_cb: LazyCallback = None,
) -&gt; MIPSolveStats:
self._raise_if_callback()
assert self.model is not None
def cb_wrapper(cb_model, cb_where):
try:
self.cb_where = cb_where
if cb_where in self.lazy_cb_where:
lazy_cb(self, self.model)
except:
logger.exception(&#34;callback error&#34;)
finally:
self.cb_where = None
if lazy_cb:
self.params[&#34;LazyConstraints&#34;] = 1
total_wallclock_time = 0
total_nodes = 0
streams: List[Any] = [StringIO()]
if tee:
streams += [sys.stdout]
self._apply_params(streams)
if iteration_cb is None:
iteration_cb = lambda: False
while True:
with _RedirectOutput(streams):
if lazy_cb is None:
self.model.optimize()
else:
self.model.optimize(cb_wrapper)
total_wallclock_time += self.model.runtime
total_nodes += int(self.model.nodeCount)
should_repeat = iteration_cb()
if not should_repeat:
break
log = streams[0].getvalue()
ub, lb = None, None
sense = &#34;min&#34; if self.model.modelSense == 1 else &#34;max&#34;
if self.model.solCount &gt; 0:
if self.model.modelSense == 1:
lb = self.model.objBound
ub = self.model.objVal
else:
lb = self.model.objVal
ub = self.model.objBound
ws_value = self._extract_warm_start_value(log)
stats: MIPSolveStats = {
&#34;Lower bound&#34;: lb,
&#34;Upper bound&#34;: ub,
&#34;Wallclock time&#34;: total_wallclock_time,
&#34;Nodes&#34;: total_nodes,
&#34;Sense&#34;: sense,
&#34;Log&#34;: log,
&#34;Warm start value&#34;: ws_value,
&#34;LP value&#34;: None,
}
return stats
def get_solution(self) -&gt; Optional[Solution]:
self._raise_if_callback()
assert self.model is not None
if self.model.solCount == 0:
return None
solution: Solution = {}
for (varname, vardict) in self._all_vars.items():
solution[varname] = {}
for (idx, var) in vardict.items():
solution[varname][idx] = var.x
return solution
def set_warm_start(self, solution: Solution) -&gt; None:
self._raise_if_callback()
self._clear_warm_start()
count_fixed, count_total = 0, 0
for (varname, vardict) in solution.items():
for (idx, value) in vardict.items():
count_total += 1
if value is not None:
count_fixed += 1
self._all_vars[varname][idx].start = value
logger.info(
&#34;Setting start values for %d variables (out of %d)&#34;
% (count_fixed, count_total)
)
def get_sense(self) -&gt; str:
assert self.model is not None
if self.model.modelSense == 1:
return &#34;min&#34;
else:
return &#34;max&#34;
def get_value(
self,
var_name: str,
index: VarIndex,
) -&gt; Optional[float]:
var = self._all_vars[var_name][index]
return self._get_value(var)
def is_infeasible(self) -&gt; bool:
assert self.model is not None
return self.model.status in [self.gp.GRB.INFEASIBLE, self.gp.GRB.INF_OR_UNBD]
def get_dual(self, cid: str) -&gt; float:
assert self.model is not None
c = self.model.getConstrByName(cid)
if self.is_infeasible():
return c.farkasDual
else:
return c.pi
def _get_value(self, var: Any) -&gt; Optional[float]:
assert self.model is not None
if self.cb_where == self.gp.GRB.Callback.MIPSOL:
return self.model.cbGetSolution(var)
elif self.cb_where == self.gp.GRB.Callback.MIPNODE:
return self.model.cbGetNodeRel(var)
elif self.cb_where is None:
if self.is_infeasible():
return None
else:
return var.x
else:
raise Exception(
&#34;get_value cannot be called from cb_where=%s&#34; % self.cb_where
)
def get_empty_solution(self) -&gt; Solution:
self._raise_if_callback()
solution: Solution = {}
for (varname, vardict) in self._all_vars.items():
solution[varname] = {}
for (idx, var) in vardict.items():
solution[varname][idx] = None
return solution
def add_constraint(
self,
constraint: Any,
name: str = &#34;&#34;,
) -&gt; None:
assert self.model is not None
if type(constraint) is tuple:
lhs, sense, rhs, name = constraint
if self.cb_where in [
self.gp.GRB.Callback.MIPSOL,
self.gp.GRB.Callback.MIPNODE,
]:
self.model.cbLazy(lhs, sense, rhs)
else:
self.model.addConstr(lhs, sense, rhs, name)
else:
if self.cb_where in [
self.gp.GRB.Callback.MIPSOL,
self.gp.GRB.Callback.MIPNODE,
]:
self.model.cbLazy(constraint)
else:
self.model.addConstr(constraint, name=name)
def _clear_warm_start(self) -&gt; None:
for (varname, vardict) in self._all_vars.items():
for (idx, var) in vardict.items():
var.start = self.gp.GRB.UNDEFINED
def fix(self, solution: Solution) -&gt; None:
self._raise_if_callback()
for (varname, vardict) in solution.items():
for (idx, value) in vardict.items():
if value is None:
continue
var = self._all_vars[varname][idx]
var.vtype = self.gp.GRB.CONTINUOUS
var.lb = value
var.ub = value
def get_constraint_ids(self):
self._raise_if_callback()
self.model.update()
return [c.ConstrName for c in self.model.getConstrs()]
def extract_constraint(self, cid):
self._raise_if_callback()
constr = self.model.getConstrByName(cid)
cobj = (self.model.getRow(constr), constr.sense, constr.RHS, constr.ConstrName)
self.model.remove(constr)
return cobj
def is_constraint_satisfied(self, cobj, tol=1e-5):
lhs, sense, rhs, name = cobj
if self.cb_where is not None:
lhs_value = lhs.getConstant()
for i in range(lhs.size()):
var = lhs.getVar(i)
coeff = lhs.getCoeff(i)
lhs_value += self._get_value(var) * coeff
else:
lhs_value = lhs.getValue()
if sense == &#34;&lt;&#34;:
return lhs_value &lt;= rhs + tol
elif sense == &#34;&gt;&#34;:
return lhs_value &gt;= rhs - tol
elif sense == &#34;=&#34;:
return abs(rhs - lhs_value) &lt; abs(tol)
else:
raise Exception(&#34;Unknown sense: %s&#34; % sense)
def get_inequality_slacks(self) -&gt; Dict[str, float]:
assert self.model is not None
ineqs = [c for c in self.model.getConstrs() if c.sense != &#34;=&#34;]
return {c.ConstrName: c.Slack for c in ineqs}
def set_constraint_sense(self, cid: str, sense: str) -&gt; None:
assert self.model is not None
c = self.model.getConstrByName(cid)
c.Sense = sense
def get_constraint_sense(self, cid: str) -&gt; str:
assert self.model is not None
c = self.model.getConstrByName(cid)
return c.Sense
def relax(self) -&gt; None:
assert self.model is not None
self.model = self.model.relax()
self._update_vars()
def _extract_warm_start_value(self, log: str) -&gt; Optional[float]:
ws = self.__extract(log, &#34;MIP start with objective ([0-9.e+-]*)&#34;)
if ws is None:
return None
return float(ws)
@staticmethod
def __extract(
log: str,
regexp: str,
default: Optional[str] = None,
) -&gt; Optional[str]:
value = default
for line in log.splitlines():
matches = re.findall(regexp, line)
if len(matches) == 0:
continue
value = matches[0]
return value
def __getstate__(self):
return {
&#34;params&#34;: self.params,
&#34;lazy_cb_where&#34;: self.lazy_cb_where,
}
def __setstate__(self, state):
self.params = state[&#34;params&#34;]
self.lazy_cb_where = state[&#34;lazy_cb_where&#34;]
self.instance = None
self.model = None
self._all_vars = None
self._bin_vars = None
self.cb_where = None</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.gurobi.GurobiSolver"><code class="flex name class">
<span>class <span class="ident">GurobiSolver</span></span>
<span>(</span><span>params=None, lazy_cb_frequency=1)</span>
</code></dt>
<dd>
<section class="desc"><p>An InternalSolver backed by Gurobi's Python API (without Pyomo).</p>
<h2 id="parameters">Parameters</h2>
<dl>
<dt><strong><code>params</code></strong> :&ensp;<code>Optional</code>[<code>SolverParams</code>]</dt>
<dd>Parameters to pass to Gurobi. For example, <code>params={"MIPGap": 1e-3}</code>
sets the gap tolerance to 1e-3.</dd>
<dt><strong><code>lazy_cb_frequency</code></strong> :&ensp;<code>int</code></dt>
<dd>If 1, calls lazy constraint callbacks whenever an integer solution
is found. If 2, calls it also at every node, after solving the
LP relaxation of that node.</dd>
</dl></section>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">class GurobiSolver(InternalSolver):
&#34;&#34;&#34;
An InternalSolver backed by Gurobi&#39;s Python API (without Pyomo).
Parameters
----------
params: Optional[SolverParams]
Parameters to pass to Gurobi. For example, `params={&#34;MIPGap&#34;: 1e-3}`
sets the gap tolerance to 1e-3.
lazy_cb_frequency: int
If 1, calls lazy constraint callbacks whenever an integer solution
is found. If 2, calls it also at every node, after solving the
LP relaxation of that node.
&#34;&#34;&#34;
def __init__(
self,
params: Optional[SolverParams] = None,
lazy_cb_frequency: int = 1,
) -&gt; None:
import gurobipy
if params is None:
params = {}
params[&#34;InfUnbdInfo&#34;] = True
self.gp = gurobipy
self.instance: Optional[Instance] = None
self.model: Optional[&#34;gurobipy.Model&#34;] = None
self.params: SolverParams = params
self._all_vars: Dict = {}
self._bin_vars: Optional[Dict[str, Dict[VarIndex, &#34;gurobipy.Var&#34;]]] = None
self.cb_where: Optional[int] = None
assert lazy_cb_frequency in [1, 2]
if lazy_cb_frequency == 1:
self.lazy_cb_where = [self.gp.GRB.Callback.MIPSOL]
else:
self.lazy_cb_where = [
self.gp.GRB.Callback.MIPSOL,
self.gp.GRB.Callback.MIPNODE,
]
def set_instance(
self,
instance: Instance,
model: Any = None,
) -&gt; None:
self._raise_if_callback()
if model is None:
model = instance.to_model()
assert isinstance(model, self.gp.Model)
self.instance = instance
self.model = model
self.model.update()
self._update_vars()
def _raise_if_callback(self) -&gt; None:
if self.cb_where is not None:
raise Exception(&#34;method cannot be called from a callback&#34;)
def _update_vars(self) -&gt; None:
assert self.model is not None
self._all_vars = {}
self._bin_vars = {}
idx: VarIndex
for var in self.model.getVars():
m = re.search(r&#34;([^[]*)\[(.*)]&#34;, var.varName)
if m is None:
name = var.varName
idx = [0]
else:
name = m.group(1)
parts = m.group(2).split(&#34;,&#34;)
idx = [int(k) if k.isdecimal else k for k in parts]
if len(idx) == 1:
idx = idx[0]
if name not in self._all_vars:
self._all_vars[name] = {}
self._all_vars[name][idx] = var
if var.vtype != &#34;C&#34;:
if name not in self._bin_vars:
self._bin_vars[name] = {}
self._bin_vars[name][idx] = var
def _apply_params(self, streams: List[Any]) -&gt; None:
assert self.model is not None
with _RedirectOutput(streams):
for (name, value) in self.params.items():
self.model.setParam(name, value)
if &#34;seed&#34; not in [k.lower() for k in self.params.keys()]:
self.model.setParam(&#34;Seed&#34;, randint(0, 1_000_000))
def solve_lp(
self,
tee: bool = False,
) -&gt; LPSolveStats:
self._raise_if_callback()
streams: List[Any] = [StringIO()]
if tee:
streams += [sys.stdout]
self._apply_params(streams)
assert self.model is not None
assert self._bin_vars is not None
for (varname, vardict) in self._bin_vars.items():
for (idx, var) in vardict.items():
var.vtype = self.gp.GRB.CONTINUOUS
var.lb = 0.0
var.ub = 1.0
with _RedirectOutput(streams):
self.model.optimize()
for (varname, vardict) in self._bin_vars.items():
for (idx, var) in vardict.items():
var.vtype = self.gp.GRB.BINARY
log = streams[0].getvalue()
opt_value = None
if not self.is_infeasible():
opt_value = self.model.objVal
return {
&#34;Optimal value&#34;: opt_value,
&#34;Log&#34;: log,
}
def solve(
self,
tee: bool = False,
iteration_cb: IterationCallback = None,
lazy_cb: LazyCallback = None,
) -&gt; MIPSolveStats:
self._raise_if_callback()
assert self.model is not None
def cb_wrapper(cb_model, cb_where):
try:
self.cb_where = cb_where
if cb_where in self.lazy_cb_where:
lazy_cb(self, self.model)
except:
logger.exception(&#34;callback error&#34;)
finally:
self.cb_where = None
if lazy_cb:
self.params[&#34;LazyConstraints&#34;] = 1
total_wallclock_time = 0
total_nodes = 0
streams: List[Any] = [StringIO()]
if tee:
streams += [sys.stdout]
self._apply_params(streams)
if iteration_cb is None:
iteration_cb = lambda: False
while True:
with _RedirectOutput(streams):
if lazy_cb is None:
self.model.optimize()
else:
self.model.optimize(cb_wrapper)
total_wallclock_time += self.model.runtime
total_nodes += int(self.model.nodeCount)
should_repeat = iteration_cb()
if not should_repeat:
break
log = streams[0].getvalue()
ub, lb = None, None
sense = &#34;min&#34; if self.model.modelSense == 1 else &#34;max&#34;
if self.model.solCount &gt; 0:
if self.model.modelSense == 1:
lb = self.model.objBound
ub = self.model.objVal
else:
lb = self.model.objVal
ub = self.model.objBound
ws_value = self._extract_warm_start_value(log)
stats: MIPSolveStats = {
&#34;Lower bound&#34;: lb,
&#34;Upper bound&#34;: ub,
&#34;Wallclock time&#34;: total_wallclock_time,
&#34;Nodes&#34;: total_nodes,
&#34;Sense&#34;: sense,
&#34;Log&#34;: log,
&#34;Warm start value&#34;: ws_value,
&#34;LP value&#34;: None,
}
return stats
def get_solution(self) -&gt; Optional[Solution]:
self._raise_if_callback()
assert self.model is not None
if self.model.solCount == 0:
return None
solution: Solution = {}
for (varname, vardict) in self._all_vars.items():
solution[varname] = {}
for (idx, var) in vardict.items():
solution[varname][idx] = var.x
return solution
def set_warm_start(self, solution: Solution) -&gt; None:
self._raise_if_callback()
self._clear_warm_start()
count_fixed, count_total = 0, 0
for (varname, vardict) in solution.items():
for (idx, value) in vardict.items():
count_total += 1
if value is not None:
count_fixed += 1
self._all_vars[varname][idx].start = value
logger.info(
&#34;Setting start values for %d variables (out of %d)&#34;
% (count_fixed, count_total)
)
def get_sense(self) -&gt; str:
assert self.model is not None
if self.model.modelSense == 1:
return &#34;min&#34;
else:
return &#34;max&#34;
def get_value(
self,
var_name: str,
index: VarIndex,
) -&gt; Optional[float]:
var = self._all_vars[var_name][index]
return self._get_value(var)
def is_infeasible(self) -&gt; bool:
assert self.model is not None
return self.model.status in [self.gp.GRB.INFEASIBLE, self.gp.GRB.INF_OR_UNBD]
def get_dual(self, cid: str) -&gt; float:
assert self.model is not None
c = self.model.getConstrByName(cid)
if self.is_infeasible():
return c.farkasDual
else:
return c.pi
def _get_value(self, var: Any) -&gt; Optional[float]:
assert self.model is not None
if self.cb_where == self.gp.GRB.Callback.MIPSOL:
return self.model.cbGetSolution(var)
elif self.cb_where == self.gp.GRB.Callback.MIPNODE:
return self.model.cbGetNodeRel(var)
elif self.cb_where is None:
if self.is_infeasible():
return None
else:
return var.x
else:
raise Exception(
&#34;get_value cannot be called from cb_where=%s&#34; % self.cb_where
)
def get_empty_solution(self) -&gt; Solution:
self._raise_if_callback()
solution: Solution = {}
for (varname, vardict) in self._all_vars.items():
solution[varname] = {}
for (idx, var) in vardict.items():
solution[varname][idx] = None
return solution
def add_constraint(
self,
constraint: Any,
name: str = &#34;&#34;,
) -&gt; None:
assert self.model is not None
if type(constraint) is tuple:
lhs, sense, rhs, name = constraint
if self.cb_where in [
self.gp.GRB.Callback.MIPSOL,
self.gp.GRB.Callback.MIPNODE,
]:
self.model.cbLazy(lhs, sense, rhs)
else:
self.model.addConstr(lhs, sense, rhs, name)
else:
if self.cb_where in [
self.gp.GRB.Callback.MIPSOL,
self.gp.GRB.Callback.MIPNODE,
]:
self.model.cbLazy(constraint)
else:
self.model.addConstr(constraint, name=name)
def _clear_warm_start(self) -&gt; None:
for (varname, vardict) in self._all_vars.items():
for (idx, var) in vardict.items():
var.start = self.gp.GRB.UNDEFINED
def fix(self, solution: Solution) -&gt; None:
self._raise_if_callback()
for (varname, vardict) in solution.items():
for (idx, value) in vardict.items():
if value is None:
continue
var = self._all_vars[varname][idx]
var.vtype = self.gp.GRB.CONTINUOUS
var.lb = value
var.ub = value
def get_constraint_ids(self):
self._raise_if_callback()
self.model.update()
return [c.ConstrName for c in self.model.getConstrs()]
def extract_constraint(self, cid):
self._raise_if_callback()
constr = self.model.getConstrByName(cid)
cobj = (self.model.getRow(constr), constr.sense, constr.RHS, constr.ConstrName)
self.model.remove(constr)
return cobj
def is_constraint_satisfied(self, cobj, tol=1e-5):
lhs, sense, rhs, name = cobj
if self.cb_where is not None:
lhs_value = lhs.getConstant()
for i in range(lhs.size()):
var = lhs.getVar(i)
coeff = lhs.getCoeff(i)
lhs_value += self._get_value(var) * coeff
else:
lhs_value = lhs.getValue()
if sense == &#34;&lt;&#34;:
return lhs_value &lt;= rhs + tol
elif sense == &#34;&gt;&#34;:
return lhs_value &gt;= rhs - tol
elif sense == &#34;=&#34;:
return abs(rhs - lhs_value) &lt; abs(tol)
else:
raise Exception(&#34;Unknown sense: %s&#34; % sense)
def get_inequality_slacks(self) -&gt; Dict[str, float]:
assert self.model is not None
ineqs = [c for c in self.model.getConstrs() if c.sense != &#34;=&#34;]
return {c.ConstrName: c.Slack for c in ineqs}
def set_constraint_sense(self, cid: str, sense: str) -&gt; None:
assert self.model is not None
c = self.model.getConstrByName(cid)
c.Sense = sense
def get_constraint_sense(self, cid: str) -&gt; str:
assert self.model is not None
c = self.model.getConstrByName(cid)
return c.Sense
def relax(self) -&gt; None:
assert self.model is not None
self.model = self.model.relax()
self._update_vars()
def _extract_warm_start_value(self, log: str) -&gt; Optional[float]:
ws = self.__extract(log, &#34;MIP start with objective ([0-9.e+-]*)&#34;)
if ws is None:
return None
return float(ws)
@staticmethod
def __extract(
log: str,
regexp: str,
default: Optional[str] = None,
) -&gt; Optional[str]:
value = default
for line in log.splitlines():
matches = re.findall(regexp, line)
if len(matches) == 0:
continue
value = matches[0]
return value
def __getstate__(self):
return {
&#34;params&#34;: self.params,
&#34;lazy_cb_where&#34;: self.lazy_cb_where,
}
def __setstate__(self, state):
self.params = state[&#34;params&#34;]
self.lazy_cb_where = state[&#34;lazy_cb_where&#34;]
self.instance = None
self.model = None
self._all_vars = None
self._bin_vars = None
self.cb_where = None</code></pre>
</details>
<h3>Ancestors</h3>
<ul class="hlist">
<li><a title="miplearn.solvers.internal.InternalSolver" href="internal.html#miplearn.solvers.internal.InternalSolver">InternalSolver</a></li>
<li>abc.ABC</li>
</ul>
<h3>Inherited members</h3>
<ul class="hlist">
<li><code><b><a title="miplearn.solvers.internal.InternalSolver" href="internal.html#miplearn.solvers.internal.InternalSolver">InternalSolver</a></b></code>:
<ul class="hlist">
<li><code><a title="miplearn.solvers.internal.InternalSolver.add_constraint" href="internal.html#miplearn.solvers.internal.InternalSolver.add_constraint">add_constraint</a></code></li>
<li><code><a title="miplearn.solvers.internal.InternalSolver.extract_constraint" href="internal.html#miplearn.solvers.internal.InternalSolver.extract_constraint">extract_constraint</a></code></li>
<li><code><a title="miplearn.solvers.internal.InternalSolver.fix" href="internal.html#miplearn.solvers.internal.InternalSolver.fix">fix</a></code></li>
<li><code><a title="miplearn.solvers.internal.InternalSolver.get_constraint_ids" href="internal.html#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="internal.html#miplearn.solvers.internal.InternalSolver.get_constraint_sense">get_constraint_sense</a></code></li>
<li><code><a title="miplearn.solvers.internal.InternalSolver.get_dual" href="internal.html#miplearn.solvers.internal.InternalSolver.get_dual">get_dual</a></code></li>
<li><code><a title="miplearn.solvers.internal.InternalSolver.get_empty_solution" href="internal.html#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="internal.html#miplearn.solvers.internal.InternalSolver.get_inequality_slacks">get_inequality_slacks</a></code></li>
<li><code><a title="miplearn.solvers.internal.InternalSolver.get_sense" href="internal.html#miplearn.solvers.internal.InternalSolver.get_sense">get_sense</a></code></li>
<li><code><a title="miplearn.solvers.internal.InternalSolver.get_solution" href="internal.html#miplearn.solvers.internal.InternalSolver.get_solution">get_solution</a></code></li>
<li><code><a title="miplearn.solvers.internal.InternalSolver.get_value" href="internal.html#miplearn.solvers.internal.InternalSolver.get_value">get_value</a></code></li>
<li><code><a title="miplearn.solvers.internal.InternalSolver.is_constraint_satisfied" href="internal.html#miplearn.solvers.internal.InternalSolver.is_constraint_satisfied">is_constraint_satisfied</a></code></li>
<li><code><a title="miplearn.solvers.internal.InternalSolver.is_infeasible" href="internal.html#miplearn.solvers.internal.InternalSolver.is_infeasible">is_infeasible</a></code></li>
<li><code><a title="miplearn.solvers.internal.InternalSolver.relax" href="internal.html#miplearn.solvers.internal.InternalSolver.relax">relax</a></code></li>
<li><code><a title="miplearn.solvers.internal.InternalSolver.set_branching_priorities" href="internal.html#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="internal.html#miplearn.solvers.internal.InternalSolver.set_constraint_sense">set_constraint_sense</a></code></li>
<li><code><a title="miplearn.solvers.internal.InternalSolver.set_instance" href="internal.html#miplearn.solvers.internal.InternalSolver.set_instance">set_instance</a></code></li>
<li><code><a title="miplearn.solvers.internal.InternalSolver.set_warm_start" href="internal.html#miplearn.solvers.internal.InternalSolver.set_warm_start">set_warm_start</a></code></li>
<li><code><a title="miplearn.solvers.internal.InternalSolver.solve" href="internal.html#miplearn.solvers.internal.InternalSolver.solve">solve</a></code></li>
<li><code><a title="miplearn.solvers.internal.InternalSolver.solve_lp" href="internal.html#miplearn.solvers.internal.InternalSolver.solve_lp">solve_lp</a></code></li>
</ul>
</li>
</ul>
</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.gurobi.GurobiSolver" href="#miplearn.solvers.gurobi.GurobiSolver">GurobiSolver</a></code></h4>
</li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc"><cite>pdoc</cite> 0.7.0</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>

View File

@@ -0,0 +1,123 @@
<!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.0" />
<title>miplearn.solvers 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</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
import sys
from typing import Any, List
logger = logging.getLogger(__name__)
class _RedirectOutput:
def __init__(self, streams: List[Any]):
self.streams = streams
def write(self, data: Any) -&gt; None:
for stream in self.streams:
stream.write(data)
def flush(self) -&gt; None:
for stream in self.streams:
stream.flush()
def __enter__(self):
self._original_stdout = sys.stdout
self._original_stderr = sys.stderr
sys.stdout = self
sys.stderr = self
return self
def __exit__(self, _type, _value, _traceback):
sys.stdout = self._original_stdout
sys.stderr = self._original_stderr</code></pre>
</details>
</section>
<section>
<h2 class="section-title" id="header-submodules">Sub-modules</h2>
<dl>
<dt><code class="name"><a title="miplearn.solvers.gurobi" href="gurobi.html">miplearn.solvers.gurobi</a></code></dt>
<dd>
<section class="desc"></section>
</dd>
<dt><code class="name"><a title="miplearn.solvers.internal" href="internal.html">miplearn.solvers.internal</a></code></dt>
<dd>
<section class="desc"></section>
</dd>
<dt><code class="name"><a title="miplearn.solvers.learning" href="learning.html">miplearn.solvers.learning</a></code></dt>
<dd>
<section class="desc"></section>
</dd>
<dt><code class="name"><a title="miplearn.solvers.pyomo" href="pyomo/index.html">miplearn.solvers.pyomo</a></code></dt>
<dd>
<section class="desc"></section>
</dd>
<dt><code class="name"><a title="miplearn.solvers.tests" href="tests/index.html">miplearn.solvers.tests</a></code></dt>
<dd>
<section class="desc"></section>
</dd>
</dl>
</section>
<section>
</section>
<section>
</section>
<section>
</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" href="../index.html">miplearn</a></code></li>
</ul>
</li>
<li><h3><a href="#header-submodules">Sub-modules</a></h3>
<ul>
<li><code><a title="miplearn.solvers.gurobi" href="gurobi.html">miplearn.solvers.gurobi</a></code></li>
<li><code><a title="miplearn.solvers.internal" href="internal.html">miplearn.solvers.internal</a></code></li>
<li><code><a title="miplearn.solvers.learning" href="learning.html">miplearn.solvers.learning</a></code></li>
<li><code><a title="miplearn.solvers.pyomo" href="pyomo/index.html">miplearn.solvers.pyomo</a></code></li>
<li><code><a title="miplearn.solvers.tests" href="tests/index.html">miplearn.solvers.tests</a></code></li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc"><cite>pdoc</cite> 0.7.0</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>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,730 @@
<!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.0" />
<title>miplearn.solvers.pyomo.base 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.pyomo.base</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
import re
import sys
from io import StringIO
from typing import Any, List, Dict, Optional
import pyomo
from pyomo import environ as pe
from pyomo.core import Var, Constraint
from pyomo.opt import TerminationCondition
from pyomo.opt.base.solvers import SolverFactory
from miplearn.instance import Instance
from miplearn.solvers import _RedirectOutput
from miplearn.solvers.internal import (
InternalSolver,
LPSolveStats,
IterationCallback,
LazyCallback,
MIPSolveStats,
)
from miplearn.types import VarIndex, SolverParams, Solution
logger = logging.getLogger(__name__)
class BasePyomoSolver(InternalSolver):
&#34;&#34;&#34;
Base class for all Pyomo solvers.
&#34;&#34;&#34;
def __init__(
self,
solver_factory: SolverFactory,
params: SolverParams,
) -&gt; None:
self.instance: Optional[Instance] = None
self.model: Optional[pe.ConcreteModel] = None
self._all_vars: List[pe.Var] = []
self._bin_vars: List[pe.Var] = []
self._is_warm_start_available: bool = False
self._pyomo_solver: SolverFactory = solver_factory
self._obj_sense: str = &#34;min&#34;
self._varname_to_var: Dict[str, pe.Var] = {}
self._cname_to_constr: Dict[str, pe.Constraint] = {}
self._termination_condition: str = &#34;&#34;
for (key, value) in params.items():
self._pyomo_solver.options[key] = value
def solve_lp(
self,
tee: bool = False,
) -&gt; LPSolveStats:
self.relax()
streams: List[Any] = [StringIO()]
if tee:
streams += [sys.stdout]
with _RedirectOutput(streams):
results = self._pyomo_solver.solve(tee=True)
self._restore_integrality()
opt_value = None
if not self.is_infeasible():
opt_value = results[&#34;Problem&#34;][0][&#34;Lower bound&#34;]
return {
&#34;Optimal value&#34;: opt_value,
&#34;Log&#34;: streams[0].getvalue(),
}
def _restore_integrality(self) -&gt; None:
for var in self._bin_vars:
var.domain = pyomo.core.base.set_types.Binary
self._pyomo_solver.update_var(var)
def solve(
self,
tee: bool = False,
iteration_cb: IterationCallback = None,
lazy_cb: LazyCallback = None,
) -&gt; MIPSolveStats:
if lazy_cb is not None:
raise Exception(&#34;lazy callback not supported&#34;)
total_wallclock_time = 0
streams: List[Any] = [StringIO()]
if tee:
streams += [sys.stdout]
if iteration_cb is None:
iteration_cb = lambda: False
while True:
logger.debug(&#34;Solving MIP...&#34;)
with _RedirectOutput(streams):
results = self._pyomo_solver.solve(
tee=True,
warmstart=self._is_warm_start_available,
)
total_wallclock_time += results[&#34;Solver&#34;][0][&#34;Wallclock time&#34;]
should_repeat = iteration_cb()
if not should_repeat:
break
log = streams[0].getvalue()
node_count = self._extract_node_count(log)
ws_value = self._extract_warm_start_value(log)
self._termination_condition = results[&#34;Solver&#34;][0][&#34;Termination condition&#34;]
lb, ub = None, None
if not self.is_infeasible():
lb = results[&#34;Problem&#34;][0][&#34;Lower bound&#34;]
ub = results[&#34;Problem&#34;][0][&#34;Upper bound&#34;]
stats: MIPSolveStats = {
&#34;Lower bound&#34;: lb,
&#34;Upper bound&#34;: ub,
&#34;Wallclock time&#34;: total_wallclock_time,
&#34;Sense&#34;: self._obj_sense,
&#34;Log&#34;: log,
&#34;Nodes&#34;: node_count,
&#34;Warm start value&#34;: ws_value,
&#34;LP value&#34;: None,
}
return stats
def get_solution(self) -&gt; Optional[Solution]:
assert self.model is not None
if self.is_infeasible():
return None
solution: Solution = {}
for var in self.model.component_objects(Var):
solution[str(var)] = {}
for index in var:
if var[index].fixed:
continue
solution[str(var)][index] = var[index].value
return solution
def set_warm_start(self, solution: Solution) -&gt; None:
self._clear_warm_start()
count_total, count_fixed = 0, 0
for var_name in solution:
var = self._varname_to_var[var_name]
for index in solution[var_name]:
count_total += 1
var[index].value = solution[var_name][index]
if solution[var_name][index] is not None:
count_fixed += 1
if count_fixed &gt; 0:
self._is_warm_start_available = True
logger.info(
&#34;Setting start values for %d variables (out of %d)&#34;
% (count_fixed, count_total)
)
def set_instance(
self,
instance: Instance,
model: Any = None,
) -&gt; None:
if model is None:
model = instance.to_model()
assert isinstance(model, pe.ConcreteModel)
self.instance = instance
self.model = model
self._pyomo_solver.set_instance(model)
self._update_obj()
self._update_vars()
self._update_constrs()
def get_value(self, var_name: str, index: VarIndex) -&gt; Optional[float]:
if self.is_infeasible():
return None
else:
var = self._varname_to_var[var_name]
return var[index].value
def get_empty_solution(self) -&gt; Solution:
assert self.model is not None
solution: Solution = {}
for var in self.model.component_objects(Var):
svar = str(var)
solution[svar] = {}
for index in var:
if var[index].fixed:
continue
solution[svar][index] = None
return solution
def _clear_warm_start(self) -&gt; None:
for var in self._all_vars:
if not var.fixed:
var.value = None
self._is_warm_start_available = False
def _update_obj(self) -&gt; None:
self._obj_sense = &#34;max&#34;
if self._pyomo_solver._objective.sense == pyomo.core.kernel.objective.minimize:
self._obj_sense = &#34;min&#34;
def _update_vars(self) -&gt; None:
assert self.model is not None
self._all_vars = []
self._bin_vars = []
self._varname_to_var = {}
for var in self.model.component_objects(Var):
self._varname_to_var[var.name] = var
for idx in var:
self._all_vars += [var[idx]]
if var[idx].domain == pyomo.core.base.set_types.Binary:
self._bin_vars += [var[idx]]
def _update_constrs(self) -&gt; None:
assert self.model is not None
self._cname_to_constr = {}
for constr in self.model.component_objects(Constraint):
self._cname_to_constr[constr.name] = constr
def fix(self, solution):
count_total, count_fixed = 0, 0
for varname in solution:
for index in solution[varname]:
var = self._varname_to_var[varname]
count_total += 1
if solution[varname][index] is None:
continue
count_fixed += 1
var[index].fix(solution[varname][index])
self._pyomo_solver.update_var(var[index])
logger.info(
&#34;Fixing values for %d variables (out of %d)&#34;
% (
count_fixed,
count_total,
)
)
def add_constraint(self, constraint):
self._pyomo_solver.add_constraint(constraint)
self._update_constrs()
@staticmethod
def __extract(
log: str,
regexp: Optional[str],
default: Optional[str] = None,
) -&gt; Optional[str]:
if regexp is None:
return default
value = default
for line in log.splitlines():
matches = re.findall(regexp, line)
if len(matches) == 0:
continue
value = matches[0]
return value
def _extract_warm_start_value(self, log: str) -&gt; Optional[float]:
value = self.__extract(log, self._get_warm_start_regexp())
if value is None:
return None
return float(value)
def _extract_node_count(self, log: str) -&gt; Optional[int]:
value = self.__extract(log, self._get_node_count_regexp())
if value is None:
return None
return int(value)
def get_constraint_ids(self):
return list(self._cname_to_constr.keys())
def _get_warm_start_regexp(self) -&gt; Optional[str]:
return None
def _get_node_count_regexp(self) -&gt; Optional[str]:
return None
def relax(self) -&gt; None:
for var in self._bin_vars:
lb, ub = var.bounds
var.setlb(lb)
var.setub(ub)
var.domain = pyomo.core.base.set_types.Reals
self._pyomo_solver.update_var(var)
def get_inequality_slacks(self) -&gt; Dict[str, float]:
result: Dict[str, float] = {}
for (cname, cobj) in self._cname_to_constr.items():
if cobj.equality:
continue
result[cname] = cobj.slack()
return result
def get_constraint_sense(self, cid: str) -&gt; str:
cobj = self._cname_to_constr[cid]
has_ub = cobj.has_ub()
has_lb = cobj.has_lb()
assert (not has_lb) or (not has_ub), &#34;range constraints not supported&#34;
if has_lb:
return &#34;&gt;&#34;
elif has_ub:
return &#34;&lt;&#34;
else:
return &#34;=&#34;
def set_constraint_sense(self, cid: str, sense: str) -&gt; None:
raise Exception(&#34;Not implemented&#34;)
def extract_constraint(self, cid: str) -&gt; Constraint:
raise Exception(&#34;Not implemented&#34;)
def is_constraint_satisfied(self, cobj: Constraint) -&gt; bool:
raise Exception(&#34;Not implemented&#34;)
def is_infeasible(self) -&gt; bool:
return self._termination_condition == TerminationCondition.infeasible
def get_dual(self, cid):
raise Exception(&#34;Not implemented&#34;)
def get_sense(self) -&gt; str:
return self._obj_sense</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.pyomo.base.BasePyomoSolver"><code class="flex name class">
<span>class <span class="ident">BasePyomoSolver</span></span>
<span>(</span><span>solver_factory, params)</span>
</code></dt>
<dd>
<section class="desc"><p>Base class for all Pyomo solvers.</p></section>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">class BasePyomoSolver(InternalSolver):
&#34;&#34;&#34;
Base class for all Pyomo solvers.
&#34;&#34;&#34;
def __init__(
self,
solver_factory: SolverFactory,
params: SolverParams,
) -&gt; None:
self.instance: Optional[Instance] = None
self.model: Optional[pe.ConcreteModel] = None
self._all_vars: List[pe.Var] = []
self._bin_vars: List[pe.Var] = []
self._is_warm_start_available: bool = False
self._pyomo_solver: SolverFactory = solver_factory
self._obj_sense: str = &#34;min&#34;
self._varname_to_var: Dict[str, pe.Var] = {}
self._cname_to_constr: Dict[str, pe.Constraint] = {}
self._termination_condition: str = &#34;&#34;
for (key, value) in params.items():
self._pyomo_solver.options[key] = value
def solve_lp(
self,
tee: bool = False,
) -&gt; LPSolveStats:
self.relax()
streams: List[Any] = [StringIO()]
if tee:
streams += [sys.stdout]
with _RedirectOutput(streams):
results = self._pyomo_solver.solve(tee=True)
self._restore_integrality()
opt_value = None
if not self.is_infeasible():
opt_value = results[&#34;Problem&#34;][0][&#34;Lower bound&#34;]
return {
&#34;Optimal value&#34;: opt_value,
&#34;Log&#34;: streams[0].getvalue(),
}
def _restore_integrality(self) -&gt; None:
for var in self._bin_vars:
var.domain = pyomo.core.base.set_types.Binary
self._pyomo_solver.update_var(var)
def solve(
self,
tee: bool = False,
iteration_cb: IterationCallback = None,
lazy_cb: LazyCallback = None,
) -&gt; MIPSolveStats:
if lazy_cb is not None:
raise Exception(&#34;lazy callback not supported&#34;)
total_wallclock_time = 0
streams: List[Any] = [StringIO()]
if tee:
streams += [sys.stdout]
if iteration_cb is None:
iteration_cb = lambda: False
while True:
logger.debug(&#34;Solving MIP...&#34;)
with _RedirectOutput(streams):
results = self._pyomo_solver.solve(
tee=True,
warmstart=self._is_warm_start_available,
)
total_wallclock_time += results[&#34;Solver&#34;][0][&#34;Wallclock time&#34;]
should_repeat = iteration_cb()
if not should_repeat:
break
log = streams[0].getvalue()
node_count = self._extract_node_count(log)
ws_value = self._extract_warm_start_value(log)
self._termination_condition = results[&#34;Solver&#34;][0][&#34;Termination condition&#34;]
lb, ub = None, None
if not self.is_infeasible():
lb = results[&#34;Problem&#34;][0][&#34;Lower bound&#34;]
ub = results[&#34;Problem&#34;][0][&#34;Upper bound&#34;]
stats: MIPSolveStats = {
&#34;Lower bound&#34;: lb,
&#34;Upper bound&#34;: ub,
&#34;Wallclock time&#34;: total_wallclock_time,
&#34;Sense&#34;: self._obj_sense,
&#34;Log&#34;: log,
&#34;Nodes&#34;: node_count,
&#34;Warm start value&#34;: ws_value,
&#34;LP value&#34;: None,
}
return stats
def get_solution(self) -&gt; Optional[Solution]:
assert self.model is not None
if self.is_infeasible():
return None
solution: Solution = {}
for var in self.model.component_objects(Var):
solution[str(var)] = {}
for index in var:
if var[index].fixed:
continue
solution[str(var)][index] = var[index].value
return solution
def set_warm_start(self, solution: Solution) -&gt; None:
self._clear_warm_start()
count_total, count_fixed = 0, 0
for var_name in solution:
var = self._varname_to_var[var_name]
for index in solution[var_name]:
count_total += 1
var[index].value = solution[var_name][index]
if solution[var_name][index] is not None:
count_fixed += 1
if count_fixed &gt; 0:
self._is_warm_start_available = True
logger.info(
&#34;Setting start values for %d variables (out of %d)&#34;
% (count_fixed, count_total)
)
def set_instance(
self,
instance: Instance,
model: Any = None,
) -&gt; None:
if model is None:
model = instance.to_model()
assert isinstance(model, pe.ConcreteModel)
self.instance = instance
self.model = model
self._pyomo_solver.set_instance(model)
self._update_obj()
self._update_vars()
self._update_constrs()
def get_value(self, var_name: str, index: VarIndex) -&gt; Optional[float]:
if self.is_infeasible():
return None
else:
var = self._varname_to_var[var_name]
return var[index].value
def get_empty_solution(self) -&gt; Solution:
assert self.model is not None
solution: Solution = {}
for var in self.model.component_objects(Var):
svar = str(var)
solution[svar] = {}
for index in var:
if var[index].fixed:
continue
solution[svar][index] = None
return solution
def _clear_warm_start(self) -&gt; None:
for var in self._all_vars:
if not var.fixed:
var.value = None
self._is_warm_start_available = False
def _update_obj(self) -&gt; None:
self._obj_sense = &#34;max&#34;
if self._pyomo_solver._objective.sense == pyomo.core.kernel.objective.minimize:
self._obj_sense = &#34;min&#34;
def _update_vars(self) -&gt; None:
assert self.model is not None
self._all_vars = []
self._bin_vars = []
self._varname_to_var = {}
for var in self.model.component_objects(Var):
self._varname_to_var[var.name] = var
for idx in var:
self._all_vars += [var[idx]]
if var[idx].domain == pyomo.core.base.set_types.Binary:
self._bin_vars += [var[idx]]
def _update_constrs(self) -&gt; None:
assert self.model is not None
self._cname_to_constr = {}
for constr in self.model.component_objects(Constraint):
self._cname_to_constr[constr.name] = constr
def fix(self, solution):
count_total, count_fixed = 0, 0
for varname in solution:
for index in solution[varname]:
var = self._varname_to_var[varname]
count_total += 1
if solution[varname][index] is None:
continue
count_fixed += 1
var[index].fix(solution[varname][index])
self._pyomo_solver.update_var(var[index])
logger.info(
&#34;Fixing values for %d variables (out of %d)&#34;
% (
count_fixed,
count_total,
)
)
def add_constraint(self, constraint):
self._pyomo_solver.add_constraint(constraint)
self._update_constrs()
@staticmethod
def __extract(
log: str,
regexp: Optional[str],
default: Optional[str] = None,
) -&gt; Optional[str]:
if regexp is None:
return default
value = default
for line in log.splitlines():
matches = re.findall(regexp, line)
if len(matches) == 0:
continue
value = matches[0]
return value
def _extract_warm_start_value(self, log: str) -&gt; Optional[float]:
value = self.__extract(log, self._get_warm_start_regexp())
if value is None:
return None
return float(value)
def _extract_node_count(self, log: str) -&gt; Optional[int]:
value = self.__extract(log, self._get_node_count_regexp())
if value is None:
return None
return int(value)
def get_constraint_ids(self):
return list(self._cname_to_constr.keys())
def _get_warm_start_regexp(self) -&gt; Optional[str]:
return None
def _get_node_count_regexp(self) -&gt; Optional[str]:
return None
def relax(self) -&gt; None:
for var in self._bin_vars:
lb, ub = var.bounds
var.setlb(lb)
var.setub(ub)
var.domain = pyomo.core.base.set_types.Reals
self._pyomo_solver.update_var(var)
def get_inequality_slacks(self) -&gt; Dict[str, float]:
result: Dict[str, float] = {}
for (cname, cobj) in self._cname_to_constr.items():
if cobj.equality:
continue
result[cname] = cobj.slack()
return result
def get_constraint_sense(self, cid: str) -&gt; str:
cobj = self._cname_to_constr[cid]
has_ub = cobj.has_ub()
has_lb = cobj.has_lb()
assert (not has_lb) or (not has_ub), &#34;range constraints not supported&#34;
if has_lb:
return &#34;&gt;&#34;
elif has_ub:
return &#34;&lt;&#34;
else:
return &#34;=&#34;
def set_constraint_sense(self, cid: str, sense: str) -&gt; None:
raise Exception(&#34;Not implemented&#34;)
def extract_constraint(self, cid: str) -&gt; Constraint:
raise Exception(&#34;Not implemented&#34;)
def is_constraint_satisfied(self, cobj: Constraint) -&gt; bool:
raise Exception(&#34;Not implemented&#34;)
def is_infeasible(self) -&gt; bool:
return self._termination_condition == TerminationCondition.infeasible
def get_dual(self, cid):
raise Exception(&#34;Not implemented&#34;)
def get_sense(self) -&gt; str:
return self._obj_sense</code></pre>
</details>
<h3>Ancestors</h3>
<ul class="hlist">
<li><a title="miplearn.solvers.internal.InternalSolver" href="../internal.html#miplearn.solvers.internal.InternalSolver">InternalSolver</a></li>
<li>abc.ABC</li>
</ul>
<h3>Subclasses</h3>
<ul class="hlist">
<li><a title="miplearn.solvers.pyomo.gurobi.GurobiPyomoSolver" href="gurobi.html#miplearn.solvers.pyomo.gurobi.GurobiPyomoSolver">GurobiPyomoSolver</a></li>
<li><a title="miplearn.solvers.pyomo.cplex.CplexPyomoSolver" href="cplex.html#miplearn.solvers.pyomo.cplex.CplexPyomoSolver">CplexPyomoSolver</a></li>
<li><a title="miplearn.solvers.pyomo.xpress.XpressPyomoSolver" href="xpress.html#miplearn.solvers.pyomo.xpress.XpressPyomoSolver">XpressPyomoSolver</a></li>
</ul>
<h3>Inherited members</h3>
<ul class="hlist">
<li><code><b><a title="miplearn.solvers.internal.InternalSolver" href="../internal.html#miplearn.solvers.internal.InternalSolver">InternalSolver</a></b></code>:
<ul class="hlist">
<li><code><a title="miplearn.solvers.internal.InternalSolver.add_constraint" href="../internal.html#miplearn.solvers.internal.InternalSolver.add_constraint">add_constraint</a></code></li>
<li><code><a title="miplearn.solvers.internal.InternalSolver.extract_constraint" href="../internal.html#miplearn.solvers.internal.InternalSolver.extract_constraint">extract_constraint</a></code></li>
<li><code><a title="miplearn.solvers.internal.InternalSolver.fix" href="../internal.html#miplearn.solvers.internal.InternalSolver.fix">fix</a></code></li>
<li><code><a title="miplearn.solvers.internal.InternalSolver.get_constraint_ids" href="../internal.html#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="../internal.html#miplearn.solvers.internal.InternalSolver.get_constraint_sense">get_constraint_sense</a></code></li>
<li><code><a title="miplearn.solvers.internal.InternalSolver.get_dual" href="../internal.html#miplearn.solvers.internal.InternalSolver.get_dual">get_dual</a></code></li>
<li><code><a title="miplearn.solvers.internal.InternalSolver.get_empty_solution" href="../internal.html#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="../internal.html#miplearn.solvers.internal.InternalSolver.get_inequality_slacks">get_inequality_slacks</a></code></li>
<li><code><a title="miplearn.solvers.internal.InternalSolver.get_sense" href="../internal.html#miplearn.solvers.internal.InternalSolver.get_sense">get_sense</a></code></li>
<li><code><a title="miplearn.solvers.internal.InternalSolver.get_solution" href="../internal.html#miplearn.solvers.internal.InternalSolver.get_solution">get_solution</a></code></li>
<li><code><a title="miplearn.solvers.internal.InternalSolver.get_value" href="../internal.html#miplearn.solvers.internal.InternalSolver.get_value">get_value</a></code></li>
<li><code><a title="miplearn.solvers.internal.InternalSolver.is_constraint_satisfied" href="../internal.html#miplearn.solvers.internal.InternalSolver.is_constraint_satisfied">is_constraint_satisfied</a></code></li>
<li><code><a title="miplearn.solvers.internal.InternalSolver.is_infeasible" href="../internal.html#miplearn.solvers.internal.InternalSolver.is_infeasible">is_infeasible</a></code></li>
<li><code><a title="miplearn.solvers.internal.InternalSolver.relax" href="../internal.html#miplearn.solvers.internal.InternalSolver.relax">relax</a></code></li>
<li><code><a title="miplearn.solvers.internal.InternalSolver.set_branching_priorities" href="../internal.html#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="../internal.html#miplearn.solvers.internal.InternalSolver.set_constraint_sense">set_constraint_sense</a></code></li>
<li><code><a title="miplearn.solvers.internal.InternalSolver.set_instance" href="../internal.html#miplearn.solvers.internal.InternalSolver.set_instance">set_instance</a></code></li>
<li><code><a title="miplearn.solvers.internal.InternalSolver.set_warm_start" href="../internal.html#miplearn.solvers.internal.InternalSolver.set_warm_start">set_warm_start</a></code></li>
<li><code><a title="miplearn.solvers.internal.InternalSolver.solve" href="../internal.html#miplearn.solvers.internal.InternalSolver.solve">solve</a></code></li>
<li><code><a title="miplearn.solvers.internal.InternalSolver.solve_lp" href="../internal.html#miplearn.solvers.internal.InternalSolver.solve_lp">solve_lp</a></code></li>
</ul>
</li>
</ul>
</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.pyomo" href="index.html">miplearn.solvers.pyomo</a></code></li>
</ul>
</li>
<li><h3><a href="#header-classes">Classes</a></h3>
<ul>
<li>
<h4><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver" href="#miplearn.solvers.pyomo.base.BasePyomoSolver">BasePyomoSolver</a></code></h4>
</li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc"><cite>pdoc</cite> 0.7.0</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>

View File

@@ -0,0 +1,193 @@
<!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.0" />
<title>miplearn.solvers.pyomo.cplex 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.pyomo.cplex</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.
from typing import Optional
from pyomo import environ as pe
from scipy.stats import randint
from miplearn.solvers.pyomo.base import BasePyomoSolver
from miplearn.types import SolverParams
class CplexPyomoSolver(BasePyomoSolver):
&#34;&#34;&#34;
An InternalSolver that uses CPLEX and the Pyomo modeling language.
Parameters
----------
params: dict
Dictionary of options to pass to the Pyomo solver. For example,
{&#34;mip_display&#34;: 5} to increase the log verbosity.
&#34;&#34;&#34;
def __init__(
self,
params: Optional[SolverParams] = None,
) -&gt; None:
if params is None:
params = {}
if &#34;randomseed&#34; not in params.keys():
params[&#34;randomseed&#34;] = randint(low=0, high=1000).rvs()
if &#34;mip_display&#34; not in params.keys():
params[&#34;mip_display&#34;] = 4
super().__init__(
solver_factory=pe.SolverFactory(&#34;cplex_persistent&#34;),
params=params,
)
def _get_warm_start_regexp(self):
return &#34;MIP start .* with objective ([0-9.e+-]*)\\.&#34;
def _get_node_count_regexp(self):
return &#34;^[ *] *([0-9]+)&#34;</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.pyomo.cplex.CplexPyomoSolver"><code class="flex name class">
<span>class <span class="ident">CplexPyomoSolver</span></span>
<span>(</span><span>params=None)</span>
</code></dt>
<dd>
<section class="desc"><p>An InternalSolver that uses CPLEX and the Pyomo modeling language.</p>
<h2 id="parameters">Parameters</h2>
<dl>
<dt><strong><code>params</code></strong> :&ensp;<code>dict</code></dt>
<dd>Dictionary of options to pass to the Pyomo solver. For example,
{"mip_display": 5} to increase the log verbosity.</dd>
</dl></section>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">class CplexPyomoSolver(BasePyomoSolver):
&#34;&#34;&#34;
An InternalSolver that uses CPLEX and the Pyomo modeling language.
Parameters
----------
params: dict
Dictionary of options to pass to the Pyomo solver. For example,
{&#34;mip_display&#34;: 5} to increase the log verbosity.
&#34;&#34;&#34;
def __init__(
self,
params: Optional[SolverParams] = None,
) -&gt; None:
if params is None:
params = {}
if &#34;randomseed&#34; not in params.keys():
params[&#34;randomseed&#34;] = randint(low=0, high=1000).rvs()
if &#34;mip_display&#34; not in params.keys():
params[&#34;mip_display&#34;] = 4
super().__init__(
solver_factory=pe.SolverFactory(&#34;cplex_persistent&#34;),
params=params,
)
def _get_warm_start_regexp(self):
return &#34;MIP start .* with objective ([0-9.e+-]*)\\.&#34;
def _get_node_count_regexp(self):
return &#34;^[ *] *([0-9]+)&#34;</code></pre>
</details>
<h3>Ancestors</h3>
<ul class="hlist">
<li><a title="miplearn.solvers.pyomo.base.BasePyomoSolver" href="base.html#miplearn.solvers.pyomo.base.BasePyomoSolver">BasePyomoSolver</a></li>
<li><a title="miplearn.solvers.internal.InternalSolver" href="../internal.html#miplearn.solvers.internal.InternalSolver">InternalSolver</a></li>
<li>abc.ABC</li>
</ul>
<h3>Inherited members</h3>
<ul class="hlist">
<li><code><b><a title="miplearn.solvers.pyomo.base.BasePyomoSolver" href="base.html#miplearn.solvers.pyomo.base.BasePyomoSolver">BasePyomoSolver</a></b></code>:
<ul class="hlist">
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.add_constraint" href="../internal.html#miplearn.solvers.internal.InternalSolver.add_constraint">add_constraint</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.extract_constraint" href="../internal.html#miplearn.solvers.internal.InternalSolver.extract_constraint">extract_constraint</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.fix" href="../internal.html#miplearn.solvers.internal.InternalSolver.fix">fix</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.get_constraint_ids" href="../internal.html#miplearn.solvers.internal.InternalSolver.get_constraint_ids">get_constraint_ids</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.get_constraint_sense" href="../internal.html#miplearn.solvers.internal.InternalSolver.get_constraint_sense">get_constraint_sense</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.get_dual" href="../internal.html#miplearn.solvers.internal.InternalSolver.get_dual">get_dual</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.get_empty_solution" href="../internal.html#miplearn.solvers.internal.InternalSolver.get_empty_solution">get_empty_solution</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.get_inequality_slacks" href="../internal.html#miplearn.solvers.internal.InternalSolver.get_inequality_slacks">get_inequality_slacks</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.get_sense" href="../internal.html#miplearn.solvers.internal.InternalSolver.get_sense">get_sense</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.get_solution" href="../internal.html#miplearn.solvers.internal.InternalSolver.get_solution">get_solution</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.get_value" href="../internal.html#miplearn.solvers.internal.InternalSolver.get_value">get_value</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.is_constraint_satisfied" href="../internal.html#miplearn.solvers.internal.InternalSolver.is_constraint_satisfied">is_constraint_satisfied</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.is_infeasible" href="../internal.html#miplearn.solvers.internal.InternalSolver.is_infeasible">is_infeasible</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.relax" href="../internal.html#miplearn.solvers.internal.InternalSolver.relax">relax</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.set_branching_priorities" href="../internal.html#miplearn.solvers.internal.InternalSolver.set_branching_priorities">set_branching_priorities</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.set_constraint_sense" href="../internal.html#miplearn.solvers.internal.InternalSolver.set_constraint_sense">set_constraint_sense</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.set_instance" href="../internal.html#miplearn.solvers.internal.InternalSolver.set_instance">set_instance</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.set_warm_start" href="../internal.html#miplearn.solvers.internal.InternalSolver.set_warm_start">set_warm_start</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.solve" href="../internal.html#miplearn.solvers.internal.InternalSolver.solve">solve</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.solve_lp" href="../internal.html#miplearn.solvers.internal.InternalSolver.solve_lp">solve_lp</a></code></li>
</ul>
</li>
</ul>
</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.pyomo" href="index.html">miplearn.solvers.pyomo</a></code></li>
</ul>
</li>
<li><h3><a href="#header-classes">Classes</a></h3>
<ul>
<li>
<h4><code><a title="miplearn.solvers.pyomo.cplex.CplexPyomoSolver" href="#miplearn.solvers.pyomo.cplex.CplexPyomoSolver">CplexPyomoSolver</a></code></h4>
</li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc"><cite>pdoc</cite> 0.7.0</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>

View File

@@ -0,0 +1,221 @@
<!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.0" />
<title>miplearn.solvers.pyomo.gurobi 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.pyomo.gurobi</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 typing import Optional
from pyomo import environ as pe
from scipy.stats import randint
from miplearn.solvers.pyomo.base import BasePyomoSolver
from miplearn.types import SolverParams, BranchPriorities
logger = logging.getLogger(__name__)
class GurobiPyomoSolver(BasePyomoSolver):
&#34;&#34;&#34;
An InternalSolver that uses Gurobi and the Pyomo modeling language.
Parameters
----------
params: dict
Dictionary of options to pass to the Pyomo solver. For example,
{&#34;Threads&#34;: 4} to set the number of threads.
&#34;&#34;&#34;
def __init__(
self,
params: SolverParams = None,
) -&gt; None:
if params is None:
params = {}
if &#34;seed&#34; not in params.keys():
params[&#34;seed&#34;] = randint(low=0, high=1000).rvs()
super().__init__(
solver_factory=pe.SolverFactory(&#34;gurobi_persistent&#34;),
params=params,
)
def _extract_node_count(self, log: str) -&gt; int:
return max(1, int(self._pyomo_solver._solver_model.getAttr(&#34;NodeCount&#34;)))
def _get_warm_start_regexp(self) -&gt; str:
return &#34;MIP start with objective ([0-9.e+-]*)&#34;
def _get_node_count_regexp(self) -&gt; Optional[str]:
return None
def set_branching_priorities(self, priorities: BranchPriorities) -&gt; None:
from gurobipy import GRB
for varname in priorities.keys():
var = self._varname_to_var[varname]
for (index, priority) in priorities[varname].items():
if priority is None:
continue
gvar = self._pyomo_solver._pyomo_var_to_solver_var_map[var[index]]
gvar.setAttr(GRB.Attr.BranchPriority, int(round(priority)))</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.pyomo.gurobi.GurobiPyomoSolver"><code class="flex name class">
<span>class <span class="ident">GurobiPyomoSolver</span></span>
<span>(</span><span>params=None)</span>
</code></dt>
<dd>
<section class="desc"><p>An InternalSolver that uses Gurobi and the Pyomo modeling language.</p>
<h2 id="parameters">Parameters</h2>
<dl>
<dt><strong><code>params</code></strong> :&ensp;<code>dict</code></dt>
<dd>Dictionary of options to pass to the Pyomo solver. For example,
{"Threads": 4} to set the number of threads.</dd>
</dl></section>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">class GurobiPyomoSolver(BasePyomoSolver):
&#34;&#34;&#34;
An InternalSolver that uses Gurobi and the Pyomo modeling language.
Parameters
----------
params: dict
Dictionary of options to pass to the Pyomo solver. For example,
{&#34;Threads&#34;: 4} to set the number of threads.
&#34;&#34;&#34;
def __init__(
self,
params: SolverParams = None,
) -&gt; None:
if params is None:
params = {}
if &#34;seed&#34; not in params.keys():
params[&#34;seed&#34;] = randint(low=0, high=1000).rvs()
super().__init__(
solver_factory=pe.SolverFactory(&#34;gurobi_persistent&#34;),
params=params,
)
def _extract_node_count(self, log: str) -&gt; int:
return max(1, int(self._pyomo_solver._solver_model.getAttr(&#34;NodeCount&#34;)))
def _get_warm_start_regexp(self) -&gt; str:
return &#34;MIP start with objective ([0-9.e+-]*)&#34;
def _get_node_count_regexp(self) -&gt; Optional[str]:
return None
def set_branching_priorities(self, priorities: BranchPriorities) -&gt; None:
from gurobipy import GRB
for varname in priorities.keys():
var = self._varname_to_var[varname]
for (index, priority) in priorities[varname].items():
if priority is None:
continue
gvar = self._pyomo_solver._pyomo_var_to_solver_var_map[var[index]]
gvar.setAttr(GRB.Attr.BranchPriority, int(round(priority)))</code></pre>
</details>
<h3>Ancestors</h3>
<ul class="hlist">
<li><a title="miplearn.solvers.pyomo.base.BasePyomoSolver" href="base.html#miplearn.solvers.pyomo.base.BasePyomoSolver">BasePyomoSolver</a></li>
<li><a title="miplearn.solvers.internal.InternalSolver" href="../internal.html#miplearn.solvers.internal.InternalSolver">InternalSolver</a></li>
<li>abc.ABC</li>
</ul>
<h3>Inherited members</h3>
<ul class="hlist">
<li><code><b><a title="miplearn.solvers.pyomo.base.BasePyomoSolver" href="base.html#miplearn.solvers.pyomo.base.BasePyomoSolver">BasePyomoSolver</a></b></code>:
<ul class="hlist">
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.add_constraint" href="../internal.html#miplearn.solvers.internal.InternalSolver.add_constraint">add_constraint</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.extract_constraint" href="../internal.html#miplearn.solvers.internal.InternalSolver.extract_constraint">extract_constraint</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.fix" href="../internal.html#miplearn.solvers.internal.InternalSolver.fix">fix</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.get_constraint_ids" href="../internal.html#miplearn.solvers.internal.InternalSolver.get_constraint_ids">get_constraint_ids</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.get_constraint_sense" href="../internal.html#miplearn.solvers.internal.InternalSolver.get_constraint_sense">get_constraint_sense</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.get_dual" href="../internal.html#miplearn.solvers.internal.InternalSolver.get_dual">get_dual</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.get_empty_solution" href="../internal.html#miplearn.solvers.internal.InternalSolver.get_empty_solution">get_empty_solution</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.get_inequality_slacks" href="../internal.html#miplearn.solvers.internal.InternalSolver.get_inequality_slacks">get_inequality_slacks</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.get_sense" href="../internal.html#miplearn.solvers.internal.InternalSolver.get_sense">get_sense</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.get_solution" href="../internal.html#miplearn.solvers.internal.InternalSolver.get_solution">get_solution</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.get_value" href="../internal.html#miplearn.solvers.internal.InternalSolver.get_value">get_value</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.is_constraint_satisfied" href="../internal.html#miplearn.solvers.internal.InternalSolver.is_constraint_satisfied">is_constraint_satisfied</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.is_infeasible" href="../internal.html#miplearn.solvers.internal.InternalSolver.is_infeasible">is_infeasible</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.relax" href="../internal.html#miplearn.solvers.internal.InternalSolver.relax">relax</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.set_branching_priorities" href="../internal.html#miplearn.solvers.internal.InternalSolver.set_branching_priorities">set_branching_priorities</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.set_constraint_sense" href="../internal.html#miplearn.solvers.internal.InternalSolver.set_constraint_sense">set_constraint_sense</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.set_instance" href="../internal.html#miplearn.solvers.internal.InternalSolver.set_instance">set_instance</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.set_warm_start" href="../internal.html#miplearn.solvers.internal.InternalSolver.set_warm_start">set_warm_start</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.solve" href="../internal.html#miplearn.solvers.internal.InternalSolver.solve">solve</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.solve_lp" href="../internal.html#miplearn.solvers.internal.InternalSolver.solve_lp">solve_lp</a></code></li>
</ul>
</li>
</ul>
</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.pyomo" href="index.html">miplearn.solvers.pyomo</a></code></li>
</ul>
</li>
<li><h3><a href="#header-classes">Classes</a></h3>
<ul>
<li>
<h4><code><a title="miplearn.solvers.pyomo.gurobi.GurobiPyomoSolver" href="#miplearn.solvers.pyomo.gurobi.GurobiPyomoSolver">GurobiPyomoSolver</a></code></h4>
</li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc"><cite>pdoc</cite> 0.7.0</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>

View File

@@ -0,0 +1,88 @@
<!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.0" />
<title>miplearn.solvers.pyomo 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.pyomo</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.</code></pre>
</details>
</section>
<section>
<h2 class="section-title" id="header-submodules">Sub-modules</h2>
<dl>
<dt><code class="name"><a title="miplearn.solvers.pyomo.base" href="base.html">miplearn.solvers.pyomo.base</a></code></dt>
<dd>
<section class="desc"></section>
</dd>
<dt><code class="name"><a title="miplearn.solvers.pyomo.cplex" href="cplex.html">miplearn.solvers.pyomo.cplex</a></code></dt>
<dd>
<section class="desc"></section>
</dd>
<dt><code class="name"><a title="miplearn.solvers.pyomo.gurobi" href="gurobi.html">miplearn.solvers.pyomo.gurobi</a></code></dt>
<dd>
<section class="desc"></section>
</dd>
<dt><code class="name"><a title="miplearn.solvers.pyomo.xpress" href="xpress.html">miplearn.solvers.pyomo.xpress</a></code></dt>
<dd>
<section class="desc"></section>
</dd>
</dl>
</section>
<section>
</section>
<section>
</section>
<section>
</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-submodules">Sub-modules</a></h3>
<ul>
<li><code><a title="miplearn.solvers.pyomo.base" href="base.html">miplearn.solvers.pyomo.base</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.cplex" href="cplex.html">miplearn.solvers.pyomo.cplex</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.gurobi" href="gurobi.html">miplearn.solvers.pyomo.gurobi</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.xpress" href="xpress.html">miplearn.solvers.pyomo.xpress</a></code></li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc"><cite>pdoc</cite> 0.7.0</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>

View File

@@ -0,0 +1,174 @@
<!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.0" />
<title>miplearn.solvers.pyomo.xpress 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.pyomo.xpress</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 pyomo import environ as pe
from scipy.stats import randint
from miplearn.solvers.pyomo.base import BasePyomoSolver
from miplearn.types import SolverParams
logger = logging.getLogger(__name__)
class XpressPyomoSolver(BasePyomoSolver):
&#34;&#34;&#34;
An InternalSolver that uses XPRESS and the Pyomo modeling language.
Parameters
----------
params: dict
Dictionary of options to pass to the Pyomo solver. For example,
{&#34;Threads&#34;: 4} to set the number of threads.
&#34;&#34;&#34;
def __init__(self, params: SolverParams = None) -&gt; None:
if params is None:
params = {}
if &#34;randomseed&#34; not in params.keys():
params[&#34;randomseed&#34;] = randint(low=0, high=1000).rvs()
super().__init__(
solver_factory=pe.SolverFactory(&#34;xpress_persistent&#34;),
params=params,
)</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.pyomo.xpress.XpressPyomoSolver"><code class="flex name class">
<span>class <span class="ident">XpressPyomoSolver</span></span>
<span>(</span><span>params=None)</span>
</code></dt>
<dd>
<section class="desc"><p>An InternalSolver that uses XPRESS and the Pyomo modeling language.</p>
<h2 id="parameters">Parameters</h2>
<dl>
<dt><strong><code>params</code></strong> :&ensp;<code>dict</code></dt>
<dd>Dictionary of options to pass to the Pyomo solver. For example,
{"Threads": 4} to set the number of threads.</dd>
</dl></section>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">class XpressPyomoSolver(BasePyomoSolver):
&#34;&#34;&#34;
An InternalSolver that uses XPRESS and the Pyomo modeling language.
Parameters
----------
params: dict
Dictionary of options to pass to the Pyomo solver. For example,
{&#34;Threads&#34;: 4} to set the number of threads.
&#34;&#34;&#34;
def __init__(self, params: SolverParams = None) -&gt; None:
if params is None:
params = {}
if &#34;randomseed&#34; not in params.keys():
params[&#34;randomseed&#34;] = randint(low=0, high=1000).rvs()
super().__init__(
solver_factory=pe.SolverFactory(&#34;xpress_persistent&#34;),
params=params,
)</code></pre>
</details>
<h3>Ancestors</h3>
<ul class="hlist">
<li><a title="miplearn.solvers.pyomo.base.BasePyomoSolver" href="base.html#miplearn.solvers.pyomo.base.BasePyomoSolver">BasePyomoSolver</a></li>
<li><a title="miplearn.solvers.internal.InternalSolver" href="../internal.html#miplearn.solvers.internal.InternalSolver">InternalSolver</a></li>
<li>abc.ABC</li>
</ul>
<h3>Inherited members</h3>
<ul class="hlist">
<li><code><b><a title="miplearn.solvers.pyomo.base.BasePyomoSolver" href="base.html#miplearn.solvers.pyomo.base.BasePyomoSolver">BasePyomoSolver</a></b></code>:
<ul class="hlist">
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.add_constraint" href="../internal.html#miplearn.solvers.internal.InternalSolver.add_constraint">add_constraint</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.extract_constraint" href="../internal.html#miplearn.solvers.internal.InternalSolver.extract_constraint">extract_constraint</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.fix" href="../internal.html#miplearn.solvers.internal.InternalSolver.fix">fix</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.get_constraint_ids" href="../internal.html#miplearn.solvers.internal.InternalSolver.get_constraint_ids">get_constraint_ids</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.get_constraint_sense" href="../internal.html#miplearn.solvers.internal.InternalSolver.get_constraint_sense">get_constraint_sense</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.get_dual" href="../internal.html#miplearn.solvers.internal.InternalSolver.get_dual">get_dual</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.get_empty_solution" href="../internal.html#miplearn.solvers.internal.InternalSolver.get_empty_solution">get_empty_solution</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.get_inequality_slacks" href="../internal.html#miplearn.solvers.internal.InternalSolver.get_inequality_slacks">get_inequality_slacks</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.get_sense" href="../internal.html#miplearn.solvers.internal.InternalSolver.get_sense">get_sense</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.get_solution" href="../internal.html#miplearn.solvers.internal.InternalSolver.get_solution">get_solution</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.get_value" href="../internal.html#miplearn.solvers.internal.InternalSolver.get_value">get_value</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.is_constraint_satisfied" href="../internal.html#miplearn.solvers.internal.InternalSolver.is_constraint_satisfied">is_constraint_satisfied</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.is_infeasible" href="../internal.html#miplearn.solvers.internal.InternalSolver.is_infeasible">is_infeasible</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.relax" href="../internal.html#miplearn.solvers.internal.InternalSolver.relax">relax</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.set_branching_priorities" href="../internal.html#miplearn.solvers.internal.InternalSolver.set_branching_priorities">set_branching_priorities</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.set_constraint_sense" href="../internal.html#miplearn.solvers.internal.InternalSolver.set_constraint_sense">set_constraint_sense</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.set_instance" href="../internal.html#miplearn.solvers.internal.InternalSolver.set_instance">set_instance</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.set_warm_start" href="../internal.html#miplearn.solvers.internal.InternalSolver.set_warm_start">set_warm_start</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.solve" href="../internal.html#miplearn.solvers.internal.InternalSolver.solve">solve</a></code></li>
<li><code><a title="miplearn.solvers.pyomo.base.BasePyomoSolver.solve_lp" href="../internal.html#miplearn.solvers.internal.InternalSolver.solve_lp">solve_lp</a></code></li>
</ul>
</li>
</ul>
</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.pyomo" href="index.html">miplearn.solvers.pyomo</a></code></li>
</ul>
</li>
<li><h3><a href="#header-classes">Classes</a></h3>
<ul>
<li>
<h4><code><a title="miplearn.solvers.pyomo.xpress.XpressPyomoSolver" href="#miplearn.solvers.pyomo.xpress.XpressPyomoSolver">XpressPyomoSolver</a></code></h4>
</li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc"><cite>pdoc</cite> 0.7.0</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>

View File

@@ -0,0 +1,250 @@
<!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.0" />
<title>miplearn.solvers.tests 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.tests</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.
from inspect import isclass
from typing import List, Callable, Any
from pyomo import environ as pe
from miplearn.instance import Instance
from miplearn.problems.knapsack import KnapsackInstance, GurobiKnapsackInstance
from miplearn.solvers.gurobi import GurobiSolver
from miplearn.solvers.internal import InternalSolver
from miplearn.solvers.pyomo.base import BasePyomoSolver
from miplearn.solvers.pyomo.gurobi import GurobiPyomoSolver
from miplearn.solvers.pyomo.xpress import XpressPyomoSolver
class InfeasiblePyomoInstance(Instance):
def to_model(self) -&gt; pe.ConcreteModel:
model = pe.ConcreteModel()
model.x = pe.Var([0], domain=pe.Binary)
model.OBJ = pe.Objective(expr=model.x[0], sense=pe.maximize)
model.eq = pe.Constraint(expr=model.x[0] &gt;= 2)
return model
class InfeasibleGurobiInstance(Instance):
def to_model(self) -&gt; Any:
import gurobipy as gp
from gurobipy import GRB
model = gp.Model()
x = model.addVars(1, vtype=GRB.BINARY, name=&#34;x&#34;)
model.addConstr(x[0] &gt;= 2)
model.setObjective(x[0])
return model
def _is_subclass_or_instance(obj, parent_class):
return isinstance(obj, parent_class) or (
isclass(obj) and issubclass(obj, parent_class)
)
def _get_knapsack_instance(solver):
if _is_subclass_or_instance(solver, BasePyomoSolver):
return KnapsackInstance(
weights=[23.0, 26.0, 20.0, 18.0],
prices=[505.0, 352.0, 458.0, 220.0],
capacity=67.0,
)
if _is_subclass_or_instance(solver, GurobiSolver):
return GurobiKnapsackInstance(
weights=[23.0, 26.0, 20.0, 18.0],
prices=[505.0, 352.0, 458.0, 220.0],
capacity=67.0,
)
assert False
def _get_infeasible_instance(solver):
if _is_subclass_or_instance(solver, BasePyomoSolver):
return InfeasiblePyomoInstance()
if _is_subclass_or_instance(solver, GurobiSolver):
return InfeasibleGurobiInstance()
def _get_internal_solvers() -&gt; List[Callable[[], InternalSolver]]:
return [GurobiPyomoSolver, GurobiSolver, XpressPyomoSolver]</code></pre>
</details>
</section>
<section>
<h2 class="section-title" id="header-submodules">Sub-modules</h2>
<dl>
<dt><code class="name"><a title="miplearn.solvers.tests.test_internal_solver" href="test_internal_solver.html">miplearn.solvers.tests.test_internal_solver</a></code></dt>
<dd>
<section class="desc"></section>
</dd>
<dt><code class="name"><a title="miplearn.solvers.tests.test_lazy_cb" href="test_lazy_cb.html">miplearn.solvers.tests.test_lazy_cb</a></code></dt>
<dd>
<section class="desc"></section>
</dd>
<dt><code class="name"><a title="miplearn.solvers.tests.test_learning_solver" href="test_learning_solver.html">miplearn.solvers.tests.test_learning_solver</a></code></dt>
<dd>
<section class="desc"></section>
</dd>
</dl>
</section>
<section>
</section>
<section>
</section>
<section>
<h2 class="section-title" id="header-classes">Classes</h2>
<dl>
<dt id="miplearn.solvers.tests.InfeasibleGurobiInstance"><code class="flex name class">
<span>class <span class="ident">InfeasibleGurobiInstance</span></span>
</code></dt>
<dd>
<section class="desc"><p>Abstract class holding all the data necessary to generate a concrete model of the
problem.</p>
<p>In the knapsack problem, for example, this class could hold the number of items,
their weights and costs, as well as the size of the knapsack. Objects
implementing this class are able to convert themselves into a concrete
optimization model, which can be optimized by a solver, or into arrays of
features, which can be provided as inputs to machine learning models.</p></section>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">class InfeasibleGurobiInstance(Instance):
def to_model(self) -&gt; Any:
import gurobipy as gp
from gurobipy import GRB
model = gp.Model()
x = model.addVars(1, vtype=GRB.BINARY, name=&#34;x&#34;)
model.addConstr(x[0] &gt;= 2)
model.setObjective(x[0])
return model</code></pre>
</details>
<h3>Ancestors</h3>
<ul class="hlist">
<li><a title="miplearn.instance.Instance" href="../../instance.html#miplearn.instance.Instance">Instance</a></li>
<li>abc.ABC</li>
</ul>
<h3>Inherited members</h3>
<ul class="hlist">
<li><code><b><a title="miplearn.instance.Instance" href="../../instance.html#miplearn.instance.Instance">Instance</a></b></code>:
<ul class="hlist">
<li><code><a title="miplearn.instance.Instance.build_lazy_constraint" href="../../instance.html#miplearn.instance.Instance.build_lazy_constraint">build_lazy_constraint</a></code></li>
<li><code><a title="miplearn.instance.Instance.find_violated_lazy_constraints" href="../../instance.html#miplearn.instance.Instance.find_violated_lazy_constraints">find_violated_lazy_constraints</a></code></li>
<li><code><a title="miplearn.instance.Instance.get_instance_features" href="../../instance.html#miplearn.instance.Instance.get_instance_features">get_instance_features</a></code></li>
<li><code><a title="miplearn.instance.Instance.get_variable_category" href="../../instance.html#miplearn.instance.Instance.get_variable_category">get_variable_category</a></code></li>
<li><code><a title="miplearn.instance.Instance.get_variable_features" href="../../instance.html#miplearn.instance.Instance.get_variable_features">get_variable_features</a></code></li>
<li><code><a title="miplearn.instance.Instance.to_model" href="../../instance.html#miplearn.instance.Instance.to_model">to_model</a></code></li>
</ul>
</li>
</ul>
</dd>
<dt id="miplearn.solvers.tests.InfeasiblePyomoInstance"><code class="flex name class">
<span>class <span class="ident">InfeasiblePyomoInstance</span></span>
</code></dt>
<dd>
<section class="desc"><p>Abstract class holding all the data necessary to generate a concrete model of the
problem.</p>
<p>In the knapsack problem, for example, this class could hold the number of items,
their weights and costs, as well as the size of the knapsack. Objects
implementing this class are able to convert themselves into a concrete
optimization model, which can be optimized by a solver, or into arrays of
features, which can be provided as inputs to machine learning models.</p></section>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">class InfeasiblePyomoInstance(Instance):
def to_model(self) -&gt; pe.ConcreteModel:
model = pe.ConcreteModel()
model.x = pe.Var([0], domain=pe.Binary)
model.OBJ = pe.Objective(expr=model.x[0], sense=pe.maximize)
model.eq = pe.Constraint(expr=model.x[0] &gt;= 2)
return model</code></pre>
</details>
<h3>Ancestors</h3>
<ul class="hlist">
<li><a title="miplearn.instance.Instance" href="../../instance.html#miplearn.instance.Instance">Instance</a></li>
<li>abc.ABC</li>
</ul>
<h3>Inherited members</h3>
<ul class="hlist">
<li><code><b><a title="miplearn.instance.Instance" href="../../instance.html#miplearn.instance.Instance">Instance</a></b></code>:
<ul class="hlist">
<li><code><a title="miplearn.instance.Instance.build_lazy_constraint" href="../../instance.html#miplearn.instance.Instance.build_lazy_constraint">build_lazy_constraint</a></code></li>
<li><code><a title="miplearn.instance.Instance.find_violated_lazy_constraints" href="../../instance.html#miplearn.instance.Instance.find_violated_lazy_constraints">find_violated_lazy_constraints</a></code></li>
<li><code><a title="miplearn.instance.Instance.get_instance_features" href="../../instance.html#miplearn.instance.Instance.get_instance_features">get_instance_features</a></code></li>
<li><code><a title="miplearn.instance.Instance.get_variable_category" href="../../instance.html#miplearn.instance.Instance.get_variable_category">get_variable_category</a></code></li>
<li><code><a title="miplearn.instance.Instance.get_variable_features" href="../../instance.html#miplearn.instance.Instance.get_variable_features">get_variable_features</a></code></li>
<li><code><a title="miplearn.instance.Instance.to_model" href="../../instance.html#miplearn.instance.Instance.to_model">to_model</a></code></li>
</ul>
</li>
</ul>
</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-submodules">Sub-modules</a></h3>
<ul>
<li><code><a title="miplearn.solvers.tests.test_internal_solver" href="test_internal_solver.html">miplearn.solvers.tests.test_internal_solver</a></code></li>
<li><code><a title="miplearn.solvers.tests.test_lazy_cb" href="test_lazy_cb.html">miplearn.solvers.tests.test_lazy_cb</a></code></li>
<li><code><a title="miplearn.solvers.tests.test_learning_solver" href="test_learning_solver.html">miplearn.solvers.tests.test_learning_solver</a></code></li>
</ul>
</li>
<li><h3><a href="#header-classes">Classes</a></h3>
<ul>
<li>
<h4><code><a title="miplearn.solvers.tests.InfeasibleGurobiInstance" href="#miplearn.solvers.tests.InfeasibleGurobiInstance">InfeasibleGurobiInstance</a></code></h4>
</li>
<li>
<h4><code><a title="miplearn.solvers.tests.InfeasiblePyomoInstance" href="#miplearn.solvers.tests.InfeasiblePyomoInstance">InfeasiblePyomoInstance</a></code></h4>
</li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc"><cite>pdoc</cite> 0.7.0</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>

View File

@@ -0,0 +1,543 @@
<!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.0" />
<title>miplearn.solvers.tests.test_internal_solver 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.tests.test_internal_solver</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 io import StringIO
from warnings import warn
import pyomo.environ as pe
from miplearn.solvers import _RedirectOutput
from miplearn.solvers.gurobi import GurobiSolver
from miplearn.solvers.pyomo.base import BasePyomoSolver
from miplearn.solvers.tests import (
_get_knapsack_instance,
_get_internal_solvers,
_get_infeasible_instance,
)
logger = logging.getLogger(__name__)
def test_redirect_output():
import sys
original_stdout = sys.stdout
io = StringIO()
with _RedirectOutput([io]):
print(&#34;Hello world&#34;)
assert sys.stdout == original_stdout
assert io.getvalue() == &#34;Hello world\n&#34;
def test_internal_solver_warm_starts():
for solver_class in _get_internal_solvers():
logger.info(&#34;Solver: %s&#34; % solver_class)
instance = _get_knapsack_instance(solver_class)
model = instance.to_model()
solver = solver_class()
solver.set_instance(instance, model)
solver.set_warm_start(
{
&#34;x&#34;: {
0: 1.0,
1: 0.0,
2: 0.0,
3: 1.0,
}
}
)
stats = solver.solve(tee=True)
if stats[&#34;Warm start value&#34;] is not None:
assert stats[&#34;Warm start value&#34;] == 725.0
else:
warn(f&#34;{solver_class.__name__} should set warm start value&#34;)
solver.set_warm_start(
{
&#34;x&#34;: {
0: 1.0,
1: 1.0,
2: 1.0,
3: 1.0,
}
}
)
stats = solver.solve(tee=True)
assert stats[&#34;Warm start value&#34;] is None
solver.fix(
{
&#34;x&#34;: {
0: 1.0,
1: 0.0,
2: 0.0,
3: 1.0,
}
}
)
stats = solver.solve(tee=True)
assert stats[&#34;Lower bound&#34;] == 725.0
assert stats[&#34;Upper bound&#34;] == 725.0
def test_internal_solver():
for solver_class in _get_internal_solvers():
logger.info(&#34;Solver: %s&#34; % solver_class)
instance = _get_knapsack_instance(solver_class)
model = instance.to_model()
solver = solver_class()
solver.set_instance(instance, model)
stats = solver.solve_lp()
assert not solver.is_infeasible()
assert round(stats[&#34;Optimal value&#34;], 3) == 1287.923
assert len(stats[&#34;Log&#34;]) &gt; 100
solution = solver.get_solution()
assert round(solution[&#34;x&#34;][0], 3) == 1.000
assert round(solution[&#34;x&#34;][1], 3) == 0.923
assert round(solution[&#34;x&#34;][2], 3) == 1.000
assert round(solution[&#34;x&#34;][3], 3) == 0.000
stats = solver.solve(tee=True)
assert not solver.is_infeasible()
assert len(stats[&#34;Log&#34;]) &gt; 100
assert stats[&#34;Lower bound&#34;] == 1183.0
assert stats[&#34;Upper bound&#34;] == 1183.0
assert stats[&#34;Sense&#34;] == &#34;max&#34;
assert isinstance(stats[&#34;Wallclock time&#34;], float)
solution = solver.get_solution()
assert solution[&#34;x&#34;][0] == 1.0
assert solution[&#34;x&#34;][1] == 0.0
assert solution[&#34;x&#34;][2] == 1.0
assert solution[&#34;x&#34;][3] == 1.0
# Add a brand new constraint
if isinstance(solver, BasePyomoSolver):
model.cut = pe.Constraint(expr=model.x[0] &lt;= 0.0, name=&#34;cut&#34;)
solver.add_constraint(model.cut)
elif isinstance(solver, GurobiSolver):
x = model.getVarByName(&#34;x[0]&#34;)
solver.add_constraint(x &lt;= 0.0, name=&#34;cut&#34;)
else:
raise Exception(&#34;Illegal state&#34;)
# New constraint should affect solution and should be listed in
# constraint ids
assert solver.get_constraint_ids() == [&#34;eq_capacity&#34;, &#34;cut&#34;]
stats = solver.solve()
assert stats[&#34;Lower bound&#34;] == 1030.0
assert solver.get_sense() == &#34;max&#34;
assert solver.get_constraint_sense(&#34;cut&#34;) == &#34;&lt;&#34;
assert solver.get_constraint_sense(&#34;eq_capacity&#34;) == &#34;&lt;&#34;
# Verify slacks
assert solver.get_inequality_slacks() == {
&#34;cut&#34;: 0.0,
&#34;eq_capacity&#34;: 3.0,
}
if isinstance(solver, GurobiSolver):
# Extract the new constraint
cobj = solver.extract_constraint(&#34;cut&#34;)
# New constraint should no longer affect solution and should no longer
# be listed in constraint ids
assert solver.get_constraint_ids() == [&#34;eq_capacity&#34;]
stats = solver.solve()
assert stats[&#34;Lower bound&#34;] == 1183.0
# New constraint should not be satisfied by current solution
assert not solver.is_constraint_satisfied(cobj)
# Re-add constraint
solver.add_constraint(cobj)
# Constraint should affect solution again
assert solver.get_constraint_ids() == [&#34;eq_capacity&#34;, &#34;cut&#34;]
stats = solver.solve()
assert stats[&#34;Lower bound&#34;] == 1030.0
# New constraint should now be satisfied
assert solver.is_constraint_satisfied(cobj)
# Relax problem and make cut into an equality constraint
solver.relax()
solver.set_constraint_sense(&#34;cut&#34;, &#34;=&#34;)
stats = solver.solve()
assert round(stats[&#34;Lower bound&#34;]) == 1030.0
assert round(solver.get_dual(&#34;eq_capacity&#34;)) == 0.0
def test_relax():
for solver_class in _get_internal_solvers():
instance = _get_knapsack_instance(solver_class)
solver = solver_class()
solver.set_instance(instance)
solver.relax()
stats = solver.solve()
assert round(stats[&#34;Lower bound&#34;]) == 1288.0
def test_infeasible_instance():
for solver_class in _get_internal_solvers():
instance = _get_infeasible_instance(solver_class)
solver = solver_class()
solver.set_instance(instance)
stats = solver.solve()
assert solver.is_infeasible()
assert solver.get_solution() is None
assert stats[&#34;Upper bound&#34;] is None
assert stats[&#34;Lower bound&#34;] is None
stats = solver.solve_lp()
assert solver.get_solution() is None
assert stats[&#34;Optimal value&#34;] is None
assert solver.get_value(&#34;x&#34;, 0) is None
def test_iteration_cb():
for solver_class in _get_internal_solvers():
logger.info(&#34;Solver: %s&#34; % solver_class)
instance = _get_knapsack_instance(solver_class)
solver = solver_class()
solver.set_instance(instance)
count = 0
def custom_iteration_cb():
nonlocal count
count += 1
return count &lt; 5
solver.solve(iteration_cb=custom_iteration_cb)
assert count == 5</code></pre>
</details>
</section>
<section>
</section>
<section>
</section>
<section>
<h2 class="section-title" id="header-functions">Functions</h2>
<dl>
<dt id="miplearn.solvers.tests.test_internal_solver.test_infeasible_instance"><code class="name flex">
<span>def <span class="ident">test_infeasible_instance</span></span>(<span>)</span>
</code></dt>
<dd>
<section class="desc"></section>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def test_infeasible_instance():
for solver_class in _get_internal_solvers():
instance = _get_infeasible_instance(solver_class)
solver = solver_class()
solver.set_instance(instance)
stats = solver.solve()
assert solver.is_infeasible()
assert solver.get_solution() is None
assert stats[&#34;Upper bound&#34;] is None
assert stats[&#34;Lower bound&#34;] is None
stats = solver.solve_lp()
assert solver.get_solution() is None
assert stats[&#34;Optimal value&#34;] is None
assert solver.get_value(&#34;x&#34;, 0) is None</code></pre>
</details>
</dd>
<dt id="miplearn.solvers.tests.test_internal_solver.test_internal_solver"><code class="name flex">
<span>def <span class="ident">test_internal_solver</span></span>(<span>)</span>
</code></dt>
<dd>
<section class="desc"></section>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def test_internal_solver():
for solver_class in _get_internal_solvers():
logger.info(&#34;Solver: %s&#34; % solver_class)
instance = _get_knapsack_instance(solver_class)
model = instance.to_model()
solver = solver_class()
solver.set_instance(instance, model)
stats = solver.solve_lp()
assert not solver.is_infeasible()
assert round(stats[&#34;Optimal value&#34;], 3) == 1287.923
assert len(stats[&#34;Log&#34;]) &gt; 100
solution = solver.get_solution()
assert round(solution[&#34;x&#34;][0], 3) == 1.000
assert round(solution[&#34;x&#34;][1], 3) == 0.923
assert round(solution[&#34;x&#34;][2], 3) == 1.000
assert round(solution[&#34;x&#34;][3], 3) == 0.000
stats = solver.solve(tee=True)
assert not solver.is_infeasible()
assert len(stats[&#34;Log&#34;]) &gt; 100
assert stats[&#34;Lower bound&#34;] == 1183.0
assert stats[&#34;Upper bound&#34;] == 1183.0
assert stats[&#34;Sense&#34;] == &#34;max&#34;
assert isinstance(stats[&#34;Wallclock time&#34;], float)
solution = solver.get_solution()
assert solution[&#34;x&#34;][0] == 1.0
assert solution[&#34;x&#34;][1] == 0.0
assert solution[&#34;x&#34;][2] == 1.0
assert solution[&#34;x&#34;][3] == 1.0
# Add a brand new constraint
if isinstance(solver, BasePyomoSolver):
model.cut = pe.Constraint(expr=model.x[0] &lt;= 0.0, name=&#34;cut&#34;)
solver.add_constraint(model.cut)
elif isinstance(solver, GurobiSolver):
x = model.getVarByName(&#34;x[0]&#34;)
solver.add_constraint(x &lt;= 0.0, name=&#34;cut&#34;)
else:
raise Exception(&#34;Illegal state&#34;)
# New constraint should affect solution and should be listed in
# constraint ids
assert solver.get_constraint_ids() == [&#34;eq_capacity&#34;, &#34;cut&#34;]
stats = solver.solve()
assert stats[&#34;Lower bound&#34;] == 1030.0
assert solver.get_sense() == &#34;max&#34;
assert solver.get_constraint_sense(&#34;cut&#34;) == &#34;&lt;&#34;
assert solver.get_constraint_sense(&#34;eq_capacity&#34;) == &#34;&lt;&#34;
# Verify slacks
assert solver.get_inequality_slacks() == {
&#34;cut&#34;: 0.0,
&#34;eq_capacity&#34;: 3.0,
}
if isinstance(solver, GurobiSolver):
# Extract the new constraint
cobj = solver.extract_constraint(&#34;cut&#34;)
# New constraint should no longer affect solution and should no longer
# be listed in constraint ids
assert solver.get_constraint_ids() == [&#34;eq_capacity&#34;]
stats = solver.solve()
assert stats[&#34;Lower bound&#34;] == 1183.0
# New constraint should not be satisfied by current solution
assert not solver.is_constraint_satisfied(cobj)
# Re-add constraint
solver.add_constraint(cobj)
# Constraint should affect solution again
assert solver.get_constraint_ids() == [&#34;eq_capacity&#34;, &#34;cut&#34;]
stats = solver.solve()
assert stats[&#34;Lower bound&#34;] == 1030.0
# New constraint should now be satisfied
assert solver.is_constraint_satisfied(cobj)
# Relax problem and make cut into an equality constraint
solver.relax()
solver.set_constraint_sense(&#34;cut&#34;, &#34;=&#34;)
stats = solver.solve()
assert round(stats[&#34;Lower bound&#34;]) == 1030.0
assert round(solver.get_dual(&#34;eq_capacity&#34;)) == 0.0</code></pre>
</details>
</dd>
<dt id="miplearn.solvers.tests.test_internal_solver.test_internal_solver_warm_starts"><code class="name flex">
<span>def <span class="ident">test_internal_solver_warm_starts</span></span>(<span>)</span>
</code></dt>
<dd>
<section class="desc"></section>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def test_internal_solver_warm_starts():
for solver_class in _get_internal_solvers():
logger.info(&#34;Solver: %s&#34; % solver_class)
instance = _get_knapsack_instance(solver_class)
model = instance.to_model()
solver = solver_class()
solver.set_instance(instance, model)
solver.set_warm_start(
{
&#34;x&#34;: {
0: 1.0,
1: 0.0,
2: 0.0,
3: 1.0,
}
}
)
stats = solver.solve(tee=True)
if stats[&#34;Warm start value&#34;] is not None:
assert stats[&#34;Warm start value&#34;] == 725.0
else:
warn(f&#34;{solver_class.__name__} should set warm start value&#34;)
solver.set_warm_start(
{
&#34;x&#34;: {
0: 1.0,
1: 1.0,
2: 1.0,
3: 1.0,
}
}
)
stats = solver.solve(tee=True)
assert stats[&#34;Warm start value&#34;] is None
solver.fix(
{
&#34;x&#34;: {
0: 1.0,
1: 0.0,
2: 0.0,
3: 1.0,
}
}
)
stats = solver.solve(tee=True)
assert stats[&#34;Lower bound&#34;] == 725.0
assert stats[&#34;Upper bound&#34;] == 725.0</code></pre>
</details>
</dd>
<dt id="miplearn.solvers.tests.test_internal_solver.test_iteration_cb"><code class="name flex">
<span>def <span class="ident">test_iteration_cb</span></span>(<span>)</span>
</code></dt>
<dd>
<section class="desc"></section>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def test_iteration_cb():
for solver_class in _get_internal_solvers():
logger.info(&#34;Solver: %s&#34; % solver_class)
instance = _get_knapsack_instance(solver_class)
solver = solver_class()
solver.set_instance(instance)
count = 0
def custom_iteration_cb():
nonlocal count
count += 1
return count &lt; 5
solver.solve(iteration_cb=custom_iteration_cb)
assert count == 5</code></pre>
</details>
</dd>
<dt id="miplearn.solvers.tests.test_internal_solver.test_redirect_output"><code class="name flex">
<span>def <span class="ident">test_redirect_output</span></span>(<span>)</span>
</code></dt>
<dd>
<section class="desc"></section>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def test_redirect_output():
import sys
original_stdout = sys.stdout
io = StringIO()
with _RedirectOutput([io]):
print(&#34;Hello world&#34;)
assert sys.stdout == original_stdout
assert io.getvalue() == &#34;Hello world\n&#34;</code></pre>
</details>
</dd>
<dt id="miplearn.solvers.tests.test_internal_solver.test_relax"><code class="name flex">
<span>def <span class="ident">test_relax</span></span>(<span>)</span>
</code></dt>
<dd>
<section class="desc"></section>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def test_relax():
for solver_class in _get_internal_solvers():
instance = _get_knapsack_instance(solver_class)
solver = solver_class()
solver.set_instance(instance)
solver.relax()
stats = solver.solve()
assert round(stats[&#34;Lower bound&#34;]) == 1288.0</code></pre>
</details>
</dd>
</dl>
</section>
<section>
</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.tests" href="index.html">miplearn.solvers.tests</a></code></li>
</ul>
</li>
<li><h3><a href="#header-functions">Functions</a></h3>
<ul class="">
<li><code><a title="miplearn.solvers.tests.test_internal_solver.test_infeasible_instance" href="#miplearn.solvers.tests.test_internal_solver.test_infeasible_instance">test_infeasible_instance</a></code></li>
<li><code><a title="miplearn.solvers.tests.test_internal_solver.test_internal_solver" href="#miplearn.solvers.tests.test_internal_solver.test_internal_solver">test_internal_solver</a></code></li>
<li><code><a title="miplearn.solvers.tests.test_internal_solver.test_internal_solver_warm_starts" href="#miplearn.solvers.tests.test_internal_solver.test_internal_solver_warm_starts">test_internal_solver_warm_starts</a></code></li>
<li><code><a title="miplearn.solvers.tests.test_internal_solver.test_iteration_cb" href="#miplearn.solvers.tests.test_internal_solver.test_iteration_cb">test_iteration_cb</a></code></li>
<li><code><a title="miplearn.solvers.tests.test_internal_solver.test_redirect_output" href="#miplearn.solvers.tests.test_internal_solver.test_redirect_output">test_redirect_output</a></code></li>
<li><code><a title="miplearn.solvers.tests.test_internal_solver.test_relax" href="#miplearn.solvers.tests.test_internal_solver.test_relax">test_relax</a></code></li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc"><cite>pdoc</cite> 0.7.0</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>

View File

@@ -0,0 +1,119 @@
<!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.0" />
<title>miplearn.solvers.tests.test_lazy_cb 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.tests.test_lazy_cb</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 miplearn.solvers.gurobi import GurobiSolver
from miplearn.solvers.tests import _get_knapsack_instance
logger = logging.getLogger(__name__)
def test_lazy_cb():
solver = GurobiSolver()
instance = _get_knapsack_instance(solver)
model = instance.to_model()
def lazy_cb(cb_solver, cb_model):
logger.info(&#34;x[0] = %.f&#34; % cb_solver.get_value(&#34;x&#34;, 0))
cobj = (cb_model.getVarByName(&#34;x[0]&#34;) * 1.0, &#34;&lt;&#34;, 0.0, &#34;cut&#34;)
if not cb_solver.is_constraint_satisfied(cobj):
cb_solver.add_constraint(cobj)
solver.set_instance(instance, model)
solver.solve(lazy_cb=lazy_cb)
solution = solver.get_solution()
assert solution[&#34;x&#34;][0] == 0.0</code></pre>
</details>
</section>
<section>
</section>
<section>
</section>
<section>
<h2 class="section-title" id="header-functions">Functions</h2>
<dl>
<dt id="miplearn.solvers.tests.test_lazy_cb.test_lazy_cb"><code class="name flex">
<span>def <span class="ident">test_lazy_cb</span></span>(<span>)</span>
</code></dt>
<dd>
<section class="desc"></section>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def test_lazy_cb():
solver = GurobiSolver()
instance = _get_knapsack_instance(solver)
model = instance.to_model()
def lazy_cb(cb_solver, cb_model):
logger.info(&#34;x[0] = %.f&#34; % cb_solver.get_value(&#34;x&#34;, 0))
cobj = (cb_model.getVarByName(&#34;x[0]&#34;) * 1.0, &#34;&lt;&#34;, 0.0, &#34;cut&#34;)
if not cb_solver.is_constraint_satisfied(cobj):
cb_solver.add_constraint(cobj)
solver.set_instance(instance, model)
solver.solve(lazy_cb=lazy_cb)
solution = solver.get_solution()
assert solution[&#34;x&#34;][0] == 0.0</code></pre>
</details>
</dd>
</dl>
</section>
<section>
</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.tests" href="index.html">miplearn.solvers.tests</a></code></li>
</ul>
</li>
<li><h3><a href="#header-functions">Functions</a></h3>
<ul class="">
<li><code><a title="miplearn.solvers.tests.test_lazy_cb.test_lazy_cb" href="#miplearn.solvers.tests.test_lazy_cb.test_lazy_cb">test_lazy_cb</a></code></li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc"><cite>pdoc</cite> 0.7.0</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>

View File

@@ -0,0 +1,365 @@
<!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.0" />
<title>miplearn.solvers.tests.test_learning_solver 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.tests.test_learning_solver</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
import pickle
import tempfile
import os
from miplearn.solvers.gurobi import GurobiSolver
from miplearn.solvers.learning import LearningSolver
from miplearn.solvers.tests import _get_knapsack_instance, _get_internal_solvers
logger = logging.getLogger(__name__)
def test_learning_solver():
for mode in [&#34;exact&#34;, &#34;heuristic&#34;]:
for internal_solver in _get_internal_solvers():
logger.info(&#34;Solver: %s&#34; % internal_solver)
instance = _get_knapsack_instance(internal_solver)
solver = LearningSolver(
solver=internal_solver,
mode=mode,
)
solver.solve(instance)
data = instance.training_data[0]
assert data[&#34;Solution&#34;][&#34;x&#34;][0] == 1.0
assert data[&#34;Solution&#34;][&#34;x&#34;][1] == 0.0
assert data[&#34;Solution&#34;][&#34;x&#34;][2] == 1.0
assert data[&#34;Solution&#34;][&#34;x&#34;][3] == 1.0
assert data[&#34;Lower bound&#34;] == 1183.0
assert data[&#34;Upper bound&#34;] == 1183.0
assert round(data[&#34;LP solution&#34;][&#34;x&#34;][0], 3) == 1.000
assert round(data[&#34;LP solution&#34;][&#34;x&#34;][1], 3) == 0.923
assert round(data[&#34;LP solution&#34;][&#34;x&#34;][2], 3) == 1.000
assert round(data[&#34;LP solution&#34;][&#34;x&#34;][3], 3) == 0.000
assert round(data[&#34;LP value&#34;], 3) == 1287.923
assert len(data[&#34;MIP log&#34;]) &gt; 100
solver.fit([instance])
solver.solve(instance)
# Assert solver is picklable
with tempfile.TemporaryFile() as file:
pickle.dump(solver, file)
def test_solve_without_lp():
for internal_solver in _get_internal_solvers():
logger.info(&#34;Solver: %s&#34; % internal_solver)
instance = _get_knapsack_instance(internal_solver)
solver = LearningSolver(
solver=internal_solver,
solve_lp_first=False,
)
solver.solve(instance)
solver.fit([instance])
solver.solve(instance)
def test_parallel_solve():
for internal_solver in _get_internal_solvers():
instances = [_get_knapsack_instance(internal_solver) for _ in range(10)]
solver = LearningSolver(solver=internal_solver)
results = solver.parallel_solve(instances, n_jobs=3)
assert len(results) == 10
for instance in instances:
data = instance.training_data[0]
assert len(data[&#34;Solution&#34;][&#34;x&#34;].keys()) == 4
def test_solve_fit_from_disk():
for internal_solver in _get_internal_solvers():
# Create instances and pickle them
filenames = []
for k in range(3):
instance = _get_knapsack_instance(internal_solver)
with tempfile.NamedTemporaryFile(suffix=&#34;.pkl&#34;, delete=False) as file:
filenames += [file.name]
pickle.dump(instance, file)
# Test: solve
solver = LearningSolver(solver=internal_solver)
solver.solve(filenames[0])
with open(filenames[0], &#34;rb&#34;) as file:
instance = pickle.load(file)
assert len(instance.training_data) &gt; 0
# Test: parallel_solve
solver.parallel_solve(filenames)
for filename in filenames:
with open(filename, &#34;rb&#34;) as file:
instance = pickle.load(file)
assert len(instance.training_data) &gt; 0
# Test: solve (with specified output)
output = [f + &#34;.out&#34; for f in filenames]
solver.solve(
filenames[0],
output_filename=output[0],
)
assert os.path.isfile(output[0])
# Test: parallel_solve (with specified output)
solver.parallel_solve(
filenames,
output_filenames=output,
)
for filename in output:
assert os.path.isfile(filename)
# Delete temporary files
for filename in filenames:
os.remove(filename)
for filename in output:
os.remove(filename)
def test_simulate_perfect():
internal_solver = GurobiSolver
instance = _get_knapsack_instance(internal_solver)
with tempfile.NamedTemporaryFile(suffix=&#34;.pkl&#34;, delete=False) as tmp:
pickle.dump(instance, tmp)
tmp.flush()
solver = LearningSolver(
solver=internal_solver,
simulate_perfect=True,
)
stats = solver.solve(tmp.name)
assert stats[&#34;Lower bound&#34;] == stats[&#34;Predicted LB&#34;]</code></pre>
</details>
</section>
<section>
</section>
<section>
</section>
<section>
<h2 class="section-title" id="header-functions">Functions</h2>
<dl>
<dt id="miplearn.solvers.tests.test_learning_solver.test_learning_solver"><code class="name flex">
<span>def <span class="ident">test_learning_solver</span></span>(<span>)</span>
</code></dt>
<dd>
<section class="desc"></section>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def test_learning_solver():
for mode in [&#34;exact&#34;, &#34;heuristic&#34;]:
for internal_solver in _get_internal_solvers():
logger.info(&#34;Solver: %s&#34; % internal_solver)
instance = _get_knapsack_instance(internal_solver)
solver = LearningSolver(
solver=internal_solver,
mode=mode,
)
solver.solve(instance)
data = instance.training_data[0]
assert data[&#34;Solution&#34;][&#34;x&#34;][0] == 1.0
assert data[&#34;Solution&#34;][&#34;x&#34;][1] == 0.0
assert data[&#34;Solution&#34;][&#34;x&#34;][2] == 1.0
assert data[&#34;Solution&#34;][&#34;x&#34;][3] == 1.0
assert data[&#34;Lower bound&#34;] == 1183.0
assert data[&#34;Upper bound&#34;] == 1183.0
assert round(data[&#34;LP solution&#34;][&#34;x&#34;][0], 3) == 1.000
assert round(data[&#34;LP solution&#34;][&#34;x&#34;][1], 3) == 0.923
assert round(data[&#34;LP solution&#34;][&#34;x&#34;][2], 3) == 1.000
assert round(data[&#34;LP solution&#34;][&#34;x&#34;][3], 3) == 0.000
assert round(data[&#34;LP value&#34;], 3) == 1287.923
assert len(data[&#34;MIP log&#34;]) &gt; 100
solver.fit([instance])
solver.solve(instance)
# Assert solver is picklable
with tempfile.TemporaryFile() as file:
pickle.dump(solver, file)</code></pre>
</details>
</dd>
<dt id="miplearn.solvers.tests.test_learning_solver.test_parallel_solve"><code class="name flex">
<span>def <span class="ident">test_parallel_solve</span></span>(<span>)</span>
</code></dt>
<dd>
<section class="desc"></section>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def test_parallel_solve():
for internal_solver in _get_internal_solvers():
instances = [_get_knapsack_instance(internal_solver) for _ in range(10)]
solver = LearningSolver(solver=internal_solver)
results = solver.parallel_solve(instances, n_jobs=3)
assert len(results) == 10
for instance in instances:
data = instance.training_data[0]
assert len(data[&#34;Solution&#34;][&#34;x&#34;].keys()) == 4</code></pre>
</details>
</dd>
<dt id="miplearn.solvers.tests.test_learning_solver.test_simulate_perfect"><code class="name flex">
<span>def <span class="ident">test_simulate_perfect</span></span>(<span>)</span>
</code></dt>
<dd>
<section class="desc"></section>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def test_simulate_perfect():
internal_solver = GurobiSolver
instance = _get_knapsack_instance(internal_solver)
with tempfile.NamedTemporaryFile(suffix=&#34;.pkl&#34;, delete=False) as tmp:
pickle.dump(instance, tmp)
tmp.flush()
solver = LearningSolver(
solver=internal_solver,
simulate_perfect=True,
)
stats = solver.solve(tmp.name)
assert stats[&#34;Lower bound&#34;] == stats[&#34;Predicted LB&#34;]</code></pre>
</details>
</dd>
<dt id="miplearn.solvers.tests.test_learning_solver.test_solve_fit_from_disk"><code class="name flex">
<span>def <span class="ident">test_solve_fit_from_disk</span></span>(<span>)</span>
</code></dt>
<dd>
<section class="desc"></section>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def test_solve_fit_from_disk():
for internal_solver in _get_internal_solvers():
# Create instances and pickle them
filenames = []
for k in range(3):
instance = _get_knapsack_instance(internal_solver)
with tempfile.NamedTemporaryFile(suffix=&#34;.pkl&#34;, delete=False) as file:
filenames += [file.name]
pickle.dump(instance, file)
# Test: solve
solver = LearningSolver(solver=internal_solver)
solver.solve(filenames[0])
with open(filenames[0], &#34;rb&#34;) as file:
instance = pickle.load(file)
assert len(instance.training_data) &gt; 0
# Test: parallel_solve
solver.parallel_solve(filenames)
for filename in filenames:
with open(filename, &#34;rb&#34;) as file:
instance = pickle.load(file)
assert len(instance.training_data) &gt; 0
# Test: solve (with specified output)
output = [f + &#34;.out&#34; for f in filenames]
solver.solve(
filenames[0],
output_filename=output[0],
)
assert os.path.isfile(output[0])
# Test: parallel_solve (with specified output)
solver.parallel_solve(
filenames,
output_filenames=output,
)
for filename in output:
assert os.path.isfile(filename)
# Delete temporary files
for filename in filenames:
os.remove(filename)
for filename in output:
os.remove(filename)</code></pre>
</details>
</dd>
<dt id="miplearn.solvers.tests.test_learning_solver.test_solve_without_lp"><code class="name flex">
<span>def <span class="ident">test_solve_without_lp</span></span>(<span>)</span>
</code></dt>
<dd>
<section class="desc"></section>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def test_solve_without_lp():
for internal_solver in _get_internal_solvers():
logger.info(&#34;Solver: %s&#34; % internal_solver)
instance = _get_knapsack_instance(internal_solver)
solver = LearningSolver(
solver=internal_solver,
solve_lp_first=False,
)
solver.solve(instance)
solver.fit([instance])
solver.solve(instance)</code></pre>
</details>
</dd>
</dl>
</section>
<section>
</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.tests" href="index.html">miplearn.solvers.tests</a></code></li>
</ul>
</li>
<li><h3><a href="#header-functions">Functions</a></h3>
<ul class="">
<li><code><a title="miplearn.solvers.tests.test_learning_solver.test_learning_solver" href="#miplearn.solvers.tests.test_learning_solver.test_learning_solver">test_learning_solver</a></code></li>
<li><code><a title="miplearn.solvers.tests.test_learning_solver.test_parallel_solve" href="#miplearn.solvers.tests.test_learning_solver.test_parallel_solve">test_parallel_solve</a></code></li>
<li><code><a title="miplearn.solvers.tests.test_learning_solver.test_simulate_perfect" href="#miplearn.solvers.tests.test_learning_solver.test_simulate_perfect">test_simulate_perfect</a></code></li>
<li><code><a title="miplearn.solvers.tests.test_learning_solver.test_solve_fit_from_disk" href="#miplearn.solvers.tests.test_learning_solver.test_solve_fit_from_disk">test_solve_fit_from_disk</a></code></li>
<li><code><a title="miplearn.solvers.tests.test_learning_solver.test_solve_without_lp" href="#miplearn.solvers.tests.test_learning_solver.test_solve_without_lp">test_solve_without_lp</a></code></li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc"><cite>pdoc</cite> 0.7.0</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>