mirror of
https://github.com/ANL-CEEESA/MIPLearn.git
synced 2025-12-06 01:18:52 -06:00
Update 0.2 docs
This commit is contained in:
6
.pre-commit-config.yaml
Normal file
6
.pre-commit-config.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
repos:
|
||||
- repo: https://github.com/ambv/black
|
||||
rev: stable
|
||||
hooks:
|
||||
- id: black
|
||||
args: ["--check"]
|
||||
@@ -105,6 +105,12 @@
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
<li >
|
||||
<a href="/api/miplearn/index.html">API</a>
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
|
||||
@@ -105,6 +105,12 @@
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
<li >
|
||||
<a href="../api/miplearn/index.html">API</a>
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
|
||||
433
0.2/api/miplearn/benchmark.html
Normal file
433
0.2/api/miplearn/benchmark.html
Normal file
@@ -0,0 +1,433 @@
|
||||
<!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.benchmark 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.benchmark</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 os
|
||||
from copy import deepcopy
|
||||
|
||||
import pandas as pd
|
||||
from tqdm.auto import tqdm
|
||||
|
||||
from miplearn.solvers.learning import LearningSolver
|
||||
|
||||
|
||||
class BenchmarkRunner:
|
||||
def __init__(self, solvers):
|
||||
assert isinstance(solvers, dict)
|
||||
for solver in solvers.values():
|
||||
assert isinstance(solver, LearningSolver)
|
||||
self.solvers = solvers
|
||||
self.results = None
|
||||
|
||||
def solve(self, instances, tee=False):
|
||||
for (solver_name, solver) in self.solvers.items():
|
||||
for i in tqdm(range(len((instances)))):
|
||||
results = solver.solve(deepcopy(instances[i]), tee=tee)
|
||||
self._push_result(
|
||||
results,
|
||||
solver=solver,
|
||||
solver_name=solver_name,
|
||||
instance=i,
|
||||
)
|
||||
|
||||
def parallel_solve(
|
||||
self,
|
||||
instances,
|
||||
n_jobs=1,
|
||||
n_trials=1,
|
||||
index_offset=0,
|
||||
):
|
||||
self._silence_miplearn_logger()
|
||||
trials = instances * n_trials
|
||||
for (solver_name, solver) in self.solvers.items():
|
||||
results = solver.parallel_solve(
|
||||
trials,
|
||||
n_jobs=n_jobs,
|
||||
label="Solve (%s)" % solver_name,
|
||||
discard_outputs=True,
|
||||
)
|
||||
for i in range(len(trials)):
|
||||
idx = (i % len(instances)) + index_offset
|
||||
self._push_result(
|
||||
results[i],
|
||||
solver=solver,
|
||||
solver_name=solver_name,
|
||||
instance=idx,
|
||||
)
|
||||
self._restore_miplearn_logger()
|
||||
|
||||
def raw_results(self):
|
||||
return self.results
|
||||
|
||||
def save_results(self, filename):
|
||||
os.makedirs(os.path.dirname(filename), exist_ok=True)
|
||||
self.results.to_csv(filename)
|
||||
|
||||
def load_results(self, filename):
|
||||
self.results = pd.concat([self.results, pd.read_csv(filename, index_col=0)])
|
||||
|
||||
def load_state(self, filename):
|
||||
for (solver_name, solver) in self.solvers.items():
|
||||
solver.load_state(filename)
|
||||
|
||||
def fit(self, training_instances):
|
||||
for (solver_name, solver) in self.solvers.items():
|
||||
solver.fit(training_instances)
|
||||
|
||||
@staticmethod
|
||||
def _compute_gap(ub, lb):
|
||||
if lb is None or ub is None or lb * ub < 0:
|
||||
# solver did not find a solution and/or bound, use maximum gap possible
|
||||
return 1.0
|
||||
elif abs(ub - lb) < 1e-6:
|
||||
# avoid division by zero when ub = lb = 0
|
||||
return 0.0
|
||||
else:
|
||||
# divide by max(abs(ub),abs(lb)) to ensure gap <= 1
|
||||
return (ub - lb) / max(abs(ub), abs(lb))
|
||||
|
||||
def _push_result(self, result, solver, solver_name, instance):
|
||||
if self.results is None:
|
||||
self.results = pd.DataFrame(
|
||||
# Show the following columns first in the CSV file
|
||||
columns=[
|
||||
"Solver",
|
||||
"Instance",
|
||||
]
|
||||
)
|
||||
result["Solver"] = solver_name
|
||||
result["Instance"] = instance
|
||||
result["Gap"] = self._compute_gap(
|
||||
ub=result["Upper bound"],
|
||||
lb=result["Lower bound"],
|
||||
)
|
||||
result["Mode"] = solver.mode
|
||||
self.results = self.results.append(pd.DataFrame([result]))
|
||||
|
||||
def _silence_miplearn_logger(self):
|
||||
miplearn_logger = logging.getLogger("miplearn")
|
||||
self.prev_log_level = miplearn_logger.getEffectiveLevel()
|
||||
miplearn_logger.setLevel(logging.WARNING)
|
||||
|
||||
def _restore_miplearn_logger(self):
|
||||
miplearn_logger = logging.getLogger("miplearn")
|
||||
miplearn_logger.setLevel(self.prev_log_level)</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-classes">Classes</h2>
|
||||
<dl>
|
||||
<dt id="miplearn.benchmark.BenchmarkRunner"><code class="flex name class">
|
||||
<span>class <span class="ident">BenchmarkRunner</span></span>
|
||||
<span>(</span><span>solvers)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">class BenchmarkRunner:
|
||||
def __init__(self, solvers):
|
||||
assert isinstance(solvers, dict)
|
||||
for solver in solvers.values():
|
||||
assert isinstance(solver, LearningSolver)
|
||||
self.solvers = solvers
|
||||
self.results = None
|
||||
|
||||
def solve(self, instances, tee=False):
|
||||
for (solver_name, solver) in self.solvers.items():
|
||||
for i in tqdm(range(len((instances)))):
|
||||
results = solver.solve(deepcopy(instances[i]), tee=tee)
|
||||
self._push_result(
|
||||
results,
|
||||
solver=solver,
|
||||
solver_name=solver_name,
|
||||
instance=i,
|
||||
)
|
||||
|
||||
def parallel_solve(
|
||||
self,
|
||||
instances,
|
||||
n_jobs=1,
|
||||
n_trials=1,
|
||||
index_offset=0,
|
||||
):
|
||||
self._silence_miplearn_logger()
|
||||
trials = instances * n_trials
|
||||
for (solver_name, solver) in self.solvers.items():
|
||||
results = solver.parallel_solve(
|
||||
trials,
|
||||
n_jobs=n_jobs,
|
||||
label="Solve (%s)" % solver_name,
|
||||
discard_outputs=True,
|
||||
)
|
||||
for i in range(len(trials)):
|
||||
idx = (i % len(instances)) + index_offset
|
||||
self._push_result(
|
||||
results[i],
|
||||
solver=solver,
|
||||
solver_name=solver_name,
|
||||
instance=idx,
|
||||
)
|
||||
self._restore_miplearn_logger()
|
||||
|
||||
def raw_results(self):
|
||||
return self.results
|
||||
|
||||
def save_results(self, filename):
|
||||
os.makedirs(os.path.dirname(filename), exist_ok=True)
|
||||
self.results.to_csv(filename)
|
||||
|
||||
def load_results(self, filename):
|
||||
self.results = pd.concat([self.results, pd.read_csv(filename, index_col=0)])
|
||||
|
||||
def load_state(self, filename):
|
||||
for (solver_name, solver) in self.solvers.items():
|
||||
solver.load_state(filename)
|
||||
|
||||
def fit(self, training_instances):
|
||||
for (solver_name, solver) in self.solvers.items():
|
||||
solver.fit(training_instances)
|
||||
|
||||
@staticmethod
|
||||
def _compute_gap(ub, lb):
|
||||
if lb is None or ub is None or lb * ub < 0:
|
||||
# solver did not find a solution and/or bound, use maximum gap possible
|
||||
return 1.0
|
||||
elif abs(ub - lb) < 1e-6:
|
||||
# avoid division by zero when ub = lb = 0
|
||||
return 0.0
|
||||
else:
|
||||
# divide by max(abs(ub),abs(lb)) to ensure gap <= 1
|
||||
return (ub - lb) / max(abs(ub), abs(lb))
|
||||
|
||||
def _push_result(self, result, solver, solver_name, instance):
|
||||
if self.results is None:
|
||||
self.results = pd.DataFrame(
|
||||
# Show the following columns first in the CSV file
|
||||
columns=[
|
||||
"Solver",
|
||||
"Instance",
|
||||
]
|
||||
)
|
||||
result["Solver"] = solver_name
|
||||
result["Instance"] = instance
|
||||
result["Gap"] = self._compute_gap(
|
||||
ub=result["Upper bound"],
|
||||
lb=result["Lower bound"],
|
||||
)
|
||||
result["Mode"] = solver.mode
|
||||
self.results = self.results.append(pd.DataFrame([result]))
|
||||
|
||||
def _silence_miplearn_logger(self):
|
||||
miplearn_logger = logging.getLogger("miplearn")
|
||||
self.prev_log_level = miplearn_logger.getEffectiveLevel()
|
||||
miplearn_logger.setLevel(logging.WARNING)
|
||||
|
||||
def _restore_miplearn_logger(self):
|
||||
miplearn_logger = logging.getLogger("miplearn")
|
||||
miplearn_logger.setLevel(self.prev_log_level)</code></pre>
|
||||
</details>
|
||||
<h3>Methods</h3>
|
||||
<dl>
|
||||
<dt id="miplearn.benchmark.BenchmarkRunner.fit"><code class="name flex">
|
||||
<span>def <span class="ident">fit</span></span>(<span>self, training_instances)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def fit(self, training_instances):
|
||||
for (solver_name, solver) in self.solvers.items():
|
||||
solver.fit(training_instances)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.benchmark.BenchmarkRunner.load_results"><code class="name flex">
|
||||
<span>def <span class="ident">load_results</span></span>(<span>self, filename)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def load_results(self, filename):
|
||||
self.results = pd.concat([self.results, pd.read_csv(filename, index_col=0)])</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.benchmark.BenchmarkRunner.load_state"><code class="name flex">
|
||||
<span>def <span class="ident">load_state</span></span>(<span>self, filename)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def load_state(self, filename):
|
||||
for (solver_name, solver) in self.solvers.items():
|
||||
solver.load_state(filename)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.benchmark.BenchmarkRunner.parallel_solve"><code class="name flex">
|
||||
<span>def <span class="ident">parallel_solve</span></span>(<span>self, instances, n_jobs=1, n_trials=1, index_offset=0)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def parallel_solve(
|
||||
self,
|
||||
instances,
|
||||
n_jobs=1,
|
||||
n_trials=1,
|
||||
index_offset=0,
|
||||
):
|
||||
self._silence_miplearn_logger()
|
||||
trials = instances * n_trials
|
||||
for (solver_name, solver) in self.solvers.items():
|
||||
results = solver.parallel_solve(
|
||||
trials,
|
||||
n_jobs=n_jobs,
|
||||
label="Solve (%s)" % solver_name,
|
||||
discard_outputs=True,
|
||||
)
|
||||
for i in range(len(trials)):
|
||||
idx = (i % len(instances)) + index_offset
|
||||
self._push_result(
|
||||
results[i],
|
||||
solver=solver,
|
||||
solver_name=solver_name,
|
||||
instance=idx,
|
||||
)
|
||||
self._restore_miplearn_logger()</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.benchmark.BenchmarkRunner.raw_results"><code class="name flex">
|
||||
<span>def <span class="ident">raw_results</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def raw_results(self):
|
||||
return self.results</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.benchmark.BenchmarkRunner.save_results"><code class="name flex">
|
||||
<span>def <span class="ident">save_results</span></span>(<span>self, filename)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def save_results(self, filename):
|
||||
os.makedirs(os.path.dirname(filename), exist_ok=True)
|
||||
self.results.to_csv(filename)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.benchmark.BenchmarkRunner.solve"><code class="name flex">
|
||||
<span>def <span class="ident">solve</span></span>(<span>self, instances, tee=False)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def solve(self, instances, tee=False):
|
||||
for (solver_name, solver) in self.solvers.items():
|
||||
for i in tqdm(range(len((instances)))):
|
||||
results = solver.solve(deepcopy(instances[i]), tee=tee)
|
||||
self._push_result(
|
||||
results,
|
||||
solver=solver,
|
||||
solver_name=solver_name,
|
||||
instance=i,
|
||||
)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</section>
|
||||
</article>
|
||||
<nav id="sidebar">
|
||||
<h1>Index</h1>
|
||||
<div class="toc">
|
||||
<ul></ul>
|
||||
</div>
|
||||
<ul id="index">
|
||||
<li><h3>Super-module</h3>
|
||||
<ul>
|
||||
<li><code><a title="miplearn" href="index.html">miplearn</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-classes">Classes</a></h3>
|
||||
<ul>
|
||||
<li>
|
||||
<h4><code><a title="miplearn.benchmark.BenchmarkRunner" href="#miplearn.benchmark.BenchmarkRunner">BenchmarkRunner</a></code></h4>
|
||||
<ul class="two-column">
|
||||
<li><code><a title="miplearn.benchmark.BenchmarkRunner.fit" href="#miplearn.benchmark.BenchmarkRunner.fit">fit</a></code></li>
|
||||
<li><code><a title="miplearn.benchmark.BenchmarkRunner.load_results" href="#miplearn.benchmark.BenchmarkRunner.load_results">load_results</a></code></li>
|
||||
<li><code><a title="miplearn.benchmark.BenchmarkRunner.load_state" href="#miplearn.benchmark.BenchmarkRunner.load_state">load_state</a></code></li>
|
||||
<li><code><a title="miplearn.benchmark.BenchmarkRunner.parallel_solve" href="#miplearn.benchmark.BenchmarkRunner.parallel_solve">parallel_solve</a></code></li>
|
||||
<li><code><a title="miplearn.benchmark.BenchmarkRunner.raw_results" href="#miplearn.benchmark.BenchmarkRunner.raw_results">raw_results</a></code></li>
|
||||
<li><code><a title="miplearn.benchmark.BenchmarkRunner.save_results" href="#miplearn.benchmark.BenchmarkRunner.save_results">save_results</a></code></li>
|
||||
<li><code><a title="miplearn.benchmark.BenchmarkRunner.solve" href="#miplearn.benchmark.BenchmarkRunner.solve">solve</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</main>
|
||||
<footer id="footer">
|
||||
<p>Generated by <a href="https://pdoc3.github.io/pdoc"><cite>pdoc</cite> 0.7.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>
|
||||
249
0.2/api/miplearn/classifiers/adaptive.html
Normal file
249
0.2/api/miplearn/classifiers/adaptive.html
Normal file
@@ -0,0 +1,249 @@
|
||||
<!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.classifiers.adaptive 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.classifiers.adaptive</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 copy import deepcopy
|
||||
from typing import Any, Dict
|
||||
|
||||
from sklearn.linear_model import LogisticRegression
|
||||
from sklearn.neighbors import KNeighborsClassifier
|
||||
from sklearn.pipeline import make_pipeline
|
||||
from sklearn.preprocessing import StandardScaler
|
||||
|
||||
from miplearn.classifiers import Classifier
|
||||
from miplearn.classifiers.counting import CountingClassifier
|
||||
from miplearn.classifiers.evaluator import ClassifierEvaluator
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AdaptiveClassifier(Classifier):
|
||||
"""
|
||||
A meta-classifier which dynamically selects what actual classifier to use
|
||||
based on its cross-validation score on a particular training data set.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
candidates: Dict[str, Any] = None,
|
||||
evaluator: ClassifierEvaluator = ClassifierEvaluator(),
|
||||
) -> None:
|
||||
"""
|
||||
Initializes the meta-classifier.
|
||||
"""
|
||||
if candidates is None:
|
||||
candidates = {
|
||||
"knn(100)": {
|
||||
"classifier": KNeighborsClassifier(n_neighbors=100),
|
||||
"min samples": 100,
|
||||
},
|
||||
"logistic": {
|
||||
"classifier": make_pipeline(StandardScaler(), LogisticRegression()),
|
||||
"min samples": 30,
|
||||
},
|
||||
"counting": {
|
||||
"classifier": CountingClassifier(),
|
||||
"min samples": 0,
|
||||
},
|
||||
}
|
||||
self.candidates = candidates
|
||||
self.evaluator = evaluator
|
||||
self.classifier = None
|
||||
|
||||
def fit(self, x_train, y_train):
|
||||
best_name, best_clf, best_score = None, None, -float("inf")
|
||||
n_samples = x_train.shape[0]
|
||||
for (name, clf_dict) in self.candidates.items():
|
||||
if n_samples < clf_dict["min samples"]:
|
||||
continue
|
||||
clf = deepcopy(clf_dict["classifier"])
|
||||
clf.fit(x_train, y_train)
|
||||
score = self.evaluator.evaluate(clf, x_train, y_train)
|
||||
if score > best_score:
|
||||
best_name, best_clf, best_score = name, clf, score
|
||||
logger.debug("Best classifier: %s (score=%.3f)" % (best_name, best_score))
|
||||
self.classifier = best_clf
|
||||
|
||||
def predict_proba(self, x_test):
|
||||
return self.classifier.predict_proba(x_test)</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-classes">Classes</h2>
|
||||
<dl>
|
||||
<dt id="miplearn.classifiers.adaptive.AdaptiveClassifier"><code class="flex name class">
|
||||
<span>class <span class="ident">AdaptiveClassifier</span></span>
|
||||
<span>(</span><span>candidates=None, evaluator=<miplearn.classifiers.evaluator.ClassifierEvaluator object>)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"><p>A meta-classifier which dynamically selects what actual classifier to use
|
||||
based on its cross-validation score on a particular training data set.</p>
|
||||
<p>Initializes the meta-classifier.</p></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">class AdaptiveClassifier(Classifier):
|
||||
"""
|
||||
A meta-classifier which dynamically selects what actual classifier to use
|
||||
based on its cross-validation score on a particular training data set.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
candidates: Dict[str, Any] = None,
|
||||
evaluator: ClassifierEvaluator = ClassifierEvaluator(),
|
||||
) -> None:
|
||||
"""
|
||||
Initializes the meta-classifier.
|
||||
"""
|
||||
if candidates is None:
|
||||
candidates = {
|
||||
"knn(100)": {
|
||||
"classifier": KNeighborsClassifier(n_neighbors=100),
|
||||
"min samples": 100,
|
||||
},
|
||||
"logistic": {
|
||||
"classifier": make_pipeline(StandardScaler(), LogisticRegression()),
|
||||
"min samples": 30,
|
||||
},
|
||||
"counting": {
|
||||
"classifier": CountingClassifier(),
|
||||
"min samples": 0,
|
||||
},
|
||||
}
|
||||
self.candidates = candidates
|
||||
self.evaluator = evaluator
|
||||
self.classifier = None
|
||||
|
||||
def fit(self, x_train, y_train):
|
||||
best_name, best_clf, best_score = None, None, -float("inf")
|
||||
n_samples = x_train.shape[0]
|
||||
for (name, clf_dict) in self.candidates.items():
|
||||
if n_samples < clf_dict["min samples"]:
|
||||
continue
|
||||
clf = deepcopy(clf_dict["classifier"])
|
||||
clf.fit(x_train, y_train)
|
||||
score = self.evaluator.evaluate(clf, x_train, y_train)
|
||||
if score > best_score:
|
||||
best_name, best_clf, best_score = name, clf, score
|
||||
logger.debug("Best classifier: %s (score=%.3f)" % (best_name, best_score))
|
||||
self.classifier = best_clf
|
||||
|
||||
def predict_proba(self, x_test):
|
||||
return self.classifier.predict_proba(x_test)</code></pre>
|
||||
</details>
|
||||
<h3>Ancestors</h3>
|
||||
<ul class="hlist">
|
||||
<li><a title="miplearn.classifiers.Classifier" href="index.html#miplearn.classifiers.Classifier">Classifier</a></li>
|
||||
<li>abc.ABC</li>
|
||||
</ul>
|
||||
<h3>Methods</h3>
|
||||
<dl>
|
||||
<dt id="miplearn.classifiers.adaptive.AdaptiveClassifier.fit"><code class="name flex">
|
||||
<span>def <span class="ident">fit</span></span>(<span>self, x_train, y_train)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def fit(self, x_train, y_train):
|
||||
best_name, best_clf, best_score = None, None, -float("inf")
|
||||
n_samples = x_train.shape[0]
|
||||
for (name, clf_dict) in self.candidates.items():
|
||||
if n_samples < clf_dict["min samples"]:
|
||||
continue
|
||||
clf = deepcopy(clf_dict["classifier"])
|
||||
clf.fit(x_train, y_train)
|
||||
score = self.evaluator.evaluate(clf, x_train, y_train)
|
||||
if score > best_score:
|
||||
best_name, best_clf, best_score = name, clf, score
|
||||
logger.debug("Best classifier: %s (score=%.3f)" % (best_name, best_score))
|
||||
self.classifier = best_clf</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.classifiers.adaptive.AdaptiveClassifier.predict_proba"><code class="name flex">
|
||||
<span>def <span class="ident">predict_proba</span></span>(<span>self, x_test)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def predict_proba(self, x_test):
|
||||
return self.classifier.predict_proba(x_test)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</section>
|
||||
</article>
|
||||
<nav id="sidebar">
|
||||
<h1>Index</h1>
|
||||
<div class="toc">
|
||||
<ul></ul>
|
||||
</div>
|
||||
<ul id="index">
|
||||
<li><h3>Super-module</h3>
|
||||
<ul>
|
||||
<li><code><a title="miplearn.classifiers" href="index.html">miplearn.classifiers</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-classes">Classes</a></h3>
|
||||
<ul>
|
||||
<li>
|
||||
<h4><code><a title="miplearn.classifiers.adaptive.AdaptiveClassifier" href="#miplearn.classifiers.adaptive.AdaptiveClassifier">AdaptiveClassifier</a></code></h4>
|
||||
<ul class="">
|
||||
<li><code><a title="miplearn.classifiers.adaptive.AdaptiveClassifier.fit" href="#miplearn.classifiers.adaptive.AdaptiveClassifier.fit">fit</a></code></li>
|
||||
<li><code><a title="miplearn.classifiers.adaptive.AdaptiveClassifier.predict_proba" href="#miplearn.classifiers.adaptive.AdaptiveClassifier.predict_proba">predict_proba</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</main>
|
||||
<footer id="footer">
|
||||
<p>Generated by <a href="https://pdoc3.github.io/pdoc"><cite>pdoc</cite> 0.7.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>
|
||||
167
0.2/api/miplearn/classifiers/counting.html
Normal file
167
0.2/api/miplearn/classifiers/counting.html
Normal file
@@ -0,0 +1,167 @@
|
||||
<!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.classifiers.counting 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.classifiers.counting</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 numpy as np
|
||||
|
||||
from miplearn.classifiers import Classifier
|
||||
|
||||
|
||||
class CountingClassifier(Classifier):
|
||||
"""
|
||||
A classifier that generates constant predictions, based only on the
|
||||
frequency of the training labels. For example, if y_train is [1.0, 0.0, 0.0]
|
||||
this classifier always returns [0.66 0.33] for any x_test. It essentially
|
||||
counts how many times each label appeared, hence the name.
|
||||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.mean = None
|
||||
|
||||
def fit(self, x_train, y_train):
|
||||
self.mean = np.mean(y_train)
|
||||
|
||||
def predict_proba(self, x_test):
|
||||
return np.array([[1 - self.mean, self.mean] for _ in range(x_test.shape[0])])
|
||||
|
||||
def __repr__(self):
|
||||
return "CountingClassifier(mean=%s)" % self.mean</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-classes">Classes</h2>
|
||||
<dl>
|
||||
<dt id="miplearn.classifiers.counting.CountingClassifier"><code class="flex name class">
|
||||
<span>class <span class="ident">CountingClassifier</span></span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"><p>A classifier that generates constant predictions, based only on the
|
||||
frequency of the training labels. For example, if y_train is [1.0, 0.0, 0.0]
|
||||
this classifier always returns [0.66 0.33] for any x_test. It essentially
|
||||
counts how many times each label appeared, hence the name.</p></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">class CountingClassifier(Classifier):
|
||||
"""
|
||||
A classifier that generates constant predictions, based only on the
|
||||
frequency of the training labels. For example, if y_train is [1.0, 0.0, 0.0]
|
||||
this classifier always returns [0.66 0.33] for any x_test. It essentially
|
||||
counts how many times each label appeared, hence the name.
|
||||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.mean = None
|
||||
|
||||
def fit(self, x_train, y_train):
|
||||
self.mean = np.mean(y_train)
|
||||
|
||||
def predict_proba(self, x_test):
|
||||
return np.array([[1 - self.mean, self.mean] for _ in range(x_test.shape[0])])
|
||||
|
||||
def __repr__(self):
|
||||
return "CountingClassifier(mean=%s)" % self.mean</code></pre>
|
||||
</details>
|
||||
<h3>Ancestors</h3>
|
||||
<ul class="hlist">
|
||||
<li><a title="miplearn.classifiers.Classifier" href="index.html#miplearn.classifiers.Classifier">Classifier</a></li>
|
||||
<li>abc.ABC</li>
|
||||
</ul>
|
||||
<h3>Methods</h3>
|
||||
<dl>
|
||||
<dt id="miplearn.classifiers.counting.CountingClassifier.fit"><code class="name flex">
|
||||
<span>def <span class="ident">fit</span></span>(<span>self, x_train, y_train)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def fit(self, x_train, y_train):
|
||||
self.mean = np.mean(y_train)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.classifiers.counting.CountingClassifier.predict_proba"><code class="name flex">
|
||||
<span>def <span class="ident">predict_proba</span></span>(<span>self, x_test)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def predict_proba(self, x_test):
|
||||
return np.array([[1 - self.mean, self.mean] for _ in range(x_test.shape[0])])</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</section>
|
||||
</article>
|
||||
<nav id="sidebar">
|
||||
<h1>Index</h1>
|
||||
<div class="toc">
|
||||
<ul></ul>
|
||||
</div>
|
||||
<ul id="index">
|
||||
<li><h3>Super-module</h3>
|
||||
<ul>
|
||||
<li><code><a title="miplearn.classifiers" href="index.html">miplearn.classifiers</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-classes">Classes</a></h3>
|
||||
<ul>
|
||||
<li>
|
||||
<h4><code><a title="miplearn.classifiers.counting.CountingClassifier" href="#miplearn.classifiers.counting.CountingClassifier">CountingClassifier</a></code></h4>
|
||||
<ul class="">
|
||||
<li><code><a title="miplearn.classifiers.counting.CountingClassifier.fit" href="#miplearn.classifiers.counting.CountingClassifier.fit">fit</a></code></li>
|
||||
<li><code><a title="miplearn.classifiers.counting.CountingClassifier.predict_proba" href="#miplearn.classifiers.counting.CountingClassifier.predict_proba">predict_proba</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</main>
|
||||
<footer id="footer">
|
||||
<p>Generated by <a href="https://pdoc3.github.io/pdoc"><cite>pdoc</cite> 0.7.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>
|
||||
316
0.2/api/miplearn/classifiers/cv.html
Normal file
316
0.2/api/miplearn/classifiers/cv.html
Normal file
@@ -0,0 +1,316 @@
|
||||
<!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.classifiers.cv 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.classifiers.cv</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 copy import deepcopy
|
||||
|
||||
import numpy as np
|
||||
from sklearn.dummy import DummyClassifier
|
||||
from sklearn.linear_model import LogisticRegression
|
||||
from sklearn.model_selection import cross_val_score
|
||||
|
||||
from miplearn.classifiers import Classifier
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class CrossValidatedClassifier(Classifier):
|
||||
"""
|
||||
A meta-classifier that, upon training, evaluates the performance of another
|
||||
classifier on the training data set using k-fold cross validation, then
|
||||
either adopts the other classifier it if the cv-score is high enough, or
|
||||
returns a constant label for every x_test otherwise.
|
||||
|
||||
The threshold is specified in comparison to a dummy classifier trained
|
||||
on the same dataset. For example, a threshold of 0.0 indicates that any
|
||||
classifier as good as the dummy predictor is acceptable. A threshold of 1.0
|
||||
indicates that only classifier with a perfect cross-validation score are
|
||||
acceptable. Other numbers are a linear interpolation of these two extremes.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
classifier=LogisticRegression(),
|
||||
threshold=0.75,
|
||||
constant=0.0,
|
||||
cv=5,
|
||||
scoring="accuracy",
|
||||
):
|
||||
self.classifier = None
|
||||
self.classifier_prototype = classifier
|
||||
self.constant = constant
|
||||
self.threshold = threshold
|
||||
self.cv = cv
|
||||
self.scoring = scoring
|
||||
|
||||
def fit(self, x_train, y_train):
|
||||
# Calculate dummy score and absolute score threshold
|
||||
y_train_avg = np.average(y_train)
|
||||
dummy_score = max(y_train_avg, 1 - y_train_avg)
|
||||
absolute_threshold = 1.0 * self.threshold + dummy_score * (1 - self.threshold)
|
||||
|
||||
# Calculate cross validation score and decide which classifier to use
|
||||
clf = deepcopy(self.classifier_prototype)
|
||||
cv_score = float(
|
||||
np.mean(
|
||||
cross_val_score(
|
||||
clf,
|
||||
x_train,
|
||||
y_train,
|
||||
cv=self.cv,
|
||||
scoring=self.scoring,
|
||||
)
|
||||
)
|
||||
)
|
||||
if cv_score >= absolute_threshold:
|
||||
logger.debug(
|
||||
"cv_score is above threshold (%.2f >= %.2f); keeping"
|
||||
% (cv_score, absolute_threshold)
|
||||
)
|
||||
self.classifier = clf
|
||||
else:
|
||||
logger.debug(
|
||||
"cv_score is below threshold (%.2f < %.2f); discarding"
|
||||
% (cv_score, absolute_threshold)
|
||||
)
|
||||
self.classifier = DummyClassifier(
|
||||
strategy="constant",
|
||||
constant=self.constant,
|
||||
)
|
||||
|
||||
# Train chosen classifier
|
||||
self.classifier.fit(x_train, y_train)
|
||||
|
||||
def predict_proba(self, x_test):
|
||||
return self.classifier.predict_proba(x_test)</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-classes">Classes</h2>
|
||||
<dl>
|
||||
<dt id="miplearn.classifiers.cv.CrossValidatedClassifier"><code class="flex name class">
|
||||
<span>class <span class="ident">CrossValidatedClassifier</span></span>
|
||||
<span>(</span><span>classifier=LogisticRegression(), threshold=0.75, constant=0.0, cv=5, scoring='accuracy')</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"><p>A meta-classifier that, upon training, evaluates the performance of another
|
||||
classifier on the training data set using k-fold cross validation, then
|
||||
either adopts the other classifier it if the cv-score is high enough, or
|
||||
returns a constant label for every x_test otherwise.</p>
|
||||
<p>The threshold is specified in comparison to a dummy classifier trained
|
||||
on the same dataset. For example, a threshold of 0.0 indicates that any
|
||||
classifier as good as the dummy predictor is acceptable. A threshold of 1.0
|
||||
indicates that only classifier with a perfect cross-validation score are
|
||||
acceptable. Other numbers are a linear interpolation of these two extremes.</p></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">class CrossValidatedClassifier(Classifier):
|
||||
"""
|
||||
A meta-classifier that, upon training, evaluates the performance of another
|
||||
classifier on the training data set using k-fold cross validation, then
|
||||
either adopts the other classifier it if the cv-score is high enough, or
|
||||
returns a constant label for every x_test otherwise.
|
||||
|
||||
The threshold is specified in comparison to a dummy classifier trained
|
||||
on the same dataset. For example, a threshold of 0.0 indicates that any
|
||||
classifier as good as the dummy predictor is acceptable. A threshold of 1.0
|
||||
indicates that only classifier with a perfect cross-validation score are
|
||||
acceptable. Other numbers are a linear interpolation of these two extremes.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
classifier=LogisticRegression(),
|
||||
threshold=0.75,
|
||||
constant=0.0,
|
||||
cv=5,
|
||||
scoring="accuracy",
|
||||
):
|
||||
self.classifier = None
|
||||
self.classifier_prototype = classifier
|
||||
self.constant = constant
|
||||
self.threshold = threshold
|
||||
self.cv = cv
|
||||
self.scoring = scoring
|
||||
|
||||
def fit(self, x_train, y_train):
|
||||
# Calculate dummy score and absolute score threshold
|
||||
y_train_avg = np.average(y_train)
|
||||
dummy_score = max(y_train_avg, 1 - y_train_avg)
|
||||
absolute_threshold = 1.0 * self.threshold + dummy_score * (1 - self.threshold)
|
||||
|
||||
# Calculate cross validation score and decide which classifier to use
|
||||
clf = deepcopy(self.classifier_prototype)
|
||||
cv_score = float(
|
||||
np.mean(
|
||||
cross_val_score(
|
||||
clf,
|
||||
x_train,
|
||||
y_train,
|
||||
cv=self.cv,
|
||||
scoring=self.scoring,
|
||||
)
|
||||
)
|
||||
)
|
||||
if cv_score >= absolute_threshold:
|
||||
logger.debug(
|
||||
"cv_score is above threshold (%.2f >= %.2f); keeping"
|
||||
% (cv_score, absolute_threshold)
|
||||
)
|
||||
self.classifier = clf
|
||||
else:
|
||||
logger.debug(
|
||||
"cv_score is below threshold (%.2f < %.2f); discarding"
|
||||
% (cv_score, absolute_threshold)
|
||||
)
|
||||
self.classifier = DummyClassifier(
|
||||
strategy="constant",
|
||||
constant=self.constant,
|
||||
)
|
||||
|
||||
# Train chosen classifier
|
||||
self.classifier.fit(x_train, y_train)
|
||||
|
||||
def predict_proba(self, x_test):
|
||||
return self.classifier.predict_proba(x_test)</code></pre>
|
||||
</details>
|
||||
<h3>Ancestors</h3>
|
||||
<ul class="hlist">
|
||||
<li><a title="miplearn.classifiers.Classifier" href="index.html#miplearn.classifiers.Classifier">Classifier</a></li>
|
||||
<li>abc.ABC</li>
|
||||
</ul>
|
||||
<h3>Methods</h3>
|
||||
<dl>
|
||||
<dt id="miplearn.classifiers.cv.CrossValidatedClassifier.fit"><code class="name flex">
|
||||
<span>def <span class="ident">fit</span></span>(<span>self, x_train, y_train)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def fit(self, x_train, y_train):
|
||||
# Calculate dummy score and absolute score threshold
|
||||
y_train_avg = np.average(y_train)
|
||||
dummy_score = max(y_train_avg, 1 - y_train_avg)
|
||||
absolute_threshold = 1.0 * self.threshold + dummy_score * (1 - self.threshold)
|
||||
|
||||
# Calculate cross validation score and decide which classifier to use
|
||||
clf = deepcopy(self.classifier_prototype)
|
||||
cv_score = float(
|
||||
np.mean(
|
||||
cross_val_score(
|
||||
clf,
|
||||
x_train,
|
||||
y_train,
|
||||
cv=self.cv,
|
||||
scoring=self.scoring,
|
||||
)
|
||||
)
|
||||
)
|
||||
if cv_score >= absolute_threshold:
|
||||
logger.debug(
|
||||
"cv_score is above threshold (%.2f >= %.2f); keeping"
|
||||
% (cv_score, absolute_threshold)
|
||||
)
|
||||
self.classifier = clf
|
||||
else:
|
||||
logger.debug(
|
||||
"cv_score is below threshold (%.2f < %.2f); discarding"
|
||||
% (cv_score, absolute_threshold)
|
||||
)
|
||||
self.classifier = DummyClassifier(
|
||||
strategy="constant",
|
||||
constant=self.constant,
|
||||
)
|
||||
|
||||
# Train chosen classifier
|
||||
self.classifier.fit(x_train, y_train)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.classifiers.cv.CrossValidatedClassifier.predict_proba"><code class="name flex">
|
||||
<span>def <span class="ident">predict_proba</span></span>(<span>self, x_test)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def predict_proba(self, x_test):
|
||||
return self.classifier.predict_proba(x_test)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</section>
|
||||
</article>
|
||||
<nav id="sidebar">
|
||||
<h1>Index</h1>
|
||||
<div class="toc">
|
||||
<ul></ul>
|
||||
</div>
|
||||
<ul id="index">
|
||||
<li><h3>Super-module</h3>
|
||||
<ul>
|
||||
<li><code><a title="miplearn.classifiers" href="index.html">miplearn.classifiers</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-classes">Classes</a></h3>
|
||||
<ul>
|
||||
<li>
|
||||
<h4><code><a title="miplearn.classifiers.cv.CrossValidatedClassifier" href="#miplearn.classifiers.cv.CrossValidatedClassifier">CrossValidatedClassifier</a></code></h4>
|
||||
<ul class="">
|
||||
<li><code><a title="miplearn.classifiers.cv.CrossValidatedClassifier.fit" href="#miplearn.classifiers.cv.CrossValidatedClassifier.fit">fit</a></code></li>
|
||||
<li><code><a title="miplearn.classifiers.cv.CrossValidatedClassifier.predict_proba" href="#miplearn.classifiers.cv.CrossValidatedClassifier.predict_proba">predict_proba</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</main>
|
||||
<footer id="footer">
|
||||
<p>Generated by <a href="https://pdoc3.github.io/pdoc"><cite>pdoc</cite> 0.7.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>
|
||||
123
0.2/api/miplearn/classifiers/evaluator.html
Normal file
123
0.2/api/miplearn/classifiers/evaluator.html
Normal 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.classifiers.evaluator 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.classifiers.evaluator</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 sklearn.metrics import roc_auc_score
|
||||
|
||||
|
||||
class ClassifierEvaluator:
|
||||
def __init__(self) -> None:
|
||||
pass
|
||||
|
||||
def evaluate(self, clf, x_train, y_train):
|
||||
# FIXME: use cross-validation
|
||||
proba = clf.predict_proba(x_train)
|
||||
return roc_auc_score(y_train, proba[:, 1])</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-classes">Classes</h2>
|
||||
<dl>
|
||||
<dt id="miplearn.classifiers.evaluator.ClassifierEvaluator"><code class="flex name class">
|
||||
<span>class <span class="ident">ClassifierEvaluator</span></span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">class ClassifierEvaluator:
|
||||
def __init__(self) -> None:
|
||||
pass
|
||||
|
||||
def evaluate(self, clf, x_train, y_train):
|
||||
# FIXME: use cross-validation
|
||||
proba = clf.predict_proba(x_train)
|
||||
return roc_auc_score(y_train, proba[:, 1])</code></pre>
|
||||
</details>
|
||||
<h3>Methods</h3>
|
||||
<dl>
|
||||
<dt id="miplearn.classifiers.evaluator.ClassifierEvaluator.evaluate"><code class="name flex">
|
||||
<span>def <span class="ident">evaluate</span></span>(<span>self, clf, x_train, y_train)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def evaluate(self, clf, x_train, y_train):
|
||||
# FIXME: use cross-validation
|
||||
proba = clf.predict_proba(x_train)
|
||||
return roc_auc_score(y_train, proba[:, 1])</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</section>
|
||||
</article>
|
||||
<nav id="sidebar">
|
||||
<h1>Index</h1>
|
||||
<div class="toc">
|
||||
<ul></ul>
|
||||
</div>
|
||||
<ul id="index">
|
||||
<li><h3>Super-module</h3>
|
||||
<ul>
|
||||
<li><code><a title="miplearn.classifiers" href="index.html">miplearn.classifiers</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-classes">Classes</a></h3>
|
||||
<ul>
|
||||
<li>
|
||||
<h4><code><a title="miplearn.classifiers.evaluator.ClassifierEvaluator" href="#miplearn.classifiers.evaluator.ClassifierEvaluator">ClassifierEvaluator</a></code></h4>
|
||||
<ul class="">
|
||||
<li><code><a title="miplearn.classifiers.evaluator.ClassifierEvaluator.evaluate" href="#miplearn.classifiers.evaluator.ClassifierEvaluator.evaluate">evaluate</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</main>
|
||||
<footer id="footer">
|
||||
<p>Generated by <a href="https://pdoc3.github.io/pdoc"><cite>pdoc</cite> 0.7.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>
|
||||
290
0.2/api/miplearn/classifiers/index.html
Normal file
290
0.2/api/miplearn/classifiers/index.html
Normal file
@@ -0,0 +1,290 @@
|
||||
<!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.classifiers 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.classifiers</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 abc import ABC, abstractmethod
|
||||
|
||||
import numpy as np
|
||||
|
||||
|
||||
class Classifier(ABC):
|
||||
@abstractmethod
|
||||
def fit(self, x_train, y_train):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def predict_proba(self, x_test):
|
||||
pass
|
||||
|
||||
def predict(self, x_test):
|
||||
proba = self.predict_proba(x_test)
|
||||
assert isinstance(proba, np.ndarray)
|
||||
assert proba.shape == (x_test.shape[0], 2)
|
||||
return (proba[:, 1] > 0.5).astype(float)
|
||||
|
||||
|
||||
class Regressor(ABC):
|
||||
@abstractmethod
|
||||
def fit(self, x_train, y_train):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def predict(self):
|
||||
pass</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-submodules">Sub-modules</h2>
|
||||
<dl>
|
||||
<dt><code class="name"><a title="miplearn.classifiers.adaptive" href="adaptive.html">miplearn.classifiers.adaptive</a></code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
</dd>
|
||||
<dt><code class="name"><a title="miplearn.classifiers.counting" href="counting.html">miplearn.classifiers.counting</a></code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
</dd>
|
||||
<dt><code class="name"><a title="miplearn.classifiers.cv" href="cv.html">miplearn.classifiers.cv</a></code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
</dd>
|
||||
<dt><code class="name"><a title="miplearn.classifiers.evaluator" href="evaluator.html">miplearn.classifiers.evaluator</a></code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
</dd>
|
||||
<dt><code class="name"><a title="miplearn.classifiers.tests" href="tests/index.html">miplearn.classifiers.tests</a></code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
</dd>
|
||||
<dt><code class="name"><a title="miplearn.classifiers.threshold" href="threshold.html">miplearn.classifiers.threshold</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.classifiers.Classifier"><code class="flex name class">
|
||||
<span>class <span class="ident">Classifier</span></span>
|
||||
<span>(</span><span>*args, **kwargs)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"><p>Helper class that provides a standard way to create an ABC using
|
||||
inheritance.</p></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">class Classifier(ABC):
|
||||
@abstractmethod
|
||||
def fit(self, x_train, y_train):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def predict_proba(self, x_test):
|
||||
pass
|
||||
|
||||
def predict(self, x_test):
|
||||
proba = self.predict_proba(x_test)
|
||||
assert isinstance(proba, np.ndarray)
|
||||
assert proba.shape == (x_test.shape[0], 2)
|
||||
return (proba[:, 1] > 0.5).astype(float)</code></pre>
|
||||
</details>
|
||||
<h3>Ancestors</h3>
|
||||
<ul class="hlist">
|
||||
<li>abc.ABC</li>
|
||||
</ul>
|
||||
<h3>Subclasses</h3>
|
||||
<ul class="hlist">
|
||||
<li><a title="miplearn.classifiers.counting.CountingClassifier" href="counting.html#miplearn.classifiers.counting.CountingClassifier">CountingClassifier</a></li>
|
||||
<li><a title="miplearn.classifiers.adaptive.AdaptiveClassifier" href="adaptive.html#miplearn.classifiers.adaptive.AdaptiveClassifier">AdaptiveClassifier</a></li>
|
||||
<li><a title="miplearn.classifiers.cv.CrossValidatedClassifier" href="cv.html#miplearn.classifiers.cv.CrossValidatedClassifier">CrossValidatedClassifier</a></li>
|
||||
</ul>
|
||||
<h3>Methods</h3>
|
||||
<dl>
|
||||
<dt id="miplearn.classifiers.Classifier.fit"><code class="name flex">
|
||||
<span>def <span class="ident">fit</span></span>(<span>self, x_train, y_train)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">@abstractmethod
|
||||
def fit(self, x_train, y_train):
|
||||
pass</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.classifiers.Classifier.predict"><code class="name flex">
|
||||
<span>def <span class="ident">predict</span></span>(<span>self, x_test)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def predict(self, x_test):
|
||||
proba = self.predict_proba(x_test)
|
||||
assert isinstance(proba, np.ndarray)
|
||||
assert proba.shape == (x_test.shape[0], 2)
|
||||
return (proba[:, 1] > 0.5).astype(float)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.classifiers.Classifier.predict_proba"><code class="name flex">
|
||||
<span>def <span class="ident">predict_proba</span></span>(<span>self, x_test)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">@abstractmethod
|
||||
def predict_proba(self, x_test):
|
||||
pass</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt id="miplearn.classifiers.Regressor"><code class="flex name class">
|
||||
<span>class <span class="ident">Regressor</span></span>
|
||||
<span>(</span><span>*args, **kwargs)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"><p>Helper class that provides a standard way to create an ABC using
|
||||
inheritance.</p></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">class Regressor(ABC):
|
||||
@abstractmethod
|
||||
def fit(self, x_train, y_train):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def predict(self):
|
||||
pass</code></pre>
|
||||
</details>
|
||||
<h3>Ancestors</h3>
|
||||
<ul class="hlist">
|
||||
<li>abc.ABC</li>
|
||||
</ul>
|
||||
<h3>Methods</h3>
|
||||
<dl>
|
||||
<dt id="miplearn.classifiers.Regressor.fit"><code class="name flex">
|
||||
<span>def <span class="ident">fit</span></span>(<span>self, x_train, y_train)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">@abstractmethod
|
||||
def fit(self, x_train, y_train):
|
||||
pass</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.classifiers.Regressor.predict"><code class="name flex">
|
||||
<span>def <span class="ident">predict</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">@abstractmethod
|
||||
def predict(self):
|
||||
pass</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</section>
|
||||
</article>
|
||||
<nav id="sidebar">
|
||||
<h1>Index</h1>
|
||||
<div class="toc">
|
||||
<ul></ul>
|
||||
</div>
|
||||
<ul id="index">
|
||||
<li><h3>Super-module</h3>
|
||||
<ul>
|
||||
<li><code><a title="miplearn" 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.classifiers.adaptive" href="adaptive.html">miplearn.classifiers.adaptive</a></code></li>
|
||||
<li><code><a title="miplearn.classifiers.counting" href="counting.html">miplearn.classifiers.counting</a></code></li>
|
||||
<li><code><a title="miplearn.classifiers.cv" href="cv.html">miplearn.classifiers.cv</a></code></li>
|
||||
<li><code><a title="miplearn.classifiers.evaluator" href="evaluator.html">miplearn.classifiers.evaluator</a></code></li>
|
||||
<li><code><a title="miplearn.classifiers.tests" href="tests/index.html">miplearn.classifiers.tests</a></code></li>
|
||||
<li><code><a title="miplearn.classifiers.threshold" href="threshold.html">miplearn.classifiers.threshold</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-classes">Classes</a></h3>
|
||||
<ul>
|
||||
<li>
|
||||
<h4><code><a title="miplearn.classifiers.Classifier" href="#miplearn.classifiers.Classifier">Classifier</a></code></h4>
|
||||
<ul class="">
|
||||
<li><code><a title="miplearn.classifiers.Classifier.fit" href="#miplearn.classifiers.Classifier.fit">fit</a></code></li>
|
||||
<li><code><a title="miplearn.classifiers.Classifier.predict" href="#miplearn.classifiers.Classifier.predict">predict</a></code></li>
|
||||
<li><code><a title="miplearn.classifiers.Classifier.predict_proba" href="#miplearn.classifiers.Classifier.predict_proba">predict_proba</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<h4><code><a title="miplearn.classifiers.Regressor" href="#miplearn.classifiers.Regressor">Regressor</a></code></h4>
|
||||
<ul class="">
|
||||
<li><code><a title="miplearn.classifiers.Regressor.fit" href="#miplearn.classifiers.Regressor.fit">fit</a></code></li>
|
||||
<li><code><a title="miplearn.classifiers.Regressor.predict" href="#miplearn.classifiers.Regressor.predict">predict</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</main>
|
||||
<footer id="footer">
|
||||
<p>Generated by <a href="https://pdoc3.github.io/pdoc"><cite>pdoc</cite> 0.7.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>
|
||||
88
0.2/api/miplearn/classifiers/tests/index.html
Normal file
88
0.2/api/miplearn/classifiers/tests/index.html
Normal 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.classifiers.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.classifiers.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.</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-submodules">Sub-modules</h2>
|
||||
<dl>
|
||||
<dt><code class="name"><a title="miplearn.classifiers.tests.test_counting" href="test_counting.html">miplearn.classifiers.tests.test_counting</a></code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
</dd>
|
||||
<dt><code class="name"><a title="miplearn.classifiers.tests.test_cv" href="test_cv.html">miplearn.classifiers.tests.test_cv</a></code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
</dd>
|
||||
<dt><code class="name"><a title="miplearn.classifiers.tests.test_evaluator" href="test_evaluator.html">miplearn.classifiers.tests.test_evaluator</a></code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
</dd>
|
||||
<dt><code class="name"><a title="miplearn.classifiers.tests.test_threshold" href="test_threshold.html">miplearn.classifiers.tests.test_threshold</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.classifiers" href="../index.html">miplearn.classifiers</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-submodules">Sub-modules</a></h3>
|
||||
<ul>
|
||||
<li><code><a title="miplearn.classifiers.tests.test_counting" href="test_counting.html">miplearn.classifiers.tests.test_counting</a></code></li>
|
||||
<li><code><a title="miplearn.classifiers.tests.test_cv" href="test_cv.html">miplearn.classifiers.tests.test_cv</a></code></li>
|
||||
<li><code><a title="miplearn.classifiers.tests.test_evaluator" href="test_evaluator.html">miplearn.classifiers.tests.test_evaluator</a></code></li>
|
||||
<li><code><a title="miplearn.classifiers.tests.test_threshold" href="test_threshold.html">miplearn.classifiers.tests.test_threshold</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>
|
||||
101
0.2/api/miplearn/classifiers/tests/test_counting.html
Normal file
101
0.2/api/miplearn/classifiers/tests/test_counting.html
Normal file
@@ -0,0 +1,101 @@
|
||||
<!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.classifiers.tests.test_counting 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.classifiers.tests.test_counting</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 numpy as np
|
||||
from numpy.linalg import norm
|
||||
|
||||
from miplearn.classifiers.counting import CountingClassifier
|
||||
|
||||
E = 0.1
|
||||
|
||||
|
||||
def test_counting():
|
||||
clf = CountingClassifier()
|
||||
clf.fit(np.zeros((8, 25)), [0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0])
|
||||
expected_proba = np.array([[0.375, 0.625], [0.375, 0.625]])
|
||||
actual_proba = clf.predict_proba(np.zeros((2, 25)))
|
||||
assert norm(actual_proba - expected_proba) < E</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-functions">Functions</h2>
|
||||
<dl>
|
||||
<dt id="miplearn.classifiers.tests.test_counting.test_counting"><code class="name flex">
|
||||
<span>def <span class="ident">test_counting</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_counting():
|
||||
clf = CountingClassifier()
|
||||
clf.fit(np.zeros((8, 25)), [0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0])
|
||||
expected_proba = np.array([[0.375, 0.625], [0.375, 0.625]])
|
||||
actual_proba = clf.predict_proba(np.zeros((2, 25)))
|
||||
assert norm(actual_proba - expected_proba) < E</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.classifiers.tests" href="index.html">miplearn.classifiers.tests</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-functions">Functions</a></h3>
|
||||
<ul class="">
|
||||
<li><code><a title="miplearn.classifiers.tests.test_counting.test_counting" href="#miplearn.classifiers.tests.test_counting.test_counting">test_counting</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>
|
||||
161
0.2/api/miplearn/classifiers/tests/test_cv.html
Normal file
161
0.2/api/miplearn/classifiers/tests/test_cv.html
Normal file
@@ -0,0 +1,161 @@
|
||||
<!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.classifiers.tests.test_cv 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.classifiers.tests.test_cv</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 numpy as np
|
||||
from numpy.linalg import norm
|
||||
from sklearn.preprocessing import StandardScaler
|
||||
from sklearn.svm import SVC
|
||||
|
||||
from miplearn.classifiers.cv import CrossValidatedClassifier
|
||||
|
||||
E = 0.1
|
||||
|
||||
|
||||
def test_cv():
|
||||
# Training set: label is true if point is inside a 2D circle
|
||||
x_train = np.array([[x1, x2] for x1 in range(-10, 11) for x2 in range(-10, 11)])
|
||||
x_train = StandardScaler().fit_transform(x_train)
|
||||
n_samples = x_train.shape[0]
|
||||
|
||||
y_train = np.array(
|
||||
[
|
||||
1.0 if x1 * x1 + x2 * x2 <= 100 else 0.0
|
||||
for x1 in range(-10, 11)
|
||||
for x2 in range(-10, 11)
|
||||
]
|
||||
)
|
||||
|
||||
# Support vector machines with linear kernels do not perform well on this
|
||||
# data set, so predictor should return the given constant.
|
||||
clf = CrossValidatedClassifier(
|
||||
classifier=SVC(probability=True, random_state=42),
|
||||
threshold=0.90,
|
||||
constant=0.0,
|
||||
cv=30,
|
||||
)
|
||||
clf.fit(x_train, y_train)
|
||||
assert norm(np.zeros(n_samples) - clf.predict(x_train)) < E
|
||||
|
||||
# Support vector machines with quadratic kernels perform almost perfectly
|
||||
# on this data set, so predictor should return their prediction.
|
||||
clf = CrossValidatedClassifier(
|
||||
classifier=SVC(probability=True, kernel="poly", degree=2, random_state=42),
|
||||
threshold=0.90,
|
||||
cv=30,
|
||||
)
|
||||
clf.fit(x_train, y_train)
|
||||
print(y_train - clf.predict(x_train))
|
||||
assert norm(y_train - clf.predict(x_train)) < E</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-functions">Functions</h2>
|
||||
<dl>
|
||||
<dt id="miplearn.classifiers.tests.test_cv.test_cv"><code class="name flex">
|
||||
<span>def <span class="ident">test_cv</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_cv():
|
||||
# Training set: label is true if point is inside a 2D circle
|
||||
x_train = np.array([[x1, x2] for x1 in range(-10, 11) for x2 in range(-10, 11)])
|
||||
x_train = StandardScaler().fit_transform(x_train)
|
||||
n_samples = x_train.shape[0]
|
||||
|
||||
y_train = np.array(
|
||||
[
|
||||
1.0 if x1 * x1 + x2 * x2 <= 100 else 0.0
|
||||
for x1 in range(-10, 11)
|
||||
for x2 in range(-10, 11)
|
||||
]
|
||||
)
|
||||
|
||||
# Support vector machines with linear kernels do not perform well on this
|
||||
# data set, so predictor should return the given constant.
|
||||
clf = CrossValidatedClassifier(
|
||||
classifier=SVC(probability=True, random_state=42),
|
||||
threshold=0.90,
|
||||
constant=0.0,
|
||||
cv=30,
|
||||
)
|
||||
clf.fit(x_train, y_train)
|
||||
assert norm(np.zeros(n_samples) - clf.predict(x_train)) < E
|
||||
|
||||
# Support vector machines with quadratic kernels perform almost perfectly
|
||||
# on this data set, so predictor should return their prediction.
|
||||
clf = CrossValidatedClassifier(
|
||||
classifier=SVC(probability=True, kernel="poly", degree=2, random_state=42),
|
||||
threshold=0.90,
|
||||
cv=30,
|
||||
)
|
||||
clf.fit(x_train, y_train)
|
||||
print(y_train - clf.predict(x_train))
|
||||
assert norm(y_train - clf.predict(x_train)) < E</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.classifiers.tests" href="index.html">miplearn.classifiers.tests</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-functions">Functions</a></h3>
|
||||
<ul class="">
|
||||
<li><code><a title="miplearn.classifiers.tests.test_cv.test_cv" href="#miplearn.classifiers.tests.test_cv.test_cv">test_cv</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>
|
||||
107
0.2/api/miplearn/classifiers/tests/test_evaluator.html
Normal file
107
0.2/api/miplearn/classifiers/tests/test_evaluator.html
Normal file
@@ -0,0 +1,107 @@
|
||||
<!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.classifiers.tests.test_evaluator 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.classifiers.tests.test_evaluator</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 numpy as np
|
||||
from sklearn.neighbors import KNeighborsClassifier
|
||||
|
||||
from miplearn.classifiers.evaluator import ClassifierEvaluator
|
||||
|
||||
|
||||
def test_evaluator():
|
||||
clf_a = KNeighborsClassifier(n_neighbors=1)
|
||||
clf_b = KNeighborsClassifier(n_neighbors=2)
|
||||
x_train = np.array([[0, 0], [1, 0]])
|
||||
y_train = np.array([0, 1])
|
||||
clf_a.fit(x_train, y_train)
|
||||
clf_b.fit(x_train, y_train)
|
||||
ev = ClassifierEvaluator()
|
||||
assert ev.evaluate(clf_a, x_train, y_train) == 1.0
|
||||
assert ev.evaluate(clf_b, x_train, y_train) == 0.5</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-functions">Functions</h2>
|
||||
<dl>
|
||||
<dt id="miplearn.classifiers.tests.test_evaluator.test_evaluator"><code class="name flex">
|
||||
<span>def <span class="ident">test_evaluator</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_evaluator():
|
||||
clf_a = KNeighborsClassifier(n_neighbors=1)
|
||||
clf_b = KNeighborsClassifier(n_neighbors=2)
|
||||
x_train = np.array([[0, 0], [1, 0]])
|
||||
y_train = np.array([0, 1])
|
||||
clf_a.fit(x_train, y_train)
|
||||
clf_b.fit(x_train, y_train)
|
||||
ev = ClassifierEvaluator()
|
||||
assert ev.evaluate(clf_a, x_train, y_train) == 1.0
|
||||
assert ev.evaluate(clf_b, x_train, y_train) == 0.5</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.classifiers.tests" href="index.html">miplearn.classifiers.tests</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-functions">Functions</a></h3>
|
||||
<ul class="">
|
||||
<li><code><a title="miplearn.classifiers.tests.test_evaluator.test_evaluator" href="#miplearn.classifiers.tests.test_evaluator.test_evaluator">test_evaluator</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>
|
||||
141
0.2/api/miplearn/classifiers/tests/test_threshold.html
Normal file
141
0.2/api/miplearn/classifiers/tests/test_threshold.html
Normal file
@@ -0,0 +1,141 @@
|
||||
<!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.classifiers.tests.test_threshold 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.classifiers.tests.test_threshold</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 unittest.mock import Mock
|
||||
|
||||
import numpy as np
|
||||
|
||||
from miplearn.classifiers import Classifier
|
||||
from miplearn.classifiers.threshold import MinPrecisionThreshold
|
||||
|
||||
|
||||
def test_threshold_dynamic():
|
||||
clf = Mock(spec=Classifier)
|
||||
clf.predict_proba = Mock(
|
||||
return_value=np.array(
|
||||
[
|
||||
[0.10, 0.90],
|
||||
[0.10, 0.90],
|
||||
[0.20, 0.80],
|
||||
[0.30, 0.70],
|
||||
]
|
||||
)
|
||||
)
|
||||
x_train = np.array([0, 1, 2, 3])
|
||||
y_train = np.array([1, 1, 0, 0])
|
||||
|
||||
threshold = MinPrecisionThreshold(min_precision=1.0)
|
||||
assert threshold.find(clf, x_train, y_train) == 0.90
|
||||
|
||||
threshold = MinPrecisionThreshold(min_precision=0.65)
|
||||
assert threshold.find(clf, x_train, y_train) == 0.80
|
||||
|
||||
threshold = MinPrecisionThreshold(min_precision=0.50)
|
||||
assert threshold.find(clf, x_train, y_train) == 0.70
|
||||
|
||||
threshold = MinPrecisionThreshold(min_precision=0.00)
|
||||
assert threshold.find(clf, x_train, y_train) == 0.70</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-functions">Functions</h2>
|
||||
<dl>
|
||||
<dt id="miplearn.classifiers.tests.test_threshold.test_threshold_dynamic"><code class="name flex">
|
||||
<span>def <span class="ident">test_threshold_dynamic</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_threshold_dynamic():
|
||||
clf = Mock(spec=Classifier)
|
||||
clf.predict_proba = Mock(
|
||||
return_value=np.array(
|
||||
[
|
||||
[0.10, 0.90],
|
||||
[0.10, 0.90],
|
||||
[0.20, 0.80],
|
||||
[0.30, 0.70],
|
||||
]
|
||||
)
|
||||
)
|
||||
x_train = np.array([0, 1, 2, 3])
|
||||
y_train = np.array([1, 1, 0, 0])
|
||||
|
||||
threshold = MinPrecisionThreshold(min_precision=1.0)
|
||||
assert threshold.find(clf, x_train, y_train) == 0.90
|
||||
|
||||
threshold = MinPrecisionThreshold(min_precision=0.65)
|
||||
assert threshold.find(clf, x_train, y_train) == 0.80
|
||||
|
||||
threshold = MinPrecisionThreshold(min_precision=0.50)
|
||||
assert threshold.find(clf, x_train, y_train) == 0.70
|
||||
|
||||
threshold = MinPrecisionThreshold(min_precision=0.00)
|
||||
assert threshold.find(clf, x_train, y_train) == 0.70</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.classifiers.tests" href="index.html">miplearn.classifiers.tests</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-functions">Functions</a></h3>
|
||||
<ul class="">
|
||||
<li><code><a title="miplearn.classifiers.tests.test_threshold.test_threshold_dynamic" href="#miplearn.classifiers.tests.test_threshold.test_threshold_dynamic">test_threshold_dynamic</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>
|
||||
246
0.2/api/miplearn/classifiers/threshold.html
Normal file
246
0.2/api/miplearn/classifiers/threshold.html
Normal file
@@ -0,0 +1,246 @@
|
||||
<!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.classifiers.threshold 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.classifiers.threshold</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 abc import abstractmethod, ABC
|
||||
|
||||
import numpy as np
|
||||
from sklearn.metrics._ranking import _binary_clf_curve
|
||||
|
||||
from miplearn.classifiers import Classifier
|
||||
|
||||
|
||||
class DynamicThreshold(ABC):
|
||||
@abstractmethod
|
||||
def find(
|
||||
self,
|
||||
clf: Classifier,
|
||||
x_train: np.ndarray,
|
||||
y_train: np.ndarray,
|
||||
) -> float:
|
||||
"""
|
||||
Given a trained binary classifier `clf` and a training data set,
|
||||
returns the numerical threshold (float) satisfying some criterea.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class MinPrecisionThreshold(DynamicThreshold):
|
||||
"""
|
||||
The smallest possible threshold satisfying a minimum acceptable true
|
||||
positive rate (also known as precision).
|
||||
"""
|
||||
|
||||
def __init__(self, min_precision: float) -> None:
|
||||
self.min_precision = min_precision
|
||||
|
||||
def find(self, clf, x_train, y_train):
|
||||
proba = clf.predict_proba(x_train)
|
||||
|
||||
assert isinstance(proba, np.ndarray), "classifier should return numpy array"
|
||||
assert proba.shape == (
|
||||
x_train.shape[0],
|
||||
2,
|
||||
), "classifier should return (%d,%d)-shaped array, not %s" % (
|
||||
x_train.shape[0],
|
||||
2,
|
||||
str(proba.shape),
|
||||
)
|
||||
|
||||
fps, tps, thresholds = _binary_clf_curve(y_train, proba[:, 1])
|
||||
precision = tps / (tps + fps)
|
||||
|
||||
for k in reversed(range(len(precision))):
|
||||
if precision[k] >= self.min_precision:
|
||||
return thresholds[k]
|
||||
return 2.0</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-classes">Classes</h2>
|
||||
<dl>
|
||||
<dt id="miplearn.classifiers.threshold.DynamicThreshold"><code class="flex name class">
|
||||
<span>class <span class="ident">DynamicThreshold</span></span>
|
||||
<span>(</span><span>*args, **kwargs)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"><p>Helper class that provides a standard way to create an ABC using
|
||||
inheritance.</p></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">class DynamicThreshold(ABC):
|
||||
@abstractmethod
|
||||
def find(
|
||||
self,
|
||||
clf: Classifier,
|
||||
x_train: np.ndarray,
|
||||
y_train: np.ndarray,
|
||||
) -> float:
|
||||
"""
|
||||
Given a trained binary classifier `clf` and a training data set,
|
||||
returns the numerical threshold (float) satisfying some criterea.
|
||||
"""
|
||||
pass</code></pre>
|
||||
</details>
|
||||
<h3>Ancestors</h3>
|
||||
<ul class="hlist">
|
||||
<li>abc.ABC</li>
|
||||
</ul>
|
||||
<h3>Subclasses</h3>
|
||||
<ul class="hlist">
|
||||
<li><a title="miplearn.classifiers.threshold.MinPrecisionThreshold" href="#miplearn.classifiers.threshold.MinPrecisionThreshold">MinPrecisionThreshold</a></li>
|
||||
</ul>
|
||||
<h3>Methods</h3>
|
||||
<dl>
|
||||
<dt id="miplearn.classifiers.threshold.DynamicThreshold.find"><code class="name flex">
|
||||
<span>def <span class="ident">find</span></span>(<span>self, clf, x_train, y_train)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"><p>Given a trained binary classifier <code>clf</code> and a training data set,
|
||||
returns the numerical threshold (float) satisfying some criterea.</p></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">@abstractmethod
|
||||
def find(
|
||||
self,
|
||||
clf: Classifier,
|
||||
x_train: np.ndarray,
|
||||
y_train: np.ndarray,
|
||||
) -> float:
|
||||
"""
|
||||
Given a trained binary classifier `clf` and a training data set,
|
||||
returns the numerical threshold (float) satisfying some criterea.
|
||||
"""
|
||||
pass</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt id="miplearn.classifiers.threshold.MinPrecisionThreshold"><code class="flex name class">
|
||||
<span>class <span class="ident">MinPrecisionThreshold</span></span>
|
||||
<span>(</span><span>min_precision)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"><p>The smallest possible threshold satisfying a minimum acceptable true
|
||||
positive rate (also known as precision).</p></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">class MinPrecisionThreshold(DynamicThreshold):
|
||||
"""
|
||||
The smallest possible threshold satisfying a minimum acceptable true
|
||||
positive rate (also known as precision).
|
||||
"""
|
||||
|
||||
def __init__(self, min_precision: float) -> None:
|
||||
self.min_precision = min_precision
|
||||
|
||||
def find(self, clf, x_train, y_train):
|
||||
proba = clf.predict_proba(x_train)
|
||||
|
||||
assert isinstance(proba, np.ndarray), "classifier should return numpy array"
|
||||
assert proba.shape == (
|
||||
x_train.shape[0],
|
||||
2,
|
||||
), "classifier should return (%d,%d)-shaped array, not %s" % (
|
||||
x_train.shape[0],
|
||||
2,
|
||||
str(proba.shape),
|
||||
)
|
||||
|
||||
fps, tps, thresholds = _binary_clf_curve(y_train, proba[:, 1])
|
||||
precision = tps / (tps + fps)
|
||||
|
||||
for k in reversed(range(len(precision))):
|
||||
if precision[k] >= self.min_precision:
|
||||
return thresholds[k]
|
||||
return 2.0</code></pre>
|
||||
</details>
|
||||
<h3>Ancestors</h3>
|
||||
<ul class="hlist">
|
||||
<li><a title="miplearn.classifiers.threshold.DynamicThreshold" href="#miplearn.classifiers.threshold.DynamicThreshold">DynamicThreshold</a></li>
|
||||
<li>abc.ABC</li>
|
||||
</ul>
|
||||
<h3>Inherited members</h3>
|
||||
<ul class="hlist">
|
||||
<li><code><b><a title="miplearn.classifiers.threshold.DynamicThreshold" href="#miplearn.classifiers.threshold.DynamicThreshold">DynamicThreshold</a></b></code>:
|
||||
<ul class="hlist">
|
||||
<li><code><a title="miplearn.classifiers.threshold.DynamicThreshold.find" href="#miplearn.classifiers.threshold.DynamicThreshold.find">find</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.classifiers" href="index.html">miplearn.classifiers</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-classes">Classes</a></h3>
|
||||
<ul>
|
||||
<li>
|
||||
<h4><code><a title="miplearn.classifiers.threshold.DynamicThreshold" href="#miplearn.classifiers.threshold.DynamicThreshold">DynamicThreshold</a></code></h4>
|
||||
<ul class="">
|
||||
<li><code><a title="miplearn.classifiers.threshold.DynamicThreshold.find" href="#miplearn.classifiers.threshold.DynamicThreshold.find">find</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<h4><code><a title="miplearn.classifiers.threshold.MinPrecisionThreshold" href="#miplearn.classifiers.threshold.MinPrecisionThreshold">MinPrecisionThreshold</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>
|
||||
526
0.2/api/miplearn/components/component.html
Normal file
526
0.2/api/miplearn/components/component.html
Normal file
@@ -0,0 +1,526 @@
|
||||
<!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.components.component 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.components.component</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 abc import ABC, abstractmethod
|
||||
from typing import Any, List, Union, TYPE_CHECKING
|
||||
|
||||
from miplearn.instance import Instance
|
||||
from miplearn.types import MIPSolveStats, TrainingSample
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from miplearn.solvers.learning import LearningSolver
|
||||
|
||||
|
||||
class Component(ABC):
|
||||
"""
|
||||
A Component is an object which adds functionality to a LearningSolver.
|
||||
|
||||
For better code maintainability, LearningSolver simply delegates most of its
|
||||
functionality to Components. Each Component is responsible for exactly one ML
|
||||
strategy.
|
||||
"""
|
||||
|
||||
def before_solve(
|
||||
self,
|
||||
solver: "LearningSolver",
|
||||
instance: Instance,
|
||||
model: Any,
|
||||
) -> None:
|
||||
"""
|
||||
Method called by LearningSolver before the problem is solved.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
solver
|
||||
The solver calling this method.
|
||||
instance
|
||||
The instance being solved.
|
||||
model
|
||||
The concrete optimization model being solved.
|
||||
"""
|
||||
return
|
||||
|
||||
@abstractmethod
|
||||
def after_solve(
|
||||
self,
|
||||
solver: "LearningSolver",
|
||||
instance: Instance,
|
||||
model: Any,
|
||||
stats: MIPSolveStats,
|
||||
training_data: TrainingSample,
|
||||
) -> None:
|
||||
"""
|
||||
Method called by LearningSolver after the problem is solved to optimality.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
solver: LearningSolver
|
||||
The solver calling this method.
|
||||
instance: Instance
|
||||
The instance being solved.
|
||||
model: Any
|
||||
The concrete optimization model being solved.
|
||||
stats: dict
|
||||
A dictionary containing statistics about the solution process, such as
|
||||
number of nodes explored and running time. Components are free to add
|
||||
their own statistics here. For example, PrimalSolutionComponent adds
|
||||
statistics regarding the number of predicted variables. All statistics in
|
||||
this dictionary are exported to the benchmark CSV file.
|
||||
training_data: dict
|
||||
A dictionary containing data that may be useful for training machine
|
||||
learning models and accelerating the solution process. Components are
|
||||
free to add their own training data here. For example,
|
||||
PrimalSolutionComponent adds the current primal solution. The data must
|
||||
be pickable.
|
||||
"""
|
||||
pass
|
||||
|
||||
def fit(
|
||||
self,
|
||||
training_instances: Union[List[str], List[Instance]],
|
||||
) -> None:
|
||||
return
|
||||
|
||||
def iteration_cb(
|
||||
self,
|
||||
solver: "LearningSolver",
|
||||
instance: Instance,
|
||||
model: Any,
|
||||
) -> bool:
|
||||
"""
|
||||
Method called by LearningSolver at the end of each iteration.
|
||||
|
||||
After solving the MIP, LearningSolver calls `iteration_cb` of each component,
|
||||
giving them a chance to modify the problem and resolve it before the solution
|
||||
process ends. For example, the lazy constraint component uses `iteration_cb`
|
||||
to check that all lazy constraints are satisfied.
|
||||
|
||||
If `iteration_cb` returns False for all components, the solution process
|
||||
ends. If it retunrs True for any component, the MIP is solved again.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
solver: LearningSolver
|
||||
The solver calling this method.
|
||||
instance: Instance
|
||||
The instance being solved.
|
||||
model: Any
|
||||
The concrete optimization model being solved.
|
||||
"""
|
||||
return False
|
||||
|
||||
def lazy_cb(
|
||||
self,
|
||||
solver: "LearningSolver",
|
||||
instance: Instance,
|
||||
model: Any,
|
||||
) -> None:
|
||||
return</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-classes">Classes</h2>
|
||||
<dl>
|
||||
<dt id="miplearn.components.component.Component"><code class="flex name class">
|
||||
<span>class <span class="ident">Component</span></span>
|
||||
<span>(</span><span>*args, **kwargs)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"><p>A Component is an object which adds functionality to a LearningSolver.</p>
|
||||
<p>For better code maintainability, LearningSolver simply delegates most of its
|
||||
functionality to Components. Each Component is responsible for exactly one ML
|
||||
strategy.</p></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">class Component(ABC):
|
||||
"""
|
||||
A Component is an object which adds functionality to a LearningSolver.
|
||||
|
||||
For better code maintainability, LearningSolver simply delegates most of its
|
||||
functionality to Components. Each Component is responsible for exactly one ML
|
||||
strategy.
|
||||
"""
|
||||
|
||||
def before_solve(
|
||||
self,
|
||||
solver: "LearningSolver",
|
||||
instance: Instance,
|
||||
model: Any,
|
||||
) -> None:
|
||||
"""
|
||||
Method called by LearningSolver before the problem is solved.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
solver
|
||||
The solver calling this method.
|
||||
instance
|
||||
The instance being solved.
|
||||
model
|
||||
The concrete optimization model being solved.
|
||||
"""
|
||||
return
|
||||
|
||||
@abstractmethod
|
||||
def after_solve(
|
||||
self,
|
||||
solver: "LearningSolver",
|
||||
instance: Instance,
|
||||
model: Any,
|
||||
stats: MIPSolveStats,
|
||||
training_data: TrainingSample,
|
||||
) -> None:
|
||||
"""
|
||||
Method called by LearningSolver after the problem is solved to optimality.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
solver: LearningSolver
|
||||
The solver calling this method.
|
||||
instance: Instance
|
||||
The instance being solved.
|
||||
model: Any
|
||||
The concrete optimization model being solved.
|
||||
stats: dict
|
||||
A dictionary containing statistics about the solution process, such as
|
||||
number of nodes explored and running time. Components are free to add
|
||||
their own statistics here. For example, PrimalSolutionComponent adds
|
||||
statistics regarding the number of predicted variables. All statistics in
|
||||
this dictionary are exported to the benchmark CSV file.
|
||||
training_data: dict
|
||||
A dictionary containing data that may be useful for training machine
|
||||
learning models and accelerating the solution process. Components are
|
||||
free to add their own training data here. For example,
|
||||
PrimalSolutionComponent adds the current primal solution. The data must
|
||||
be pickable.
|
||||
"""
|
||||
pass
|
||||
|
||||
def fit(
|
||||
self,
|
||||
training_instances: Union[List[str], List[Instance]],
|
||||
) -> None:
|
||||
return
|
||||
|
||||
def iteration_cb(
|
||||
self,
|
||||
solver: "LearningSolver",
|
||||
instance: Instance,
|
||||
model: Any,
|
||||
) -> bool:
|
||||
"""
|
||||
Method called by LearningSolver at the end of each iteration.
|
||||
|
||||
After solving the MIP, LearningSolver calls `iteration_cb` of each component,
|
||||
giving them a chance to modify the problem and resolve it before the solution
|
||||
process ends. For example, the lazy constraint component uses `iteration_cb`
|
||||
to check that all lazy constraints are satisfied.
|
||||
|
||||
If `iteration_cb` returns False for all components, the solution process
|
||||
ends. If it retunrs True for any component, the MIP is solved again.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
solver: LearningSolver
|
||||
The solver calling this method.
|
||||
instance: Instance
|
||||
The instance being solved.
|
||||
model: Any
|
||||
The concrete optimization model being solved.
|
||||
"""
|
||||
return False
|
||||
|
||||
def lazy_cb(
|
||||
self,
|
||||
solver: "LearningSolver",
|
||||
instance: Instance,
|
||||
model: Any,
|
||||
) -> None:
|
||||
return</code></pre>
|
||||
</details>
|
||||
<h3>Ancestors</h3>
|
||||
<ul class="hlist">
|
||||
<li>abc.ABC</li>
|
||||
</ul>
|
||||
<h3>Subclasses</h3>
|
||||
<ul class="hlist">
|
||||
<li><a title="miplearn.components.cuts.UserCutsComponent" href="cuts.html#miplearn.components.cuts.UserCutsComponent">UserCutsComponent</a></li>
|
||||
<li><a title="miplearn.components.lazy_dynamic.DynamicLazyConstraintsComponent" href="lazy_dynamic.html#miplearn.components.lazy_dynamic.DynamicLazyConstraintsComponent">DynamicLazyConstraintsComponent</a></li>
|
||||
<li><a title="miplearn.components.objective.ObjectiveValueComponent" href="objective.html#miplearn.components.objective.ObjectiveValueComponent">ObjectiveValueComponent</a></li>
|
||||
<li><a title="miplearn.components.primal.PrimalSolutionComponent" href="primal.html#miplearn.components.primal.PrimalSolutionComponent">PrimalSolutionComponent</a></li>
|
||||
<li><a title="miplearn.components.lazy_static.StaticLazyConstraintsComponent" href="lazy_static.html#miplearn.components.lazy_static.StaticLazyConstraintsComponent">StaticLazyConstraintsComponent</a></li>
|
||||
<li><a title="miplearn.components.composite.CompositeComponent" href="composite.html#miplearn.components.composite.CompositeComponent">CompositeComponent</a></li>
|
||||
<li><a title="miplearn.components.steps.drop_redundant.DropRedundantInequalitiesStep" href="steps/drop_redundant.html#miplearn.components.steps.drop_redundant.DropRedundantInequalitiesStep">DropRedundantInequalitiesStep</a></li>
|
||||
<li><a title="miplearn.components.steps.convert_tight.ConvertTightIneqsIntoEqsStep" href="steps/convert_tight.html#miplearn.components.steps.convert_tight.ConvertTightIneqsIntoEqsStep">ConvertTightIneqsIntoEqsStep</a></li>
|
||||
<li><a title="miplearn.components.steps.relax_integrality.RelaxIntegralityStep" href="steps/relax_integrality.html#miplearn.components.steps.relax_integrality.RelaxIntegralityStep">RelaxIntegralityStep</a></li>
|
||||
<li><a title="miplearn.components.relaxation.RelaxationComponent" href="relaxation.html#miplearn.components.relaxation.RelaxationComponent">RelaxationComponent</a></li>
|
||||
</ul>
|
||||
<h3>Methods</h3>
|
||||
<dl>
|
||||
<dt id="miplearn.components.component.Component.after_solve"><code class="name flex">
|
||||
<span>def <span class="ident">after_solve</span></span>(<span>self, solver, instance, model, stats, training_data)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"><p>Method called by LearningSolver after the problem is solved to optimality.</p>
|
||||
<h2 id="parameters">Parameters</h2>
|
||||
<dl>
|
||||
<dt><strong><code>solver</code></strong> : <code>LearningSolver</code></dt>
|
||||
<dd>The solver calling this method.</dd>
|
||||
<dt><strong><code>instance</code></strong> : <code>Instance</code></dt>
|
||||
<dd>The instance being solved.</dd>
|
||||
<dt><strong><code>model</code></strong> : <code>Any</code></dt>
|
||||
<dd>The concrete optimization model being solved.</dd>
|
||||
<dt><strong><code>stats</code></strong> : <code>dict</code></dt>
|
||||
<dd>A dictionary containing statistics about the solution process, such as
|
||||
number of nodes explored and running time. Components are free to add
|
||||
their own statistics here. For example, PrimalSolutionComponent adds
|
||||
statistics regarding the number of predicted variables. All statistics in
|
||||
this dictionary are exported to the benchmark CSV file.</dd>
|
||||
<dt><strong><code>training_data</code></strong> : <code>dict</code></dt>
|
||||
<dd>A dictionary containing data that may be useful for training machine
|
||||
learning models and accelerating the solution process. Components are
|
||||
free to add their own training data here. For example,
|
||||
PrimalSolutionComponent adds the current primal solution. The data must
|
||||
be pickable.</dd>
|
||||
</dl></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">@abstractmethod
|
||||
def after_solve(
|
||||
self,
|
||||
solver: "LearningSolver",
|
||||
instance: Instance,
|
||||
model: Any,
|
||||
stats: MIPSolveStats,
|
||||
training_data: TrainingSample,
|
||||
) -> None:
|
||||
"""
|
||||
Method called by LearningSolver after the problem is solved to optimality.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
solver: LearningSolver
|
||||
The solver calling this method.
|
||||
instance: Instance
|
||||
The instance being solved.
|
||||
model: Any
|
||||
The concrete optimization model being solved.
|
||||
stats: dict
|
||||
A dictionary containing statistics about the solution process, such as
|
||||
number of nodes explored and running time. Components are free to add
|
||||
their own statistics here. For example, PrimalSolutionComponent adds
|
||||
statistics regarding the number of predicted variables. All statistics in
|
||||
this dictionary are exported to the benchmark CSV file.
|
||||
training_data: dict
|
||||
A dictionary containing data that may be useful for training machine
|
||||
learning models and accelerating the solution process. Components are
|
||||
free to add their own training data here. For example,
|
||||
PrimalSolutionComponent adds the current primal solution. The data must
|
||||
be pickable.
|
||||
"""
|
||||
pass</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.components.component.Component.before_solve"><code class="name flex">
|
||||
<span>def <span class="ident">before_solve</span></span>(<span>self, solver, instance, model)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"><p>Method called by LearningSolver before the problem is solved.</p>
|
||||
<h2 id="parameters">Parameters</h2>
|
||||
<dl>
|
||||
<dt><strong><code>solver</code></strong></dt>
|
||||
<dd>The solver calling this method.</dd>
|
||||
<dt><strong><code>instance</code></strong></dt>
|
||||
<dd>The instance being solved.</dd>
|
||||
<dt><strong><code>model</code></strong></dt>
|
||||
<dd>The concrete optimization model being solved.</dd>
|
||||
</dl></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def before_solve(
|
||||
self,
|
||||
solver: "LearningSolver",
|
||||
instance: Instance,
|
||||
model: Any,
|
||||
) -> None:
|
||||
"""
|
||||
Method called by LearningSolver before the problem is solved.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
solver
|
||||
The solver calling this method.
|
||||
instance
|
||||
The instance being solved.
|
||||
model
|
||||
The concrete optimization model being solved.
|
||||
"""
|
||||
return</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.components.component.Component.fit"><code class="name flex">
|
||||
<span>def <span class="ident">fit</span></span>(<span>self, training_instances)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def fit(
|
||||
self,
|
||||
training_instances: Union[List[str], List[Instance]],
|
||||
) -> None:
|
||||
return</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.components.component.Component.iteration_cb"><code class="name flex">
|
||||
<span>def <span class="ident">iteration_cb</span></span>(<span>self, solver, instance, model)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"><p>Method called by LearningSolver at the end of each iteration.</p>
|
||||
<p>After solving the MIP, LearningSolver calls <code>iteration_cb</code> of each component,
|
||||
giving them a chance to modify the problem and resolve it before the solution
|
||||
process ends. For example, the lazy constraint component uses <code>iteration_cb</code>
|
||||
to check that all lazy constraints are satisfied.</p>
|
||||
<p>If <code>iteration_cb</code> returns False for all components, the solution process
|
||||
ends. If it retunrs True for any component, the MIP is solved again.</p>
|
||||
<h2 id="parameters">Parameters</h2>
|
||||
<dl>
|
||||
<dt><strong><code>solver</code></strong> : <code>LearningSolver</code></dt>
|
||||
<dd>The solver calling this method.</dd>
|
||||
<dt><strong><code>instance</code></strong> : <code>Instance</code></dt>
|
||||
<dd>The instance being solved.</dd>
|
||||
<dt><strong><code>model</code></strong> : <code>Any</code></dt>
|
||||
<dd>The concrete optimization model being solved.</dd>
|
||||
</dl></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def iteration_cb(
|
||||
self,
|
||||
solver: "LearningSolver",
|
||||
instance: Instance,
|
||||
model: Any,
|
||||
) -> bool:
|
||||
"""
|
||||
Method called by LearningSolver at the end of each iteration.
|
||||
|
||||
After solving the MIP, LearningSolver calls `iteration_cb` of each component,
|
||||
giving them a chance to modify the problem and resolve it before the solution
|
||||
process ends. For example, the lazy constraint component uses `iteration_cb`
|
||||
to check that all lazy constraints are satisfied.
|
||||
|
||||
If `iteration_cb` returns False for all components, the solution process
|
||||
ends. If it retunrs True for any component, the MIP is solved again.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
solver: LearningSolver
|
||||
The solver calling this method.
|
||||
instance: Instance
|
||||
The instance being solved.
|
||||
model: Any
|
||||
The concrete optimization model being solved.
|
||||
"""
|
||||
return False</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.components.component.Component.lazy_cb"><code class="name flex">
|
||||
<span>def <span class="ident">lazy_cb</span></span>(<span>self, solver, instance, model)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def lazy_cb(
|
||||
self,
|
||||
solver: "LearningSolver",
|
||||
instance: Instance,
|
||||
model: Any,
|
||||
) -> None:
|
||||
return</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</section>
|
||||
</article>
|
||||
<nav id="sidebar">
|
||||
<h1>Index</h1>
|
||||
<div class="toc">
|
||||
<ul></ul>
|
||||
</div>
|
||||
<ul id="index">
|
||||
<li><h3>Super-module</h3>
|
||||
<ul>
|
||||
<li><code><a title="miplearn.components" href="index.html">miplearn.components</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-classes">Classes</a></h3>
|
||||
<ul>
|
||||
<li>
|
||||
<h4><code><a title="miplearn.components.component.Component" href="#miplearn.components.component.Component">Component</a></code></h4>
|
||||
<ul class="">
|
||||
<li><code><a title="miplearn.components.component.Component.after_solve" href="#miplearn.components.component.Component.after_solve">after_solve</a></code></li>
|
||||
<li><code><a title="miplearn.components.component.Component.before_solve" href="#miplearn.components.component.Component.before_solve">before_solve</a></code></li>
|
||||
<li><code><a title="miplearn.components.component.Component.fit" href="#miplearn.components.component.Component.fit">fit</a></code></li>
|
||||
<li><code><a title="miplearn.components.component.Component.iteration_cb" href="#miplearn.components.component.Component.iteration_cb">iteration_cb</a></code></li>
|
||||
<li><code><a title="miplearn.components.component.Component.lazy_cb" href="#miplearn.components.component.Component.lazy_cb">lazy_cb</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</main>
|
||||
<footer id="footer">
|
||||
<p>Generated by <a href="https://pdoc3.github.io/pdoc"><cite>pdoc</cite> 0.7.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>
|
||||
234
0.2/api/miplearn/components/composite.html
Normal file
234
0.2/api/miplearn/components/composite.html
Normal file
@@ -0,0 +1,234 @@
|
||||
<!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.components.composite 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.components.composite</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 miplearn.components.component import Component
|
||||
|
||||
|
||||
class CompositeComponent(Component):
|
||||
"""
|
||||
A Component which redirects each method call to one or more subcomponents.
|
||||
|
||||
Useful for breaking down complex components into smaller classes. See
|
||||
RelaxationComponent for a concrete example.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
children : list[Component]
|
||||
Subcomponents that compose this component.
|
||||
"""
|
||||
|
||||
def __init__(self, children):
|
||||
self.children = children
|
||||
|
||||
def before_solve(self, solver, instance, model):
|
||||
for child in self.children:
|
||||
child.before_solve(solver, instance, model)
|
||||
|
||||
def after_solve(
|
||||
self,
|
||||
solver,
|
||||
instance,
|
||||
model,
|
||||
stats,
|
||||
training_data,
|
||||
):
|
||||
for child in self.children:
|
||||
child.after_solve(solver, instance, model, stats, training_data)
|
||||
|
||||
def fit(self, training_instances):
|
||||
for child in self.children:
|
||||
child.fit(training_instances)
|
||||
|
||||
def lazy_cb(self, solver, instance, model):
|
||||
for child in self.children:
|
||||
child.lazy_cb(solver, instance, model)
|
||||
|
||||
def iteration_cb(self, solver, instance, model):
|
||||
should_repeat = False
|
||||
for child in self.children:
|
||||
if child.iteration_cb(solver, instance, model):
|
||||
should_repeat = True
|
||||
return should_repeat</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-classes">Classes</h2>
|
||||
<dl>
|
||||
<dt id="miplearn.components.composite.CompositeComponent"><code class="flex name class">
|
||||
<span>class <span class="ident">CompositeComponent</span></span>
|
||||
<span>(</span><span>children)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"><p>A Component which redirects each method call to one or more subcomponents.</p>
|
||||
<p>Useful for breaking down complex components into smaller classes. See
|
||||
RelaxationComponent for a concrete example.</p>
|
||||
<h2 id="parameters">Parameters</h2>
|
||||
<dl>
|
||||
<dt><strong><code>children</code></strong> : <code>list</code>[<code>Component</code>]</dt>
|
||||
<dd>Subcomponents that compose this component.</dd>
|
||||
</dl></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">class CompositeComponent(Component):
|
||||
"""
|
||||
A Component which redirects each method call to one or more subcomponents.
|
||||
|
||||
Useful for breaking down complex components into smaller classes. See
|
||||
RelaxationComponent for a concrete example.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
children : list[Component]
|
||||
Subcomponents that compose this component.
|
||||
"""
|
||||
|
||||
def __init__(self, children):
|
||||
self.children = children
|
||||
|
||||
def before_solve(self, solver, instance, model):
|
||||
for child in self.children:
|
||||
child.before_solve(solver, instance, model)
|
||||
|
||||
def after_solve(
|
||||
self,
|
||||
solver,
|
||||
instance,
|
||||
model,
|
||||
stats,
|
||||
training_data,
|
||||
):
|
||||
for child in self.children:
|
||||
child.after_solve(solver, instance, model, stats, training_data)
|
||||
|
||||
def fit(self, training_instances):
|
||||
for child in self.children:
|
||||
child.fit(training_instances)
|
||||
|
||||
def lazy_cb(self, solver, instance, model):
|
||||
for child in self.children:
|
||||
child.lazy_cb(solver, instance, model)
|
||||
|
||||
def iteration_cb(self, solver, instance, model):
|
||||
should_repeat = False
|
||||
for child in self.children:
|
||||
if child.iteration_cb(solver, instance, model):
|
||||
should_repeat = True
|
||||
return should_repeat</code></pre>
|
||||
</details>
|
||||
<h3>Ancestors</h3>
|
||||
<ul class="hlist">
|
||||
<li><a title="miplearn.components.component.Component" href="component.html#miplearn.components.component.Component">Component</a></li>
|
||||
<li>abc.ABC</li>
|
||||
</ul>
|
||||
<h3>Methods</h3>
|
||||
<dl>
|
||||
<dt id="miplearn.components.composite.CompositeComponent.fit"><code class="name flex">
|
||||
<span>def <span class="ident">fit</span></span>(<span>self, training_instances)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def fit(self, training_instances):
|
||||
for child in self.children:
|
||||
child.fit(training_instances)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.components.composite.CompositeComponent.lazy_cb"><code class="name flex">
|
||||
<span>def <span class="ident">lazy_cb</span></span>(<span>self, solver, instance, model)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def lazy_cb(self, solver, instance, model):
|
||||
for child in self.children:
|
||||
child.lazy_cb(solver, instance, model)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>Inherited members</h3>
|
||||
<ul class="hlist">
|
||||
<li><code><b><a title="miplearn.components.component.Component" href="component.html#miplearn.components.component.Component">Component</a></b></code>:
|
||||
<ul class="hlist">
|
||||
<li><code><a title="miplearn.components.component.Component.after_solve" href="component.html#miplearn.components.component.Component.after_solve">after_solve</a></code></li>
|
||||
<li><code><a title="miplearn.components.component.Component.before_solve" href="component.html#miplearn.components.component.Component.before_solve">before_solve</a></code></li>
|
||||
<li><code><a title="miplearn.components.component.Component.iteration_cb" href="component.html#miplearn.components.component.Component.iteration_cb">iteration_cb</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.components" href="index.html">miplearn.components</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-classes">Classes</a></h3>
|
||||
<ul>
|
||||
<li>
|
||||
<h4><code><a title="miplearn.components.composite.CompositeComponent" href="#miplearn.components.composite.CompositeComponent">CompositeComponent</a></code></h4>
|
||||
<ul class="">
|
||||
<li><code><a title="miplearn.components.composite.CompositeComponent.fit" href="#miplearn.components.composite.CompositeComponent.fit">fit</a></code></li>
|
||||
<li><code><a title="miplearn.components.composite.CompositeComponent.lazy_cb" href="#miplearn.components.composite.CompositeComponent.lazy_cb">lazy_cb</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</main>
|
||||
<footer id="footer">
|
||||
<p>Generated by <a href="https://pdoc3.github.io/pdoc"><cite>pdoc</cite> 0.7.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>
|
||||
386
0.2/api/miplearn/components/cuts.html
Normal file
386
0.2/api/miplearn/components/cuts.html
Normal file
@@ -0,0 +1,386 @@
|
||||
<!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.components.cuts 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.components.cuts</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 copy import deepcopy
|
||||
from typing import Any, Dict
|
||||
|
||||
import numpy as np
|
||||
from tqdm.auto import tqdm
|
||||
|
||||
from miplearn.classifiers import Classifier
|
||||
from miplearn.classifiers.counting import CountingClassifier
|
||||
from miplearn.components import classifier_evaluation_dict
|
||||
from miplearn.components.component import Component
|
||||
from miplearn.extractors import InstanceFeaturesExtractor
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class UserCutsComponent(Component):
|
||||
"""
|
||||
A component that predicts which user cuts to enforce.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
classifier: Classifier = CountingClassifier(),
|
||||
threshold: float = 0.05,
|
||||
):
|
||||
self.threshold: float = threshold
|
||||
self.classifier_prototype: Classifier = classifier
|
||||
self.classifiers: Dict[Any, Classifier] = {}
|
||||
|
||||
def before_solve(self, solver, instance, model):
|
||||
instance.found_violated_user_cuts = []
|
||||
logger.info("Predicting violated user cuts...")
|
||||
violations = self.predict(instance)
|
||||
logger.info("Enforcing %d user cuts..." % len(violations))
|
||||
for v in violations:
|
||||
cut = instance.build_user_cut(model, v)
|
||||
solver.internal_solver.add_constraint(cut)
|
||||
|
||||
def after_solve(
|
||||
self,
|
||||
solver,
|
||||
instance,
|
||||
model,
|
||||
results,
|
||||
training_data,
|
||||
):
|
||||
pass
|
||||
|
||||
def fit(self, training_instances):
|
||||
logger.debug("Fitting...")
|
||||
features = InstanceFeaturesExtractor().extract(training_instances)
|
||||
|
||||
self.classifiers = {}
|
||||
violation_to_instance_idx = {}
|
||||
for (idx, instance) in enumerate(training_instances):
|
||||
if not hasattr(instance, "found_violated_user_cuts"):
|
||||
continue
|
||||
for v in instance.found_violated_user_cuts:
|
||||
if v not in self.classifiers:
|
||||
self.classifiers[v] = deepcopy(self.classifier_prototype)
|
||||
violation_to_instance_idx[v] = []
|
||||
violation_to_instance_idx[v] += [idx]
|
||||
|
||||
for (v, classifier) in tqdm(
|
||||
self.classifiers.items(),
|
||||
desc="Fit (user cuts)",
|
||||
disable=not sys.stdout.isatty(),
|
||||
):
|
||||
logger.debug("Training: %s" % (str(v)))
|
||||
label = np.zeros(len(training_instances))
|
||||
label[violation_to_instance_idx[v]] = 1.0
|
||||
classifier.fit(features, label)
|
||||
|
||||
def predict(self, instance):
|
||||
violations = []
|
||||
features = InstanceFeaturesExtractor().extract([instance])
|
||||
for (v, classifier) in self.classifiers.items():
|
||||
proba = classifier.predict_proba(features)
|
||||
if proba[0][1] > self.threshold:
|
||||
violations += [v]
|
||||
return violations
|
||||
|
||||
def evaluate(self, instances):
|
||||
results = {}
|
||||
all_violations = set()
|
||||
for instance in instances:
|
||||
all_violations |= set(instance.found_violated_user_cuts)
|
||||
for idx in tqdm(
|
||||
range(len(instances)),
|
||||
desc="Evaluate (lazy)",
|
||||
disable=not sys.stdout.isatty(),
|
||||
):
|
||||
instance = instances[idx]
|
||||
condition_positive = set(instance.found_violated_user_cuts)
|
||||
condition_negative = all_violations - condition_positive
|
||||
pred_positive = set(self.predict(instance)) & all_violations
|
||||
pred_negative = all_violations - pred_positive
|
||||
tp = len(pred_positive & condition_positive)
|
||||
tn = len(pred_negative & condition_negative)
|
||||
fp = len(pred_positive & condition_negative)
|
||||
fn = len(pred_negative & condition_positive)
|
||||
results[idx] = classifier_evaluation_dict(tp, tn, fp, fn)
|
||||
return results</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-classes">Classes</h2>
|
||||
<dl>
|
||||
<dt id="miplearn.components.cuts.UserCutsComponent"><code class="flex name class">
|
||||
<span>class <span class="ident">UserCutsComponent</span></span>
|
||||
<span>(</span><span>classifier=CountingClassifier(mean=None), threshold=0.05)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"><p>A component that predicts which user cuts to enforce.</p></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">class UserCutsComponent(Component):
|
||||
"""
|
||||
A component that predicts which user cuts to enforce.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
classifier: Classifier = CountingClassifier(),
|
||||
threshold: float = 0.05,
|
||||
):
|
||||
self.threshold: float = threshold
|
||||
self.classifier_prototype: Classifier = classifier
|
||||
self.classifiers: Dict[Any, Classifier] = {}
|
||||
|
||||
def before_solve(self, solver, instance, model):
|
||||
instance.found_violated_user_cuts = []
|
||||
logger.info("Predicting violated user cuts...")
|
||||
violations = self.predict(instance)
|
||||
logger.info("Enforcing %d user cuts..." % len(violations))
|
||||
for v in violations:
|
||||
cut = instance.build_user_cut(model, v)
|
||||
solver.internal_solver.add_constraint(cut)
|
||||
|
||||
def after_solve(
|
||||
self,
|
||||
solver,
|
||||
instance,
|
||||
model,
|
||||
results,
|
||||
training_data,
|
||||
):
|
||||
pass
|
||||
|
||||
def fit(self, training_instances):
|
||||
logger.debug("Fitting...")
|
||||
features = InstanceFeaturesExtractor().extract(training_instances)
|
||||
|
||||
self.classifiers = {}
|
||||
violation_to_instance_idx = {}
|
||||
for (idx, instance) in enumerate(training_instances):
|
||||
if not hasattr(instance, "found_violated_user_cuts"):
|
||||
continue
|
||||
for v in instance.found_violated_user_cuts:
|
||||
if v not in self.classifiers:
|
||||
self.classifiers[v] = deepcopy(self.classifier_prototype)
|
||||
violation_to_instance_idx[v] = []
|
||||
violation_to_instance_idx[v] += [idx]
|
||||
|
||||
for (v, classifier) in tqdm(
|
||||
self.classifiers.items(),
|
||||
desc="Fit (user cuts)",
|
||||
disable=not sys.stdout.isatty(),
|
||||
):
|
||||
logger.debug("Training: %s" % (str(v)))
|
||||
label = np.zeros(len(training_instances))
|
||||
label[violation_to_instance_idx[v]] = 1.0
|
||||
classifier.fit(features, label)
|
||||
|
||||
def predict(self, instance):
|
||||
violations = []
|
||||
features = InstanceFeaturesExtractor().extract([instance])
|
||||
for (v, classifier) in self.classifiers.items():
|
||||
proba = classifier.predict_proba(features)
|
||||
if proba[0][1] > self.threshold:
|
||||
violations += [v]
|
||||
return violations
|
||||
|
||||
def evaluate(self, instances):
|
||||
results = {}
|
||||
all_violations = set()
|
||||
for instance in instances:
|
||||
all_violations |= set(instance.found_violated_user_cuts)
|
||||
for idx in tqdm(
|
||||
range(len(instances)),
|
||||
desc="Evaluate (lazy)",
|
||||
disable=not sys.stdout.isatty(),
|
||||
):
|
||||
instance = instances[idx]
|
||||
condition_positive = set(instance.found_violated_user_cuts)
|
||||
condition_negative = all_violations - condition_positive
|
||||
pred_positive = set(self.predict(instance)) & all_violations
|
||||
pred_negative = all_violations - pred_positive
|
||||
tp = len(pred_positive & condition_positive)
|
||||
tn = len(pred_negative & condition_negative)
|
||||
fp = len(pred_positive & condition_negative)
|
||||
fn = len(pred_negative & condition_positive)
|
||||
results[idx] = classifier_evaluation_dict(tp, tn, fp, fn)
|
||||
return results</code></pre>
|
||||
</details>
|
||||
<h3>Ancestors</h3>
|
||||
<ul class="hlist">
|
||||
<li><a title="miplearn.components.component.Component" href="component.html#miplearn.components.component.Component">Component</a></li>
|
||||
<li>abc.ABC</li>
|
||||
</ul>
|
||||
<h3>Methods</h3>
|
||||
<dl>
|
||||
<dt id="miplearn.components.cuts.UserCutsComponent.evaluate"><code class="name flex">
|
||||
<span>def <span class="ident">evaluate</span></span>(<span>self, instances)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def evaluate(self, instances):
|
||||
results = {}
|
||||
all_violations = set()
|
||||
for instance in instances:
|
||||
all_violations |= set(instance.found_violated_user_cuts)
|
||||
for idx in tqdm(
|
||||
range(len(instances)),
|
||||
desc="Evaluate (lazy)",
|
||||
disable=not sys.stdout.isatty(),
|
||||
):
|
||||
instance = instances[idx]
|
||||
condition_positive = set(instance.found_violated_user_cuts)
|
||||
condition_negative = all_violations - condition_positive
|
||||
pred_positive = set(self.predict(instance)) & all_violations
|
||||
pred_negative = all_violations - pred_positive
|
||||
tp = len(pred_positive & condition_positive)
|
||||
tn = len(pred_negative & condition_negative)
|
||||
fp = len(pred_positive & condition_negative)
|
||||
fn = len(pred_negative & condition_positive)
|
||||
results[idx] = classifier_evaluation_dict(tp, tn, fp, fn)
|
||||
return results</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.components.cuts.UserCutsComponent.fit"><code class="name flex">
|
||||
<span>def <span class="ident">fit</span></span>(<span>self, training_instances)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def fit(self, training_instances):
|
||||
logger.debug("Fitting...")
|
||||
features = InstanceFeaturesExtractor().extract(training_instances)
|
||||
|
||||
self.classifiers = {}
|
||||
violation_to_instance_idx = {}
|
||||
for (idx, instance) in enumerate(training_instances):
|
||||
if not hasattr(instance, "found_violated_user_cuts"):
|
||||
continue
|
||||
for v in instance.found_violated_user_cuts:
|
||||
if v not in self.classifiers:
|
||||
self.classifiers[v] = deepcopy(self.classifier_prototype)
|
||||
violation_to_instance_idx[v] = []
|
||||
violation_to_instance_idx[v] += [idx]
|
||||
|
||||
for (v, classifier) in tqdm(
|
||||
self.classifiers.items(),
|
||||
desc="Fit (user cuts)",
|
||||
disable=not sys.stdout.isatty(),
|
||||
):
|
||||
logger.debug("Training: %s" % (str(v)))
|
||||
label = np.zeros(len(training_instances))
|
||||
label[violation_to_instance_idx[v]] = 1.0
|
||||
classifier.fit(features, label)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.components.cuts.UserCutsComponent.predict"><code class="name flex">
|
||||
<span>def <span class="ident">predict</span></span>(<span>self, instance)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def predict(self, instance):
|
||||
violations = []
|
||||
features = InstanceFeaturesExtractor().extract([instance])
|
||||
for (v, classifier) in self.classifiers.items():
|
||||
proba = classifier.predict_proba(features)
|
||||
if proba[0][1] > self.threshold:
|
||||
violations += [v]
|
||||
return violations</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>Inherited members</h3>
|
||||
<ul class="hlist">
|
||||
<li><code><b><a title="miplearn.components.component.Component" href="component.html#miplearn.components.component.Component">Component</a></b></code>:
|
||||
<ul class="hlist">
|
||||
<li><code><a title="miplearn.components.component.Component.after_solve" href="component.html#miplearn.components.component.Component.after_solve">after_solve</a></code></li>
|
||||
<li><code><a title="miplearn.components.component.Component.before_solve" href="component.html#miplearn.components.component.Component.before_solve">before_solve</a></code></li>
|
||||
<li><code><a title="miplearn.components.component.Component.iteration_cb" href="component.html#miplearn.components.component.Component.iteration_cb">iteration_cb</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.components" href="index.html">miplearn.components</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-classes">Classes</a></h3>
|
||||
<ul>
|
||||
<li>
|
||||
<h4><code><a title="miplearn.components.cuts.UserCutsComponent" href="#miplearn.components.cuts.UserCutsComponent">UserCutsComponent</a></code></h4>
|
||||
<ul class="">
|
||||
<li><code><a title="miplearn.components.cuts.UserCutsComponent.evaluate" href="#miplearn.components.cuts.UserCutsComponent.evaluate">evaluate</a></code></li>
|
||||
<li><code><a title="miplearn.components.cuts.UserCutsComponent.fit" href="#miplearn.components.cuts.UserCutsComponent.fit">fit</a></code></li>
|
||||
<li><code><a title="miplearn.components.cuts.UserCutsComponent.predict" href="#miplearn.components.cuts.UserCutsComponent.predict">predict</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</main>
|
||||
<footer id="footer">
|
||||
<p>Generated by <a href="https://pdoc3.github.io/pdoc"><cite>pdoc</cite> 0.7.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>
|
||||
211
0.2/api/miplearn/components/index.html
Normal file
211
0.2/api/miplearn/components/index.html
Normal file
@@ -0,0 +1,211 @@
|
||||
<!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.components 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.components</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.
|
||||
|
||||
|
||||
def classifier_evaluation_dict(tp, tn, fp, fn):
|
||||
p = tp + fn
|
||||
n = fp + tn
|
||||
d = {
|
||||
"Predicted positive": fp + tp,
|
||||
"Predicted negative": fn + tn,
|
||||
"Condition positive": p,
|
||||
"Condition negative": n,
|
||||
"True positive": tp,
|
||||
"True negative": tn,
|
||||
"False positive": fp,
|
||||
"False negative": fn,
|
||||
"Accuracy": (tp + tn) / (p + n),
|
||||
"F1 score": (2 * tp) / (2 * tp + fp + fn),
|
||||
}
|
||||
|
||||
if p > 0:
|
||||
d["Recall"] = tp / p
|
||||
else:
|
||||
d["Recall"] = 1.0
|
||||
|
||||
if tp + fp > 0:
|
||||
d["Precision"] = tp / (tp + fp)
|
||||
else:
|
||||
d["Precision"] = 1.0
|
||||
|
||||
t = (p + n) / 100.0
|
||||
d["Predicted positive (%)"] = d["Predicted positive"] / t
|
||||
d["Predicted negative (%)"] = d["Predicted negative"] / t
|
||||
d["Condition positive (%)"] = d["Condition positive"] / t
|
||||
d["Condition negative (%)"] = d["Condition negative"] / t
|
||||
d["True positive (%)"] = d["True positive"] / t
|
||||
d["True negative (%)"] = d["True negative"] / t
|
||||
d["False positive (%)"] = d["False positive"] / t
|
||||
d["False negative (%)"] = d["False negative"] / t
|
||||
return d</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-submodules">Sub-modules</h2>
|
||||
<dl>
|
||||
<dt><code class="name"><a title="miplearn.components.component" href="component.html">miplearn.components.component</a></code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
</dd>
|
||||
<dt><code class="name"><a title="miplearn.components.composite" href="composite.html">miplearn.components.composite</a></code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
</dd>
|
||||
<dt><code class="name"><a title="miplearn.components.cuts" href="cuts.html">miplearn.components.cuts</a></code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
</dd>
|
||||
<dt><code class="name"><a title="miplearn.components.lazy_dynamic" href="lazy_dynamic.html">miplearn.components.lazy_dynamic</a></code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
</dd>
|
||||
<dt><code class="name"><a title="miplearn.components.lazy_static" href="lazy_static.html">miplearn.components.lazy_static</a></code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
</dd>
|
||||
<dt><code class="name"><a title="miplearn.components.objective" href="objective.html">miplearn.components.objective</a></code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
</dd>
|
||||
<dt><code class="name"><a title="miplearn.components.primal" href="primal.html">miplearn.components.primal</a></code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
</dd>
|
||||
<dt><code class="name"><a title="miplearn.components.relaxation" href="relaxation.html">miplearn.components.relaxation</a></code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
</dd>
|
||||
<dt><code class="name"><a title="miplearn.components.steps" href="steps/index.html">miplearn.components.steps</a></code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
</dd>
|
||||
<dt><code class="name"><a title="miplearn.components.tests" href="tests/index.html">miplearn.components.tests</a></code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
</dd>
|
||||
</dl>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-functions">Functions</h2>
|
||||
<dl>
|
||||
<dt id="miplearn.components.classifier_evaluation_dict"><code class="name flex">
|
||||
<span>def <span class="ident">classifier_evaluation_dict</span></span>(<span>tp, tn, fp, fn)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def classifier_evaluation_dict(tp, tn, fp, fn):
|
||||
p = tp + fn
|
||||
n = fp + tn
|
||||
d = {
|
||||
"Predicted positive": fp + tp,
|
||||
"Predicted negative": fn + tn,
|
||||
"Condition positive": p,
|
||||
"Condition negative": n,
|
||||
"True positive": tp,
|
||||
"True negative": tn,
|
||||
"False positive": fp,
|
||||
"False negative": fn,
|
||||
"Accuracy": (tp + tn) / (p + n),
|
||||
"F1 score": (2 * tp) / (2 * tp + fp + fn),
|
||||
}
|
||||
|
||||
if p > 0:
|
||||
d["Recall"] = tp / p
|
||||
else:
|
||||
d["Recall"] = 1.0
|
||||
|
||||
if tp + fp > 0:
|
||||
d["Precision"] = tp / (tp + fp)
|
||||
else:
|
||||
d["Precision"] = 1.0
|
||||
|
||||
t = (p + n) / 100.0
|
||||
d["Predicted positive (%)"] = d["Predicted positive"] / t
|
||||
d["Predicted negative (%)"] = d["Predicted negative"] / t
|
||||
d["Condition positive (%)"] = d["Condition positive"] / t
|
||||
d["Condition negative (%)"] = d["Condition negative"] / t
|
||||
d["True positive (%)"] = d["True positive"] / t
|
||||
d["True negative (%)"] = d["True negative"] / t
|
||||
d["False positive (%)"] = d["False positive"] / t
|
||||
d["False negative (%)"] = d["False negative"] / t
|
||||
return d</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" 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.components.component" href="component.html">miplearn.components.component</a></code></li>
|
||||
<li><code><a title="miplearn.components.composite" href="composite.html">miplearn.components.composite</a></code></li>
|
||||
<li><code><a title="miplearn.components.cuts" href="cuts.html">miplearn.components.cuts</a></code></li>
|
||||
<li><code><a title="miplearn.components.lazy_dynamic" href="lazy_dynamic.html">miplearn.components.lazy_dynamic</a></code></li>
|
||||
<li><code><a title="miplearn.components.lazy_static" href="lazy_static.html">miplearn.components.lazy_static</a></code></li>
|
||||
<li><code><a title="miplearn.components.objective" href="objective.html">miplearn.components.objective</a></code></li>
|
||||
<li><code><a title="miplearn.components.primal" href="primal.html">miplearn.components.primal</a></code></li>
|
||||
<li><code><a title="miplearn.components.relaxation" href="relaxation.html">miplearn.components.relaxation</a></code></li>
|
||||
<li><code><a title="miplearn.components.steps" href="steps/index.html">miplearn.components.steps</a></code></li>
|
||||
<li><code><a title="miplearn.components.tests" href="tests/index.html">miplearn.components.tests</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-functions">Functions</a></h3>
|
||||
<ul class="">
|
||||
<li><code><a title="miplearn.components.classifier_evaluation_dict" href="#miplearn.components.classifier_evaluation_dict">classifier_evaluation_dict</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>
|
||||
410
0.2/api/miplearn/components/lazy_dynamic.html
Normal file
410
0.2/api/miplearn/components/lazy_dynamic.html
Normal file
@@ -0,0 +1,410 @@
|
||||
<!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.components.lazy_dynamic 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.components.lazy_dynamic</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 copy import deepcopy
|
||||
from typing import Any, Dict
|
||||
|
||||
import numpy as np
|
||||
from tqdm.auto import tqdm
|
||||
|
||||
from miplearn.classifiers import Classifier
|
||||
from miplearn.classifiers.counting import CountingClassifier
|
||||
from miplearn.components import classifier_evaluation_dict
|
||||
from miplearn.components.component import Component
|
||||
from miplearn.extractors import InstanceFeaturesExtractor, InstanceIterator
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class DynamicLazyConstraintsComponent(Component):
|
||||
"""
|
||||
A component that predicts which lazy constraints to enforce.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
classifier: Classifier = CountingClassifier(),
|
||||
threshold: float = 0.05,
|
||||
):
|
||||
self.threshold: float = threshold
|
||||
self.classifier_prototype: Classifier = classifier
|
||||
self.classifiers: Dict[Any, Classifier] = {}
|
||||
|
||||
def before_solve(self, solver, instance, model):
|
||||
instance.found_violated_lazy_constraints = []
|
||||
logger.info("Predicting violated lazy constraints...")
|
||||
violations = self.predict(instance)
|
||||
logger.info("Enforcing %d lazy constraints..." % len(violations))
|
||||
for v in violations:
|
||||
cut = instance.build_lazy_constraint(model, v)
|
||||
solver.internal_solver.add_constraint(cut)
|
||||
|
||||
def iteration_cb(self, solver, instance, model):
|
||||
logger.debug("Finding violated (dynamic) lazy constraints...")
|
||||
violations = instance.find_violated_lazy_constraints(model)
|
||||
if len(violations) == 0:
|
||||
return False
|
||||
instance.found_violated_lazy_constraints += violations
|
||||
logger.debug(" %d violations found" % len(violations))
|
||||
for v in violations:
|
||||
cut = instance.build_lazy_constraint(model, v)
|
||||
solver.internal_solver.add_constraint(cut)
|
||||
return True
|
||||
|
||||
def after_solve(
|
||||
self,
|
||||
solver,
|
||||
instance,
|
||||
model,
|
||||
stats,
|
||||
training_data,
|
||||
):
|
||||
pass
|
||||
|
||||
def fit(self, training_instances):
|
||||
logger.debug("Fitting...")
|
||||
features = InstanceFeaturesExtractor().extract(training_instances)
|
||||
|
||||
self.classifiers = {}
|
||||
violation_to_instance_idx = {}
|
||||
for (idx, instance) in enumerate(InstanceIterator(training_instances)):
|
||||
for v in instance.found_violated_lazy_constraints:
|
||||
if isinstance(v, list):
|
||||
v = tuple(v)
|
||||
if v not in self.classifiers:
|
||||
self.classifiers[v] = deepcopy(self.classifier_prototype)
|
||||
violation_to_instance_idx[v] = []
|
||||
violation_to_instance_idx[v] += [idx]
|
||||
|
||||
for (v, classifier) in tqdm(
|
||||
self.classifiers.items(),
|
||||
desc="Fit (lazy)",
|
||||
disable=not sys.stdout.isatty(),
|
||||
):
|
||||
logger.debug("Training: %s" % (str(v)))
|
||||
label = np.zeros(len(training_instances))
|
||||
label[violation_to_instance_idx[v]] = 1.0
|
||||
classifier.fit(features, label)
|
||||
|
||||
def predict(self, instance):
|
||||
violations = []
|
||||
features = InstanceFeaturesExtractor().extract([instance])
|
||||
for (v, classifier) in self.classifiers.items():
|
||||
proba = classifier.predict_proba(features)
|
||||
if proba[0][1] > self.threshold:
|
||||
violations += [v]
|
||||
return violations
|
||||
|
||||
def evaluate(self, instances):
|
||||
results = {}
|
||||
all_violations = set()
|
||||
for instance in instances:
|
||||
all_violations |= set(instance.found_violated_lazy_constraints)
|
||||
for idx in tqdm(
|
||||
range(len(instances)),
|
||||
desc="Evaluate (lazy)",
|
||||
disable=not sys.stdout.isatty(),
|
||||
):
|
||||
instance = instances[idx]
|
||||
condition_positive = set(instance.found_violated_lazy_constraints)
|
||||
condition_negative = all_violations - condition_positive
|
||||
pred_positive = set(self.predict(instance)) & all_violations
|
||||
pred_negative = all_violations - pred_positive
|
||||
tp = len(pred_positive & condition_positive)
|
||||
tn = len(pred_negative & condition_negative)
|
||||
fp = len(pred_positive & condition_negative)
|
||||
fn = len(pred_negative & condition_positive)
|
||||
results[idx] = classifier_evaluation_dict(tp, tn, fp, fn)
|
||||
return results</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-classes">Classes</h2>
|
||||
<dl>
|
||||
<dt id="miplearn.components.lazy_dynamic.DynamicLazyConstraintsComponent"><code class="flex name class">
|
||||
<span>class <span class="ident">DynamicLazyConstraintsComponent</span></span>
|
||||
<span>(</span><span>classifier=CountingClassifier(mean=None), threshold=0.05)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"><p>A component that predicts which lazy constraints to enforce.</p></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">class DynamicLazyConstraintsComponent(Component):
|
||||
"""
|
||||
A component that predicts which lazy constraints to enforce.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
classifier: Classifier = CountingClassifier(),
|
||||
threshold: float = 0.05,
|
||||
):
|
||||
self.threshold: float = threshold
|
||||
self.classifier_prototype: Classifier = classifier
|
||||
self.classifiers: Dict[Any, Classifier] = {}
|
||||
|
||||
def before_solve(self, solver, instance, model):
|
||||
instance.found_violated_lazy_constraints = []
|
||||
logger.info("Predicting violated lazy constraints...")
|
||||
violations = self.predict(instance)
|
||||
logger.info("Enforcing %d lazy constraints..." % len(violations))
|
||||
for v in violations:
|
||||
cut = instance.build_lazy_constraint(model, v)
|
||||
solver.internal_solver.add_constraint(cut)
|
||||
|
||||
def iteration_cb(self, solver, instance, model):
|
||||
logger.debug("Finding violated (dynamic) lazy constraints...")
|
||||
violations = instance.find_violated_lazy_constraints(model)
|
||||
if len(violations) == 0:
|
||||
return False
|
||||
instance.found_violated_lazy_constraints += violations
|
||||
logger.debug(" %d violations found" % len(violations))
|
||||
for v in violations:
|
||||
cut = instance.build_lazy_constraint(model, v)
|
||||
solver.internal_solver.add_constraint(cut)
|
||||
return True
|
||||
|
||||
def after_solve(
|
||||
self,
|
||||
solver,
|
||||
instance,
|
||||
model,
|
||||
stats,
|
||||
training_data,
|
||||
):
|
||||
pass
|
||||
|
||||
def fit(self, training_instances):
|
||||
logger.debug("Fitting...")
|
||||
features = InstanceFeaturesExtractor().extract(training_instances)
|
||||
|
||||
self.classifiers = {}
|
||||
violation_to_instance_idx = {}
|
||||
for (idx, instance) in enumerate(InstanceIterator(training_instances)):
|
||||
for v in instance.found_violated_lazy_constraints:
|
||||
if isinstance(v, list):
|
||||
v = tuple(v)
|
||||
if v not in self.classifiers:
|
||||
self.classifiers[v] = deepcopy(self.classifier_prototype)
|
||||
violation_to_instance_idx[v] = []
|
||||
violation_to_instance_idx[v] += [idx]
|
||||
|
||||
for (v, classifier) in tqdm(
|
||||
self.classifiers.items(),
|
||||
desc="Fit (lazy)",
|
||||
disable=not sys.stdout.isatty(),
|
||||
):
|
||||
logger.debug("Training: %s" % (str(v)))
|
||||
label = np.zeros(len(training_instances))
|
||||
label[violation_to_instance_idx[v]] = 1.0
|
||||
classifier.fit(features, label)
|
||||
|
||||
def predict(self, instance):
|
||||
violations = []
|
||||
features = InstanceFeaturesExtractor().extract([instance])
|
||||
for (v, classifier) in self.classifiers.items():
|
||||
proba = classifier.predict_proba(features)
|
||||
if proba[0][1] > self.threshold:
|
||||
violations += [v]
|
||||
return violations
|
||||
|
||||
def evaluate(self, instances):
|
||||
results = {}
|
||||
all_violations = set()
|
||||
for instance in instances:
|
||||
all_violations |= set(instance.found_violated_lazy_constraints)
|
||||
for idx in tqdm(
|
||||
range(len(instances)),
|
||||
desc="Evaluate (lazy)",
|
||||
disable=not sys.stdout.isatty(),
|
||||
):
|
||||
instance = instances[idx]
|
||||
condition_positive = set(instance.found_violated_lazy_constraints)
|
||||
condition_negative = all_violations - condition_positive
|
||||
pred_positive = set(self.predict(instance)) & all_violations
|
||||
pred_negative = all_violations - pred_positive
|
||||
tp = len(pred_positive & condition_positive)
|
||||
tn = len(pred_negative & condition_negative)
|
||||
fp = len(pred_positive & condition_negative)
|
||||
fn = len(pred_negative & condition_positive)
|
||||
results[idx] = classifier_evaluation_dict(tp, tn, fp, fn)
|
||||
return results</code></pre>
|
||||
</details>
|
||||
<h3>Ancestors</h3>
|
||||
<ul class="hlist">
|
||||
<li><a title="miplearn.components.component.Component" href="component.html#miplearn.components.component.Component">Component</a></li>
|
||||
<li>abc.ABC</li>
|
||||
</ul>
|
||||
<h3>Methods</h3>
|
||||
<dl>
|
||||
<dt id="miplearn.components.lazy_dynamic.DynamicLazyConstraintsComponent.evaluate"><code class="name flex">
|
||||
<span>def <span class="ident">evaluate</span></span>(<span>self, instances)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def evaluate(self, instances):
|
||||
results = {}
|
||||
all_violations = set()
|
||||
for instance in instances:
|
||||
all_violations |= set(instance.found_violated_lazy_constraints)
|
||||
for idx in tqdm(
|
||||
range(len(instances)),
|
||||
desc="Evaluate (lazy)",
|
||||
disable=not sys.stdout.isatty(),
|
||||
):
|
||||
instance = instances[idx]
|
||||
condition_positive = set(instance.found_violated_lazy_constraints)
|
||||
condition_negative = all_violations - condition_positive
|
||||
pred_positive = set(self.predict(instance)) & all_violations
|
||||
pred_negative = all_violations - pred_positive
|
||||
tp = len(pred_positive & condition_positive)
|
||||
tn = len(pred_negative & condition_negative)
|
||||
fp = len(pred_positive & condition_negative)
|
||||
fn = len(pred_negative & condition_positive)
|
||||
results[idx] = classifier_evaluation_dict(tp, tn, fp, fn)
|
||||
return results</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.components.lazy_dynamic.DynamicLazyConstraintsComponent.fit"><code class="name flex">
|
||||
<span>def <span class="ident">fit</span></span>(<span>self, training_instances)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def fit(self, training_instances):
|
||||
logger.debug("Fitting...")
|
||||
features = InstanceFeaturesExtractor().extract(training_instances)
|
||||
|
||||
self.classifiers = {}
|
||||
violation_to_instance_idx = {}
|
||||
for (idx, instance) in enumerate(InstanceIterator(training_instances)):
|
||||
for v in instance.found_violated_lazy_constraints:
|
||||
if isinstance(v, list):
|
||||
v = tuple(v)
|
||||
if v not in self.classifiers:
|
||||
self.classifiers[v] = deepcopy(self.classifier_prototype)
|
||||
violation_to_instance_idx[v] = []
|
||||
violation_to_instance_idx[v] += [idx]
|
||||
|
||||
for (v, classifier) in tqdm(
|
||||
self.classifiers.items(),
|
||||
desc="Fit (lazy)",
|
||||
disable=not sys.stdout.isatty(),
|
||||
):
|
||||
logger.debug("Training: %s" % (str(v)))
|
||||
label = np.zeros(len(training_instances))
|
||||
label[violation_to_instance_idx[v]] = 1.0
|
||||
classifier.fit(features, label)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.components.lazy_dynamic.DynamicLazyConstraintsComponent.predict"><code class="name flex">
|
||||
<span>def <span class="ident">predict</span></span>(<span>self, instance)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def predict(self, instance):
|
||||
violations = []
|
||||
features = InstanceFeaturesExtractor().extract([instance])
|
||||
for (v, classifier) in self.classifiers.items():
|
||||
proba = classifier.predict_proba(features)
|
||||
if proba[0][1] > self.threshold:
|
||||
violations += [v]
|
||||
return violations</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>Inherited members</h3>
|
||||
<ul class="hlist">
|
||||
<li><code><b><a title="miplearn.components.component.Component" href="component.html#miplearn.components.component.Component">Component</a></b></code>:
|
||||
<ul class="hlist">
|
||||
<li><code><a title="miplearn.components.component.Component.after_solve" href="component.html#miplearn.components.component.Component.after_solve">after_solve</a></code></li>
|
||||
<li><code><a title="miplearn.components.component.Component.before_solve" href="component.html#miplearn.components.component.Component.before_solve">before_solve</a></code></li>
|
||||
<li><code><a title="miplearn.components.component.Component.iteration_cb" href="component.html#miplearn.components.component.Component.iteration_cb">iteration_cb</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.components" href="index.html">miplearn.components</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-classes">Classes</a></h3>
|
||||
<ul>
|
||||
<li>
|
||||
<h4><code><a title="miplearn.components.lazy_dynamic.DynamicLazyConstraintsComponent" href="#miplearn.components.lazy_dynamic.DynamicLazyConstraintsComponent">DynamicLazyConstraintsComponent</a></code></h4>
|
||||
<ul class="">
|
||||
<li><code><a title="miplearn.components.lazy_dynamic.DynamicLazyConstraintsComponent.evaluate" href="#miplearn.components.lazy_dynamic.DynamicLazyConstraintsComponent.evaluate">evaluate</a></code></li>
|
||||
<li><code><a title="miplearn.components.lazy_dynamic.DynamicLazyConstraintsComponent.fit" href="#miplearn.components.lazy_dynamic.DynamicLazyConstraintsComponent.fit">fit</a></code></li>
|
||||
<li><code><a title="miplearn.components.lazy_dynamic.DynamicLazyConstraintsComponent.predict" href="#miplearn.components.lazy_dynamic.DynamicLazyConstraintsComponent.predict">predict</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</main>
|
||||
<footer id="footer">
|
||||
<p>Generated by <a href="https://pdoc3.github.io/pdoc"><cite>pdoc</cite> 0.7.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>
|
||||
624
0.2/api/miplearn/components/lazy_static.html
Normal file
624
0.2/api/miplearn/components/lazy_static.html
Normal file
@@ -0,0 +1,624 @@
|
||||
<!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.components.lazy_static 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.components.lazy_static</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 copy import deepcopy
|
||||
|
||||
import numpy as np
|
||||
from tqdm.auto import tqdm
|
||||
|
||||
from miplearn.classifiers.counting import CountingClassifier
|
||||
from miplearn.components.component import Component
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class LazyConstraint:
|
||||
def __init__(self, cid, obj):
|
||||
self.cid = cid
|
||||
self.obj = obj
|
||||
|
||||
|
||||
class StaticLazyConstraintsComponent(Component):
|
||||
def __init__(
|
||||
self,
|
||||
classifier=CountingClassifier(),
|
||||
threshold=0.05,
|
||||
use_two_phase_gap=True,
|
||||
large_gap=1e-2,
|
||||
violation_tolerance=-0.5,
|
||||
):
|
||||
self.threshold = threshold
|
||||
self.classifier_prototype = classifier
|
||||
self.classifiers = {}
|
||||
self.pool = []
|
||||
self.original_gap = None
|
||||
self.large_gap = large_gap
|
||||
self.is_gap_large = False
|
||||
self.use_two_phase_gap = use_two_phase_gap
|
||||
self.violation_tolerance = violation_tolerance
|
||||
|
||||
def before_solve(self, solver, instance, model):
|
||||
self.pool = []
|
||||
if not solver.use_lazy_cb and self.use_two_phase_gap:
|
||||
logger.info("Increasing gap tolerance to %f", self.large_gap)
|
||||
self.original_gap = solver.gap_tolerance
|
||||
self.is_gap_large = True
|
||||
solver.internal_solver.set_gap_tolerance(self.large_gap)
|
||||
|
||||
instance.found_violated_lazy_constraints = []
|
||||
if instance.has_static_lazy_constraints():
|
||||
self._extract_and_predict_static(solver, instance)
|
||||
|
||||
def after_solve(
|
||||
self,
|
||||
solver,
|
||||
instance,
|
||||
model,
|
||||
stats,
|
||||
training_data,
|
||||
):
|
||||
pass
|
||||
|
||||
def iteration_cb(self, solver, instance, model):
|
||||
if solver.use_lazy_cb:
|
||||
return False
|
||||
else:
|
||||
should_repeat = self._check_and_add(instance, solver)
|
||||
if should_repeat:
|
||||
return True
|
||||
else:
|
||||
if self.is_gap_large:
|
||||
logger.info("Restoring gap tolerance to %f", self.original_gap)
|
||||
solver.internal_solver.set_gap_tolerance(self.original_gap)
|
||||
self.is_gap_large = False
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def lazy_cb(self, solver, instance, model):
|
||||
self._check_and_add(instance, solver)
|
||||
|
||||
def _check_and_add(self, instance, solver):
|
||||
logger.debug("Finding violated lazy constraints...")
|
||||
constraints_to_add = []
|
||||
for c in self.pool:
|
||||
if not solver.internal_solver.is_constraint_satisfied(
|
||||
c.obj, tol=self.violation_tolerance
|
||||
):
|
||||
constraints_to_add.append(c)
|
||||
for c in constraints_to_add:
|
||||
self.pool.remove(c)
|
||||
solver.internal_solver.add_constraint(c.obj)
|
||||
instance.found_violated_lazy_constraints += [c.cid]
|
||||
if len(constraints_to_add) > 0:
|
||||
logger.info(
|
||||
"%8d lazy constraints added %8d in the pool"
|
||||
% (len(constraints_to_add), len(self.pool))
|
||||
)
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def fit(self, training_instances):
|
||||
training_instances = [
|
||||
t
|
||||
for t in training_instances
|
||||
if hasattr(t, "found_violated_lazy_constraints")
|
||||
]
|
||||
|
||||
logger.debug("Extracting x and y...")
|
||||
x = self.x(training_instances)
|
||||
y = self.y(training_instances)
|
||||
|
||||
logger.debug("Fitting...")
|
||||
for category in tqdm(
|
||||
x.keys(), desc="Fit (lazy)", disable=not sys.stdout.isatty()
|
||||
):
|
||||
if category not in self.classifiers:
|
||||
self.classifiers[category] = deepcopy(self.classifier_prototype)
|
||||
self.classifiers[category].fit(x[category], y[category])
|
||||
|
||||
def predict(self, instance):
|
||||
pass
|
||||
|
||||
def evaluate(self, instances):
|
||||
pass
|
||||
|
||||
def _extract_and_predict_static(self, solver, instance):
|
||||
x = {}
|
||||
constraints = {}
|
||||
logger.info("Extracting lazy constraints...")
|
||||
for cid in solver.internal_solver.get_constraint_ids():
|
||||
if instance.is_constraint_lazy(cid):
|
||||
category = instance.get_constraint_category(cid)
|
||||
if category not in x:
|
||||
x[category] = []
|
||||
constraints[category] = []
|
||||
x[category] += [instance.get_constraint_features(cid)]
|
||||
c = LazyConstraint(
|
||||
cid=cid,
|
||||
obj=solver.internal_solver.extract_constraint(cid),
|
||||
)
|
||||
constraints[category] += [c]
|
||||
self.pool.append(c)
|
||||
logger.info("%8d lazy constraints extracted" % len(self.pool))
|
||||
logger.info("Predicting required lazy constraints...")
|
||||
n_added = 0
|
||||
for (category, x_values) in x.items():
|
||||
if category not in self.classifiers:
|
||||
continue
|
||||
if isinstance(x_values[0], np.ndarray):
|
||||
x[category] = np.array(x_values)
|
||||
proba = self.classifiers[category].predict_proba(x[category])
|
||||
for i in range(len(proba)):
|
||||
if proba[i][1] > self.threshold:
|
||||
n_added += 1
|
||||
c = constraints[category][i]
|
||||
self.pool.remove(c)
|
||||
solver.internal_solver.add_constraint(c.obj)
|
||||
instance.found_violated_lazy_constraints += [c.cid]
|
||||
logger.info(
|
||||
"%8d lazy constraints added %8d in the pool"
|
||||
% (
|
||||
n_added,
|
||||
len(self.pool),
|
||||
)
|
||||
)
|
||||
|
||||
def _collect_constraints(self, train_instances):
|
||||
constraints = {}
|
||||
for instance in train_instances:
|
||||
for cid in instance.found_violated_lazy_constraints:
|
||||
category = instance.get_constraint_category(cid)
|
||||
if category not in constraints:
|
||||
constraints[category] = set()
|
||||
constraints[category].add(cid)
|
||||
for (category, cids) in constraints.items():
|
||||
constraints[category] = sorted(list(cids))
|
||||
return constraints
|
||||
|
||||
def x(self, train_instances):
|
||||
result = {}
|
||||
constraints = self._collect_constraints(train_instances)
|
||||
for (category, cids) in constraints.items():
|
||||
result[category] = []
|
||||
for instance in train_instances:
|
||||
for cid in cids:
|
||||
result[category].append(instance.get_constraint_features(cid))
|
||||
return result
|
||||
|
||||
def y(self, train_instances):
|
||||
result = {}
|
||||
constraints = self._collect_constraints(train_instances)
|
||||
for (category, cids) in constraints.items():
|
||||
result[category] = []
|
||||
for instance in train_instances:
|
||||
for cid in cids:
|
||||
if cid in instance.found_violated_lazy_constraints:
|
||||
result[category].append([0, 1])
|
||||
else:
|
||||
result[category].append([1, 0])
|
||||
return result</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-classes">Classes</h2>
|
||||
<dl>
|
||||
<dt id="miplearn.components.lazy_static.LazyConstraint"><code class="flex name class">
|
||||
<span>class <span class="ident">LazyConstraint</span></span>
|
||||
<span>(</span><span>cid, obj)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">class LazyConstraint:
|
||||
def __init__(self, cid, obj):
|
||||
self.cid = cid
|
||||
self.obj = obj</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.components.lazy_static.StaticLazyConstraintsComponent"><code class="flex name class">
|
||||
<span>class <span class="ident">StaticLazyConstraintsComponent</span></span>
|
||||
<span>(</span><span>classifier=CountingClassifier(mean=None), threshold=0.05, use_two_phase_gap=True, large_gap=0.01, violation_tolerance=-0.5)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"><p>A Component is an object which adds functionality to a LearningSolver.</p>
|
||||
<p>For better code maintainability, LearningSolver simply delegates most of its
|
||||
functionality to Components. Each Component is responsible for exactly one ML
|
||||
strategy.</p></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">class StaticLazyConstraintsComponent(Component):
|
||||
def __init__(
|
||||
self,
|
||||
classifier=CountingClassifier(),
|
||||
threshold=0.05,
|
||||
use_two_phase_gap=True,
|
||||
large_gap=1e-2,
|
||||
violation_tolerance=-0.5,
|
||||
):
|
||||
self.threshold = threshold
|
||||
self.classifier_prototype = classifier
|
||||
self.classifiers = {}
|
||||
self.pool = []
|
||||
self.original_gap = None
|
||||
self.large_gap = large_gap
|
||||
self.is_gap_large = False
|
||||
self.use_two_phase_gap = use_two_phase_gap
|
||||
self.violation_tolerance = violation_tolerance
|
||||
|
||||
def before_solve(self, solver, instance, model):
|
||||
self.pool = []
|
||||
if not solver.use_lazy_cb and self.use_two_phase_gap:
|
||||
logger.info("Increasing gap tolerance to %f", self.large_gap)
|
||||
self.original_gap = solver.gap_tolerance
|
||||
self.is_gap_large = True
|
||||
solver.internal_solver.set_gap_tolerance(self.large_gap)
|
||||
|
||||
instance.found_violated_lazy_constraints = []
|
||||
if instance.has_static_lazy_constraints():
|
||||
self._extract_and_predict_static(solver, instance)
|
||||
|
||||
def after_solve(
|
||||
self,
|
||||
solver,
|
||||
instance,
|
||||
model,
|
||||
stats,
|
||||
training_data,
|
||||
):
|
||||
pass
|
||||
|
||||
def iteration_cb(self, solver, instance, model):
|
||||
if solver.use_lazy_cb:
|
||||
return False
|
||||
else:
|
||||
should_repeat = self._check_and_add(instance, solver)
|
||||
if should_repeat:
|
||||
return True
|
||||
else:
|
||||
if self.is_gap_large:
|
||||
logger.info("Restoring gap tolerance to %f", self.original_gap)
|
||||
solver.internal_solver.set_gap_tolerance(self.original_gap)
|
||||
self.is_gap_large = False
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def lazy_cb(self, solver, instance, model):
|
||||
self._check_and_add(instance, solver)
|
||||
|
||||
def _check_and_add(self, instance, solver):
|
||||
logger.debug("Finding violated lazy constraints...")
|
||||
constraints_to_add = []
|
||||
for c in self.pool:
|
||||
if not solver.internal_solver.is_constraint_satisfied(
|
||||
c.obj, tol=self.violation_tolerance
|
||||
):
|
||||
constraints_to_add.append(c)
|
||||
for c in constraints_to_add:
|
||||
self.pool.remove(c)
|
||||
solver.internal_solver.add_constraint(c.obj)
|
||||
instance.found_violated_lazy_constraints += [c.cid]
|
||||
if len(constraints_to_add) > 0:
|
||||
logger.info(
|
||||
"%8d lazy constraints added %8d in the pool"
|
||||
% (len(constraints_to_add), len(self.pool))
|
||||
)
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def fit(self, training_instances):
|
||||
training_instances = [
|
||||
t
|
||||
for t in training_instances
|
||||
if hasattr(t, "found_violated_lazy_constraints")
|
||||
]
|
||||
|
||||
logger.debug("Extracting x and y...")
|
||||
x = self.x(training_instances)
|
||||
y = self.y(training_instances)
|
||||
|
||||
logger.debug("Fitting...")
|
||||
for category in tqdm(
|
||||
x.keys(), desc="Fit (lazy)", disable=not sys.stdout.isatty()
|
||||
):
|
||||
if category not in self.classifiers:
|
||||
self.classifiers[category] = deepcopy(self.classifier_prototype)
|
||||
self.classifiers[category].fit(x[category], y[category])
|
||||
|
||||
def predict(self, instance):
|
||||
pass
|
||||
|
||||
def evaluate(self, instances):
|
||||
pass
|
||||
|
||||
def _extract_and_predict_static(self, solver, instance):
|
||||
x = {}
|
||||
constraints = {}
|
||||
logger.info("Extracting lazy constraints...")
|
||||
for cid in solver.internal_solver.get_constraint_ids():
|
||||
if instance.is_constraint_lazy(cid):
|
||||
category = instance.get_constraint_category(cid)
|
||||
if category not in x:
|
||||
x[category] = []
|
||||
constraints[category] = []
|
||||
x[category] += [instance.get_constraint_features(cid)]
|
||||
c = LazyConstraint(
|
||||
cid=cid,
|
||||
obj=solver.internal_solver.extract_constraint(cid),
|
||||
)
|
||||
constraints[category] += [c]
|
||||
self.pool.append(c)
|
||||
logger.info("%8d lazy constraints extracted" % len(self.pool))
|
||||
logger.info("Predicting required lazy constraints...")
|
||||
n_added = 0
|
||||
for (category, x_values) in x.items():
|
||||
if category not in self.classifiers:
|
||||
continue
|
||||
if isinstance(x_values[0], np.ndarray):
|
||||
x[category] = np.array(x_values)
|
||||
proba = self.classifiers[category].predict_proba(x[category])
|
||||
for i in range(len(proba)):
|
||||
if proba[i][1] > self.threshold:
|
||||
n_added += 1
|
||||
c = constraints[category][i]
|
||||
self.pool.remove(c)
|
||||
solver.internal_solver.add_constraint(c.obj)
|
||||
instance.found_violated_lazy_constraints += [c.cid]
|
||||
logger.info(
|
||||
"%8d lazy constraints added %8d in the pool"
|
||||
% (
|
||||
n_added,
|
||||
len(self.pool),
|
||||
)
|
||||
)
|
||||
|
||||
def _collect_constraints(self, train_instances):
|
||||
constraints = {}
|
||||
for instance in train_instances:
|
||||
for cid in instance.found_violated_lazy_constraints:
|
||||
category = instance.get_constraint_category(cid)
|
||||
if category not in constraints:
|
||||
constraints[category] = set()
|
||||
constraints[category].add(cid)
|
||||
for (category, cids) in constraints.items():
|
||||
constraints[category] = sorted(list(cids))
|
||||
return constraints
|
||||
|
||||
def x(self, train_instances):
|
||||
result = {}
|
||||
constraints = self._collect_constraints(train_instances)
|
||||
for (category, cids) in constraints.items():
|
||||
result[category] = []
|
||||
for instance in train_instances:
|
||||
for cid in cids:
|
||||
result[category].append(instance.get_constraint_features(cid))
|
||||
return result
|
||||
|
||||
def y(self, train_instances):
|
||||
result = {}
|
||||
constraints = self._collect_constraints(train_instances)
|
||||
for (category, cids) in constraints.items():
|
||||
result[category] = []
|
||||
for instance in train_instances:
|
||||
for cid in cids:
|
||||
if cid in instance.found_violated_lazy_constraints:
|
||||
result[category].append([0, 1])
|
||||
else:
|
||||
result[category].append([1, 0])
|
||||
return result</code></pre>
|
||||
</details>
|
||||
<h3>Ancestors</h3>
|
||||
<ul class="hlist">
|
||||
<li><a title="miplearn.components.component.Component" href="component.html#miplearn.components.component.Component">Component</a></li>
|
||||
<li>abc.ABC</li>
|
||||
</ul>
|
||||
<h3>Methods</h3>
|
||||
<dl>
|
||||
<dt id="miplearn.components.lazy_static.StaticLazyConstraintsComponent.evaluate"><code class="name flex">
|
||||
<span>def <span class="ident">evaluate</span></span>(<span>self, instances)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def evaluate(self, instances):
|
||||
pass</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.components.lazy_static.StaticLazyConstraintsComponent.fit"><code class="name flex">
|
||||
<span>def <span class="ident">fit</span></span>(<span>self, training_instances)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def fit(self, training_instances):
|
||||
training_instances = [
|
||||
t
|
||||
for t in training_instances
|
||||
if hasattr(t, "found_violated_lazy_constraints")
|
||||
]
|
||||
|
||||
logger.debug("Extracting x and y...")
|
||||
x = self.x(training_instances)
|
||||
y = self.y(training_instances)
|
||||
|
||||
logger.debug("Fitting...")
|
||||
for category in tqdm(
|
||||
x.keys(), desc="Fit (lazy)", disable=not sys.stdout.isatty()
|
||||
):
|
||||
if category not in self.classifiers:
|
||||
self.classifiers[category] = deepcopy(self.classifier_prototype)
|
||||
self.classifiers[category].fit(x[category], y[category])</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.components.lazy_static.StaticLazyConstraintsComponent.lazy_cb"><code class="name flex">
|
||||
<span>def <span class="ident">lazy_cb</span></span>(<span>self, solver, instance, model)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def lazy_cb(self, solver, instance, model):
|
||||
self._check_and_add(instance, solver)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.components.lazy_static.StaticLazyConstraintsComponent.predict"><code class="name flex">
|
||||
<span>def <span class="ident">predict</span></span>(<span>self, instance)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def predict(self, instance):
|
||||
pass</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.components.lazy_static.StaticLazyConstraintsComponent.x"><code class="name flex">
|
||||
<span>def <span class="ident">x</span></span>(<span>self, train_instances)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def x(self, train_instances):
|
||||
result = {}
|
||||
constraints = self._collect_constraints(train_instances)
|
||||
for (category, cids) in constraints.items():
|
||||
result[category] = []
|
||||
for instance in train_instances:
|
||||
for cid in cids:
|
||||
result[category].append(instance.get_constraint_features(cid))
|
||||
return result</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.components.lazy_static.StaticLazyConstraintsComponent.y"><code class="name flex">
|
||||
<span>def <span class="ident">y</span></span>(<span>self, train_instances)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def y(self, train_instances):
|
||||
result = {}
|
||||
constraints = self._collect_constraints(train_instances)
|
||||
for (category, cids) in constraints.items():
|
||||
result[category] = []
|
||||
for instance in train_instances:
|
||||
for cid in cids:
|
||||
if cid in instance.found_violated_lazy_constraints:
|
||||
result[category].append([0, 1])
|
||||
else:
|
||||
result[category].append([1, 0])
|
||||
return result</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>Inherited members</h3>
|
||||
<ul class="hlist">
|
||||
<li><code><b><a title="miplearn.components.component.Component" href="component.html#miplearn.components.component.Component">Component</a></b></code>:
|
||||
<ul class="hlist">
|
||||
<li><code><a title="miplearn.components.component.Component.after_solve" href="component.html#miplearn.components.component.Component.after_solve">after_solve</a></code></li>
|
||||
<li><code><a title="miplearn.components.component.Component.before_solve" href="component.html#miplearn.components.component.Component.before_solve">before_solve</a></code></li>
|
||||
<li><code><a title="miplearn.components.component.Component.iteration_cb" href="component.html#miplearn.components.component.Component.iteration_cb">iteration_cb</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.components" href="index.html">miplearn.components</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-classes">Classes</a></h3>
|
||||
<ul>
|
||||
<li>
|
||||
<h4><code><a title="miplearn.components.lazy_static.LazyConstraint" href="#miplearn.components.lazy_static.LazyConstraint">LazyConstraint</a></code></h4>
|
||||
</li>
|
||||
<li>
|
||||
<h4><code><a title="miplearn.components.lazy_static.StaticLazyConstraintsComponent" href="#miplearn.components.lazy_static.StaticLazyConstraintsComponent">StaticLazyConstraintsComponent</a></code></h4>
|
||||
<ul class="two-column">
|
||||
<li><code><a title="miplearn.components.lazy_static.StaticLazyConstraintsComponent.evaluate" href="#miplearn.components.lazy_static.StaticLazyConstraintsComponent.evaluate">evaluate</a></code></li>
|
||||
<li><code><a title="miplearn.components.lazy_static.StaticLazyConstraintsComponent.fit" href="#miplearn.components.lazy_static.StaticLazyConstraintsComponent.fit">fit</a></code></li>
|
||||
<li><code><a title="miplearn.components.lazy_static.StaticLazyConstraintsComponent.lazy_cb" href="#miplearn.components.lazy_static.StaticLazyConstraintsComponent.lazy_cb">lazy_cb</a></code></li>
|
||||
<li><code><a title="miplearn.components.lazy_static.StaticLazyConstraintsComponent.predict" href="#miplearn.components.lazy_static.StaticLazyConstraintsComponent.predict">predict</a></code></li>
|
||||
<li><code><a title="miplearn.components.lazy_static.StaticLazyConstraintsComponent.x" href="#miplearn.components.lazy_static.StaticLazyConstraintsComponent.x">x</a></code></li>
|
||||
<li><code><a title="miplearn.components.lazy_static.StaticLazyConstraintsComponent.y" href="#miplearn.components.lazy_static.StaticLazyConstraintsComponent.y">y</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</main>
|
||||
<footer id="footer">
|
||||
<p>Generated by <a href="https://pdoc3.github.io/pdoc"><cite>pdoc</cite> 0.7.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>
|
||||
392
0.2/api/miplearn/components/objective.html
Normal file
392
0.2/api/miplearn/components/objective.html
Normal file
@@ -0,0 +1,392 @@
|
||||
<!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.components.objective 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.components.objective</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 copy import deepcopy
|
||||
|
||||
import numpy as np
|
||||
from sklearn.linear_model import LinearRegression
|
||||
from sklearn.metrics import (
|
||||
mean_squared_error,
|
||||
explained_variance_score,
|
||||
max_error,
|
||||
mean_absolute_error,
|
||||
r2_score,
|
||||
)
|
||||
|
||||
from miplearn.classifiers import Regressor
|
||||
from miplearn.components.component import Component
|
||||
from miplearn.extractors import InstanceFeaturesExtractor, ObjectiveValueExtractor
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ObjectiveValueComponent(Component):
|
||||
"""
|
||||
A Component which predicts the optimal objective value of the problem.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
regressor: Regressor = LinearRegression(),
|
||||
) -> None:
|
||||
self.ub_regressor = None
|
||||
self.lb_regressor = None
|
||||
self.regressor_prototype = regressor
|
||||
|
||||
def before_solve(self, solver, instance, model):
|
||||
if self.ub_regressor is not None:
|
||||
logger.info("Predicting optimal value...")
|
||||
lb, ub = self.predict([instance])[0]
|
||||
instance.predicted_ub = ub
|
||||
instance.predicted_lb = lb
|
||||
logger.info("Predicted values: lb=%.2f, ub=%.2f" % (lb, ub))
|
||||
|
||||
def after_solve(
|
||||
self,
|
||||
solver,
|
||||
instance,
|
||||
model,
|
||||
stats,
|
||||
training_data,
|
||||
):
|
||||
if self.ub_regressor is not None:
|
||||
stats["Predicted UB"] = instance.predicted_ub
|
||||
stats["Predicted LB"] = instance.predicted_lb
|
||||
else:
|
||||
stats["Predicted UB"] = None
|
||||
stats["Predicted LB"] = None
|
||||
|
||||
def fit(self, training_instances):
|
||||
logger.debug("Extracting features...")
|
||||
features = InstanceFeaturesExtractor().extract(training_instances)
|
||||
ub = ObjectiveValueExtractor(kind="upper bound").extract(training_instances)
|
||||
lb = ObjectiveValueExtractor(kind="lower bound").extract(training_instances)
|
||||
assert ub.shape == (len(training_instances), 1)
|
||||
assert lb.shape == (len(training_instances), 1)
|
||||
self.ub_regressor = deepcopy(self.regressor_prototype)
|
||||
self.lb_regressor = deepcopy(self.regressor_prototype)
|
||||
logger.debug("Fitting ub_regressor...")
|
||||
self.ub_regressor.fit(features, ub.ravel())
|
||||
logger.debug("Fitting ub_regressor...")
|
||||
self.lb_regressor.fit(features, lb.ravel())
|
||||
|
||||
def predict(self, instances):
|
||||
features = InstanceFeaturesExtractor().extract(instances)
|
||||
lb = self.lb_regressor.predict(features)
|
||||
ub = self.ub_regressor.predict(features)
|
||||
assert lb.shape == (len(instances),)
|
||||
assert ub.shape == (len(instances),)
|
||||
return np.array([lb, ub]).T
|
||||
|
||||
def evaluate(self, instances):
|
||||
y_pred = self.predict(instances)
|
||||
y_true = np.array(
|
||||
[
|
||||
[
|
||||
inst.training_data[0]["Lower bound"],
|
||||
inst.training_data[0]["Upper bound"],
|
||||
]
|
||||
for inst in instances
|
||||
]
|
||||
)
|
||||
y_true_lb, y_true_ub = y_true[:, 0], y_true[:, 1]
|
||||
y_pred_lb, y_pred_ub = y_pred[:, 1], y_pred[:, 1]
|
||||
ev = {
|
||||
"Lower bound": {
|
||||
"Mean squared error": mean_squared_error(y_true_lb, y_pred_lb),
|
||||
"Explained variance": explained_variance_score(y_true_lb, y_pred_lb),
|
||||
"Max error": max_error(y_true_lb, y_pred_lb),
|
||||
"Mean absolute error": mean_absolute_error(y_true_lb, y_pred_lb),
|
||||
"R2": r2_score(y_true_lb, y_pred_lb),
|
||||
"Median absolute error": mean_absolute_error(y_true_lb, y_pred_lb),
|
||||
},
|
||||
"Upper bound": {
|
||||
"Mean squared error": mean_squared_error(y_true_ub, y_pred_ub),
|
||||
"Explained variance": explained_variance_score(y_true_ub, y_pred_ub),
|
||||
"Max error": max_error(y_true_ub, y_pred_ub),
|
||||
"Mean absolute error": mean_absolute_error(y_true_ub, y_pred_ub),
|
||||
"R2": r2_score(y_true_ub, y_pred_ub),
|
||||
"Median absolute error": mean_absolute_error(y_true_ub, y_pred_ub),
|
||||
},
|
||||
}
|
||||
return ev</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-classes">Classes</h2>
|
||||
<dl>
|
||||
<dt id="miplearn.components.objective.ObjectiveValueComponent"><code class="flex name class">
|
||||
<span>class <span class="ident">ObjectiveValueComponent</span></span>
|
||||
<span>(</span><span>regressor=LinearRegression())</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"><p>A Component which predicts the optimal objective value of the problem.</p></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">class ObjectiveValueComponent(Component):
|
||||
"""
|
||||
A Component which predicts the optimal objective value of the problem.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
regressor: Regressor = LinearRegression(),
|
||||
) -> None:
|
||||
self.ub_regressor = None
|
||||
self.lb_regressor = None
|
||||
self.regressor_prototype = regressor
|
||||
|
||||
def before_solve(self, solver, instance, model):
|
||||
if self.ub_regressor is not None:
|
||||
logger.info("Predicting optimal value...")
|
||||
lb, ub = self.predict([instance])[0]
|
||||
instance.predicted_ub = ub
|
||||
instance.predicted_lb = lb
|
||||
logger.info("Predicted values: lb=%.2f, ub=%.2f" % (lb, ub))
|
||||
|
||||
def after_solve(
|
||||
self,
|
||||
solver,
|
||||
instance,
|
||||
model,
|
||||
stats,
|
||||
training_data,
|
||||
):
|
||||
if self.ub_regressor is not None:
|
||||
stats["Predicted UB"] = instance.predicted_ub
|
||||
stats["Predicted LB"] = instance.predicted_lb
|
||||
else:
|
||||
stats["Predicted UB"] = None
|
||||
stats["Predicted LB"] = None
|
||||
|
||||
def fit(self, training_instances):
|
||||
logger.debug("Extracting features...")
|
||||
features = InstanceFeaturesExtractor().extract(training_instances)
|
||||
ub = ObjectiveValueExtractor(kind="upper bound").extract(training_instances)
|
||||
lb = ObjectiveValueExtractor(kind="lower bound").extract(training_instances)
|
||||
assert ub.shape == (len(training_instances), 1)
|
||||
assert lb.shape == (len(training_instances), 1)
|
||||
self.ub_regressor = deepcopy(self.regressor_prototype)
|
||||
self.lb_regressor = deepcopy(self.regressor_prototype)
|
||||
logger.debug("Fitting ub_regressor...")
|
||||
self.ub_regressor.fit(features, ub.ravel())
|
||||
logger.debug("Fitting ub_regressor...")
|
||||
self.lb_regressor.fit(features, lb.ravel())
|
||||
|
||||
def predict(self, instances):
|
||||
features = InstanceFeaturesExtractor().extract(instances)
|
||||
lb = self.lb_regressor.predict(features)
|
||||
ub = self.ub_regressor.predict(features)
|
||||
assert lb.shape == (len(instances),)
|
||||
assert ub.shape == (len(instances),)
|
||||
return np.array([lb, ub]).T
|
||||
|
||||
def evaluate(self, instances):
|
||||
y_pred = self.predict(instances)
|
||||
y_true = np.array(
|
||||
[
|
||||
[
|
||||
inst.training_data[0]["Lower bound"],
|
||||
inst.training_data[0]["Upper bound"],
|
||||
]
|
||||
for inst in instances
|
||||
]
|
||||
)
|
||||
y_true_lb, y_true_ub = y_true[:, 0], y_true[:, 1]
|
||||
y_pred_lb, y_pred_ub = y_pred[:, 1], y_pred[:, 1]
|
||||
ev = {
|
||||
"Lower bound": {
|
||||
"Mean squared error": mean_squared_error(y_true_lb, y_pred_lb),
|
||||
"Explained variance": explained_variance_score(y_true_lb, y_pred_lb),
|
||||
"Max error": max_error(y_true_lb, y_pred_lb),
|
||||
"Mean absolute error": mean_absolute_error(y_true_lb, y_pred_lb),
|
||||
"R2": r2_score(y_true_lb, y_pred_lb),
|
||||
"Median absolute error": mean_absolute_error(y_true_lb, y_pred_lb),
|
||||
},
|
||||
"Upper bound": {
|
||||
"Mean squared error": mean_squared_error(y_true_ub, y_pred_ub),
|
||||
"Explained variance": explained_variance_score(y_true_ub, y_pred_ub),
|
||||
"Max error": max_error(y_true_ub, y_pred_ub),
|
||||
"Mean absolute error": mean_absolute_error(y_true_ub, y_pred_ub),
|
||||
"R2": r2_score(y_true_ub, y_pred_ub),
|
||||
"Median absolute error": mean_absolute_error(y_true_ub, y_pred_ub),
|
||||
},
|
||||
}
|
||||
return ev</code></pre>
|
||||
</details>
|
||||
<h3>Ancestors</h3>
|
||||
<ul class="hlist">
|
||||
<li><a title="miplearn.components.component.Component" href="component.html#miplearn.components.component.Component">Component</a></li>
|
||||
<li>abc.ABC</li>
|
||||
</ul>
|
||||
<h3>Methods</h3>
|
||||
<dl>
|
||||
<dt id="miplearn.components.objective.ObjectiveValueComponent.evaluate"><code class="name flex">
|
||||
<span>def <span class="ident">evaluate</span></span>(<span>self, instances)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def evaluate(self, instances):
|
||||
y_pred = self.predict(instances)
|
||||
y_true = np.array(
|
||||
[
|
||||
[
|
||||
inst.training_data[0]["Lower bound"],
|
||||
inst.training_data[0]["Upper bound"],
|
||||
]
|
||||
for inst in instances
|
||||
]
|
||||
)
|
||||
y_true_lb, y_true_ub = y_true[:, 0], y_true[:, 1]
|
||||
y_pred_lb, y_pred_ub = y_pred[:, 1], y_pred[:, 1]
|
||||
ev = {
|
||||
"Lower bound": {
|
||||
"Mean squared error": mean_squared_error(y_true_lb, y_pred_lb),
|
||||
"Explained variance": explained_variance_score(y_true_lb, y_pred_lb),
|
||||
"Max error": max_error(y_true_lb, y_pred_lb),
|
||||
"Mean absolute error": mean_absolute_error(y_true_lb, y_pred_lb),
|
||||
"R2": r2_score(y_true_lb, y_pred_lb),
|
||||
"Median absolute error": mean_absolute_error(y_true_lb, y_pred_lb),
|
||||
},
|
||||
"Upper bound": {
|
||||
"Mean squared error": mean_squared_error(y_true_ub, y_pred_ub),
|
||||
"Explained variance": explained_variance_score(y_true_ub, y_pred_ub),
|
||||
"Max error": max_error(y_true_ub, y_pred_ub),
|
||||
"Mean absolute error": mean_absolute_error(y_true_ub, y_pred_ub),
|
||||
"R2": r2_score(y_true_ub, y_pred_ub),
|
||||
"Median absolute error": mean_absolute_error(y_true_ub, y_pred_ub),
|
||||
},
|
||||
}
|
||||
return ev</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.components.objective.ObjectiveValueComponent.fit"><code class="name flex">
|
||||
<span>def <span class="ident">fit</span></span>(<span>self, training_instances)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def fit(self, training_instances):
|
||||
logger.debug("Extracting features...")
|
||||
features = InstanceFeaturesExtractor().extract(training_instances)
|
||||
ub = ObjectiveValueExtractor(kind="upper bound").extract(training_instances)
|
||||
lb = ObjectiveValueExtractor(kind="lower bound").extract(training_instances)
|
||||
assert ub.shape == (len(training_instances), 1)
|
||||
assert lb.shape == (len(training_instances), 1)
|
||||
self.ub_regressor = deepcopy(self.regressor_prototype)
|
||||
self.lb_regressor = deepcopy(self.regressor_prototype)
|
||||
logger.debug("Fitting ub_regressor...")
|
||||
self.ub_regressor.fit(features, ub.ravel())
|
||||
logger.debug("Fitting ub_regressor...")
|
||||
self.lb_regressor.fit(features, lb.ravel())</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.components.objective.ObjectiveValueComponent.predict"><code class="name flex">
|
||||
<span>def <span class="ident">predict</span></span>(<span>self, instances)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def predict(self, instances):
|
||||
features = InstanceFeaturesExtractor().extract(instances)
|
||||
lb = self.lb_regressor.predict(features)
|
||||
ub = self.ub_regressor.predict(features)
|
||||
assert lb.shape == (len(instances),)
|
||||
assert ub.shape == (len(instances),)
|
||||
return np.array([lb, ub]).T</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>Inherited members</h3>
|
||||
<ul class="hlist">
|
||||
<li><code><b><a title="miplearn.components.component.Component" href="component.html#miplearn.components.component.Component">Component</a></b></code>:
|
||||
<ul class="hlist">
|
||||
<li><code><a title="miplearn.components.component.Component.after_solve" href="component.html#miplearn.components.component.Component.after_solve">after_solve</a></code></li>
|
||||
<li><code><a title="miplearn.components.component.Component.before_solve" href="component.html#miplearn.components.component.Component.before_solve">before_solve</a></code></li>
|
||||
<li><code><a title="miplearn.components.component.Component.iteration_cb" href="component.html#miplearn.components.component.Component.iteration_cb">iteration_cb</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.components" href="index.html">miplearn.components</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-classes">Classes</a></h3>
|
||||
<ul>
|
||||
<li>
|
||||
<h4><code><a title="miplearn.components.objective.ObjectiveValueComponent" href="#miplearn.components.objective.ObjectiveValueComponent">ObjectiveValueComponent</a></code></h4>
|
||||
<ul class="">
|
||||
<li><code><a title="miplearn.components.objective.ObjectiveValueComponent.evaluate" href="#miplearn.components.objective.ObjectiveValueComponent.evaluate">evaluate</a></code></li>
|
||||
<li><code><a title="miplearn.components.objective.ObjectiveValueComponent.fit" href="#miplearn.components.objective.ObjectiveValueComponent.fit">fit</a></code></li>
|
||||
<li><code><a title="miplearn.components.objective.ObjectiveValueComponent.predict" href="#miplearn.components.objective.ObjectiveValueComponent.predict">predict</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</main>
|
||||
<footer id="footer">
|
||||
<p>Generated by <a href="https://pdoc3.github.io/pdoc"><cite>pdoc</cite> 0.7.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>
|
||||
610
0.2/api/miplearn/components/primal.html
Normal file
610
0.2/api/miplearn/components/primal.html
Normal file
@@ -0,0 +1,610 @@
|
||||
<!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.components.primal 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.components.primal</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 copy import deepcopy
|
||||
from typing import Union, Dict, Any
|
||||
|
||||
import numpy as np
|
||||
from tqdm.auto import tqdm
|
||||
|
||||
from miplearn.classifiers import Classifier
|
||||
from miplearn.classifiers.adaptive import AdaptiveClassifier
|
||||
from miplearn.classifiers.threshold import MinPrecisionThreshold, DynamicThreshold
|
||||
from miplearn.components import classifier_evaluation_dict
|
||||
from miplearn.components.component import Component
|
||||
from miplearn.extractors import VariableFeaturesExtractor, SolutionExtractor, Extractor
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class PrimalSolutionComponent(Component):
|
||||
"""
|
||||
A component that predicts primal solutions.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
classifier: Classifier = AdaptiveClassifier(),
|
||||
mode: str = "exact",
|
||||
threshold: Union[float, DynamicThreshold] = MinPrecisionThreshold(0.98),
|
||||
) -> None:
|
||||
self.mode = mode
|
||||
self.classifiers: Dict[Any, Classifier] = {}
|
||||
self.thresholds: Dict[Any, Union[float, DynamicThreshold]] = {}
|
||||
self.threshold_prototype = threshold
|
||||
self.classifier_prototype = classifier
|
||||
|
||||
def before_solve(self, solver, instance, model):
|
||||
logger.info("Predicting primal solution...")
|
||||
solution = self.predict(instance)
|
||||
if self.mode == "heuristic":
|
||||
solver.internal_solver.fix(solution)
|
||||
else:
|
||||
solver.internal_solver.set_warm_start(solution)
|
||||
|
||||
def after_solve(
|
||||
self,
|
||||
solver,
|
||||
instance,
|
||||
model,
|
||||
stats,
|
||||
training_data,
|
||||
):
|
||||
pass
|
||||
|
||||
def x(self, training_instances):
|
||||
return VariableFeaturesExtractor().extract(training_instances)
|
||||
|
||||
def y(self, training_instances):
|
||||
return SolutionExtractor().extract(training_instances)
|
||||
|
||||
def fit(self, training_instances, n_jobs=1):
|
||||
logger.debug("Extracting features...")
|
||||
features = VariableFeaturesExtractor().extract(training_instances)
|
||||
solutions = SolutionExtractor().extract(training_instances)
|
||||
|
||||
for category in tqdm(
|
||||
features.keys(),
|
||||
desc="Fit (primal)",
|
||||
):
|
||||
x_train = features[category]
|
||||
for label in [0, 1]:
|
||||
y_train = solutions[category][:, label].astype(int)
|
||||
|
||||
# If all samples are either positive or negative, make constant
|
||||
# predictions
|
||||
y_avg = np.average(y_train)
|
||||
if y_avg < 0.001 or y_avg >= 0.999:
|
||||
self.classifiers[category, label] = round(y_avg)
|
||||
self.thresholds[category, label] = 0.50
|
||||
continue
|
||||
|
||||
# Create a copy of classifier prototype and train it
|
||||
if isinstance(self.classifier_prototype, list):
|
||||
clf = deepcopy(self.classifier_prototype[label])
|
||||
else:
|
||||
clf = deepcopy(self.classifier_prototype)
|
||||
clf.fit(x_train, y_train)
|
||||
|
||||
# Find threshold (dynamic or static)
|
||||
if isinstance(self.threshold_prototype, DynamicThreshold):
|
||||
self.thresholds[category, label] = self.threshold_prototype.find(
|
||||
clf,
|
||||
x_train,
|
||||
y_train,
|
||||
)
|
||||
else:
|
||||
self.thresholds[category, label] = deepcopy(
|
||||
self.threshold_prototype
|
||||
)
|
||||
|
||||
self.classifiers[category, label] = clf
|
||||
|
||||
def predict(self, instance):
|
||||
solution = {}
|
||||
x_test = VariableFeaturesExtractor().extract([instance])
|
||||
var_split = Extractor.split_variables(instance)
|
||||
for category in var_split.keys():
|
||||
n = len(var_split[category])
|
||||
for (i, (var, index)) in enumerate(var_split[category]):
|
||||
if var not in solution.keys():
|
||||
solution[var] = {}
|
||||
solution[var][index] = None
|
||||
for label in [0, 1]:
|
||||
if (category, label) not in self.classifiers.keys():
|
||||
continue
|
||||
clf = self.classifiers[category, label]
|
||||
if isinstance(clf, float) or isinstance(clf, int):
|
||||
ws = np.array([[1 - clf, clf] for _ in range(n)])
|
||||
else:
|
||||
ws = clf.predict_proba(x_test[category])
|
||||
assert ws.shape == (n, 2), "ws.shape should be (%d, 2) not %s" % (
|
||||
n,
|
||||
ws.shape,
|
||||
)
|
||||
for (i, (var, index)) in enumerate(var_split[category]):
|
||||
if ws[i, 1] >= self.thresholds[category, label]:
|
||||
solution[var][index] = label
|
||||
return solution
|
||||
|
||||
def evaluate(self, instances):
|
||||
ev = {"Fix zero": {}, "Fix one": {}}
|
||||
for instance_idx in tqdm(
|
||||
range(len(instances)),
|
||||
desc="Evaluate (primal)",
|
||||
):
|
||||
instance = instances[instance_idx]
|
||||
solution_actual = instance.training_data[0]["Solution"]
|
||||
solution_pred = self.predict(instance)
|
||||
|
||||
vars_all, vars_one, vars_zero = set(), set(), set()
|
||||
pred_one_positive, pred_zero_positive = set(), set()
|
||||
for (varname, var_dict) in solution_actual.items():
|
||||
if varname not in solution_pred.keys():
|
||||
continue
|
||||
for (idx, value) in var_dict.items():
|
||||
vars_all.add((varname, idx))
|
||||
if value > 0.5:
|
||||
vars_one.add((varname, idx))
|
||||
else:
|
||||
vars_zero.add((varname, idx))
|
||||
if solution_pred[varname][idx] is not None:
|
||||
if solution_pred[varname][idx] > 0.5:
|
||||
pred_one_positive.add((varname, idx))
|
||||
else:
|
||||
pred_zero_positive.add((varname, idx))
|
||||
pred_one_negative = vars_all - pred_one_positive
|
||||
pred_zero_negative = vars_all - pred_zero_positive
|
||||
|
||||
tp_zero = len(pred_zero_positive & vars_zero)
|
||||
fp_zero = len(pred_zero_positive & vars_one)
|
||||
tn_zero = len(pred_zero_negative & vars_one)
|
||||
fn_zero = len(pred_zero_negative & vars_zero)
|
||||
|
||||
tp_one = len(pred_one_positive & vars_one)
|
||||
fp_one = len(pred_one_positive & vars_zero)
|
||||
tn_one = len(pred_one_negative & vars_zero)
|
||||
fn_one = len(pred_one_negative & vars_one)
|
||||
|
||||
ev["Fix zero"][instance_idx] = classifier_evaluation_dict(
|
||||
tp_zero, tn_zero, fp_zero, fn_zero
|
||||
)
|
||||
ev["Fix one"][instance_idx] = classifier_evaluation_dict(
|
||||
tp_one, tn_one, fp_one, fn_one
|
||||
)
|
||||
return ev</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-classes">Classes</h2>
|
||||
<dl>
|
||||
<dt id="miplearn.components.primal.PrimalSolutionComponent"><code class="flex name class">
|
||||
<span>class <span class="ident">PrimalSolutionComponent</span></span>
|
||||
<span>(</span><span>classifier=<miplearn.classifiers.adaptive.AdaptiveClassifier object>, mode='exact', threshold=<miplearn.classifiers.threshold.MinPrecisionThreshold object>)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"><p>A component that predicts primal solutions.</p></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">class PrimalSolutionComponent(Component):
|
||||
"""
|
||||
A component that predicts primal solutions.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
classifier: Classifier = AdaptiveClassifier(),
|
||||
mode: str = "exact",
|
||||
threshold: Union[float, DynamicThreshold] = MinPrecisionThreshold(0.98),
|
||||
) -> None:
|
||||
self.mode = mode
|
||||
self.classifiers: Dict[Any, Classifier] = {}
|
||||
self.thresholds: Dict[Any, Union[float, DynamicThreshold]] = {}
|
||||
self.threshold_prototype = threshold
|
||||
self.classifier_prototype = classifier
|
||||
|
||||
def before_solve(self, solver, instance, model):
|
||||
logger.info("Predicting primal solution...")
|
||||
solution = self.predict(instance)
|
||||
if self.mode == "heuristic":
|
||||
solver.internal_solver.fix(solution)
|
||||
else:
|
||||
solver.internal_solver.set_warm_start(solution)
|
||||
|
||||
def after_solve(
|
||||
self,
|
||||
solver,
|
||||
instance,
|
||||
model,
|
||||
stats,
|
||||
training_data,
|
||||
):
|
||||
pass
|
||||
|
||||
def x(self, training_instances):
|
||||
return VariableFeaturesExtractor().extract(training_instances)
|
||||
|
||||
def y(self, training_instances):
|
||||
return SolutionExtractor().extract(training_instances)
|
||||
|
||||
def fit(self, training_instances, n_jobs=1):
|
||||
logger.debug("Extracting features...")
|
||||
features = VariableFeaturesExtractor().extract(training_instances)
|
||||
solutions = SolutionExtractor().extract(training_instances)
|
||||
|
||||
for category in tqdm(
|
||||
features.keys(),
|
||||
desc="Fit (primal)",
|
||||
):
|
||||
x_train = features[category]
|
||||
for label in [0, 1]:
|
||||
y_train = solutions[category][:, label].astype(int)
|
||||
|
||||
# If all samples are either positive or negative, make constant
|
||||
# predictions
|
||||
y_avg = np.average(y_train)
|
||||
if y_avg < 0.001 or y_avg >= 0.999:
|
||||
self.classifiers[category, label] = round(y_avg)
|
||||
self.thresholds[category, label] = 0.50
|
||||
continue
|
||||
|
||||
# Create a copy of classifier prototype and train it
|
||||
if isinstance(self.classifier_prototype, list):
|
||||
clf = deepcopy(self.classifier_prototype[label])
|
||||
else:
|
||||
clf = deepcopy(self.classifier_prototype)
|
||||
clf.fit(x_train, y_train)
|
||||
|
||||
# Find threshold (dynamic or static)
|
||||
if isinstance(self.threshold_prototype, DynamicThreshold):
|
||||
self.thresholds[category, label] = self.threshold_prototype.find(
|
||||
clf,
|
||||
x_train,
|
||||
y_train,
|
||||
)
|
||||
else:
|
||||
self.thresholds[category, label] = deepcopy(
|
||||
self.threshold_prototype
|
||||
)
|
||||
|
||||
self.classifiers[category, label] = clf
|
||||
|
||||
def predict(self, instance):
|
||||
solution = {}
|
||||
x_test = VariableFeaturesExtractor().extract([instance])
|
||||
var_split = Extractor.split_variables(instance)
|
||||
for category in var_split.keys():
|
||||
n = len(var_split[category])
|
||||
for (i, (var, index)) in enumerate(var_split[category]):
|
||||
if var not in solution.keys():
|
||||
solution[var] = {}
|
||||
solution[var][index] = None
|
||||
for label in [0, 1]:
|
||||
if (category, label) not in self.classifiers.keys():
|
||||
continue
|
||||
clf = self.classifiers[category, label]
|
||||
if isinstance(clf, float) or isinstance(clf, int):
|
||||
ws = np.array([[1 - clf, clf] for _ in range(n)])
|
||||
else:
|
||||
ws = clf.predict_proba(x_test[category])
|
||||
assert ws.shape == (n, 2), "ws.shape should be (%d, 2) not %s" % (
|
||||
n,
|
||||
ws.shape,
|
||||
)
|
||||
for (i, (var, index)) in enumerate(var_split[category]):
|
||||
if ws[i, 1] >= self.thresholds[category, label]:
|
||||
solution[var][index] = label
|
||||
return solution
|
||||
|
||||
def evaluate(self, instances):
|
||||
ev = {"Fix zero": {}, "Fix one": {}}
|
||||
for instance_idx in tqdm(
|
||||
range(len(instances)),
|
||||
desc="Evaluate (primal)",
|
||||
):
|
||||
instance = instances[instance_idx]
|
||||
solution_actual = instance.training_data[0]["Solution"]
|
||||
solution_pred = self.predict(instance)
|
||||
|
||||
vars_all, vars_one, vars_zero = set(), set(), set()
|
||||
pred_one_positive, pred_zero_positive = set(), set()
|
||||
for (varname, var_dict) in solution_actual.items():
|
||||
if varname not in solution_pred.keys():
|
||||
continue
|
||||
for (idx, value) in var_dict.items():
|
||||
vars_all.add((varname, idx))
|
||||
if value > 0.5:
|
||||
vars_one.add((varname, idx))
|
||||
else:
|
||||
vars_zero.add((varname, idx))
|
||||
if solution_pred[varname][idx] is not None:
|
||||
if solution_pred[varname][idx] > 0.5:
|
||||
pred_one_positive.add((varname, idx))
|
||||
else:
|
||||
pred_zero_positive.add((varname, idx))
|
||||
pred_one_negative = vars_all - pred_one_positive
|
||||
pred_zero_negative = vars_all - pred_zero_positive
|
||||
|
||||
tp_zero = len(pred_zero_positive & vars_zero)
|
||||
fp_zero = len(pred_zero_positive & vars_one)
|
||||
tn_zero = len(pred_zero_negative & vars_one)
|
||||
fn_zero = len(pred_zero_negative & vars_zero)
|
||||
|
||||
tp_one = len(pred_one_positive & vars_one)
|
||||
fp_one = len(pred_one_positive & vars_zero)
|
||||
tn_one = len(pred_one_negative & vars_zero)
|
||||
fn_one = len(pred_one_negative & vars_one)
|
||||
|
||||
ev["Fix zero"][instance_idx] = classifier_evaluation_dict(
|
||||
tp_zero, tn_zero, fp_zero, fn_zero
|
||||
)
|
||||
ev["Fix one"][instance_idx] = classifier_evaluation_dict(
|
||||
tp_one, tn_one, fp_one, fn_one
|
||||
)
|
||||
return ev</code></pre>
|
||||
</details>
|
||||
<h3>Ancestors</h3>
|
||||
<ul class="hlist">
|
||||
<li><a title="miplearn.components.component.Component" href="component.html#miplearn.components.component.Component">Component</a></li>
|
||||
<li>abc.ABC</li>
|
||||
</ul>
|
||||
<h3>Methods</h3>
|
||||
<dl>
|
||||
<dt id="miplearn.components.primal.PrimalSolutionComponent.evaluate"><code class="name flex">
|
||||
<span>def <span class="ident">evaluate</span></span>(<span>self, instances)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def evaluate(self, instances):
|
||||
ev = {"Fix zero": {}, "Fix one": {}}
|
||||
for instance_idx in tqdm(
|
||||
range(len(instances)),
|
||||
desc="Evaluate (primal)",
|
||||
):
|
||||
instance = instances[instance_idx]
|
||||
solution_actual = instance.training_data[0]["Solution"]
|
||||
solution_pred = self.predict(instance)
|
||||
|
||||
vars_all, vars_one, vars_zero = set(), set(), set()
|
||||
pred_one_positive, pred_zero_positive = set(), set()
|
||||
for (varname, var_dict) in solution_actual.items():
|
||||
if varname not in solution_pred.keys():
|
||||
continue
|
||||
for (idx, value) in var_dict.items():
|
||||
vars_all.add((varname, idx))
|
||||
if value > 0.5:
|
||||
vars_one.add((varname, idx))
|
||||
else:
|
||||
vars_zero.add((varname, idx))
|
||||
if solution_pred[varname][idx] is not None:
|
||||
if solution_pred[varname][idx] > 0.5:
|
||||
pred_one_positive.add((varname, idx))
|
||||
else:
|
||||
pred_zero_positive.add((varname, idx))
|
||||
pred_one_negative = vars_all - pred_one_positive
|
||||
pred_zero_negative = vars_all - pred_zero_positive
|
||||
|
||||
tp_zero = len(pred_zero_positive & vars_zero)
|
||||
fp_zero = len(pred_zero_positive & vars_one)
|
||||
tn_zero = len(pred_zero_negative & vars_one)
|
||||
fn_zero = len(pred_zero_negative & vars_zero)
|
||||
|
||||
tp_one = len(pred_one_positive & vars_one)
|
||||
fp_one = len(pred_one_positive & vars_zero)
|
||||
tn_one = len(pred_one_negative & vars_zero)
|
||||
fn_one = len(pred_one_negative & vars_one)
|
||||
|
||||
ev["Fix zero"][instance_idx] = classifier_evaluation_dict(
|
||||
tp_zero, tn_zero, fp_zero, fn_zero
|
||||
)
|
||||
ev["Fix one"][instance_idx] = classifier_evaluation_dict(
|
||||
tp_one, tn_one, fp_one, fn_one
|
||||
)
|
||||
return ev</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.components.primal.PrimalSolutionComponent.fit"><code class="name flex">
|
||||
<span>def <span class="ident">fit</span></span>(<span>self, training_instances, n_jobs=1)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def fit(self, training_instances, n_jobs=1):
|
||||
logger.debug("Extracting features...")
|
||||
features = VariableFeaturesExtractor().extract(training_instances)
|
||||
solutions = SolutionExtractor().extract(training_instances)
|
||||
|
||||
for category in tqdm(
|
||||
features.keys(),
|
||||
desc="Fit (primal)",
|
||||
):
|
||||
x_train = features[category]
|
||||
for label in [0, 1]:
|
||||
y_train = solutions[category][:, label].astype(int)
|
||||
|
||||
# If all samples are either positive or negative, make constant
|
||||
# predictions
|
||||
y_avg = np.average(y_train)
|
||||
if y_avg < 0.001 or y_avg >= 0.999:
|
||||
self.classifiers[category, label] = round(y_avg)
|
||||
self.thresholds[category, label] = 0.50
|
||||
continue
|
||||
|
||||
# Create a copy of classifier prototype and train it
|
||||
if isinstance(self.classifier_prototype, list):
|
||||
clf = deepcopy(self.classifier_prototype[label])
|
||||
else:
|
||||
clf = deepcopy(self.classifier_prototype)
|
||||
clf.fit(x_train, y_train)
|
||||
|
||||
# Find threshold (dynamic or static)
|
||||
if isinstance(self.threshold_prototype, DynamicThreshold):
|
||||
self.thresholds[category, label] = self.threshold_prototype.find(
|
||||
clf,
|
||||
x_train,
|
||||
y_train,
|
||||
)
|
||||
else:
|
||||
self.thresholds[category, label] = deepcopy(
|
||||
self.threshold_prototype
|
||||
)
|
||||
|
||||
self.classifiers[category, label] = clf</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.components.primal.PrimalSolutionComponent.predict"><code class="name flex">
|
||||
<span>def <span class="ident">predict</span></span>(<span>self, instance)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def predict(self, instance):
|
||||
solution = {}
|
||||
x_test = VariableFeaturesExtractor().extract([instance])
|
||||
var_split = Extractor.split_variables(instance)
|
||||
for category in var_split.keys():
|
||||
n = len(var_split[category])
|
||||
for (i, (var, index)) in enumerate(var_split[category]):
|
||||
if var not in solution.keys():
|
||||
solution[var] = {}
|
||||
solution[var][index] = None
|
||||
for label in [0, 1]:
|
||||
if (category, label) not in self.classifiers.keys():
|
||||
continue
|
||||
clf = self.classifiers[category, label]
|
||||
if isinstance(clf, float) or isinstance(clf, int):
|
||||
ws = np.array([[1 - clf, clf] for _ in range(n)])
|
||||
else:
|
||||
ws = clf.predict_proba(x_test[category])
|
||||
assert ws.shape == (n, 2), "ws.shape should be (%d, 2) not %s" % (
|
||||
n,
|
||||
ws.shape,
|
||||
)
|
||||
for (i, (var, index)) in enumerate(var_split[category]):
|
||||
if ws[i, 1] >= self.thresholds[category, label]:
|
||||
solution[var][index] = label
|
||||
return solution</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.components.primal.PrimalSolutionComponent.x"><code class="name flex">
|
||||
<span>def <span class="ident">x</span></span>(<span>self, training_instances)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def x(self, training_instances):
|
||||
return VariableFeaturesExtractor().extract(training_instances)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.components.primal.PrimalSolutionComponent.y"><code class="name flex">
|
||||
<span>def <span class="ident">y</span></span>(<span>self, training_instances)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def y(self, training_instances):
|
||||
return SolutionExtractor().extract(training_instances)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>Inherited members</h3>
|
||||
<ul class="hlist">
|
||||
<li><code><b><a title="miplearn.components.component.Component" href="component.html#miplearn.components.component.Component">Component</a></b></code>:
|
||||
<ul class="hlist">
|
||||
<li><code><a title="miplearn.components.component.Component.after_solve" href="component.html#miplearn.components.component.Component.after_solve">after_solve</a></code></li>
|
||||
<li><code><a title="miplearn.components.component.Component.before_solve" href="component.html#miplearn.components.component.Component.before_solve">before_solve</a></code></li>
|
||||
<li><code><a title="miplearn.components.component.Component.iteration_cb" href="component.html#miplearn.components.component.Component.iteration_cb">iteration_cb</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.components" href="index.html">miplearn.components</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-classes">Classes</a></h3>
|
||||
<ul>
|
||||
<li>
|
||||
<h4><code><a title="miplearn.components.primal.PrimalSolutionComponent" href="#miplearn.components.primal.PrimalSolutionComponent">PrimalSolutionComponent</a></code></h4>
|
||||
<ul class="">
|
||||
<li><code><a title="miplearn.components.primal.PrimalSolutionComponent.evaluate" href="#miplearn.components.primal.PrimalSolutionComponent.evaluate">evaluate</a></code></li>
|
||||
<li><code><a title="miplearn.components.primal.PrimalSolutionComponent.fit" href="#miplearn.components.primal.PrimalSolutionComponent.fit">fit</a></code></li>
|
||||
<li><code><a title="miplearn.components.primal.PrimalSolutionComponent.predict" href="#miplearn.components.primal.PrimalSolutionComponent.predict">predict</a></code></li>
|
||||
<li><code><a title="miplearn.components.primal.PrimalSolutionComponent.x" href="#miplearn.components.primal.PrimalSolutionComponent.x">x</a></code></li>
|
||||
<li><code><a title="miplearn.components.primal.PrimalSolutionComponent.y" href="#miplearn.components.primal.PrimalSolutionComponent.y">y</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</main>
|
||||
<footer id="footer">
|
||||
<p>Generated by <a href="https://pdoc3.github.io/pdoc"><cite>pdoc</cite> 0.7.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>
|
||||
326
0.2/api/miplearn/components/relaxation.html
Normal file
326
0.2/api/miplearn/components/relaxation.html
Normal file
@@ -0,0 +1,326 @@
|
||||
<!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.components.relaxation 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.components.relaxation</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.classifiers.counting import CountingClassifier
|
||||
from miplearn.components.component import Component
|
||||
from miplearn.components.composite import CompositeComponent
|
||||
from miplearn.components.steps.convert_tight import ConvertTightIneqsIntoEqsStep
|
||||
from miplearn.components.steps.drop_redundant import DropRedundantInequalitiesStep
|
||||
from miplearn.components.steps.relax_integrality import RelaxIntegralityStep
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class RelaxationComponent(Component):
|
||||
"""
|
||||
A Component that tries to build a relaxation that is simultaneously strong and easy
|
||||
to solve. Currently, this component is composed by three steps:
|
||||
|
||||
- RelaxIntegralityStep
|
||||
- DropRedundantInequalitiesStep
|
||||
- ConvertTightIneqsIntoEqsStep
|
||||
|
||||
Parameters
|
||||
----------
|
||||
redundant_classifier : Classifier, optional
|
||||
Classifier used to predict if a constraint is likely redundant. One deep
|
||||
copy of this classifier is made for each constraint category.
|
||||
redundant_threshold : float, optional
|
||||
If the probability that a constraint is redundant exceeds this threshold, the
|
||||
constraint is dropped from the linear relaxation.
|
||||
tight_classifier : Classifier, optional
|
||||
Classifier used to predict if a constraint is likely to be tight. One deep
|
||||
copy of this classifier is made for each constraint category.
|
||||
tight_threshold : float, optional
|
||||
If the probability that a constraint is tight exceeds this threshold, the
|
||||
constraint is converted into an equality constraint.
|
||||
slack_tolerance : float, optional
|
||||
If a constraint has slack greater than this threshold, then the constraint is
|
||||
considered loose. By default, this threshold equals a small positive number to
|
||||
compensate for numerical issues.
|
||||
check_feasibility : bool, optional
|
||||
If true, after the problem is solved, the component verifies that all dropped
|
||||
constraints are still satisfied, re-adds the violated ones and resolves the
|
||||
problem. This loop continues until either no violations are found, or a maximum
|
||||
number of iterations is reached.
|
||||
violation_tolerance : float, optional
|
||||
If `check_dropped` is true, a constraint is considered satisfied during the
|
||||
check if its violation is smaller than this tolerance.
|
||||
max_check_iterations : int
|
||||
If `check_dropped` is true, set the maximum number of iterations in the lazy
|
||||
constraint loop.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
redundant_classifier=CountingClassifier(),
|
||||
redundant_threshold=0.95,
|
||||
tight_classifier=CountingClassifier(),
|
||||
tight_threshold=0.95,
|
||||
slack_tolerance=1e-5,
|
||||
check_feasibility=False,
|
||||
violation_tolerance=1e-5,
|
||||
max_check_iterations=3,
|
||||
):
|
||||
self.steps = [
|
||||
RelaxIntegralityStep(),
|
||||
DropRedundantInequalitiesStep(
|
||||
classifier=redundant_classifier,
|
||||
threshold=redundant_threshold,
|
||||
slack_tolerance=slack_tolerance,
|
||||
violation_tolerance=violation_tolerance,
|
||||
max_iterations=max_check_iterations,
|
||||
check_feasibility=check_feasibility,
|
||||
),
|
||||
ConvertTightIneqsIntoEqsStep(
|
||||
classifier=tight_classifier,
|
||||
threshold=tight_threshold,
|
||||
slack_tolerance=slack_tolerance,
|
||||
),
|
||||
]
|
||||
self.composite = CompositeComponent(self.steps)
|
||||
|
||||
def before_solve(self, solver, instance, model):
|
||||
self.composite.before_solve(solver, instance, model)
|
||||
|
||||
def after_solve(self, solver, instance, model, stats, training_data):
|
||||
self.composite.after_solve(solver, instance, model, stats, training_data)
|
||||
|
||||
def fit(self, training_instances):
|
||||
self.composite.fit(training_instances)
|
||||
|
||||
def iteration_cb(self, solver, instance, model):
|
||||
return self.composite.iteration_cb(solver, instance, model)</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-classes">Classes</h2>
|
||||
<dl>
|
||||
<dt id="miplearn.components.relaxation.RelaxationComponent"><code class="flex name class">
|
||||
<span>class <span class="ident">RelaxationComponent</span></span>
|
||||
<span>(</span><span>redundant_classifier=CountingClassifier(mean=None), redundant_threshold=0.95, tight_classifier=CountingClassifier(mean=None), tight_threshold=0.95, slack_tolerance=1e-05, check_feasibility=False, violation_tolerance=1e-05, max_check_iterations=3)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"><p>A Component that tries to build a relaxation that is simultaneously strong and easy
|
||||
to solve. Currently, this component is composed by three steps:</p>
|
||||
<ul>
|
||||
<li>RelaxIntegralityStep</li>
|
||||
<li>DropRedundantInequalitiesStep</li>
|
||||
<li>ConvertTightIneqsIntoEqsStep</li>
|
||||
</ul>
|
||||
<h2 id="parameters">Parameters</h2>
|
||||
<dl>
|
||||
<dt><strong><code>redundant_classifier</code></strong> : <code>Classifier</code>, optional</dt>
|
||||
<dd>Classifier used to predict if a constraint is likely redundant. One deep
|
||||
copy of this classifier is made for each constraint category.</dd>
|
||||
<dt><strong><code>redundant_threshold</code></strong> : <code>float</code>, optional</dt>
|
||||
<dd>If the probability that a constraint is redundant exceeds this threshold, the
|
||||
constraint is dropped from the linear relaxation.</dd>
|
||||
<dt><strong><code>tight_classifier</code></strong> : <code>Classifier</code>, optional</dt>
|
||||
<dd>Classifier used to predict if a constraint is likely to be tight. One deep
|
||||
copy of this classifier is made for each constraint category.</dd>
|
||||
<dt><strong><code>tight_threshold</code></strong> : <code>float</code>, optional</dt>
|
||||
<dd>If the probability that a constraint is tight exceeds this threshold, the
|
||||
constraint is converted into an equality constraint.</dd>
|
||||
<dt><strong><code>slack_tolerance</code></strong> : <code>float</code>, optional</dt>
|
||||
<dd>If a constraint has slack greater than this threshold, then the constraint is
|
||||
considered loose. By default, this threshold equals a small positive number to
|
||||
compensate for numerical issues.</dd>
|
||||
<dt><strong><code>check_feasibility</code></strong> : <code>bool</code>, optional</dt>
|
||||
<dd>If true, after the problem is solved, the component verifies that all dropped
|
||||
constraints are still satisfied, re-adds the violated ones and resolves the
|
||||
problem. This loop continues until either no violations are found, or a maximum
|
||||
number of iterations is reached.</dd>
|
||||
<dt><strong><code>violation_tolerance</code></strong> : <code>float</code>, optional</dt>
|
||||
<dd>If <code>check_dropped</code> is true, a constraint is considered satisfied during the
|
||||
check if its violation is smaller than this tolerance.</dd>
|
||||
<dt><strong><code>max_check_iterations</code></strong> : <code>int</code></dt>
|
||||
<dd>If <code>check_dropped</code> is true, set the maximum number of iterations in the lazy
|
||||
constraint loop.</dd>
|
||||
</dl></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">class RelaxationComponent(Component):
|
||||
"""
|
||||
A Component that tries to build a relaxation that is simultaneously strong and easy
|
||||
to solve. Currently, this component is composed by three steps:
|
||||
|
||||
- RelaxIntegralityStep
|
||||
- DropRedundantInequalitiesStep
|
||||
- ConvertTightIneqsIntoEqsStep
|
||||
|
||||
Parameters
|
||||
----------
|
||||
redundant_classifier : Classifier, optional
|
||||
Classifier used to predict if a constraint is likely redundant. One deep
|
||||
copy of this classifier is made for each constraint category.
|
||||
redundant_threshold : float, optional
|
||||
If the probability that a constraint is redundant exceeds this threshold, the
|
||||
constraint is dropped from the linear relaxation.
|
||||
tight_classifier : Classifier, optional
|
||||
Classifier used to predict if a constraint is likely to be tight. One deep
|
||||
copy of this classifier is made for each constraint category.
|
||||
tight_threshold : float, optional
|
||||
If the probability that a constraint is tight exceeds this threshold, the
|
||||
constraint is converted into an equality constraint.
|
||||
slack_tolerance : float, optional
|
||||
If a constraint has slack greater than this threshold, then the constraint is
|
||||
considered loose. By default, this threshold equals a small positive number to
|
||||
compensate for numerical issues.
|
||||
check_feasibility : bool, optional
|
||||
If true, after the problem is solved, the component verifies that all dropped
|
||||
constraints are still satisfied, re-adds the violated ones and resolves the
|
||||
problem. This loop continues until either no violations are found, or a maximum
|
||||
number of iterations is reached.
|
||||
violation_tolerance : float, optional
|
||||
If `check_dropped` is true, a constraint is considered satisfied during the
|
||||
check if its violation is smaller than this tolerance.
|
||||
max_check_iterations : int
|
||||
If `check_dropped` is true, set the maximum number of iterations in the lazy
|
||||
constraint loop.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
redundant_classifier=CountingClassifier(),
|
||||
redundant_threshold=0.95,
|
||||
tight_classifier=CountingClassifier(),
|
||||
tight_threshold=0.95,
|
||||
slack_tolerance=1e-5,
|
||||
check_feasibility=False,
|
||||
violation_tolerance=1e-5,
|
||||
max_check_iterations=3,
|
||||
):
|
||||
self.steps = [
|
||||
RelaxIntegralityStep(),
|
||||
DropRedundantInequalitiesStep(
|
||||
classifier=redundant_classifier,
|
||||
threshold=redundant_threshold,
|
||||
slack_tolerance=slack_tolerance,
|
||||
violation_tolerance=violation_tolerance,
|
||||
max_iterations=max_check_iterations,
|
||||
check_feasibility=check_feasibility,
|
||||
),
|
||||
ConvertTightIneqsIntoEqsStep(
|
||||
classifier=tight_classifier,
|
||||
threshold=tight_threshold,
|
||||
slack_tolerance=slack_tolerance,
|
||||
),
|
||||
]
|
||||
self.composite = CompositeComponent(self.steps)
|
||||
|
||||
def before_solve(self, solver, instance, model):
|
||||
self.composite.before_solve(solver, instance, model)
|
||||
|
||||
def after_solve(self, solver, instance, model, stats, training_data):
|
||||
self.composite.after_solve(solver, instance, model, stats, training_data)
|
||||
|
||||
def fit(self, training_instances):
|
||||
self.composite.fit(training_instances)
|
||||
|
||||
def iteration_cb(self, solver, instance, model):
|
||||
return self.composite.iteration_cb(solver, instance, model)</code></pre>
|
||||
</details>
|
||||
<h3>Ancestors</h3>
|
||||
<ul class="hlist">
|
||||
<li><a title="miplearn.components.component.Component" href="component.html#miplearn.components.component.Component">Component</a></li>
|
||||
<li>abc.ABC</li>
|
||||
</ul>
|
||||
<h3>Methods</h3>
|
||||
<dl>
|
||||
<dt id="miplearn.components.relaxation.RelaxationComponent.fit"><code class="name flex">
|
||||
<span>def <span class="ident">fit</span></span>(<span>self, training_instances)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def fit(self, training_instances):
|
||||
self.composite.fit(training_instances)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>Inherited members</h3>
|
||||
<ul class="hlist">
|
||||
<li><code><b><a title="miplearn.components.component.Component" href="component.html#miplearn.components.component.Component">Component</a></b></code>:
|
||||
<ul class="hlist">
|
||||
<li><code><a title="miplearn.components.component.Component.after_solve" href="component.html#miplearn.components.component.Component.after_solve">after_solve</a></code></li>
|
||||
<li><code><a title="miplearn.components.component.Component.before_solve" href="component.html#miplearn.components.component.Component.before_solve">before_solve</a></code></li>
|
||||
<li><code><a title="miplearn.components.component.Component.iteration_cb" href="component.html#miplearn.components.component.Component.iteration_cb">iteration_cb</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.components" href="index.html">miplearn.components</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-classes">Classes</a></h3>
|
||||
<ul>
|
||||
<li>
|
||||
<h4><code><a title="miplearn.components.relaxation.RelaxationComponent" href="#miplearn.components.relaxation.RelaxationComponent">RelaxationComponent</a></code></h4>
|
||||
<ul class="">
|
||||
<li><code><a title="miplearn.components.relaxation.RelaxationComponent.fit" href="#miplearn.components.relaxation.RelaxationComponent.fit">fit</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</main>
|
||||
<footer id="footer">
|
||||
<p>Generated by <a href="https://pdoc3.github.io/pdoc"><cite>pdoc</cite> 0.7.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>
|
||||
635
0.2/api/miplearn/components/steps/convert_tight.html
Normal file
635
0.2/api/miplearn/components/steps/convert_tight.html
Normal file
@@ -0,0 +1,635 @@
|
||||
<!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.components.steps.convert_tight 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.components.steps.convert_tight</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 random
|
||||
from copy import deepcopy
|
||||
|
||||
import numpy as np
|
||||
from tqdm import tqdm
|
||||
|
||||
from miplearn.classifiers.counting import CountingClassifier
|
||||
from miplearn.components import classifier_evaluation_dict
|
||||
from miplearn.components.component import Component
|
||||
from miplearn.components.steps.drop_redundant import DropRedundantInequalitiesStep
|
||||
from miplearn.extractors import InstanceIterator
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ConvertTightIneqsIntoEqsStep(Component):
|
||||
"""
|
||||
Component that predicts which inequality constraints are likely to be binding in
|
||||
the LP relaxation of the problem and converts them into equality constraints.
|
||||
|
||||
This component always makes sure that the conversion process does not affect the
|
||||
feasibility of the problem. It can also, optionally, make sure that it does not affect
|
||||
the optimality, but this may be expensive.
|
||||
|
||||
This component does not work on MIPs. All integrality constraints must be relaxed
|
||||
before this component is used.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
classifier=CountingClassifier(),
|
||||
threshold=0.95,
|
||||
slack_tolerance=0.0,
|
||||
check_optimality=False,
|
||||
):
|
||||
self.classifiers = {}
|
||||
self.classifier_prototype = classifier
|
||||
self.threshold = threshold
|
||||
self.slack_tolerance = slack_tolerance
|
||||
self.check_optimality = check_optimality
|
||||
self.converted = []
|
||||
self.original_sense = {}
|
||||
|
||||
def before_solve(self, solver, instance, _):
|
||||
logger.info("Predicting tight LP constraints...")
|
||||
x, constraints = DropRedundantInequalitiesStep._x_test(
|
||||
instance,
|
||||
constraint_ids=solver.internal_solver.get_constraint_ids(),
|
||||
)
|
||||
y = self.predict(x)
|
||||
|
||||
self.n_converted = 0
|
||||
self.n_restored = 0
|
||||
self.n_kept = 0
|
||||
self.n_infeasible_iterations = 0
|
||||
self.n_suboptimal_iterations = 0
|
||||
for category in y.keys():
|
||||
for i in range(len(y[category])):
|
||||
if y[category][i][0] == 1:
|
||||
cid = constraints[category][i]
|
||||
s = solver.internal_solver.get_constraint_sense(cid)
|
||||
self.original_sense[cid] = s
|
||||
solver.internal_solver.set_constraint_sense(cid, "=")
|
||||
self.converted += [cid]
|
||||
self.n_converted += 1
|
||||
else:
|
||||
self.n_kept += 1
|
||||
|
||||
logger.info(f"Converted {self.n_converted} inequalities")
|
||||
|
||||
def after_solve(
|
||||
self,
|
||||
solver,
|
||||
instance,
|
||||
model,
|
||||
stats,
|
||||
training_data,
|
||||
):
|
||||
if "slacks" not in training_data.keys():
|
||||
training_data["slacks"] = solver.internal_solver.get_inequality_slacks()
|
||||
stats["ConvertTight: Kept"] = self.n_kept
|
||||
stats["ConvertTight: Converted"] = self.n_converted
|
||||
stats["ConvertTight: Restored"] = self.n_restored
|
||||
stats["ConvertTight: Inf iterations"] = self.n_infeasible_iterations
|
||||
stats["ConvertTight: Subopt iterations"] = self.n_suboptimal_iterations
|
||||
|
||||
def fit(self, training_instances):
|
||||
logger.debug("Extracting x and y...")
|
||||
x = self.x(training_instances)
|
||||
y = self.y(training_instances)
|
||||
logger.debug("Fitting...")
|
||||
for category in tqdm(x.keys(), desc="Fit (rlx:conv_ineqs)"):
|
||||
if category not in self.classifiers:
|
||||
self.classifiers[category] = deepcopy(self.classifier_prototype)
|
||||
self.classifiers[category].fit(x[category], y[category])
|
||||
|
||||
def x(self, instances):
|
||||
return DropRedundantInequalitiesStep._x_train(instances)
|
||||
|
||||
def y(self, instances):
|
||||
y = {}
|
||||
for instance in tqdm(
|
||||
InstanceIterator(instances),
|
||||
desc="Extract (rlx:conv_ineqs:y)",
|
||||
disable=len(instances) < 5,
|
||||
):
|
||||
for (cid, slack) in instance.training_data[0]["slacks"].items():
|
||||
category = instance.get_constraint_category(cid)
|
||||
if category is None:
|
||||
continue
|
||||
if category not in y:
|
||||
y[category] = []
|
||||
if 0 <= slack <= self.slack_tolerance:
|
||||
y[category] += [[1]]
|
||||
else:
|
||||
y[category] += [[0]]
|
||||
return y
|
||||
|
||||
def predict(self, x):
|
||||
y = {}
|
||||
for (category, x_cat) in x.items():
|
||||
if category not in self.classifiers:
|
||||
continue
|
||||
y[category] = []
|
||||
x_cat = np.array(x_cat)
|
||||
proba = self.classifiers[category].predict_proba(x_cat)
|
||||
for i in range(len(proba)):
|
||||
if proba[i][1] >= self.threshold:
|
||||
y[category] += [[1]]
|
||||
else:
|
||||
y[category] += [[0]]
|
||||
return y
|
||||
|
||||
def evaluate(self, instance):
|
||||
x = self.x([instance])
|
||||
y_true = self.y([instance])
|
||||
y_pred = self.predict(x)
|
||||
tp, tn, fp, fn = 0, 0, 0, 0
|
||||
for category in y_true.keys():
|
||||
for i in range(len(y_true[category])):
|
||||
if y_pred[category][i][0] == 1:
|
||||
if y_true[category][i][0] == 1:
|
||||
tp += 1
|
||||
else:
|
||||
fp += 1
|
||||
else:
|
||||
if y_true[category][i][0] == 1:
|
||||
fn += 1
|
||||
else:
|
||||
tn += 1
|
||||
return classifier_evaluation_dict(tp, tn, fp, fn)
|
||||
|
||||
def iteration_cb(self, solver, instance, model):
|
||||
is_infeasible, is_suboptimal = False, False
|
||||
restored = []
|
||||
|
||||
def check_pi(msense, csense, pi):
|
||||
if csense == "=":
|
||||
return True
|
||||
if msense == "max":
|
||||
if csense == "<":
|
||||
return pi >= 0
|
||||
else:
|
||||
return pi <= 0
|
||||
else:
|
||||
if csense == ">":
|
||||
return pi >= 0
|
||||
else:
|
||||
return pi <= 0
|
||||
|
||||
def restore(cid):
|
||||
nonlocal restored
|
||||
csense = self.original_sense[cid]
|
||||
solver.internal_solver.set_constraint_sense(cid, csense)
|
||||
restored += [cid]
|
||||
|
||||
if solver.internal_solver.is_infeasible():
|
||||
for cid in self.converted:
|
||||
pi = solver.internal_solver.get_dual(cid)
|
||||
if abs(pi) > 0:
|
||||
is_infeasible = True
|
||||
restore(cid)
|
||||
elif self.check_optimality:
|
||||
random.shuffle(self.converted)
|
||||
n_restored = 0
|
||||
for cid in self.converted:
|
||||
if n_restored >= 100:
|
||||
break
|
||||
pi = solver.internal_solver.get_dual(cid)
|
||||
csense = self.original_sense[cid]
|
||||
msense = solver.internal_solver.get_sense()
|
||||
if not check_pi(msense, csense, pi):
|
||||
is_suboptimal = True
|
||||
restore(cid)
|
||||
n_restored += 1
|
||||
|
||||
for cid in restored:
|
||||
self.converted.remove(cid)
|
||||
|
||||
if len(restored) > 0:
|
||||
self.n_restored += len(restored)
|
||||
if is_infeasible:
|
||||
self.n_infeasible_iterations += 1
|
||||
if is_suboptimal:
|
||||
self.n_suboptimal_iterations += 1
|
||||
logger.info(f"Restored {len(restored)} inequalities")
|
||||
return True
|
||||
else:
|
||||
return False</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-classes">Classes</h2>
|
||||
<dl>
|
||||
<dt id="miplearn.components.steps.convert_tight.ConvertTightIneqsIntoEqsStep"><code class="flex name class">
|
||||
<span>class <span class="ident">ConvertTightIneqsIntoEqsStep</span></span>
|
||||
<span>(</span><span>classifier=CountingClassifier(mean=None), threshold=0.95, slack_tolerance=0.0, check_optimality=False)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"><p>Component that predicts which inequality constraints are likely to be binding in
|
||||
the LP relaxation of the problem and converts them into equality constraints.</p>
|
||||
<p>This component always makes sure that the conversion process does not affect the
|
||||
feasibility of the problem. It can also, optionally, make sure that it does not affect
|
||||
the optimality, but this may be expensive.</p>
|
||||
<p>This component does not work on MIPs. All integrality constraints must be relaxed
|
||||
before this component is used.</p></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">class ConvertTightIneqsIntoEqsStep(Component):
|
||||
"""
|
||||
Component that predicts which inequality constraints are likely to be binding in
|
||||
the LP relaxation of the problem and converts them into equality constraints.
|
||||
|
||||
This component always makes sure that the conversion process does not affect the
|
||||
feasibility of the problem. It can also, optionally, make sure that it does not affect
|
||||
the optimality, but this may be expensive.
|
||||
|
||||
This component does not work on MIPs. All integrality constraints must be relaxed
|
||||
before this component is used.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
classifier=CountingClassifier(),
|
||||
threshold=0.95,
|
||||
slack_tolerance=0.0,
|
||||
check_optimality=False,
|
||||
):
|
||||
self.classifiers = {}
|
||||
self.classifier_prototype = classifier
|
||||
self.threshold = threshold
|
||||
self.slack_tolerance = slack_tolerance
|
||||
self.check_optimality = check_optimality
|
||||
self.converted = []
|
||||
self.original_sense = {}
|
||||
|
||||
def before_solve(self, solver, instance, _):
|
||||
logger.info("Predicting tight LP constraints...")
|
||||
x, constraints = DropRedundantInequalitiesStep._x_test(
|
||||
instance,
|
||||
constraint_ids=solver.internal_solver.get_constraint_ids(),
|
||||
)
|
||||
y = self.predict(x)
|
||||
|
||||
self.n_converted = 0
|
||||
self.n_restored = 0
|
||||
self.n_kept = 0
|
||||
self.n_infeasible_iterations = 0
|
||||
self.n_suboptimal_iterations = 0
|
||||
for category in y.keys():
|
||||
for i in range(len(y[category])):
|
||||
if y[category][i][0] == 1:
|
||||
cid = constraints[category][i]
|
||||
s = solver.internal_solver.get_constraint_sense(cid)
|
||||
self.original_sense[cid] = s
|
||||
solver.internal_solver.set_constraint_sense(cid, "=")
|
||||
self.converted += [cid]
|
||||
self.n_converted += 1
|
||||
else:
|
||||
self.n_kept += 1
|
||||
|
||||
logger.info(f"Converted {self.n_converted} inequalities")
|
||||
|
||||
def after_solve(
|
||||
self,
|
||||
solver,
|
||||
instance,
|
||||
model,
|
||||
stats,
|
||||
training_data,
|
||||
):
|
||||
if "slacks" not in training_data.keys():
|
||||
training_data["slacks"] = solver.internal_solver.get_inequality_slacks()
|
||||
stats["ConvertTight: Kept"] = self.n_kept
|
||||
stats["ConvertTight: Converted"] = self.n_converted
|
||||
stats["ConvertTight: Restored"] = self.n_restored
|
||||
stats["ConvertTight: Inf iterations"] = self.n_infeasible_iterations
|
||||
stats["ConvertTight: Subopt iterations"] = self.n_suboptimal_iterations
|
||||
|
||||
def fit(self, training_instances):
|
||||
logger.debug("Extracting x and y...")
|
||||
x = self.x(training_instances)
|
||||
y = self.y(training_instances)
|
||||
logger.debug("Fitting...")
|
||||
for category in tqdm(x.keys(), desc="Fit (rlx:conv_ineqs)"):
|
||||
if category not in self.classifiers:
|
||||
self.classifiers[category] = deepcopy(self.classifier_prototype)
|
||||
self.classifiers[category].fit(x[category], y[category])
|
||||
|
||||
def x(self, instances):
|
||||
return DropRedundantInequalitiesStep._x_train(instances)
|
||||
|
||||
def y(self, instances):
|
||||
y = {}
|
||||
for instance in tqdm(
|
||||
InstanceIterator(instances),
|
||||
desc="Extract (rlx:conv_ineqs:y)",
|
||||
disable=len(instances) < 5,
|
||||
):
|
||||
for (cid, slack) in instance.training_data[0]["slacks"].items():
|
||||
category = instance.get_constraint_category(cid)
|
||||
if category is None:
|
||||
continue
|
||||
if category not in y:
|
||||
y[category] = []
|
||||
if 0 <= slack <= self.slack_tolerance:
|
||||
y[category] += [[1]]
|
||||
else:
|
||||
y[category] += [[0]]
|
||||
return y
|
||||
|
||||
def predict(self, x):
|
||||
y = {}
|
||||
for (category, x_cat) in x.items():
|
||||
if category not in self.classifiers:
|
||||
continue
|
||||
y[category] = []
|
||||
x_cat = np.array(x_cat)
|
||||
proba = self.classifiers[category].predict_proba(x_cat)
|
||||
for i in range(len(proba)):
|
||||
if proba[i][1] >= self.threshold:
|
||||
y[category] += [[1]]
|
||||
else:
|
||||
y[category] += [[0]]
|
||||
return y
|
||||
|
||||
def evaluate(self, instance):
|
||||
x = self.x([instance])
|
||||
y_true = self.y([instance])
|
||||
y_pred = self.predict(x)
|
||||
tp, tn, fp, fn = 0, 0, 0, 0
|
||||
for category in y_true.keys():
|
||||
for i in range(len(y_true[category])):
|
||||
if y_pred[category][i][0] == 1:
|
||||
if y_true[category][i][0] == 1:
|
||||
tp += 1
|
||||
else:
|
||||
fp += 1
|
||||
else:
|
||||
if y_true[category][i][0] == 1:
|
||||
fn += 1
|
||||
else:
|
||||
tn += 1
|
||||
return classifier_evaluation_dict(tp, tn, fp, fn)
|
||||
|
||||
def iteration_cb(self, solver, instance, model):
|
||||
is_infeasible, is_suboptimal = False, False
|
||||
restored = []
|
||||
|
||||
def check_pi(msense, csense, pi):
|
||||
if csense == "=":
|
||||
return True
|
||||
if msense == "max":
|
||||
if csense == "<":
|
||||
return pi >= 0
|
||||
else:
|
||||
return pi <= 0
|
||||
else:
|
||||
if csense == ">":
|
||||
return pi >= 0
|
||||
else:
|
||||
return pi <= 0
|
||||
|
||||
def restore(cid):
|
||||
nonlocal restored
|
||||
csense = self.original_sense[cid]
|
||||
solver.internal_solver.set_constraint_sense(cid, csense)
|
||||
restored += [cid]
|
||||
|
||||
if solver.internal_solver.is_infeasible():
|
||||
for cid in self.converted:
|
||||
pi = solver.internal_solver.get_dual(cid)
|
||||
if abs(pi) > 0:
|
||||
is_infeasible = True
|
||||
restore(cid)
|
||||
elif self.check_optimality:
|
||||
random.shuffle(self.converted)
|
||||
n_restored = 0
|
||||
for cid in self.converted:
|
||||
if n_restored >= 100:
|
||||
break
|
||||
pi = solver.internal_solver.get_dual(cid)
|
||||
csense = self.original_sense[cid]
|
||||
msense = solver.internal_solver.get_sense()
|
||||
if not check_pi(msense, csense, pi):
|
||||
is_suboptimal = True
|
||||
restore(cid)
|
||||
n_restored += 1
|
||||
|
||||
for cid in restored:
|
||||
self.converted.remove(cid)
|
||||
|
||||
if len(restored) > 0:
|
||||
self.n_restored += len(restored)
|
||||
if is_infeasible:
|
||||
self.n_infeasible_iterations += 1
|
||||
if is_suboptimal:
|
||||
self.n_suboptimal_iterations += 1
|
||||
logger.info(f"Restored {len(restored)} inequalities")
|
||||
return True
|
||||
else:
|
||||
return False</code></pre>
|
||||
</details>
|
||||
<h3>Ancestors</h3>
|
||||
<ul class="hlist">
|
||||
<li><a title="miplearn.components.component.Component" href="../component.html#miplearn.components.component.Component">Component</a></li>
|
||||
<li>abc.ABC</li>
|
||||
</ul>
|
||||
<h3>Methods</h3>
|
||||
<dl>
|
||||
<dt id="miplearn.components.steps.convert_tight.ConvertTightIneqsIntoEqsStep.evaluate"><code class="name flex">
|
||||
<span>def <span class="ident">evaluate</span></span>(<span>self, instance)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def evaluate(self, instance):
|
||||
x = self.x([instance])
|
||||
y_true = self.y([instance])
|
||||
y_pred = self.predict(x)
|
||||
tp, tn, fp, fn = 0, 0, 0, 0
|
||||
for category in y_true.keys():
|
||||
for i in range(len(y_true[category])):
|
||||
if y_pred[category][i][0] == 1:
|
||||
if y_true[category][i][0] == 1:
|
||||
tp += 1
|
||||
else:
|
||||
fp += 1
|
||||
else:
|
||||
if y_true[category][i][0] == 1:
|
||||
fn += 1
|
||||
else:
|
||||
tn += 1
|
||||
return classifier_evaluation_dict(tp, tn, fp, fn)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.components.steps.convert_tight.ConvertTightIneqsIntoEqsStep.fit"><code class="name flex">
|
||||
<span>def <span class="ident">fit</span></span>(<span>self, training_instances)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def fit(self, training_instances):
|
||||
logger.debug("Extracting x and y...")
|
||||
x = self.x(training_instances)
|
||||
y = self.y(training_instances)
|
||||
logger.debug("Fitting...")
|
||||
for category in tqdm(x.keys(), desc="Fit (rlx:conv_ineqs)"):
|
||||
if category not in self.classifiers:
|
||||
self.classifiers[category] = deepcopy(self.classifier_prototype)
|
||||
self.classifiers[category].fit(x[category], y[category])</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.components.steps.convert_tight.ConvertTightIneqsIntoEqsStep.predict"><code class="name flex">
|
||||
<span>def <span class="ident">predict</span></span>(<span>self, x)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def predict(self, x):
|
||||
y = {}
|
||||
for (category, x_cat) in x.items():
|
||||
if category not in self.classifiers:
|
||||
continue
|
||||
y[category] = []
|
||||
x_cat = np.array(x_cat)
|
||||
proba = self.classifiers[category].predict_proba(x_cat)
|
||||
for i in range(len(proba)):
|
||||
if proba[i][1] >= self.threshold:
|
||||
y[category] += [[1]]
|
||||
else:
|
||||
y[category] += [[0]]
|
||||
return y</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.components.steps.convert_tight.ConvertTightIneqsIntoEqsStep.x"><code class="name flex">
|
||||
<span>def <span class="ident">x</span></span>(<span>self, instances)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def x(self, instances):
|
||||
return DropRedundantInequalitiesStep._x_train(instances)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.components.steps.convert_tight.ConvertTightIneqsIntoEqsStep.y"><code class="name flex">
|
||||
<span>def <span class="ident">y</span></span>(<span>self, instances)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def y(self, instances):
|
||||
y = {}
|
||||
for instance in tqdm(
|
||||
InstanceIterator(instances),
|
||||
desc="Extract (rlx:conv_ineqs:y)",
|
||||
disable=len(instances) < 5,
|
||||
):
|
||||
for (cid, slack) in instance.training_data[0]["slacks"].items():
|
||||
category = instance.get_constraint_category(cid)
|
||||
if category is None:
|
||||
continue
|
||||
if category not in y:
|
||||
y[category] = []
|
||||
if 0 <= slack <= self.slack_tolerance:
|
||||
y[category] += [[1]]
|
||||
else:
|
||||
y[category] += [[0]]
|
||||
return y</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>Inherited members</h3>
|
||||
<ul class="hlist">
|
||||
<li><code><b><a title="miplearn.components.component.Component" href="../component.html#miplearn.components.component.Component">Component</a></b></code>:
|
||||
<ul class="hlist">
|
||||
<li><code><a title="miplearn.components.component.Component.after_solve" href="../component.html#miplearn.components.component.Component.after_solve">after_solve</a></code></li>
|
||||
<li><code><a title="miplearn.components.component.Component.before_solve" href="../component.html#miplearn.components.component.Component.before_solve">before_solve</a></code></li>
|
||||
<li><code><a title="miplearn.components.component.Component.iteration_cb" href="../component.html#miplearn.components.component.Component.iteration_cb">iteration_cb</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.components.steps" href="index.html">miplearn.components.steps</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-classes">Classes</a></h3>
|
||||
<ul>
|
||||
<li>
|
||||
<h4><code><a title="miplearn.components.steps.convert_tight.ConvertTightIneqsIntoEqsStep" href="#miplearn.components.steps.convert_tight.ConvertTightIneqsIntoEqsStep">ConvertTightIneqsIntoEqsStep</a></code></h4>
|
||||
<ul class="">
|
||||
<li><code><a title="miplearn.components.steps.convert_tight.ConvertTightIneqsIntoEqsStep.evaluate" href="#miplearn.components.steps.convert_tight.ConvertTightIneqsIntoEqsStep.evaluate">evaluate</a></code></li>
|
||||
<li><code><a title="miplearn.components.steps.convert_tight.ConvertTightIneqsIntoEqsStep.fit" href="#miplearn.components.steps.convert_tight.ConvertTightIneqsIntoEqsStep.fit">fit</a></code></li>
|
||||
<li><code><a title="miplearn.components.steps.convert_tight.ConvertTightIneqsIntoEqsStep.predict" href="#miplearn.components.steps.convert_tight.ConvertTightIneqsIntoEqsStep.predict">predict</a></code></li>
|
||||
<li><code><a title="miplearn.components.steps.convert_tight.ConvertTightIneqsIntoEqsStep.x" href="#miplearn.components.steps.convert_tight.ConvertTightIneqsIntoEqsStep.x">x</a></code></li>
|
||||
<li><code><a title="miplearn.components.steps.convert_tight.ConvertTightIneqsIntoEqsStep.y" href="#miplearn.components.steps.convert_tight.ConvertTightIneqsIntoEqsStep.y">y</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</main>
|
||||
<footer id="footer">
|
||||
<p>Generated by <a href="https://pdoc3.github.io/pdoc"><cite>pdoc</cite> 0.7.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>
|
||||
663
0.2/api/miplearn/components/steps/drop_redundant.html
Normal file
663
0.2/api/miplearn/components/steps/drop_redundant.html
Normal file
@@ -0,0 +1,663 @@
|
||||
<!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.components.steps.drop_redundant 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.components.steps.drop_redundant</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 copy import deepcopy
|
||||
|
||||
import numpy as np
|
||||
from tqdm import tqdm
|
||||
|
||||
from miplearn.classifiers.counting import CountingClassifier
|
||||
from miplearn.components import classifier_evaluation_dict
|
||||
from miplearn.components.component import Component
|
||||
from miplearn.components.lazy_static import LazyConstraint
|
||||
from miplearn.extractors import InstanceIterator
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class DropRedundantInequalitiesStep(Component):
|
||||
"""
|
||||
Component that predicts which inequalities are likely loose in the LP and removes
|
||||
them. Optionally, double checks after the problem is solved that all dropped
|
||||
inequalities were in fact redundant, and, if not, re-adds them to the problem.
|
||||
|
||||
This component does not work on MIPs. All integrality constraints must be relaxed
|
||||
before this component is used.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
classifier=CountingClassifier(),
|
||||
threshold=0.95,
|
||||
slack_tolerance=1e-5,
|
||||
check_feasibility=False,
|
||||
violation_tolerance=1e-5,
|
||||
max_iterations=3,
|
||||
):
|
||||
self.classifiers = {}
|
||||
self.classifier_prototype = classifier
|
||||
self.threshold = threshold
|
||||
self.slack_tolerance = slack_tolerance
|
||||
self.pool = []
|
||||
self.check_feasibility = check_feasibility
|
||||
self.violation_tolerance = violation_tolerance
|
||||
self.max_iterations = max_iterations
|
||||
self.current_iteration = 0
|
||||
|
||||
def before_solve(self, solver, instance, _):
|
||||
self.current_iteration = 0
|
||||
|
||||
logger.info("Predicting redundant LP constraints...")
|
||||
x, constraints = self._x_test(
|
||||
instance,
|
||||
constraint_ids=solver.internal_solver.get_constraint_ids(),
|
||||
)
|
||||
y = self.predict(x)
|
||||
|
||||
self.total_dropped = 0
|
||||
self.total_restored = 0
|
||||
self.total_kept = 0
|
||||
self.total_iterations = 0
|
||||
for category in y.keys():
|
||||
for i in range(len(y[category])):
|
||||
if y[category][i][0] == 1:
|
||||
cid = constraints[category][i]
|
||||
c = LazyConstraint(
|
||||
cid=cid,
|
||||
obj=solver.internal_solver.extract_constraint(cid),
|
||||
)
|
||||
self.pool += [c]
|
||||
self.total_dropped += 1
|
||||
else:
|
||||
self.total_kept += 1
|
||||
logger.info(f"Extracted {self.total_dropped} predicted constraints")
|
||||
|
||||
def after_solve(
|
||||
self,
|
||||
solver,
|
||||
instance,
|
||||
model,
|
||||
stats,
|
||||
training_data,
|
||||
):
|
||||
if "slacks" not in training_data.keys():
|
||||
training_data["slacks"] = solver.internal_solver.get_inequality_slacks()
|
||||
stats.update(
|
||||
{
|
||||
"DropRedundant: Kept": self.total_kept,
|
||||
"DropRedundant: Dropped": self.total_dropped,
|
||||
"DropRedundant: Restored": self.total_restored,
|
||||
"DropRedundant: Iterations": self.total_iterations,
|
||||
}
|
||||
)
|
||||
|
||||
def fit(self, training_instances):
|
||||
logger.debug("Extracting x and y...")
|
||||
x = self.x(training_instances)
|
||||
y = self.y(training_instances)
|
||||
logger.debug("Fitting...")
|
||||
for category in tqdm(x.keys(), desc="Fit (rlx:drop_ineq)"):
|
||||
if category not in self.classifiers:
|
||||
self.classifiers[category] = deepcopy(self.classifier_prototype)
|
||||
self.classifiers[category].fit(x[category], y[category])
|
||||
|
||||
@staticmethod
|
||||
def _x_test(instance, constraint_ids):
|
||||
x = {}
|
||||
constraints = {}
|
||||
cids = constraint_ids
|
||||
for cid in cids:
|
||||
category = instance.get_constraint_category(cid)
|
||||
if category is None:
|
||||
continue
|
||||
if category not in x:
|
||||
x[category] = []
|
||||
constraints[category] = []
|
||||
x[category] += [instance.get_constraint_features(cid)]
|
||||
constraints[category] += [cid]
|
||||
for category in x.keys():
|
||||
x[category] = np.array(x[category])
|
||||
return x, constraints
|
||||
|
||||
@staticmethod
|
||||
def _x_train(instances):
|
||||
x = {}
|
||||
for instance in tqdm(
|
||||
InstanceIterator(instances),
|
||||
desc="Extract (rlx:drop_ineq:x)",
|
||||
disable=len(instances) < 5,
|
||||
):
|
||||
for training_data in instance.training_data:
|
||||
cids = training_data["slacks"].keys()
|
||||
for cid in cids:
|
||||
category = instance.get_constraint_category(cid)
|
||||
if category is None:
|
||||
continue
|
||||
if category not in x:
|
||||
x[category] = []
|
||||
x[category] += [instance.get_constraint_features(cid)]
|
||||
for category in x.keys():
|
||||
x[category] = np.array(x[category])
|
||||
return x
|
||||
|
||||
def x(self, instances):
|
||||
return self._x_train(instances)
|
||||
|
||||
def y(self, instances):
|
||||
y = {}
|
||||
for instance in tqdm(
|
||||
InstanceIterator(instances),
|
||||
desc="Extract (rlx:drop_ineq:y)",
|
||||
disable=len(instances) < 5,
|
||||
):
|
||||
for training_data in instance.training_data:
|
||||
for (cid, slack) in training_data["slacks"].items():
|
||||
category = instance.get_constraint_category(cid)
|
||||
if category is None:
|
||||
continue
|
||||
if category not in y:
|
||||
y[category] = []
|
||||
if slack > self.slack_tolerance:
|
||||
y[category] += [[1]]
|
||||
else:
|
||||
y[category] += [[0]]
|
||||
return y
|
||||
|
||||
def predict(self, x):
|
||||
y = {}
|
||||
for (category, x_cat) in x.items():
|
||||
if category not in self.classifiers:
|
||||
continue
|
||||
y[category] = []
|
||||
x_cat = np.array(x_cat)
|
||||
proba = self.classifiers[category].predict_proba(x_cat)
|
||||
for i in range(len(proba)):
|
||||
if proba[i][1] >= self.threshold:
|
||||
y[category] += [[1]]
|
||||
else:
|
||||
y[category] += [[0]]
|
||||
return y
|
||||
|
||||
def evaluate(self, instance):
|
||||
x = self.x([instance])
|
||||
y_true = self.y([instance])
|
||||
y_pred = self.predict(x)
|
||||
tp, tn, fp, fn = 0, 0, 0, 0
|
||||
for category in y_true.keys():
|
||||
for i in range(len(y_true[category])):
|
||||
if y_pred[category][i][0] == 1:
|
||||
if y_true[category][i][0] == 1:
|
||||
tp += 1
|
||||
else:
|
||||
fp += 1
|
||||
else:
|
||||
if y_true[category][i][0] == 1:
|
||||
fn += 1
|
||||
else:
|
||||
tn += 1
|
||||
return classifier_evaluation_dict(tp, tn, fp, fn)
|
||||
|
||||
def iteration_cb(self, solver, instance, model):
|
||||
if not self.check_feasibility:
|
||||
return False
|
||||
if self.current_iteration >= self.max_iterations:
|
||||
return False
|
||||
self.current_iteration += 1
|
||||
logger.debug("Checking that dropped constraints are satisfied...")
|
||||
constraints_to_add = []
|
||||
for c in self.pool:
|
||||
if not solver.internal_solver.is_constraint_satisfied(
|
||||
c.obj,
|
||||
self.violation_tolerance,
|
||||
):
|
||||
constraints_to_add.append(c)
|
||||
for c in constraints_to_add:
|
||||
self.pool.remove(c)
|
||||
solver.internal_solver.add_constraint(c.obj)
|
||||
if len(constraints_to_add) > 0:
|
||||
self.total_restored += len(constraints_to_add)
|
||||
logger.info(
|
||||
"%8d constraints %8d in the pool"
|
||||
% (len(constraints_to_add), len(self.pool))
|
||||
)
|
||||
self.total_iterations += 1
|
||||
return True
|
||||
else:
|
||||
return False</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-classes">Classes</h2>
|
||||
<dl>
|
||||
<dt id="miplearn.components.steps.drop_redundant.DropRedundantInequalitiesStep"><code class="flex name class">
|
||||
<span>class <span class="ident">DropRedundantInequalitiesStep</span></span>
|
||||
<span>(</span><span>classifier=CountingClassifier(mean=None), threshold=0.95, slack_tolerance=1e-05, check_feasibility=False, violation_tolerance=1e-05, max_iterations=3)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"><p>Component that predicts which inequalities are likely loose in the LP and removes
|
||||
them. Optionally, double checks after the problem is solved that all dropped
|
||||
inequalities were in fact redundant, and, if not, re-adds them to the problem.</p>
|
||||
<p>This component does not work on MIPs. All integrality constraints must be relaxed
|
||||
before this component is used.</p></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">class DropRedundantInequalitiesStep(Component):
|
||||
"""
|
||||
Component that predicts which inequalities are likely loose in the LP and removes
|
||||
them. Optionally, double checks after the problem is solved that all dropped
|
||||
inequalities were in fact redundant, and, if not, re-adds them to the problem.
|
||||
|
||||
This component does not work on MIPs. All integrality constraints must be relaxed
|
||||
before this component is used.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
classifier=CountingClassifier(),
|
||||
threshold=0.95,
|
||||
slack_tolerance=1e-5,
|
||||
check_feasibility=False,
|
||||
violation_tolerance=1e-5,
|
||||
max_iterations=3,
|
||||
):
|
||||
self.classifiers = {}
|
||||
self.classifier_prototype = classifier
|
||||
self.threshold = threshold
|
||||
self.slack_tolerance = slack_tolerance
|
||||
self.pool = []
|
||||
self.check_feasibility = check_feasibility
|
||||
self.violation_tolerance = violation_tolerance
|
||||
self.max_iterations = max_iterations
|
||||
self.current_iteration = 0
|
||||
|
||||
def before_solve(self, solver, instance, _):
|
||||
self.current_iteration = 0
|
||||
|
||||
logger.info("Predicting redundant LP constraints...")
|
||||
x, constraints = self._x_test(
|
||||
instance,
|
||||
constraint_ids=solver.internal_solver.get_constraint_ids(),
|
||||
)
|
||||
y = self.predict(x)
|
||||
|
||||
self.total_dropped = 0
|
||||
self.total_restored = 0
|
||||
self.total_kept = 0
|
||||
self.total_iterations = 0
|
||||
for category in y.keys():
|
||||
for i in range(len(y[category])):
|
||||
if y[category][i][0] == 1:
|
||||
cid = constraints[category][i]
|
||||
c = LazyConstraint(
|
||||
cid=cid,
|
||||
obj=solver.internal_solver.extract_constraint(cid),
|
||||
)
|
||||
self.pool += [c]
|
||||
self.total_dropped += 1
|
||||
else:
|
||||
self.total_kept += 1
|
||||
logger.info(f"Extracted {self.total_dropped} predicted constraints")
|
||||
|
||||
def after_solve(
|
||||
self,
|
||||
solver,
|
||||
instance,
|
||||
model,
|
||||
stats,
|
||||
training_data,
|
||||
):
|
||||
if "slacks" not in training_data.keys():
|
||||
training_data["slacks"] = solver.internal_solver.get_inequality_slacks()
|
||||
stats.update(
|
||||
{
|
||||
"DropRedundant: Kept": self.total_kept,
|
||||
"DropRedundant: Dropped": self.total_dropped,
|
||||
"DropRedundant: Restored": self.total_restored,
|
||||
"DropRedundant: Iterations": self.total_iterations,
|
||||
}
|
||||
)
|
||||
|
||||
def fit(self, training_instances):
|
||||
logger.debug("Extracting x and y...")
|
||||
x = self.x(training_instances)
|
||||
y = self.y(training_instances)
|
||||
logger.debug("Fitting...")
|
||||
for category in tqdm(x.keys(), desc="Fit (rlx:drop_ineq)"):
|
||||
if category not in self.classifiers:
|
||||
self.classifiers[category] = deepcopy(self.classifier_prototype)
|
||||
self.classifiers[category].fit(x[category], y[category])
|
||||
|
||||
@staticmethod
|
||||
def _x_test(instance, constraint_ids):
|
||||
x = {}
|
||||
constraints = {}
|
||||
cids = constraint_ids
|
||||
for cid in cids:
|
||||
category = instance.get_constraint_category(cid)
|
||||
if category is None:
|
||||
continue
|
||||
if category not in x:
|
||||
x[category] = []
|
||||
constraints[category] = []
|
||||
x[category] += [instance.get_constraint_features(cid)]
|
||||
constraints[category] += [cid]
|
||||
for category in x.keys():
|
||||
x[category] = np.array(x[category])
|
||||
return x, constraints
|
||||
|
||||
@staticmethod
|
||||
def _x_train(instances):
|
||||
x = {}
|
||||
for instance in tqdm(
|
||||
InstanceIterator(instances),
|
||||
desc="Extract (rlx:drop_ineq:x)",
|
||||
disable=len(instances) < 5,
|
||||
):
|
||||
for training_data in instance.training_data:
|
||||
cids = training_data["slacks"].keys()
|
||||
for cid in cids:
|
||||
category = instance.get_constraint_category(cid)
|
||||
if category is None:
|
||||
continue
|
||||
if category not in x:
|
||||
x[category] = []
|
||||
x[category] += [instance.get_constraint_features(cid)]
|
||||
for category in x.keys():
|
||||
x[category] = np.array(x[category])
|
||||
return x
|
||||
|
||||
def x(self, instances):
|
||||
return self._x_train(instances)
|
||||
|
||||
def y(self, instances):
|
||||
y = {}
|
||||
for instance in tqdm(
|
||||
InstanceIterator(instances),
|
||||
desc="Extract (rlx:drop_ineq:y)",
|
||||
disable=len(instances) < 5,
|
||||
):
|
||||
for training_data in instance.training_data:
|
||||
for (cid, slack) in training_data["slacks"].items():
|
||||
category = instance.get_constraint_category(cid)
|
||||
if category is None:
|
||||
continue
|
||||
if category not in y:
|
||||
y[category] = []
|
||||
if slack > self.slack_tolerance:
|
||||
y[category] += [[1]]
|
||||
else:
|
||||
y[category] += [[0]]
|
||||
return y
|
||||
|
||||
def predict(self, x):
|
||||
y = {}
|
||||
for (category, x_cat) in x.items():
|
||||
if category not in self.classifiers:
|
||||
continue
|
||||
y[category] = []
|
||||
x_cat = np.array(x_cat)
|
||||
proba = self.classifiers[category].predict_proba(x_cat)
|
||||
for i in range(len(proba)):
|
||||
if proba[i][1] >= self.threshold:
|
||||
y[category] += [[1]]
|
||||
else:
|
||||
y[category] += [[0]]
|
||||
return y
|
||||
|
||||
def evaluate(self, instance):
|
||||
x = self.x([instance])
|
||||
y_true = self.y([instance])
|
||||
y_pred = self.predict(x)
|
||||
tp, tn, fp, fn = 0, 0, 0, 0
|
||||
for category in y_true.keys():
|
||||
for i in range(len(y_true[category])):
|
||||
if y_pred[category][i][0] == 1:
|
||||
if y_true[category][i][0] == 1:
|
||||
tp += 1
|
||||
else:
|
||||
fp += 1
|
||||
else:
|
||||
if y_true[category][i][0] == 1:
|
||||
fn += 1
|
||||
else:
|
||||
tn += 1
|
||||
return classifier_evaluation_dict(tp, tn, fp, fn)
|
||||
|
||||
def iteration_cb(self, solver, instance, model):
|
||||
if not self.check_feasibility:
|
||||
return False
|
||||
if self.current_iteration >= self.max_iterations:
|
||||
return False
|
||||
self.current_iteration += 1
|
||||
logger.debug("Checking that dropped constraints are satisfied...")
|
||||
constraints_to_add = []
|
||||
for c in self.pool:
|
||||
if not solver.internal_solver.is_constraint_satisfied(
|
||||
c.obj,
|
||||
self.violation_tolerance,
|
||||
):
|
||||
constraints_to_add.append(c)
|
||||
for c in constraints_to_add:
|
||||
self.pool.remove(c)
|
||||
solver.internal_solver.add_constraint(c.obj)
|
||||
if len(constraints_to_add) > 0:
|
||||
self.total_restored += len(constraints_to_add)
|
||||
logger.info(
|
||||
"%8d constraints %8d in the pool"
|
||||
% (len(constraints_to_add), len(self.pool))
|
||||
)
|
||||
self.total_iterations += 1
|
||||
return True
|
||||
else:
|
||||
return False</code></pre>
|
||||
</details>
|
||||
<h3>Ancestors</h3>
|
||||
<ul class="hlist">
|
||||
<li><a title="miplearn.components.component.Component" href="../component.html#miplearn.components.component.Component">Component</a></li>
|
||||
<li>abc.ABC</li>
|
||||
</ul>
|
||||
<h3>Methods</h3>
|
||||
<dl>
|
||||
<dt id="miplearn.components.steps.drop_redundant.DropRedundantInequalitiesStep.evaluate"><code class="name flex">
|
||||
<span>def <span class="ident">evaluate</span></span>(<span>self, instance)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def evaluate(self, instance):
|
||||
x = self.x([instance])
|
||||
y_true = self.y([instance])
|
||||
y_pred = self.predict(x)
|
||||
tp, tn, fp, fn = 0, 0, 0, 0
|
||||
for category in y_true.keys():
|
||||
for i in range(len(y_true[category])):
|
||||
if y_pred[category][i][0] == 1:
|
||||
if y_true[category][i][0] == 1:
|
||||
tp += 1
|
||||
else:
|
||||
fp += 1
|
||||
else:
|
||||
if y_true[category][i][0] == 1:
|
||||
fn += 1
|
||||
else:
|
||||
tn += 1
|
||||
return classifier_evaluation_dict(tp, tn, fp, fn)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.components.steps.drop_redundant.DropRedundantInequalitiesStep.fit"><code class="name flex">
|
||||
<span>def <span class="ident">fit</span></span>(<span>self, training_instances)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def fit(self, training_instances):
|
||||
logger.debug("Extracting x and y...")
|
||||
x = self.x(training_instances)
|
||||
y = self.y(training_instances)
|
||||
logger.debug("Fitting...")
|
||||
for category in tqdm(x.keys(), desc="Fit (rlx:drop_ineq)"):
|
||||
if category not in self.classifiers:
|
||||
self.classifiers[category] = deepcopy(self.classifier_prototype)
|
||||
self.classifiers[category].fit(x[category], y[category])</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.components.steps.drop_redundant.DropRedundantInequalitiesStep.predict"><code class="name flex">
|
||||
<span>def <span class="ident">predict</span></span>(<span>self, x)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def predict(self, x):
|
||||
y = {}
|
||||
for (category, x_cat) in x.items():
|
||||
if category not in self.classifiers:
|
||||
continue
|
||||
y[category] = []
|
||||
x_cat = np.array(x_cat)
|
||||
proba = self.classifiers[category].predict_proba(x_cat)
|
||||
for i in range(len(proba)):
|
||||
if proba[i][1] >= self.threshold:
|
||||
y[category] += [[1]]
|
||||
else:
|
||||
y[category] += [[0]]
|
||||
return y</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.components.steps.drop_redundant.DropRedundantInequalitiesStep.x"><code class="name flex">
|
||||
<span>def <span class="ident">x</span></span>(<span>self, instances)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def x(self, instances):
|
||||
return self._x_train(instances)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.components.steps.drop_redundant.DropRedundantInequalitiesStep.y"><code class="name flex">
|
||||
<span>def <span class="ident">y</span></span>(<span>self, instances)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def y(self, instances):
|
||||
y = {}
|
||||
for instance in tqdm(
|
||||
InstanceIterator(instances),
|
||||
desc="Extract (rlx:drop_ineq:y)",
|
||||
disable=len(instances) < 5,
|
||||
):
|
||||
for training_data in instance.training_data:
|
||||
for (cid, slack) in training_data["slacks"].items():
|
||||
category = instance.get_constraint_category(cid)
|
||||
if category is None:
|
||||
continue
|
||||
if category not in y:
|
||||
y[category] = []
|
||||
if slack > self.slack_tolerance:
|
||||
y[category] += [[1]]
|
||||
else:
|
||||
y[category] += [[0]]
|
||||
return y</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>Inherited members</h3>
|
||||
<ul class="hlist">
|
||||
<li><code><b><a title="miplearn.components.component.Component" href="../component.html#miplearn.components.component.Component">Component</a></b></code>:
|
||||
<ul class="hlist">
|
||||
<li><code><a title="miplearn.components.component.Component.after_solve" href="../component.html#miplearn.components.component.Component.after_solve">after_solve</a></code></li>
|
||||
<li><code><a title="miplearn.components.component.Component.before_solve" href="../component.html#miplearn.components.component.Component.before_solve">before_solve</a></code></li>
|
||||
<li><code><a title="miplearn.components.component.Component.iteration_cb" href="../component.html#miplearn.components.component.Component.iteration_cb">iteration_cb</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.components.steps" href="index.html">miplearn.components.steps</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-classes">Classes</a></h3>
|
||||
<ul>
|
||||
<li>
|
||||
<h4><code><a title="miplearn.components.steps.drop_redundant.DropRedundantInequalitiesStep" href="#miplearn.components.steps.drop_redundant.DropRedundantInequalitiesStep">DropRedundantInequalitiesStep</a></code></h4>
|
||||
<ul class="">
|
||||
<li><code><a title="miplearn.components.steps.drop_redundant.DropRedundantInequalitiesStep.evaluate" href="#miplearn.components.steps.drop_redundant.DropRedundantInequalitiesStep.evaluate">evaluate</a></code></li>
|
||||
<li><code><a title="miplearn.components.steps.drop_redundant.DropRedundantInequalitiesStep.fit" href="#miplearn.components.steps.drop_redundant.DropRedundantInequalitiesStep.fit">fit</a></code></li>
|
||||
<li><code><a title="miplearn.components.steps.drop_redundant.DropRedundantInequalitiesStep.predict" href="#miplearn.components.steps.drop_redundant.DropRedundantInequalitiesStep.predict">predict</a></code></li>
|
||||
<li><code><a title="miplearn.components.steps.drop_redundant.DropRedundantInequalitiesStep.x" href="#miplearn.components.steps.drop_redundant.DropRedundantInequalitiesStep.x">x</a></code></li>
|
||||
<li><code><a title="miplearn.components.steps.drop_redundant.DropRedundantInequalitiesStep.y" href="#miplearn.components.steps.drop_redundant.DropRedundantInequalitiesStep.y">y</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</main>
|
||||
<footer id="footer">
|
||||
<p>Generated by <a href="https://pdoc3.github.io/pdoc"><cite>pdoc</cite> 0.7.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>
|
||||
80
0.2/api/miplearn/components/steps/index.html
Normal file
80
0.2/api/miplearn/components/steps/index.html
Normal file
@@ -0,0 +1,80 @@
|
||||
<!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.components.steps 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.components.steps</code></h1>
|
||||
</header>
|
||||
<section id="section-intro">
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-submodules">Sub-modules</h2>
|
||||
<dl>
|
||||
<dt><code class="name"><a title="miplearn.components.steps.convert_tight" href="convert_tight.html">miplearn.components.steps.convert_tight</a></code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
</dd>
|
||||
<dt><code class="name"><a title="miplearn.components.steps.drop_redundant" href="drop_redundant.html">miplearn.components.steps.drop_redundant</a></code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
</dd>
|
||||
<dt><code class="name"><a title="miplearn.components.steps.relax_integrality" href="relax_integrality.html">miplearn.components.steps.relax_integrality</a></code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
</dd>
|
||||
<dt><code class="name"><a title="miplearn.components.steps.tests" href="tests/index.html">miplearn.components.steps.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.components" href="../index.html">miplearn.components</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-submodules">Sub-modules</a></h3>
|
||||
<ul>
|
||||
<li><code><a title="miplearn.components.steps.convert_tight" href="convert_tight.html">miplearn.components.steps.convert_tight</a></code></li>
|
||||
<li><code><a title="miplearn.components.steps.drop_redundant" href="drop_redundant.html">miplearn.components.steps.drop_redundant</a></code></li>
|
||||
<li><code><a title="miplearn.components.steps.relax_integrality" href="relax_integrality.html">miplearn.components.steps.relax_integrality</a></code></li>
|
||||
<li><code><a title="miplearn.components.steps.tests" href="tests/index.html">miplearn.components.steps.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>
|
||||
142
0.2/api/miplearn/components/steps/relax_integrality.html
Normal file
142
0.2/api/miplearn/components/steps/relax_integrality.html
Normal file
@@ -0,0 +1,142 @@
|
||||
<!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.components.steps.relax_integrality 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.components.steps.relax_integrality</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.components.component import Component
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class RelaxIntegralityStep(Component):
|
||||
"""
|
||||
Component that relaxes all integrality constraints before the problem is solved.
|
||||
"""
|
||||
|
||||
def before_solve(self, solver, instance, _):
|
||||
logger.info("Relaxing integrality...")
|
||||
solver.internal_solver.relax()
|
||||
|
||||
def after_solve(
|
||||
self,
|
||||
solver,
|
||||
instance,
|
||||
model,
|
||||
stats,
|
||||
training_data,
|
||||
):
|
||||
return</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-classes">Classes</h2>
|
||||
<dl>
|
||||
<dt id="miplearn.components.steps.relax_integrality.RelaxIntegralityStep"><code class="flex name class">
|
||||
<span>class <span class="ident">RelaxIntegralityStep</span></span>
|
||||
<span>(</span><span>*args, **kwargs)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"><p>Component that relaxes all integrality constraints before the problem is solved.</p></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">class RelaxIntegralityStep(Component):
|
||||
"""
|
||||
Component that relaxes all integrality constraints before the problem is solved.
|
||||
"""
|
||||
|
||||
def before_solve(self, solver, instance, _):
|
||||
logger.info("Relaxing integrality...")
|
||||
solver.internal_solver.relax()
|
||||
|
||||
def after_solve(
|
||||
self,
|
||||
solver,
|
||||
instance,
|
||||
model,
|
||||
stats,
|
||||
training_data,
|
||||
):
|
||||
return</code></pre>
|
||||
</details>
|
||||
<h3>Ancestors</h3>
|
||||
<ul class="hlist">
|
||||
<li><a title="miplearn.components.component.Component" href="../component.html#miplearn.components.component.Component">Component</a></li>
|
||||
<li>abc.ABC</li>
|
||||
</ul>
|
||||
<h3>Inherited members</h3>
|
||||
<ul class="hlist">
|
||||
<li><code><b><a title="miplearn.components.component.Component" href="../component.html#miplearn.components.component.Component">Component</a></b></code>:
|
||||
<ul class="hlist">
|
||||
<li><code><a title="miplearn.components.component.Component.after_solve" href="../component.html#miplearn.components.component.Component.after_solve">after_solve</a></code></li>
|
||||
<li><code><a title="miplearn.components.component.Component.before_solve" href="../component.html#miplearn.components.component.Component.before_solve">before_solve</a></code></li>
|
||||
<li><code><a title="miplearn.components.component.Component.iteration_cb" href="../component.html#miplearn.components.component.Component.iteration_cb">iteration_cb</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.components.steps" href="index.html">miplearn.components.steps</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-classes">Classes</a></h3>
|
||||
<ul>
|
||||
<li>
|
||||
<h4><code><a title="miplearn.components.steps.relax_integrality.RelaxIntegralityStep" href="#miplearn.components.steps.relax_integrality.RelaxIntegralityStep">RelaxIntegralityStep</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>
|
||||
70
0.2/api/miplearn/components/steps/tests/index.html
Normal file
70
0.2/api/miplearn/components/steps/tests/index.html
Normal file
@@ -0,0 +1,70 @@
|
||||
<!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.components.steps.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.components.steps.tests</code></h1>
|
||||
</header>
|
||||
<section id="section-intro">
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-submodules">Sub-modules</h2>
|
||||
<dl>
|
||||
<dt><code class="name"><a title="miplearn.components.steps.tests.test_convert_tight" href="test_convert_tight.html">miplearn.components.steps.tests.test_convert_tight</a></code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
</dd>
|
||||
<dt><code class="name"><a title="miplearn.components.steps.tests.test_drop_redundant" href="test_drop_redundant.html">miplearn.components.steps.tests.test_drop_redundant</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.components.steps" href="../index.html">miplearn.components.steps</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-submodules">Sub-modules</a></h3>
|
||||
<ul>
|
||||
<li><code><a title="miplearn.components.steps.tests.test_convert_tight" href="test_convert_tight.html">miplearn.components.steps.tests.test_convert_tight</a></code></li>
|
||||
<li><code><a title="miplearn.components.steps.tests.test_drop_redundant" href="test_drop_redundant.html">miplearn.components.steps.tests.test_drop_redundant</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>
|
||||
385
0.2/api/miplearn/components/steps/tests/test_convert_tight.html
Normal file
385
0.2/api/miplearn/components/steps/tests/test_convert_tight.html
Normal file
@@ -0,0 +1,385 @@
|
||||
<!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.components.steps.tests.test_convert_tight 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.components.steps.tests.test_convert_tight</code></h1>
|
||||
</header>
|
||||
<section id="section-intro">
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">from unittest.mock import Mock
|
||||
|
||||
from miplearn.classifiers import Classifier
|
||||
from miplearn.components.steps.convert_tight import ConvertTightIneqsIntoEqsStep
|
||||
from miplearn.components.steps.relax_integrality import RelaxIntegralityStep
|
||||
from miplearn.instance import Instance
|
||||
from miplearn.problems.knapsack import GurobiKnapsackInstance
|
||||
from miplearn.solvers.gurobi import GurobiSolver
|
||||
from miplearn.solvers.learning import LearningSolver
|
||||
|
||||
|
||||
def test_convert_tight_usage():
|
||||
instance = GurobiKnapsackInstance(
|
||||
weights=[3.0, 5.0, 10.0],
|
||||
prices=[1.0, 1.0, 1.0],
|
||||
capacity=16.0,
|
||||
)
|
||||
solver = LearningSolver(
|
||||
solver=GurobiSolver,
|
||||
components=[
|
||||
RelaxIntegralityStep(),
|
||||
ConvertTightIneqsIntoEqsStep(),
|
||||
],
|
||||
)
|
||||
|
||||
# Solve original problem
|
||||
stats = solver.solve(instance)
|
||||
original_upper_bound = stats["Upper bound"]
|
||||
|
||||
# Should collect training data
|
||||
assert instance.training_data[0]["slacks"]["eq_capacity"] == 0.0
|
||||
|
||||
# Fit and resolve
|
||||
solver.fit([instance])
|
||||
stats = solver.solve(instance)
|
||||
|
||||
# Objective value should be the same
|
||||
assert stats["Upper bound"] == original_upper_bound
|
||||
assert stats["ConvertTight: Inf iterations"] == 0
|
||||
assert stats["ConvertTight: Subopt iterations"] == 0
|
||||
|
||||
|
||||
class SampleInstance(Instance):
|
||||
def to_model(self):
|
||||
import gurobipy as grb
|
||||
|
||||
m = grb.Model("model")
|
||||
x1 = m.addVar(name="x1")
|
||||
x2 = m.addVar(name="x2")
|
||||
m.setObjective(x1 + 2 * x2, grb.GRB.MAXIMIZE)
|
||||
m.addConstr(x1 <= 2, name="c1")
|
||||
m.addConstr(x2 <= 2, name="c2")
|
||||
m.addConstr(x1 + x2 <= 3, name="c2")
|
||||
return m
|
||||
|
||||
|
||||
def test_convert_tight_infeasibility():
|
||||
comp = ConvertTightIneqsIntoEqsStep()
|
||||
comp.classifiers = {
|
||||
"c1": Mock(spec=Classifier),
|
||||
"c2": Mock(spec=Classifier),
|
||||
"c3": Mock(spec=Classifier),
|
||||
}
|
||||
comp.classifiers["c1"].predict_proba = Mock(return_value=[[0, 1]])
|
||||
comp.classifiers["c2"].predict_proba = Mock(return_value=[[0, 1]])
|
||||
comp.classifiers["c3"].predict_proba = Mock(return_value=[[1, 0]])
|
||||
|
||||
solver = LearningSolver(
|
||||
solver=GurobiSolver,
|
||||
components=[comp],
|
||||
solve_lp_first=False,
|
||||
)
|
||||
instance = SampleInstance()
|
||||
stats = solver.solve(instance)
|
||||
assert stats["Upper bound"] == 5.0
|
||||
assert stats["ConvertTight: Inf iterations"] == 1
|
||||
assert stats["ConvertTight: Subopt iterations"] == 0
|
||||
|
||||
|
||||
def test_convert_tight_suboptimality():
|
||||
comp = ConvertTightIneqsIntoEqsStep(check_optimality=True)
|
||||
comp.classifiers = {
|
||||
"c1": Mock(spec=Classifier),
|
||||
"c2": Mock(spec=Classifier),
|
||||
"c3": Mock(spec=Classifier),
|
||||
}
|
||||
comp.classifiers["c1"].predict_proba = Mock(return_value=[[0, 1]])
|
||||
comp.classifiers["c2"].predict_proba = Mock(return_value=[[1, 0]])
|
||||
comp.classifiers["c3"].predict_proba = Mock(return_value=[[0, 1]])
|
||||
|
||||
solver = LearningSolver(
|
||||
solver=GurobiSolver,
|
||||
components=[comp],
|
||||
solve_lp_first=False,
|
||||
)
|
||||
instance = SampleInstance()
|
||||
stats = solver.solve(instance)
|
||||
assert stats["Upper bound"] == 5.0
|
||||
assert stats["ConvertTight: Inf iterations"] == 0
|
||||
assert stats["ConvertTight: Subopt iterations"] == 1
|
||||
|
||||
|
||||
def test_convert_tight_optimal():
|
||||
comp = ConvertTightIneqsIntoEqsStep()
|
||||
comp.classifiers = {
|
||||
"c1": Mock(spec=Classifier),
|
||||
"c2": Mock(spec=Classifier),
|
||||
"c3": Mock(spec=Classifier),
|
||||
}
|
||||
comp.classifiers["c1"].predict_proba = Mock(return_value=[[1, 0]])
|
||||
comp.classifiers["c2"].predict_proba = Mock(return_value=[[0, 1]])
|
||||
comp.classifiers["c3"].predict_proba = Mock(return_value=[[0, 1]])
|
||||
|
||||
solver = LearningSolver(
|
||||
solver=GurobiSolver,
|
||||
components=[comp],
|
||||
solve_lp_first=False,
|
||||
)
|
||||
instance = SampleInstance()
|
||||
stats = solver.solve(instance)
|
||||
assert stats["Upper bound"] == 5.0
|
||||
assert stats["ConvertTight: Inf iterations"] == 0
|
||||
assert stats["ConvertTight: Subopt iterations"] == 0</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-functions">Functions</h2>
|
||||
<dl>
|
||||
<dt id="miplearn.components.steps.tests.test_convert_tight.test_convert_tight_infeasibility"><code class="name flex">
|
||||
<span>def <span class="ident">test_convert_tight_infeasibility</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_convert_tight_infeasibility():
|
||||
comp = ConvertTightIneqsIntoEqsStep()
|
||||
comp.classifiers = {
|
||||
"c1": Mock(spec=Classifier),
|
||||
"c2": Mock(spec=Classifier),
|
||||
"c3": Mock(spec=Classifier),
|
||||
}
|
||||
comp.classifiers["c1"].predict_proba = Mock(return_value=[[0, 1]])
|
||||
comp.classifiers["c2"].predict_proba = Mock(return_value=[[0, 1]])
|
||||
comp.classifiers["c3"].predict_proba = Mock(return_value=[[1, 0]])
|
||||
|
||||
solver = LearningSolver(
|
||||
solver=GurobiSolver,
|
||||
components=[comp],
|
||||
solve_lp_first=False,
|
||||
)
|
||||
instance = SampleInstance()
|
||||
stats = solver.solve(instance)
|
||||
assert stats["Upper bound"] == 5.0
|
||||
assert stats["ConvertTight: Inf iterations"] == 1
|
||||
assert stats["ConvertTight: Subopt iterations"] == 0</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.components.steps.tests.test_convert_tight.test_convert_tight_optimal"><code class="name flex">
|
||||
<span>def <span class="ident">test_convert_tight_optimal</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_convert_tight_optimal():
|
||||
comp = ConvertTightIneqsIntoEqsStep()
|
||||
comp.classifiers = {
|
||||
"c1": Mock(spec=Classifier),
|
||||
"c2": Mock(spec=Classifier),
|
||||
"c3": Mock(spec=Classifier),
|
||||
}
|
||||
comp.classifiers["c1"].predict_proba = Mock(return_value=[[1, 0]])
|
||||
comp.classifiers["c2"].predict_proba = Mock(return_value=[[0, 1]])
|
||||
comp.classifiers["c3"].predict_proba = Mock(return_value=[[0, 1]])
|
||||
|
||||
solver = LearningSolver(
|
||||
solver=GurobiSolver,
|
||||
components=[comp],
|
||||
solve_lp_first=False,
|
||||
)
|
||||
instance = SampleInstance()
|
||||
stats = solver.solve(instance)
|
||||
assert stats["Upper bound"] == 5.0
|
||||
assert stats["ConvertTight: Inf iterations"] == 0
|
||||
assert stats["ConvertTight: Subopt iterations"] == 0</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.components.steps.tests.test_convert_tight.test_convert_tight_suboptimality"><code class="name flex">
|
||||
<span>def <span class="ident">test_convert_tight_suboptimality</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_convert_tight_suboptimality():
|
||||
comp = ConvertTightIneqsIntoEqsStep(check_optimality=True)
|
||||
comp.classifiers = {
|
||||
"c1": Mock(spec=Classifier),
|
||||
"c2": Mock(spec=Classifier),
|
||||
"c3": Mock(spec=Classifier),
|
||||
}
|
||||
comp.classifiers["c1"].predict_proba = Mock(return_value=[[0, 1]])
|
||||
comp.classifiers["c2"].predict_proba = Mock(return_value=[[1, 0]])
|
||||
comp.classifiers["c3"].predict_proba = Mock(return_value=[[0, 1]])
|
||||
|
||||
solver = LearningSolver(
|
||||
solver=GurobiSolver,
|
||||
components=[comp],
|
||||
solve_lp_first=False,
|
||||
)
|
||||
instance = SampleInstance()
|
||||
stats = solver.solve(instance)
|
||||
assert stats["Upper bound"] == 5.0
|
||||
assert stats["ConvertTight: Inf iterations"] == 0
|
||||
assert stats["ConvertTight: Subopt iterations"] == 1</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.components.steps.tests.test_convert_tight.test_convert_tight_usage"><code class="name flex">
|
||||
<span>def <span class="ident">test_convert_tight_usage</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_convert_tight_usage():
|
||||
instance = GurobiKnapsackInstance(
|
||||
weights=[3.0, 5.0, 10.0],
|
||||
prices=[1.0, 1.0, 1.0],
|
||||
capacity=16.0,
|
||||
)
|
||||
solver = LearningSolver(
|
||||
solver=GurobiSolver,
|
||||
components=[
|
||||
RelaxIntegralityStep(),
|
||||
ConvertTightIneqsIntoEqsStep(),
|
||||
],
|
||||
)
|
||||
|
||||
# Solve original problem
|
||||
stats = solver.solve(instance)
|
||||
original_upper_bound = stats["Upper bound"]
|
||||
|
||||
# Should collect training data
|
||||
assert instance.training_data[0]["slacks"]["eq_capacity"] == 0.0
|
||||
|
||||
# Fit and resolve
|
||||
solver.fit([instance])
|
||||
stats = solver.solve(instance)
|
||||
|
||||
# Objective value should be the same
|
||||
assert stats["Upper bound"] == original_upper_bound
|
||||
assert stats["ConvertTight: Inf iterations"] == 0
|
||||
assert stats["ConvertTight: Subopt iterations"] == 0</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-classes">Classes</h2>
|
||||
<dl>
|
||||
<dt id="miplearn.components.steps.tests.test_convert_tight.SampleInstance"><code class="flex name class">
|
||||
<span>class <span class="ident">SampleInstance</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 SampleInstance(Instance):
|
||||
def to_model(self):
|
||||
import gurobipy as grb
|
||||
|
||||
m = grb.Model("model")
|
||||
x1 = m.addVar(name="x1")
|
||||
x2 = m.addVar(name="x2")
|
||||
m.setObjective(x1 + 2 * x2, grb.GRB.MAXIMIZE)
|
||||
m.addConstr(x1 <= 2, name="c1")
|
||||
m.addConstr(x2 <= 2, name="c2")
|
||||
m.addConstr(x1 + x2 <= 3, name="c2")
|
||||
return m</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.components.steps.tests" href="index.html">miplearn.components.steps.tests</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-functions">Functions</a></h3>
|
||||
<ul class="">
|
||||
<li><code><a title="miplearn.components.steps.tests.test_convert_tight.test_convert_tight_infeasibility" href="#miplearn.components.steps.tests.test_convert_tight.test_convert_tight_infeasibility">test_convert_tight_infeasibility</a></code></li>
|
||||
<li><code><a title="miplearn.components.steps.tests.test_convert_tight.test_convert_tight_optimal" href="#miplearn.components.steps.tests.test_convert_tight.test_convert_tight_optimal">test_convert_tight_optimal</a></code></li>
|
||||
<li><code><a title="miplearn.components.steps.tests.test_convert_tight.test_convert_tight_suboptimality" href="#miplearn.components.steps.tests.test_convert_tight.test_convert_tight_suboptimality">test_convert_tight_suboptimality</a></code></li>
|
||||
<li><code><a title="miplearn.components.steps.tests.test_convert_tight.test_convert_tight_usage" href="#miplearn.components.steps.tests.test_convert_tight.test_convert_tight_usage">test_convert_tight_usage</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-classes">Classes</a></h3>
|
||||
<ul>
|
||||
<li>
|
||||
<h4><code><a title="miplearn.components.steps.tests.test_convert_tight.SampleInstance" href="#miplearn.components.steps.tests.test_convert_tight.SampleInstance">SampleInstance</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>
|
||||
764
0.2/api/miplearn/components/steps/tests/test_drop_redundant.html
Normal file
764
0.2/api/miplearn/components/steps/tests/test_drop_redundant.html
Normal file
@@ -0,0 +1,764 @@
|
||||
<!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.components.steps.tests.test_drop_redundant 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.components.steps.tests.test_drop_redundant</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 unittest.mock import Mock, call
|
||||
|
||||
import numpy as np
|
||||
|
||||
from miplearn.classifiers import Classifier
|
||||
from miplearn.components.relaxation import DropRedundantInequalitiesStep
|
||||
from miplearn.instance import Instance
|
||||
from miplearn.solvers.internal import InternalSolver
|
||||
from miplearn.solvers.learning import LearningSolver
|
||||
|
||||
|
||||
def _setup():
|
||||
solver = Mock(spec=LearningSolver)
|
||||
|
||||
internal = solver.internal_solver = Mock(spec=InternalSolver)
|
||||
internal.get_constraint_ids = Mock(return_value=["c1", "c2", "c3", "c4"])
|
||||
internal.get_inequality_slacks = Mock(
|
||||
side_effect=lambda: {
|
||||
"c1": 0.5,
|
||||
"c2": 0.0,
|
||||
"c3": 0.0,
|
||||
"c4": 1.4,
|
||||
}
|
||||
)
|
||||
internal.extract_constraint = Mock(side_effect=lambda cid: "<%s>" % cid)
|
||||
internal.is_constraint_satisfied = Mock(return_value=False)
|
||||
|
||||
instance = Mock(spec=Instance)
|
||||
instance.get_constraint_features = Mock(
|
||||
side_effect=lambda cid: {
|
||||
"c2": np.array([1.0, 0.0]),
|
||||
"c3": np.array([0.5, 0.5]),
|
||||
"c4": np.array([1.0]),
|
||||
}[cid]
|
||||
)
|
||||
instance.get_constraint_category = Mock(
|
||||
side_effect=lambda cid: {
|
||||
"c1": None,
|
||||
"c2": "type-a",
|
||||
"c3": "type-a",
|
||||
"c4": "type-b",
|
||||
}[cid]
|
||||
)
|
||||
|
||||
classifiers = {
|
||||
"type-a": Mock(spec=Classifier),
|
||||
"type-b": Mock(spec=Classifier),
|
||||
}
|
||||
classifiers["type-a"].predict_proba = Mock(
|
||||
return_value=np.array(
|
||||
[
|
||||
[0.20, 0.80],
|
||||
[0.05, 0.95],
|
||||
]
|
||||
)
|
||||
)
|
||||
classifiers["type-b"].predict_proba = Mock(
|
||||
return_value=np.array(
|
||||
[
|
||||
[0.02, 0.98],
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
return solver, internal, instance, classifiers
|
||||
|
||||
|
||||
def test_drop_redundant():
|
||||
solver, internal, instance, classifiers = _setup()
|
||||
|
||||
component = DropRedundantInequalitiesStep()
|
||||
component.classifiers = classifiers
|
||||
|
||||
# LearningSolver calls before_solve
|
||||
component.before_solve(solver, instance, None)
|
||||
|
||||
# Should query list of constraints
|
||||
internal.get_constraint_ids.assert_called_once()
|
||||
|
||||
# Should query category and features for each constraint in the model
|
||||
assert instance.get_constraint_category.call_count == 4
|
||||
instance.get_constraint_category.assert_has_calls(
|
||||
[
|
||||
call("c1"),
|
||||
call("c2"),
|
||||
call("c3"),
|
||||
call("c4"),
|
||||
]
|
||||
)
|
||||
|
||||
# For constraint with non-null categories, should ask for features
|
||||
assert instance.get_constraint_features.call_count == 3
|
||||
instance.get_constraint_features.assert_has_calls(
|
||||
[
|
||||
call("c2"),
|
||||
call("c3"),
|
||||
call("c4"),
|
||||
]
|
||||
)
|
||||
|
||||
# Should ask ML to predict whether constraint should be removed
|
||||
type_a_actual = component.classifiers["type-a"].predict_proba.call_args[0][0]
|
||||
type_b_actual = component.classifiers["type-b"].predict_proba.call_args[0][0]
|
||||
np.testing.assert_array_equal(type_a_actual, np.array([[1.0, 0.0], [0.5, 0.5]]))
|
||||
np.testing.assert_array_equal(type_b_actual, np.array([[1.0]]))
|
||||
|
||||
# Should ask internal solver to remove constraints predicted as redundant
|
||||
assert internal.extract_constraint.call_count == 2
|
||||
internal.extract_constraint.assert_has_calls(
|
||||
[
|
||||
call("c3"),
|
||||
call("c4"),
|
||||
]
|
||||
)
|
||||
|
||||
# LearningSolver calls after_solve
|
||||
training_data = {}
|
||||
component.after_solve(solver, instance, None, {}, training_data)
|
||||
|
||||
# Should query slack for all inequalities
|
||||
internal.get_inequality_slacks.assert_called_once()
|
||||
|
||||
# Should store constraint slacks in instance object
|
||||
assert training_data["slacks"] == {
|
||||
"c1": 0.5,
|
||||
"c2": 0.0,
|
||||
"c3": 0.0,
|
||||
"c4": 1.4,
|
||||
}
|
||||
|
||||
|
||||
def test_drop_redundant_with_check_feasibility():
|
||||
solver, internal, instance, classifiers = _setup()
|
||||
|
||||
component = DropRedundantInequalitiesStep(
|
||||
check_feasibility=True,
|
||||
violation_tolerance=1e-3,
|
||||
)
|
||||
component.classifiers = classifiers
|
||||
|
||||
# LearningSolver call before_solve
|
||||
component.before_solve(solver, instance, None)
|
||||
|
||||
# Assert constraints are extracted
|
||||
assert internal.extract_constraint.call_count == 2
|
||||
internal.extract_constraint.assert_has_calls(
|
||||
[
|
||||
call("c3"),
|
||||
call("c4"),
|
||||
]
|
||||
)
|
||||
|
||||
# LearningSolver calls iteration_cb (first time)
|
||||
should_repeat = component.iteration_cb(solver, instance, None)
|
||||
|
||||
# Should ask LearningSolver to repeat
|
||||
assert should_repeat
|
||||
|
||||
# Should ask solver if removed constraints are satisfied (mock always returns false)
|
||||
internal.is_constraint_satisfied.assert_has_calls(
|
||||
[
|
||||
call("<c3>", 1e-3),
|
||||
call("<c4>", 1e-3),
|
||||
]
|
||||
)
|
||||
|
||||
# Should add constraints back to LP relaxation
|
||||
internal.add_constraint.assert_has_calls([call("<c3>"), call("<c4>")])
|
||||
|
||||
# LearningSolver calls iteration_cb (second time)
|
||||
should_repeat = component.iteration_cb(solver, instance, None)
|
||||
assert not should_repeat
|
||||
|
||||
|
||||
def test_x_y_fit_predict_evaluate():
|
||||
instances = [Mock(spec=Instance), Mock(spec=Instance)]
|
||||
component = DropRedundantInequalitiesStep(slack_tolerance=0.05, threshold=0.80)
|
||||
component.classifiers = {
|
||||
"type-a": Mock(spec=Classifier),
|
||||
"type-b": Mock(spec=Classifier),
|
||||
}
|
||||
component.classifiers["type-a"].predict_proba = Mock(
|
||||
return_value=[
|
||||
np.array([0.20, 0.80]),
|
||||
]
|
||||
)
|
||||
component.classifiers["type-b"].predict_proba = Mock(
|
||||
return_value=np.array(
|
||||
[
|
||||
[0.50, 0.50],
|
||||
[0.05, 0.95],
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
# First mock instance
|
||||
instances[0].training_data = [
|
||||
{
|
||||
"slacks": {
|
||||
"c1": 0.00,
|
||||
"c2": 0.05,
|
||||
"c3": 0.00,
|
||||
"c4": 30.0,
|
||||
}
|
||||
}
|
||||
]
|
||||
instances[0].get_constraint_category = Mock(
|
||||
side_effect=lambda cid: {
|
||||
"c1": None,
|
||||
"c2": "type-a",
|
||||
"c3": "type-a",
|
||||
"c4": "type-b",
|
||||
}[cid]
|
||||
)
|
||||
instances[0].get_constraint_features = Mock(
|
||||
side_effect=lambda cid: {
|
||||
"c2": np.array([1.0, 0.0]),
|
||||
"c3": np.array([0.5, 0.5]),
|
||||
"c4": np.array([1.0]),
|
||||
}[cid]
|
||||
)
|
||||
|
||||
# Second mock instance
|
||||
instances[1].training_data = [
|
||||
{
|
||||
"slacks": {
|
||||
"c1": 0.00,
|
||||
"c3": 0.30,
|
||||
"c4": 0.00,
|
||||
"c5": 0.00,
|
||||
}
|
||||
}
|
||||
]
|
||||
instances[1].get_constraint_category = Mock(
|
||||
side_effect=lambda cid: {
|
||||
"c1": None,
|
||||
"c3": "type-a",
|
||||
"c4": "type-b",
|
||||
"c5": "type-b",
|
||||
}[cid]
|
||||
)
|
||||
instances[1].get_constraint_features = Mock(
|
||||
side_effect=lambda cid: {
|
||||
"c3": np.array([0.3, 0.4]),
|
||||
"c4": np.array([0.7]),
|
||||
"c5": np.array([0.8]),
|
||||
}[cid]
|
||||
)
|
||||
|
||||
expected_x = {
|
||||
"type-a": np.array(
|
||||
[
|
||||
[1.0, 0.0],
|
||||
[0.5, 0.5],
|
||||
[0.3, 0.4],
|
||||
]
|
||||
),
|
||||
"type-b": np.array(
|
||||
[
|
||||
[1.0],
|
||||
[0.7],
|
||||
[0.8],
|
||||
]
|
||||
),
|
||||
}
|
||||
expected_y = {
|
||||
"type-a": np.array([[0], [0], [1]]),
|
||||
"type-b": np.array([[1], [0], [0]]),
|
||||
}
|
||||
|
||||
# Should build X and Y matrices correctly
|
||||
actual_x = component.x(instances)
|
||||
actual_y = component.y(instances)
|
||||
for category in ["type-a", "type-b"]:
|
||||
np.testing.assert_array_equal(actual_x[category], expected_x[category])
|
||||
np.testing.assert_array_equal(actual_y[category], expected_y[category])
|
||||
|
||||
# Should pass along X and Y matrices to classifiers
|
||||
component.fit(instances)
|
||||
for category in ["type-a", "type-b"]:
|
||||
actual_x = component.classifiers[category].fit.call_args[0][0]
|
||||
actual_y = component.classifiers[category].fit.call_args[0][1]
|
||||
np.testing.assert_array_equal(actual_x, expected_x[category])
|
||||
np.testing.assert_array_equal(actual_y, expected_y[category])
|
||||
|
||||
assert component.predict(expected_x) == {"type-a": [[1]], "type-b": [[0], [1]]}
|
||||
|
||||
ev = component.evaluate(instances[1])
|
||||
assert ev["True positive"] == 1
|
||||
assert ev["True negative"] == 1
|
||||
assert ev["False positive"] == 1
|
||||
assert ev["False negative"] == 0
|
||||
|
||||
|
||||
def test_x_multiple_solves():
|
||||
instance = Mock(spec=Instance)
|
||||
instance.training_data = [
|
||||
{
|
||||
"slacks": {
|
||||
"c1": 0.00,
|
||||
"c2": 0.05,
|
||||
"c3": 0.00,
|
||||
"c4": 30.0,
|
||||
}
|
||||
},
|
||||
{
|
||||
"slacks": {
|
||||
"c1": 0.00,
|
||||
"c2": 0.00,
|
||||
"c3": 1.00,
|
||||
"c4": 0.0,
|
||||
}
|
||||
},
|
||||
]
|
||||
instance.get_constraint_category = Mock(
|
||||
side_effect=lambda cid: {
|
||||
"c1": None,
|
||||
"c2": "type-a",
|
||||
"c3": "type-a",
|
||||
"c4": "type-b",
|
||||
}[cid]
|
||||
)
|
||||
instance.get_constraint_features = Mock(
|
||||
side_effect=lambda cid: {
|
||||
"c2": np.array([1.0, 0.0]),
|
||||
"c3": np.array([0.5, 0.5]),
|
||||
"c4": np.array([1.0]),
|
||||
}[cid]
|
||||
)
|
||||
|
||||
expected_x = {
|
||||
"type-a": np.array(
|
||||
[
|
||||
[1.0, 0.0],
|
||||
[0.5, 0.5],
|
||||
[1.0, 0.0],
|
||||
[0.5, 0.5],
|
||||
]
|
||||
),
|
||||
"type-b": np.array(
|
||||
[
|
||||
[1.0],
|
||||
[1.0],
|
||||
]
|
||||
),
|
||||
}
|
||||
|
||||
expected_y = {
|
||||
"type-a": np.array([[1], [0], [0], [1]]),
|
||||
"type-b": np.array([[1], [0]]),
|
||||
}
|
||||
|
||||
# Should build X and Y matrices correctly
|
||||
component = DropRedundantInequalitiesStep()
|
||||
actual_x = component.x([instance])
|
||||
actual_y = component.y([instance])
|
||||
print(actual_x)
|
||||
for category in ["type-a", "type-b"]:
|
||||
np.testing.assert_array_equal(actual_x[category], expected_x[category])
|
||||
np.testing.assert_array_equal(actual_y[category], expected_y[category])</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-functions">Functions</h2>
|
||||
<dl>
|
||||
<dt id="miplearn.components.steps.tests.test_drop_redundant.test_drop_redundant"><code class="name flex">
|
||||
<span>def <span class="ident">test_drop_redundant</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_drop_redundant():
|
||||
solver, internal, instance, classifiers = _setup()
|
||||
|
||||
component = DropRedundantInequalitiesStep()
|
||||
component.classifiers = classifiers
|
||||
|
||||
# LearningSolver calls before_solve
|
||||
component.before_solve(solver, instance, None)
|
||||
|
||||
# Should query list of constraints
|
||||
internal.get_constraint_ids.assert_called_once()
|
||||
|
||||
# Should query category and features for each constraint in the model
|
||||
assert instance.get_constraint_category.call_count == 4
|
||||
instance.get_constraint_category.assert_has_calls(
|
||||
[
|
||||
call("c1"),
|
||||
call("c2"),
|
||||
call("c3"),
|
||||
call("c4"),
|
||||
]
|
||||
)
|
||||
|
||||
# For constraint with non-null categories, should ask for features
|
||||
assert instance.get_constraint_features.call_count == 3
|
||||
instance.get_constraint_features.assert_has_calls(
|
||||
[
|
||||
call("c2"),
|
||||
call("c3"),
|
||||
call("c4"),
|
||||
]
|
||||
)
|
||||
|
||||
# Should ask ML to predict whether constraint should be removed
|
||||
type_a_actual = component.classifiers["type-a"].predict_proba.call_args[0][0]
|
||||
type_b_actual = component.classifiers["type-b"].predict_proba.call_args[0][0]
|
||||
np.testing.assert_array_equal(type_a_actual, np.array([[1.0, 0.0], [0.5, 0.5]]))
|
||||
np.testing.assert_array_equal(type_b_actual, np.array([[1.0]]))
|
||||
|
||||
# Should ask internal solver to remove constraints predicted as redundant
|
||||
assert internal.extract_constraint.call_count == 2
|
||||
internal.extract_constraint.assert_has_calls(
|
||||
[
|
||||
call("c3"),
|
||||
call("c4"),
|
||||
]
|
||||
)
|
||||
|
||||
# LearningSolver calls after_solve
|
||||
training_data = {}
|
||||
component.after_solve(solver, instance, None, {}, training_data)
|
||||
|
||||
# Should query slack for all inequalities
|
||||
internal.get_inequality_slacks.assert_called_once()
|
||||
|
||||
# Should store constraint slacks in instance object
|
||||
assert training_data["slacks"] == {
|
||||
"c1": 0.5,
|
||||
"c2": 0.0,
|
||||
"c3": 0.0,
|
||||
"c4": 1.4,
|
||||
}</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.components.steps.tests.test_drop_redundant.test_drop_redundant_with_check_feasibility"><code class="name flex">
|
||||
<span>def <span class="ident">test_drop_redundant_with_check_feasibility</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_drop_redundant_with_check_feasibility():
|
||||
solver, internal, instance, classifiers = _setup()
|
||||
|
||||
component = DropRedundantInequalitiesStep(
|
||||
check_feasibility=True,
|
||||
violation_tolerance=1e-3,
|
||||
)
|
||||
component.classifiers = classifiers
|
||||
|
||||
# LearningSolver call before_solve
|
||||
component.before_solve(solver, instance, None)
|
||||
|
||||
# Assert constraints are extracted
|
||||
assert internal.extract_constraint.call_count == 2
|
||||
internal.extract_constraint.assert_has_calls(
|
||||
[
|
||||
call("c3"),
|
||||
call("c4"),
|
||||
]
|
||||
)
|
||||
|
||||
# LearningSolver calls iteration_cb (first time)
|
||||
should_repeat = component.iteration_cb(solver, instance, None)
|
||||
|
||||
# Should ask LearningSolver to repeat
|
||||
assert should_repeat
|
||||
|
||||
# Should ask solver if removed constraints are satisfied (mock always returns false)
|
||||
internal.is_constraint_satisfied.assert_has_calls(
|
||||
[
|
||||
call("<c3>", 1e-3),
|
||||
call("<c4>", 1e-3),
|
||||
]
|
||||
)
|
||||
|
||||
# Should add constraints back to LP relaxation
|
||||
internal.add_constraint.assert_has_calls([call("<c3>"), call("<c4>")])
|
||||
|
||||
# LearningSolver calls iteration_cb (second time)
|
||||
should_repeat = component.iteration_cb(solver, instance, None)
|
||||
assert not should_repeat</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.components.steps.tests.test_drop_redundant.test_x_multiple_solves"><code class="name flex">
|
||||
<span>def <span class="ident">test_x_multiple_solves</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_x_multiple_solves():
|
||||
instance = Mock(spec=Instance)
|
||||
instance.training_data = [
|
||||
{
|
||||
"slacks": {
|
||||
"c1": 0.00,
|
||||
"c2": 0.05,
|
||||
"c3": 0.00,
|
||||
"c4": 30.0,
|
||||
}
|
||||
},
|
||||
{
|
||||
"slacks": {
|
||||
"c1": 0.00,
|
||||
"c2": 0.00,
|
||||
"c3": 1.00,
|
||||
"c4": 0.0,
|
||||
}
|
||||
},
|
||||
]
|
||||
instance.get_constraint_category = Mock(
|
||||
side_effect=lambda cid: {
|
||||
"c1": None,
|
||||
"c2": "type-a",
|
||||
"c3": "type-a",
|
||||
"c4": "type-b",
|
||||
}[cid]
|
||||
)
|
||||
instance.get_constraint_features = Mock(
|
||||
side_effect=lambda cid: {
|
||||
"c2": np.array([1.0, 0.0]),
|
||||
"c3": np.array([0.5, 0.5]),
|
||||
"c4": np.array([1.0]),
|
||||
}[cid]
|
||||
)
|
||||
|
||||
expected_x = {
|
||||
"type-a": np.array(
|
||||
[
|
||||
[1.0, 0.0],
|
||||
[0.5, 0.5],
|
||||
[1.0, 0.0],
|
||||
[0.5, 0.5],
|
||||
]
|
||||
),
|
||||
"type-b": np.array(
|
||||
[
|
||||
[1.0],
|
||||
[1.0],
|
||||
]
|
||||
),
|
||||
}
|
||||
|
||||
expected_y = {
|
||||
"type-a": np.array([[1], [0], [0], [1]]),
|
||||
"type-b": np.array([[1], [0]]),
|
||||
}
|
||||
|
||||
# Should build X and Y matrices correctly
|
||||
component = DropRedundantInequalitiesStep()
|
||||
actual_x = component.x([instance])
|
||||
actual_y = component.y([instance])
|
||||
print(actual_x)
|
||||
for category in ["type-a", "type-b"]:
|
||||
np.testing.assert_array_equal(actual_x[category], expected_x[category])
|
||||
np.testing.assert_array_equal(actual_y[category], expected_y[category])</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.components.steps.tests.test_drop_redundant.test_x_y_fit_predict_evaluate"><code class="name flex">
|
||||
<span>def <span class="ident">test_x_y_fit_predict_evaluate</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_x_y_fit_predict_evaluate():
|
||||
instances = [Mock(spec=Instance), Mock(spec=Instance)]
|
||||
component = DropRedundantInequalitiesStep(slack_tolerance=0.05, threshold=0.80)
|
||||
component.classifiers = {
|
||||
"type-a": Mock(spec=Classifier),
|
||||
"type-b": Mock(spec=Classifier),
|
||||
}
|
||||
component.classifiers["type-a"].predict_proba = Mock(
|
||||
return_value=[
|
||||
np.array([0.20, 0.80]),
|
||||
]
|
||||
)
|
||||
component.classifiers["type-b"].predict_proba = Mock(
|
||||
return_value=np.array(
|
||||
[
|
||||
[0.50, 0.50],
|
||||
[0.05, 0.95],
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
# First mock instance
|
||||
instances[0].training_data = [
|
||||
{
|
||||
"slacks": {
|
||||
"c1": 0.00,
|
||||
"c2": 0.05,
|
||||
"c3": 0.00,
|
||||
"c4": 30.0,
|
||||
}
|
||||
}
|
||||
]
|
||||
instances[0].get_constraint_category = Mock(
|
||||
side_effect=lambda cid: {
|
||||
"c1": None,
|
||||
"c2": "type-a",
|
||||
"c3": "type-a",
|
||||
"c4": "type-b",
|
||||
}[cid]
|
||||
)
|
||||
instances[0].get_constraint_features = Mock(
|
||||
side_effect=lambda cid: {
|
||||
"c2": np.array([1.0, 0.0]),
|
||||
"c3": np.array([0.5, 0.5]),
|
||||
"c4": np.array([1.0]),
|
||||
}[cid]
|
||||
)
|
||||
|
||||
# Second mock instance
|
||||
instances[1].training_data = [
|
||||
{
|
||||
"slacks": {
|
||||
"c1": 0.00,
|
||||
"c3": 0.30,
|
||||
"c4": 0.00,
|
||||
"c5": 0.00,
|
||||
}
|
||||
}
|
||||
]
|
||||
instances[1].get_constraint_category = Mock(
|
||||
side_effect=lambda cid: {
|
||||
"c1": None,
|
||||
"c3": "type-a",
|
||||
"c4": "type-b",
|
||||
"c5": "type-b",
|
||||
}[cid]
|
||||
)
|
||||
instances[1].get_constraint_features = Mock(
|
||||
side_effect=lambda cid: {
|
||||
"c3": np.array([0.3, 0.4]),
|
||||
"c4": np.array([0.7]),
|
||||
"c5": np.array([0.8]),
|
||||
}[cid]
|
||||
)
|
||||
|
||||
expected_x = {
|
||||
"type-a": np.array(
|
||||
[
|
||||
[1.0, 0.0],
|
||||
[0.5, 0.5],
|
||||
[0.3, 0.4],
|
||||
]
|
||||
),
|
||||
"type-b": np.array(
|
||||
[
|
||||
[1.0],
|
||||
[0.7],
|
||||
[0.8],
|
||||
]
|
||||
),
|
||||
}
|
||||
expected_y = {
|
||||
"type-a": np.array([[0], [0], [1]]),
|
||||
"type-b": np.array([[1], [0], [0]]),
|
||||
}
|
||||
|
||||
# Should build X and Y matrices correctly
|
||||
actual_x = component.x(instances)
|
||||
actual_y = component.y(instances)
|
||||
for category in ["type-a", "type-b"]:
|
||||
np.testing.assert_array_equal(actual_x[category], expected_x[category])
|
||||
np.testing.assert_array_equal(actual_y[category], expected_y[category])
|
||||
|
||||
# Should pass along X and Y matrices to classifiers
|
||||
component.fit(instances)
|
||||
for category in ["type-a", "type-b"]:
|
||||
actual_x = component.classifiers[category].fit.call_args[0][0]
|
||||
actual_y = component.classifiers[category].fit.call_args[0][1]
|
||||
np.testing.assert_array_equal(actual_x, expected_x[category])
|
||||
np.testing.assert_array_equal(actual_y, expected_y[category])
|
||||
|
||||
assert component.predict(expected_x) == {"type-a": [[1]], "type-b": [[0], [1]]}
|
||||
|
||||
ev = component.evaluate(instances[1])
|
||||
assert ev["True positive"] == 1
|
||||
assert ev["True negative"] == 1
|
||||
assert ev["False positive"] == 1
|
||||
assert ev["False negative"] == 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.components.steps.tests" href="index.html">miplearn.components.steps.tests</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-functions">Functions</a></h3>
|
||||
<ul class="">
|
||||
<li><code><a title="miplearn.components.steps.tests.test_drop_redundant.test_drop_redundant" href="#miplearn.components.steps.tests.test_drop_redundant.test_drop_redundant">test_drop_redundant</a></code></li>
|
||||
<li><code><a title="miplearn.components.steps.tests.test_drop_redundant.test_drop_redundant_with_check_feasibility" href="#miplearn.components.steps.tests.test_drop_redundant.test_drop_redundant_with_check_feasibility">test_drop_redundant_with_check_feasibility</a></code></li>
|
||||
<li><code><a title="miplearn.components.steps.tests.test_drop_redundant.test_x_multiple_solves" href="#miplearn.components.steps.tests.test_drop_redundant.test_x_multiple_solves">test_x_multiple_solves</a></code></li>
|
||||
<li><code><a title="miplearn.components.steps.tests.test_drop_redundant.test_x_y_fit_predict_evaluate" href="#miplearn.components.steps.tests.test_drop_redundant.test_x_y_fit_predict_evaluate">test_x_y_fit_predict_evaluate</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>
|
||||
93
0.2/api/miplearn/components/tests/index.html
Normal file
93
0.2/api/miplearn/components/tests/index.html
Normal file
@@ -0,0 +1,93 @@
|
||||
<!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.components.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.components.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.</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-submodules">Sub-modules</h2>
|
||||
<dl>
|
||||
<dt><code class="name"><a title="miplearn.components.tests.test_composite" href="test_composite.html">miplearn.components.tests.test_composite</a></code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
</dd>
|
||||
<dt><code class="name"><a title="miplearn.components.tests.test_lazy_dynamic" href="test_lazy_dynamic.html">miplearn.components.tests.test_lazy_dynamic</a></code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
</dd>
|
||||
<dt><code class="name"><a title="miplearn.components.tests.test_lazy_static" href="test_lazy_static.html">miplearn.components.tests.test_lazy_static</a></code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
</dd>
|
||||
<dt><code class="name"><a title="miplearn.components.tests.test_objective" href="test_objective.html">miplearn.components.tests.test_objective</a></code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
</dd>
|
||||
<dt><code class="name"><a title="miplearn.components.tests.test_primal" href="test_primal.html">miplearn.components.tests.test_primal</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.components" href="../index.html">miplearn.components</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-submodules">Sub-modules</a></h3>
|
||||
<ul>
|
||||
<li><code><a title="miplearn.components.tests.test_composite" href="test_composite.html">miplearn.components.tests.test_composite</a></code></li>
|
||||
<li><code><a title="miplearn.components.tests.test_lazy_dynamic" href="test_lazy_dynamic.html">miplearn.components.tests.test_lazy_dynamic</a></code></li>
|
||||
<li><code><a title="miplearn.components.tests.test_lazy_static" href="test_lazy_static.html">miplearn.components.tests.test_lazy_static</a></code></li>
|
||||
<li><code><a title="miplearn.components.tests.test_objective" href="test_objective.html">miplearn.components.tests.test_objective</a></code></li>
|
||||
<li><code><a title="miplearn.components.tests.test_primal" href="test_primal.html">miplearn.components.tests.test_primal</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>
|
||||
179
0.2/api/miplearn/components/tests/test_composite.html
Normal file
179
0.2/api/miplearn/components/tests/test_composite.html
Normal file
@@ -0,0 +1,179 @@
|
||||
<!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.components.tests.test_composite 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.components.tests.test_composite</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 unittest.mock import Mock, call
|
||||
|
||||
from miplearn.components.component import Component
|
||||
from miplearn.components.composite import CompositeComponent
|
||||
from miplearn.instance import Instance
|
||||
from miplearn.solvers.learning import LearningSolver
|
||||
|
||||
|
||||
def test_composite():
|
||||
solver, instance, model = (
|
||||
Mock(spec=LearningSolver),
|
||||
Mock(spec=Instance),
|
||||
Mock(),
|
||||
)
|
||||
|
||||
c1 = Mock(spec=Component)
|
||||
c2 = Mock(spec=Component)
|
||||
cc = CompositeComponent([c1, c2])
|
||||
|
||||
# Should broadcast before_solve
|
||||
cc.before_solve(solver, instance, model)
|
||||
c1.before_solve.assert_has_calls([call(solver, instance, model)])
|
||||
c2.before_solve.assert_has_calls([call(solver, instance, model)])
|
||||
|
||||
# Should broadcast after_solve
|
||||
cc.after_solve(solver, instance, model, {}, {})
|
||||
c1.after_solve.assert_has_calls([call(solver, instance, model, {}, {})])
|
||||
c2.after_solve.assert_has_calls([call(solver, instance, model, {}, {})])
|
||||
|
||||
# Should broadcast fit
|
||||
cc.fit([1, 2, 3])
|
||||
c1.fit.assert_has_calls([call([1, 2, 3])])
|
||||
c2.fit.assert_has_calls([call([1, 2, 3])])
|
||||
|
||||
# Should broadcast lazy_cb
|
||||
cc.lazy_cb(solver, instance, model)
|
||||
c1.lazy_cb.assert_has_calls([call(solver, instance, model)])
|
||||
c2.lazy_cb.assert_has_calls([call(solver, instance, model)])
|
||||
|
||||
# Should broadcast iteration_cb
|
||||
cc.iteration_cb(solver, instance, model)
|
||||
c1.iteration_cb.assert_has_calls([call(solver, instance, model)])
|
||||
c2.iteration_cb.assert_has_calls([call(solver, instance, model)])
|
||||
|
||||
# If at least one child component returns true, iteration_cb should return True
|
||||
c1.iteration_cb = Mock(return_value=True)
|
||||
c2.iteration_cb = Mock(return_value=False)
|
||||
assert cc.iteration_cb(solver, instance, model)
|
||||
|
||||
# If all children return False, iteration_cb should return False
|
||||
c1.iteration_cb = Mock(return_value=False)
|
||||
c2.iteration_cb = Mock(return_value=False)
|
||||
assert not cc.iteration_cb(solver, instance, model)</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-functions">Functions</h2>
|
||||
<dl>
|
||||
<dt id="miplearn.components.tests.test_composite.test_composite"><code class="name flex">
|
||||
<span>def <span class="ident">test_composite</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_composite():
|
||||
solver, instance, model = (
|
||||
Mock(spec=LearningSolver),
|
||||
Mock(spec=Instance),
|
||||
Mock(),
|
||||
)
|
||||
|
||||
c1 = Mock(spec=Component)
|
||||
c2 = Mock(spec=Component)
|
||||
cc = CompositeComponent([c1, c2])
|
||||
|
||||
# Should broadcast before_solve
|
||||
cc.before_solve(solver, instance, model)
|
||||
c1.before_solve.assert_has_calls([call(solver, instance, model)])
|
||||
c2.before_solve.assert_has_calls([call(solver, instance, model)])
|
||||
|
||||
# Should broadcast after_solve
|
||||
cc.after_solve(solver, instance, model, {}, {})
|
||||
c1.after_solve.assert_has_calls([call(solver, instance, model, {}, {})])
|
||||
c2.after_solve.assert_has_calls([call(solver, instance, model, {}, {})])
|
||||
|
||||
# Should broadcast fit
|
||||
cc.fit([1, 2, 3])
|
||||
c1.fit.assert_has_calls([call([1, 2, 3])])
|
||||
c2.fit.assert_has_calls([call([1, 2, 3])])
|
||||
|
||||
# Should broadcast lazy_cb
|
||||
cc.lazy_cb(solver, instance, model)
|
||||
c1.lazy_cb.assert_has_calls([call(solver, instance, model)])
|
||||
c2.lazy_cb.assert_has_calls([call(solver, instance, model)])
|
||||
|
||||
# Should broadcast iteration_cb
|
||||
cc.iteration_cb(solver, instance, model)
|
||||
c1.iteration_cb.assert_has_calls([call(solver, instance, model)])
|
||||
c2.iteration_cb.assert_has_calls([call(solver, instance, model)])
|
||||
|
||||
# If at least one child component returns true, iteration_cb should return True
|
||||
c1.iteration_cb = Mock(return_value=True)
|
||||
c2.iteration_cb = Mock(return_value=False)
|
||||
assert cc.iteration_cb(solver, instance, model)
|
||||
|
||||
# If all children return False, iteration_cb should return False
|
||||
c1.iteration_cb = Mock(return_value=False)
|
||||
c2.iteration_cb = Mock(return_value=False)
|
||||
assert not cc.iteration_cb(solver, instance, model)</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.components.tests" href="index.html">miplearn.components.tests</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-functions">Functions</a></h3>
|
||||
<ul class="">
|
||||
<li><code><a title="miplearn.components.tests.test_composite.test_composite" href="#miplearn.components.tests.test_composite.test_composite">test_composite</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>
|
||||
365
0.2/api/miplearn/components/tests/test_lazy_dynamic.html
Normal file
365
0.2/api/miplearn/components/tests/test_lazy_dynamic.html
Normal 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.components.tests.test_lazy_dynamic 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.components.tests.test_lazy_dynamic</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 unittest.mock import Mock
|
||||
|
||||
import numpy as np
|
||||
from numpy.linalg import norm
|
||||
|
||||
from miplearn.classifiers import Classifier
|
||||
from miplearn.components.lazy_dynamic import DynamicLazyConstraintsComponent
|
||||
from miplearn.solvers.internal import InternalSolver
|
||||
from miplearn.solvers.learning import LearningSolver
|
||||
from miplearn.tests import get_test_pyomo_instances
|
||||
|
||||
E = 0.1
|
||||
|
||||
|
||||
def test_lazy_fit():
|
||||
instances, models = get_test_pyomo_instances()
|
||||
instances[0].found_violated_lazy_constraints = ["a", "b"]
|
||||
instances[1].found_violated_lazy_constraints = ["b", "c"]
|
||||
classifier = Mock(spec=Classifier)
|
||||
component = DynamicLazyConstraintsComponent(classifier=classifier)
|
||||
|
||||
component.fit(instances)
|
||||
|
||||
# Should create one classifier for each violation
|
||||
assert "a" in component.classifiers
|
||||
assert "b" in component.classifiers
|
||||
assert "c" in component.classifiers
|
||||
|
||||
# Should provide correct x_train to each classifier
|
||||
expected_x_train_a = np.array([[67.0, 21.75, 1287.92], [70.0, 23.75, 1199.83]])
|
||||
expected_x_train_b = np.array([[67.0, 21.75, 1287.92], [70.0, 23.75, 1199.83]])
|
||||
expected_x_train_c = np.array([[67.0, 21.75, 1287.92], [70.0, 23.75, 1199.83]])
|
||||
actual_x_train_a = component.classifiers["a"].fit.call_args[0][0]
|
||||
actual_x_train_b = component.classifiers["b"].fit.call_args[0][0]
|
||||
actual_x_train_c = component.classifiers["c"].fit.call_args[0][0]
|
||||
assert norm(expected_x_train_a - actual_x_train_a) < E
|
||||
assert norm(expected_x_train_b - actual_x_train_b) < E
|
||||
assert norm(expected_x_train_c - actual_x_train_c) < E
|
||||
|
||||
# Should provide correct y_train to each classifier
|
||||
expected_y_train_a = np.array([1.0, 0.0])
|
||||
expected_y_train_b = np.array([1.0, 1.0])
|
||||
expected_y_train_c = np.array([0.0, 1.0])
|
||||
actual_y_train_a = component.classifiers["a"].fit.call_args[0][1]
|
||||
actual_y_train_b = component.classifiers["b"].fit.call_args[0][1]
|
||||
actual_y_train_c = component.classifiers["c"].fit.call_args[0][1]
|
||||
assert norm(expected_y_train_a - actual_y_train_a) < E
|
||||
assert norm(expected_y_train_b - actual_y_train_b) < E
|
||||
assert norm(expected_y_train_c - actual_y_train_c) < E
|
||||
|
||||
|
||||
def test_lazy_before():
|
||||
instances, models = get_test_pyomo_instances()
|
||||
instances[0].build_lazy_constraint = Mock(return_value="c1")
|
||||
solver = LearningSolver()
|
||||
solver.internal_solver = Mock(spec=InternalSolver)
|
||||
component = DynamicLazyConstraintsComponent(threshold=0.10)
|
||||
component.classifiers = {"a": Mock(spec=Classifier), "b": Mock(spec=Classifier)}
|
||||
component.classifiers["a"].predict_proba = Mock(return_value=[[0.95, 0.05]])
|
||||
component.classifiers["b"].predict_proba = Mock(return_value=[[0.02, 0.80]])
|
||||
|
||||
component.before_solve(solver, instances[0], models[0])
|
||||
|
||||
# Should ask classifier likelihood of each constraint being violated
|
||||
expected_x_test_a = np.array([[67.0, 21.75, 1287.92]])
|
||||
expected_x_test_b = np.array([[67.0, 21.75, 1287.92]])
|
||||
actual_x_test_a = component.classifiers["a"].predict_proba.call_args[0][0]
|
||||
actual_x_test_b = component.classifiers["b"].predict_proba.call_args[0][0]
|
||||
assert norm(expected_x_test_a - actual_x_test_a) < E
|
||||
assert norm(expected_x_test_b - actual_x_test_b) < E
|
||||
|
||||
# Should ask instance to generate cut for constraints whose likelihood
|
||||
# of being violated exceeds the threshold
|
||||
instances[0].build_lazy_constraint.assert_called_once_with(models[0], "b")
|
||||
|
||||
# Should ask internal solver to add generated constraint
|
||||
solver.internal_solver.add_constraint.assert_called_once_with("c1")
|
||||
|
||||
|
||||
def test_lazy_evaluate():
|
||||
instances, models = get_test_pyomo_instances()
|
||||
component = DynamicLazyConstraintsComponent()
|
||||
component.classifiers = {
|
||||
"a": Mock(spec=Classifier),
|
||||
"b": Mock(spec=Classifier),
|
||||
"c": Mock(spec=Classifier),
|
||||
}
|
||||
component.classifiers["a"].predict_proba = Mock(return_value=[[1.0, 0.0]])
|
||||
component.classifiers["b"].predict_proba = Mock(return_value=[[0.0, 1.0]])
|
||||
component.classifiers["c"].predict_proba = Mock(return_value=[[0.0, 1.0]])
|
||||
|
||||
instances[0].found_violated_lazy_constraints = ["a", "b", "c"]
|
||||
instances[1].found_violated_lazy_constraints = ["b", "d"]
|
||||
assert component.evaluate(instances) == {
|
||||
0: {
|
||||
"Accuracy": 0.75,
|
||||
"F1 score": 0.8,
|
||||
"Precision": 1.0,
|
||||
"Recall": 2 / 3.0,
|
||||
"Predicted positive": 2,
|
||||
"Predicted negative": 2,
|
||||
"Condition positive": 3,
|
||||
"Condition negative": 1,
|
||||
"False negative": 1,
|
||||
"False positive": 0,
|
||||
"True negative": 1,
|
||||
"True positive": 2,
|
||||
"Predicted positive (%)": 50.0,
|
||||
"Predicted negative (%)": 50.0,
|
||||
"Condition positive (%)": 75.0,
|
||||
"Condition negative (%)": 25.0,
|
||||
"False negative (%)": 25.0,
|
||||
"False positive (%)": 0,
|
||||
"True negative (%)": 25.0,
|
||||
"True positive (%)": 50.0,
|
||||
},
|
||||
1: {
|
||||
"Accuracy": 0.5,
|
||||
"F1 score": 0.5,
|
||||
"Precision": 0.5,
|
||||
"Recall": 0.5,
|
||||
"Predicted positive": 2,
|
||||
"Predicted negative": 2,
|
||||
"Condition positive": 2,
|
||||
"Condition negative": 2,
|
||||
"False negative": 1,
|
||||
"False positive": 1,
|
||||
"True negative": 1,
|
||||
"True positive": 1,
|
||||
"Predicted positive (%)": 50.0,
|
||||
"Predicted negative (%)": 50.0,
|
||||
"Condition positive (%)": 50.0,
|
||||
"Condition negative (%)": 50.0,
|
||||
"False negative (%)": 25.0,
|
||||
"False positive (%)": 25.0,
|
||||
"True negative (%)": 25.0,
|
||||
"True positive (%)": 25.0,
|
||||
},
|
||||
}</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-functions">Functions</h2>
|
||||
<dl>
|
||||
<dt id="miplearn.components.tests.test_lazy_dynamic.test_lazy_before"><code class="name flex">
|
||||
<span>def <span class="ident">test_lazy_before</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_before():
|
||||
instances, models = get_test_pyomo_instances()
|
||||
instances[0].build_lazy_constraint = Mock(return_value="c1")
|
||||
solver = LearningSolver()
|
||||
solver.internal_solver = Mock(spec=InternalSolver)
|
||||
component = DynamicLazyConstraintsComponent(threshold=0.10)
|
||||
component.classifiers = {"a": Mock(spec=Classifier), "b": Mock(spec=Classifier)}
|
||||
component.classifiers["a"].predict_proba = Mock(return_value=[[0.95, 0.05]])
|
||||
component.classifiers["b"].predict_proba = Mock(return_value=[[0.02, 0.80]])
|
||||
|
||||
component.before_solve(solver, instances[0], models[0])
|
||||
|
||||
# Should ask classifier likelihood of each constraint being violated
|
||||
expected_x_test_a = np.array([[67.0, 21.75, 1287.92]])
|
||||
expected_x_test_b = np.array([[67.0, 21.75, 1287.92]])
|
||||
actual_x_test_a = component.classifiers["a"].predict_proba.call_args[0][0]
|
||||
actual_x_test_b = component.classifiers["b"].predict_proba.call_args[0][0]
|
||||
assert norm(expected_x_test_a - actual_x_test_a) < E
|
||||
assert norm(expected_x_test_b - actual_x_test_b) < E
|
||||
|
||||
# Should ask instance to generate cut for constraints whose likelihood
|
||||
# of being violated exceeds the threshold
|
||||
instances[0].build_lazy_constraint.assert_called_once_with(models[0], "b")
|
||||
|
||||
# Should ask internal solver to add generated constraint
|
||||
solver.internal_solver.add_constraint.assert_called_once_with("c1")</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.components.tests.test_lazy_dynamic.test_lazy_evaluate"><code class="name flex">
|
||||
<span>def <span class="ident">test_lazy_evaluate</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_evaluate():
|
||||
instances, models = get_test_pyomo_instances()
|
||||
component = DynamicLazyConstraintsComponent()
|
||||
component.classifiers = {
|
||||
"a": Mock(spec=Classifier),
|
||||
"b": Mock(spec=Classifier),
|
||||
"c": Mock(spec=Classifier),
|
||||
}
|
||||
component.classifiers["a"].predict_proba = Mock(return_value=[[1.0, 0.0]])
|
||||
component.classifiers["b"].predict_proba = Mock(return_value=[[0.0, 1.0]])
|
||||
component.classifiers["c"].predict_proba = Mock(return_value=[[0.0, 1.0]])
|
||||
|
||||
instances[0].found_violated_lazy_constraints = ["a", "b", "c"]
|
||||
instances[1].found_violated_lazy_constraints = ["b", "d"]
|
||||
assert component.evaluate(instances) == {
|
||||
0: {
|
||||
"Accuracy": 0.75,
|
||||
"F1 score": 0.8,
|
||||
"Precision": 1.0,
|
||||
"Recall": 2 / 3.0,
|
||||
"Predicted positive": 2,
|
||||
"Predicted negative": 2,
|
||||
"Condition positive": 3,
|
||||
"Condition negative": 1,
|
||||
"False negative": 1,
|
||||
"False positive": 0,
|
||||
"True negative": 1,
|
||||
"True positive": 2,
|
||||
"Predicted positive (%)": 50.0,
|
||||
"Predicted negative (%)": 50.0,
|
||||
"Condition positive (%)": 75.0,
|
||||
"Condition negative (%)": 25.0,
|
||||
"False negative (%)": 25.0,
|
||||
"False positive (%)": 0,
|
||||
"True negative (%)": 25.0,
|
||||
"True positive (%)": 50.0,
|
||||
},
|
||||
1: {
|
||||
"Accuracy": 0.5,
|
||||
"F1 score": 0.5,
|
||||
"Precision": 0.5,
|
||||
"Recall": 0.5,
|
||||
"Predicted positive": 2,
|
||||
"Predicted negative": 2,
|
||||
"Condition positive": 2,
|
||||
"Condition negative": 2,
|
||||
"False negative": 1,
|
||||
"False positive": 1,
|
||||
"True negative": 1,
|
||||
"True positive": 1,
|
||||
"Predicted positive (%)": 50.0,
|
||||
"Predicted negative (%)": 50.0,
|
||||
"Condition positive (%)": 50.0,
|
||||
"Condition negative (%)": 50.0,
|
||||
"False negative (%)": 25.0,
|
||||
"False positive (%)": 25.0,
|
||||
"True negative (%)": 25.0,
|
||||
"True positive (%)": 25.0,
|
||||
},
|
||||
}</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.components.tests.test_lazy_dynamic.test_lazy_fit"><code class="name flex">
|
||||
<span>def <span class="ident">test_lazy_fit</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_fit():
|
||||
instances, models = get_test_pyomo_instances()
|
||||
instances[0].found_violated_lazy_constraints = ["a", "b"]
|
||||
instances[1].found_violated_lazy_constraints = ["b", "c"]
|
||||
classifier = Mock(spec=Classifier)
|
||||
component = DynamicLazyConstraintsComponent(classifier=classifier)
|
||||
|
||||
component.fit(instances)
|
||||
|
||||
# Should create one classifier for each violation
|
||||
assert "a" in component.classifiers
|
||||
assert "b" in component.classifiers
|
||||
assert "c" in component.classifiers
|
||||
|
||||
# Should provide correct x_train to each classifier
|
||||
expected_x_train_a = np.array([[67.0, 21.75, 1287.92], [70.0, 23.75, 1199.83]])
|
||||
expected_x_train_b = np.array([[67.0, 21.75, 1287.92], [70.0, 23.75, 1199.83]])
|
||||
expected_x_train_c = np.array([[67.0, 21.75, 1287.92], [70.0, 23.75, 1199.83]])
|
||||
actual_x_train_a = component.classifiers["a"].fit.call_args[0][0]
|
||||
actual_x_train_b = component.classifiers["b"].fit.call_args[0][0]
|
||||
actual_x_train_c = component.classifiers["c"].fit.call_args[0][0]
|
||||
assert norm(expected_x_train_a - actual_x_train_a) < E
|
||||
assert norm(expected_x_train_b - actual_x_train_b) < E
|
||||
assert norm(expected_x_train_c - actual_x_train_c) < E
|
||||
|
||||
# Should provide correct y_train to each classifier
|
||||
expected_y_train_a = np.array([1.0, 0.0])
|
||||
expected_y_train_b = np.array([1.0, 1.0])
|
||||
expected_y_train_c = np.array([0.0, 1.0])
|
||||
actual_y_train_a = component.classifiers["a"].fit.call_args[0][1]
|
||||
actual_y_train_b = component.classifiers["b"].fit.call_args[0][1]
|
||||
actual_y_train_c = component.classifiers["c"].fit.call_args[0][1]
|
||||
assert norm(expected_y_train_a - actual_y_train_a) < E
|
||||
assert norm(expected_y_train_b - actual_y_train_b) < E
|
||||
assert norm(expected_y_train_c - actual_y_train_c) < E</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.components.tests" href="index.html">miplearn.components.tests</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-functions">Functions</a></h3>
|
||||
<ul class="">
|
||||
<li><code><a title="miplearn.components.tests.test_lazy_dynamic.test_lazy_before" href="#miplearn.components.tests.test_lazy_dynamic.test_lazy_before">test_lazy_before</a></code></li>
|
||||
<li><code><a title="miplearn.components.tests.test_lazy_dynamic.test_lazy_evaluate" href="#miplearn.components.tests.test_lazy_dynamic.test_lazy_evaluate">test_lazy_evaluate</a></code></li>
|
||||
<li><code><a title="miplearn.components.tests.test_lazy_dynamic.test_lazy_fit" href="#miplearn.components.tests.test_lazy_dynamic.test_lazy_fit">test_lazy_fit</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>
|
||||
538
0.2/api/miplearn/components/tests/test_lazy_static.html
Normal file
538
0.2/api/miplearn/components/tests/test_lazy_static.html
Normal file
@@ -0,0 +1,538 @@
|
||||
<!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.components.tests.test_lazy_static 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.components.tests.test_lazy_static</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 unittest.mock import Mock, call
|
||||
|
||||
from miplearn.classifiers import Classifier
|
||||
from miplearn.components.lazy_static import StaticLazyConstraintsComponent
|
||||
from miplearn.instance import Instance
|
||||
from miplearn.solvers.internal import InternalSolver
|
||||
from miplearn.solvers.learning import LearningSolver
|
||||
|
||||
|
||||
def test_usage_with_solver():
|
||||
solver = Mock(spec=LearningSolver)
|
||||
solver.use_lazy_cb = False
|
||||
solver.gap_tolerance = 1e-4
|
||||
|
||||
internal = solver.internal_solver = Mock(spec=InternalSolver)
|
||||
internal.get_constraint_ids = Mock(return_value=["c1", "c2", "c3", "c4"])
|
||||
internal.extract_constraint = Mock(side_effect=lambda cid: "<%s>" % cid)
|
||||
internal.is_constraint_satisfied = Mock(return_value=False)
|
||||
|
||||
instance = Mock(spec=Instance)
|
||||
instance.has_static_lazy_constraints = Mock(return_value=True)
|
||||
instance.is_constraint_lazy = Mock(
|
||||
side_effect=lambda cid: {
|
||||
"c1": False,
|
||||
"c2": True,
|
||||
"c3": True,
|
||||
"c4": True,
|
||||
}[cid]
|
||||
)
|
||||
instance.get_constraint_features = Mock(
|
||||
side_effect=lambda cid: {
|
||||
"c2": [1.0, 0.0],
|
||||
"c3": [0.5, 0.5],
|
||||
"c4": [1.0],
|
||||
}[cid]
|
||||
)
|
||||
instance.get_constraint_category = Mock(
|
||||
side_effect=lambda cid: {
|
||||
"c2": "type-a",
|
||||
"c3": "type-a",
|
||||
"c4": "type-b",
|
||||
}[cid]
|
||||
)
|
||||
|
||||
component = StaticLazyConstraintsComponent(
|
||||
threshold=0.90,
|
||||
use_two_phase_gap=False,
|
||||
violation_tolerance=1.0,
|
||||
)
|
||||
component.classifiers = {
|
||||
"type-a": Mock(spec=Classifier),
|
||||
"type-b": Mock(spec=Classifier),
|
||||
}
|
||||
component.classifiers["type-a"].predict_proba = Mock(
|
||||
return_value=[
|
||||
[0.20, 0.80],
|
||||
[0.05, 0.95],
|
||||
]
|
||||
)
|
||||
component.classifiers["type-b"].predict_proba = Mock(
|
||||
return_value=[
|
||||
[0.02, 0.98],
|
||||
]
|
||||
)
|
||||
|
||||
# LearningSolver calls before_solve
|
||||
component.before_solve(solver, instance, None)
|
||||
|
||||
# Should ask if instance has static lazy constraints
|
||||
instance.has_static_lazy_constraints.assert_called_once()
|
||||
|
||||
# Should ask internal solver for a list of constraints in the model
|
||||
internal.get_constraint_ids.assert_called_once()
|
||||
|
||||
# Should ask if each constraint in the model is lazy
|
||||
instance.is_constraint_lazy.assert_has_calls(
|
||||
[
|
||||
call("c1"),
|
||||
call("c2"),
|
||||
call("c3"),
|
||||
call("c4"),
|
||||
]
|
||||
)
|
||||
|
||||
# For the lazy ones, should ask for features
|
||||
instance.get_constraint_features.assert_has_calls(
|
||||
[
|
||||
call("c2"),
|
||||
call("c3"),
|
||||
call("c4"),
|
||||
]
|
||||
)
|
||||
|
||||
# Should also ask for categories
|
||||
assert instance.get_constraint_category.call_count == 3
|
||||
instance.get_constraint_category.assert_has_calls(
|
||||
[
|
||||
call("c2"),
|
||||
call("c3"),
|
||||
call("c4"),
|
||||
]
|
||||
)
|
||||
|
||||
# Should ask internal solver to remove constraints identified as lazy
|
||||
assert internal.extract_constraint.call_count == 3
|
||||
internal.extract_constraint.assert_has_calls(
|
||||
[
|
||||
call("c2"),
|
||||
call("c3"),
|
||||
call("c4"),
|
||||
]
|
||||
)
|
||||
|
||||
# Should ask ML to predict whether each lazy constraint should be enforced
|
||||
component.classifiers["type-a"].predict_proba.assert_called_once_with(
|
||||
[[1.0, 0.0], [0.5, 0.5]]
|
||||
)
|
||||
component.classifiers["type-b"].predict_proba.assert_called_once_with([[1.0]])
|
||||
|
||||
# For the ones that should be enforced, should ask solver to re-add them
|
||||
# to the formulation. The remaining ones should remain in the pool.
|
||||
assert internal.add_constraint.call_count == 2
|
||||
internal.add_constraint.assert_has_calls(
|
||||
[
|
||||
call("<c3>"),
|
||||
call("<c4>"),
|
||||
]
|
||||
)
|
||||
internal.add_constraint.reset_mock()
|
||||
|
||||
# LearningSolver calls after_iteration (first time)
|
||||
should_repeat = component.iteration_cb(solver, instance, None)
|
||||
assert should_repeat
|
||||
|
||||
# Should ask internal solver to verify if constraints in the pool are
|
||||
# satisfied and add the ones that are not
|
||||
internal.is_constraint_satisfied.assert_called_once_with("<c2>", tol=1.0)
|
||||
internal.is_constraint_satisfied.reset_mock()
|
||||
internal.add_constraint.assert_called_once_with("<c2>")
|
||||
internal.add_constraint.reset_mock()
|
||||
|
||||
# LearningSolver calls after_iteration (second time)
|
||||
should_repeat = component.iteration_cb(solver, instance, None)
|
||||
assert not should_repeat
|
||||
|
||||
# The lazy constraint pool should be empty by now, so no calls should be made
|
||||
internal.is_constraint_satisfied.assert_not_called()
|
||||
internal.add_constraint.assert_not_called()
|
||||
|
||||
# Should update instance object
|
||||
assert instance.found_violated_lazy_constraints == ["c3", "c4", "c2"]
|
||||
|
||||
|
||||
def test_fit():
|
||||
instance_1 = Mock(spec=Instance)
|
||||
instance_1.found_violated_lazy_constraints = ["c1", "c2", "c4", "c5"]
|
||||
instance_1.get_constraint_category = Mock(
|
||||
side_effect=lambda cid: {
|
||||
"c1": "type-a",
|
||||
"c2": "type-a",
|
||||
"c3": "type-a",
|
||||
"c4": "type-b",
|
||||
"c5": "type-b",
|
||||
}[cid]
|
||||
)
|
||||
instance_1.get_constraint_features = Mock(
|
||||
side_effect=lambda cid: {
|
||||
"c1": [1, 1],
|
||||
"c2": [1, 2],
|
||||
"c3": [1, 3],
|
||||
"c4": [1, 4, 0],
|
||||
"c5": [1, 5, 0],
|
||||
}[cid]
|
||||
)
|
||||
|
||||
instance_2 = Mock(spec=Instance)
|
||||
instance_2.found_violated_lazy_constraints = ["c2", "c3", "c4"]
|
||||
instance_2.get_constraint_category = Mock(
|
||||
side_effect=lambda cid: {
|
||||
"c1": "type-a",
|
||||
"c2": "type-a",
|
||||
"c3": "type-a",
|
||||
"c4": "type-b",
|
||||
"c5": "type-b",
|
||||
}[cid]
|
||||
)
|
||||
instance_2.get_constraint_features = Mock(
|
||||
side_effect=lambda cid: {
|
||||
"c1": [2, 1],
|
||||
"c2": [2, 2],
|
||||
"c3": [2, 3],
|
||||
"c4": [2, 4, 0],
|
||||
"c5": [2, 5, 0],
|
||||
}[cid]
|
||||
)
|
||||
|
||||
instances = [instance_1, instance_2]
|
||||
component = StaticLazyConstraintsComponent()
|
||||
component.classifiers = {
|
||||
"type-a": Mock(spec=Classifier),
|
||||
"type-b": Mock(spec=Classifier),
|
||||
}
|
||||
|
||||
expected_constraints = {
|
||||
"type-a": ["c1", "c2", "c3"],
|
||||
"type-b": ["c4", "c5"],
|
||||
}
|
||||
expected_x = {
|
||||
"type-a": [[1, 1], [1, 2], [1, 3], [2, 1], [2, 2], [2, 3]],
|
||||
"type-b": [[1, 4, 0], [1, 5, 0], [2, 4, 0], [2, 5, 0]],
|
||||
}
|
||||
expected_y = {
|
||||
"type-a": [[0, 1], [0, 1], [1, 0], [1, 0], [0, 1], [0, 1]],
|
||||
"type-b": [[0, 1], [0, 1], [0, 1], [1, 0]],
|
||||
}
|
||||
assert component._collect_constraints(instances) == expected_constraints
|
||||
assert component.x(instances) == expected_x
|
||||
assert component.y(instances) == expected_y
|
||||
|
||||
component.fit(instances)
|
||||
component.classifiers["type-a"].fit.assert_called_once_with(
|
||||
expected_x["type-a"],
|
||||
expected_y["type-a"],
|
||||
)
|
||||
component.classifiers["type-b"].fit.assert_called_once_with(
|
||||
expected_x["type-b"],
|
||||
expected_y["type-b"],
|
||||
)</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-functions">Functions</h2>
|
||||
<dl>
|
||||
<dt id="miplearn.components.tests.test_lazy_static.test_fit"><code class="name flex">
|
||||
<span>def <span class="ident">test_fit</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_fit():
|
||||
instance_1 = Mock(spec=Instance)
|
||||
instance_1.found_violated_lazy_constraints = ["c1", "c2", "c4", "c5"]
|
||||
instance_1.get_constraint_category = Mock(
|
||||
side_effect=lambda cid: {
|
||||
"c1": "type-a",
|
||||
"c2": "type-a",
|
||||
"c3": "type-a",
|
||||
"c4": "type-b",
|
||||
"c5": "type-b",
|
||||
}[cid]
|
||||
)
|
||||
instance_1.get_constraint_features = Mock(
|
||||
side_effect=lambda cid: {
|
||||
"c1": [1, 1],
|
||||
"c2": [1, 2],
|
||||
"c3": [1, 3],
|
||||
"c4": [1, 4, 0],
|
||||
"c5": [1, 5, 0],
|
||||
}[cid]
|
||||
)
|
||||
|
||||
instance_2 = Mock(spec=Instance)
|
||||
instance_2.found_violated_lazy_constraints = ["c2", "c3", "c4"]
|
||||
instance_2.get_constraint_category = Mock(
|
||||
side_effect=lambda cid: {
|
||||
"c1": "type-a",
|
||||
"c2": "type-a",
|
||||
"c3": "type-a",
|
||||
"c4": "type-b",
|
||||
"c5": "type-b",
|
||||
}[cid]
|
||||
)
|
||||
instance_2.get_constraint_features = Mock(
|
||||
side_effect=lambda cid: {
|
||||
"c1": [2, 1],
|
||||
"c2": [2, 2],
|
||||
"c3": [2, 3],
|
||||
"c4": [2, 4, 0],
|
||||
"c5": [2, 5, 0],
|
||||
}[cid]
|
||||
)
|
||||
|
||||
instances = [instance_1, instance_2]
|
||||
component = StaticLazyConstraintsComponent()
|
||||
component.classifiers = {
|
||||
"type-a": Mock(spec=Classifier),
|
||||
"type-b": Mock(spec=Classifier),
|
||||
}
|
||||
|
||||
expected_constraints = {
|
||||
"type-a": ["c1", "c2", "c3"],
|
||||
"type-b": ["c4", "c5"],
|
||||
}
|
||||
expected_x = {
|
||||
"type-a": [[1, 1], [1, 2], [1, 3], [2, 1], [2, 2], [2, 3]],
|
||||
"type-b": [[1, 4, 0], [1, 5, 0], [2, 4, 0], [2, 5, 0]],
|
||||
}
|
||||
expected_y = {
|
||||
"type-a": [[0, 1], [0, 1], [1, 0], [1, 0], [0, 1], [0, 1]],
|
||||
"type-b": [[0, 1], [0, 1], [0, 1], [1, 0]],
|
||||
}
|
||||
assert component._collect_constraints(instances) == expected_constraints
|
||||
assert component.x(instances) == expected_x
|
||||
assert component.y(instances) == expected_y
|
||||
|
||||
component.fit(instances)
|
||||
component.classifiers["type-a"].fit.assert_called_once_with(
|
||||
expected_x["type-a"],
|
||||
expected_y["type-a"],
|
||||
)
|
||||
component.classifiers["type-b"].fit.assert_called_once_with(
|
||||
expected_x["type-b"],
|
||||
expected_y["type-b"],
|
||||
)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.components.tests.test_lazy_static.test_usage_with_solver"><code class="name flex">
|
||||
<span>def <span class="ident">test_usage_with_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_usage_with_solver():
|
||||
solver = Mock(spec=LearningSolver)
|
||||
solver.use_lazy_cb = False
|
||||
solver.gap_tolerance = 1e-4
|
||||
|
||||
internal = solver.internal_solver = Mock(spec=InternalSolver)
|
||||
internal.get_constraint_ids = Mock(return_value=["c1", "c2", "c3", "c4"])
|
||||
internal.extract_constraint = Mock(side_effect=lambda cid: "<%s>" % cid)
|
||||
internal.is_constraint_satisfied = Mock(return_value=False)
|
||||
|
||||
instance = Mock(spec=Instance)
|
||||
instance.has_static_lazy_constraints = Mock(return_value=True)
|
||||
instance.is_constraint_lazy = Mock(
|
||||
side_effect=lambda cid: {
|
||||
"c1": False,
|
||||
"c2": True,
|
||||
"c3": True,
|
||||
"c4": True,
|
||||
}[cid]
|
||||
)
|
||||
instance.get_constraint_features = Mock(
|
||||
side_effect=lambda cid: {
|
||||
"c2": [1.0, 0.0],
|
||||
"c3": [0.5, 0.5],
|
||||
"c4": [1.0],
|
||||
}[cid]
|
||||
)
|
||||
instance.get_constraint_category = Mock(
|
||||
side_effect=lambda cid: {
|
||||
"c2": "type-a",
|
||||
"c3": "type-a",
|
||||
"c4": "type-b",
|
||||
}[cid]
|
||||
)
|
||||
|
||||
component = StaticLazyConstraintsComponent(
|
||||
threshold=0.90,
|
||||
use_two_phase_gap=False,
|
||||
violation_tolerance=1.0,
|
||||
)
|
||||
component.classifiers = {
|
||||
"type-a": Mock(spec=Classifier),
|
||||
"type-b": Mock(spec=Classifier),
|
||||
}
|
||||
component.classifiers["type-a"].predict_proba = Mock(
|
||||
return_value=[
|
||||
[0.20, 0.80],
|
||||
[0.05, 0.95],
|
||||
]
|
||||
)
|
||||
component.classifiers["type-b"].predict_proba = Mock(
|
||||
return_value=[
|
||||
[0.02, 0.98],
|
||||
]
|
||||
)
|
||||
|
||||
# LearningSolver calls before_solve
|
||||
component.before_solve(solver, instance, None)
|
||||
|
||||
# Should ask if instance has static lazy constraints
|
||||
instance.has_static_lazy_constraints.assert_called_once()
|
||||
|
||||
# Should ask internal solver for a list of constraints in the model
|
||||
internal.get_constraint_ids.assert_called_once()
|
||||
|
||||
# Should ask if each constraint in the model is lazy
|
||||
instance.is_constraint_lazy.assert_has_calls(
|
||||
[
|
||||
call("c1"),
|
||||
call("c2"),
|
||||
call("c3"),
|
||||
call("c4"),
|
||||
]
|
||||
)
|
||||
|
||||
# For the lazy ones, should ask for features
|
||||
instance.get_constraint_features.assert_has_calls(
|
||||
[
|
||||
call("c2"),
|
||||
call("c3"),
|
||||
call("c4"),
|
||||
]
|
||||
)
|
||||
|
||||
# Should also ask for categories
|
||||
assert instance.get_constraint_category.call_count == 3
|
||||
instance.get_constraint_category.assert_has_calls(
|
||||
[
|
||||
call("c2"),
|
||||
call("c3"),
|
||||
call("c4"),
|
||||
]
|
||||
)
|
||||
|
||||
# Should ask internal solver to remove constraints identified as lazy
|
||||
assert internal.extract_constraint.call_count == 3
|
||||
internal.extract_constraint.assert_has_calls(
|
||||
[
|
||||
call("c2"),
|
||||
call("c3"),
|
||||
call("c4"),
|
||||
]
|
||||
)
|
||||
|
||||
# Should ask ML to predict whether each lazy constraint should be enforced
|
||||
component.classifiers["type-a"].predict_proba.assert_called_once_with(
|
||||
[[1.0, 0.0], [0.5, 0.5]]
|
||||
)
|
||||
component.classifiers["type-b"].predict_proba.assert_called_once_with([[1.0]])
|
||||
|
||||
# For the ones that should be enforced, should ask solver to re-add them
|
||||
# to the formulation. The remaining ones should remain in the pool.
|
||||
assert internal.add_constraint.call_count == 2
|
||||
internal.add_constraint.assert_has_calls(
|
||||
[
|
||||
call("<c3>"),
|
||||
call("<c4>"),
|
||||
]
|
||||
)
|
||||
internal.add_constraint.reset_mock()
|
||||
|
||||
# LearningSolver calls after_iteration (first time)
|
||||
should_repeat = component.iteration_cb(solver, instance, None)
|
||||
assert should_repeat
|
||||
|
||||
# Should ask internal solver to verify if constraints in the pool are
|
||||
# satisfied and add the ones that are not
|
||||
internal.is_constraint_satisfied.assert_called_once_with("<c2>", tol=1.0)
|
||||
internal.is_constraint_satisfied.reset_mock()
|
||||
internal.add_constraint.assert_called_once_with("<c2>")
|
||||
internal.add_constraint.reset_mock()
|
||||
|
||||
# LearningSolver calls after_iteration (second time)
|
||||
should_repeat = component.iteration_cb(solver, instance, None)
|
||||
assert not should_repeat
|
||||
|
||||
# The lazy constraint pool should be empty by now, so no calls should be made
|
||||
internal.is_constraint_satisfied.assert_not_called()
|
||||
internal.add_constraint.assert_not_called()
|
||||
|
||||
# Should update instance object
|
||||
assert instance.found_violated_lazy_constraints == ["c3", "c4", "c2"]</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.components.tests" href="index.html">miplearn.components.tests</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-functions">Functions</a></h3>
|
||||
<ul class="">
|
||||
<li><code><a title="miplearn.components.tests.test_lazy_static.test_fit" href="#miplearn.components.tests.test_lazy_static.test_fit">test_fit</a></code></li>
|
||||
<li><code><a title="miplearn.components.tests.test_lazy_static.test_usage_with_solver" href="#miplearn.components.tests.test_lazy_static.test_usage_with_solver">test_usage_with_solver</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>
|
||||
174
0.2/api/miplearn/components/tests/test_objective.html
Normal file
174
0.2/api/miplearn/components/tests/test_objective.html
Normal 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.components.tests.test_objective 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.components.tests.test_objective</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 unittest.mock import Mock
|
||||
|
||||
import numpy as np
|
||||
|
||||
from miplearn.classifiers import Regressor
|
||||
from miplearn.components.objective import ObjectiveValueComponent
|
||||
from miplearn.tests import get_test_pyomo_instances
|
||||
|
||||
|
||||
def test_usage():
|
||||
instances, models = get_test_pyomo_instances()
|
||||
comp = ObjectiveValueComponent()
|
||||
comp.fit(instances)
|
||||
assert instances[0].training_data[0]["Lower bound"] == 1183.0
|
||||
assert instances[0].training_data[0]["Upper bound"] == 1183.0
|
||||
assert np.round(comp.predict(instances), 2).tolist() == [
|
||||
[1183.0, 1183.0],
|
||||
[1070.0, 1070.0],
|
||||
]
|
||||
|
||||
|
||||
def test_obj_evaluate():
|
||||
instances, models = get_test_pyomo_instances()
|
||||
reg = Mock(spec=Regressor)
|
||||
reg.predict = Mock(return_value=np.array([1000.0, 1000.0]))
|
||||
comp = ObjectiveValueComponent(regressor=reg)
|
||||
comp.fit(instances)
|
||||
ev = comp.evaluate(instances)
|
||||
assert ev == {
|
||||
"Lower bound": {
|
||||
"Explained variance": 0.0,
|
||||
"Max error": 183.0,
|
||||
"Mean absolute error": 126.5,
|
||||
"Mean squared error": 19194.5,
|
||||
"Median absolute error": 126.5,
|
||||
"R2": -5.012843605607331,
|
||||
},
|
||||
"Upper bound": {
|
||||
"Explained variance": 0.0,
|
||||
"Max error": 183.0,
|
||||
"Mean absolute error": 126.5,
|
||||
"Mean squared error": 19194.5,
|
||||
"Median absolute error": 126.5,
|
||||
"R2": -5.012843605607331,
|
||||
},
|
||||
}</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-functions">Functions</h2>
|
||||
<dl>
|
||||
<dt id="miplearn.components.tests.test_objective.test_obj_evaluate"><code class="name flex">
|
||||
<span>def <span class="ident">test_obj_evaluate</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_obj_evaluate():
|
||||
instances, models = get_test_pyomo_instances()
|
||||
reg = Mock(spec=Regressor)
|
||||
reg.predict = Mock(return_value=np.array([1000.0, 1000.0]))
|
||||
comp = ObjectiveValueComponent(regressor=reg)
|
||||
comp.fit(instances)
|
||||
ev = comp.evaluate(instances)
|
||||
assert ev == {
|
||||
"Lower bound": {
|
||||
"Explained variance": 0.0,
|
||||
"Max error": 183.0,
|
||||
"Mean absolute error": 126.5,
|
||||
"Mean squared error": 19194.5,
|
||||
"Median absolute error": 126.5,
|
||||
"R2": -5.012843605607331,
|
||||
},
|
||||
"Upper bound": {
|
||||
"Explained variance": 0.0,
|
||||
"Max error": 183.0,
|
||||
"Mean absolute error": 126.5,
|
||||
"Mean squared error": 19194.5,
|
||||
"Median absolute error": 126.5,
|
||||
"R2": -5.012843605607331,
|
||||
},
|
||||
}</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.components.tests.test_objective.test_usage"><code class="name flex">
|
||||
<span>def <span class="ident">test_usage</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_usage():
|
||||
instances, models = get_test_pyomo_instances()
|
||||
comp = ObjectiveValueComponent()
|
||||
comp.fit(instances)
|
||||
assert instances[0].training_data[0]["Lower bound"] == 1183.0
|
||||
assert instances[0].training_data[0]["Upper bound"] == 1183.0
|
||||
assert np.round(comp.predict(instances), 2).tolist() == [
|
||||
[1183.0, 1183.0],
|
||||
[1070.0, 1070.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.components.tests" href="index.html">miplearn.components.tests</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-functions">Functions</a></h3>
|
||||
<ul class="">
|
||||
<li><code><a title="miplearn.components.tests.test_objective.test_obj_evaluate" href="#miplearn.components.tests.test_objective.test_obj_evaluate">test_obj_evaluate</a></code></li>
|
||||
<li><code><a title="miplearn.components.tests.test_objective.test_usage" href="#miplearn.components.tests.test_objective.test_usage">test_usage</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>
|
||||
306
0.2/api/miplearn/components/tests/test_primal.html
Normal file
306
0.2/api/miplearn/components/tests/test_primal.html
Normal file
@@ -0,0 +1,306 @@
|
||||
<!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.components.tests.test_primal 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.components.tests.test_primal</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 unittest.mock import Mock
|
||||
|
||||
import numpy as np
|
||||
|
||||
from miplearn.classifiers import Classifier
|
||||
from miplearn.components.primal import PrimalSolutionComponent
|
||||
from miplearn.tests import get_test_pyomo_instances
|
||||
|
||||
|
||||
def test_predict():
|
||||
instances, models = get_test_pyomo_instances()
|
||||
comp = PrimalSolutionComponent()
|
||||
comp.fit(instances)
|
||||
solution = comp.predict(instances[0])
|
||||
assert "x" in solution
|
||||
assert 0 in solution["x"]
|
||||
assert 1 in solution["x"]
|
||||
assert 2 in solution["x"]
|
||||
assert 3 in solution["x"]
|
||||
|
||||
|
||||
def test_evaluate():
|
||||
instances, models = get_test_pyomo_instances()
|
||||
clf_zero = Mock(spec=Classifier)
|
||||
clf_zero.predict_proba = Mock(
|
||||
return_value=np.array(
|
||||
[
|
||||
[0.0, 1.0], # x[0]
|
||||
[0.0, 1.0], # x[1]
|
||||
[1.0, 0.0], # x[2]
|
||||
[1.0, 0.0], # x[3]
|
||||
]
|
||||
)
|
||||
)
|
||||
clf_one = Mock(spec=Classifier)
|
||||
clf_one.predict_proba = Mock(
|
||||
return_value=np.array(
|
||||
[
|
||||
[1.0, 0.0], # x[0] instances[0]
|
||||
[1.0, 0.0], # x[1] instances[0]
|
||||
[0.0, 1.0], # x[2] instances[0]
|
||||
[1.0, 0.0], # x[3] instances[0]
|
||||
]
|
||||
)
|
||||
)
|
||||
comp = PrimalSolutionComponent(classifier=[clf_zero, clf_one], threshold=0.50)
|
||||
comp.fit(instances[:1])
|
||||
assert comp.predict(instances[0]) == {"x": {0: 0, 1: 0, 2: 1, 3: None}}
|
||||
assert instances[0].training_data[0]["Solution"] == {"x": {0: 1, 1: 0, 2: 1, 3: 1}}
|
||||
ev = comp.evaluate(instances[:1])
|
||||
assert ev == {
|
||||
"Fix one": {
|
||||
0: {
|
||||
"Accuracy": 0.5,
|
||||
"Condition negative": 1,
|
||||
"Condition negative (%)": 25.0,
|
||||
"Condition positive": 3,
|
||||
"Condition positive (%)": 75.0,
|
||||
"F1 score": 0.5,
|
||||
"False negative": 2,
|
||||
"False negative (%)": 50.0,
|
||||
"False positive": 0,
|
||||
"False positive (%)": 0.0,
|
||||
"Precision": 1.0,
|
||||
"Predicted negative": 3,
|
||||
"Predicted negative (%)": 75.0,
|
||||
"Predicted positive": 1,
|
||||
"Predicted positive (%)": 25.0,
|
||||
"Recall": 0.3333333333333333,
|
||||
"True negative": 1,
|
||||
"True negative (%)": 25.0,
|
||||
"True positive": 1,
|
||||
"True positive (%)": 25.0,
|
||||
}
|
||||
},
|
||||
"Fix zero": {
|
||||
0: {
|
||||
"Accuracy": 0.75,
|
||||
"Condition negative": 3,
|
||||
"Condition negative (%)": 75.0,
|
||||
"Condition positive": 1,
|
||||
"Condition positive (%)": 25.0,
|
||||
"F1 score": 0.6666666666666666,
|
||||
"False negative": 0,
|
||||
"False negative (%)": 0.0,
|
||||
"False positive": 1,
|
||||
"False positive (%)": 25.0,
|
||||
"Precision": 0.5,
|
||||
"Predicted negative": 2,
|
||||
"Predicted negative (%)": 50.0,
|
||||
"Predicted positive": 2,
|
||||
"Predicted positive (%)": 50.0,
|
||||
"Recall": 1.0,
|
||||
"True negative": 2,
|
||||
"True negative (%)": 50.0,
|
||||
"True positive": 1,
|
||||
"True positive (%)": 25.0,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def test_primal_parallel_fit():
|
||||
instances, models = get_test_pyomo_instances()
|
||||
comp = PrimalSolutionComponent()
|
||||
comp.fit(instances, n_jobs=2)
|
||||
assert len(comp.classifiers) == 2</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-functions">Functions</h2>
|
||||
<dl>
|
||||
<dt id="miplearn.components.tests.test_primal.test_evaluate"><code class="name flex">
|
||||
<span>def <span class="ident">test_evaluate</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_evaluate():
|
||||
instances, models = get_test_pyomo_instances()
|
||||
clf_zero = Mock(spec=Classifier)
|
||||
clf_zero.predict_proba = Mock(
|
||||
return_value=np.array(
|
||||
[
|
||||
[0.0, 1.0], # x[0]
|
||||
[0.0, 1.0], # x[1]
|
||||
[1.0, 0.0], # x[2]
|
||||
[1.0, 0.0], # x[3]
|
||||
]
|
||||
)
|
||||
)
|
||||
clf_one = Mock(spec=Classifier)
|
||||
clf_one.predict_proba = Mock(
|
||||
return_value=np.array(
|
||||
[
|
||||
[1.0, 0.0], # x[0] instances[0]
|
||||
[1.0, 0.0], # x[1] instances[0]
|
||||
[0.0, 1.0], # x[2] instances[0]
|
||||
[1.0, 0.0], # x[3] instances[0]
|
||||
]
|
||||
)
|
||||
)
|
||||
comp = PrimalSolutionComponent(classifier=[clf_zero, clf_one], threshold=0.50)
|
||||
comp.fit(instances[:1])
|
||||
assert comp.predict(instances[0]) == {"x": {0: 0, 1: 0, 2: 1, 3: None}}
|
||||
assert instances[0].training_data[0]["Solution"] == {"x": {0: 1, 1: 0, 2: 1, 3: 1}}
|
||||
ev = comp.evaluate(instances[:1])
|
||||
assert ev == {
|
||||
"Fix one": {
|
||||
0: {
|
||||
"Accuracy": 0.5,
|
||||
"Condition negative": 1,
|
||||
"Condition negative (%)": 25.0,
|
||||
"Condition positive": 3,
|
||||
"Condition positive (%)": 75.0,
|
||||
"F1 score": 0.5,
|
||||
"False negative": 2,
|
||||
"False negative (%)": 50.0,
|
||||
"False positive": 0,
|
||||
"False positive (%)": 0.0,
|
||||
"Precision": 1.0,
|
||||
"Predicted negative": 3,
|
||||
"Predicted negative (%)": 75.0,
|
||||
"Predicted positive": 1,
|
||||
"Predicted positive (%)": 25.0,
|
||||
"Recall": 0.3333333333333333,
|
||||
"True negative": 1,
|
||||
"True negative (%)": 25.0,
|
||||
"True positive": 1,
|
||||
"True positive (%)": 25.0,
|
||||
}
|
||||
},
|
||||
"Fix zero": {
|
||||
0: {
|
||||
"Accuracy": 0.75,
|
||||
"Condition negative": 3,
|
||||
"Condition negative (%)": 75.0,
|
||||
"Condition positive": 1,
|
||||
"Condition positive (%)": 25.0,
|
||||
"F1 score": 0.6666666666666666,
|
||||
"False negative": 0,
|
||||
"False negative (%)": 0.0,
|
||||
"False positive": 1,
|
||||
"False positive (%)": 25.0,
|
||||
"Precision": 0.5,
|
||||
"Predicted negative": 2,
|
||||
"Predicted negative (%)": 50.0,
|
||||
"Predicted positive": 2,
|
||||
"Predicted positive (%)": 50.0,
|
||||
"Recall": 1.0,
|
||||
"True negative": 2,
|
||||
"True negative (%)": 50.0,
|
||||
"True positive": 1,
|
||||
"True positive (%)": 25.0,
|
||||
}
|
||||
},
|
||||
}</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.components.tests.test_primal.test_predict"><code class="name flex">
|
||||
<span>def <span class="ident">test_predict</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_predict():
|
||||
instances, models = get_test_pyomo_instances()
|
||||
comp = PrimalSolutionComponent()
|
||||
comp.fit(instances)
|
||||
solution = comp.predict(instances[0])
|
||||
assert "x" in solution
|
||||
assert 0 in solution["x"]
|
||||
assert 1 in solution["x"]
|
||||
assert 2 in solution["x"]
|
||||
assert 3 in solution["x"]</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.components.tests.test_primal.test_primal_parallel_fit"><code class="name flex">
|
||||
<span>def <span class="ident">test_primal_parallel_fit</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_primal_parallel_fit():
|
||||
instances, models = get_test_pyomo_instances()
|
||||
comp = PrimalSolutionComponent()
|
||||
comp.fit(instances, n_jobs=2)
|
||||
assert len(comp.classifiers) == 2</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.components.tests" href="index.html">miplearn.components.tests</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-functions">Functions</a></h3>
|
||||
<ul class="">
|
||||
<li><code><a title="miplearn.components.tests.test_primal.test_evaluate" href="#miplearn.components.tests.test_primal.test_evaluate">test_evaluate</a></code></li>
|
||||
<li><code><a title="miplearn.components.tests.test_primal.test_predict" href="#miplearn.components.tests.test_primal.test_predict">test_predict</a></code></li>
|
||||
<li><code><a title="miplearn.components.tests.test_primal.test_primal_parallel_fit" href="#miplearn.components.tests.test_primal.test_primal_parallel_fit">test_primal_parallel_fit</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>
|
||||
680
0.2/api/miplearn/extractors.html
Normal file
680
0.2/api/miplearn/extractors.html
Normal file
@@ -0,0 +1,680 @@
|
||||
<!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.extractors 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.extractors</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 gzip
|
||||
import logging
|
||||
import pickle
|
||||
from abc import ABC, abstractmethod
|
||||
|
||||
import numpy as np
|
||||
from tqdm.auto import tqdm
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class InstanceIterator:
|
||||
def __init__(self, instances):
|
||||
self.instances = instances
|
||||
self.current = 0
|
||||
|
||||
def __iter__(self):
|
||||
return self
|
||||
|
||||
def __next__(self):
|
||||
if self.current >= len(self.instances):
|
||||
raise StopIteration
|
||||
result = self.instances[self.current]
|
||||
self.current += 1
|
||||
if isinstance(result, str):
|
||||
logger.debug("Read: %s" % result)
|
||||
try:
|
||||
if result.endswith(".gz"):
|
||||
with gzip.GzipFile(result, "rb") as file:
|
||||
result = pickle.load(file)
|
||||
else:
|
||||
with open(result, "rb") as file:
|
||||
result = pickle.load(file)
|
||||
except pickle.UnpicklingError:
|
||||
raise Exception(f"Invalid instance file: {result}")
|
||||
return result
|
||||
|
||||
|
||||
class Extractor(ABC):
|
||||
@abstractmethod
|
||||
def extract(self, instances):
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def split_variables(instance):
|
||||
result = {}
|
||||
lp_solution = instance.training_data[0]["LP solution"]
|
||||
for var_name in lp_solution:
|
||||
for index in lp_solution[var_name]:
|
||||
category = instance.get_variable_category(var_name, index)
|
||||
if category is None:
|
||||
continue
|
||||
if category not in result:
|
||||
result[category] = []
|
||||
result[category] += [(var_name, index)]
|
||||
return result
|
||||
|
||||
|
||||
class VariableFeaturesExtractor(Extractor):
|
||||
def extract(self, instances):
|
||||
result = {}
|
||||
for instance in tqdm(
|
||||
InstanceIterator(instances),
|
||||
desc="Extract (vars)",
|
||||
disable=len(instances) < 5,
|
||||
):
|
||||
instance_features = instance.get_instance_features()
|
||||
var_split = self.split_variables(instance)
|
||||
lp_solution = instance.training_data[0]["LP solution"]
|
||||
for (category, var_index_pairs) in var_split.items():
|
||||
if category not in result:
|
||||
result[category] = []
|
||||
for (var_name, index) in var_index_pairs:
|
||||
result[category] += [
|
||||
instance_features.tolist()
|
||||
+ instance.get_variable_features(var_name, index).tolist()
|
||||
+ [lp_solution[var_name][index]]
|
||||
]
|
||||
for category in result:
|
||||
result[category] = np.array(result[category])
|
||||
return result
|
||||
|
||||
|
||||
class SolutionExtractor(Extractor):
|
||||
def __init__(self, relaxation=False):
|
||||
self.relaxation = relaxation
|
||||
|
||||
def extract(self, instances):
|
||||
result = {}
|
||||
for instance in tqdm(
|
||||
InstanceIterator(instances),
|
||||
desc="Extract (solution)",
|
||||
disable=len(instances) < 5,
|
||||
):
|
||||
var_split = self.split_variables(instance)
|
||||
if self.relaxation:
|
||||
solution = instance.training_data[0]["LP solution"]
|
||||
else:
|
||||
solution = instance.training_data[0]["Solution"]
|
||||
for (category, var_index_pairs) in var_split.items():
|
||||
if category not in result:
|
||||
result[category] = []
|
||||
for (var_name, index) in var_index_pairs:
|
||||
v = solution[var_name][index]
|
||||
if v is None:
|
||||
result[category] += [[0, 0]]
|
||||
else:
|
||||
result[category] += [[1 - v, v]]
|
||||
for category in result:
|
||||
result[category] = np.array(result[category])
|
||||
return result
|
||||
|
||||
|
||||
class InstanceFeaturesExtractor(Extractor):
|
||||
def extract(self, instances):
|
||||
return np.vstack(
|
||||
[
|
||||
np.hstack(
|
||||
[
|
||||
instance.get_instance_features(),
|
||||
instance.training_data[0]["LP value"],
|
||||
]
|
||||
)
|
||||
for instance in InstanceIterator(instances)
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
class ObjectiveValueExtractor(Extractor):
|
||||
def __init__(self, kind="lp"):
|
||||
assert kind in ["lower bound", "upper bound", "lp"]
|
||||
self.kind = kind
|
||||
|
||||
def extract(self, instances):
|
||||
if self.kind == "lower bound":
|
||||
return np.array(
|
||||
[
|
||||
[instance.training_data[0]["Lower bound"]]
|
||||
for instance in InstanceIterator(instances)
|
||||
]
|
||||
)
|
||||
if self.kind == "upper bound":
|
||||
return np.array(
|
||||
[
|
||||
[instance.training_data[0]["Upper bound"]]
|
||||
for instance in InstanceIterator(instances)
|
||||
]
|
||||
)
|
||||
if self.kind == "lp":
|
||||
return np.array(
|
||||
[
|
||||
[instance.training_data[0]["LP value"]]
|
||||
for instance in InstanceIterator(instances)
|
||||
]
|
||||
)</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-classes">Classes</h2>
|
||||
<dl>
|
||||
<dt id="miplearn.extractors.Extractor"><code class="flex name class">
|
||||
<span>class <span class="ident">Extractor</span></span>
|
||||
<span>(</span><span>*args, **kwargs)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"><p>Helper class that provides a standard way to create an ABC using
|
||||
inheritance.</p></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">class Extractor(ABC):
|
||||
@abstractmethod
|
||||
def extract(self, instances):
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def split_variables(instance):
|
||||
result = {}
|
||||
lp_solution = instance.training_data[0]["LP solution"]
|
||||
for var_name in lp_solution:
|
||||
for index in lp_solution[var_name]:
|
||||
category = instance.get_variable_category(var_name, index)
|
||||
if category is None:
|
||||
continue
|
||||
if category not in result:
|
||||
result[category] = []
|
||||
result[category] += [(var_name, index)]
|
||||
return result</code></pre>
|
||||
</details>
|
||||
<h3>Ancestors</h3>
|
||||
<ul class="hlist">
|
||||
<li>abc.ABC</li>
|
||||
</ul>
|
||||
<h3>Subclasses</h3>
|
||||
<ul class="hlist">
|
||||
<li><a title="miplearn.extractors.VariableFeaturesExtractor" href="#miplearn.extractors.VariableFeaturesExtractor">VariableFeaturesExtractor</a></li>
|
||||
<li><a title="miplearn.extractors.SolutionExtractor" href="#miplearn.extractors.SolutionExtractor">SolutionExtractor</a></li>
|
||||
<li><a title="miplearn.extractors.InstanceFeaturesExtractor" href="#miplearn.extractors.InstanceFeaturesExtractor">InstanceFeaturesExtractor</a></li>
|
||||
<li><a title="miplearn.extractors.ObjectiveValueExtractor" href="#miplearn.extractors.ObjectiveValueExtractor">ObjectiveValueExtractor</a></li>
|
||||
</ul>
|
||||
<h3>Static methods</h3>
|
||||
<dl>
|
||||
<dt id="miplearn.extractors.Extractor.split_variables"><code class="name flex">
|
||||
<span>def <span class="ident">split_variables</span></span>(<span>instance)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">@staticmethod
|
||||
def split_variables(instance):
|
||||
result = {}
|
||||
lp_solution = instance.training_data[0]["LP solution"]
|
||||
for var_name in lp_solution:
|
||||
for index in lp_solution[var_name]:
|
||||
category = instance.get_variable_category(var_name, index)
|
||||
if category is None:
|
||||
continue
|
||||
if category not in result:
|
||||
result[category] = []
|
||||
result[category] += [(var_name, index)]
|
||||
return result</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>Methods</h3>
|
||||
<dl>
|
||||
<dt id="miplearn.extractors.Extractor.extract"><code class="name flex">
|
||||
<span>def <span class="ident">extract</span></span>(<span>self, instances)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">@abstractmethod
|
||||
def extract(self, instances):
|
||||
pass</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt id="miplearn.extractors.InstanceFeaturesExtractor"><code class="flex name class">
|
||||
<span>class <span class="ident">InstanceFeaturesExtractor</span></span>
|
||||
<span>(</span><span>*args, **kwargs)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"><p>Helper class that provides a standard way to create an ABC using
|
||||
inheritance.</p></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">class InstanceFeaturesExtractor(Extractor):
|
||||
def extract(self, instances):
|
||||
return np.vstack(
|
||||
[
|
||||
np.hstack(
|
||||
[
|
||||
instance.get_instance_features(),
|
||||
instance.training_data[0]["LP value"],
|
||||
]
|
||||
)
|
||||
for instance in InstanceIterator(instances)
|
||||
]
|
||||
)</code></pre>
|
||||
</details>
|
||||
<h3>Ancestors</h3>
|
||||
<ul class="hlist">
|
||||
<li><a title="miplearn.extractors.Extractor" href="#miplearn.extractors.Extractor">Extractor</a></li>
|
||||
<li>abc.ABC</li>
|
||||
</ul>
|
||||
<h3>Methods</h3>
|
||||
<dl>
|
||||
<dt id="miplearn.extractors.InstanceFeaturesExtractor.extract"><code class="name flex">
|
||||
<span>def <span class="ident">extract</span></span>(<span>self, instances)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def extract(self, instances):
|
||||
return np.vstack(
|
||||
[
|
||||
np.hstack(
|
||||
[
|
||||
instance.get_instance_features(),
|
||||
instance.training_data[0]["LP value"],
|
||||
]
|
||||
)
|
||||
for instance in InstanceIterator(instances)
|
||||
]
|
||||
)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt id="miplearn.extractors.InstanceIterator"><code class="flex name class">
|
||||
<span>class <span class="ident">InstanceIterator</span></span>
|
||||
<span>(</span><span>instances)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">class InstanceIterator:
|
||||
def __init__(self, instances):
|
||||
self.instances = instances
|
||||
self.current = 0
|
||||
|
||||
def __iter__(self):
|
||||
return self
|
||||
|
||||
def __next__(self):
|
||||
if self.current >= len(self.instances):
|
||||
raise StopIteration
|
||||
result = self.instances[self.current]
|
||||
self.current += 1
|
||||
if isinstance(result, str):
|
||||
logger.debug("Read: %s" % result)
|
||||
try:
|
||||
if result.endswith(".gz"):
|
||||
with gzip.GzipFile(result, "rb") as file:
|
||||
result = pickle.load(file)
|
||||
else:
|
||||
with open(result, "rb") as file:
|
||||
result = pickle.load(file)
|
||||
except pickle.UnpicklingError:
|
||||
raise Exception(f"Invalid instance file: {result}")
|
||||
return result</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.extractors.ObjectiveValueExtractor"><code class="flex name class">
|
||||
<span>class <span class="ident">ObjectiveValueExtractor</span></span>
|
||||
<span>(</span><span>kind='lp')</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"><p>Helper class that provides a standard way to create an ABC using
|
||||
inheritance.</p></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">class ObjectiveValueExtractor(Extractor):
|
||||
def __init__(self, kind="lp"):
|
||||
assert kind in ["lower bound", "upper bound", "lp"]
|
||||
self.kind = kind
|
||||
|
||||
def extract(self, instances):
|
||||
if self.kind == "lower bound":
|
||||
return np.array(
|
||||
[
|
||||
[instance.training_data[0]["Lower bound"]]
|
||||
for instance in InstanceIterator(instances)
|
||||
]
|
||||
)
|
||||
if self.kind == "upper bound":
|
||||
return np.array(
|
||||
[
|
||||
[instance.training_data[0]["Upper bound"]]
|
||||
for instance in InstanceIterator(instances)
|
||||
]
|
||||
)
|
||||
if self.kind == "lp":
|
||||
return np.array(
|
||||
[
|
||||
[instance.training_data[0]["LP value"]]
|
||||
for instance in InstanceIterator(instances)
|
||||
]
|
||||
)</code></pre>
|
||||
</details>
|
||||
<h3>Ancestors</h3>
|
||||
<ul class="hlist">
|
||||
<li><a title="miplearn.extractors.Extractor" href="#miplearn.extractors.Extractor">Extractor</a></li>
|
||||
<li>abc.ABC</li>
|
||||
</ul>
|
||||
<h3>Methods</h3>
|
||||
<dl>
|
||||
<dt id="miplearn.extractors.ObjectiveValueExtractor.extract"><code class="name flex">
|
||||
<span>def <span class="ident">extract</span></span>(<span>self, instances)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def extract(self, instances):
|
||||
if self.kind == "lower bound":
|
||||
return np.array(
|
||||
[
|
||||
[instance.training_data[0]["Lower bound"]]
|
||||
for instance in InstanceIterator(instances)
|
||||
]
|
||||
)
|
||||
if self.kind == "upper bound":
|
||||
return np.array(
|
||||
[
|
||||
[instance.training_data[0]["Upper bound"]]
|
||||
for instance in InstanceIterator(instances)
|
||||
]
|
||||
)
|
||||
if self.kind == "lp":
|
||||
return np.array(
|
||||
[
|
||||
[instance.training_data[0]["LP value"]]
|
||||
for instance in InstanceIterator(instances)
|
||||
]
|
||||
)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt id="miplearn.extractors.SolutionExtractor"><code class="flex name class">
|
||||
<span>class <span class="ident">SolutionExtractor</span></span>
|
||||
<span>(</span><span>relaxation=False)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"><p>Helper class that provides a standard way to create an ABC using
|
||||
inheritance.</p></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">class SolutionExtractor(Extractor):
|
||||
def __init__(self, relaxation=False):
|
||||
self.relaxation = relaxation
|
||||
|
||||
def extract(self, instances):
|
||||
result = {}
|
||||
for instance in tqdm(
|
||||
InstanceIterator(instances),
|
||||
desc="Extract (solution)",
|
||||
disable=len(instances) < 5,
|
||||
):
|
||||
var_split = self.split_variables(instance)
|
||||
if self.relaxation:
|
||||
solution = instance.training_data[0]["LP solution"]
|
||||
else:
|
||||
solution = instance.training_data[0]["Solution"]
|
||||
for (category, var_index_pairs) in var_split.items():
|
||||
if category not in result:
|
||||
result[category] = []
|
||||
for (var_name, index) in var_index_pairs:
|
||||
v = solution[var_name][index]
|
||||
if v is None:
|
||||
result[category] += [[0, 0]]
|
||||
else:
|
||||
result[category] += [[1 - v, v]]
|
||||
for category in result:
|
||||
result[category] = np.array(result[category])
|
||||
return result</code></pre>
|
||||
</details>
|
||||
<h3>Ancestors</h3>
|
||||
<ul class="hlist">
|
||||
<li><a title="miplearn.extractors.Extractor" href="#miplearn.extractors.Extractor">Extractor</a></li>
|
||||
<li>abc.ABC</li>
|
||||
</ul>
|
||||
<h3>Methods</h3>
|
||||
<dl>
|
||||
<dt id="miplearn.extractors.SolutionExtractor.extract"><code class="name flex">
|
||||
<span>def <span class="ident">extract</span></span>(<span>self, instances)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def extract(self, instances):
|
||||
result = {}
|
||||
for instance in tqdm(
|
||||
InstanceIterator(instances),
|
||||
desc="Extract (solution)",
|
||||
disable=len(instances) < 5,
|
||||
):
|
||||
var_split = self.split_variables(instance)
|
||||
if self.relaxation:
|
||||
solution = instance.training_data[0]["LP solution"]
|
||||
else:
|
||||
solution = instance.training_data[0]["Solution"]
|
||||
for (category, var_index_pairs) in var_split.items():
|
||||
if category not in result:
|
||||
result[category] = []
|
||||
for (var_name, index) in var_index_pairs:
|
||||
v = solution[var_name][index]
|
||||
if v is None:
|
||||
result[category] += [[0, 0]]
|
||||
else:
|
||||
result[category] += [[1 - v, v]]
|
||||
for category in result:
|
||||
result[category] = np.array(result[category])
|
||||
return result</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt id="miplearn.extractors.VariableFeaturesExtractor"><code class="flex name class">
|
||||
<span>class <span class="ident">VariableFeaturesExtractor</span></span>
|
||||
<span>(</span><span>*args, **kwargs)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"><p>Helper class that provides a standard way to create an ABC using
|
||||
inheritance.</p></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">class VariableFeaturesExtractor(Extractor):
|
||||
def extract(self, instances):
|
||||
result = {}
|
||||
for instance in tqdm(
|
||||
InstanceIterator(instances),
|
||||
desc="Extract (vars)",
|
||||
disable=len(instances) < 5,
|
||||
):
|
||||
instance_features = instance.get_instance_features()
|
||||
var_split = self.split_variables(instance)
|
||||
lp_solution = instance.training_data[0]["LP solution"]
|
||||
for (category, var_index_pairs) in var_split.items():
|
||||
if category not in result:
|
||||
result[category] = []
|
||||
for (var_name, index) in var_index_pairs:
|
||||
result[category] += [
|
||||
instance_features.tolist()
|
||||
+ instance.get_variable_features(var_name, index).tolist()
|
||||
+ [lp_solution[var_name][index]]
|
||||
]
|
||||
for category in result:
|
||||
result[category] = np.array(result[category])
|
||||
return result</code></pre>
|
||||
</details>
|
||||
<h3>Ancestors</h3>
|
||||
<ul class="hlist">
|
||||
<li><a title="miplearn.extractors.Extractor" href="#miplearn.extractors.Extractor">Extractor</a></li>
|
||||
<li>abc.ABC</li>
|
||||
</ul>
|
||||
<h3>Methods</h3>
|
||||
<dl>
|
||||
<dt id="miplearn.extractors.VariableFeaturesExtractor.extract"><code class="name flex">
|
||||
<span>def <span class="ident">extract</span></span>(<span>self, instances)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def extract(self, instances):
|
||||
result = {}
|
||||
for instance in tqdm(
|
||||
InstanceIterator(instances),
|
||||
desc="Extract (vars)",
|
||||
disable=len(instances) < 5,
|
||||
):
|
||||
instance_features = instance.get_instance_features()
|
||||
var_split = self.split_variables(instance)
|
||||
lp_solution = instance.training_data[0]["LP solution"]
|
||||
for (category, var_index_pairs) in var_split.items():
|
||||
if category not in result:
|
||||
result[category] = []
|
||||
for (var_name, index) in var_index_pairs:
|
||||
result[category] += [
|
||||
instance_features.tolist()
|
||||
+ instance.get_variable_features(var_name, index).tolist()
|
||||
+ [lp_solution[var_name][index]]
|
||||
]
|
||||
for category in result:
|
||||
result[category] = np.array(result[category])
|
||||
return result</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</section>
|
||||
</article>
|
||||
<nav id="sidebar">
|
||||
<h1>Index</h1>
|
||||
<div class="toc">
|
||||
<ul></ul>
|
||||
</div>
|
||||
<ul id="index">
|
||||
<li><h3>Super-module</h3>
|
||||
<ul>
|
||||
<li><code><a title="miplearn" href="index.html">miplearn</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-classes">Classes</a></h3>
|
||||
<ul>
|
||||
<li>
|
||||
<h4><code><a title="miplearn.extractors.Extractor" href="#miplearn.extractors.Extractor">Extractor</a></code></h4>
|
||||
<ul class="">
|
||||
<li><code><a title="miplearn.extractors.Extractor.extract" href="#miplearn.extractors.Extractor.extract">extract</a></code></li>
|
||||
<li><code><a title="miplearn.extractors.Extractor.split_variables" href="#miplearn.extractors.Extractor.split_variables">split_variables</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<h4><code><a title="miplearn.extractors.InstanceFeaturesExtractor" href="#miplearn.extractors.InstanceFeaturesExtractor">InstanceFeaturesExtractor</a></code></h4>
|
||||
<ul class="">
|
||||
<li><code><a title="miplearn.extractors.InstanceFeaturesExtractor.extract" href="#miplearn.extractors.InstanceFeaturesExtractor.extract">extract</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<h4><code><a title="miplearn.extractors.InstanceIterator" href="#miplearn.extractors.InstanceIterator">InstanceIterator</a></code></h4>
|
||||
</li>
|
||||
<li>
|
||||
<h4><code><a title="miplearn.extractors.ObjectiveValueExtractor" href="#miplearn.extractors.ObjectiveValueExtractor">ObjectiveValueExtractor</a></code></h4>
|
||||
<ul class="">
|
||||
<li><code><a title="miplearn.extractors.ObjectiveValueExtractor.extract" href="#miplearn.extractors.ObjectiveValueExtractor.extract">extract</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<h4><code><a title="miplearn.extractors.SolutionExtractor" href="#miplearn.extractors.SolutionExtractor">SolutionExtractor</a></code></h4>
|
||||
<ul class="">
|
||||
<li><code><a title="miplearn.extractors.SolutionExtractor.extract" href="#miplearn.extractors.SolutionExtractor.extract">extract</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<h4><code><a title="miplearn.extractors.VariableFeaturesExtractor" href="#miplearn.extractors.VariableFeaturesExtractor">VariableFeaturesExtractor</a></code></h4>
|
||||
<ul class="">
|
||||
<li><code><a title="miplearn.extractors.VariableFeaturesExtractor.extract" href="#miplearn.extractors.VariableFeaturesExtractor.extract">extract</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</main>
|
||||
<footer id="footer">
|
||||
<p>Generated by <a href="https://pdoc3.github.io/pdoc"><cite>pdoc</cite> 0.7.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>
|
||||
142
0.2/api/miplearn/index.html
Normal file
142
0.2/api/miplearn/index.html
Normal file
@@ -0,0 +1,142 @@
|
||||
<!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 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</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 .benchmark import BenchmarkRunner
|
||||
from .classifiers import Classifier, Regressor
|
||||
from .classifiers.adaptive import AdaptiveClassifier
|
||||
from .classifiers.threshold import MinPrecisionThreshold
|
||||
from .components.component import Component
|
||||
from .components.cuts import UserCutsComponent
|
||||
from .components.lazy_dynamic import DynamicLazyConstraintsComponent
|
||||
from .components.lazy_static import StaticLazyConstraintsComponent
|
||||
from .components.objective import ObjectiveValueComponent
|
||||
from .components.primal import PrimalSolutionComponent
|
||||
from .components.relaxation import RelaxationComponent
|
||||
from .components.steps.convert_tight import ConvertTightIneqsIntoEqsStep
|
||||
from .components.steps.drop_redundant import DropRedundantInequalitiesStep
|
||||
from .components.steps.relax_integrality import RelaxIntegralityStep
|
||||
from .extractors import (
|
||||
SolutionExtractor,
|
||||
InstanceFeaturesExtractor,
|
||||
ObjectiveValueExtractor,
|
||||
VariableFeaturesExtractor,
|
||||
)
|
||||
from .instance import Instance
|
||||
from .log import setup_logger
|
||||
from .solvers.gurobi import GurobiSolver
|
||||
from .solvers.internal import InternalSolver
|
||||
from .solvers.learning import LearningSolver
|
||||
from .solvers.pyomo.base import BasePyomoSolver
|
||||
from .solvers.pyomo.cplex import CplexPyomoSolver
|
||||
from .solvers.pyomo.gurobi import GurobiPyomoSolver</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-submodules">Sub-modules</h2>
|
||||
<dl>
|
||||
<dt><code class="name"><a title="miplearn.benchmark" href="benchmark.html">miplearn.benchmark</a></code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
</dd>
|
||||
<dt><code class="name"><a title="miplearn.classifiers" href="classifiers/index.html">miplearn.classifiers</a></code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
</dd>
|
||||
<dt><code class="name"><a title="miplearn.components" href="components/index.html">miplearn.components</a></code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
</dd>
|
||||
<dt><code class="name"><a title="miplearn.extractors" href="extractors.html">miplearn.extractors</a></code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
</dd>
|
||||
<dt><code class="name"><a title="miplearn.instance" href="instance.html">miplearn.instance</a></code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
</dd>
|
||||
<dt><code class="name"><a title="miplearn.log" href="log.html">miplearn.log</a></code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
</dd>
|
||||
<dt><code class="name"><a title="miplearn.problems" href="problems/index.html">miplearn.problems</a></code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
</dd>
|
||||
<dt><code class="name"><a title="miplearn.solvers" href="solvers/index.html">miplearn.solvers</a></code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
</dd>
|
||||
<dt><code class="name"><a title="miplearn.tests" href="tests/index.html">miplearn.tests</a></code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
</dd>
|
||||
<dt><code class="name"><a title="miplearn.types" href="types.html">miplearn.types</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><a href="#header-submodules">Sub-modules</a></h3>
|
||||
<ul>
|
||||
<li><code><a title="miplearn.benchmark" href="benchmark.html">miplearn.benchmark</a></code></li>
|
||||
<li><code><a title="miplearn.classifiers" href="classifiers/index.html">miplearn.classifiers</a></code></li>
|
||||
<li><code><a title="miplearn.components" href="components/index.html">miplearn.components</a></code></li>
|
||||
<li><code><a title="miplearn.extractors" href="extractors.html">miplearn.extractors</a></code></li>
|
||||
<li><code><a title="miplearn.instance" href="instance.html">miplearn.instance</a></code></li>
|
||||
<li><code><a title="miplearn.log" href="log.html">miplearn.log</a></code></li>
|
||||
<li><code><a title="miplearn.problems" href="problems/index.html">miplearn.problems</a></code></li>
|
||||
<li><code><a title="miplearn.solvers" href="solvers/index.html">miplearn.solvers</a></code></li>
|
||||
<li><code><a title="miplearn.tests" href="tests/index.html">miplearn.tests</a></code></li>
|
||||
<li><code><a title="miplearn.types" href="types.html">miplearn.types</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>
|
||||
775
0.2/api/miplearn/instance.html
Normal file
775
0.2/api/miplearn/instance.html
Normal file
@@ -0,0 +1,775 @@
|
||||
<!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.instance 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.instance</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 gzip
|
||||
import json
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import Any, List
|
||||
|
||||
import numpy as np
|
||||
|
||||
from miplearn.types import TrainingSample
|
||||
|
||||
|
||||
class Instance(ABC):
|
||||
"""
|
||||
Abstract class holding all the data necessary to generate a concrete model of the
|
||||
problem.
|
||||
|
||||
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.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.training_data: List[TrainingSample] = []
|
||||
|
||||
@abstractmethod
|
||||
def to_model(self) -> Any:
|
||||
"""
|
||||
Returns the optimization model corresponding to this instance.
|
||||
"""
|
||||
pass
|
||||
|
||||
def get_instance_features(self):
|
||||
"""
|
||||
Returns a 1-dimensional Numpy array of (numerical) features describing the
|
||||
entire instance.
|
||||
|
||||
The array is used by LearningSolver to determine how similar two instances
|
||||
are. It may also be used to predict, in combination with variable-specific
|
||||
features, the values of binary decision variables in the problem.
|
||||
|
||||
There is not necessarily a one-to-one correspondence between models and
|
||||
instance features: the features may encode only part of the data necessary to
|
||||
generate the complete model. Features may also be statistics computed from
|
||||
the original data. For example, in the knapsack problem, an implementation
|
||||
may decide to provide as instance features only the average weights, average
|
||||
prices, number of items and the size of the knapsack.
|
||||
|
||||
The returned array MUST have the same length for all relevant instances of
|
||||
the problem. If two instances map into arrays of different lengths,
|
||||
they cannot be solved by the same LearningSolver object.
|
||||
|
||||
By default, returns [0].
|
||||
"""
|
||||
return np.zeros(1)
|
||||
|
||||
def get_variable_features(self, var, index):
|
||||
"""
|
||||
Returns a 1-dimensional array of (numerical) features describing a particular
|
||||
decision variable.
|
||||
|
||||
The argument `var` is a pyomo.core.Var object, which represents a collection
|
||||
of decision variables. The argument `index` specifies which variable in the
|
||||
collection is the relevant one.
|
||||
|
||||
In combination with instance features, variable features are used by
|
||||
LearningSolver to predict, among other things, the optimal value of each
|
||||
decision variable before the optimization takes place. In the knapsack
|
||||
problem, for example, an implementation could provide as variable features
|
||||
the weight and the price of a specific item.
|
||||
|
||||
Like instance features, the arrays returned by this method MUST have the same
|
||||
length for all variables within the same category, for all relevant instances
|
||||
of the problem.
|
||||
|
||||
By default, returns [0].
|
||||
"""
|
||||
return np.zeros(1)
|
||||
|
||||
def get_variable_category(self, var, index):
|
||||
"""
|
||||
Returns the category (a string, an integer or any hashable type) for each
|
||||
decision variable.
|
||||
|
||||
If two variables have the same category, LearningSolver will use the same
|
||||
internal ML model to predict the values of both variables. If the returned
|
||||
category is None, ML models will ignore the variable.
|
||||
|
||||
By default, returns "default".
|
||||
"""
|
||||
return "default"
|
||||
|
||||
def get_constraint_features(self, cid):
|
||||
return np.zeros(1)
|
||||
|
||||
def get_constraint_category(self, cid):
|
||||
return cid
|
||||
|
||||
def has_static_lazy_constraints(self):
|
||||
return False
|
||||
|
||||
def has_dynamic_lazy_constraints(self):
|
||||
return False
|
||||
|
||||
def is_constraint_lazy(self, cid):
|
||||
return False
|
||||
|
||||
def find_violated_lazy_constraints(self, model):
|
||||
"""
|
||||
Returns lazy constraint violations found for the current solution.
|
||||
|
||||
After solving a model, LearningSolver will ask the instance to identify which
|
||||
lazy constraints are violated by the current solution. For each identified
|
||||
violation, LearningSolver will then call the build_lazy_constraint, add the
|
||||
generated Pyomo constraint to the model, then resolve the problem. The
|
||||
process repeats until no further lazy constraint violations are found.
|
||||
|
||||
Each "violation" is simply a string, a tuple or any other hashable type which
|
||||
allows the instance to identify unambiguously which lazy constraint should be
|
||||
generated. In the Traveling Salesman Problem, for example, a subtour
|
||||
violation could be a frozen set containing the cities in the subtour.
|
||||
|
||||
For a concrete example, see TravelingSalesmanInstance.
|
||||
"""
|
||||
return []
|
||||
|
||||
def build_lazy_constraint(self, model, violation):
|
||||
"""
|
||||
Returns a Pyomo constraint which fixes a given violation.
|
||||
|
||||
This method is typically called immediately after
|
||||
find_violated_lazy_constraints. The violation object provided to this method
|
||||
is exactly the same object returned earlier by
|
||||
find_violated_lazy_constraints. After some training, LearningSolver may
|
||||
decide to proactively build some lazy constraints at the beginning of the
|
||||
optimization process, before a solution is even available. In this case,
|
||||
build_lazy_constraints will be called without a corresponding call to
|
||||
find_violated_lazy_constraints.
|
||||
|
||||
The implementation should not directly add the constraint to the model. The
|
||||
constraint will be added by LearningSolver after the method returns.
|
||||
|
||||
For a concrete example, see TravelingSalesmanInstance.
|
||||
"""
|
||||
pass
|
||||
|
||||
def find_violated_user_cuts(self, model):
|
||||
return []
|
||||
|
||||
def build_user_cut(self, model, violation):
|
||||
pass
|
||||
|
||||
def load(self, filename):
|
||||
with gzip.GzipFile(filename, "r") as f:
|
||||
data = json.loads(f.read().decode("utf-8"))
|
||||
self.__dict__ = data
|
||||
|
||||
def dump(self, filename):
|
||||
data = json.dumps(self.__dict__, indent=2).encode("utf-8")
|
||||
with gzip.GzipFile(filename, "w") as f:
|
||||
f.write(data)</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-classes">Classes</h2>
|
||||
<dl>
|
||||
<dt id="miplearn.instance.Instance"><code class="flex name class">
|
||||
<span>class <span class="ident">Instance</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 Instance(ABC):
|
||||
"""
|
||||
Abstract class holding all the data necessary to generate a concrete model of the
|
||||
problem.
|
||||
|
||||
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.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.training_data: List[TrainingSample] = []
|
||||
|
||||
@abstractmethod
|
||||
def to_model(self) -> Any:
|
||||
"""
|
||||
Returns the optimization model corresponding to this instance.
|
||||
"""
|
||||
pass
|
||||
|
||||
def get_instance_features(self):
|
||||
"""
|
||||
Returns a 1-dimensional Numpy array of (numerical) features describing the
|
||||
entire instance.
|
||||
|
||||
The array is used by LearningSolver to determine how similar two instances
|
||||
are. It may also be used to predict, in combination with variable-specific
|
||||
features, the values of binary decision variables in the problem.
|
||||
|
||||
There is not necessarily a one-to-one correspondence between models and
|
||||
instance features: the features may encode only part of the data necessary to
|
||||
generate the complete model. Features may also be statistics computed from
|
||||
the original data. For example, in the knapsack problem, an implementation
|
||||
may decide to provide as instance features only the average weights, average
|
||||
prices, number of items and the size of the knapsack.
|
||||
|
||||
The returned array MUST have the same length for all relevant instances of
|
||||
the problem. If two instances map into arrays of different lengths,
|
||||
they cannot be solved by the same LearningSolver object.
|
||||
|
||||
By default, returns [0].
|
||||
"""
|
||||
return np.zeros(1)
|
||||
|
||||
def get_variable_features(self, var, index):
|
||||
"""
|
||||
Returns a 1-dimensional array of (numerical) features describing a particular
|
||||
decision variable.
|
||||
|
||||
The argument `var` is a pyomo.core.Var object, which represents a collection
|
||||
of decision variables. The argument `index` specifies which variable in the
|
||||
collection is the relevant one.
|
||||
|
||||
In combination with instance features, variable features are used by
|
||||
LearningSolver to predict, among other things, the optimal value of each
|
||||
decision variable before the optimization takes place. In the knapsack
|
||||
problem, for example, an implementation could provide as variable features
|
||||
the weight and the price of a specific item.
|
||||
|
||||
Like instance features, the arrays returned by this method MUST have the same
|
||||
length for all variables within the same category, for all relevant instances
|
||||
of the problem.
|
||||
|
||||
By default, returns [0].
|
||||
"""
|
||||
return np.zeros(1)
|
||||
|
||||
def get_variable_category(self, var, index):
|
||||
"""
|
||||
Returns the category (a string, an integer or any hashable type) for each
|
||||
decision variable.
|
||||
|
||||
If two variables have the same category, LearningSolver will use the same
|
||||
internal ML model to predict the values of both variables. If the returned
|
||||
category is None, ML models will ignore the variable.
|
||||
|
||||
By default, returns "default".
|
||||
"""
|
||||
return "default"
|
||||
|
||||
def get_constraint_features(self, cid):
|
||||
return np.zeros(1)
|
||||
|
||||
def get_constraint_category(self, cid):
|
||||
return cid
|
||||
|
||||
def has_static_lazy_constraints(self):
|
||||
return False
|
||||
|
||||
def has_dynamic_lazy_constraints(self):
|
||||
return False
|
||||
|
||||
def is_constraint_lazy(self, cid):
|
||||
return False
|
||||
|
||||
def find_violated_lazy_constraints(self, model):
|
||||
"""
|
||||
Returns lazy constraint violations found for the current solution.
|
||||
|
||||
After solving a model, LearningSolver will ask the instance to identify which
|
||||
lazy constraints are violated by the current solution. For each identified
|
||||
violation, LearningSolver will then call the build_lazy_constraint, add the
|
||||
generated Pyomo constraint to the model, then resolve the problem. The
|
||||
process repeats until no further lazy constraint violations are found.
|
||||
|
||||
Each "violation" is simply a string, a tuple or any other hashable type which
|
||||
allows the instance to identify unambiguously which lazy constraint should be
|
||||
generated. In the Traveling Salesman Problem, for example, a subtour
|
||||
violation could be a frozen set containing the cities in the subtour.
|
||||
|
||||
For a concrete example, see TravelingSalesmanInstance.
|
||||
"""
|
||||
return []
|
||||
|
||||
def build_lazy_constraint(self, model, violation):
|
||||
"""
|
||||
Returns a Pyomo constraint which fixes a given violation.
|
||||
|
||||
This method is typically called immediately after
|
||||
find_violated_lazy_constraints. The violation object provided to this method
|
||||
is exactly the same object returned earlier by
|
||||
find_violated_lazy_constraints. After some training, LearningSolver may
|
||||
decide to proactively build some lazy constraints at the beginning of the
|
||||
optimization process, before a solution is even available. In this case,
|
||||
build_lazy_constraints will be called without a corresponding call to
|
||||
find_violated_lazy_constraints.
|
||||
|
||||
The implementation should not directly add the constraint to the model. The
|
||||
constraint will be added by LearningSolver after the method returns.
|
||||
|
||||
For a concrete example, see TravelingSalesmanInstance.
|
||||
"""
|
||||
pass
|
||||
|
||||
def find_violated_user_cuts(self, model):
|
||||
return []
|
||||
|
||||
def build_user_cut(self, model, violation):
|
||||
pass
|
||||
|
||||
def load(self, filename):
|
||||
with gzip.GzipFile(filename, "r") as f:
|
||||
data = json.loads(f.read().decode("utf-8"))
|
||||
self.__dict__ = data
|
||||
|
||||
def dump(self, filename):
|
||||
data = json.dumps(self.__dict__, indent=2).encode("utf-8")
|
||||
with gzip.GzipFile(filename, "w") as f:
|
||||
f.write(data)</code></pre>
|
||||
</details>
|
||||
<h3>Ancestors</h3>
|
||||
<ul class="hlist">
|
||||
<li>abc.ABC</li>
|
||||
</ul>
|
||||
<h3>Subclasses</h3>
|
||||
<ul class="hlist">
|
||||
<li><a title="miplearn.problems.knapsack.MultiKnapsackInstance" href="problems/knapsack.html#miplearn.problems.knapsack.MultiKnapsackInstance">MultiKnapsackInstance</a></li>
|
||||
<li><a title="miplearn.problems.knapsack.KnapsackInstance" href="problems/knapsack.html#miplearn.problems.knapsack.KnapsackInstance">KnapsackInstance</a></li>
|
||||
<li><a title="miplearn.solvers.tests.InfeasiblePyomoInstance" href="solvers/tests/index.html#miplearn.solvers.tests.InfeasiblePyomoInstance">InfeasiblePyomoInstance</a></li>
|
||||
<li><a title="miplearn.solvers.tests.InfeasibleGurobiInstance" href="solvers/tests/index.html#miplearn.solvers.tests.InfeasibleGurobiInstance">InfeasibleGurobiInstance</a></li>
|
||||
<li><a title="miplearn.problems.stab.MaxWeightStableSetInstance" href="problems/stab.html#miplearn.problems.stab.MaxWeightStableSetInstance">MaxWeightStableSetInstance</a></li>
|
||||
<li><a title="miplearn.problems.tsp.TravelingSalesmanInstance" href="problems/tsp.html#miplearn.problems.tsp.TravelingSalesmanInstance">TravelingSalesmanInstance</a></li>
|
||||
<li><a title="miplearn.components.steps.tests.test_convert_tight.SampleInstance" href="components/steps/tests/test_convert_tight.html#miplearn.components.steps.tests.test_convert_tight.SampleInstance">SampleInstance</a></li>
|
||||
</ul>
|
||||
<h3>Methods</h3>
|
||||
<dl>
|
||||
<dt id="miplearn.instance.Instance.build_lazy_constraint"><code class="name flex">
|
||||
<span>def <span class="ident">build_lazy_constraint</span></span>(<span>self, model, violation)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"><p>Returns a Pyomo constraint which fixes a given violation.</p>
|
||||
<p>This method is typically called immediately after
|
||||
find_violated_lazy_constraints. The violation object provided to this method
|
||||
is exactly the same object returned earlier by
|
||||
find_violated_lazy_constraints. After some training, LearningSolver may
|
||||
decide to proactively build some lazy constraints at the beginning of the
|
||||
optimization process, before a solution is even available. In this case,
|
||||
build_lazy_constraints will be called without a corresponding call to
|
||||
find_violated_lazy_constraints.</p>
|
||||
<p>The implementation should not directly add the constraint to the model. The
|
||||
constraint will be added by LearningSolver after the method returns.</p>
|
||||
<p>For a concrete example, see TravelingSalesmanInstance.</p></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def build_lazy_constraint(self, model, violation):
|
||||
"""
|
||||
Returns a Pyomo constraint which fixes a given violation.
|
||||
|
||||
This method is typically called immediately after
|
||||
find_violated_lazy_constraints. The violation object provided to this method
|
||||
is exactly the same object returned earlier by
|
||||
find_violated_lazy_constraints. After some training, LearningSolver may
|
||||
decide to proactively build some lazy constraints at the beginning of the
|
||||
optimization process, before a solution is even available. In this case,
|
||||
build_lazy_constraints will be called without a corresponding call to
|
||||
find_violated_lazy_constraints.
|
||||
|
||||
The implementation should not directly add the constraint to the model. The
|
||||
constraint will be added by LearningSolver after the method returns.
|
||||
|
||||
For a concrete example, see TravelingSalesmanInstance.
|
||||
"""
|
||||
pass</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.instance.Instance.build_user_cut"><code class="name flex">
|
||||
<span>def <span class="ident">build_user_cut</span></span>(<span>self, model, violation)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def build_user_cut(self, model, violation):
|
||||
pass</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.instance.Instance.dump"><code class="name flex">
|
||||
<span>def <span class="ident">dump</span></span>(<span>self, filename)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def dump(self, filename):
|
||||
data = json.dumps(self.__dict__, indent=2).encode("utf-8")
|
||||
with gzip.GzipFile(filename, "w") as f:
|
||||
f.write(data)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.instance.Instance.find_violated_lazy_constraints"><code class="name flex">
|
||||
<span>def <span class="ident">find_violated_lazy_constraints</span></span>(<span>self, model)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"><p>Returns lazy constraint violations found for the current solution.</p>
|
||||
<p>After solving a model, LearningSolver will ask the instance to identify which
|
||||
lazy constraints are violated by the current solution. For each identified
|
||||
violation, LearningSolver will then call the build_lazy_constraint, add the
|
||||
generated Pyomo constraint to the model, then resolve the problem. The
|
||||
process repeats until no further lazy constraint violations are found.</p>
|
||||
<p>Each "violation" is simply a string, a tuple or any other hashable type which
|
||||
allows the instance to identify unambiguously which lazy constraint should be
|
||||
generated. In the Traveling Salesman Problem, for example, a subtour
|
||||
violation could be a frozen set containing the cities in the subtour.</p>
|
||||
<p>For a concrete example, see TravelingSalesmanInstance.</p></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def find_violated_lazy_constraints(self, model):
|
||||
"""
|
||||
Returns lazy constraint violations found for the current solution.
|
||||
|
||||
After solving a model, LearningSolver will ask the instance to identify which
|
||||
lazy constraints are violated by the current solution. For each identified
|
||||
violation, LearningSolver will then call the build_lazy_constraint, add the
|
||||
generated Pyomo constraint to the model, then resolve the problem. The
|
||||
process repeats until no further lazy constraint violations are found.
|
||||
|
||||
Each "violation" is simply a string, a tuple or any other hashable type which
|
||||
allows the instance to identify unambiguously which lazy constraint should be
|
||||
generated. In the Traveling Salesman Problem, for example, a subtour
|
||||
violation could be a frozen set containing the cities in the subtour.
|
||||
|
||||
For a concrete example, see TravelingSalesmanInstance.
|
||||
"""
|
||||
return []</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.instance.Instance.find_violated_user_cuts"><code class="name flex">
|
||||
<span>def <span class="ident">find_violated_user_cuts</span></span>(<span>self, model)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def find_violated_user_cuts(self, model):
|
||||
return []</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.instance.Instance.get_constraint_category"><code class="name flex">
|
||||
<span>def <span class="ident">get_constraint_category</span></span>(<span>self, cid)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def get_constraint_category(self, cid):
|
||||
return cid</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.instance.Instance.get_constraint_features"><code class="name flex">
|
||||
<span>def <span class="ident">get_constraint_features</span></span>(<span>self, cid)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def get_constraint_features(self, cid):
|
||||
return np.zeros(1)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.instance.Instance.get_instance_features"><code class="name flex">
|
||||
<span>def <span class="ident">get_instance_features</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"><p>Returns a 1-dimensional Numpy array of (numerical) features describing the
|
||||
entire instance.</p>
|
||||
<p>The array is used by LearningSolver to determine how similar two instances
|
||||
are. It may also be used to predict, in combination with variable-specific
|
||||
features, the values of binary decision variables in the problem.</p>
|
||||
<p>There is not necessarily a one-to-one correspondence between models and
|
||||
instance features: the features may encode only part of the data necessary to
|
||||
generate the complete model. Features may also be statistics computed from
|
||||
the original data. For example, in the knapsack problem, an implementation
|
||||
may decide to provide as instance features only the average weights, average
|
||||
prices, number of items and the size of the knapsack.</p>
|
||||
<p>The returned array MUST have the same length for all relevant instances of
|
||||
the problem. If two instances map into arrays of different lengths,
|
||||
they cannot be solved by the same LearningSolver object.</p>
|
||||
<p>By default, returns [0].</p></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def get_instance_features(self):
|
||||
"""
|
||||
Returns a 1-dimensional Numpy array of (numerical) features describing the
|
||||
entire instance.
|
||||
|
||||
The array is used by LearningSolver to determine how similar two instances
|
||||
are. It may also be used to predict, in combination with variable-specific
|
||||
features, the values of binary decision variables in the problem.
|
||||
|
||||
There is not necessarily a one-to-one correspondence between models and
|
||||
instance features: the features may encode only part of the data necessary to
|
||||
generate the complete model. Features may also be statistics computed from
|
||||
the original data. For example, in the knapsack problem, an implementation
|
||||
may decide to provide as instance features only the average weights, average
|
||||
prices, number of items and the size of the knapsack.
|
||||
|
||||
The returned array MUST have the same length for all relevant instances of
|
||||
the problem. If two instances map into arrays of different lengths,
|
||||
they cannot be solved by the same LearningSolver object.
|
||||
|
||||
By default, returns [0].
|
||||
"""
|
||||
return np.zeros(1)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.instance.Instance.get_variable_category"><code class="name flex">
|
||||
<span>def <span class="ident">get_variable_category</span></span>(<span>self, var, index)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"><p>Returns the category (a string, an integer or any hashable type) for each
|
||||
decision variable.</p>
|
||||
<p>If two variables have the same category, LearningSolver will use the same
|
||||
internal ML model to predict the values of both variables. If the returned
|
||||
category is None, ML models will ignore the variable.</p>
|
||||
<p>By default, returns "default".</p></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def get_variable_category(self, var, index):
|
||||
"""
|
||||
Returns the category (a string, an integer or any hashable type) for each
|
||||
decision variable.
|
||||
|
||||
If two variables have the same category, LearningSolver will use the same
|
||||
internal ML model to predict the values of both variables. If the returned
|
||||
category is None, ML models will ignore the variable.
|
||||
|
||||
By default, returns "default".
|
||||
"""
|
||||
return "default"</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.instance.Instance.get_variable_features"><code class="name flex">
|
||||
<span>def <span class="ident">get_variable_features</span></span>(<span>self, var, index)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"><p>Returns a 1-dimensional array of (numerical) features describing a particular
|
||||
decision variable.</p>
|
||||
<p>The argument <code>var</code> is a pyomo.core.Var object, which represents a collection
|
||||
of decision variables. The argument <code>index</code> specifies which variable in the
|
||||
collection is the relevant one.</p>
|
||||
<p>In combination with instance features, variable features are used by
|
||||
LearningSolver to predict, among other things, the optimal value of each
|
||||
decision variable before the optimization takes place. In the knapsack
|
||||
problem, for example, an implementation could provide as variable features
|
||||
the weight and the price of a specific item.</p>
|
||||
<p>Like instance features, the arrays returned by this method MUST have the same
|
||||
length for all variables within the same category, for all relevant instances
|
||||
of the problem.</p>
|
||||
<p>By default, returns [0].</p></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def get_variable_features(self, var, index):
|
||||
"""
|
||||
Returns a 1-dimensional array of (numerical) features describing a particular
|
||||
decision variable.
|
||||
|
||||
The argument `var` is a pyomo.core.Var object, which represents a collection
|
||||
of decision variables. The argument `index` specifies which variable in the
|
||||
collection is the relevant one.
|
||||
|
||||
In combination with instance features, variable features are used by
|
||||
LearningSolver to predict, among other things, the optimal value of each
|
||||
decision variable before the optimization takes place. In the knapsack
|
||||
problem, for example, an implementation could provide as variable features
|
||||
the weight and the price of a specific item.
|
||||
|
||||
Like instance features, the arrays returned by this method MUST have the same
|
||||
length for all variables within the same category, for all relevant instances
|
||||
of the problem.
|
||||
|
||||
By default, returns [0].
|
||||
"""
|
||||
return np.zeros(1)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.instance.Instance.has_dynamic_lazy_constraints"><code class="name flex">
|
||||
<span>def <span class="ident">has_dynamic_lazy_constraints</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def has_dynamic_lazy_constraints(self):
|
||||
return False</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.instance.Instance.has_static_lazy_constraints"><code class="name flex">
|
||||
<span>def <span class="ident">has_static_lazy_constraints</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def has_static_lazy_constraints(self):
|
||||
return False</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.instance.Instance.is_constraint_lazy"><code class="name flex">
|
||||
<span>def <span class="ident">is_constraint_lazy</span></span>(<span>self, cid)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def is_constraint_lazy(self, cid):
|
||||
return False</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.instance.Instance.load"><code class="name flex">
|
||||
<span>def <span class="ident">load</span></span>(<span>self, filename)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def load(self, filename):
|
||||
with gzip.GzipFile(filename, "r") as f:
|
||||
data = json.loads(f.read().decode("utf-8"))
|
||||
self.__dict__ = data</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.instance.Instance.to_model"><code class="name flex">
|
||||
<span>def <span class="ident">to_model</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"><p>Returns the optimization model corresponding to this instance.</p></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">@abstractmethod
|
||||
def to_model(self) -> Any:
|
||||
"""
|
||||
Returns the optimization model corresponding to this instance.
|
||||
"""
|
||||
pass</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</section>
|
||||
</article>
|
||||
<nav id="sidebar">
|
||||
<h1>Index</h1>
|
||||
<div class="toc">
|
||||
<ul></ul>
|
||||
</div>
|
||||
<ul id="index">
|
||||
<li><h3>Super-module</h3>
|
||||
<ul>
|
||||
<li><code><a title="miplearn" href="index.html">miplearn</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-classes">Classes</a></h3>
|
||||
<ul>
|
||||
<li>
|
||||
<h4><code><a title="miplearn.instance.Instance" href="#miplearn.instance.Instance">Instance</a></code></h4>
|
||||
<ul class="">
|
||||
<li><code><a title="miplearn.instance.Instance.build_lazy_constraint" href="#miplearn.instance.Instance.build_lazy_constraint">build_lazy_constraint</a></code></li>
|
||||
<li><code><a title="miplearn.instance.Instance.build_user_cut" href="#miplearn.instance.Instance.build_user_cut">build_user_cut</a></code></li>
|
||||
<li><code><a title="miplearn.instance.Instance.dump" href="#miplearn.instance.Instance.dump">dump</a></code></li>
|
||||
<li><code><a title="miplearn.instance.Instance.find_violated_lazy_constraints" href="#miplearn.instance.Instance.find_violated_lazy_constraints">find_violated_lazy_constraints</a></code></li>
|
||||
<li><code><a title="miplearn.instance.Instance.find_violated_user_cuts" href="#miplearn.instance.Instance.find_violated_user_cuts">find_violated_user_cuts</a></code></li>
|
||||
<li><code><a title="miplearn.instance.Instance.get_constraint_category" href="#miplearn.instance.Instance.get_constraint_category">get_constraint_category</a></code></li>
|
||||
<li><code><a title="miplearn.instance.Instance.get_constraint_features" href="#miplearn.instance.Instance.get_constraint_features">get_constraint_features</a></code></li>
|
||||
<li><code><a title="miplearn.instance.Instance.get_instance_features" href="#miplearn.instance.Instance.get_instance_features">get_instance_features</a></code></li>
|
||||
<li><code><a title="miplearn.instance.Instance.get_variable_category" href="#miplearn.instance.Instance.get_variable_category">get_variable_category</a></code></li>
|
||||
<li><code><a title="miplearn.instance.Instance.get_variable_features" href="#miplearn.instance.Instance.get_variable_features">get_variable_features</a></code></li>
|
||||
<li><code><a title="miplearn.instance.Instance.has_dynamic_lazy_constraints" href="#miplearn.instance.Instance.has_dynamic_lazy_constraints">has_dynamic_lazy_constraints</a></code></li>
|
||||
<li><code><a title="miplearn.instance.Instance.has_static_lazy_constraints" href="#miplearn.instance.Instance.has_static_lazy_constraints">has_static_lazy_constraints</a></code></li>
|
||||
<li><code><a title="miplearn.instance.Instance.is_constraint_lazy" href="#miplearn.instance.Instance.is_constraint_lazy">is_constraint_lazy</a></code></li>
|
||||
<li><code><a title="miplearn.instance.Instance.load" href="#miplearn.instance.Instance.load">load</a></code></li>
|
||||
<li><code><a title="miplearn.instance.Instance.to_model" href="#miplearn.instance.Instance.to_model">to_model</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</main>
|
||||
<footer id="footer">
|
||||
<p>Generated by <a href="https://pdoc3.github.io/pdoc"><cite>pdoc</cite> 0.7.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>
|
||||
294
0.2/api/miplearn/log.html
Normal file
294
0.2/api/miplearn/log.html
Normal file
@@ -0,0 +1,294 @@
|
||||
<!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.log 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.log</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
|
||||
import time
|
||||
|
||||
|
||||
class TimeFormatter(logging.Formatter):
|
||||
def __init__(self, start_time, log_colors):
|
||||
super().__init__()
|
||||
self.start_time = start_time
|
||||
self.log_colors = log_colors
|
||||
|
||||
def format(self, record):
|
||||
if record.levelno >= logging.ERROR:
|
||||
color = self.log_colors["red"]
|
||||
elif record.levelno >= logging.WARNING:
|
||||
color = self.log_colors["yellow"]
|
||||
else:
|
||||
color = self.log_colors["green"]
|
||||
return "%s[%12.3f]%s %s" % (
|
||||
color,
|
||||
record.created - self.start_time,
|
||||
self.log_colors["reset"],
|
||||
record.getMessage(),
|
||||
)
|
||||
|
||||
|
||||
def setup_logger(start_time=None, force_color=False):
|
||||
if start_time is None:
|
||||
start_time = time.time()
|
||||
if sys.stdout.isatty() or force_color:
|
||||
log_colors = {
|
||||
"green": "\033[92m",
|
||||
"yellow": "\033[93m",
|
||||
"red": "\033[91m",
|
||||
"reset": "\033[0m",
|
||||
}
|
||||
else:
|
||||
log_colors = {
|
||||
"green": "",
|
||||
"yellow": "",
|
||||
"red": "",
|
||||
"reset": "",
|
||||
}
|
||||
handler = logging.StreamHandler()
|
||||
handler.setFormatter(TimeFormatter(start_time, log_colors))
|
||||
logging.getLogger().addHandler(handler)
|
||||
logging.getLogger("miplearn").setLevel(logging.INFO)</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-functions">Functions</h2>
|
||||
<dl>
|
||||
<dt id="miplearn.log.setup_logger"><code class="name flex">
|
||||
<span>def <span class="ident">setup_logger</span></span>(<span>start_time=None, force_color=False)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def setup_logger(start_time=None, force_color=False):
|
||||
if start_time is None:
|
||||
start_time = time.time()
|
||||
if sys.stdout.isatty() or force_color:
|
||||
log_colors = {
|
||||
"green": "\033[92m",
|
||||
"yellow": "\033[93m",
|
||||
"red": "\033[91m",
|
||||
"reset": "\033[0m",
|
||||
}
|
||||
else:
|
||||
log_colors = {
|
||||
"green": "",
|
||||
"yellow": "",
|
||||
"red": "",
|
||||
"reset": "",
|
||||
}
|
||||
handler = logging.StreamHandler()
|
||||
handler.setFormatter(TimeFormatter(start_time, log_colors))
|
||||
logging.getLogger().addHandler(handler)
|
||||
logging.getLogger("miplearn").setLevel(logging.INFO)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-classes">Classes</h2>
|
||||
<dl>
|
||||
<dt id="miplearn.log.TimeFormatter"><code class="flex name class">
|
||||
<span>class <span class="ident">TimeFormatter</span></span>
|
||||
<span>(</span><span>start_time, log_colors)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"><p>Formatter instances are used to convert a LogRecord to text.</p>
|
||||
<p>Formatters need to know how a LogRecord is constructed. They are
|
||||
responsible for converting a LogRecord to (usually) a string which can
|
||||
be interpreted by either a human or an external system. The base Formatter
|
||||
allows a formatting string to be specified. If none is supplied, the
|
||||
the style-dependent default value, "%(message)s", "{message}", or
|
||||
"${message}", is used.</p>
|
||||
<p>The Formatter can be initialized with a format string which makes use of
|
||||
knowledge of the LogRecord attributes - e.g. the default value mentioned
|
||||
above makes use of the fact that the user's message and arguments are pre-
|
||||
formatted into a LogRecord's message attribute. Currently, the useful
|
||||
attributes in a LogRecord are described by:</p>
|
||||
<p>%(name)s
|
||||
Name of the logger (logging channel)
|
||||
%(levelno)s
|
||||
Numeric logging level for the message (DEBUG, INFO,
|
||||
WARNING, ERROR, CRITICAL)
|
||||
%(levelname)s
|
||||
Text logging level for the message ("DEBUG", "INFO",
|
||||
"WARNING", "ERROR", "CRITICAL")
|
||||
%(pathname)s
|
||||
Full pathname of the source file where the logging
|
||||
call was issued (if available)
|
||||
%(filename)s
|
||||
Filename portion of pathname
|
||||
%(module)s
|
||||
Module (name portion of filename)
|
||||
%(lineno)d
|
||||
Source line number where the logging call was issued
|
||||
(if available)
|
||||
%(funcName)s
|
||||
Function name
|
||||
%(created)f
|
||||
Time when the LogRecord was created (time.time()
|
||||
return value)
|
||||
%(asctime)s
|
||||
Textual time when the LogRecord was created
|
||||
%(msecs)d
|
||||
Millisecond portion of the creation time
|
||||
%(relativeCreated)d Time in milliseconds when the LogRecord was created,
|
||||
relative to the time the logging module was loaded
|
||||
(typically at application startup time)
|
||||
%(thread)d
|
||||
Thread ID (if available)
|
||||
%(threadName)s
|
||||
Thread name (if available)
|
||||
%(process)d
|
||||
Process ID (if available)
|
||||
%(message)s
|
||||
The result of record.getMessage(), computed just as
|
||||
the record is emitted</p>
|
||||
<p>Initialize the formatter with specified format strings.</p>
|
||||
<p>Initialize the formatter either with the specified format string, or a
|
||||
default as described above. Allow for specialized date formatting with
|
||||
the optional datefmt argument. If datefmt is omitted, you get an
|
||||
ISO8601-like (or RFC 3339-like) format.</p>
|
||||
<p>Use a style parameter of '%', '{' or '$' to specify that you want to
|
||||
use one of %-formatting, :meth:<code>str.format</code> (<code>{}</code>) formatting or
|
||||
:class:<code>string.Template</code> formatting in your format string.</p>
|
||||
<div class="admonition versionchanged">
|
||||
<p class="admonition-title">Changed in version: 3.2</p>
|
||||
<p>Added the <code>style</code> parameter.</p>
|
||||
</div></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">class TimeFormatter(logging.Formatter):
|
||||
def __init__(self, start_time, log_colors):
|
||||
super().__init__()
|
||||
self.start_time = start_time
|
||||
self.log_colors = log_colors
|
||||
|
||||
def format(self, record):
|
||||
if record.levelno >= logging.ERROR:
|
||||
color = self.log_colors["red"]
|
||||
elif record.levelno >= logging.WARNING:
|
||||
color = self.log_colors["yellow"]
|
||||
else:
|
||||
color = self.log_colors["green"]
|
||||
return "%s[%12.3f]%s %s" % (
|
||||
color,
|
||||
record.created - self.start_time,
|
||||
self.log_colors["reset"],
|
||||
record.getMessage(),
|
||||
)</code></pre>
|
||||
</details>
|
||||
<h3>Ancestors</h3>
|
||||
<ul class="hlist">
|
||||
<li>logging.Formatter</li>
|
||||
</ul>
|
||||
<h3>Methods</h3>
|
||||
<dl>
|
||||
<dt id="miplearn.log.TimeFormatter.format"><code class="name flex">
|
||||
<span>def <span class="ident">format</span></span>(<span>self, record)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"><p>Format the specified record as text.</p>
|
||||
<p>The record's attribute dictionary is used as the operand to a
|
||||
string formatting operation which yields the returned string.
|
||||
Before formatting the dictionary, a couple of preparatory steps
|
||||
are carried out. The message attribute of the record is computed
|
||||
using LogRecord.getMessage(). If the formatting string uses the
|
||||
time (as determined by a call to usesTime(), formatTime() is
|
||||
called to format the event time. If there is exception information,
|
||||
it is formatted using formatException() and appended to the message.</p></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def format(self, record):
|
||||
if record.levelno >= logging.ERROR:
|
||||
color = self.log_colors["red"]
|
||||
elif record.levelno >= logging.WARNING:
|
||||
color = self.log_colors["yellow"]
|
||||
else:
|
||||
color = self.log_colors["green"]
|
||||
return "%s[%12.3f]%s %s" % (
|
||||
color,
|
||||
record.created - self.start_time,
|
||||
self.log_colors["reset"],
|
||||
record.getMessage(),
|
||||
)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</section>
|
||||
</article>
|
||||
<nav id="sidebar">
|
||||
<h1>Index</h1>
|
||||
<div class="toc">
|
||||
<ul></ul>
|
||||
</div>
|
||||
<ul id="index">
|
||||
<li><h3>Super-module</h3>
|
||||
<ul>
|
||||
<li><code><a title="miplearn" href="index.html">miplearn</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-functions">Functions</a></h3>
|
||||
<ul class="">
|
||||
<li><code><a title="miplearn.log.setup_logger" href="#miplearn.log.setup_logger">setup_logger</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-classes">Classes</a></h3>
|
||||
<ul>
|
||||
<li>
|
||||
<h4><code><a title="miplearn.log.TimeFormatter" href="#miplearn.log.TimeFormatter">TimeFormatter</a></code></h4>
|
||||
<ul class="">
|
||||
<li><code><a title="miplearn.log.TimeFormatter.format" href="#miplearn.log.TimeFormatter.format">format</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</main>
|
||||
<footer id="footer">
|
||||
<p>Generated by <a href="https://pdoc3.github.io/pdoc"><cite>pdoc</cite> 0.7.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>
|
||||
88
0.2/api/miplearn/problems/index.html
Normal file
88
0.2/api/miplearn/problems/index.html
Normal 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.problems 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.problems</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.problems.knapsack" href="knapsack.html">miplearn.problems.knapsack</a></code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
</dd>
|
||||
<dt><code class="name"><a title="miplearn.problems.stab" href="stab.html">miplearn.problems.stab</a></code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
</dd>
|
||||
<dt><code class="name"><a title="miplearn.problems.tests" href="tests/index.html">miplearn.problems.tests</a></code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
</dd>
|
||||
<dt><code class="name"><a title="miplearn.problems.tsp" href="tsp.html">miplearn.problems.tsp</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.problems.knapsack" href="knapsack.html">miplearn.problems.knapsack</a></code></li>
|
||||
<li><code><a title="miplearn.problems.stab" href="stab.html">miplearn.problems.stab</a></code></li>
|
||||
<li><code><a title="miplearn.problems.tests" href="tests/index.html">miplearn.problems.tests</a></code></li>
|
||||
<li><code><a title="miplearn.problems.tsp" href="tsp.html">miplearn.problems.tsp</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>
|
||||
881
0.2/api/miplearn/problems/knapsack.html
Normal file
881
0.2/api/miplearn/problems/knapsack.html
Normal file
@@ -0,0 +1,881 @@
|
||||
<!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.problems.knapsack 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.problems.knapsack</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 numpy as np
|
||||
import pyomo.environ as pe
|
||||
from scipy.stats import uniform, randint
|
||||
from scipy.stats.distributions import rv_frozen
|
||||
|
||||
from miplearn.instance import Instance
|
||||
|
||||
|
||||
class ChallengeA:
|
||||
"""
|
||||
- 250 variables, 10 constraints, fixed weights
|
||||
- w ~ U(0, 1000), jitter ~ U(0.95, 1.05)
|
||||
- K = 500, u ~ U(0., 1.)
|
||||
- alpha = 0.25
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
seed=42,
|
||||
n_training_instances=500,
|
||||
n_test_instances=50,
|
||||
):
|
||||
|
||||
np.random.seed(seed)
|
||||
self.gen = MultiKnapsackGenerator(
|
||||
n=randint(low=250, high=251),
|
||||
m=randint(low=10, high=11),
|
||||
w=uniform(loc=0.0, scale=1000.0),
|
||||
K=uniform(loc=500.0, scale=0.0),
|
||||
u=uniform(loc=0.0, scale=1.0),
|
||||
alpha=uniform(loc=0.25, scale=0.0),
|
||||
fix_w=True,
|
||||
w_jitter=uniform(loc=0.95, scale=0.1),
|
||||
)
|
||||
np.random.seed(seed + 1)
|
||||
self.training_instances = self.gen.generate(n_training_instances)
|
||||
|
||||
np.random.seed(seed + 2)
|
||||
self.test_instances = self.gen.generate(n_test_instances)
|
||||
|
||||
|
||||
class MultiKnapsackInstance(Instance):
|
||||
"""Representation of the Multidimensional 0-1 Knapsack Problem.
|
||||
|
||||
Given a set of n items and m knapsacks, the problem is to find a subset of items S maximizing
|
||||
sum(prices[i] for i in S). If selected, each item i occupies weights[i,j] units of space in
|
||||
each knapsack j. Furthermore, each knapsack j has limited storage space, given by capacities[j].
|
||||
|
||||
This implementation assigns a different category for each decision variable, and therefore
|
||||
trains one ML model per variable. It is only suitable when training and test instances have
|
||||
same size and items don't shuffle around.
|
||||
"""
|
||||
|
||||
def __init__(self, prices, capacities, weights):
|
||||
super().__init__()
|
||||
assert isinstance(prices, np.ndarray)
|
||||
assert isinstance(capacities, np.ndarray)
|
||||
assert isinstance(weights, np.ndarray)
|
||||
assert len(weights.shape) == 2
|
||||
self.m, self.n = weights.shape
|
||||
assert prices.shape == (self.n,)
|
||||
assert capacities.shape == (self.m,)
|
||||
self.prices = prices
|
||||
self.capacities = capacities
|
||||
self.weights = weights
|
||||
|
||||
def to_model(self):
|
||||
model = pe.ConcreteModel()
|
||||
model.x = pe.Var(range(self.n), domain=pe.Binary)
|
||||
model.OBJ = pe.Objective(
|
||||
rule=lambda model: sum(model.x[j] * self.prices[j] for j in range(self.n)),
|
||||
sense=pe.maximize,
|
||||
)
|
||||
model.eq_capacity = pe.ConstraintList()
|
||||
for i in range(self.m):
|
||||
model.eq_capacity.add(
|
||||
sum(model.x[j] * self.weights[i, j] for j in range(self.n))
|
||||
<= self.capacities[i]
|
||||
)
|
||||
|
||||
return model
|
||||
|
||||
def get_instance_features(self):
|
||||
return np.hstack(
|
||||
[
|
||||
np.mean(self.prices),
|
||||
self.capacities,
|
||||
]
|
||||
)
|
||||
|
||||
def get_variable_features(self, var, index):
|
||||
return np.hstack(
|
||||
[
|
||||
self.prices[index],
|
||||
self.weights[:, index],
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
# def get_variable_category(self, var, index):
|
||||
# return index
|
||||
|
||||
|
||||
class MultiKnapsackGenerator:
|
||||
def __init__(
|
||||
self,
|
||||
n=randint(low=100, high=101),
|
||||
m=randint(low=30, high=31),
|
||||
w=randint(low=0, high=1000),
|
||||
K=randint(low=500, high=500),
|
||||
u=uniform(loc=0.0, scale=1.0),
|
||||
alpha=uniform(loc=0.25, scale=0.0),
|
||||
fix_w=False,
|
||||
w_jitter=uniform(loc=1.0, scale=0.0),
|
||||
round=True,
|
||||
):
|
||||
"""Initialize the problem generator.
|
||||
|
||||
Instances have a random number of items (or variables) and a random number of knapsacks
|
||||
(or constraints), as specified by the provided probability distributions `n` and `m`,
|
||||
respectively. The weight of each item `i` on knapsack `j` is sampled independently from
|
||||
the provided distribution `w`. The capacity of knapsack `j` is set to:
|
||||
|
||||
alpha_j * sum(w[i,j] for i in range(n)),
|
||||
|
||||
where `alpha_j`, the tightness ratio, is sampled from the provided probability
|
||||
distribution `alpha`. To make the instances more challenging, the costs of the items
|
||||
are linearly correlated to their average weights. More specifically, the weight of each
|
||||
item `i` is set to:
|
||||
|
||||
sum(w[i,j]/m for j in range(m)) + K * u_i,
|
||||
|
||||
where `K`, the correlation coefficient, and `u_i`, the correlation multiplier, are sampled
|
||||
from the provided probability distributions. Note that `K` is only sample once for the
|
||||
entire instance.
|
||||
|
||||
If fix_w=True is provided, then w[i,j] are kept the same in all generated instances. This
|
||||
also implies that n and m are kept fixed. Although the prices and capacities are derived
|
||||
from w[i,j], as long as u and K are not constants, the generated instances will still not
|
||||
be completely identical.
|
||||
|
||||
If a probability distribution w_jitter is provided, then item weights will be set to
|
||||
w[i,j] * gamma[i,j] where gamma[i,j] is sampled from w_jitter. When combined with
|
||||
fix_w=True, this argument may be used to generate instances where the weight of each item
|
||||
is roughly the same, but not exactly identical, across all instances. The prices of the
|
||||
items and the capacities of the knapsacks will be calculated as above, but using these
|
||||
perturbed weights instead.
|
||||
|
||||
By default, all generated prices, weights and capacities are rounded to the nearest integer
|
||||
number. If `round=False` is provided, this rounding will be disabled.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
n: rv_discrete
|
||||
Probability distribution for the number of items (or variables)
|
||||
m: rv_discrete
|
||||
Probability distribution for the number of knapsacks (or constraints)
|
||||
w: rv_continuous
|
||||
Probability distribution for the item weights
|
||||
K: rv_continuous
|
||||
Probability distribution for the profit correlation coefficient
|
||||
u: rv_continuous
|
||||
Probability distribution for the profit multiplier
|
||||
alpha: rv_continuous
|
||||
Probability distribution for the tightness ratio
|
||||
fix_w: boolean
|
||||
If true, weights are kept the same (minus the noise from w_jitter) in all instances
|
||||
w_jitter: rv_continuous
|
||||
Probability distribution for random noise added to the weights
|
||||
round: boolean
|
||||
If true, all prices, weights and capacities are rounded to the nearest integer
|
||||
"""
|
||||
assert isinstance(n, rv_frozen), "n should be a SciPy probability distribution"
|
||||
assert isinstance(m, rv_frozen), "m should be a SciPy probability distribution"
|
||||
assert isinstance(w, rv_frozen), "w should be a SciPy probability distribution"
|
||||
assert isinstance(K, rv_frozen), "K should be a SciPy probability distribution"
|
||||
assert isinstance(u, rv_frozen), "u should be a SciPy probability distribution"
|
||||
assert isinstance(
|
||||
alpha, rv_frozen
|
||||
), "alpha should be a SciPy probability distribution"
|
||||
assert isinstance(fix_w, bool), "fix_w should be boolean"
|
||||
assert isinstance(
|
||||
w_jitter, rv_frozen
|
||||
), "w_jitter should be a SciPy probability distribution"
|
||||
|
||||
self.n = n
|
||||
self.m = m
|
||||
self.w = w
|
||||
self.K = K
|
||||
self.u = u
|
||||
self.alpha = alpha
|
||||
self.w_jitter = w_jitter
|
||||
self.round = round
|
||||
|
||||
if fix_w:
|
||||
self.fix_n = self.n.rvs()
|
||||
self.fix_m = self.m.rvs()
|
||||
self.fix_w = np.array([self.w.rvs(self.fix_n) for _ in range(self.fix_m)])
|
||||
self.fix_u = self.u.rvs(self.fix_n)
|
||||
self.fix_K = self.K.rvs()
|
||||
else:
|
||||
self.fix_n = None
|
||||
self.fix_m = None
|
||||
self.fix_w = None
|
||||
self.fix_u = None
|
||||
self.fix_K = None
|
||||
|
||||
def generate(self, n_samples):
|
||||
def _sample():
|
||||
if self.fix_w is not None:
|
||||
n = self.fix_n
|
||||
m = self.fix_m
|
||||
w = self.fix_w
|
||||
u = self.fix_u
|
||||
K = self.fix_K
|
||||
else:
|
||||
n = self.n.rvs()
|
||||
m = self.m.rvs()
|
||||
w = np.array([self.w.rvs(n) for _ in range(m)])
|
||||
u = self.u.rvs(n)
|
||||
K = self.K.rvs()
|
||||
w = w * np.array([self.w_jitter.rvs(n) for _ in range(m)])
|
||||
alpha = self.alpha.rvs(m)
|
||||
p = np.array([w[:, j].sum() / m + K * u[j] for j in range(n)])
|
||||
b = np.array([w[i, :].sum() * alpha[i] for i in range(m)])
|
||||
if self.round:
|
||||
p = p.round()
|
||||
b = b.round()
|
||||
w = w.round()
|
||||
return MultiKnapsackInstance(p, b, w)
|
||||
|
||||
return [_sample() for _ in range(n_samples)]
|
||||
|
||||
|
||||
class KnapsackInstance(Instance):
|
||||
"""
|
||||
Simpler (one-dimensional) Knapsack Problem, used for testing.
|
||||
"""
|
||||
|
||||
def __init__(self, weights, prices, capacity):
|
||||
super().__init__()
|
||||
self.weights = weights
|
||||
self.prices = prices
|
||||
self.capacity = capacity
|
||||
|
||||
def to_model(self):
|
||||
model = pe.ConcreteModel()
|
||||
items = range(len(self.weights))
|
||||
model.x = pe.Var(items, domain=pe.Binary)
|
||||
model.OBJ = pe.Objective(
|
||||
expr=sum(model.x[v] * self.prices[v] for v in items), sense=pe.maximize
|
||||
)
|
||||
model.eq_capacity = pe.Constraint(
|
||||
expr=sum(model.x[v] * self.weights[v] for v in items) <= self.capacity
|
||||
)
|
||||
return model
|
||||
|
||||
def get_instance_features(self):
|
||||
return np.array(
|
||||
[
|
||||
self.capacity,
|
||||
np.average(self.weights),
|
||||
]
|
||||
)
|
||||
|
||||
def get_variable_features(self, var, index):
|
||||
return np.array(
|
||||
[
|
||||
self.weights[index],
|
||||
self.prices[index],
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
class GurobiKnapsackInstance(KnapsackInstance):
|
||||
"""
|
||||
Simpler (one-dimensional) knapsack instance, implemented directly in Gurobi
|
||||
instead of Pyomo, used for testing.
|
||||
"""
|
||||
|
||||
def __init__(self, weights, prices, capacity):
|
||||
super().__init__(weights, prices, capacity)
|
||||
|
||||
def to_model(self):
|
||||
import gurobipy as gp
|
||||
from gurobipy import GRB
|
||||
|
||||
model = gp.Model("Knapsack")
|
||||
n = len(self.weights)
|
||||
x = model.addVars(n, vtype=GRB.BINARY, name="x")
|
||||
model.addConstr(
|
||||
gp.quicksum(x[i] * self.weights[i] for i in range(n)) <= self.capacity,
|
||||
"eq_capacity",
|
||||
)
|
||||
model.setObjective(
|
||||
gp.quicksum(x[i] * self.prices[i] for i in range(n)), GRB.MAXIMIZE
|
||||
)
|
||||
return model</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-classes">Classes</h2>
|
||||
<dl>
|
||||
<dt id="miplearn.problems.knapsack.ChallengeA"><code class="flex name class">
|
||||
<span>class <span class="ident">ChallengeA</span></span>
|
||||
<span>(</span><span>seed=42, n_training_instances=500, n_test_instances=50)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"><ul>
|
||||
<li>250 variables, 10 constraints, fixed weights</li>
|
||||
<li>w ~ U(0, 1000), jitter ~ U(0.95, 1.05)</li>
|
||||
<li>K = 500, u ~ U(0., 1.)</li>
|
||||
<li>alpha = 0.25</li>
|
||||
</ul></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">class ChallengeA:
|
||||
"""
|
||||
- 250 variables, 10 constraints, fixed weights
|
||||
- w ~ U(0, 1000), jitter ~ U(0.95, 1.05)
|
||||
- K = 500, u ~ U(0., 1.)
|
||||
- alpha = 0.25
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
seed=42,
|
||||
n_training_instances=500,
|
||||
n_test_instances=50,
|
||||
):
|
||||
|
||||
np.random.seed(seed)
|
||||
self.gen = MultiKnapsackGenerator(
|
||||
n=randint(low=250, high=251),
|
||||
m=randint(low=10, high=11),
|
||||
w=uniform(loc=0.0, scale=1000.0),
|
||||
K=uniform(loc=500.0, scale=0.0),
|
||||
u=uniform(loc=0.0, scale=1.0),
|
||||
alpha=uniform(loc=0.25, scale=0.0),
|
||||
fix_w=True,
|
||||
w_jitter=uniform(loc=0.95, scale=0.1),
|
||||
)
|
||||
np.random.seed(seed + 1)
|
||||
self.training_instances = self.gen.generate(n_training_instances)
|
||||
|
||||
np.random.seed(seed + 2)
|
||||
self.test_instances = self.gen.generate(n_test_instances)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.problems.knapsack.GurobiKnapsackInstance"><code class="flex name class">
|
||||
<span>class <span class="ident">GurobiKnapsackInstance</span></span>
|
||||
<span>(</span><span>weights, prices, capacity)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"><p>Simpler (one-dimensional) knapsack instance, implemented directly in Gurobi
|
||||
instead of Pyomo, used for testing.</p></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">class GurobiKnapsackInstance(KnapsackInstance):
|
||||
"""
|
||||
Simpler (one-dimensional) knapsack instance, implemented directly in Gurobi
|
||||
instead of Pyomo, used for testing.
|
||||
"""
|
||||
|
||||
def __init__(self, weights, prices, capacity):
|
||||
super().__init__(weights, prices, capacity)
|
||||
|
||||
def to_model(self):
|
||||
import gurobipy as gp
|
||||
from gurobipy import GRB
|
||||
|
||||
model = gp.Model("Knapsack")
|
||||
n = len(self.weights)
|
||||
x = model.addVars(n, vtype=GRB.BINARY, name="x")
|
||||
model.addConstr(
|
||||
gp.quicksum(x[i] * self.weights[i] for i in range(n)) <= self.capacity,
|
||||
"eq_capacity",
|
||||
)
|
||||
model.setObjective(
|
||||
gp.quicksum(x[i] * self.prices[i] for i in range(n)), GRB.MAXIMIZE
|
||||
)
|
||||
return model</code></pre>
|
||||
</details>
|
||||
<h3>Ancestors</h3>
|
||||
<ul class="hlist">
|
||||
<li><a title="miplearn.problems.knapsack.KnapsackInstance" href="#miplearn.problems.knapsack.KnapsackInstance">KnapsackInstance</a></li>
|
||||
<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.problems.knapsack.KnapsackInstance" href="#miplearn.problems.knapsack.KnapsackInstance">KnapsackInstance</a></b></code>:
|
||||
<ul class="hlist">
|
||||
<li><code><a title="miplearn.problems.knapsack.KnapsackInstance.build_lazy_constraint" href="../instance.html#miplearn.instance.Instance.build_lazy_constraint">build_lazy_constraint</a></code></li>
|
||||
<li><code><a title="miplearn.problems.knapsack.KnapsackInstance.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.problems.knapsack.KnapsackInstance.get_instance_features" href="../instance.html#miplearn.instance.Instance.get_instance_features">get_instance_features</a></code></li>
|
||||
<li><code><a title="miplearn.problems.knapsack.KnapsackInstance.get_variable_category" href="../instance.html#miplearn.instance.Instance.get_variable_category">get_variable_category</a></code></li>
|
||||
<li><code><a title="miplearn.problems.knapsack.KnapsackInstance.get_variable_features" href="../instance.html#miplearn.instance.Instance.get_variable_features">get_variable_features</a></code></li>
|
||||
<li><code><a title="miplearn.problems.knapsack.KnapsackInstance.to_model" href="../instance.html#miplearn.instance.Instance.to_model">to_model</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</dd>
|
||||
<dt id="miplearn.problems.knapsack.KnapsackInstance"><code class="flex name class">
|
||||
<span>class <span class="ident">KnapsackInstance</span></span>
|
||||
<span>(</span><span>weights, prices, capacity)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"><p>Simpler (one-dimensional) Knapsack Problem, used for testing.</p></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">class KnapsackInstance(Instance):
|
||||
"""
|
||||
Simpler (one-dimensional) Knapsack Problem, used for testing.
|
||||
"""
|
||||
|
||||
def __init__(self, weights, prices, capacity):
|
||||
super().__init__()
|
||||
self.weights = weights
|
||||
self.prices = prices
|
||||
self.capacity = capacity
|
||||
|
||||
def to_model(self):
|
||||
model = pe.ConcreteModel()
|
||||
items = range(len(self.weights))
|
||||
model.x = pe.Var(items, domain=pe.Binary)
|
||||
model.OBJ = pe.Objective(
|
||||
expr=sum(model.x[v] * self.prices[v] for v in items), sense=pe.maximize
|
||||
)
|
||||
model.eq_capacity = pe.Constraint(
|
||||
expr=sum(model.x[v] * self.weights[v] for v in items) <= self.capacity
|
||||
)
|
||||
return model
|
||||
|
||||
def get_instance_features(self):
|
||||
return np.array(
|
||||
[
|
||||
self.capacity,
|
||||
np.average(self.weights),
|
||||
]
|
||||
)
|
||||
|
||||
def get_variable_features(self, var, index):
|
||||
return np.array(
|
||||
[
|
||||
self.weights[index],
|
||||
self.prices[index],
|
||||
]
|
||||
)</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>Subclasses</h3>
|
||||
<ul class="hlist">
|
||||
<li><a title="miplearn.problems.knapsack.GurobiKnapsackInstance" href="#miplearn.problems.knapsack.GurobiKnapsackInstance">GurobiKnapsackInstance</a></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.problems.knapsack.MultiKnapsackGenerator"><code class="flex name class">
|
||||
<span>class <span class="ident">MultiKnapsackGenerator</span></span>
|
||||
<span>(</span><span>n=<scipy.stats._distn_infrastructure.rv_frozen object>, m=<scipy.stats._distn_infrastructure.rv_frozen object>, w=<scipy.stats._distn_infrastructure.rv_frozen object>, K=<scipy.stats._distn_infrastructure.rv_frozen object>, u=<scipy.stats._distn_infrastructure.rv_frozen object>, alpha=<scipy.stats._distn_infrastructure.rv_frozen object>, fix_w=False, w_jitter=<scipy.stats._distn_infrastructure.rv_frozen object>, round=True)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"><p>Initialize the problem generator.</p>
|
||||
<p>Instances have a random number of items (or variables) and a random number of knapsacks
|
||||
(or constraints), as specified by the provided probability distributions <code>n</code> and <code>m</code>,
|
||||
respectively. The weight of each item <code>i</code> on knapsack <code>j</code> is sampled independently from
|
||||
the provided distribution <code>w</code>. The capacity of knapsack <code>j</code> is set to:</p>
|
||||
<pre><code>alpha_j * sum(w[i,j] for i in range(n)),
|
||||
</code></pre>
|
||||
<p>where <code>alpha_j</code>, the tightness ratio, is sampled from the provided probability
|
||||
distribution <code>alpha</code>. To make the instances more challenging, the costs of the items
|
||||
are linearly correlated to their average weights. More specifically, the weight of each
|
||||
item <code>i</code> is set to:</p>
|
||||
<pre><code>sum(w[i,j]/m for j in range(m)) + K * u_i,
|
||||
</code></pre>
|
||||
<p>where <code>K</code>, the correlation coefficient, and <code>u_i</code>, the correlation multiplier, are sampled
|
||||
from the provided probability distributions. Note that <code>K</code> is only sample once for the
|
||||
entire instance.</p>
|
||||
<p>If fix_w=True is provided, then w[i,j] are kept the same in all generated instances. This
|
||||
also implies that n and m are kept fixed. Although the prices and capacities are derived
|
||||
from w[i,j], as long as u and K are not constants, the generated instances will still not
|
||||
be completely identical.</p>
|
||||
<p>If a probability distribution w_jitter is provided, then item weights will be set to
|
||||
w[i,j] * gamma[i,j] where gamma[i,j] is sampled from w_jitter. When combined with
|
||||
fix_w=True, this argument may be used to generate instances where the weight of each item
|
||||
is roughly the same, but not exactly identical, across all instances. The prices of the
|
||||
items and the capacities of the knapsacks will be calculated as above, but using these
|
||||
perturbed weights instead.</p>
|
||||
<p>By default, all generated prices, weights and capacities are rounded to the nearest integer
|
||||
number. If <code>round=False</code> is provided, this rounding will be disabled.</p>
|
||||
<h2 id="parameters">Parameters</h2>
|
||||
<dl>
|
||||
<dt><strong><code>n</code></strong> : <code>rv_discrete</code></dt>
|
||||
<dd>Probability distribution for the number of items (or variables)</dd>
|
||||
<dt><strong><code>m</code></strong> : <code>rv_discrete</code></dt>
|
||||
<dd>Probability distribution for the number of knapsacks (or constraints)</dd>
|
||||
<dt><strong><code>w</code></strong> : <code>rv_continuous</code></dt>
|
||||
<dd>Probability distribution for the item weights</dd>
|
||||
<dt><strong><code>K</code></strong> : <code>rv_continuous</code></dt>
|
||||
<dd>Probability distribution for the profit correlation coefficient</dd>
|
||||
<dt><strong><code>u</code></strong> : <code>rv_continuous</code></dt>
|
||||
<dd>Probability distribution for the profit multiplier</dd>
|
||||
<dt><strong><code>alpha</code></strong> : <code>rv_continuous</code></dt>
|
||||
<dd>Probability distribution for the tightness ratio</dd>
|
||||
<dt><strong><code>fix_w</code></strong> : <code>boolean</code></dt>
|
||||
<dd>If true, weights are kept the same (minus the noise from w_jitter) in all instances</dd>
|
||||
<dt><strong><code>w_jitter</code></strong> : <code>rv_continuous</code></dt>
|
||||
<dd>Probability distribution for random noise added to the weights</dd>
|
||||
<dt><strong><code>round</code></strong> : <code>boolean</code></dt>
|
||||
<dd>If true, all prices, weights and capacities are rounded to the nearest integer</dd>
|
||||
</dl></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">class MultiKnapsackGenerator:
|
||||
def __init__(
|
||||
self,
|
||||
n=randint(low=100, high=101),
|
||||
m=randint(low=30, high=31),
|
||||
w=randint(low=0, high=1000),
|
||||
K=randint(low=500, high=500),
|
||||
u=uniform(loc=0.0, scale=1.0),
|
||||
alpha=uniform(loc=0.25, scale=0.0),
|
||||
fix_w=False,
|
||||
w_jitter=uniform(loc=1.0, scale=0.0),
|
||||
round=True,
|
||||
):
|
||||
"""Initialize the problem generator.
|
||||
|
||||
Instances have a random number of items (or variables) and a random number of knapsacks
|
||||
(or constraints), as specified by the provided probability distributions `n` and `m`,
|
||||
respectively. The weight of each item `i` on knapsack `j` is sampled independently from
|
||||
the provided distribution `w`. The capacity of knapsack `j` is set to:
|
||||
|
||||
alpha_j * sum(w[i,j] for i in range(n)),
|
||||
|
||||
where `alpha_j`, the tightness ratio, is sampled from the provided probability
|
||||
distribution `alpha`. To make the instances more challenging, the costs of the items
|
||||
are linearly correlated to their average weights. More specifically, the weight of each
|
||||
item `i` is set to:
|
||||
|
||||
sum(w[i,j]/m for j in range(m)) + K * u_i,
|
||||
|
||||
where `K`, the correlation coefficient, and `u_i`, the correlation multiplier, are sampled
|
||||
from the provided probability distributions. Note that `K` is only sample once for the
|
||||
entire instance.
|
||||
|
||||
If fix_w=True is provided, then w[i,j] are kept the same in all generated instances. This
|
||||
also implies that n and m are kept fixed. Although the prices and capacities are derived
|
||||
from w[i,j], as long as u and K are not constants, the generated instances will still not
|
||||
be completely identical.
|
||||
|
||||
If a probability distribution w_jitter is provided, then item weights will be set to
|
||||
w[i,j] * gamma[i,j] where gamma[i,j] is sampled from w_jitter. When combined with
|
||||
fix_w=True, this argument may be used to generate instances where the weight of each item
|
||||
is roughly the same, but not exactly identical, across all instances. The prices of the
|
||||
items and the capacities of the knapsacks will be calculated as above, but using these
|
||||
perturbed weights instead.
|
||||
|
||||
By default, all generated prices, weights and capacities are rounded to the nearest integer
|
||||
number. If `round=False` is provided, this rounding will be disabled.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
n: rv_discrete
|
||||
Probability distribution for the number of items (or variables)
|
||||
m: rv_discrete
|
||||
Probability distribution for the number of knapsacks (or constraints)
|
||||
w: rv_continuous
|
||||
Probability distribution for the item weights
|
||||
K: rv_continuous
|
||||
Probability distribution for the profit correlation coefficient
|
||||
u: rv_continuous
|
||||
Probability distribution for the profit multiplier
|
||||
alpha: rv_continuous
|
||||
Probability distribution for the tightness ratio
|
||||
fix_w: boolean
|
||||
If true, weights are kept the same (minus the noise from w_jitter) in all instances
|
||||
w_jitter: rv_continuous
|
||||
Probability distribution for random noise added to the weights
|
||||
round: boolean
|
||||
If true, all prices, weights and capacities are rounded to the nearest integer
|
||||
"""
|
||||
assert isinstance(n, rv_frozen), "n should be a SciPy probability distribution"
|
||||
assert isinstance(m, rv_frozen), "m should be a SciPy probability distribution"
|
||||
assert isinstance(w, rv_frozen), "w should be a SciPy probability distribution"
|
||||
assert isinstance(K, rv_frozen), "K should be a SciPy probability distribution"
|
||||
assert isinstance(u, rv_frozen), "u should be a SciPy probability distribution"
|
||||
assert isinstance(
|
||||
alpha, rv_frozen
|
||||
), "alpha should be a SciPy probability distribution"
|
||||
assert isinstance(fix_w, bool), "fix_w should be boolean"
|
||||
assert isinstance(
|
||||
w_jitter, rv_frozen
|
||||
), "w_jitter should be a SciPy probability distribution"
|
||||
|
||||
self.n = n
|
||||
self.m = m
|
||||
self.w = w
|
||||
self.K = K
|
||||
self.u = u
|
||||
self.alpha = alpha
|
||||
self.w_jitter = w_jitter
|
||||
self.round = round
|
||||
|
||||
if fix_w:
|
||||
self.fix_n = self.n.rvs()
|
||||
self.fix_m = self.m.rvs()
|
||||
self.fix_w = np.array([self.w.rvs(self.fix_n) for _ in range(self.fix_m)])
|
||||
self.fix_u = self.u.rvs(self.fix_n)
|
||||
self.fix_K = self.K.rvs()
|
||||
else:
|
||||
self.fix_n = None
|
||||
self.fix_m = None
|
||||
self.fix_w = None
|
||||
self.fix_u = None
|
||||
self.fix_K = None
|
||||
|
||||
def generate(self, n_samples):
|
||||
def _sample():
|
||||
if self.fix_w is not None:
|
||||
n = self.fix_n
|
||||
m = self.fix_m
|
||||
w = self.fix_w
|
||||
u = self.fix_u
|
||||
K = self.fix_K
|
||||
else:
|
||||
n = self.n.rvs()
|
||||
m = self.m.rvs()
|
||||
w = np.array([self.w.rvs(n) for _ in range(m)])
|
||||
u = self.u.rvs(n)
|
||||
K = self.K.rvs()
|
||||
w = w * np.array([self.w_jitter.rvs(n) for _ in range(m)])
|
||||
alpha = self.alpha.rvs(m)
|
||||
p = np.array([w[:, j].sum() / m + K * u[j] for j in range(n)])
|
||||
b = np.array([w[i, :].sum() * alpha[i] for i in range(m)])
|
||||
if self.round:
|
||||
p = p.round()
|
||||
b = b.round()
|
||||
w = w.round()
|
||||
return MultiKnapsackInstance(p, b, w)
|
||||
|
||||
return [_sample() for _ in range(n_samples)]</code></pre>
|
||||
</details>
|
||||
<h3>Methods</h3>
|
||||
<dl>
|
||||
<dt id="miplearn.problems.knapsack.MultiKnapsackGenerator.generate"><code class="name flex">
|
||||
<span>def <span class="ident">generate</span></span>(<span>self, n_samples)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def generate(self, n_samples):
|
||||
def _sample():
|
||||
if self.fix_w is not None:
|
||||
n = self.fix_n
|
||||
m = self.fix_m
|
||||
w = self.fix_w
|
||||
u = self.fix_u
|
||||
K = self.fix_K
|
||||
else:
|
||||
n = self.n.rvs()
|
||||
m = self.m.rvs()
|
||||
w = np.array([self.w.rvs(n) for _ in range(m)])
|
||||
u = self.u.rvs(n)
|
||||
K = self.K.rvs()
|
||||
w = w * np.array([self.w_jitter.rvs(n) for _ in range(m)])
|
||||
alpha = self.alpha.rvs(m)
|
||||
p = np.array([w[:, j].sum() / m + K * u[j] for j in range(n)])
|
||||
b = np.array([w[i, :].sum() * alpha[i] for i in range(m)])
|
||||
if self.round:
|
||||
p = p.round()
|
||||
b = b.round()
|
||||
w = w.round()
|
||||
return MultiKnapsackInstance(p, b, w)
|
||||
|
||||
return [_sample() for _ in range(n_samples)]</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt id="miplearn.problems.knapsack.MultiKnapsackInstance"><code class="flex name class">
|
||||
<span>class <span class="ident">MultiKnapsackInstance</span></span>
|
||||
<span>(</span><span>prices, capacities, weights)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"><p>Representation of the Multidimensional 0-1 Knapsack Problem.</p>
|
||||
<p>Given a set of n items and m knapsacks, the problem is to find a subset of items S maximizing
|
||||
sum(prices[i] for i in S). If selected, each item i occupies weights[i,j] units of space in
|
||||
each knapsack j. Furthermore, each knapsack j has limited storage space, given by capacities[j].</p>
|
||||
<p>This implementation assigns a different category for each decision variable, and therefore
|
||||
trains one ML model per variable. It is only suitable when training and test instances have
|
||||
same size and items don't shuffle around.</p></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">class MultiKnapsackInstance(Instance):
|
||||
"""Representation of the Multidimensional 0-1 Knapsack Problem.
|
||||
|
||||
Given a set of n items and m knapsacks, the problem is to find a subset of items S maximizing
|
||||
sum(prices[i] for i in S). If selected, each item i occupies weights[i,j] units of space in
|
||||
each knapsack j. Furthermore, each knapsack j has limited storage space, given by capacities[j].
|
||||
|
||||
This implementation assigns a different category for each decision variable, and therefore
|
||||
trains one ML model per variable. It is only suitable when training and test instances have
|
||||
same size and items don't shuffle around.
|
||||
"""
|
||||
|
||||
def __init__(self, prices, capacities, weights):
|
||||
super().__init__()
|
||||
assert isinstance(prices, np.ndarray)
|
||||
assert isinstance(capacities, np.ndarray)
|
||||
assert isinstance(weights, np.ndarray)
|
||||
assert len(weights.shape) == 2
|
||||
self.m, self.n = weights.shape
|
||||
assert prices.shape == (self.n,)
|
||||
assert capacities.shape == (self.m,)
|
||||
self.prices = prices
|
||||
self.capacities = capacities
|
||||
self.weights = weights
|
||||
|
||||
def to_model(self):
|
||||
model = pe.ConcreteModel()
|
||||
model.x = pe.Var(range(self.n), domain=pe.Binary)
|
||||
model.OBJ = pe.Objective(
|
||||
rule=lambda model: sum(model.x[j] * self.prices[j] for j in range(self.n)),
|
||||
sense=pe.maximize,
|
||||
)
|
||||
model.eq_capacity = pe.ConstraintList()
|
||||
for i in range(self.m):
|
||||
model.eq_capacity.add(
|
||||
sum(model.x[j] * self.weights[i, j] for j in range(self.n))
|
||||
<= self.capacities[i]
|
||||
)
|
||||
|
||||
return model
|
||||
|
||||
def get_instance_features(self):
|
||||
return np.hstack(
|
||||
[
|
||||
np.mean(self.prices),
|
||||
self.capacities,
|
||||
]
|
||||
)
|
||||
|
||||
def get_variable_features(self, var, index):
|
||||
return np.hstack(
|
||||
[
|
||||
self.prices[index],
|
||||
self.weights[:, index],
|
||||
]
|
||||
)</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.problems" href="index.html">miplearn.problems</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-classes">Classes</a></h3>
|
||||
<ul>
|
||||
<li>
|
||||
<h4><code><a title="miplearn.problems.knapsack.ChallengeA" href="#miplearn.problems.knapsack.ChallengeA">ChallengeA</a></code></h4>
|
||||
</li>
|
||||
<li>
|
||||
<h4><code><a title="miplearn.problems.knapsack.GurobiKnapsackInstance" href="#miplearn.problems.knapsack.GurobiKnapsackInstance">GurobiKnapsackInstance</a></code></h4>
|
||||
</li>
|
||||
<li>
|
||||
<h4><code><a title="miplearn.problems.knapsack.KnapsackInstance" href="#miplearn.problems.knapsack.KnapsackInstance">KnapsackInstance</a></code></h4>
|
||||
</li>
|
||||
<li>
|
||||
<h4><code><a title="miplearn.problems.knapsack.MultiKnapsackGenerator" href="#miplearn.problems.knapsack.MultiKnapsackGenerator">MultiKnapsackGenerator</a></code></h4>
|
||||
<ul class="">
|
||||
<li><code><a title="miplearn.problems.knapsack.MultiKnapsackGenerator.generate" href="#miplearn.problems.knapsack.MultiKnapsackGenerator.generate">generate</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<h4><code><a title="miplearn.problems.knapsack.MultiKnapsackInstance" href="#miplearn.problems.knapsack.MultiKnapsackInstance">MultiKnapsackInstance</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>
|
||||
434
0.2/api/miplearn/problems/stab.html
Normal file
434
0.2/api/miplearn/problems/stab.html
Normal file
@@ -0,0 +1,434 @@
|
||||
<!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.problems.stab 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.problems.stab</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 networkx as nx
|
||||
import numpy as np
|
||||
import pyomo.environ as pe
|
||||
from scipy.stats import uniform, randint
|
||||
from scipy.stats.distributions import rv_frozen
|
||||
|
||||
from miplearn.instance import Instance
|
||||
|
||||
|
||||
class ChallengeA:
|
||||
def __init__(
|
||||
self,
|
||||
seed=42,
|
||||
n_training_instances=500,
|
||||
n_test_instances=50,
|
||||
):
|
||||
|
||||
np.random.seed(seed)
|
||||
self.generator = MaxWeightStableSetGenerator(
|
||||
w=uniform(loc=100.0, scale=50.0),
|
||||
n=randint(low=200, high=201),
|
||||
p=uniform(loc=0.05, scale=0.0),
|
||||
fix_graph=True,
|
||||
)
|
||||
|
||||
np.random.seed(seed + 1)
|
||||
self.training_instances = self.generator.generate(n_training_instances)
|
||||
|
||||
np.random.seed(seed + 2)
|
||||
self.test_instances = self.generator.generate(n_test_instances)
|
||||
|
||||
|
||||
class MaxWeightStableSetGenerator:
|
||||
"""Random instance generator for the Maximum-Weight Stable Set Problem.
|
||||
|
||||
The generator has two modes of operation. When `fix_graph=True` is provided, one random
|
||||
Erdős-Rényi graph $G_{n,p}$ is generated in the constructor, where $n$ and $p$ are sampled
|
||||
from user-provided probability distributions `n` and `p`. To generate each instance, the
|
||||
generator independently samples each $w_v$ from the user-provided probability distribution `w`.
|
||||
|
||||
When `fix_graph=False`, a new random graph is generated for each instance; the remaining
|
||||
parameters are sampled in the same way.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
w=uniform(loc=10.0, scale=1.0),
|
||||
n=randint(low=250, high=251),
|
||||
p=uniform(loc=0.05, scale=0.0),
|
||||
fix_graph=True,
|
||||
):
|
||||
"""Initialize the problem generator.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
w: rv_continuous
|
||||
Probability distribution for vertex weights.
|
||||
n: rv_discrete
|
||||
Probability distribution for parameter $n$ in Erdős-Rényi model.
|
||||
p: rv_continuous
|
||||
Probability distribution for parameter $p$ in Erdős-Rényi model.
|
||||
"""
|
||||
assert isinstance(w, rv_frozen), "w should be a SciPy probability distribution"
|
||||
assert isinstance(n, rv_frozen), "n should be a SciPy probability distribution"
|
||||
assert isinstance(p, rv_frozen), "p should be a SciPy probability distribution"
|
||||
self.w = w
|
||||
self.n = n
|
||||
self.p = p
|
||||
self.fix_graph = fix_graph
|
||||
self.graph = None
|
||||
if fix_graph:
|
||||
self.graph = self._generate_graph()
|
||||
|
||||
def generate(self, n_samples):
|
||||
def _sample():
|
||||
if self.graph is not None:
|
||||
graph = self.graph
|
||||
else:
|
||||
graph = self._generate_graph()
|
||||
weights = self.w.rvs(graph.number_of_nodes())
|
||||
return MaxWeightStableSetInstance(graph, weights)
|
||||
|
||||
return [_sample() for _ in range(n_samples)]
|
||||
|
||||
def _generate_graph(self):
|
||||
return nx.generators.random_graphs.binomial_graph(self.n.rvs(), self.p.rvs())
|
||||
|
||||
|
||||
class MaxWeightStableSetInstance(Instance):
|
||||
"""An instance of the Maximum-Weight Stable Set Problem.
|
||||
|
||||
Given a graph G=(V,E) and a weight w_v for each vertex v, the problem asks for a stable
|
||||
set S of G maximizing sum(w_v for v in S). A stable set (also called independent set) is
|
||||
a subset of vertices, no two of which are adjacent.
|
||||
|
||||
This is one of Karp's 21 NP-complete problems.
|
||||
"""
|
||||
|
||||
def __init__(self, graph, weights):
|
||||
super().__init__()
|
||||
self.graph = graph
|
||||
self.weights = weights
|
||||
|
||||
def to_model(self):
|
||||
nodes = list(self.graph.nodes)
|
||||
model = pe.ConcreteModel()
|
||||
model.x = pe.Var(nodes, domain=pe.Binary)
|
||||
model.OBJ = pe.Objective(
|
||||
expr=sum(model.x[v] * self.weights[v] for v in nodes), sense=pe.maximize
|
||||
)
|
||||
model.clique_eqs = pe.ConstraintList()
|
||||
for clique in nx.find_cliques(self.graph):
|
||||
model.clique_eqs.add(sum(model.x[i] for i in clique) <= 1)
|
||||
return model
|
||||
|
||||
def get_instance_features(self):
|
||||
return np.ones(0)
|
||||
|
||||
def get_variable_features(self, var, index):
|
||||
neighbor_weights = [0] * 15
|
||||
neighbor_degrees = [100] * 15
|
||||
for n in self.graph.neighbors(index):
|
||||
neighbor_weights += [self.weights[n] / self.weights[index]]
|
||||
neighbor_degrees += [self.graph.degree(n) / self.graph.degree(index)]
|
||||
neighbor_weights.sort(reverse=True)
|
||||
neighbor_degrees.sort()
|
||||
features = []
|
||||
features += neighbor_weights[:5]
|
||||
features += neighbor_degrees[:5]
|
||||
features += [self.graph.degree(index)]
|
||||
return np.array(features)
|
||||
|
||||
def get_variable_category(self, var, index):
|
||||
return "default"</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-classes">Classes</h2>
|
||||
<dl>
|
||||
<dt id="miplearn.problems.stab.ChallengeA"><code class="flex name class">
|
||||
<span>class <span class="ident">ChallengeA</span></span>
|
||||
<span>(</span><span>seed=42, n_training_instances=500, n_test_instances=50)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">class ChallengeA:
|
||||
def __init__(
|
||||
self,
|
||||
seed=42,
|
||||
n_training_instances=500,
|
||||
n_test_instances=50,
|
||||
):
|
||||
|
||||
np.random.seed(seed)
|
||||
self.generator = MaxWeightStableSetGenerator(
|
||||
w=uniform(loc=100.0, scale=50.0),
|
||||
n=randint(low=200, high=201),
|
||||
p=uniform(loc=0.05, scale=0.0),
|
||||
fix_graph=True,
|
||||
)
|
||||
|
||||
np.random.seed(seed + 1)
|
||||
self.training_instances = self.generator.generate(n_training_instances)
|
||||
|
||||
np.random.seed(seed + 2)
|
||||
self.test_instances = self.generator.generate(n_test_instances)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.problems.stab.MaxWeightStableSetGenerator"><code class="flex name class">
|
||||
<span>class <span class="ident">MaxWeightStableSetGenerator</span></span>
|
||||
<span>(</span><span>w=<scipy.stats._distn_infrastructure.rv_frozen object>, n=<scipy.stats._distn_infrastructure.rv_frozen object>, p=<scipy.stats._distn_infrastructure.rv_frozen object>, fix_graph=True)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"><p>Random instance generator for the Maximum-Weight Stable Set Problem.</p>
|
||||
<p>The generator has two modes of operation. When <code>fix_graph=True</code> is provided, one random
|
||||
Erdős-Rényi graph $G_{n,p}$ is generated in the constructor, where $n$ and $p$ are sampled
|
||||
from user-provided probability distributions <code>n</code> and <code>p</code>. To generate each instance, the
|
||||
generator independently samples each $w_v$ from the user-provided probability distribution <code>w</code>.</p>
|
||||
<p>When <code>fix_graph=False</code>, a new random graph is generated for each instance; the remaining
|
||||
parameters are sampled in the same way.</p>
|
||||
<p>Initialize the problem generator.</p>
|
||||
<h2 id="parameters">Parameters</h2>
|
||||
<dl>
|
||||
<dt><strong><code>w</code></strong> : <code>rv_continuous</code></dt>
|
||||
<dd>Probability distribution for vertex weights.</dd>
|
||||
<dt><strong><code>n</code></strong> : <code>rv_discrete</code></dt>
|
||||
<dd>Probability distribution for parameter $n$ in Erdős-Rényi model.</dd>
|
||||
<dt><strong><code>p</code></strong> : <code>rv_continuous</code></dt>
|
||||
<dd>Probability distribution for parameter $p$ in Erdős-Rényi model.</dd>
|
||||
</dl></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">class MaxWeightStableSetGenerator:
|
||||
"""Random instance generator for the Maximum-Weight Stable Set Problem.
|
||||
|
||||
The generator has two modes of operation. When `fix_graph=True` is provided, one random
|
||||
Erdős-Rényi graph $G_{n,p}$ is generated in the constructor, where $n$ and $p$ are sampled
|
||||
from user-provided probability distributions `n` and `p`. To generate each instance, the
|
||||
generator independently samples each $w_v$ from the user-provided probability distribution `w`.
|
||||
|
||||
When `fix_graph=False`, a new random graph is generated for each instance; the remaining
|
||||
parameters are sampled in the same way.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
w=uniform(loc=10.0, scale=1.0),
|
||||
n=randint(low=250, high=251),
|
||||
p=uniform(loc=0.05, scale=0.0),
|
||||
fix_graph=True,
|
||||
):
|
||||
"""Initialize the problem generator.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
w: rv_continuous
|
||||
Probability distribution for vertex weights.
|
||||
n: rv_discrete
|
||||
Probability distribution for parameter $n$ in Erdős-Rényi model.
|
||||
p: rv_continuous
|
||||
Probability distribution for parameter $p$ in Erdős-Rényi model.
|
||||
"""
|
||||
assert isinstance(w, rv_frozen), "w should be a SciPy probability distribution"
|
||||
assert isinstance(n, rv_frozen), "n should be a SciPy probability distribution"
|
||||
assert isinstance(p, rv_frozen), "p should be a SciPy probability distribution"
|
||||
self.w = w
|
||||
self.n = n
|
||||
self.p = p
|
||||
self.fix_graph = fix_graph
|
||||
self.graph = None
|
||||
if fix_graph:
|
||||
self.graph = self._generate_graph()
|
||||
|
||||
def generate(self, n_samples):
|
||||
def _sample():
|
||||
if self.graph is not None:
|
||||
graph = self.graph
|
||||
else:
|
||||
graph = self._generate_graph()
|
||||
weights = self.w.rvs(graph.number_of_nodes())
|
||||
return MaxWeightStableSetInstance(graph, weights)
|
||||
|
||||
return [_sample() for _ in range(n_samples)]
|
||||
|
||||
def _generate_graph(self):
|
||||
return nx.generators.random_graphs.binomial_graph(self.n.rvs(), self.p.rvs())</code></pre>
|
||||
</details>
|
||||
<h3>Methods</h3>
|
||||
<dl>
|
||||
<dt id="miplearn.problems.stab.MaxWeightStableSetGenerator.generate"><code class="name flex">
|
||||
<span>def <span class="ident">generate</span></span>(<span>self, n_samples)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def generate(self, n_samples):
|
||||
def _sample():
|
||||
if self.graph is not None:
|
||||
graph = self.graph
|
||||
else:
|
||||
graph = self._generate_graph()
|
||||
weights = self.w.rvs(graph.number_of_nodes())
|
||||
return MaxWeightStableSetInstance(graph, weights)
|
||||
|
||||
return [_sample() for _ in range(n_samples)]</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt id="miplearn.problems.stab.MaxWeightStableSetInstance"><code class="flex name class">
|
||||
<span>class <span class="ident">MaxWeightStableSetInstance</span></span>
|
||||
<span>(</span><span>graph, weights)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"><p>An instance of the Maximum-Weight Stable Set Problem.</p>
|
||||
<p>Given a graph G=(V,E) and a weight w_v for each vertex v, the problem asks for a stable
|
||||
set S of G maximizing sum(w_v for v in S). A stable set (also called independent set) is
|
||||
a subset of vertices, no two of which are adjacent.</p>
|
||||
<p>This is one of Karp's 21 NP-complete problems.</p></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">class MaxWeightStableSetInstance(Instance):
|
||||
"""An instance of the Maximum-Weight Stable Set Problem.
|
||||
|
||||
Given a graph G=(V,E) and a weight w_v for each vertex v, the problem asks for a stable
|
||||
set S of G maximizing sum(w_v for v in S). A stable set (also called independent set) is
|
||||
a subset of vertices, no two of which are adjacent.
|
||||
|
||||
This is one of Karp's 21 NP-complete problems.
|
||||
"""
|
||||
|
||||
def __init__(self, graph, weights):
|
||||
super().__init__()
|
||||
self.graph = graph
|
||||
self.weights = weights
|
||||
|
||||
def to_model(self):
|
||||
nodes = list(self.graph.nodes)
|
||||
model = pe.ConcreteModel()
|
||||
model.x = pe.Var(nodes, domain=pe.Binary)
|
||||
model.OBJ = pe.Objective(
|
||||
expr=sum(model.x[v] * self.weights[v] for v in nodes), sense=pe.maximize
|
||||
)
|
||||
model.clique_eqs = pe.ConstraintList()
|
||||
for clique in nx.find_cliques(self.graph):
|
||||
model.clique_eqs.add(sum(model.x[i] for i in clique) <= 1)
|
||||
return model
|
||||
|
||||
def get_instance_features(self):
|
||||
return np.ones(0)
|
||||
|
||||
def get_variable_features(self, var, index):
|
||||
neighbor_weights = [0] * 15
|
||||
neighbor_degrees = [100] * 15
|
||||
for n in self.graph.neighbors(index):
|
||||
neighbor_weights += [self.weights[n] / self.weights[index]]
|
||||
neighbor_degrees += [self.graph.degree(n) / self.graph.degree(index)]
|
||||
neighbor_weights.sort(reverse=True)
|
||||
neighbor_degrees.sort()
|
||||
features = []
|
||||
features += neighbor_weights[:5]
|
||||
features += neighbor_degrees[:5]
|
||||
features += [self.graph.degree(index)]
|
||||
return np.array(features)
|
||||
|
||||
def get_variable_category(self, var, index):
|
||||
return "default"</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.problems" href="index.html">miplearn.problems</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-classes">Classes</a></h3>
|
||||
<ul>
|
||||
<li>
|
||||
<h4><code><a title="miplearn.problems.stab.ChallengeA" href="#miplearn.problems.stab.ChallengeA">ChallengeA</a></code></h4>
|
||||
</li>
|
||||
<li>
|
||||
<h4><code><a title="miplearn.problems.stab.MaxWeightStableSetGenerator" href="#miplearn.problems.stab.MaxWeightStableSetGenerator">MaxWeightStableSetGenerator</a></code></h4>
|
||||
<ul class="">
|
||||
<li><code><a title="miplearn.problems.stab.MaxWeightStableSetGenerator.generate" href="#miplearn.problems.stab.MaxWeightStableSetGenerator.generate">generate</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<h4><code><a title="miplearn.problems.stab.MaxWeightStableSetInstance" href="#miplearn.problems.stab.MaxWeightStableSetInstance">MaxWeightStableSetInstance</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>
|
||||
83
0.2/api/miplearn/problems/tests/index.html
Normal file
83
0.2/api/miplearn/problems/tests/index.html
Normal file
@@ -0,0 +1,83 @@
|
||||
<!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.problems.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.problems.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.</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-submodules">Sub-modules</h2>
|
||||
<dl>
|
||||
<dt><code class="name"><a title="miplearn.problems.tests.test_knapsack" href="test_knapsack.html">miplearn.problems.tests.test_knapsack</a></code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
</dd>
|
||||
<dt><code class="name"><a title="miplearn.problems.tests.test_stab" href="test_stab.html">miplearn.problems.tests.test_stab</a></code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
</dd>
|
||||
<dt><code class="name"><a title="miplearn.problems.tests.test_tsp" href="test_tsp.html">miplearn.problems.tests.test_tsp</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.problems" href="../index.html">miplearn.problems</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-submodules">Sub-modules</a></h3>
|
||||
<ul>
|
||||
<li><code><a title="miplearn.problems.tests.test_knapsack" href="test_knapsack.html">miplearn.problems.tests.test_knapsack</a></code></li>
|
||||
<li><code><a title="miplearn.problems.tests.test_stab" href="test_stab.html">miplearn.problems.tests.test_stab</a></code></li>
|
||||
<li><code><a title="miplearn.problems.tests.test_tsp" href="test_tsp.html">miplearn.problems.tests.test_tsp</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>
|
||||
115
0.2/api/miplearn/problems/tests/test_knapsack.html
Normal file
115
0.2/api/miplearn/problems/tests/test_knapsack.html
Normal file
@@ -0,0 +1,115 @@
|
||||
<!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.problems.tests.test_knapsack 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.problems.tests.test_knapsack</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 numpy as np
|
||||
from scipy.stats import uniform, randint
|
||||
|
||||
from miplearn.problems.knapsack import MultiKnapsackGenerator
|
||||
|
||||
|
||||
def test_knapsack_generator():
|
||||
gen = MultiKnapsackGenerator(
|
||||
n=randint(low=100, high=101),
|
||||
m=randint(low=30, high=31),
|
||||
w=randint(low=0, high=1000),
|
||||
K=randint(low=500, high=501),
|
||||
u=uniform(loc=1.0, scale=1.0),
|
||||
alpha=uniform(loc=0.50, scale=0.0),
|
||||
)
|
||||
instances = gen.generate(100)
|
||||
w_sum = sum(instance.weights for instance in instances) / len(instances)
|
||||
b_sum = sum(instance.capacities for instance in instances) / len(instances)
|
||||
assert round(np.mean(w_sum), -1) == 500.0
|
||||
assert round(np.mean(b_sum), -3) == 25000.0</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-functions">Functions</h2>
|
||||
<dl>
|
||||
<dt id="miplearn.problems.tests.test_knapsack.test_knapsack_generator"><code class="name flex">
|
||||
<span>def <span class="ident">test_knapsack_generator</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_knapsack_generator():
|
||||
gen = MultiKnapsackGenerator(
|
||||
n=randint(low=100, high=101),
|
||||
m=randint(low=30, high=31),
|
||||
w=randint(low=0, high=1000),
|
||||
K=randint(low=500, high=501),
|
||||
u=uniform(loc=1.0, scale=1.0),
|
||||
alpha=uniform(loc=0.50, scale=0.0),
|
||||
)
|
||||
instances = gen.generate(100)
|
||||
w_sum = sum(instance.weights for instance in instances) / len(instances)
|
||||
b_sum = sum(instance.capacities for instance in instances) / len(instances)
|
||||
assert round(np.mean(w_sum), -1) == 500.0
|
||||
assert round(np.mean(b_sum), -3) == 25000.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.problems.tests" href="index.html">miplearn.problems.tests</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-functions">Functions</a></h3>
|
||||
<ul class="">
|
||||
<li><code><a title="miplearn.problems.tests.test_knapsack.test_knapsack_generator" href="#miplearn.problems.tests.test_knapsack.test_knapsack_generator">test_knapsack_generator</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>
|
||||
191
0.2/api/miplearn/problems/tests/test_stab.html
Normal file
191
0.2/api/miplearn/problems/tests/test_stab.html
Normal file
@@ -0,0 +1,191 @@
|
||||
<!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.problems.tests.test_stab 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.problems.tests.test_stab</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 networkx as nx
|
||||
import numpy as np
|
||||
from scipy.stats import uniform, randint
|
||||
|
||||
from miplearn.problems.stab import MaxWeightStableSetInstance
|
||||
from miplearn.solvers.learning import LearningSolver
|
||||
|
||||
|
||||
def test_stab():
|
||||
graph = nx.cycle_graph(5)
|
||||
weights = [1.0, 1.0, 1.0, 1.0, 1.0]
|
||||
instance = MaxWeightStableSetInstance(graph, weights)
|
||||
solver = LearningSolver()
|
||||
stats = solver.solve(instance)
|
||||
assert stats["Lower bound"] == 2.0
|
||||
|
||||
|
||||
def test_stab_generator_fixed_graph():
|
||||
np.random.seed(42)
|
||||
from miplearn.problems.stab import MaxWeightStableSetGenerator
|
||||
|
||||
gen = MaxWeightStableSetGenerator(
|
||||
w=uniform(loc=50.0, scale=10.0),
|
||||
n=randint(low=10, high=11),
|
||||
p=uniform(loc=0.05, scale=0.0),
|
||||
fix_graph=True,
|
||||
)
|
||||
instances = gen.generate(1_000)
|
||||
weights = np.array([instance.weights for instance in instances])
|
||||
weights_avg_actual = np.round(np.average(weights, axis=0))
|
||||
weights_avg_expected = [55.0] * 10
|
||||
assert list(weights_avg_actual) == weights_avg_expected
|
||||
|
||||
|
||||
def test_stab_generator_random_graph():
|
||||
np.random.seed(42)
|
||||
from miplearn.problems.stab import MaxWeightStableSetGenerator
|
||||
|
||||
gen = MaxWeightStableSetGenerator(
|
||||
w=uniform(loc=50.0, scale=10.0),
|
||||
n=randint(low=30, high=41),
|
||||
p=uniform(loc=0.5, scale=0.0),
|
||||
fix_graph=False,
|
||||
)
|
||||
instances = gen.generate(1_000)
|
||||
n_nodes = [instance.graph.number_of_nodes() for instance in instances]
|
||||
n_edges = [instance.graph.number_of_edges() for instance in instances]
|
||||
assert np.round(np.mean(n_nodes)) == 35.0
|
||||
assert np.round(np.mean(n_edges), -1) == 300.0</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-functions">Functions</h2>
|
||||
<dl>
|
||||
<dt id="miplearn.problems.tests.test_stab.test_stab"><code class="name flex">
|
||||
<span>def <span class="ident">test_stab</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_stab():
|
||||
graph = nx.cycle_graph(5)
|
||||
weights = [1.0, 1.0, 1.0, 1.0, 1.0]
|
||||
instance = MaxWeightStableSetInstance(graph, weights)
|
||||
solver = LearningSolver()
|
||||
stats = solver.solve(instance)
|
||||
assert stats["Lower bound"] == 2.0</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.problems.tests.test_stab.test_stab_generator_fixed_graph"><code class="name flex">
|
||||
<span>def <span class="ident">test_stab_generator_fixed_graph</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_stab_generator_fixed_graph():
|
||||
np.random.seed(42)
|
||||
from miplearn.problems.stab import MaxWeightStableSetGenerator
|
||||
|
||||
gen = MaxWeightStableSetGenerator(
|
||||
w=uniform(loc=50.0, scale=10.0),
|
||||
n=randint(low=10, high=11),
|
||||
p=uniform(loc=0.05, scale=0.0),
|
||||
fix_graph=True,
|
||||
)
|
||||
instances = gen.generate(1_000)
|
||||
weights = np.array([instance.weights for instance in instances])
|
||||
weights_avg_actual = np.round(np.average(weights, axis=0))
|
||||
weights_avg_expected = [55.0] * 10
|
||||
assert list(weights_avg_actual) == weights_avg_expected</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.problems.tests.test_stab.test_stab_generator_random_graph"><code class="name flex">
|
||||
<span>def <span class="ident">test_stab_generator_random_graph</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_stab_generator_random_graph():
|
||||
np.random.seed(42)
|
||||
from miplearn.problems.stab import MaxWeightStableSetGenerator
|
||||
|
||||
gen = MaxWeightStableSetGenerator(
|
||||
w=uniform(loc=50.0, scale=10.0),
|
||||
n=randint(low=30, high=41),
|
||||
p=uniform(loc=0.5, scale=0.0),
|
||||
fix_graph=False,
|
||||
)
|
||||
instances = gen.generate(1_000)
|
||||
n_nodes = [instance.graph.number_of_nodes() for instance in instances]
|
||||
n_edges = [instance.graph.number_of_edges() for instance in instances]
|
||||
assert np.round(np.mean(n_nodes)) == 35.0
|
||||
assert np.round(np.mean(n_edges), -1) == 300.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.problems.tests" href="index.html">miplearn.problems.tests</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-functions">Functions</a></h3>
|
||||
<ul class="">
|
||||
<li><code><a title="miplearn.problems.tests.test_stab.test_stab" href="#miplearn.problems.tests.test_stab.test_stab">test_stab</a></code></li>
|
||||
<li><code><a title="miplearn.problems.tests.test_stab.test_stab_generator_fixed_graph" href="#miplearn.problems.tests.test_stab.test_stab_generator_fixed_graph">test_stab_generator_fixed_graph</a></code></li>
|
||||
<li><code><a title="miplearn.problems.tests.test_stab.test_stab_generator_random_graph" href="#miplearn.problems.tests.test_stab.test_stab_generator_random_graph">test_stab_generator_random_graph</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>
|
||||
242
0.2/api/miplearn/problems/tests/test_tsp.html
Normal file
242
0.2/api/miplearn/problems/tests/test_tsp.html
Normal file
@@ -0,0 +1,242 @@
|
||||
<!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.problems.tests.test_tsp 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.problems.tests.test_tsp</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 numpy as np
|
||||
from numpy.linalg import norm
|
||||
from scipy.spatial.distance import pdist, squareform
|
||||
from scipy.stats import uniform, randint
|
||||
|
||||
from miplearn.problems.tsp import TravelingSalesmanGenerator, TravelingSalesmanInstance
|
||||
from miplearn.solvers.learning import LearningSolver
|
||||
|
||||
|
||||
def test_generator():
|
||||
instances = TravelingSalesmanGenerator(
|
||||
x=uniform(loc=0.0, scale=1000.0),
|
||||
y=uniform(loc=0.0, scale=1000.0),
|
||||
n=randint(low=100, high=101),
|
||||
gamma=uniform(loc=0.95, scale=0.1),
|
||||
fix_cities=True,
|
||||
).generate(100)
|
||||
assert len(instances) == 100
|
||||
assert instances[0].n_cities == 100
|
||||
assert norm(instances[0].distances - instances[0].distances.T) < 1e-6
|
||||
d = [instance.distances[0, 1] for instance in instances]
|
||||
assert np.std(d) > 0
|
||||
|
||||
|
||||
def test_instance():
|
||||
n_cities = 4
|
||||
distances = np.array(
|
||||
[
|
||||
[0.0, 1.0, 2.0, 1.0],
|
||||
[1.0, 0.0, 1.0, 2.0],
|
||||
[2.0, 1.0, 0.0, 1.0],
|
||||
[1.0, 2.0, 1.0, 0.0],
|
||||
]
|
||||
)
|
||||
instance = TravelingSalesmanInstance(n_cities, distances)
|
||||
solver = LearningSolver()
|
||||
stats = solver.solve(instance)
|
||||
x = instance.training_data[0]["Solution"]["x"]
|
||||
assert x[0, 1] == 1.0
|
||||
assert x[0, 2] == 0.0
|
||||
assert x[0, 3] == 1.0
|
||||
assert x[1, 2] == 1.0
|
||||
assert x[1, 3] == 0.0
|
||||
assert x[2, 3] == 1.0
|
||||
assert stats["Lower bound"] == 4.0
|
||||
assert stats["Upper bound"] == 4.0
|
||||
|
||||
|
||||
def test_subtour():
|
||||
n_cities = 6
|
||||
cities = np.array(
|
||||
[
|
||||
[0.0, 0.0],
|
||||
[1.0, 0.0],
|
||||
[2.0, 0.0],
|
||||
[3.0, 0.0],
|
||||
[0.0, 1.0],
|
||||
[3.0, 1.0],
|
||||
]
|
||||
)
|
||||
distances = squareform(pdist(cities))
|
||||
instance = TravelingSalesmanInstance(n_cities, distances)
|
||||
solver = LearningSolver()
|
||||
solver.solve(instance)
|
||||
assert hasattr(instance, "found_violated_lazy_constraints")
|
||||
assert hasattr(instance, "found_violated_user_cuts")
|
||||
x = instance.training_data[0]["Solution"]["x"]
|
||||
assert x[0, 1] == 1.0
|
||||
assert x[0, 4] == 1.0
|
||||
assert x[1, 2] == 1.0
|
||||
assert x[2, 3] == 1.0
|
||||
assert x[3, 5] == 1.0
|
||||
assert x[4, 5] == 1.0
|
||||
solver.fit([instance])
|
||||
solver.solve(instance)</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-functions">Functions</h2>
|
||||
<dl>
|
||||
<dt id="miplearn.problems.tests.test_tsp.test_generator"><code class="name flex">
|
||||
<span>def <span class="ident">test_generator</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_generator():
|
||||
instances = TravelingSalesmanGenerator(
|
||||
x=uniform(loc=0.0, scale=1000.0),
|
||||
y=uniform(loc=0.0, scale=1000.0),
|
||||
n=randint(low=100, high=101),
|
||||
gamma=uniform(loc=0.95, scale=0.1),
|
||||
fix_cities=True,
|
||||
).generate(100)
|
||||
assert len(instances) == 100
|
||||
assert instances[0].n_cities == 100
|
||||
assert norm(instances[0].distances - instances[0].distances.T) < 1e-6
|
||||
d = [instance.distances[0, 1] for instance in instances]
|
||||
assert np.std(d) > 0</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.problems.tests.test_tsp.test_instance"><code class="name flex">
|
||||
<span>def <span class="ident">test_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_instance():
|
||||
n_cities = 4
|
||||
distances = np.array(
|
||||
[
|
||||
[0.0, 1.0, 2.0, 1.0],
|
||||
[1.0, 0.0, 1.0, 2.0],
|
||||
[2.0, 1.0, 0.0, 1.0],
|
||||
[1.0, 2.0, 1.0, 0.0],
|
||||
]
|
||||
)
|
||||
instance = TravelingSalesmanInstance(n_cities, distances)
|
||||
solver = LearningSolver()
|
||||
stats = solver.solve(instance)
|
||||
x = instance.training_data[0]["Solution"]["x"]
|
||||
assert x[0, 1] == 1.0
|
||||
assert x[0, 2] == 0.0
|
||||
assert x[0, 3] == 1.0
|
||||
assert x[1, 2] == 1.0
|
||||
assert x[1, 3] == 0.0
|
||||
assert x[2, 3] == 1.0
|
||||
assert stats["Lower bound"] == 4.0
|
||||
assert stats["Upper bound"] == 4.0</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.problems.tests.test_tsp.test_subtour"><code class="name flex">
|
||||
<span>def <span class="ident">test_subtour</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_subtour():
|
||||
n_cities = 6
|
||||
cities = np.array(
|
||||
[
|
||||
[0.0, 0.0],
|
||||
[1.0, 0.0],
|
||||
[2.0, 0.0],
|
||||
[3.0, 0.0],
|
||||
[0.0, 1.0],
|
||||
[3.0, 1.0],
|
||||
]
|
||||
)
|
||||
distances = squareform(pdist(cities))
|
||||
instance = TravelingSalesmanInstance(n_cities, distances)
|
||||
solver = LearningSolver()
|
||||
solver.solve(instance)
|
||||
assert hasattr(instance, "found_violated_lazy_constraints")
|
||||
assert hasattr(instance, "found_violated_user_cuts")
|
||||
x = instance.training_data[0]["Solution"]["x"]
|
||||
assert x[0, 1] == 1.0
|
||||
assert x[0, 4] == 1.0
|
||||
assert x[1, 2] == 1.0
|
||||
assert x[2, 3] == 1.0
|
||||
assert x[3, 5] == 1.0
|
||||
assert x[4, 5] == 1.0
|
||||
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.problems.tests" href="index.html">miplearn.problems.tests</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-functions">Functions</a></h3>
|
||||
<ul class="">
|
||||
<li><code><a title="miplearn.problems.tests.test_tsp.test_generator" href="#miplearn.problems.tests.test_tsp.test_generator">test_generator</a></code></li>
|
||||
<li><code><a title="miplearn.problems.tests.test_tsp.test_instance" href="#miplearn.problems.tests.test_tsp.test_instance">test_instance</a></code></li>
|
||||
<li><code><a title="miplearn.problems.tests.test_tsp.test_subtour" href="#miplearn.problems.tests.test_tsp.test_subtour">test_subtour</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>
|
||||
587
0.2/api/miplearn/problems/tsp.html
Normal file
587
0.2/api/miplearn/problems/tsp.html
Normal file
@@ -0,0 +1,587 @@
|
||||
<!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.problems.tsp 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.problems.tsp</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 networkx as nx
|
||||
import numpy as np
|
||||
import pyomo.environ as pe
|
||||
from scipy.spatial.distance import pdist, squareform
|
||||
from scipy.stats import uniform, randint
|
||||
from scipy.stats.distributions import rv_frozen
|
||||
|
||||
from miplearn.instance import Instance
|
||||
|
||||
|
||||
class ChallengeA:
|
||||
def __init__(
|
||||
self,
|
||||
seed=42,
|
||||
n_training_instances=500,
|
||||
n_test_instances=50,
|
||||
):
|
||||
|
||||
np.random.seed(seed)
|
||||
self.generator = TravelingSalesmanGenerator(
|
||||
x=uniform(loc=0.0, scale=1000.0),
|
||||
y=uniform(loc=0.0, scale=1000.0),
|
||||
n=randint(low=350, high=351),
|
||||
gamma=uniform(loc=0.95, scale=0.1),
|
||||
fix_cities=True,
|
||||
round=True,
|
||||
)
|
||||
|
||||
np.random.seed(seed + 1)
|
||||
self.training_instances = self.generator.generate(n_training_instances)
|
||||
|
||||
np.random.seed(seed + 2)
|
||||
self.test_instances = self.generator.generate(n_test_instances)
|
||||
|
||||
|
||||
class TravelingSalesmanGenerator:
|
||||
"""Random generator for the Traveling Salesman Problem."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
x=uniform(loc=0.0, scale=1000.0),
|
||||
y=uniform(loc=0.0, scale=1000.0),
|
||||
n=randint(low=100, high=101),
|
||||
gamma=uniform(loc=1.0, scale=0.0),
|
||||
fix_cities=True,
|
||||
round=True,
|
||||
):
|
||||
"""Initializes the problem generator.
|
||||
|
||||
Initially, the generator creates n cities (x_1,y_1),...,(x_n,y_n) where n, x_i and y_i are
|
||||
sampled independently from the provided probability distributions `n`, `x` and `y`. For each
|
||||
(unordered) pair of cities (i,j), the distance d[i,j] between them is set to:
|
||||
|
||||
d[i,j] = gamma[i,j] \sqrt{(x_i - x_j)^2 + (y_i - y_j)^2}
|
||||
|
||||
where gamma is sampled from the provided probability distribution `gamma`.
|
||||
|
||||
If fix_cities=True, the list of cities is kept the same for all generated instances. The
|
||||
gamma values, and therefore also the distances, are still different.
|
||||
|
||||
By default, all distances d[i,j] are rounded to the nearest integer. If `round=False`
|
||||
is provided, this rounding will be disabled.
|
||||
|
||||
Arguments
|
||||
---------
|
||||
x: rv_continuous
|
||||
Probability distribution for the x-coordinate of each city.
|
||||
y: rv_continuous
|
||||
Probability distribution for the y-coordinate of each city.
|
||||
n: rv_discrete
|
||||
Probability distribution for the number of cities.
|
||||
fix_cities: bool
|
||||
If False, cities will be resampled for every generated instance. Otherwise, list of
|
||||
cities will be computed once, during the constructor.
|
||||
round: bool
|
||||
If True, distances are rounded to the nearest integer.
|
||||
"""
|
||||
assert isinstance(x, rv_frozen), "x should be a SciPy probability distribution"
|
||||
assert isinstance(y, rv_frozen), "y should be a SciPy probability distribution"
|
||||
assert isinstance(n, rv_frozen), "n should be a SciPy probability distribution"
|
||||
assert isinstance(
|
||||
gamma,
|
||||
rv_frozen,
|
||||
), "gamma should be a SciPy probability distribution"
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.n = n
|
||||
self.gamma = gamma
|
||||
self.round = round
|
||||
|
||||
if fix_cities:
|
||||
self.fixed_n, self.fixed_cities = self._generate_cities()
|
||||
else:
|
||||
self.fixed_n = None
|
||||
self.fixed_cities = None
|
||||
|
||||
def generate(self, n_samples):
|
||||
def _sample():
|
||||
if self.fixed_cities is not None:
|
||||
n, cities = self.fixed_n, self.fixed_cities
|
||||
else:
|
||||
n, cities = self._generate_cities()
|
||||
distances = squareform(pdist(cities)) * self.gamma.rvs(size=(n, n))
|
||||
distances = np.tril(distances) + np.triu(distances.T, 1)
|
||||
if self.round:
|
||||
distances = distances.round()
|
||||
return TravelingSalesmanInstance(n, distances)
|
||||
|
||||
return [_sample() for _ in range(n_samples)]
|
||||
|
||||
def _generate_cities(self):
|
||||
n = self.n.rvs()
|
||||
cities = np.array([(self.x.rvs(), self.y.rvs()) for _ in range(n)])
|
||||
return n, cities
|
||||
|
||||
|
||||
class TravelingSalesmanInstance(Instance):
|
||||
"""An instance ot the Traveling Salesman Problem.
|
||||
|
||||
Given a list of cities and the distance between each pair of cities, the problem asks for the
|
||||
shortest route starting at the first city, visiting each other city exactly once, then
|
||||
returning to the first city. This problem is a generalization of the Hamiltonian path problem,
|
||||
one of Karp's 21 NP-complete problems.
|
||||
"""
|
||||
|
||||
def __init__(self, n_cities, distances):
|
||||
assert isinstance(distances, np.ndarray)
|
||||
assert distances.shape == (n_cities, n_cities)
|
||||
self.n_cities = n_cities
|
||||
self.distances = distances
|
||||
|
||||
def to_model(self):
|
||||
model = pe.ConcreteModel()
|
||||
model.edges = edges = [
|
||||
(i, j) for i in range(self.n_cities) for j in range(i + 1, self.n_cities)
|
||||
]
|
||||
model.x = pe.Var(edges, domain=pe.Binary)
|
||||
model.obj = pe.Objective(
|
||||
expr=sum(model.x[i, j] * self.distances[i, j] for (i, j) in edges),
|
||||
sense=pe.minimize,
|
||||
)
|
||||
model.eq_degree = pe.ConstraintList()
|
||||
model.eq_subtour = pe.ConstraintList()
|
||||
for i in range(self.n_cities):
|
||||
model.eq_degree.add(
|
||||
sum(
|
||||
model.x[min(i, j), max(i, j)]
|
||||
for j in range(self.n_cities)
|
||||
if i != j
|
||||
)
|
||||
== 2
|
||||
)
|
||||
return model
|
||||
|
||||
def get_instance_features(self):
|
||||
return np.array([1])
|
||||
|
||||
def get_variable_features(self, var_name, index):
|
||||
return np.array([1])
|
||||
|
||||
def get_variable_category(self, var_name, index):
|
||||
return index
|
||||
|
||||
def find_violated_lazy_constraints(self, model):
|
||||
selected_edges = [e for e in model.edges if model.x[e].value > 0.5]
|
||||
graph = nx.Graph()
|
||||
graph.add_edges_from(selected_edges)
|
||||
components = [frozenset(c) for c in list(nx.connected_components(graph))]
|
||||
violations = []
|
||||
for c in components:
|
||||
if len(c) < self.n_cities:
|
||||
violations += [c]
|
||||
return violations
|
||||
|
||||
def build_lazy_constraint(self, model, component):
|
||||
cut_edges = [
|
||||
e
|
||||
for e in model.edges
|
||||
if (e[0] in component and e[1] not in component)
|
||||
or (e[0] not in component and e[1] in component)
|
||||
]
|
||||
return model.eq_subtour.add(sum(model.x[e] for e in cut_edges) >= 2)
|
||||
|
||||
def find_violated_user_cuts(self, model):
|
||||
return self.find_violated_lazy_constraints(model)
|
||||
|
||||
def build_user_cut(self, model, violation):
|
||||
return self.build_lazy_constraint(model, violation)</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-classes">Classes</h2>
|
||||
<dl>
|
||||
<dt id="miplearn.problems.tsp.ChallengeA"><code class="flex name class">
|
||||
<span>class <span class="ident">ChallengeA</span></span>
|
||||
<span>(</span><span>seed=42, n_training_instances=500, n_test_instances=50)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">class ChallengeA:
|
||||
def __init__(
|
||||
self,
|
||||
seed=42,
|
||||
n_training_instances=500,
|
||||
n_test_instances=50,
|
||||
):
|
||||
|
||||
np.random.seed(seed)
|
||||
self.generator = TravelingSalesmanGenerator(
|
||||
x=uniform(loc=0.0, scale=1000.0),
|
||||
y=uniform(loc=0.0, scale=1000.0),
|
||||
n=randint(low=350, high=351),
|
||||
gamma=uniform(loc=0.95, scale=0.1),
|
||||
fix_cities=True,
|
||||
round=True,
|
||||
)
|
||||
|
||||
np.random.seed(seed + 1)
|
||||
self.training_instances = self.generator.generate(n_training_instances)
|
||||
|
||||
np.random.seed(seed + 2)
|
||||
self.test_instances = self.generator.generate(n_test_instances)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.problems.tsp.TravelingSalesmanGenerator"><code class="flex name class">
|
||||
<span>class <span class="ident">TravelingSalesmanGenerator</span></span>
|
||||
<span>(</span><span>x=<scipy.stats._distn_infrastructure.rv_frozen object>, y=<scipy.stats._distn_infrastructure.rv_frozen object>, n=<scipy.stats._distn_infrastructure.rv_frozen object>, gamma=<scipy.stats._distn_infrastructure.rv_frozen object>, fix_cities=True, round=True)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"><p>Random generator for the Traveling Salesman Problem.</p>
|
||||
<p>Initializes the problem generator.</p>
|
||||
<p>Initially, the generator creates n cities (x_1,y_1),…,(x_n,y_n) where n, x_i and y_i are
|
||||
sampled independently from the provided probability distributions <code>n</code>, <code>x</code> and <code>y</code>. For each
|
||||
(unordered) pair of cities (i,j), the distance d[i,j] between them is set to:</p>
|
||||
<pre><code>d[i,j] = gamma[i,j] \sqrt{(x_i - x_j)^2 + (y_i - y_j)^2}
|
||||
</code></pre>
|
||||
<p>where gamma is sampled from the provided probability distribution <code>gamma</code>.</p>
|
||||
<p>If fix_cities=True, the list of cities is kept the same for all generated instances. The
|
||||
gamma values, and therefore also the distances, are still different.</p>
|
||||
<p>By default, all distances d[i,j] are rounded to the nearest integer.
|
||||
If <code>round=False</code>
|
||||
is provided, this rounding will be disabled.</p>
|
||||
<h2 id="arguments">Arguments</h2>
|
||||
<dl>
|
||||
<dt><strong><code>x</code></strong> : <code>rv_continuous</code></dt>
|
||||
<dd>Probability distribution for the x-coordinate of each city.</dd>
|
||||
<dt><strong><code>y</code></strong> : <code>rv_continuous</code></dt>
|
||||
<dd>Probability distribution for the y-coordinate of each city.</dd>
|
||||
<dt><strong><code>n</code></strong> : <code>rv_discrete</code></dt>
|
||||
<dd>Probability distribution for the number of cities.</dd>
|
||||
<dt><strong><code>fix_cities</code></strong> : <code>bool</code></dt>
|
||||
<dd>If False, cities will be resampled for every generated instance. Otherwise, list of
|
||||
cities will be computed once, during the constructor.</dd>
|
||||
<dt><strong><code>round</code></strong> : <code>bool</code></dt>
|
||||
<dd>If True, distances are rounded to the nearest integer.</dd>
|
||||
</dl></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">class TravelingSalesmanGenerator:
|
||||
"""Random generator for the Traveling Salesman Problem."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
x=uniform(loc=0.0, scale=1000.0),
|
||||
y=uniform(loc=0.0, scale=1000.0),
|
||||
n=randint(low=100, high=101),
|
||||
gamma=uniform(loc=1.0, scale=0.0),
|
||||
fix_cities=True,
|
||||
round=True,
|
||||
):
|
||||
"""Initializes the problem generator.
|
||||
|
||||
Initially, the generator creates n cities (x_1,y_1),...,(x_n,y_n) where n, x_i and y_i are
|
||||
sampled independently from the provided probability distributions `n`, `x` and `y`. For each
|
||||
(unordered) pair of cities (i,j), the distance d[i,j] between them is set to:
|
||||
|
||||
d[i,j] = gamma[i,j] \sqrt{(x_i - x_j)^2 + (y_i - y_j)^2}
|
||||
|
||||
where gamma is sampled from the provided probability distribution `gamma`.
|
||||
|
||||
If fix_cities=True, the list of cities is kept the same for all generated instances. The
|
||||
gamma values, and therefore also the distances, are still different.
|
||||
|
||||
By default, all distances d[i,j] are rounded to the nearest integer. If `round=False`
|
||||
is provided, this rounding will be disabled.
|
||||
|
||||
Arguments
|
||||
---------
|
||||
x: rv_continuous
|
||||
Probability distribution for the x-coordinate of each city.
|
||||
y: rv_continuous
|
||||
Probability distribution for the y-coordinate of each city.
|
||||
n: rv_discrete
|
||||
Probability distribution for the number of cities.
|
||||
fix_cities: bool
|
||||
If False, cities will be resampled for every generated instance. Otherwise, list of
|
||||
cities will be computed once, during the constructor.
|
||||
round: bool
|
||||
If True, distances are rounded to the nearest integer.
|
||||
"""
|
||||
assert isinstance(x, rv_frozen), "x should be a SciPy probability distribution"
|
||||
assert isinstance(y, rv_frozen), "y should be a SciPy probability distribution"
|
||||
assert isinstance(n, rv_frozen), "n should be a SciPy probability distribution"
|
||||
assert isinstance(
|
||||
gamma,
|
||||
rv_frozen,
|
||||
), "gamma should be a SciPy probability distribution"
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.n = n
|
||||
self.gamma = gamma
|
||||
self.round = round
|
||||
|
||||
if fix_cities:
|
||||
self.fixed_n, self.fixed_cities = self._generate_cities()
|
||||
else:
|
||||
self.fixed_n = None
|
||||
self.fixed_cities = None
|
||||
|
||||
def generate(self, n_samples):
|
||||
def _sample():
|
||||
if self.fixed_cities is not None:
|
||||
n, cities = self.fixed_n, self.fixed_cities
|
||||
else:
|
||||
n, cities = self._generate_cities()
|
||||
distances = squareform(pdist(cities)) * self.gamma.rvs(size=(n, n))
|
||||
distances = np.tril(distances) + np.triu(distances.T, 1)
|
||||
if self.round:
|
||||
distances = distances.round()
|
||||
return TravelingSalesmanInstance(n, distances)
|
||||
|
||||
return [_sample() for _ in range(n_samples)]
|
||||
|
||||
def _generate_cities(self):
|
||||
n = self.n.rvs()
|
||||
cities = np.array([(self.x.rvs(), self.y.rvs()) for _ in range(n)])
|
||||
return n, cities</code></pre>
|
||||
</details>
|
||||
<h3>Methods</h3>
|
||||
<dl>
|
||||
<dt id="miplearn.problems.tsp.TravelingSalesmanGenerator.generate"><code class="name flex">
|
||||
<span>def <span class="ident">generate</span></span>(<span>self, n_samples)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def generate(self, n_samples):
|
||||
def _sample():
|
||||
if self.fixed_cities is not None:
|
||||
n, cities = self.fixed_n, self.fixed_cities
|
||||
else:
|
||||
n, cities = self._generate_cities()
|
||||
distances = squareform(pdist(cities)) * self.gamma.rvs(size=(n, n))
|
||||
distances = np.tril(distances) + np.triu(distances.T, 1)
|
||||
if self.round:
|
||||
distances = distances.round()
|
||||
return TravelingSalesmanInstance(n, distances)
|
||||
|
||||
return [_sample() for _ in range(n_samples)]</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt id="miplearn.problems.tsp.TravelingSalesmanInstance"><code class="flex name class">
|
||||
<span>class <span class="ident">TravelingSalesmanInstance</span></span>
|
||||
<span>(</span><span>n_cities, distances)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"><p>An instance ot the Traveling Salesman Problem.</p>
|
||||
<p>Given a list of cities and the distance between each pair of cities, the problem asks for the
|
||||
shortest route starting at the first city, visiting each other city exactly once, then
|
||||
returning to the first city. This problem is a generalization of the Hamiltonian path problem,
|
||||
one of Karp's 21 NP-complete problems.</p></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">class TravelingSalesmanInstance(Instance):
|
||||
"""An instance ot the Traveling Salesman Problem.
|
||||
|
||||
Given a list of cities and the distance between each pair of cities, the problem asks for the
|
||||
shortest route starting at the first city, visiting each other city exactly once, then
|
||||
returning to the first city. This problem is a generalization of the Hamiltonian path problem,
|
||||
one of Karp's 21 NP-complete problems.
|
||||
"""
|
||||
|
||||
def __init__(self, n_cities, distances):
|
||||
assert isinstance(distances, np.ndarray)
|
||||
assert distances.shape == (n_cities, n_cities)
|
||||
self.n_cities = n_cities
|
||||
self.distances = distances
|
||||
|
||||
def to_model(self):
|
||||
model = pe.ConcreteModel()
|
||||
model.edges = edges = [
|
||||
(i, j) for i in range(self.n_cities) for j in range(i + 1, self.n_cities)
|
||||
]
|
||||
model.x = pe.Var(edges, domain=pe.Binary)
|
||||
model.obj = pe.Objective(
|
||||
expr=sum(model.x[i, j] * self.distances[i, j] for (i, j) in edges),
|
||||
sense=pe.minimize,
|
||||
)
|
||||
model.eq_degree = pe.ConstraintList()
|
||||
model.eq_subtour = pe.ConstraintList()
|
||||
for i in range(self.n_cities):
|
||||
model.eq_degree.add(
|
||||
sum(
|
||||
model.x[min(i, j), max(i, j)]
|
||||
for j in range(self.n_cities)
|
||||
if i != j
|
||||
)
|
||||
== 2
|
||||
)
|
||||
return model
|
||||
|
||||
def get_instance_features(self):
|
||||
return np.array([1])
|
||||
|
||||
def get_variable_features(self, var_name, index):
|
||||
return np.array([1])
|
||||
|
||||
def get_variable_category(self, var_name, index):
|
||||
return index
|
||||
|
||||
def find_violated_lazy_constraints(self, model):
|
||||
selected_edges = [e for e in model.edges if model.x[e].value > 0.5]
|
||||
graph = nx.Graph()
|
||||
graph.add_edges_from(selected_edges)
|
||||
components = [frozenset(c) for c in list(nx.connected_components(graph))]
|
||||
violations = []
|
||||
for c in components:
|
||||
if len(c) < self.n_cities:
|
||||
violations += [c]
|
||||
return violations
|
||||
|
||||
def build_lazy_constraint(self, model, component):
|
||||
cut_edges = [
|
||||
e
|
||||
for e in model.edges
|
||||
if (e[0] in component and e[1] not in component)
|
||||
or (e[0] not in component and e[1] in component)
|
||||
]
|
||||
return model.eq_subtour.add(sum(model.x[e] for e in cut_edges) >= 2)
|
||||
|
||||
def find_violated_user_cuts(self, model):
|
||||
return self.find_violated_lazy_constraints(model)
|
||||
|
||||
def build_user_cut(self, model, violation):
|
||||
return self.build_lazy_constraint(model, violation)</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>Methods</h3>
|
||||
<dl>
|
||||
<dt id="miplearn.problems.tsp.TravelingSalesmanInstance.build_user_cut"><code class="name flex">
|
||||
<span>def <span class="ident">build_user_cut</span></span>(<span>self, model, violation)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def build_user_cut(self, model, violation):
|
||||
return self.build_lazy_constraint(model, violation)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.problems.tsp.TravelingSalesmanInstance.find_violated_user_cuts"><code class="name flex">
|
||||
<span>def <span class="ident">find_violated_user_cuts</span></span>(<span>self, model)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def find_violated_user_cuts(self, model):
|
||||
return self.find_violated_lazy_constraints(model)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
<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.problems" href="index.html">miplearn.problems</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-classes">Classes</a></h3>
|
||||
<ul>
|
||||
<li>
|
||||
<h4><code><a title="miplearn.problems.tsp.ChallengeA" href="#miplearn.problems.tsp.ChallengeA">ChallengeA</a></code></h4>
|
||||
</li>
|
||||
<li>
|
||||
<h4><code><a title="miplearn.problems.tsp.TravelingSalesmanGenerator" href="#miplearn.problems.tsp.TravelingSalesmanGenerator">TravelingSalesmanGenerator</a></code></h4>
|
||||
<ul class="">
|
||||
<li><code><a title="miplearn.problems.tsp.TravelingSalesmanGenerator.generate" href="#miplearn.problems.tsp.TravelingSalesmanGenerator.generate">generate</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<h4><code><a title="miplearn.problems.tsp.TravelingSalesmanInstance" href="#miplearn.problems.tsp.TravelingSalesmanInstance">TravelingSalesmanInstance</a></code></h4>
|
||||
<ul class="">
|
||||
<li><code><a title="miplearn.problems.tsp.TravelingSalesmanInstance.build_user_cut" href="#miplearn.problems.tsp.TravelingSalesmanInstance.build_user_cut">build_user_cut</a></code></li>
|
||||
<li><code><a title="miplearn.problems.tsp.TravelingSalesmanInstance.find_violated_user_cuts" href="#miplearn.problems.tsp.TravelingSalesmanInstance.find_violated_user_cuts">find_violated_user_cuts</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</main>
|
||||
<footer id="footer">
|
||||
<p>Generated by <a href="https://pdoc3.github.io/pdoc"><cite>pdoc</cite> 0.7.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>
|
||||
928
0.2/api/miplearn/solvers/gurobi.html
Normal file
928
0.2/api/miplearn/solvers/gurobi.html
Normal 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):
|
||||
"""
|
||||
An InternalSolver backed by Gurobi's Python API (without Pyomo).
|
||||
|
||||
Parameters
|
||||
----------
|
||||
params: Optional[SolverParams]
|
||||
Parameters to pass to Gurobi. For example, `params={"MIPGap": 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.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
params: Optional[SolverParams] = None,
|
||||
lazy_cb_frequency: int = 1,
|
||||
) -> None:
|
||||
import gurobipy
|
||||
|
||||
if params is None:
|
||||
params = {}
|
||||
params["InfUnbdInfo"] = True
|
||||
|
||||
self.gp = gurobipy
|
||||
self.instance: Optional[Instance] = None
|
||||
self.model: Optional["gurobipy.Model"] = None
|
||||
self.params: SolverParams = params
|
||||
self._all_vars: Dict = {}
|
||||
self._bin_vars: Optional[Dict[str, Dict[VarIndex, "gurobipy.Var"]]] = 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,
|
||||
) -> 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) -> None:
|
||||
if self.cb_where is not None:
|
||||
raise Exception("method cannot be called from a callback")
|
||||
|
||||
def _update_vars(self) -> 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"([^[]*)\[(.*)]", var.varName)
|
||||
if m is None:
|
||||
name = var.varName
|
||||
idx = [0]
|
||||
else:
|
||||
name = m.group(1)
|
||||
parts = m.group(2).split(",")
|
||||
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 != "C":
|
||||
if name not in self._bin_vars:
|
||||
self._bin_vars[name] = {}
|
||||
self._bin_vars[name][idx] = var
|
||||
|
||||
def _apply_params(self, streams: List[Any]) -> None:
|
||||
assert self.model is not None
|
||||
with _RedirectOutput(streams):
|
||||
for (name, value) in self.params.items():
|
||||
self.model.setParam(name, value)
|
||||
if "seed" not in [k.lower() for k in self.params.keys()]:
|
||||
self.model.setParam("Seed", randint(0, 1_000_000))
|
||||
|
||||
def solve_lp(
|
||||
self,
|
||||
tee: bool = False,
|
||||
) -> 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 {
|
||||
"Optimal value": opt_value,
|
||||
"Log": log,
|
||||
}
|
||||
|
||||
def solve(
|
||||
self,
|
||||
tee: bool = False,
|
||||
iteration_cb: IterationCallback = None,
|
||||
lazy_cb: LazyCallback = None,
|
||||
) -> 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("callback error")
|
||||
finally:
|
||||
self.cb_where = None
|
||||
|
||||
if lazy_cb:
|
||||
self.params["LazyConstraints"] = 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 = "min" if self.model.modelSense == 1 else "max"
|
||||
if self.model.solCount > 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 = {
|
||||
"Lower bound": lb,
|
||||
"Upper bound": ub,
|
||||
"Wallclock time": total_wallclock_time,
|
||||
"Nodes": total_nodes,
|
||||
"Sense": sense,
|
||||
"Log": log,
|
||||
"Warm start value": ws_value,
|
||||
"LP value": None,
|
||||
}
|
||||
return stats
|
||||
|
||||
def get_solution(self) -> 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) -> 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(
|
||||
"Setting start values for %d variables (out of %d)"
|
||||
% (count_fixed, count_total)
|
||||
)
|
||||
|
||||
def get_sense(self) -> str:
|
||||
assert self.model is not None
|
||||
if self.model.modelSense == 1:
|
||||
return "min"
|
||||
else:
|
||||
return "max"
|
||||
|
||||
def get_value(
|
||||
self,
|
||||
var_name: str,
|
||||
index: VarIndex,
|
||||
) -> Optional[float]:
|
||||
var = self._all_vars[var_name][index]
|
||||
return self._get_value(var)
|
||||
|
||||
def is_infeasible(self) -> 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) -> 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) -> 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(
|
||||
"get_value cannot be called from cb_where=%s" % self.cb_where
|
||||
)
|
||||
|
||||
def get_empty_solution(self) -> 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 = "",
|
||||
) -> 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) -> 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) -> 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 == "<":
|
||||
return lhs_value <= rhs + tol
|
||||
elif sense == ">":
|
||||
return lhs_value >= rhs - tol
|
||||
elif sense == "=":
|
||||
return abs(rhs - lhs_value) < abs(tol)
|
||||
else:
|
||||
raise Exception("Unknown sense: %s" % sense)
|
||||
|
||||
def get_inequality_slacks(self) -> Dict[str, float]:
|
||||
assert self.model is not None
|
||||
ineqs = [c for c in self.model.getConstrs() if c.sense != "="]
|
||||
return {c.ConstrName: c.Slack for c in ineqs}
|
||||
|
||||
def set_constraint_sense(self, cid: str, sense: str) -> None:
|
||||
assert self.model is not None
|
||||
c = self.model.getConstrByName(cid)
|
||||
c.Sense = sense
|
||||
|
||||
def get_constraint_sense(self, cid: str) -> str:
|
||||
assert self.model is not None
|
||||
c = self.model.getConstrByName(cid)
|
||||
return c.Sense
|
||||
|
||||
def relax(self) -> None:
|
||||
assert self.model is not None
|
||||
self.model = self.model.relax()
|
||||
self._update_vars()
|
||||
|
||||
def _extract_warm_start_value(self, log: str) -> Optional[float]:
|
||||
ws = self.__extract(log, "MIP start with objective ([0-9.e+-]*)")
|
||||
if ws is None:
|
||||
return None
|
||||
return float(ws)
|
||||
|
||||
@staticmethod
|
||||
def __extract(
|
||||
log: str,
|
||||
regexp: str,
|
||||
default: Optional[str] = None,
|
||||
) -> 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 {
|
||||
"params": self.params,
|
||||
"lazy_cb_where": self.lazy_cb_where,
|
||||
}
|
||||
|
||||
def __setstate__(self, state):
|
||||
|
||||
self.params = state["params"]
|
||||
self.lazy_cb_where = state["lazy_cb_where"]
|
||||
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> : <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> : <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):
|
||||
"""
|
||||
An InternalSolver backed by Gurobi's Python API (without Pyomo).
|
||||
|
||||
Parameters
|
||||
----------
|
||||
params: Optional[SolverParams]
|
||||
Parameters to pass to Gurobi. For example, `params={"MIPGap": 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.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
params: Optional[SolverParams] = None,
|
||||
lazy_cb_frequency: int = 1,
|
||||
) -> None:
|
||||
import gurobipy
|
||||
|
||||
if params is None:
|
||||
params = {}
|
||||
params["InfUnbdInfo"] = True
|
||||
|
||||
self.gp = gurobipy
|
||||
self.instance: Optional[Instance] = None
|
||||
self.model: Optional["gurobipy.Model"] = None
|
||||
self.params: SolverParams = params
|
||||
self._all_vars: Dict = {}
|
||||
self._bin_vars: Optional[Dict[str, Dict[VarIndex, "gurobipy.Var"]]] = 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,
|
||||
) -> 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) -> None:
|
||||
if self.cb_where is not None:
|
||||
raise Exception("method cannot be called from a callback")
|
||||
|
||||
def _update_vars(self) -> 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"([^[]*)\[(.*)]", var.varName)
|
||||
if m is None:
|
||||
name = var.varName
|
||||
idx = [0]
|
||||
else:
|
||||
name = m.group(1)
|
||||
parts = m.group(2).split(",")
|
||||
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 != "C":
|
||||
if name not in self._bin_vars:
|
||||
self._bin_vars[name] = {}
|
||||
self._bin_vars[name][idx] = var
|
||||
|
||||
def _apply_params(self, streams: List[Any]) -> None:
|
||||
assert self.model is not None
|
||||
with _RedirectOutput(streams):
|
||||
for (name, value) in self.params.items():
|
||||
self.model.setParam(name, value)
|
||||
if "seed" not in [k.lower() for k in self.params.keys()]:
|
||||
self.model.setParam("Seed", randint(0, 1_000_000))
|
||||
|
||||
def solve_lp(
|
||||
self,
|
||||
tee: bool = False,
|
||||
) -> 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 {
|
||||
"Optimal value": opt_value,
|
||||
"Log": log,
|
||||
}
|
||||
|
||||
def solve(
|
||||
self,
|
||||
tee: bool = False,
|
||||
iteration_cb: IterationCallback = None,
|
||||
lazy_cb: LazyCallback = None,
|
||||
) -> 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("callback error")
|
||||
finally:
|
||||
self.cb_where = None
|
||||
|
||||
if lazy_cb:
|
||||
self.params["LazyConstraints"] = 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 = "min" if self.model.modelSense == 1 else "max"
|
||||
if self.model.solCount > 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 = {
|
||||
"Lower bound": lb,
|
||||
"Upper bound": ub,
|
||||
"Wallclock time": total_wallclock_time,
|
||||
"Nodes": total_nodes,
|
||||
"Sense": sense,
|
||||
"Log": log,
|
||||
"Warm start value": ws_value,
|
||||
"LP value": None,
|
||||
}
|
||||
return stats
|
||||
|
||||
def get_solution(self) -> 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) -> 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(
|
||||
"Setting start values for %d variables (out of %d)"
|
||||
% (count_fixed, count_total)
|
||||
)
|
||||
|
||||
def get_sense(self) -> str:
|
||||
assert self.model is not None
|
||||
if self.model.modelSense == 1:
|
||||
return "min"
|
||||
else:
|
||||
return "max"
|
||||
|
||||
def get_value(
|
||||
self,
|
||||
var_name: str,
|
||||
index: VarIndex,
|
||||
) -> Optional[float]:
|
||||
var = self._all_vars[var_name][index]
|
||||
return self._get_value(var)
|
||||
|
||||
def is_infeasible(self) -> 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) -> 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) -> 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(
|
||||
"get_value cannot be called from cb_where=%s" % self.cb_where
|
||||
)
|
||||
|
||||
def get_empty_solution(self) -> 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 = "",
|
||||
) -> 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) -> 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) -> 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 == "<":
|
||||
return lhs_value <= rhs + tol
|
||||
elif sense == ">":
|
||||
return lhs_value >= rhs - tol
|
||||
elif sense == "=":
|
||||
return abs(rhs - lhs_value) < abs(tol)
|
||||
else:
|
||||
raise Exception("Unknown sense: %s" % sense)
|
||||
|
||||
def get_inequality_slacks(self) -> Dict[str, float]:
|
||||
assert self.model is not None
|
||||
ineqs = [c for c in self.model.getConstrs() if c.sense != "="]
|
||||
return {c.ConstrName: c.Slack for c in ineqs}
|
||||
|
||||
def set_constraint_sense(self, cid: str, sense: str) -> None:
|
||||
assert self.model is not None
|
||||
c = self.model.getConstrByName(cid)
|
||||
c.Sense = sense
|
||||
|
||||
def get_constraint_sense(self, cid: str) -> str:
|
||||
assert self.model is not None
|
||||
c = self.model.getConstrByName(cid)
|
||||
return c.Sense
|
||||
|
||||
def relax(self) -> None:
|
||||
assert self.model is not None
|
||||
self.model = self.model.relax()
|
||||
self._update_vars()
|
||||
|
||||
def _extract_warm_start_value(self, log: str) -> Optional[float]:
|
||||
ws = self.__extract(log, "MIP start with objective ([0-9.e+-]*)")
|
||||
if ws is None:
|
||||
return None
|
||||
return float(ws)
|
||||
|
||||
@staticmethod
|
||||
def __extract(
|
||||
log: str,
|
||||
regexp: str,
|
||||
default: Optional[str] = None,
|
||||
) -> 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 {
|
||||
"params": self.params,
|
||||
"lazy_cb_where": self.lazy_cb_where,
|
||||
}
|
||||
|
||||
def __setstate__(self, state):
|
||||
|
||||
self.params = state["params"]
|
||||
self.lazy_cb_where = state["lazy_cb_where"]
|
||||
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>
|
||||
123
0.2/api/miplearn/solvers/index.html
Normal file
123
0.2/api/miplearn/solvers/index.html
Normal 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) -> None:
|
||||
for stream in self.streams:
|
||||
stream.write(data)
|
||||
|
||||
def flush(self) -> 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>
|
||||
1142
0.2/api/miplearn/solvers/internal.html
Normal file
1142
0.2/api/miplearn/solvers/internal.html
Normal file
File diff suppressed because it is too large
Load Diff
1058
0.2/api/miplearn/solvers/learning.html
Normal file
1058
0.2/api/miplearn/solvers/learning.html
Normal file
File diff suppressed because it is too large
Load Diff
730
0.2/api/miplearn/solvers/pyomo/base.html
Normal file
730
0.2/api/miplearn/solvers/pyomo/base.html
Normal 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):
|
||||
"""
|
||||
Base class for all Pyomo solvers.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
solver_factory: SolverFactory,
|
||||
params: SolverParams,
|
||||
) -> 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 = "min"
|
||||
self._varname_to_var: Dict[str, pe.Var] = {}
|
||||
self._cname_to_constr: Dict[str, pe.Constraint] = {}
|
||||
self._termination_condition: str = ""
|
||||
|
||||
for (key, value) in params.items():
|
||||
self._pyomo_solver.options[key] = value
|
||||
|
||||
def solve_lp(
|
||||
self,
|
||||
tee: bool = False,
|
||||
) -> 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["Problem"][0]["Lower bound"]
|
||||
return {
|
||||
"Optimal value": opt_value,
|
||||
"Log": streams[0].getvalue(),
|
||||
}
|
||||
|
||||
def _restore_integrality(self) -> 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,
|
||||
) -> MIPSolveStats:
|
||||
if lazy_cb is not None:
|
||||
raise Exception("lazy callback not supported")
|
||||
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("Solving MIP...")
|
||||
with _RedirectOutput(streams):
|
||||
results = self._pyomo_solver.solve(
|
||||
tee=True,
|
||||
warmstart=self._is_warm_start_available,
|
||||
)
|
||||
total_wallclock_time += results["Solver"][0]["Wallclock time"]
|
||||
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["Solver"][0]["Termination condition"]
|
||||
lb, ub = None, None
|
||||
if not self.is_infeasible():
|
||||
lb = results["Problem"][0]["Lower bound"]
|
||||
ub = results["Problem"][0]["Upper bound"]
|
||||
stats: MIPSolveStats = {
|
||||
"Lower bound": lb,
|
||||
"Upper bound": ub,
|
||||
"Wallclock time": total_wallclock_time,
|
||||
"Sense": self._obj_sense,
|
||||
"Log": log,
|
||||
"Nodes": node_count,
|
||||
"Warm start value": ws_value,
|
||||
"LP value": None,
|
||||
}
|
||||
return stats
|
||||
|
||||
def get_solution(self) -> 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) -> 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 > 0:
|
||||
self._is_warm_start_available = True
|
||||
logger.info(
|
||||
"Setting start values for %d variables (out of %d)"
|
||||
% (count_fixed, count_total)
|
||||
)
|
||||
|
||||
def set_instance(
|
||||
self,
|
||||
instance: Instance,
|
||||
model: Any = None,
|
||||
) -> 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) -> 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) -> 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) -> None:
|
||||
for var in self._all_vars:
|
||||
if not var.fixed:
|
||||
var.value = None
|
||||
self._is_warm_start_available = False
|
||||
|
||||
def _update_obj(self) -> None:
|
||||
self._obj_sense = "max"
|
||||
if self._pyomo_solver._objective.sense == pyomo.core.kernel.objective.minimize:
|
||||
self._obj_sense = "min"
|
||||
|
||||
def _update_vars(self) -> 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) -> 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(
|
||||
"Fixing values for %d variables (out of %d)"
|
||||
% (
|
||||
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,
|
||||
) -> 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) -> 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) -> 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) -> Optional[str]:
|
||||
return None
|
||||
|
||||
def _get_node_count_regexp(self) -> Optional[str]:
|
||||
return None
|
||||
|
||||
def relax(self) -> 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) -> 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) -> 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), "range constraints not supported"
|
||||
if has_lb:
|
||||
return ">"
|
||||
elif has_ub:
|
||||
return "<"
|
||||
else:
|
||||
return "="
|
||||
|
||||
def set_constraint_sense(self, cid: str, sense: str) -> None:
|
||||
raise Exception("Not implemented")
|
||||
|
||||
def extract_constraint(self, cid: str) -> Constraint:
|
||||
raise Exception("Not implemented")
|
||||
|
||||
def is_constraint_satisfied(self, cobj: Constraint) -> bool:
|
||||
raise Exception("Not implemented")
|
||||
|
||||
def is_infeasible(self) -> bool:
|
||||
return self._termination_condition == TerminationCondition.infeasible
|
||||
|
||||
def get_dual(self, cid):
|
||||
raise Exception("Not implemented")
|
||||
|
||||
def get_sense(self) -> 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):
|
||||
"""
|
||||
Base class for all Pyomo solvers.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
solver_factory: SolverFactory,
|
||||
params: SolverParams,
|
||||
) -> 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 = "min"
|
||||
self._varname_to_var: Dict[str, pe.Var] = {}
|
||||
self._cname_to_constr: Dict[str, pe.Constraint] = {}
|
||||
self._termination_condition: str = ""
|
||||
|
||||
for (key, value) in params.items():
|
||||
self._pyomo_solver.options[key] = value
|
||||
|
||||
def solve_lp(
|
||||
self,
|
||||
tee: bool = False,
|
||||
) -> 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["Problem"][0]["Lower bound"]
|
||||
return {
|
||||
"Optimal value": opt_value,
|
||||
"Log": streams[0].getvalue(),
|
||||
}
|
||||
|
||||
def _restore_integrality(self) -> 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,
|
||||
) -> MIPSolveStats:
|
||||
if lazy_cb is not None:
|
||||
raise Exception("lazy callback not supported")
|
||||
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("Solving MIP...")
|
||||
with _RedirectOutput(streams):
|
||||
results = self._pyomo_solver.solve(
|
||||
tee=True,
|
||||
warmstart=self._is_warm_start_available,
|
||||
)
|
||||
total_wallclock_time += results["Solver"][0]["Wallclock time"]
|
||||
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["Solver"][0]["Termination condition"]
|
||||
lb, ub = None, None
|
||||
if not self.is_infeasible():
|
||||
lb = results["Problem"][0]["Lower bound"]
|
||||
ub = results["Problem"][0]["Upper bound"]
|
||||
stats: MIPSolveStats = {
|
||||
"Lower bound": lb,
|
||||
"Upper bound": ub,
|
||||
"Wallclock time": total_wallclock_time,
|
||||
"Sense": self._obj_sense,
|
||||
"Log": log,
|
||||
"Nodes": node_count,
|
||||
"Warm start value": ws_value,
|
||||
"LP value": None,
|
||||
}
|
||||
return stats
|
||||
|
||||
def get_solution(self) -> 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) -> 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 > 0:
|
||||
self._is_warm_start_available = True
|
||||
logger.info(
|
||||
"Setting start values for %d variables (out of %d)"
|
||||
% (count_fixed, count_total)
|
||||
)
|
||||
|
||||
def set_instance(
|
||||
self,
|
||||
instance: Instance,
|
||||
model: Any = None,
|
||||
) -> 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) -> 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) -> 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) -> None:
|
||||
for var in self._all_vars:
|
||||
if not var.fixed:
|
||||
var.value = None
|
||||
self._is_warm_start_available = False
|
||||
|
||||
def _update_obj(self) -> None:
|
||||
self._obj_sense = "max"
|
||||
if self._pyomo_solver._objective.sense == pyomo.core.kernel.objective.minimize:
|
||||
self._obj_sense = "min"
|
||||
|
||||
def _update_vars(self) -> 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) -> 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(
|
||||
"Fixing values for %d variables (out of %d)"
|
||||
% (
|
||||
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,
|
||||
) -> 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) -> 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) -> 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) -> Optional[str]:
|
||||
return None
|
||||
|
||||
def _get_node_count_regexp(self) -> Optional[str]:
|
||||
return None
|
||||
|
||||
def relax(self) -> 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) -> 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) -> 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), "range constraints not supported"
|
||||
if has_lb:
|
||||
return ">"
|
||||
elif has_ub:
|
||||
return "<"
|
||||
else:
|
||||
return "="
|
||||
|
||||
def set_constraint_sense(self, cid: str, sense: str) -> None:
|
||||
raise Exception("Not implemented")
|
||||
|
||||
def extract_constraint(self, cid: str) -> Constraint:
|
||||
raise Exception("Not implemented")
|
||||
|
||||
def is_constraint_satisfied(self, cobj: Constraint) -> bool:
|
||||
raise Exception("Not implemented")
|
||||
|
||||
def is_infeasible(self) -> bool:
|
||||
return self._termination_condition == TerminationCondition.infeasible
|
||||
|
||||
def get_dual(self, cid):
|
||||
raise Exception("Not implemented")
|
||||
|
||||
def get_sense(self) -> 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>
|
||||
193
0.2/api/miplearn/solvers/pyomo/cplex.html
Normal file
193
0.2/api/miplearn/solvers/pyomo/cplex.html
Normal 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):
|
||||
"""
|
||||
An InternalSolver that uses CPLEX and the Pyomo modeling language.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
params: dict
|
||||
Dictionary of options to pass to the Pyomo solver. For example,
|
||||
{"mip_display": 5} to increase the log verbosity.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
params: Optional[SolverParams] = None,
|
||||
) -> None:
|
||||
if params is None:
|
||||
params = {}
|
||||
if "randomseed" not in params.keys():
|
||||
params["randomseed"] = randint(low=0, high=1000).rvs()
|
||||
if "mip_display" not in params.keys():
|
||||
params["mip_display"] = 4
|
||||
super().__init__(
|
||||
solver_factory=pe.SolverFactory("cplex_persistent"),
|
||||
params=params,
|
||||
)
|
||||
|
||||
def _get_warm_start_regexp(self):
|
||||
return "MIP start .* with objective ([0-9.e+-]*)\\."
|
||||
|
||||
def _get_node_count_regexp(self):
|
||||
return "^[ *] *([0-9]+)"</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> : <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):
|
||||
"""
|
||||
An InternalSolver that uses CPLEX and the Pyomo modeling language.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
params: dict
|
||||
Dictionary of options to pass to the Pyomo solver. For example,
|
||||
{"mip_display": 5} to increase the log verbosity.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
params: Optional[SolverParams] = None,
|
||||
) -> None:
|
||||
if params is None:
|
||||
params = {}
|
||||
if "randomseed" not in params.keys():
|
||||
params["randomseed"] = randint(low=0, high=1000).rvs()
|
||||
if "mip_display" not in params.keys():
|
||||
params["mip_display"] = 4
|
||||
super().__init__(
|
||||
solver_factory=pe.SolverFactory("cplex_persistent"),
|
||||
params=params,
|
||||
)
|
||||
|
||||
def _get_warm_start_regexp(self):
|
||||
return "MIP start .* with objective ([0-9.e+-]*)\\."
|
||||
|
||||
def _get_node_count_regexp(self):
|
||||
return "^[ *] *([0-9]+)"</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>
|
||||
221
0.2/api/miplearn/solvers/pyomo/gurobi.html
Normal file
221
0.2/api/miplearn/solvers/pyomo/gurobi.html
Normal 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):
|
||||
"""
|
||||
An InternalSolver that uses Gurobi and the Pyomo modeling language.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
params: dict
|
||||
Dictionary of options to pass to the Pyomo solver. For example,
|
||||
{"Threads": 4} to set the number of threads.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
params: SolverParams = None,
|
||||
) -> None:
|
||||
if params is None:
|
||||
params = {}
|
||||
if "seed" not in params.keys():
|
||||
params["seed"] = randint(low=0, high=1000).rvs()
|
||||
super().__init__(
|
||||
solver_factory=pe.SolverFactory("gurobi_persistent"),
|
||||
params=params,
|
||||
)
|
||||
|
||||
def _extract_node_count(self, log: str) -> int:
|
||||
return max(1, int(self._pyomo_solver._solver_model.getAttr("NodeCount")))
|
||||
|
||||
def _get_warm_start_regexp(self) -> str:
|
||||
return "MIP start with objective ([0-9.e+-]*)"
|
||||
|
||||
def _get_node_count_regexp(self) -> Optional[str]:
|
||||
return None
|
||||
|
||||
def set_branching_priorities(self, priorities: BranchPriorities) -> 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> : <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):
|
||||
"""
|
||||
An InternalSolver that uses Gurobi and the Pyomo modeling language.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
params: dict
|
||||
Dictionary of options to pass to the Pyomo solver. For example,
|
||||
{"Threads": 4} to set the number of threads.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
params: SolverParams = None,
|
||||
) -> None:
|
||||
if params is None:
|
||||
params = {}
|
||||
if "seed" not in params.keys():
|
||||
params["seed"] = randint(low=0, high=1000).rvs()
|
||||
super().__init__(
|
||||
solver_factory=pe.SolverFactory("gurobi_persistent"),
|
||||
params=params,
|
||||
)
|
||||
|
||||
def _extract_node_count(self, log: str) -> int:
|
||||
return max(1, int(self._pyomo_solver._solver_model.getAttr("NodeCount")))
|
||||
|
||||
def _get_warm_start_regexp(self) -> str:
|
||||
return "MIP start with objective ([0-9.e+-]*)"
|
||||
|
||||
def _get_node_count_regexp(self) -> Optional[str]:
|
||||
return None
|
||||
|
||||
def set_branching_priorities(self, priorities: BranchPriorities) -> 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>
|
||||
88
0.2/api/miplearn/solvers/pyomo/index.html
Normal file
88
0.2/api/miplearn/solvers/pyomo/index.html
Normal 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>
|
||||
174
0.2/api/miplearn/solvers/pyomo/xpress.html
Normal file
174
0.2/api/miplearn/solvers/pyomo/xpress.html
Normal 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):
|
||||
"""
|
||||
An InternalSolver that uses XPRESS and the Pyomo modeling language.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
params: dict
|
||||
Dictionary of options to pass to the Pyomo solver. For example,
|
||||
{"Threads": 4} to set the number of threads.
|
||||
"""
|
||||
|
||||
def __init__(self, params: SolverParams = None) -> None:
|
||||
if params is None:
|
||||
params = {}
|
||||
if "randomseed" not in params.keys():
|
||||
params["randomseed"] = randint(low=0, high=1000).rvs()
|
||||
super().__init__(
|
||||
solver_factory=pe.SolverFactory("xpress_persistent"),
|
||||
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> : <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):
|
||||
"""
|
||||
An InternalSolver that uses XPRESS and the Pyomo modeling language.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
params: dict
|
||||
Dictionary of options to pass to the Pyomo solver. For example,
|
||||
{"Threads": 4} to set the number of threads.
|
||||
"""
|
||||
|
||||
def __init__(self, params: SolverParams = None) -> None:
|
||||
if params is None:
|
||||
params = {}
|
||||
if "randomseed" not in params.keys():
|
||||
params["randomseed"] = randint(low=0, high=1000).rvs()
|
||||
super().__init__(
|
||||
solver_factory=pe.SolverFactory("xpress_persistent"),
|
||||
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>
|
||||
250
0.2/api/miplearn/solvers/tests/index.html
Normal file
250
0.2/api/miplearn/solvers/tests/index.html
Normal 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) -> 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] >= 2)
|
||||
return model
|
||||
|
||||
|
||||
class InfeasibleGurobiInstance(Instance):
|
||||
def to_model(self) -> Any:
|
||||
import gurobipy as gp
|
||||
from gurobipy import GRB
|
||||
|
||||
model = gp.Model()
|
||||
x = model.addVars(1, vtype=GRB.BINARY, name="x")
|
||||
model.addConstr(x[0] >= 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() -> 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) -> Any:
|
||||
import gurobipy as gp
|
||||
from gurobipy import GRB
|
||||
|
||||
model = gp.Model()
|
||||
x = model.addVars(1, vtype=GRB.BINARY, name="x")
|
||||
model.addConstr(x[0] >= 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) -> 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] >= 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>
|
||||
543
0.2/api/miplearn/solvers/tests/test_internal_solver.html
Normal file
543
0.2/api/miplearn/solvers/tests/test_internal_solver.html
Normal 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("Hello world")
|
||||
assert sys.stdout == original_stdout
|
||||
assert io.getvalue() == "Hello world\n"
|
||||
|
||||
|
||||
def test_internal_solver_warm_starts():
|
||||
for solver_class in _get_internal_solvers():
|
||||
logger.info("Solver: %s" % solver_class)
|
||||
instance = _get_knapsack_instance(solver_class)
|
||||
model = instance.to_model()
|
||||
solver = solver_class()
|
||||
solver.set_instance(instance, model)
|
||||
solver.set_warm_start(
|
||||
{
|
||||
"x": {
|
||||
0: 1.0,
|
||||
1: 0.0,
|
||||
2: 0.0,
|
||||
3: 1.0,
|
||||
}
|
||||
}
|
||||
)
|
||||
stats = solver.solve(tee=True)
|
||||
if stats["Warm start value"] is not None:
|
||||
assert stats["Warm start value"] == 725.0
|
||||
else:
|
||||
warn(f"{solver_class.__name__} should set warm start value")
|
||||
|
||||
solver.set_warm_start(
|
||||
{
|
||||
"x": {
|
||||
0: 1.0,
|
||||
1: 1.0,
|
||||
2: 1.0,
|
||||
3: 1.0,
|
||||
}
|
||||
}
|
||||
)
|
||||
stats = solver.solve(tee=True)
|
||||
assert stats["Warm start value"] is None
|
||||
|
||||
solver.fix(
|
||||
{
|
||||
"x": {
|
||||
0: 1.0,
|
||||
1: 0.0,
|
||||
2: 0.0,
|
||||
3: 1.0,
|
||||
}
|
||||
}
|
||||
)
|
||||
stats = solver.solve(tee=True)
|
||||
assert stats["Lower bound"] == 725.0
|
||||
assert stats["Upper bound"] == 725.0
|
||||
|
||||
|
||||
def test_internal_solver():
|
||||
for solver_class in _get_internal_solvers():
|
||||
logger.info("Solver: %s" % 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["Optimal value"], 3) == 1287.923
|
||||
assert len(stats["Log"]) > 100
|
||||
|
||||
solution = solver.get_solution()
|
||||
assert round(solution["x"][0], 3) == 1.000
|
||||
assert round(solution["x"][1], 3) == 0.923
|
||||
assert round(solution["x"][2], 3) == 1.000
|
||||
assert round(solution["x"][3], 3) == 0.000
|
||||
|
||||
stats = solver.solve(tee=True)
|
||||
assert not solver.is_infeasible()
|
||||
assert len(stats["Log"]) > 100
|
||||
assert stats["Lower bound"] == 1183.0
|
||||
assert stats["Upper bound"] == 1183.0
|
||||
assert stats["Sense"] == "max"
|
||||
assert isinstance(stats["Wallclock time"], float)
|
||||
|
||||
solution = solver.get_solution()
|
||||
assert solution["x"][0] == 1.0
|
||||
assert solution["x"][1] == 0.0
|
||||
assert solution["x"][2] == 1.0
|
||||
assert solution["x"][3] == 1.0
|
||||
|
||||
# Add a brand new constraint
|
||||
if isinstance(solver, BasePyomoSolver):
|
||||
model.cut = pe.Constraint(expr=model.x[0] <= 0.0, name="cut")
|
||||
solver.add_constraint(model.cut)
|
||||
elif isinstance(solver, GurobiSolver):
|
||||
x = model.getVarByName("x[0]")
|
||||
solver.add_constraint(x <= 0.0, name="cut")
|
||||
else:
|
||||
raise Exception("Illegal state")
|
||||
|
||||
# New constraint should affect solution and should be listed in
|
||||
# constraint ids
|
||||
assert solver.get_constraint_ids() == ["eq_capacity", "cut"]
|
||||
stats = solver.solve()
|
||||
assert stats["Lower bound"] == 1030.0
|
||||
|
||||
assert solver.get_sense() == "max"
|
||||
assert solver.get_constraint_sense("cut") == "<"
|
||||
assert solver.get_constraint_sense("eq_capacity") == "<"
|
||||
|
||||
# Verify slacks
|
||||
assert solver.get_inequality_slacks() == {
|
||||
"cut": 0.0,
|
||||
"eq_capacity": 3.0,
|
||||
}
|
||||
|
||||
if isinstance(solver, GurobiSolver):
|
||||
# Extract the new constraint
|
||||
cobj = solver.extract_constraint("cut")
|
||||
|
||||
# New constraint should no longer affect solution and should no longer
|
||||
# be listed in constraint ids
|
||||
assert solver.get_constraint_ids() == ["eq_capacity"]
|
||||
stats = solver.solve()
|
||||
assert stats["Lower bound"] == 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() == ["eq_capacity", "cut"]
|
||||
stats = solver.solve()
|
||||
assert stats["Lower bound"] == 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("cut", "=")
|
||||
stats = solver.solve()
|
||||
assert round(stats["Lower bound"]) == 1030.0
|
||||
assert round(solver.get_dual("eq_capacity")) == 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["Lower bound"]) == 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["Upper bound"] is None
|
||||
assert stats["Lower bound"] is None
|
||||
|
||||
stats = solver.solve_lp()
|
||||
assert solver.get_solution() is None
|
||||
assert stats["Optimal value"] is None
|
||||
assert solver.get_value("x", 0) is None
|
||||
|
||||
|
||||
def test_iteration_cb():
|
||||
for solver_class in _get_internal_solvers():
|
||||
logger.info("Solver: %s" % 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 < 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["Upper bound"] is None
|
||||
assert stats["Lower bound"] is None
|
||||
|
||||
stats = solver.solve_lp()
|
||||
assert solver.get_solution() is None
|
||||
assert stats["Optimal value"] is None
|
||||
assert solver.get_value("x", 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("Solver: %s" % 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["Optimal value"], 3) == 1287.923
|
||||
assert len(stats["Log"]) > 100
|
||||
|
||||
solution = solver.get_solution()
|
||||
assert round(solution["x"][0], 3) == 1.000
|
||||
assert round(solution["x"][1], 3) == 0.923
|
||||
assert round(solution["x"][2], 3) == 1.000
|
||||
assert round(solution["x"][3], 3) == 0.000
|
||||
|
||||
stats = solver.solve(tee=True)
|
||||
assert not solver.is_infeasible()
|
||||
assert len(stats["Log"]) > 100
|
||||
assert stats["Lower bound"] == 1183.0
|
||||
assert stats["Upper bound"] == 1183.0
|
||||
assert stats["Sense"] == "max"
|
||||
assert isinstance(stats["Wallclock time"], float)
|
||||
|
||||
solution = solver.get_solution()
|
||||
assert solution["x"][0] == 1.0
|
||||
assert solution["x"][1] == 0.0
|
||||
assert solution["x"][2] == 1.0
|
||||
assert solution["x"][3] == 1.0
|
||||
|
||||
# Add a brand new constraint
|
||||
if isinstance(solver, BasePyomoSolver):
|
||||
model.cut = pe.Constraint(expr=model.x[0] <= 0.0, name="cut")
|
||||
solver.add_constraint(model.cut)
|
||||
elif isinstance(solver, GurobiSolver):
|
||||
x = model.getVarByName("x[0]")
|
||||
solver.add_constraint(x <= 0.0, name="cut")
|
||||
else:
|
||||
raise Exception("Illegal state")
|
||||
|
||||
# New constraint should affect solution and should be listed in
|
||||
# constraint ids
|
||||
assert solver.get_constraint_ids() == ["eq_capacity", "cut"]
|
||||
stats = solver.solve()
|
||||
assert stats["Lower bound"] == 1030.0
|
||||
|
||||
assert solver.get_sense() == "max"
|
||||
assert solver.get_constraint_sense("cut") == "<"
|
||||
assert solver.get_constraint_sense("eq_capacity") == "<"
|
||||
|
||||
# Verify slacks
|
||||
assert solver.get_inequality_slacks() == {
|
||||
"cut": 0.0,
|
||||
"eq_capacity": 3.0,
|
||||
}
|
||||
|
||||
if isinstance(solver, GurobiSolver):
|
||||
# Extract the new constraint
|
||||
cobj = solver.extract_constraint("cut")
|
||||
|
||||
# New constraint should no longer affect solution and should no longer
|
||||
# be listed in constraint ids
|
||||
assert solver.get_constraint_ids() == ["eq_capacity"]
|
||||
stats = solver.solve()
|
||||
assert stats["Lower bound"] == 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() == ["eq_capacity", "cut"]
|
||||
stats = solver.solve()
|
||||
assert stats["Lower bound"] == 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("cut", "=")
|
||||
stats = solver.solve()
|
||||
assert round(stats["Lower bound"]) == 1030.0
|
||||
assert round(solver.get_dual("eq_capacity")) == 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("Solver: %s" % solver_class)
|
||||
instance = _get_knapsack_instance(solver_class)
|
||||
model = instance.to_model()
|
||||
solver = solver_class()
|
||||
solver.set_instance(instance, model)
|
||||
solver.set_warm_start(
|
||||
{
|
||||
"x": {
|
||||
0: 1.0,
|
||||
1: 0.0,
|
||||
2: 0.0,
|
||||
3: 1.0,
|
||||
}
|
||||
}
|
||||
)
|
||||
stats = solver.solve(tee=True)
|
||||
if stats["Warm start value"] is not None:
|
||||
assert stats["Warm start value"] == 725.0
|
||||
else:
|
||||
warn(f"{solver_class.__name__} should set warm start value")
|
||||
|
||||
solver.set_warm_start(
|
||||
{
|
||||
"x": {
|
||||
0: 1.0,
|
||||
1: 1.0,
|
||||
2: 1.0,
|
||||
3: 1.0,
|
||||
}
|
||||
}
|
||||
)
|
||||
stats = solver.solve(tee=True)
|
||||
assert stats["Warm start value"] is None
|
||||
|
||||
solver.fix(
|
||||
{
|
||||
"x": {
|
||||
0: 1.0,
|
||||
1: 0.0,
|
||||
2: 0.0,
|
||||
3: 1.0,
|
||||
}
|
||||
}
|
||||
)
|
||||
stats = solver.solve(tee=True)
|
||||
assert stats["Lower bound"] == 725.0
|
||||
assert stats["Upper bound"] == 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("Solver: %s" % 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 < 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("Hello world")
|
||||
assert sys.stdout == original_stdout
|
||||
assert io.getvalue() == "Hello world\n"</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["Lower bound"]) == 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>
|
||||
119
0.2/api/miplearn/solvers/tests/test_lazy_cb.html
Normal file
119
0.2/api/miplearn/solvers/tests/test_lazy_cb.html
Normal 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("x[0] = %.f" % cb_solver.get_value("x", 0))
|
||||
cobj = (cb_model.getVarByName("x[0]") * 1.0, "<", 0.0, "cut")
|
||||
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["x"][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("x[0] = %.f" % cb_solver.get_value("x", 0))
|
||||
cobj = (cb_model.getVarByName("x[0]") * 1.0, "<", 0.0, "cut")
|
||||
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["x"][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>
|
||||
365
0.2/api/miplearn/solvers/tests/test_learning_solver.html
Normal file
365
0.2/api/miplearn/solvers/tests/test_learning_solver.html
Normal 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 ["exact", "heuristic"]:
|
||||
for internal_solver in _get_internal_solvers():
|
||||
logger.info("Solver: %s" % 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["Solution"]["x"][0] == 1.0
|
||||
assert data["Solution"]["x"][1] == 0.0
|
||||
assert data["Solution"]["x"][2] == 1.0
|
||||
assert data["Solution"]["x"][3] == 1.0
|
||||
assert data["Lower bound"] == 1183.0
|
||||
assert data["Upper bound"] == 1183.0
|
||||
assert round(data["LP solution"]["x"][0], 3) == 1.000
|
||||
assert round(data["LP solution"]["x"][1], 3) == 0.923
|
||||
assert round(data["LP solution"]["x"][2], 3) == 1.000
|
||||
assert round(data["LP solution"]["x"][3], 3) == 0.000
|
||||
assert round(data["LP value"], 3) == 1287.923
|
||||
assert len(data["MIP log"]) > 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("Solver: %s" % 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["Solution"]["x"].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=".pkl", 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], "rb") as file:
|
||||
instance = pickle.load(file)
|
||||
assert len(instance.training_data) > 0
|
||||
|
||||
# Test: parallel_solve
|
||||
solver.parallel_solve(filenames)
|
||||
for filename in filenames:
|
||||
with open(filename, "rb") as file:
|
||||
instance = pickle.load(file)
|
||||
assert len(instance.training_data) > 0
|
||||
|
||||
# Test: solve (with specified output)
|
||||
output = [f + ".out" 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=".pkl", 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["Lower bound"] == stats["Predicted LB"]</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 ["exact", "heuristic"]:
|
||||
for internal_solver in _get_internal_solvers():
|
||||
logger.info("Solver: %s" % 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["Solution"]["x"][0] == 1.0
|
||||
assert data["Solution"]["x"][1] == 0.0
|
||||
assert data["Solution"]["x"][2] == 1.0
|
||||
assert data["Solution"]["x"][3] == 1.0
|
||||
assert data["Lower bound"] == 1183.0
|
||||
assert data["Upper bound"] == 1183.0
|
||||
assert round(data["LP solution"]["x"][0], 3) == 1.000
|
||||
assert round(data["LP solution"]["x"][1], 3) == 0.923
|
||||
assert round(data["LP solution"]["x"][2], 3) == 1.000
|
||||
assert round(data["LP solution"]["x"][3], 3) == 0.000
|
||||
assert round(data["LP value"], 3) == 1287.923
|
||||
assert len(data["MIP log"]) > 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["Solution"]["x"].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=".pkl", 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["Lower bound"] == stats["Predicted LB"]</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=".pkl", 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], "rb") as file:
|
||||
instance = pickle.load(file)
|
||||
assert len(instance.training_data) > 0
|
||||
|
||||
# Test: parallel_solve
|
||||
solver.parallel_solve(filenames)
|
||||
for filename in filenames:
|
||||
with open(filename, "rb") as file:
|
||||
instance = pickle.load(file)
|
||||
assert len(instance.training_data) > 0
|
||||
|
||||
# Test: solve (with specified output)
|
||||
output = [f + ".out" 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("Solver: %s" % 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>
|
||||
138
0.2/api/miplearn/tests/index.html
Normal file
138
0.2/api/miplearn/tests/index.html
Normal file
@@ -0,0 +1,138 @@
|
||||
<!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.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.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 miplearn.problems.knapsack import KnapsackInstance
|
||||
from miplearn.solvers.learning import LearningSolver
|
||||
|
||||
|
||||
def get_test_pyomo_instances():
|
||||
instances = [
|
||||
KnapsackInstance(
|
||||
weights=[23.0, 26.0, 20.0, 18.0],
|
||||
prices=[505.0, 352.0, 458.0, 220.0],
|
||||
capacity=67.0,
|
||||
),
|
||||
KnapsackInstance(
|
||||
weights=[25.0, 30.0, 22.0, 18.0],
|
||||
prices=[500.0, 365.0, 420.0, 150.0],
|
||||
capacity=70.0,
|
||||
),
|
||||
]
|
||||
models = [instance.to_model() for instance in instances]
|
||||
solver = LearningSolver()
|
||||
for i in range(len(instances)):
|
||||
solver.solve(instances[i], models[i])
|
||||
return instances, models</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-submodules">Sub-modules</h2>
|
||||
<dl>
|
||||
<dt><code class="name"><a title="miplearn.tests.test_benchmark" href="test_benchmark.html">miplearn.tests.test_benchmark</a></code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
</dd>
|
||||
<dt><code class="name"><a title="miplearn.tests.test_extractors" href="test_extractors.html">miplearn.tests.test_extractors</a></code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
</dd>
|
||||
</dl>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-functions">Functions</h2>
|
||||
<dl>
|
||||
<dt id="miplearn.tests.get_test_pyomo_instances"><code class="name flex">
|
||||
<span>def <span class="ident">get_test_pyomo_instances</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 get_test_pyomo_instances():
|
||||
instances = [
|
||||
KnapsackInstance(
|
||||
weights=[23.0, 26.0, 20.0, 18.0],
|
||||
prices=[505.0, 352.0, 458.0, 220.0],
|
||||
capacity=67.0,
|
||||
),
|
||||
KnapsackInstance(
|
||||
weights=[25.0, 30.0, 22.0, 18.0],
|
||||
prices=[500.0, 365.0, 420.0, 150.0],
|
||||
capacity=70.0,
|
||||
),
|
||||
]
|
||||
models = [instance.to_model() for instance in instances]
|
||||
solver = LearningSolver()
|
||||
for i in range(len(instances)):
|
||||
solver.solve(instances[i], models[i])
|
||||
return instances, models</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" 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.tests.test_benchmark" href="test_benchmark.html">miplearn.tests.test_benchmark</a></code></li>
|
||||
<li><code><a title="miplearn.tests.test_extractors" href="test_extractors.html">miplearn.tests.test_extractors</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-functions">Functions</a></h3>
|
||||
<ul class="">
|
||||
<li><code><a title="miplearn.tests.get_test_pyomo_instances" href="#miplearn.tests.get_test_pyomo_instances">get_test_pyomo_instances</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>
|
||||
172
0.2/api/miplearn/tests/test_benchmark.html
Normal file
172
0.2/api/miplearn/tests/test_benchmark.html
Normal file
@@ -0,0 +1,172 @@
|
||||
<!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.tests.test_benchmark 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.tests.test_benchmark</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 os.path
|
||||
|
||||
from miplearn.benchmark import BenchmarkRunner
|
||||
from miplearn.problems.stab import MaxWeightStableSetGenerator
|
||||
from scipy.stats import randint
|
||||
|
||||
from miplearn.solvers.learning import LearningSolver
|
||||
|
||||
|
||||
def test_benchmark():
|
||||
# Generate training and test instances
|
||||
generator = MaxWeightStableSetGenerator(n=randint(low=25, high=26))
|
||||
train_instances = generator.generate(5)
|
||||
test_instances = generator.generate(3)
|
||||
|
||||
# Training phase...
|
||||
training_solver = LearningSolver()
|
||||
training_solver.parallel_solve(train_instances, n_jobs=10)
|
||||
|
||||
# Test phase...
|
||||
test_solvers = {
|
||||
"Strategy A": LearningSolver(),
|
||||
"Strategy B": LearningSolver(),
|
||||
}
|
||||
benchmark = BenchmarkRunner(test_solvers)
|
||||
benchmark.fit(train_instances)
|
||||
benchmark.parallel_solve(test_instances, n_jobs=2, n_trials=2)
|
||||
assert benchmark.raw_results().values.shape == (12, 14)
|
||||
|
||||
benchmark.save_results("/tmp/benchmark.csv")
|
||||
assert os.path.isfile("/tmp/benchmark.csv")
|
||||
|
||||
benchmark = BenchmarkRunner(test_solvers)
|
||||
benchmark.load_results("/tmp/benchmark.csv")
|
||||
assert benchmark.raw_results().values.shape == (12, 14)
|
||||
|
||||
|
||||
def test_gap():
|
||||
assert BenchmarkRunner._compute_gap(ub=0.0, lb=0.0) == 0.0
|
||||
assert BenchmarkRunner._compute_gap(ub=1.0, lb=0.5) == 0.5
|
||||
assert BenchmarkRunner._compute_gap(ub=1.0, lb=1.0) == 0.0
|
||||
assert BenchmarkRunner._compute_gap(ub=1.0, lb=-1.0) == 1.0
|
||||
assert BenchmarkRunner._compute_gap(ub=1.0, lb=None) == 1.0
|
||||
assert BenchmarkRunner._compute_gap(ub=None, lb=1.0) == 1.0
|
||||
assert BenchmarkRunner._compute_gap(ub=None, lb=None) == 1.0</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-functions">Functions</h2>
|
||||
<dl>
|
||||
<dt id="miplearn.tests.test_benchmark.test_benchmark"><code class="name flex">
|
||||
<span>def <span class="ident">test_benchmark</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_benchmark():
|
||||
# Generate training and test instances
|
||||
generator = MaxWeightStableSetGenerator(n=randint(low=25, high=26))
|
||||
train_instances = generator.generate(5)
|
||||
test_instances = generator.generate(3)
|
||||
|
||||
# Training phase...
|
||||
training_solver = LearningSolver()
|
||||
training_solver.parallel_solve(train_instances, n_jobs=10)
|
||||
|
||||
# Test phase...
|
||||
test_solvers = {
|
||||
"Strategy A": LearningSolver(),
|
||||
"Strategy B": LearningSolver(),
|
||||
}
|
||||
benchmark = BenchmarkRunner(test_solvers)
|
||||
benchmark.fit(train_instances)
|
||||
benchmark.parallel_solve(test_instances, n_jobs=2, n_trials=2)
|
||||
assert benchmark.raw_results().values.shape == (12, 14)
|
||||
|
||||
benchmark.save_results("/tmp/benchmark.csv")
|
||||
assert os.path.isfile("/tmp/benchmark.csv")
|
||||
|
||||
benchmark = BenchmarkRunner(test_solvers)
|
||||
benchmark.load_results("/tmp/benchmark.csv")
|
||||
assert benchmark.raw_results().values.shape == (12, 14)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.tests.test_benchmark.test_gap"><code class="name flex">
|
||||
<span>def <span class="ident">test_gap</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_gap():
|
||||
assert BenchmarkRunner._compute_gap(ub=0.0, lb=0.0) == 0.0
|
||||
assert BenchmarkRunner._compute_gap(ub=1.0, lb=0.5) == 0.5
|
||||
assert BenchmarkRunner._compute_gap(ub=1.0, lb=1.0) == 0.0
|
||||
assert BenchmarkRunner._compute_gap(ub=1.0, lb=-1.0) == 1.0
|
||||
assert BenchmarkRunner._compute_gap(ub=1.0, lb=None) == 1.0
|
||||
assert BenchmarkRunner._compute_gap(ub=None, lb=1.0) == 1.0
|
||||
assert BenchmarkRunner._compute_gap(ub=None, lb=None) == 1.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.tests" href="index.html">miplearn.tests</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-functions">Functions</a></h3>
|
||||
<ul class="">
|
||||
<li><code><a title="miplearn.tests.test_benchmark.test_benchmark" href="#miplearn.tests.test_benchmark.test_benchmark">test_benchmark</a></code></li>
|
||||
<li><code><a title="miplearn.tests.test_benchmark.test_gap" href="#miplearn.tests.test_benchmark.test_gap">test_gap</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>
|
||||
201
0.2/api/miplearn/tests/test_extractors.html
Normal file
201
0.2/api/miplearn/tests/test_extractors.html
Normal file
@@ -0,0 +1,201 @@
|
||||
<!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.tests.test_extractors 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.tests.test_extractors</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 numpy as np
|
||||
|
||||
from miplearn.extractors import (
|
||||
SolutionExtractor,
|
||||
InstanceFeaturesExtractor,
|
||||
VariableFeaturesExtractor,
|
||||
)
|
||||
from miplearn.problems.knapsack import KnapsackInstance
|
||||
from miplearn.solvers.learning import LearningSolver
|
||||
|
||||
|
||||
def _get_instances():
|
||||
instances = [
|
||||
KnapsackInstance(
|
||||
weights=[1.0, 2.0, 3.0],
|
||||
prices=[10.0, 20.0, 30.0],
|
||||
capacity=2.5,
|
||||
),
|
||||
KnapsackInstance(
|
||||
weights=[3.0, 4.0, 5.0],
|
||||
prices=[20.0, 30.0, 40.0],
|
||||
capacity=4.5,
|
||||
),
|
||||
]
|
||||
models = [instance.to_model() for instance in instances]
|
||||
solver = LearningSolver()
|
||||
for (i, instance) in enumerate(instances):
|
||||
solver.solve(instances[i], models[i])
|
||||
return instances, models
|
||||
|
||||
|
||||
def test_solution_extractor():
|
||||
instances, models = _get_instances()
|
||||
features = SolutionExtractor().extract(instances)
|
||||
assert isinstance(features, dict)
|
||||
assert "default" in features.keys()
|
||||
assert isinstance(features["default"], np.ndarray)
|
||||
assert features["default"].shape == (6, 2)
|
||||
assert features["default"].ravel().tolist() == [
|
||||
1.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0,
|
||||
1.0,
|
||||
0.0,
|
||||
1.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0,
|
||||
1.0,
|
||||
0.0,
|
||||
]
|
||||
|
||||
|
||||
def test_instance_features_extractor():
|
||||
instances, models = _get_instances()
|
||||
features = InstanceFeaturesExtractor().extract(instances)
|
||||
assert features.shape == (2, 3)
|
||||
|
||||
|
||||
def test_variable_features_extractor():
|
||||
instances, models = _get_instances()
|
||||
features = VariableFeaturesExtractor().extract(instances)
|
||||
assert isinstance(features, dict)
|
||||
assert "default" in features
|
||||
assert features["default"].shape == (6, 5)</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-functions">Functions</h2>
|
||||
<dl>
|
||||
<dt id="miplearn.tests.test_extractors.test_instance_features_extractor"><code class="name flex">
|
||||
<span>def <span class="ident">test_instance_features_extractor</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_instance_features_extractor():
|
||||
instances, models = _get_instances()
|
||||
features = InstanceFeaturesExtractor().extract(instances)
|
||||
assert features.shape == (2, 3)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.tests.test_extractors.test_solution_extractor"><code class="name flex">
|
||||
<span>def <span class="ident">test_solution_extractor</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_solution_extractor():
|
||||
instances, models = _get_instances()
|
||||
features = SolutionExtractor().extract(instances)
|
||||
assert isinstance(features, dict)
|
||||
assert "default" in features.keys()
|
||||
assert isinstance(features["default"], np.ndarray)
|
||||
assert features["default"].shape == (6, 2)
|
||||
assert features["default"].ravel().tolist() == [
|
||||
1.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0,
|
||||
1.0,
|
||||
0.0,
|
||||
1.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0,
|
||||
1.0,
|
||||
0.0,
|
||||
]</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.tests.test_extractors.test_variable_features_extractor"><code class="name flex">
|
||||
<span>def <span class="ident">test_variable_features_extractor</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_variable_features_extractor():
|
||||
instances, models = _get_instances()
|
||||
features = VariableFeaturesExtractor().extract(instances)
|
||||
assert isinstance(features, dict)
|
||||
assert "default" in features
|
||||
assert features["default"].shape == (6, 5)</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.tests" href="index.html">miplearn.tests</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-functions">Functions</a></h3>
|
||||
<ul class="">
|
||||
<li><code><a title="miplearn.tests.test_extractors.test_instance_features_extractor" href="#miplearn.tests.test_extractors.test_instance_features_extractor">test_instance_features_extractor</a></code></li>
|
||||
<li><code><a title="miplearn.tests.test_extractors.test_solution_extractor" href="#miplearn.tests.test_extractors.test_solution_extractor">test_solution_extractor</a></code></li>
|
||||
<li><code><a title="miplearn.tests.test_extractors.test_variable_features_extractor" href="#miplearn.tests.test_extractors.test_variable_features_extractor">test_variable_features_extractor</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>
|
||||
214
0.2/api/miplearn/types.html
Normal file
214
0.2/api/miplearn/types.html
Normal file
@@ -0,0 +1,214 @@
|
||||
<!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.types 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.types</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, Dict, Callable, Any, Union, List
|
||||
|
||||
from mypy_extensions import TypedDict
|
||||
|
||||
VarIndex = Union[str, int, List[Union[str, int]]]
|
||||
|
||||
Solution = Dict[str, Dict[VarIndex, Optional[float]]]
|
||||
|
||||
TrainingSample = TypedDict(
|
||||
"TrainingSample",
|
||||
{
|
||||
"LP log": str,
|
||||
"LP solution": Optional[Solution],
|
||||
"LP value": Optional[float],
|
||||
"Lower bound": Optional[float],
|
||||
"MIP log": str,
|
||||
"Solution": Optional[Solution],
|
||||
"Upper bound": Optional[float],
|
||||
"slacks": Dict,
|
||||
},
|
||||
total=False,
|
||||
)
|
||||
|
||||
LPSolveStats = TypedDict(
|
||||
"LPSolveStats",
|
||||
{
|
||||
"Optimal value": Optional[float],
|
||||
"Log": str,
|
||||
},
|
||||
)
|
||||
|
||||
MIPSolveStats = TypedDict(
|
||||
"MIPSolveStats",
|
||||
{
|
||||
"Lower bound": Optional[float],
|
||||
"Upper bound": Optional[float],
|
||||
"Wallclock time": float,
|
||||
"Nodes": Optional[int],
|
||||
"Sense": str,
|
||||
"Log": str,
|
||||
"Warm start value": Optional[float],
|
||||
"LP value": Optional[float],
|
||||
},
|
||||
)
|
||||
|
||||
IterationCallback = Callable[[], bool]
|
||||
|
||||
LazyCallback = Callable[[Any, Any], None]
|
||||
|
||||
SolverParams = Dict[str, Any]
|
||||
|
||||
BranchPriorities = Solution
|
||||
|
||||
|
||||
class Constraint:
|
||||
pass</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-classes">Classes</h2>
|
||||
<dl>
|
||||
<dt id="miplearn.types.Constraint"><code class="flex name class">
|
||||
<span>class <span class="ident">Constraint</span></span>
|
||||
<span>(</span><span>*args, **kwargs)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"></section>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">class Constraint:
|
||||
pass</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="miplearn.types.LPSolveStats"><code class="flex name class">
|
||||
<span>class <span class="ident">LPSolveStats</span></span>
|
||||
<span>(</span><span>*args, **kwargs)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"><p>dict() -> new empty dictionary
|
||||
dict(mapping) -> new dictionary initialized from a mapping object's
|
||||
(key, value) pairs
|
||||
dict(iterable) -> new dictionary initialized as if via:
|
||||
d = {}
|
||||
for k, v in iterable:
|
||||
d[k] = v
|
||||
dict(**kwargs) -> new dictionary initialized with the name=value pairs
|
||||
in the keyword argument list.
|
||||
For example:
|
||||
dict(one=1, two=2)</p></section>
|
||||
<h3>Ancestors</h3>
|
||||
<ul class="hlist">
|
||||
<li>builtins.dict</li>
|
||||
</ul>
|
||||
</dd>
|
||||
<dt id="miplearn.types.MIPSolveStats"><code class="flex name class">
|
||||
<span>class <span class="ident">MIPSolveStats</span></span>
|
||||
<span>(</span><span>*args, **kwargs)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"><p>dict() -> new empty dictionary
|
||||
dict(mapping) -> new dictionary initialized from a mapping object's
|
||||
(key, value) pairs
|
||||
dict(iterable) -> new dictionary initialized as if via:
|
||||
d = {}
|
||||
for k, v in iterable:
|
||||
d[k] = v
|
||||
dict(**kwargs) -> new dictionary initialized with the name=value pairs
|
||||
in the keyword argument list.
|
||||
For example:
|
||||
dict(one=1, two=2)</p></section>
|
||||
<h3>Ancestors</h3>
|
||||
<ul class="hlist">
|
||||
<li>builtins.dict</li>
|
||||
</ul>
|
||||
</dd>
|
||||
<dt id="miplearn.types.TrainingSample"><code class="flex name class">
|
||||
<span>class <span class="ident">TrainingSample</span></span>
|
||||
<span>(</span><span>*args, **kwargs)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<section class="desc"><p>dict() -> new empty dictionary
|
||||
dict(mapping) -> new dictionary initialized from a mapping object's
|
||||
(key, value) pairs
|
||||
dict(iterable) -> new dictionary initialized as if via:
|
||||
d = {}
|
||||
for k, v in iterable:
|
||||
d[k] = v
|
||||
dict(**kwargs) -> new dictionary initialized with the name=value pairs
|
||||
in the keyword argument list.
|
||||
For example:
|
||||
dict(one=1, two=2)</p></section>
|
||||
<h3>Ancestors</h3>
|
||||
<ul class="hlist">
|
||||
<li>builtins.dict</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" href="index.html">miplearn</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-classes">Classes</a></h3>
|
||||
<ul>
|
||||
<li>
|
||||
<h4><code><a title="miplearn.types.Constraint" href="#miplearn.types.Constraint">Constraint</a></code></h4>
|
||||
</li>
|
||||
<li>
|
||||
<h4><code><a title="miplearn.types.LPSolveStats" href="#miplearn.types.LPSolveStats">LPSolveStats</a></code></h4>
|
||||
</li>
|
||||
<li>
|
||||
<h4><code><a title="miplearn.types.MIPSolveStats" href="#miplearn.types.MIPSolveStats">MIPSolveStats</a></code></h4>
|
||||
</li>
|
||||
<li>
|
||||
<h4><code><a title="miplearn.types.TrainingSample" href="#miplearn.types.TrainingSample">TrainingSample</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>
|
||||
@@ -105,6 +105,12 @@
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
<li >
|
||||
<a href="../api/miplearn/index.html">API</a>
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
|
||||
@@ -105,6 +105,12 @@
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
<li >
|
||||
<a href="../api/miplearn/index.html">API</a>
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
@@ -153,11 +159,28 @@
|
||||
<h1 id="customization">Customization</h1>
|
||||
<h2 id="customizing-solver-parameters">Customizing solver parameters</h2>
|
||||
<h3 id="selecting-the-internal-mip-solver">Selecting the internal MIP solver</h3>
|
||||
<p>By default, <code>LearningSolver</code> uses <a href="https://www.gurobi.com/">Gurobi</a> as its internal MIP solver. Another supported solver is <a href="https://www.ibm.com/products/ilog-cplex-optimization-studio">IBM ILOG CPLEX</a>. To switch between solvers, use the <code>solver</code> constructor argument, as shown below. It is also possible to specify a time limit (in seconds) and a relative MIP gap tolerance.</p>
|
||||
<pre><code class="language-python">from miplearn import LearningSolver
|
||||
solver = LearningSolver(solver="cplex",
|
||||
time_limit=300,
|
||||
gap_tolerance=1e-3)
|
||||
<p>By default, <code>LearningSolver</code> uses <a href="https://www.gurobi.com/">Gurobi</a> as its internal MIP solver, and expects models to be provided using the Pyomo modeling language. Supported solvers and modeling languages include:</p>
|
||||
<ul>
|
||||
<li><code>GurobiPyomoSolver</code>: Gurobi with Pyomo (default).</li>
|
||||
<li><code>CplexPyomoSolver</code>: <a href="https://www.ibm.com/products/ilog-cplex-optimization-studio">IBM ILOG CPLEX</a> with Pyomo.</li>
|
||||
<li><code>XpressPyomoSolver</code>: <a href="https://www.fico.com/en/products/fico-xpress-solver">FICO XPRESS Solver</a> with Pyomo.</li>
|
||||
<li><code>GurobiSolver</code>: Gurobi without any modeling language.</li>
|
||||
</ul>
|
||||
<p>To switch between solvers, provide the desired class using the <code>solver</code> argument:</p>
|
||||
<pre><code class="language-python">from miplearn import LearningSolver, CplexPyomoSolver
|
||||
solver = LearningSolver(solver=CplexPyomoSolver)
|
||||
</code></pre>
|
||||
<p>To configure a particular solver, use the <code>params</code> constructor argument, as shown below.</p>
|
||||
<pre><code class="language-python">from miplearn import LearningSolver, GurobiPyomoSolver
|
||||
solver = LearningSolver(
|
||||
solver=lambda: GurobiPyomoSolver(
|
||||
params={
|
||||
"TimeLimit": 900,
|
||||
"MIPGap": 1e-3,
|
||||
"NodeLimit": 1000,
|
||||
}
|
||||
),
|
||||
)
|
||||
</code></pre>
|
||||
<h2 id="customizing-solver-components">Customizing solver components</h2>
|
||||
<p><code>LearningSolver</code> is composed by a number of individual machine-learning components, each targeting a different part of the solution process. Each component can be individually enabled, disabled or customized. The following components are enabled by default:</p>
|
||||
@@ -181,13 +204,6 @@ solver2 = LearningSolver(components=[
|
||||
PrimalSolutionComponent(...),
|
||||
])
|
||||
</code></pre>
|
||||
<p>It is also possible to add components to an existing solver using the <code>solver.add</code> method, as shown below. If the solver already holds another component of that type, the new component will replace the previous one.</p>
|
||||
<pre><code class="language-python"># Create solver with default components
|
||||
solver = LearningSolver()
|
||||
|
||||
# Replace the default LazyConstraintComponent by one with custom parameters
|
||||
solver.add(LazyConstraintComponent(...))
|
||||
</code></pre>
|
||||
<h3 id="adjusting-component-aggressiveness">Adjusting component aggressiveness</h3>
|
||||
<p>The aggressiveness of classification components (such as <code>PrimalSolutionComponent</code> and <code>LazyConstraintComponent</code>) can
|
||||
be adjusted through the <code>threshold</code> constructor argument. Internally, these components ask the ML models how confident
|
||||
|
||||
@@ -105,6 +105,12 @@
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
<li >
|
||||
<a href="api/miplearn/index.html">API</a>
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
@@ -148,8 +154,10 @@
|
||||
<div class="col-md-9" role="main">
|
||||
|
||||
<h1 id="miplearn">MIPLearn</h1>
|
||||
<p><strong>MIPLearn</strong> is an extensible framework for <strong>Learning-Enhanced Mixed-Integer Optimization</strong>, an approach targeted at discrete optimization problems that need to be repeatedly solved with only minor changes to input data.</p>
|
||||
<p>The package uses Machine Learning (ML) to automatically identify patterns in previously solved instances of the problem, or in the solution process itself, and produces hints that can guide a conventional MIP solver towards the optimal solution faster. For particular classes of problems, this approach has been shown to provide significant performance benefits (see <a href="problems/">benchmark results</a> and <a href="about/#references">references</a> for more details).</p>
|
||||
<p><strong>MIPLearn</strong> is an extensible framework for solving discrete optimization problems using a combination of Mixed-Integer Linear Programming (MIP) and Machine Learning (ML). The framework uses ML methods to automatically identify patterns in previously solved instances of the problem, then uses these patterns to accelerate the performance of conventional state-of-the-art MIP solvers (such as CPLEX, Gurobi or XPRESS).</p>
|
||||
<p>Unlike pure ML methods, MIPLearn is not only able to find high-quality solutions to discrete optimization problems, but it can also prove the optimality and feasibility of these solutions.
|
||||
Unlike conventional MIP solvers, MIPLearn can take full advantage of very specific observations that happen to be true in a particular family of instances (such as the observation that a particular constraint is typically redundant, or that a particular variable typically assumes a certain value). </p>
|
||||
<p>For certain classes of problems, this approach has been shown to provide significant performance benefits (see <a href="problems/">benchmarks</a> and <a href="about/">references</a>).</p>
|
||||
<h3 id="features">Features</h3>
|
||||
<ul>
|
||||
<li>
|
||||
@@ -285,5 +293,5 @@
|
||||
|
||||
<!--
|
||||
MkDocs version : 1.1.2
|
||||
Build Date UTC : 2020-12-03 18:22:04.344984+00:00
|
||||
Build Date UTC : 2021-01-22 02:31:46.190084+00:00
|
||||
-->
|
||||
|
||||
@@ -105,6 +105,12 @@
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
<li >
|
||||
<a href="../api/miplearn/index.html">API</a>
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,27 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"><url>
|
||||
<loc>None</loc>
|
||||
<lastmod>2020-12-03</lastmod>
|
||||
<lastmod>2021-01-22</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url><url>
|
||||
<loc>None</loc>
|
||||
<lastmod>2020-12-03</lastmod>
|
||||
<lastmod>2021-01-22</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url><url>
|
||||
<loc>None</loc>
|
||||
<lastmod>2020-12-03</lastmod>
|
||||
<lastmod>2021-01-22</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url><url>
|
||||
<loc>None</loc>
|
||||
<lastmod>2020-12-03</lastmod>
|
||||
<lastmod>2021-01-22</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url><url>
|
||||
<loc>None</loc>
|
||||
<lastmod>2020-12-03</lastmod>
|
||||
<lastmod>2021-01-22</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url><url>
|
||||
<loc>None</loc>
|
||||
<lastmod>2020-12-03</lastmod>
|
||||
<lastmod>2021-01-22</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
</urlset>
|
||||
Binary file not shown.
@@ -105,6 +105,12 @@
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
<li >
|
||||
<a href="../api/miplearn/index.html">API</a>
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
@@ -149,11 +155,12 @@
|
||||
<li class="third-level"><a href="#42-adding-lazy-constraints-through-callbacks">4.2 Adding lazy constraints through callbacks</a></li>
|
||||
<li class="second-level"><a href="#5-obtaining-heuristic-solutions">5. Obtaining heuristic solutions</a></li>
|
||||
|
||||
<li class="second-level"><a href="#6-saving-and-loading-solver-state">6. Saving and loading solver state</a></li>
|
||||
<li class="second-level"><a href="#6-scaling-up">6. Scaling Up</a></li>
|
||||
|
||||
<li class="second-level"><a href="#7-solving-training-instances-in-parallel">7. Solving training instances in parallel</a></li>
|
||||
|
||||
<li class="second-level"><a href="#8-current-limitations">8. Current Limitations</a></li>
|
||||
<li class="third-level"><a href="#61-saving-and-loading-solver-state">6.1 Saving and loading solver state</a></li>
|
||||
<li class="third-level"><a href="#62-solving-instances-in-parallel">6.2 Solving instances in parallel</a></li>
|
||||
<li class="third-level"><a href="#63-solving-instances-from-the-disk">6.3 Solving instances from the disk</a></li>
|
||||
<li class="second-level"><a href="#7-current-limitations">7. Current Limitations</a></li>
|
||||
|
||||
</ul>
|
||||
</div></div>
|
||||
@@ -242,7 +249,8 @@ for instance in test_instances:
|
||||
<p class="admonition-title">Danger</p>
|
||||
<p>The <code>heuristic</code> mode provides no optimality guarantees, and therefore should only be used if the solver is first trained on a large and representative set of training instances. Training on a small or non-representative set of instances may produce low-quality solutions, or make the solver incorrectly classify new instances as infeasible.</p>
|
||||
</div>
|
||||
<h2 id="6-saving-and-loading-solver-state">6. Saving and loading solver state</h2>
|
||||
<h2 id="6-scaling-up">6. Scaling Up</h2>
|
||||
<h3 id="61-saving-and-loading-solver-state">6.1 Saving and loading solver state</h3>
|
||||
<p>After solving a large number of training instances, it may be desirable to save the current state of <code>LearningSolver</code> to disk, so that the solver can still use the acquired knowledge after the application restarts. This can be accomplished by using the standard <code>pickle</code> module, as the following example illustrates:</p>
|
||||
<pre><code class="language-python">from miplearn import LearningSolver
|
||||
import pickle
|
||||
@@ -257,20 +265,22 @@ for instance in training_instances:
|
||||
solver.fit(training_instances)
|
||||
|
||||
# Save trained solver to disk
|
||||
pickle.dump(solver, open("solver.pickle", "wb"))
|
||||
with open("solver.pickle", "wb") as file:
|
||||
pickle.dump(solver, file)
|
||||
|
||||
# Application restarts...
|
||||
|
||||
# Load trained solver from disk
|
||||
solver = pickle.load(open("solver.pickle", "rb"))
|
||||
with open("solver.pickle", "rb") as file:
|
||||
solver = pickle.load(file)
|
||||
|
||||
# Solve additional instances
|
||||
test_instances = [...]
|
||||
for instance in test_instances:
|
||||
solver.solve(instance)
|
||||
</code></pre>
|
||||
<h2 id="7-solving-training-instances-in-parallel">7. Solving training instances in parallel</h2>
|
||||
<p>In many situations, training and test instances can be solved in parallel to accelerate the training process. <code>LearningSolver</code> provides the method <code>parallel_solve(instances)</code> to easily achieve this:</p>
|
||||
<h3 id="62-solving-instances-in-parallel">6.2 Solving instances in parallel</h3>
|
||||
<p>In many situations, instances can be solved in parallel to accelerate the training process. <code>LearningSolver</code> provides the method <code>parallel_solve(instances)</code> to easily achieve this:</p>
|
||||
<pre><code class="language-python">from miplearn import LearningSolver
|
||||
|
||||
training_instances = [...]
|
||||
@@ -282,9 +292,48 @@ solver.fit(training_instances)
|
||||
test_instances = [...]
|
||||
solver.parallel_solve(test_instances)
|
||||
</code></pre>
|
||||
<h2 id="8-current-limitations">8. Current Limitations</h2>
|
||||
<h3 id="63-solving-instances-from-the-disk">6.3 Solving instances from the disk</h3>
|
||||
<p>In all examples above, we have assumed that instances are available as Python objects, stored in memory. When problem instances are very large, or when there is a large number of problem instances, this approach may require an excessive amount of memory. To reduce memory requirements, MIPLearn can also operate on instances that are stored on disk. More precisely, the methods <code>fit</code>, <code>solve</code> and <code>parallel_solve</code> in <code>LearningSolver</code> can operate on filenames (or lists of filenames) instead of instance objects, as the next example illustrates.
|
||||
Instance files must be pickled instance objects. The method <code>solve</code> loads at most one instance to memory at a time, while <code>parallel_solve</code> loads at most <code>n_jobs</code> instances.</p>
|
||||
<pre><code class="language-python">from miplearn import LearningSolver
|
||||
|
||||
# Construct and pickle 600 problem instances
|
||||
for i in range(600):
|
||||
instance = CustomInstance([...])
|
||||
with open("instance_%03d.pkl" % i, "w") as file:
|
||||
pickle.dump(instance, obj)
|
||||
|
||||
# Split instances into training and test
|
||||
test_instances = ["instance_%03d.pkl" % i for i in range(500)]
|
||||
train_instances = ["instance_%03d.pkl" % i for i in range(500, 600)]
|
||||
|
||||
# Create solver
|
||||
solver = LearningSolver([...])
|
||||
|
||||
# Solve training instances
|
||||
solver.parallel_solve(train_instances, n_jobs=4)
|
||||
|
||||
# Train ML models
|
||||
solver.fit(train_instances)
|
||||
|
||||
# Solve test instances
|
||||
solver.parallel_solve(test_instances, n_jobs=4)
|
||||
</code></pre>
|
||||
<p>By default, <code>solve</code> and <code>parallel_solve</code> modify files in place. That is, after the instances are loaded from disk and solved, MIPLearn writes them back to the disk, overwriting the original files. To write to an alternative file instead, the argument <code>output</code> may be used. In <code>solve</code>, this argument should be a single filename. In <code>parallel_solve</code>, it should be a list, containing exactly as many filenames as instances. If <code>output</code> is <code>None</code>, the modifications are simply discarded. This can be useful, for example, during benchmarks.</p>
|
||||
<pre><code class="language-python"># Solve a single instance file and store the output to another file
|
||||
solver.solve("knapsack_1.orig.pkl", output="knapsack_1.solved.pkl")
|
||||
|
||||
# Solve a list of instance files
|
||||
instances = ["knapsack_%03d.orig.pkl" % i for i in range(100)]
|
||||
output = ["knapsack_%03d.solved.pkl" % i for i in range(100)]
|
||||
solver.parallel_solve(instances, output=output)
|
||||
|
||||
# Solve instances and discard solutions and training data
|
||||
solver.parallel_solve(instances, output=None)
|
||||
</code></pre>
|
||||
<h2 id="7-current-limitations">7. Current Limitations</h2>
|
||||
<ul>
|
||||
<li>Only binary and continuous decision variables are currently supported.</li>
|
||||
<li>Only binary and continuous decision variables are currently supported. General integer variables are not currently supported by all solver components.</li>
|
||||
</ul></div>
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user