Update 0.2 docs

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

View File

@@ -0,0 +1,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):
&#34;&#34;&#34;
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.
&#34;&#34;&#34;
def before_solve(
self,
solver: &#34;LearningSolver&#34;,
instance: Instance,
model: Any,
) -&gt; None:
&#34;&#34;&#34;
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.
&#34;&#34;&#34;
return
@abstractmethod
def after_solve(
self,
solver: &#34;LearningSolver&#34;,
instance: Instance,
model: Any,
stats: MIPSolveStats,
training_data: TrainingSample,
) -&gt; None:
&#34;&#34;&#34;
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.
&#34;&#34;&#34;
pass
def fit(
self,
training_instances: Union[List[str], List[Instance]],
) -&gt; None:
return
def iteration_cb(
self,
solver: &#34;LearningSolver&#34;,
instance: Instance,
model: Any,
) -&gt; bool:
&#34;&#34;&#34;
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.
&#34;&#34;&#34;
return False
def lazy_cb(
self,
solver: &#34;LearningSolver&#34;,
instance: Instance,
model: Any,
) -&gt; 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):
&#34;&#34;&#34;
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.
&#34;&#34;&#34;
def before_solve(
self,
solver: &#34;LearningSolver&#34;,
instance: Instance,
model: Any,
) -&gt; None:
&#34;&#34;&#34;
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.
&#34;&#34;&#34;
return
@abstractmethod
def after_solve(
self,
solver: &#34;LearningSolver&#34;,
instance: Instance,
model: Any,
stats: MIPSolveStats,
training_data: TrainingSample,
) -&gt; None:
&#34;&#34;&#34;
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.
&#34;&#34;&#34;
pass
def fit(
self,
training_instances: Union[List[str], List[Instance]],
) -&gt; None:
return
def iteration_cb(
self,
solver: &#34;LearningSolver&#34;,
instance: Instance,
model: Any,
) -&gt; bool:
&#34;&#34;&#34;
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.
&#34;&#34;&#34;
return False
def lazy_cb(
self,
solver: &#34;LearningSolver&#34;,
instance: Instance,
model: Any,
) -&gt; 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> :&ensp;<code>LearningSolver</code></dt>
<dd>The solver calling this method.</dd>
<dt><strong><code>instance</code></strong> :&ensp;<code>Instance</code></dt>
<dd>The instance being solved.</dd>
<dt><strong><code>model</code></strong> :&ensp;<code>Any</code></dt>
<dd>The concrete optimization model being solved.</dd>
<dt><strong><code>stats</code></strong> :&ensp;<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> :&ensp;<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: &#34;LearningSolver&#34;,
instance: Instance,
model: Any,
stats: MIPSolveStats,
training_data: TrainingSample,
) -&gt; None:
&#34;&#34;&#34;
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.
&#34;&#34;&#34;
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: &#34;LearningSolver&#34;,
instance: Instance,
model: Any,
) -&gt; None:
&#34;&#34;&#34;
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.
&#34;&#34;&#34;
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]],
) -&gt; 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> :&ensp;<code>LearningSolver</code></dt>
<dd>The solver calling this method.</dd>
<dt><strong><code>instance</code></strong> :&ensp;<code>Instance</code></dt>
<dd>The instance being solved.</dd>
<dt><strong><code>model</code></strong> :&ensp;<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: &#34;LearningSolver&#34;,
instance: Instance,
model: Any,
) -&gt; bool:
&#34;&#34;&#34;
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.
&#34;&#34;&#34;
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: &#34;LearningSolver&#34;,
instance: Instance,
model: Any,
) -&gt; 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>

View 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):
&#34;&#34;&#34;
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.
&#34;&#34;&#34;
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> :&ensp;<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):
&#34;&#34;&#34;
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.
&#34;&#34;&#34;
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>

View 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):
&#34;&#34;&#34;
A component that predicts which user cuts to enforce.
&#34;&#34;&#34;
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(&#34;Predicting violated user cuts...&#34;)
violations = self.predict(instance)
logger.info(&#34;Enforcing %d user cuts...&#34; % 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(&#34;Fitting...&#34;)
features = InstanceFeaturesExtractor().extract(training_instances)
self.classifiers = {}
violation_to_instance_idx = {}
for (idx, instance) in enumerate(training_instances):
if not hasattr(instance, &#34;found_violated_user_cuts&#34;):
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=&#34;Fit (user cuts)&#34;,
disable=not sys.stdout.isatty(),
):
logger.debug(&#34;Training: %s&#34; % (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] &gt; 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=&#34;Evaluate (lazy)&#34;,
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)) &amp; all_violations
pred_negative = all_violations - pred_positive
tp = len(pred_positive &amp; condition_positive)
tn = len(pred_negative &amp; condition_negative)
fp = len(pred_positive &amp; condition_negative)
fn = len(pred_negative &amp; 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):
&#34;&#34;&#34;
A component that predicts which user cuts to enforce.
&#34;&#34;&#34;
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(&#34;Predicting violated user cuts...&#34;)
violations = self.predict(instance)
logger.info(&#34;Enforcing %d user cuts...&#34; % 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(&#34;Fitting...&#34;)
features = InstanceFeaturesExtractor().extract(training_instances)
self.classifiers = {}
violation_to_instance_idx = {}
for (idx, instance) in enumerate(training_instances):
if not hasattr(instance, &#34;found_violated_user_cuts&#34;):
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=&#34;Fit (user cuts)&#34;,
disable=not sys.stdout.isatty(),
):
logger.debug(&#34;Training: %s&#34; % (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] &gt; 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=&#34;Evaluate (lazy)&#34;,
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)) &amp; all_violations
pred_negative = all_violations - pred_positive
tp = len(pred_positive &amp; condition_positive)
tn = len(pred_negative &amp; condition_negative)
fp = len(pred_positive &amp; condition_negative)
fn = len(pred_negative &amp; 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=&#34;Evaluate (lazy)&#34;,
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)) &amp; all_violations
pred_negative = all_violations - pred_positive
tp = len(pred_positive &amp; condition_positive)
tn = len(pred_negative &amp; condition_negative)
fp = len(pred_positive &amp; condition_negative)
fn = len(pred_negative &amp; 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(&#34;Fitting...&#34;)
features = InstanceFeaturesExtractor().extract(training_instances)
self.classifiers = {}
violation_to_instance_idx = {}
for (idx, instance) in enumerate(training_instances):
if not hasattr(instance, &#34;found_violated_user_cuts&#34;):
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=&#34;Fit (user cuts)&#34;,
disable=not sys.stdout.isatty(),
):
logger.debug(&#34;Training: %s&#34; % (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] &gt; 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>

View 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 = {
&#34;Predicted positive&#34;: fp + tp,
&#34;Predicted negative&#34;: fn + tn,
&#34;Condition positive&#34;: p,
&#34;Condition negative&#34;: n,
&#34;True positive&#34;: tp,
&#34;True negative&#34;: tn,
&#34;False positive&#34;: fp,
&#34;False negative&#34;: fn,
&#34;Accuracy&#34;: (tp + tn) / (p + n),
&#34;F1 score&#34;: (2 * tp) / (2 * tp + fp + fn),
}
if p &gt; 0:
d[&#34;Recall&#34;] = tp / p
else:
d[&#34;Recall&#34;] = 1.0
if tp + fp &gt; 0:
d[&#34;Precision&#34;] = tp / (tp + fp)
else:
d[&#34;Precision&#34;] = 1.0
t = (p + n) / 100.0
d[&#34;Predicted positive (%)&#34;] = d[&#34;Predicted positive&#34;] / t
d[&#34;Predicted negative (%)&#34;] = d[&#34;Predicted negative&#34;] / t
d[&#34;Condition positive (%)&#34;] = d[&#34;Condition positive&#34;] / t
d[&#34;Condition negative (%)&#34;] = d[&#34;Condition negative&#34;] / t
d[&#34;True positive (%)&#34;] = d[&#34;True positive&#34;] / t
d[&#34;True negative (%)&#34;] = d[&#34;True negative&#34;] / t
d[&#34;False positive (%)&#34;] = d[&#34;False positive&#34;] / t
d[&#34;False negative (%)&#34;] = d[&#34;False negative&#34;] / 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 = {
&#34;Predicted positive&#34;: fp + tp,
&#34;Predicted negative&#34;: fn + tn,
&#34;Condition positive&#34;: p,
&#34;Condition negative&#34;: n,
&#34;True positive&#34;: tp,
&#34;True negative&#34;: tn,
&#34;False positive&#34;: fp,
&#34;False negative&#34;: fn,
&#34;Accuracy&#34;: (tp + tn) / (p + n),
&#34;F1 score&#34;: (2 * tp) / (2 * tp + fp + fn),
}
if p &gt; 0:
d[&#34;Recall&#34;] = tp / p
else:
d[&#34;Recall&#34;] = 1.0
if tp + fp &gt; 0:
d[&#34;Precision&#34;] = tp / (tp + fp)
else:
d[&#34;Precision&#34;] = 1.0
t = (p + n) / 100.0
d[&#34;Predicted positive (%)&#34;] = d[&#34;Predicted positive&#34;] / t
d[&#34;Predicted negative (%)&#34;] = d[&#34;Predicted negative&#34;] / t
d[&#34;Condition positive (%)&#34;] = d[&#34;Condition positive&#34;] / t
d[&#34;Condition negative (%)&#34;] = d[&#34;Condition negative&#34;] / t
d[&#34;True positive (%)&#34;] = d[&#34;True positive&#34;] / t
d[&#34;True negative (%)&#34;] = d[&#34;True negative&#34;] / t
d[&#34;False positive (%)&#34;] = d[&#34;False positive&#34;] / t
d[&#34;False negative (%)&#34;] = d[&#34;False negative&#34;] / 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>

View 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):
&#34;&#34;&#34;
A component that predicts which lazy constraints to enforce.
&#34;&#34;&#34;
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(&#34;Predicting violated lazy constraints...&#34;)
violations = self.predict(instance)
logger.info(&#34;Enforcing %d lazy constraints...&#34; % 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(&#34;Finding violated (dynamic) lazy constraints...&#34;)
violations = instance.find_violated_lazy_constraints(model)
if len(violations) == 0:
return False
instance.found_violated_lazy_constraints += violations
logger.debug(&#34; %d violations found&#34; % 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(&#34;Fitting...&#34;)
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=&#34;Fit (lazy)&#34;,
disable=not sys.stdout.isatty(),
):
logger.debug(&#34;Training: %s&#34; % (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] &gt; 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=&#34;Evaluate (lazy)&#34;,
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)) &amp; all_violations
pred_negative = all_violations - pred_positive
tp = len(pred_positive &amp; condition_positive)
tn = len(pred_negative &amp; condition_negative)
fp = len(pred_positive &amp; condition_negative)
fn = len(pred_negative &amp; 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):
&#34;&#34;&#34;
A component that predicts which lazy constraints to enforce.
&#34;&#34;&#34;
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(&#34;Predicting violated lazy constraints...&#34;)
violations = self.predict(instance)
logger.info(&#34;Enforcing %d lazy constraints...&#34; % 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(&#34;Finding violated (dynamic) lazy constraints...&#34;)
violations = instance.find_violated_lazy_constraints(model)
if len(violations) == 0:
return False
instance.found_violated_lazy_constraints += violations
logger.debug(&#34; %d violations found&#34; % 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(&#34;Fitting...&#34;)
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=&#34;Fit (lazy)&#34;,
disable=not sys.stdout.isatty(),
):
logger.debug(&#34;Training: %s&#34; % (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] &gt; 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=&#34;Evaluate (lazy)&#34;,
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)) &amp; all_violations
pred_negative = all_violations - pred_positive
tp = len(pred_positive &amp; condition_positive)
tn = len(pred_negative &amp; condition_negative)
fp = len(pred_positive &amp; condition_negative)
fn = len(pred_negative &amp; 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=&#34;Evaluate (lazy)&#34;,
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)) &amp; all_violations
pred_negative = all_violations - pred_positive
tp = len(pred_positive &amp; condition_positive)
tn = len(pred_negative &amp; condition_negative)
fp = len(pred_positive &amp; condition_negative)
fn = len(pred_negative &amp; 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(&#34;Fitting...&#34;)
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=&#34;Fit (lazy)&#34;,
disable=not sys.stdout.isatty(),
):
logger.debug(&#34;Training: %s&#34; % (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] &gt; 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>

View 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(&#34;Increasing gap tolerance to %f&#34;, 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(&#34;Restoring gap tolerance to %f&#34;, 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(&#34;Finding violated lazy constraints...&#34;)
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) &gt; 0:
logger.info(
&#34;%8d lazy constraints added %8d in the pool&#34;
% (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, &#34;found_violated_lazy_constraints&#34;)
]
logger.debug(&#34;Extracting x and y...&#34;)
x = self.x(training_instances)
y = self.y(training_instances)
logger.debug(&#34;Fitting...&#34;)
for category in tqdm(
x.keys(), desc=&#34;Fit (lazy)&#34;, 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(&#34;Extracting lazy constraints...&#34;)
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(&#34;%8d lazy constraints extracted&#34; % len(self.pool))
logger.info(&#34;Predicting required lazy constraints...&#34;)
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] &gt; 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(
&#34;%8d lazy constraints added %8d in the pool&#34;
% (
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(&#34;Increasing gap tolerance to %f&#34;, 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(&#34;Restoring gap tolerance to %f&#34;, 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(&#34;Finding violated lazy constraints...&#34;)
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) &gt; 0:
logger.info(
&#34;%8d lazy constraints added %8d in the pool&#34;
% (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, &#34;found_violated_lazy_constraints&#34;)
]
logger.debug(&#34;Extracting x and y...&#34;)
x = self.x(training_instances)
y = self.y(training_instances)
logger.debug(&#34;Fitting...&#34;)
for category in tqdm(
x.keys(), desc=&#34;Fit (lazy)&#34;, 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(&#34;Extracting lazy constraints...&#34;)
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(&#34;%8d lazy constraints extracted&#34; % len(self.pool))
logger.info(&#34;Predicting required lazy constraints...&#34;)
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] &gt; 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(
&#34;%8d lazy constraints added %8d in the pool&#34;
% (
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, &#34;found_violated_lazy_constraints&#34;)
]
logger.debug(&#34;Extracting x and y...&#34;)
x = self.x(training_instances)
y = self.y(training_instances)
logger.debug(&#34;Fitting...&#34;)
for category in tqdm(
x.keys(), desc=&#34;Fit (lazy)&#34;, 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>

View 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):
&#34;&#34;&#34;
A Component which predicts the optimal objective value of the problem.
&#34;&#34;&#34;
def __init__(
self,
regressor: Regressor = LinearRegression(),
) -&gt; 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(&#34;Predicting optimal value...&#34;)
lb, ub = self.predict([instance])[0]
instance.predicted_ub = ub
instance.predicted_lb = lb
logger.info(&#34;Predicted values: lb=%.2f, ub=%.2f&#34; % (lb, ub))
def after_solve(
self,
solver,
instance,
model,
stats,
training_data,
):
if self.ub_regressor is not None:
stats[&#34;Predicted UB&#34;] = instance.predicted_ub
stats[&#34;Predicted LB&#34;] = instance.predicted_lb
else:
stats[&#34;Predicted UB&#34;] = None
stats[&#34;Predicted LB&#34;] = None
def fit(self, training_instances):
logger.debug(&#34;Extracting features...&#34;)
features = InstanceFeaturesExtractor().extract(training_instances)
ub = ObjectiveValueExtractor(kind=&#34;upper bound&#34;).extract(training_instances)
lb = ObjectiveValueExtractor(kind=&#34;lower bound&#34;).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(&#34;Fitting ub_regressor...&#34;)
self.ub_regressor.fit(features, ub.ravel())
logger.debug(&#34;Fitting ub_regressor...&#34;)
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][&#34;Lower bound&#34;],
inst.training_data[0][&#34;Upper bound&#34;],
]
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 = {
&#34;Lower bound&#34;: {
&#34;Mean squared error&#34;: mean_squared_error(y_true_lb, y_pred_lb),
&#34;Explained variance&#34;: explained_variance_score(y_true_lb, y_pred_lb),
&#34;Max error&#34;: max_error(y_true_lb, y_pred_lb),
&#34;Mean absolute error&#34;: mean_absolute_error(y_true_lb, y_pred_lb),
&#34;R2&#34;: r2_score(y_true_lb, y_pred_lb),
&#34;Median absolute error&#34;: mean_absolute_error(y_true_lb, y_pred_lb),
},
&#34;Upper bound&#34;: {
&#34;Mean squared error&#34;: mean_squared_error(y_true_ub, y_pred_ub),
&#34;Explained variance&#34;: explained_variance_score(y_true_ub, y_pred_ub),
&#34;Max error&#34;: max_error(y_true_ub, y_pred_ub),
&#34;Mean absolute error&#34;: mean_absolute_error(y_true_ub, y_pred_ub),
&#34;R2&#34;: r2_score(y_true_ub, y_pred_ub),
&#34;Median absolute error&#34;: 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):
&#34;&#34;&#34;
A Component which predicts the optimal objective value of the problem.
&#34;&#34;&#34;
def __init__(
self,
regressor: Regressor = LinearRegression(),
) -&gt; 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(&#34;Predicting optimal value...&#34;)
lb, ub = self.predict([instance])[0]
instance.predicted_ub = ub
instance.predicted_lb = lb
logger.info(&#34;Predicted values: lb=%.2f, ub=%.2f&#34; % (lb, ub))
def after_solve(
self,
solver,
instance,
model,
stats,
training_data,
):
if self.ub_regressor is not None:
stats[&#34;Predicted UB&#34;] = instance.predicted_ub
stats[&#34;Predicted LB&#34;] = instance.predicted_lb
else:
stats[&#34;Predicted UB&#34;] = None
stats[&#34;Predicted LB&#34;] = None
def fit(self, training_instances):
logger.debug(&#34;Extracting features...&#34;)
features = InstanceFeaturesExtractor().extract(training_instances)
ub = ObjectiveValueExtractor(kind=&#34;upper bound&#34;).extract(training_instances)
lb = ObjectiveValueExtractor(kind=&#34;lower bound&#34;).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(&#34;Fitting ub_regressor...&#34;)
self.ub_regressor.fit(features, ub.ravel())
logger.debug(&#34;Fitting ub_regressor...&#34;)
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][&#34;Lower bound&#34;],
inst.training_data[0][&#34;Upper bound&#34;],
]
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 = {
&#34;Lower bound&#34;: {
&#34;Mean squared error&#34;: mean_squared_error(y_true_lb, y_pred_lb),
&#34;Explained variance&#34;: explained_variance_score(y_true_lb, y_pred_lb),
&#34;Max error&#34;: max_error(y_true_lb, y_pred_lb),
&#34;Mean absolute error&#34;: mean_absolute_error(y_true_lb, y_pred_lb),
&#34;R2&#34;: r2_score(y_true_lb, y_pred_lb),
&#34;Median absolute error&#34;: mean_absolute_error(y_true_lb, y_pred_lb),
},
&#34;Upper bound&#34;: {
&#34;Mean squared error&#34;: mean_squared_error(y_true_ub, y_pred_ub),
&#34;Explained variance&#34;: explained_variance_score(y_true_ub, y_pred_ub),
&#34;Max error&#34;: max_error(y_true_ub, y_pred_ub),
&#34;Mean absolute error&#34;: mean_absolute_error(y_true_ub, y_pred_ub),
&#34;R2&#34;: r2_score(y_true_ub, y_pred_ub),
&#34;Median absolute error&#34;: 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][&#34;Lower bound&#34;],
inst.training_data[0][&#34;Upper bound&#34;],
]
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 = {
&#34;Lower bound&#34;: {
&#34;Mean squared error&#34;: mean_squared_error(y_true_lb, y_pred_lb),
&#34;Explained variance&#34;: explained_variance_score(y_true_lb, y_pred_lb),
&#34;Max error&#34;: max_error(y_true_lb, y_pred_lb),
&#34;Mean absolute error&#34;: mean_absolute_error(y_true_lb, y_pred_lb),
&#34;R2&#34;: r2_score(y_true_lb, y_pred_lb),
&#34;Median absolute error&#34;: mean_absolute_error(y_true_lb, y_pred_lb),
},
&#34;Upper bound&#34;: {
&#34;Mean squared error&#34;: mean_squared_error(y_true_ub, y_pred_ub),
&#34;Explained variance&#34;: explained_variance_score(y_true_ub, y_pred_ub),
&#34;Max error&#34;: max_error(y_true_ub, y_pred_ub),
&#34;Mean absolute error&#34;: mean_absolute_error(y_true_ub, y_pred_ub),
&#34;R2&#34;: r2_score(y_true_ub, y_pred_ub),
&#34;Median absolute error&#34;: 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(&#34;Extracting features...&#34;)
features = InstanceFeaturesExtractor().extract(training_instances)
ub = ObjectiveValueExtractor(kind=&#34;upper bound&#34;).extract(training_instances)
lb = ObjectiveValueExtractor(kind=&#34;lower bound&#34;).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(&#34;Fitting ub_regressor...&#34;)
self.ub_regressor.fit(features, ub.ravel())
logger.debug(&#34;Fitting ub_regressor...&#34;)
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>

View 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):
&#34;&#34;&#34;
A component that predicts primal solutions.
&#34;&#34;&#34;
def __init__(
self,
classifier: Classifier = AdaptiveClassifier(),
mode: str = &#34;exact&#34;,
threshold: Union[float, DynamicThreshold] = MinPrecisionThreshold(0.98),
) -&gt; 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(&#34;Predicting primal solution...&#34;)
solution = self.predict(instance)
if self.mode == &#34;heuristic&#34;:
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(&#34;Extracting features...&#34;)
features = VariableFeaturesExtractor().extract(training_instances)
solutions = SolutionExtractor().extract(training_instances)
for category in tqdm(
features.keys(),
desc=&#34;Fit (primal)&#34;,
):
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 &lt; 0.001 or y_avg &gt;= 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), &#34;ws.shape should be (%d, 2) not %s&#34; % (
n,
ws.shape,
)
for (i, (var, index)) in enumerate(var_split[category]):
if ws[i, 1] &gt;= self.thresholds[category, label]:
solution[var][index] = label
return solution
def evaluate(self, instances):
ev = {&#34;Fix zero&#34;: {}, &#34;Fix one&#34;: {}}
for instance_idx in tqdm(
range(len(instances)),
desc=&#34;Evaluate (primal)&#34;,
):
instance = instances[instance_idx]
solution_actual = instance.training_data[0][&#34;Solution&#34;]
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 &gt; 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] &gt; 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 &amp; vars_zero)
fp_zero = len(pred_zero_positive &amp; vars_one)
tn_zero = len(pred_zero_negative &amp; vars_one)
fn_zero = len(pred_zero_negative &amp; vars_zero)
tp_one = len(pred_one_positive &amp; vars_one)
fp_one = len(pred_one_positive &amp; vars_zero)
tn_one = len(pred_one_negative &amp; vars_zero)
fn_one = len(pred_one_negative &amp; vars_one)
ev[&#34;Fix zero&#34;][instance_idx] = classifier_evaluation_dict(
tp_zero, tn_zero, fp_zero, fn_zero
)
ev[&#34;Fix one&#34;][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):
&#34;&#34;&#34;
A component that predicts primal solutions.
&#34;&#34;&#34;
def __init__(
self,
classifier: Classifier = AdaptiveClassifier(),
mode: str = &#34;exact&#34;,
threshold: Union[float, DynamicThreshold] = MinPrecisionThreshold(0.98),
) -&gt; 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(&#34;Predicting primal solution...&#34;)
solution = self.predict(instance)
if self.mode == &#34;heuristic&#34;:
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(&#34;Extracting features...&#34;)
features = VariableFeaturesExtractor().extract(training_instances)
solutions = SolutionExtractor().extract(training_instances)
for category in tqdm(
features.keys(),
desc=&#34;Fit (primal)&#34;,
):
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 &lt; 0.001 or y_avg &gt;= 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), &#34;ws.shape should be (%d, 2) not %s&#34; % (
n,
ws.shape,
)
for (i, (var, index)) in enumerate(var_split[category]):
if ws[i, 1] &gt;= self.thresholds[category, label]:
solution[var][index] = label
return solution
def evaluate(self, instances):
ev = {&#34;Fix zero&#34;: {}, &#34;Fix one&#34;: {}}
for instance_idx in tqdm(
range(len(instances)),
desc=&#34;Evaluate (primal)&#34;,
):
instance = instances[instance_idx]
solution_actual = instance.training_data[0][&#34;Solution&#34;]
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 &gt; 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] &gt; 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 &amp; vars_zero)
fp_zero = len(pred_zero_positive &amp; vars_one)
tn_zero = len(pred_zero_negative &amp; vars_one)
fn_zero = len(pred_zero_negative &amp; vars_zero)
tp_one = len(pred_one_positive &amp; vars_one)
fp_one = len(pred_one_positive &amp; vars_zero)
tn_one = len(pred_one_negative &amp; vars_zero)
fn_one = len(pred_one_negative &amp; vars_one)
ev[&#34;Fix zero&#34;][instance_idx] = classifier_evaluation_dict(
tp_zero, tn_zero, fp_zero, fn_zero
)
ev[&#34;Fix one&#34;][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 = {&#34;Fix zero&#34;: {}, &#34;Fix one&#34;: {}}
for instance_idx in tqdm(
range(len(instances)),
desc=&#34;Evaluate (primal)&#34;,
):
instance = instances[instance_idx]
solution_actual = instance.training_data[0][&#34;Solution&#34;]
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 &gt; 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] &gt; 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 &amp; vars_zero)
fp_zero = len(pred_zero_positive &amp; vars_one)
tn_zero = len(pred_zero_negative &amp; vars_one)
fn_zero = len(pred_zero_negative &amp; vars_zero)
tp_one = len(pred_one_positive &amp; vars_one)
fp_one = len(pred_one_positive &amp; vars_zero)
tn_one = len(pred_one_negative &amp; vars_zero)
fn_one = len(pred_one_negative &amp; vars_one)
ev[&#34;Fix zero&#34;][instance_idx] = classifier_evaluation_dict(
tp_zero, tn_zero, fp_zero, fn_zero
)
ev[&#34;Fix one&#34;][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(&#34;Extracting features...&#34;)
features = VariableFeaturesExtractor().extract(training_instances)
solutions = SolutionExtractor().extract(training_instances)
for category in tqdm(
features.keys(),
desc=&#34;Fit (primal)&#34;,
):
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 &lt; 0.001 or y_avg &gt;= 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), &#34;ws.shape should be (%d, 2) not %s&#34; % (
n,
ws.shape,
)
for (i, (var, index)) in enumerate(var_split[category]):
if ws[i, 1] &gt;= 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>

View 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):
&#34;&#34;&#34;
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.
&#34;&#34;&#34;
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> :&ensp;<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> :&ensp;<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> :&ensp;<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> :&ensp;<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> :&ensp;<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> :&ensp;<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> :&ensp;<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> :&ensp;<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):
&#34;&#34;&#34;
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.
&#34;&#34;&#34;
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>

View 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):
&#34;&#34;&#34;
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.
&#34;&#34;&#34;
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(&#34;Predicting tight LP constraints...&#34;)
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, &#34;=&#34;)
self.converted += [cid]
self.n_converted += 1
else:
self.n_kept += 1
logger.info(f&#34;Converted {self.n_converted} inequalities&#34;)
def after_solve(
self,
solver,
instance,
model,
stats,
training_data,
):
if &#34;slacks&#34; not in training_data.keys():
training_data[&#34;slacks&#34;] = solver.internal_solver.get_inequality_slacks()
stats[&#34;ConvertTight: Kept&#34;] = self.n_kept
stats[&#34;ConvertTight: Converted&#34;] = self.n_converted
stats[&#34;ConvertTight: Restored&#34;] = self.n_restored
stats[&#34;ConvertTight: Inf iterations&#34;] = self.n_infeasible_iterations
stats[&#34;ConvertTight: Subopt iterations&#34;] = self.n_suboptimal_iterations
def fit(self, training_instances):
logger.debug(&#34;Extracting x and y...&#34;)
x = self.x(training_instances)
y = self.y(training_instances)
logger.debug(&#34;Fitting...&#34;)
for category in tqdm(x.keys(), desc=&#34;Fit (rlx:conv_ineqs)&#34;):
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=&#34;Extract (rlx:conv_ineqs:y)&#34;,
disable=len(instances) &lt; 5,
):
for (cid, slack) in instance.training_data[0][&#34;slacks&#34;].items():
category = instance.get_constraint_category(cid)
if category is None:
continue
if category not in y:
y[category] = []
if 0 &lt;= slack &lt;= 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] &gt;= 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 == &#34;=&#34;:
return True
if msense == &#34;max&#34;:
if csense == &#34;&lt;&#34;:
return pi &gt;= 0
else:
return pi &lt;= 0
else:
if csense == &#34;&gt;&#34;:
return pi &gt;= 0
else:
return pi &lt;= 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) &gt; 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 &gt;= 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) &gt; 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&#34;Restored {len(restored)} inequalities&#34;)
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):
&#34;&#34;&#34;
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.
&#34;&#34;&#34;
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(&#34;Predicting tight LP constraints...&#34;)
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, &#34;=&#34;)
self.converted += [cid]
self.n_converted += 1
else:
self.n_kept += 1
logger.info(f&#34;Converted {self.n_converted} inequalities&#34;)
def after_solve(
self,
solver,
instance,
model,
stats,
training_data,
):
if &#34;slacks&#34; not in training_data.keys():
training_data[&#34;slacks&#34;] = solver.internal_solver.get_inequality_slacks()
stats[&#34;ConvertTight: Kept&#34;] = self.n_kept
stats[&#34;ConvertTight: Converted&#34;] = self.n_converted
stats[&#34;ConvertTight: Restored&#34;] = self.n_restored
stats[&#34;ConvertTight: Inf iterations&#34;] = self.n_infeasible_iterations
stats[&#34;ConvertTight: Subopt iterations&#34;] = self.n_suboptimal_iterations
def fit(self, training_instances):
logger.debug(&#34;Extracting x and y...&#34;)
x = self.x(training_instances)
y = self.y(training_instances)
logger.debug(&#34;Fitting...&#34;)
for category in tqdm(x.keys(), desc=&#34;Fit (rlx:conv_ineqs)&#34;):
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=&#34;Extract (rlx:conv_ineqs:y)&#34;,
disable=len(instances) &lt; 5,
):
for (cid, slack) in instance.training_data[0][&#34;slacks&#34;].items():
category = instance.get_constraint_category(cid)
if category is None:
continue
if category not in y:
y[category] = []
if 0 &lt;= slack &lt;= 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] &gt;= 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 == &#34;=&#34;:
return True
if msense == &#34;max&#34;:
if csense == &#34;&lt;&#34;:
return pi &gt;= 0
else:
return pi &lt;= 0
else:
if csense == &#34;&gt;&#34;:
return pi &gt;= 0
else:
return pi &lt;= 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) &gt; 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 &gt;= 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) &gt; 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&#34;Restored {len(restored)} inequalities&#34;)
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(&#34;Extracting x and y...&#34;)
x = self.x(training_instances)
y = self.y(training_instances)
logger.debug(&#34;Fitting...&#34;)
for category in tqdm(x.keys(), desc=&#34;Fit (rlx:conv_ineqs)&#34;):
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] &gt;= 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=&#34;Extract (rlx:conv_ineqs:y)&#34;,
disable=len(instances) &lt; 5,
):
for (cid, slack) in instance.training_data[0][&#34;slacks&#34;].items():
category = instance.get_constraint_category(cid)
if category is None:
continue
if category not in y:
y[category] = []
if 0 &lt;= slack &lt;= 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>

View 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):
&#34;&#34;&#34;
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.
&#34;&#34;&#34;
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(&#34;Predicting redundant LP constraints...&#34;)
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&#34;Extracted {self.total_dropped} predicted constraints&#34;)
def after_solve(
self,
solver,
instance,
model,
stats,
training_data,
):
if &#34;slacks&#34; not in training_data.keys():
training_data[&#34;slacks&#34;] = solver.internal_solver.get_inequality_slacks()
stats.update(
{
&#34;DropRedundant: Kept&#34;: self.total_kept,
&#34;DropRedundant: Dropped&#34;: self.total_dropped,
&#34;DropRedundant: Restored&#34;: self.total_restored,
&#34;DropRedundant: Iterations&#34;: self.total_iterations,
}
)
def fit(self, training_instances):
logger.debug(&#34;Extracting x and y...&#34;)
x = self.x(training_instances)
y = self.y(training_instances)
logger.debug(&#34;Fitting...&#34;)
for category in tqdm(x.keys(), desc=&#34;Fit (rlx:drop_ineq)&#34;):
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=&#34;Extract (rlx:drop_ineq:x)&#34;,
disable=len(instances) &lt; 5,
):
for training_data in instance.training_data:
cids = training_data[&#34;slacks&#34;].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=&#34;Extract (rlx:drop_ineq:y)&#34;,
disable=len(instances) &lt; 5,
):
for training_data in instance.training_data:
for (cid, slack) in training_data[&#34;slacks&#34;].items():
category = instance.get_constraint_category(cid)
if category is None:
continue
if category not in y:
y[category] = []
if slack &gt; 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] &gt;= 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 &gt;= self.max_iterations:
return False
self.current_iteration += 1
logger.debug(&#34;Checking that dropped constraints are satisfied...&#34;)
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) &gt; 0:
self.total_restored += len(constraints_to_add)
logger.info(
&#34;%8d constraints %8d in the pool&#34;
% (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):
&#34;&#34;&#34;
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.
&#34;&#34;&#34;
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(&#34;Predicting redundant LP constraints...&#34;)
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&#34;Extracted {self.total_dropped} predicted constraints&#34;)
def after_solve(
self,
solver,
instance,
model,
stats,
training_data,
):
if &#34;slacks&#34; not in training_data.keys():
training_data[&#34;slacks&#34;] = solver.internal_solver.get_inequality_slacks()
stats.update(
{
&#34;DropRedundant: Kept&#34;: self.total_kept,
&#34;DropRedundant: Dropped&#34;: self.total_dropped,
&#34;DropRedundant: Restored&#34;: self.total_restored,
&#34;DropRedundant: Iterations&#34;: self.total_iterations,
}
)
def fit(self, training_instances):
logger.debug(&#34;Extracting x and y...&#34;)
x = self.x(training_instances)
y = self.y(training_instances)
logger.debug(&#34;Fitting...&#34;)
for category in tqdm(x.keys(), desc=&#34;Fit (rlx:drop_ineq)&#34;):
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=&#34;Extract (rlx:drop_ineq:x)&#34;,
disable=len(instances) &lt; 5,
):
for training_data in instance.training_data:
cids = training_data[&#34;slacks&#34;].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=&#34;Extract (rlx:drop_ineq:y)&#34;,
disable=len(instances) &lt; 5,
):
for training_data in instance.training_data:
for (cid, slack) in training_data[&#34;slacks&#34;].items():
category = instance.get_constraint_category(cid)
if category is None:
continue
if category not in y:
y[category] = []
if slack &gt; 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] &gt;= 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 &gt;= self.max_iterations:
return False
self.current_iteration += 1
logger.debug(&#34;Checking that dropped constraints are satisfied...&#34;)
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) &gt; 0:
self.total_restored += len(constraints_to_add)
logger.info(
&#34;%8d constraints %8d in the pool&#34;
% (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(&#34;Extracting x and y...&#34;)
x = self.x(training_instances)
y = self.y(training_instances)
logger.debug(&#34;Fitting...&#34;)
for category in tqdm(x.keys(), desc=&#34;Fit (rlx:drop_ineq)&#34;):
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] &gt;= 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=&#34;Extract (rlx:drop_ineq:y)&#34;,
disable=len(instances) &lt; 5,
):
for training_data in instance.training_data:
for (cid, slack) in training_data[&#34;slacks&#34;].items():
category = instance.get_constraint_category(cid)
if category is None:
continue
if category not in y:
y[category] = []
if slack &gt; 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>

View 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>

View 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):
&#34;&#34;&#34;
Component that relaxes all integrality constraints before the problem is solved.
&#34;&#34;&#34;
def before_solve(self, solver, instance, _):
logger.info(&#34;Relaxing integrality...&#34;)
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):
&#34;&#34;&#34;
Component that relaxes all integrality constraints before the problem is solved.
&#34;&#34;&#34;
def before_solve(self, solver, instance, _):
logger.info(&#34;Relaxing integrality...&#34;)
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>

View 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>

View 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[&#34;Upper bound&#34;]
# Should collect training data
assert instance.training_data[0][&#34;slacks&#34;][&#34;eq_capacity&#34;] == 0.0
# Fit and resolve
solver.fit([instance])
stats = solver.solve(instance)
# Objective value should be the same
assert stats[&#34;Upper bound&#34;] == original_upper_bound
assert stats[&#34;ConvertTight: Inf iterations&#34;] == 0
assert stats[&#34;ConvertTight: Subopt iterations&#34;] == 0
class SampleInstance(Instance):
def to_model(self):
import gurobipy as grb
m = grb.Model(&#34;model&#34;)
x1 = m.addVar(name=&#34;x1&#34;)
x2 = m.addVar(name=&#34;x2&#34;)
m.setObjective(x1 + 2 * x2, grb.GRB.MAXIMIZE)
m.addConstr(x1 &lt;= 2, name=&#34;c1&#34;)
m.addConstr(x2 &lt;= 2, name=&#34;c2&#34;)
m.addConstr(x1 + x2 &lt;= 3, name=&#34;c2&#34;)
return m
def test_convert_tight_infeasibility():
comp = ConvertTightIneqsIntoEqsStep()
comp.classifiers = {
&#34;c1&#34;: Mock(spec=Classifier),
&#34;c2&#34;: Mock(spec=Classifier),
&#34;c3&#34;: Mock(spec=Classifier),
}
comp.classifiers[&#34;c1&#34;].predict_proba = Mock(return_value=[[0, 1]])
comp.classifiers[&#34;c2&#34;].predict_proba = Mock(return_value=[[0, 1]])
comp.classifiers[&#34;c3&#34;].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[&#34;Upper bound&#34;] == 5.0
assert stats[&#34;ConvertTight: Inf iterations&#34;] == 1
assert stats[&#34;ConvertTight: Subopt iterations&#34;] == 0
def test_convert_tight_suboptimality():
comp = ConvertTightIneqsIntoEqsStep(check_optimality=True)
comp.classifiers = {
&#34;c1&#34;: Mock(spec=Classifier),
&#34;c2&#34;: Mock(spec=Classifier),
&#34;c3&#34;: Mock(spec=Classifier),
}
comp.classifiers[&#34;c1&#34;].predict_proba = Mock(return_value=[[0, 1]])
comp.classifiers[&#34;c2&#34;].predict_proba = Mock(return_value=[[1, 0]])
comp.classifiers[&#34;c3&#34;].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[&#34;Upper bound&#34;] == 5.0
assert stats[&#34;ConvertTight: Inf iterations&#34;] == 0
assert stats[&#34;ConvertTight: Subopt iterations&#34;] == 1
def test_convert_tight_optimal():
comp = ConvertTightIneqsIntoEqsStep()
comp.classifiers = {
&#34;c1&#34;: Mock(spec=Classifier),
&#34;c2&#34;: Mock(spec=Classifier),
&#34;c3&#34;: Mock(spec=Classifier),
}
comp.classifiers[&#34;c1&#34;].predict_proba = Mock(return_value=[[1, 0]])
comp.classifiers[&#34;c2&#34;].predict_proba = Mock(return_value=[[0, 1]])
comp.classifiers[&#34;c3&#34;].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[&#34;Upper bound&#34;] == 5.0
assert stats[&#34;ConvertTight: Inf iterations&#34;] == 0
assert stats[&#34;ConvertTight: Subopt iterations&#34;] == 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 = {
&#34;c1&#34;: Mock(spec=Classifier),
&#34;c2&#34;: Mock(spec=Classifier),
&#34;c3&#34;: Mock(spec=Classifier),
}
comp.classifiers[&#34;c1&#34;].predict_proba = Mock(return_value=[[0, 1]])
comp.classifiers[&#34;c2&#34;].predict_proba = Mock(return_value=[[0, 1]])
comp.classifiers[&#34;c3&#34;].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[&#34;Upper bound&#34;] == 5.0
assert stats[&#34;ConvertTight: Inf iterations&#34;] == 1
assert stats[&#34;ConvertTight: Subopt iterations&#34;] == 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 = {
&#34;c1&#34;: Mock(spec=Classifier),
&#34;c2&#34;: Mock(spec=Classifier),
&#34;c3&#34;: Mock(spec=Classifier),
}
comp.classifiers[&#34;c1&#34;].predict_proba = Mock(return_value=[[1, 0]])
comp.classifiers[&#34;c2&#34;].predict_proba = Mock(return_value=[[0, 1]])
comp.classifiers[&#34;c3&#34;].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[&#34;Upper bound&#34;] == 5.0
assert stats[&#34;ConvertTight: Inf iterations&#34;] == 0
assert stats[&#34;ConvertTight: Subopt iterations&#34;] == 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 = {
&#34;c1&#34;: Mock(spec=Classifier),
&#34;c2&#34;: Mock(spec=Classifier),
&#34;c3&#34;: Mock(spec=Classifier),
}
comp.classifiers[&#34;c1&#34;].predict_proba = Mock(return_value=[[0, 1]])
comp.classifiers[&#34;c2&#34;].predict_proba = Mock(return_value=[[1, 0]])
comp.classifiers[&#34;c3&#34;].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[&#34;Upper bound&#34;] == 5.0
assert stats[&#34;ConvertTight: Inf iterations&#34;] == 0
assert stats[&#34;ConvertTight: Subopt iterations&#34;] == 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[&#34;Upper bound&#34;]
# Should collect training data
assert instance.training_data[0][&#34;slacks&#34;][&#34;eq_capacity&#34;] == 0.0
# Fit and resolve
solver.fit([instance])
stats = solver.solve(instance)
# Objective value should be the same
assert stats[&#34;Upper bound&#34;] == original_upper_bound
assert stats[&#34;ConvertTight: Inf iterations&#34;] == 0
assert stats[&#34;ConvertTight: Subopt iterations&#34;] == 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(&#34;model&#34;)
x1 = m.addVar(name=&#34;x1&#34;)
x2 = m.addVar(name=&#34;x2&#34;)
m.setObjective(x1 + 2 * x2, grb.GRB.MAXIMIZE)
m.addConstr(x1 &lt;= 2, name=&#34;c1&#34;)
m.addConstr(x2 &lt;= 2, name=&#34;c2&#34;)
m.addConstr(x1 + x2 &lt;= 3, name=&#34;c2&#34;)
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>

View 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=[&#34;c1&#34;, &#34;c2&#34;, &#34;c3&#34;, &#34;c4&#34;])
internal.get_inequality_slacks = Mock(
side_effect=lambda: {
&#34;c1&#34;: 0.5,
&#34;c2&#34;: 0.0,
&#34;c3&#34;: 0.0,
&#34;c4&#34;: 1.4,
}
)
internal.extract_constraint = Mock(side_effect=lambda cid: &#34;&lt;%s&gt;&#34; % cid)
internal.is_constraint_satisfied = Mock(return_value=False)
instance = Mock(spec=Instance)
instance.get_constraint_features = Mock(
side_effect=lambda cid: {
&#34;c2&#34;: np.array([1.0, 0.0]),
&#34;c3&#34;: np.array([0.5, 0.5]),
&#34;c4&#34;: np.array([1.0]),
}[cid]
)
instance.get_constraint_category = Mock(
side_effect=lambda cid: {
&#34;c1&#34;: None,
&#34;c2&#34;: &#34;type-a&#34;,
&#34;c3&#34;: &#34;type-a&#34;,
&#34;c4&#34;: &#34;type-b&#34;,
}[cid]
)
classifiers = {
&#34;type-a&#34;: Mock(spec=Classifier),
&#34;type-b&#34;: Mock(spec=Classifier),
}
classifiers[&#34;type-a&#34;].predict_proba = Mock(
return_value=np.array(
[
[0.20, 0.80],
[0.05, 0.95],
]
)
)
classifiers[&#34;type-b&#34;].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(&#34;c1&#34;),
call(&#34;c2&#34;),
call(&#34;c3&#34;),
call(&#34;c4&#34;),
]
)
# 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(&#34;c2&#34;),
call(&#34;c3&#34;),
call(&#34;c4&#34;),
]
)
# Should ask ML to predict whether constraint should be removed
type_a_actual = component.classifiers[&#34;type-a&#34;].predict_proba.call_args[0][0]
type_b_actual = component.classifiers[&#34;type-b&#34;].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(&#34;c3&#34;),
call(&#34;c4&#34;),
]
)
# 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[&#34;slacks&#34;] == {
&#34;c1&#34;: 0.5,
&#34;c2&#34;: 0.0,
&#34;c3&#34;: 0.0,
&#34;c4&#34;: 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(&#34;c3&#34;),
call(&#34;c4&#34;),
]
)
# 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(&#34;&lt;c3&gt;&#34;, 1e-3),
call(&#34;&lt;c4&gt;&#34;, 1e-3),
]
)
# Should add constraints back to LP relaxation
internal.add_constraint.assert_has_calls([call(&#34;&lt;c3&gt;&#34;), call(&#34;&lt;c4&gt;&#34;)])
# 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 = {
&#34;type-a&#34;: Mock(spec=Classifier),
&#34;type-b&#34;: Mock(spec=Classifier),
}
component.classifiers[&#34;type-a&#34;].predict_proba = Mock(
return_value=[
np.array([0.20, 0.80]),
]
)
component.classifiers[&#34;type-b&#34;].predict_proba = Mock(
return_value=np.array(
[
[0.50, 0.50],
[0.05, 0.95],
]
)
)
# First mock instance
instances[0].training_data = [
{
&#34;slacks&#34;: {
&#34;c1&#34;: 0.00,
&#34;c2&#34;: 0.05,
&#34;c3&#34;: 0.00,
&#34;c4&#34;: 30.0,
}
}
]
instances[0].get_constraint_category = Mock(
side_effect=lambda cid: {
&#34;c1&#34;: None,
&#34;c2&#34;: &#34;type-a&#34;,
&#34;c3&#34;: &#34;type-a&#34;,
&#34;c4&#34;: &#34;type-b&#34;,
}[cid]
)
instances[0].get_constraint_features = Mock(
side_effect=lambda cid: {
&#34;c2&#34;: np.array([1.0, 0.0]),
&#34;c3&#34;: np.array([0.5, 0.5]),
&#34;c4&#34;: np.array([1.0]),
}[cid]
)
# Second mock instance
instances[1].training_data = [
{
&#34;slacks&#34;: {
&#34;c1&#34;: 0.00,
&#34;c3&#34;: 0.30,
&#34;c4&#34;: 0.00,
&#34;c5&#34;: 0.00,
}
}
]
instances[1].get_constraint_category = Mock(
side_effect=lambda cid: {
&#34;c1&#34;: None,
&#34;c3&#34;: &#34;type-a&#34;,
&#34;c4&#34;: &#34;type-b&#34;,
&#34;c5&#34;: &#34;type-b&#34;,
}[cid]
)
instances[1].get_constraint_features = Mock(
side_effect=lambda cid: {
&#34;c3&#34;: np.array([0.3, 0.4]),
&#34;c4&#34;: np.array([0.7]),
&#34;c5&#34;: np.array([0.8]),
}[cid]
)
expected_x = {
&#34;type-a&#34;: np.array(
[
[1.0, 0.0],
[0.5, 0.5],
[0.3, 0.4],
]
),
&#34;type-b&#34;: np.array(
[
[1.0],
[0.7],
[0.8],
]
),
}
expected_y = {
&#34;type-a&#34;: np.array([[0], [0], [1]]),
&#34;type-b&#34;: 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 [&#34;type-a&#34;, &#34;type-b&#34;]:
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 [&#34;type-a&#34;, &#34;type-b&#34;]:
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) == {&#34;type-a&#34;: [[1]], &#34;type-b&#34;: [[0], [1]]}
ev = component.evaluate(instances[1])
assert ev[&#34;True positive&#34;] == 1
assert ev[&#34;True negative&#34;] == 1
assert ev[&#34;False positive&#34;] == 1
assert ev[&#34;False negative&#34;] == 0
def test_x_multiple_solves():
instance = Mock(spec=Instance)
instance.training_data = [
{
&#34;slacks&#34;: {
&#34;c1&#34;: 0.00,
&#34;c2&#34;: 0.05,
&#34;c3&#34;: 0.00,
&#34;c4&#34;: 30.0,
}
},
{
&#34;slacks&#34;: {
&#34;c1&#34;: 0.00,
&#34;c2&#34;: 0.00,
&#34;c3&#34;: 1.00,
&#34;c4&#34;: 0.0,
}
},
]
instance.get_constraint_category = Mock(
side_effect=lambda cid: {
&#34;c1&#34;: None,
&#34;c2&#34;: &#34;type-a&#34;,
&#34;c3&#34;: &#34;type-a&#34;,
&#34;c4&#34;: &#34;type-b&#34;,
}[cid]
)
instance.get_constraint_features = Mock(
side_effect=lambda cid: {
&#34;c2&#34;: np.array([1.0, 0.0]),
&#34;c3&#34;: np.array([0.5, 0.5]),
&#34;c4&#34;: np.array([1.0]),
}[cid]
)
expected_x = {
&#34;type-a&#34;: np.array(
[
[1.0, 0.0],
[0.5, 0.5],
[1.0, 0.0],
[0.5, 0.5],
]
),
&#34;type-b&#34;: np.array(
[
[1.0],
[1.0],
]
),
}
expected_y = {
&#34;type-a&#34;: np.array([[1], [0], [0], [1]]),
&#34;type-b&#34;: 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 [&#34;type-a&#34;, &#34;type-b&#34;]:
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(&#34;c1&#34;),
call(&#34;c2&#34;),
call(&#34;c3&#34;),
call(&#34;c4&#34;),
]
)
# 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(&#34;c2&#34;),
call(&#34;c3&#34;),
call(&#34;c4&#34;),
]
)
# Should ask ML to predict whether constraint should be removed
type_a_actual = component.classifiers[&#34;type-a&#34;].predict_proba.call_args[0][0]
type_b_actual = component.classifiers[&#34;type-b&#34;].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(&#34;c3&#34;),
call(&#34;c4&#34;),
]
)
# 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[&#34;slacks&#34;] == {
&#34;c1&#34;: 0.5,
&#34;c2&#34;: 0.0,
&#34;c3&#34;: 0.0,
&#34;c4&#34;: 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(&#34;c3&#34;),
call(&#34;c4&#34;),
]
)
# 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(&#34;&lt;c3&gt;&#34;, 1e-3),
call(&#34;&lt;c4&gt;&#34;, 1e-3),
]
)
# Should add constraints back to LP relaxation
internal.add_constraint.assert_has_calls([call(&#34;&lt;c3&gt;&#34;), call(&#34;&lt;c4&gt;&#34;)])
# 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 = [
{
&#34;slacks&#34;: {
&#34;c1&#34;: 0.00,
&#34;c2&#34;: 0.05,
&#34;c3&#34;: 0.00,
&#34;c4&#34;: 30.0,
}
},
{
&#34;slacks&#34;: {
&#34;c1&#34;: 0.00,
&#34;c2&#34;: 0.00,
&#34;c3&#34;: 1.00,
&#34;c4&#34;: 0.0,
}
},
]
instance.get_constraint_category = Mock(
side_effect=lambda cid: {
&#34;c1&#34;: None,
&#34;c2&#34;: &#34;type-a&#34;,
&#34;c3&#34;: &#34;type-a&#34;,
&#34;c4&#34;: &#34;type-b&#34;,
}[cid]
)
instance.get_constraint_features = Mock(
side_effect=lambda cid: {
&#34;c2&#34;: np.array([1.0, 0.0]),
&#34;c3&#34;: np.array([0.5, 0.5]),
&#34;c4&#34;: np.array([1.0]),
}[cid]
)
expected_x = {
&#34;type-a&#34;: np.array(
[
[1.0, 0.0],
[0.5, 0.5],
[1.0, 0.0],
[0.5, 0.5],
]
),
&#34;type-b&#34;: np.array(
[
[1.0],
[1.0],
]
),
}
expected_y = {
&#34;type-a&#34;: np.array([[1], [0], [0], [1]]),
&#34;type-b&#34;: 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 [&#34;type-a&#34;, &#34;type-b&#34;]:
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 = {
&#34;type-a&#34;: Mock(spec=Classifier),
&#34;type-b&#34;: Mock(spec=Classifier),
}
component.classifiers[&#34;type-a&#34;].predict_proba = Mock(
return_value=[
np.array([0.20, 0.80]),
]
)
component.classifiers[&#34;type-b&#34;].predict_proba = Mock(
return_value=np.array(
[
[0.50, 0.50],
[0.05, 0.95],
]
)
)
# First mock instance
instances[0].training_data = [
{
&#34;slacks&#34;: {
&#34;c1&#34;: 0.00,
&#34;c2&#34;: 0.05,
&#34;c3&#34;: 0.00,
&#34;c4&#34;: 30.0,
}
}
]
instances[0].get_constraint_category = Mock(
side_effect=lambda cid: {
&#34;c1&#34;: None,
&#34;c2&#34;: &#34;type-a&#34;,
&#34;c3&#34;: &#34;type-a&#34;,
&#34;c4&#34;: &#34;type-b&#34;,
}[cid]
)
instances[0].get_constraint_features = Mock(
side_effect=lambda cid: {
&#34;c2&#34;: np.array([1.0, 0.0]),
&#34;c3&#34;: np.array([0.5, 0.5]),
&#34;c4&#34;: np.array([1.0]),
}[cid]
)
# Second mock instance
instances[1].training_data = [
{
&#34;slacks&#34;: {
&#34;c1&#34;: 0.00,
&#34;c3&#34;: 0.30,
&#34;c4&#34;: 0.00,
&#34;c5&#34;: 0.00,
}
}
]
instances[1].get_constraint_category = Mock(
side_effect=lambda cid: {
&#34;c1&#34;: None,
&#34;c3&#34;: &#34;type-a&#34;,
&#34;c4&#34;: &#34;type-b&#34;,
&#34;c5&#34;: &#34;type-b&#34;,
}[cid]
)
instances[1].get_constraint_features = Mock(
side_effect=lambda cid: {
&#34;c3&#34;: np.array([0.3, 0.4]),
&#34;c4&#34;: np.array([0.7]),
&#34;c5&#34;: np.array([0.8]),
}[cid]
)
expected_x = {
&#34;type-a&#34;: np.array(
[
[1.0, 0.0],
[0.5, 0.5],
[0.3, 0.4],
]
),
&#34;type-b&#34;: np.array(
[
[1.0],
[0.7],
[0.8],
]
),
}
expected_y = {
&#34;type-a&#34;: np.array([[0], [0], [1]]),
&#34;type-b&#34;: 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 [&#34;type-a&#34;, &#34;type-b&#34;]:
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 [&#34;type-a&#34;, &#34;type-b&#34;]:
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) == {&#34;type-a&#34;: [[1]], &#34;type-b&#34;: [[0], [1]]}
ev = component.evaluate(instances[1])
assert ev[&#34;True positive&#34;] == 1
assert ev[&#34;True negative&#34;] == 1
assert ev[&#34;False positive&#34;] == 1
assert ev[&#34;False negative&#34;] == 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>

View 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>

View 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>

View File

@@ -0,0 +1,365 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<meta name="generator" content="pdoc 0.7.0" />
<title>miplearn.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 = [&#34;a&#34;, &#34;b&#34;]
instances[1].found_violated_lazy_constraints = [&#34;b&#34;, &#34;c&#34;]
classifier = Mock(spec=Classifier)
component = DynamicLazyConstraintsComponent(classifier=classifier)
component.fit(instances)
# Should create one classifier for each violation
assert &#34;a&#34; in component.classifiers
assert &#34;b&#34; in component.classifiers
assert &#34;c&#34; 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[&#34;a&#34;].fit.call_args[0][0]
actual_x_train_b = component.classifiers[&#34;b&#34;].fit.call_args[0][0]
actual_x_train_c = component.classifiers[&#34;c&#34;].fit.call_args[0][0]
assert norm(expected_x_train_a - actual_x_train_a) &lt; E
assert norm(expected_x_train_b - actual_x_train_b) &lt; E
assert norm(expected_x_train_c - actual_x_train_c) &lt; 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[&#34;a&#34;].fit.call_args[0][1]
actual_y_train_b = component.classifiers[&#34;b&#34;].fit.call_args[0][1]
actual_y_train_c = component.classifiers[&#34;c&#34;].fit.call_args[0][1]
assert norm(expected_y_train_a - actual_y_train_a) &lt; E
assert norm(expected_y_train_b - actual_y_train_b) &lt; E
assert norm(expected_y_train_c - actual_y_train_c) &lt; E
def test_lazy_before():
instances, models = get_test_pyomo_instances()
instances[0].build_lazy_constraint = Mock(return_value=&#34;c1&#34;)
solver = LearningSolver()
solver.internal_solver = Mock(spec=InternalSolver)
component = DynamicLazyConstraintsComponent(threshold=0.10)
component.classifiers = {&#34;a&#34;: Mock(spec=Classifier), &#34;b&#34;: Mock(spec=Classifier)}
component.classifiers[&#34;a&#34;].predict_proba = Mock(return_value=[[0.95, 0.05]])
component.classifiers[&#34;b&#34;].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[&#34;a&#34;].predict_proba.call_args[0][0]
actual_x_test_b = component.classifiers[&#34;b&#34;].predict_proba.call_args[0][0]
assert norm(expected_x_test_a - actual_x_test_a) &lt; E
assert norm(expected_x_test_b - actual_x_test_b) &lt; 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], &#34;b&#34;)
# Should ask internal solver to add generated constraint
solver.internal_solver.add_constraint.assert_called_once_with(&#34;c1&#34;)
def test_lazy_evaluate():
instances, models = get_test_pyomo_instances()
component = DynamicLazyConstraintsComponent()
component.classifiers = {
&#34;a&#34;: Mock(spec=Classifier),
&#34;b&#34;: Mock(spec=Classifier),
&#34;c&#34;: Mock(spec=Classifier),
}
component.classifiers[&#34;a&#34;].predict_proba = Mock(return_value=[[1.0, 0.0]])
component.classifiers[&#34;b&#34;].predict_proba = Mock(return_value=[[0.0, 1.0]])
component.classifiers[&#34;c&#34;].predict_proba = Mock(return_value=[[0.0, 1.0]])
instances[0].found_violated_lazy_constraints = [&#34;a&#34;, &#34;b&#34;, &#34;c&#34;]
instances[1].found_violated_lazy_constraints = [&#34;b&#34;, &#34;d&#34;]
assert component.evaluate(instances) == {
0: {
&#34;Accuracy&#34;: 0.75,
&#34;F1 score&#34;: 0.8,
&#34;Precision&#34;: 1.0,
&#34;Recall&#34;: 2 / 3.0,
&#34;Predicted positive&#34;: 2,
&#34;Predicted negative&#34;: 2,
&#34;Condition positive&#34;: 3,
&#34;Condition negative&#34;: 1,
&#34;False negative&#34;: 1,
&#34;False positive&#34;: 0,
&#34;True negative&#34;: 1,
&#34;True positive&#34;: 2,
&#34;Predicted positive (%)&#34;: 50.0,
&#34;Predicted negative (%)&#34;: 50.0,
&#34;Condition positive (%)&#34;: 75.0,
&#34;Condition negative (%)&#34;: 25.0,
&#34;False negative (%)&#34;: 25.0,
&#34;False positive (%)&#34;: 0,
&#34;True negative (%)&#34;: 25.0,
&#34;True positive (%)&#34;: 50.0,
},
1: {
&#34;Accuracy&#34;: 0.5,
&#34;F1 score&#34;: 0.5,
&#34;Precision&#34;: 0.5,
&#34;Recall&#34;: 0.5,
&#34;Predicted positive&#34;: 2,
&#34;Predicted negative&#34;: 2,
&#34;Condition positive&#34;: 2,
&#34;Condition negative&#34;: 2,
&#34;False negative&#34;: 1,
&#34;False positive&#34;: 1,
&#34;True negative&#34;: 1,
&#34;True positive&#34;: 1,
&#34;Predicted positive (%)&#34;: 50.0,
&#34;Predicted negative (%)&#34;: 50.0,
&#34;Condition positive (%)&#34;: 50.0,
&#34;Condition negative (%)&#34;: 50.0,
&#34;False negative (%)&#34;: 25.0,
&#34;False positive (%)&#34;: 25.0,
&#34;True negative (%)&#34;: 25.0,
&#34;True positive (%)&#34;: 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=&#34;c1&#34;)
solver = LearningSolver()
solver.internal_solver = Mock(spec=InternalSolver)
component = DynamicLazyConstraintsComponent(threshold=0.10)
component.classifiers = {&#34;a&#34;: Mock(spec=Classifier), &#34;b&#34;: Mock(spec=Classifier)}
component.classifiers[&#34;a&#34;].predict_proba = Mock(return_value=[[0.95, 0.05]])
component.classifiers[&#34;b&#34;].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[&#34;a&#34;].predict_proba.call_args[0][0]
actual_x_test_b = component.classifiers[&#34;b&#34;].predict_proba.call_args[0][0]
assert norm(expected_x_test_a - actual_x_test_a) &lt; E
assert norm(expected_x_test_b - actual_x_test_b) &lt; 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], &#34;b&#34;)
# Should ask internal solver to add generated constraint
solver.internal_solver.add_constraint.assert_called_once_with(&#34;c1&#34;)</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 = {
&#34;a&#34;: Mock(spec=Classifier),
&#34;b&#34;: Mock(spec=Classifier),
&#34;c&#34;: Mock(spec=Classifier),
}
component.classifiers[&#34;a&#34;].predict_proba = Mock(return_value=[[1.0, 0.0]])
component.classifiers[&#34;b&#34;].predict_proba = Mock(return_value=[[0.0, 1.0]])
component.classifiers[&#34;c&#34;].predict_proba = Mock(return_value=[[0.0, 1.0]])
instances[0].found_violated_lazy_constraints = [&#34;a&#34;, &#34;b&#34;, &#34;c&#34;]
instances[1].found_violated_lazy_constraints = [&#34;b&#34;, &#34;d&#34;]
assert component.evaluate(instances) == {
0: {
&#34;Accuracy&#34;: 0.75,
&#34;F1 score&#34;: 0.8,
&#34;Precision&#34;: 1.0,
&#34;Recall&#34;: 2 / 3.0,
&#34;Predicted positive&#34;: 2,
&#34;Predicted negative&#34;: 2,
&#34;Condition positive&#34;: 3,
&#34;Condition negative&#34;: 1,
&#34;False negative&#34;: 1,
&#34;False positive&#34;: 0,
&#34;True negative&#34;: 1,
&#34;True positive&#34;: 2,
&#34;Predicted positive (%)&#34;: 50.0,
&#34;Predicted negative (%)&#34;: 50.0,
&#34;Condition positive (%)&#34;: 75.0,
&#34;Condition negative (%)&#34;: 25.0,
&#34;False negative (%)&#34;: 25.0,
&#34;False positive (%)&#34;: 0,
&#34;True negative (%)&#34;: 25.0,
&#34;True positive (%)&#34;: 50.0,
},
1: {
&#34;Accuracy&#34;: 0.5,
&#34;F1 score&#34;: 0.5,
&#34;Precision&#34;: 0.5,
&#34;Recall&#34;: 0.5,
&#34;Predicted positive&#34;: 2,
&#34;Predicted negative&#34;: 2,
&#34;Condition positive&#34;: 2,
&#34;Condition negative&#34;: 2,
&#34;False negative&#34;: 1,
&#34;False positive&#34;: 1,
&#34;True negative&#34;: 1,
&#34;True positive&#34;: 1,
&#34;Predicted positive (%)&#34;: 50.0,
&#34;Predicted negative (%)&#34;: 50.0,
&#34;Condition positive (%)&#34;: 50.0,
&#34;Condition negative (%)&#34;: 50.0,
&#34;False negative (%)&#34;: 25.0,
&#34;False positive (%)&#34;: 25.0,
&#34;True negative (%)&#34;: 25.0,
&#34;True positive (%)&#34;: 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 = [&#34;a&#34;, &#34;b&#34;]
instances[1].found_violated_lazy_constraints = [&#34;b&#34;, &#34;c&#34;]
classifier = Mock(spec=Classifier)
component = DynamicLazyConstraintsComponent(classifier=classifier)
component.fit(instances)
# Should create one classifier for each violation
assert &#34;a&#34; in component.classifiers
assert &#34;b&#34; in component.classifiers
assert &#34;c&#34; 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[&#34;a&#34;].fit.call_args[0][0]
actual_x_train_b = component.classifiers[&#34;b&#34;].fit.call_args[0][0]
actual_x_train_c = component.classifiers[&#34;c&#34;].fit.call_args[0][0]
assert norm(expected_x_train_a - actual_x_train_a) &lt; E
assert norm(expected_x_train_b - actual_x_train_b) &lt; E
assert norm(expected_x_train_c - actual_x_train_c) &lt; 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[&#34;a&#34;].fit.call_args[0][1]
actual_y_train_b = component.classifiers[&#34;b&#34;].fit.call_args[0][1]
actual_y_train_c = component.classifiers[&#34;c&#34;].fit.call_args[0][1]
assert norm(expected_y_train_a - actual_y_train_a) &lt; E
assert norm(expected_y_train_b - actual_y_train_b) &lt; E
assert norm(expected_y_train_c - actual_y_train_c) &lt; 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>

View 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=[&#34;c1&#34;, &#34;c2&#34;, &#34;c3&#34;, &#34;c4&#34;])
internal.extract_constraint = Mock(side_effect=lambda cid: &#34;&lt;%s&gt;&#34; % 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: {
&#34;c1&#34;: False,
&#34;c2&#34;: True,
&#34;c3&#34;: True,
&#34;c4&#34;: True,
}[cid]
)
instance.get_constraint_features = Mock(
side_effect=lambda cid: {
&#34;c2&#34;: [1.0, 0.0],
&#34;c3&#34;: [0.5, 0.5],
&#34;c4&#34;: [1.0],
}[cid]
)
instance.get_constraint_category = Mock(
side_effect=lambda cid: {
&#34;c2&#34;: &#34;type-a&#34;,
&#34;c3&#34;: &#34;type-a&#34;,
&#34;c4&#34;: &#34;type-b&#34;,
}[cid]
)
component = StaticLazyConstraintsComponent(
threshold=0.90,
use_two_phase_gap=False,
violation_tolerance=1.0,
)
component.classifiers = {
&#34;type-a&#34;: Mock(spec=Classifier),
&#34;type-b&#34;: Mock(spec=Classifier),
}
component.classifiers[&#34;type-a&#34;].predict_proba = Mock(
return_value=[
[0.20, 0.80],
[0.05, 0.95],
]
)
component.classifiers[&#34;type-b&#34;].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(&#34;c1&#34;),
call(&#34;c2&#34;),
call(&#34;c3&#34;),
call(&#34;c4&#34;),
]
)
# For the lazy ones, should ask for features
instance.get_constraint_features.assert_has_calls(
[
call(&#34;c2&#34;),
call(&#34;c3&#34;),
call(&#34;c4&#34;),
]
)
# Should also ask for categories
assert instance.get_constraint_category.call_count == 3
instance.get_constraint_category.assert_has_calls(
[
call(&#34;c2&#34;),
call(&#34;c3&#34;),
call(&#34;c4&#34;),
]
)
# Should ask internal solver to remove constraints identified as lazy
assert internal.extract_constraint.call_count == 3
internal.extract_constraint.assert_has_calls(
[
call(&#34;c2&#34;),
call(&#34;c3&#34;),
call(&#34;c4&#34;),
]
)
# Should ask ML to predict whether each lazy constraint should be enforced
component.classifiers[&#34;type-a&#34;].predict_proba.assert_called_once_with(
[[1.0, 0.0], [0.5, 0.5]]
)
component.classifiers[&#34;type-b&#34;].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(&#34;&lt;c3&gt;&#34;),
call(&#34;&lt;c4&gt;&#34;),
]
)
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(&#34;&lt;c2&gt;&#34;, tol=1.0)
internal.is_constraint_satisfied.reset_mock()
internal.add_constraint.assert_called_once_with(&#34;&lt;c2&gt;&#34;)
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 == [&#34;c3&#34;, &#34;c4&#34;, &#34;c2&#34;]
def test_fit():
instance_1 = Mock(spec=Instance)
instance_1.found_violated_lazy_constraints = [&#34;c1&#34;, &#34;c2&#34;, &#34;c4&#34;, &#34;c5&#34;]
instance_1.get_constraint_category = Mock(
side_effect=lambda cid: {
&#34;c1&#34;: &#34;type-a&#34;,
&#34;c2&#34;: &#34;type-a&#34;,
&#34;c3&#34;: &#34;type-a&#34;,
&#34;c4&#34;: &#34;type-b&#34;,
&#34;c5&#34;: &#34;type-b&#34;,
}[cid]
)
instance_1.get_constraint_features = Mock(
side_effect=lambda cid: {
&#34;c1&#34;: [1, 1],
&#34;c2&#34;: [1, 2],
&#34;c3&#34;: [1, 3],
&#34;c4&#34;: [1, 4, 0],
&#34;c5&#34;: [1, 5, 0],
}[cid]
)
instance_2 = Mock(spec=Instance)
instance_2.found_violated_lazy_constraints = [&#34;c2&#34;, &#34;c3&#34;, &#34;c4&#34;]
instance_2.get_constraint_category = Mock(
side_effect=lambda cid: {
&#34;c1&#34;: &#34;type-a&#34;,
&#34;c2&#34;: &#34;type-a&#34;,
&#34;c3&#34;: &#34;type-a&#34;,
&#34;c4&#34;: &#34;type-b&#34;,
&#34;c5&#34;: &#34;type-b&#34;,
}[cid]
)
instance_2.get_constraint_features = Mock(
side_effect=lambda cid: {
&#34;c1&#34;: [2, 1],
&#34;c2&#34;: [2, 2],
&#34;c3&#34;: [2, 3],
&#34;c4&#34;: [2, 4, 0],
&#34;c5&#34;: [2, 5, 0],
}[cid]
)
instances = [instance_1, instance_2]
component = StaticLazyConstraintsComponent()
component.classifiers = {
&#34;type-a&#34;: Mock(spec=Classifier),
&#34;type-b&#34;: Mock(spec=Classifier),
}
expected_constraints = {
&#34;type-a&#34;: [&#34;c1&#34;, &#34;c2&#34;, &#34;c3&#34;],
&#34;type-b&#34;: [&#34;c4&#34;, &#34;c5&#34;],
}
expected_x = {
&#34;type-a&#34;: [[1, 1], [1, 2], [1, 3], [2, 1], [2, 2], [2, 3]],
&#34;type-b&#34;: [[1, 4, 0], [1, 5, 0], [2, 4, 0], [2, 5, 0]],
}
expected_y = {
&#34;type-a&#34;: [[0, 1], [0, 1], [1, 0], [1, 0], [0, 1], [0, 1]],
&#34;type-b&#34;: [[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[&#34;type-a&#34;].fit.assert_called_once_with(
expected_x[&#34;type-a&#34;],
expected_y[&#34;type-a&#34;],
)
component.classifiers[&#34;type-b&#34;].fit.assert_called_once_with(
expected_x[&#34;type-b&#34;],
expected_y[&#34;type-b&#34;],
)</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 = [&#34;c1&#34;, &#34;c2&#34;, &#34;c4&#34;, &#34;c5&#34;]
instance_1.get_constraint_category = Mock(
side_effect=lambda cid: {
&#34;c1&#34;: &#34;type-a&#34;,
&#34;c2&#34;: &#34;type-a&#34;,
&#34;c3&#34;: &#34;type-a&#34;,
&#34;c4&#34;: &#34;type-b&#34;,
&#34;c5&#34;: &#34;type-b&#34;,
}[cid]
)
instance_1.get_constraint_features = Mock(
side_effect=lambda cid: {
&#34;c1&#34;: [1, 1],
&#34;c2&#34;: [1, 2],
&#34;c3&#34;: [1, 3],
&#34;c4&#34;: [1, 4, 0],
&#34;c5&#34;: [1, 5, 0],
}[cid]
)
instance_2 = Mock(spec=Instance)
instance_2.found_violated_lazy_constraints = [&#34;c2&#34;, &#34;c3&#34;, &#34;c4&#34;]
instance_2.get_constraint_category = Mock(
side_effect=lambda cid: {
&#34;c1&#34;: &#34;type-a&#34;,
&#34;c2&#34;: &#34;type-a&#34;,
&#34;c3&#34;: &#34;type-a&#34;,
&#34;c4&#34;: &#34;type-b&#34;,
&#34;c5&#34;: &#34;type-b&#34;,
}[cid]
)
instance_2.get_constraint_features = Mock(
side_effect=lambda cid: {
&#34;c1&#34;: [2, 1],
&#34;c2&#34;: [2, 2],
&#34;c3&#34;: [2, 3],
&#34;c4&#34;: [2, 4, 0],
&#34;c5&#34;: [2, 5, 0],
}[cid]
)
instances = [instance_1, instance_2]
component = StaticLazyConstraintsComponent()
component.classifiers = {
&#34;type-a&#34;: Mock(spec=Classifier),
&#34;type-b&#34;: Mock(spec=Classifier),
}
expected_constraints = {
&#34;type-a&#34;: [&#34;c1&#34;, &#34;c2&#34;, &#34;c3&#34;],
&#34;type-b&#34;: [&#34;c4&#34;, &#34;c5&#34;],
}
expected_x = {
&#34;type-a&#34;: [[1, 1], [1, 2], [1, 3], [2, 1], [2, 2], [2, 3]],
&#34;type-b&#34;: [[1, 4, 0], [1, 5, 0], [2, 4, 0], [2, 5, 0]],
}
expected_y = {
&#34;type-a&#34;: [[0, 1], [0, 1], [1, 0], [1, 0], [0, 1], [0, 1]],
&#34;type-b&#34;: [[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[&#34;type-a&#34;].fit.assert_called_once_with(
expected_x[&#34;type-a&#34;],
expected_y[&#34;type-a&#34;],
)
component.classifiers[&#34;type-b&#34;].fit.assert_called_once_with(
expected_x[&#34;type-b&#34;],
expected_y[&#34;type-b&#34;],
)</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=[&#34;c1&#34;, &#34;c2&#34;, &#34;c3&#34;, &#34;c4&#34;])
internal.extract_constraint = Mock(side_effect=lambda cid: &#34;&lt;%s&gt;&#34; % 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: {
&#34;c1&#34;: False,
&#34;c2&#34;: True,
&#34;c3&#34;: True,
&#34;c4&#34;: True,
}[cid]
)
instance.get_constraint_features = Mock(
side_effect=lambda cid: {
&#34;c2&#34;: [1.0, 0.0],
&#34;c3&#34;: [0.5, 0.5],
&#34;c4&#34;: [1.0],
}[cid]
)
instance.get_constraint_category = Mock(
side_effect=lambda cid: {
&#34;c2&#34;: &#34;type-a&#34;,
&#34;c3&#34;: &#34;type-a&#34;,
&#34;c4&#34;: &#34;type-b&#34;,
}[cid]
)
component = StaticLazyConstraintsComponent(
threshold=0.90,
use_two_phase_gap=False,
violation_tolerance=1.0,
)
component.classifiers = {
&#34;type-a&#34;: Mock(spec=Classifier),
&#34;type-b&#34;: Mock(spec=Classifier),
}
component.classifiers[&#34;type-a&#34;].predict_proba = Mock(
return_value=[
[0.20, 0.80],
[0.05, 0.95],
]
)
component.classifiers[&#34;type-b&#34;].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(&#34;c1&#34;),
call(&#34;c2&#34;),
call(&#34;c3&#34;),
call(&#34;c4&#34;),
]
)
# For the lazy ones, should ask for features
instance.get_constraint_features.assert_has_calls(
[
call(&#34;c2&#34;),
call(&#34;c3&#34;),
call(&#34;c4&#34;),
]
)
# Should also ask for categories
assert instance.get_constraint_category.call_count == 3
instance.get_constraint_category.assert_has_calls(
[
call(&#34;c2&#34;),
call(&#34;c3&#34;),
call(&#34;c4&#34;),
]
)
# Should ask internal solver to remove constraints identified as lazy
assert internal.extract_constraint.call_count == 3
internal.extract_constraint.assert_has_calls(
[
call(&#34;c2&#34;),
call(&#34;c3&#34;),
call(&#34;c4&#34;),
]
)
# Should ask ML to predict whether each lazy constraint should be enforced
component.classifiers[&#34;type-a&#34;].predict_proba.assert_called_once_with(
[[1.0, 0.0], [0.5, 0.5]]
)
component.classifiers[&#34;type-b&#34;].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(&#34;&lt;c3&gt;&#34;),
call(&#34;&lt;c4&gt;&#34;),
]
)
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(&#34;&lt;c2&gt;&#34;, tol=1.0)
internal.is_constraint_satisfied.reset_mock()
internal.add_constraint.assert_called_once_with(&#34;&lt;c2&gt;&#34;)
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 == [&#34;c3&#34;, &#34;c4&#34;, &#34;c2&#34;]</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>

View File

@@ -0,0 +1,174 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<meta name="generator" content="pdoc 0.7.0" />
<title>miplearn.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][&#34;Lower bound&#34;] == 1183.0
assert instances[0].training_data[0][&#34;Upper bound&#34;] == 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 == {
&#34;Lower bound&#34;: {
&#34;Explained variance&#34;: 0.0,
&#34;Max error&#34;: 183.0,
&#34;Mean absolute error&#34;: 126.5,
&#34;Mean squared error&#34;: 19194.5,
&#34;Median absolute error&#34;: 126.5,
&#34;R2&#34;: -5.012843605607331,
},
&#34;Upper bound&#34;: {
&#34;Explained variance&#34;: 0.0,
&#34;Max error&#34;: 183.0,
&#34;Mean absolute error&#34;: 126.5,
&#34;Mean squared error&#34;: 19194.5,
&#34;Median absolute error&#34;: 126.5,
&#34;R2&#34;: -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 == {
&#34;Lower bound&#34;: {
&#34;Explained variance&#34;: 0.0,
&#34;Max error&#34;: 183.0,
&#34;Mean absolute error&#34;: 126.5,
&#34;Mean squared error&#34;: 19194.5,
&#34;Median absolute error&#34;: 126.5,
&#34;R2&#34;: -5.012843605607331,
},
&#34;Upper bound&#34;: {
&#34;Explained variance&#34;: 0.0,
&#34;Max error&#34;: 183.0,
&#34;Mean absolute error&#34;: 126.5,
&#34;Mean squared error&#34;: 19194.5,
&#34;Median absolute error&#34;: 126.5,
&#34;R2&#34;: -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][&#34;Lower bound&#34;] == 1183.0
assert instances[0].training_data[0][&#34;Upper bound&#34;] == 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>

View 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 &#34;x&#34; in solution
assert 0 in solution[&#34;x&#34;]
assert 1 in solution[&#34;x&#34;]
assert 2 in solution[&#34;x&#34;]
assert 3 in solution[&#34;x&#34;]
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]) == {&#34;x&#34;: {0: 0, 1: 0, 2: 1, 3: None}}
assert instances[0].training_data[0][&#34;Solution&#34;] == {&#34;x&#34;: {0: 1, 1: 0, 2: 1, 3: 1}}
ev = comp.evaluate(instances[:1])
assert ev == {
&#34;Fix one&#34;: {
0: {
&#34;Accuracy&#34;: 0.5,
&#34;Condition negative&#34;: 1,
&#34;Condition negative (%)&#34;: 25.0,
&#34;Condition positive&#34;: 3,
&#34;Condition positive (%)&#34;: 75.0,
&#34;F1 score&#34;: 0.5,
&#34;False negative&#34;: 2,
&#34;False negative (%)&#34;: 50.0,
&#34;False positive&#34;: 0,
&#34;False positive (%)&#34;: 0.0,
&#34;Precision&#34;: 1.0,
&#34;Predicted negative&#34;: 3,
&#34;Predicted negative (%)&#34;: 75.0,
&#34;Predicted positive&#34;: 1,
&#34;Predicted positive (%)&#34;: 25.0,
&#34;Recall&#34;: 0.3333333333333333,
&#34;True negative&#34;: 1,
&#34;True negative (%)&#34;: 25.0,
&#34;True positive&#34;: 1,
&#34;True positive (%)&#34;: 25.0,
}
},
&#34;Fix zero&#34;: {
0: {
&#34;Accuracy&#34;: 0.75,
&#34;Condition negative&#34;: 3,
&#34;Condition negative (%)&#34;: 75.0,
&#34;Condition positive&#34;: 1,
&#34;Condition positive (%)&#34;: 25.0,
&#34;F1 score&#34;: 0.6666666666666666,
&#34;False negative&#34;: 0,
&#34;False negative (%)&#34;: 0.0,
&#34;False positive&#34;: 1,
&#34;False positive (%)&#34;: 25.0,
&#34;Precision&#34;: 0.5,
&#34;Predicted negative&#34;: 2,
&#34;Predicted negative (%)&#34;: 50.0,
&#34;Predicted positive&#34;: 2,
&#34;Predicted positive (%)&#34;: 50.0,
&#34;Recall&#34;: 1.0,
&#34;True negative&#34;: 2,
&#34;True negative (%)&#34;: 50.0,
&#34;True positive&#34;: 1,
&#34;True positive (%)&#34;: 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]) == {&#34;x&#34;: {0: 0, 1: 0, 2: 1, 3: None}}
assert instances[0].training_data[0][&#34;Solution&#34;] == {&#34;x&#34;: {0: 1, 1: 0, 2: 1, 3: 1}}
ev = comp.evaluate(instances[:1])
assert ev == {
&#34;Fix one&#34;: {
0: {
&#34;Accuracy&#34;: 0.5,
&#34;Condition negative&#34;: 1,
&#34;Condition negative (%)&#34;: 25.0,
&#34;Condition positive&#34;: 3,
&#34;Condition positive (%)&#34;: 75.0,
&#34;F1 score&#34;: 0.5,
&#34;False negative&#34;: 2,
&#34;False negative (%)&#34;: 50.0,
&#34;False positive&#34;: 0,
&#34;False positive (%)&#34;: 0.0,
&#34;Precision&#34;: 1.0,
&#34;Predicted negative&#34;: 3,
&#34;Predicted negative (%)&#34;: 75.0,
&#34;Predicted positive&#34;: 1,
&#34;Predicted positive (%)&#34;: 25.0,
&#34;Recall&#34;: 0.3333333333333333,
&#34;True negative&#34;: 1,
&#34;True negative (%)&#34;: 25.0,
&#34;True positive&#34;: 1,
&#34;True positive (%)&#34;: 25.0,
}
},
&#34;Fix zero&#34;: {
0: {
&#34;Accuracy&#34;: 0.75,
&#34;Condition negative&#34;: 3,
&#34;Condition negative (%)&#34;: 75.0,
&#34;Condition positive&#34;: 1,
&#34;Condition positive (%)&#34;: 25.0,
&#34;F1 score&#34;: 0.6666666666666666,
&#34;False negative&#34;: 0,
&#34;False negative (%)&#34;: 0.0,
&#34;False positive&#34;: 1,
&#34;False positive (%)&#34;: 25.0,
&#34;Precision&#34;: 0.5,
&#34;Predicted negative&#34;: 2,
&#34;Predicted negative (%)&#34;: 50.0,
&#34;Predicted positive&#34;: 2,
&#34;Predicted positive (%)&#34;: 50.0,
&#34;Recall&#34;: 1.0,
&#34;True negative&#34;: 2,
&#34;True negative (%)&#34;: 50.0,
&#34;True positive&#34;: 1,
&#34;True positive (%)&#34;: 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 &#34;x&#34; in solution
assert 0 in solution[&#34;x&#34;]
assert 1 in solution[&#34;x&#34;]
assert 2 in solution[&#34;x&#34;]
assert 3 in solution[&#34;x&#34;]</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>