Skip to content

Commit

Permalink
fix bounds on continuous variables not exported to mps
Browse files Browse the repository at this point in the history
  • Loading branch information
hlefebvr committed Jun 21, 2024
1 parent 90dab1e commit 873b455
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 47 deletions.
6 changes: 6 additions & 0 deletions docs/_static/design.css
Original file line number Diff line number Diff line change
Expand Up @@ -166,4 +166,10 @@ h1, h2, h3, h4, h5, h6 {
content: "";
}

.document {
text-align: justify;
}

.eqno {
float:right;
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,16 @@ The Column-and-Constraint Generation (CCG) algorithm is a classical method for s
It was originally introduced by :cite:`Zeng2013`.

In idol, the implementation of CCG alows to solve a class of problems which is slightly more general than classical
two-stage robust optimization problems. This class of problems is defined in the following sub-section.
two-stage robust optimization problems. This class of problems is defined in the following section.

Problem Class
-------------
.. contents:: Table of Contents
:local:
:depth: 2

Problem Definition and Notation
-------------------------------

The CCG algorithm can solve optimization problems of the following form:
The CCG algorithm can solve optimization problems of the form

.. math::
:label: eq:original-problem
Expand All @@ -21,40 +25,38 @@ The CCG algorithm can solve optimization problems of the following form:
& \forall \xi\in\Xi, \ \exists y\in Y(x,\xi), \ G(x,y,\xi) \le 0.
\end{align}
in which

- :math:`f` is a given function,
- :math:`X` is a given set, called the *first-stage feasible set*,
- :math:`\Xi` is a given set, called the *uncertainty set*, typically compact,
- :math:`Y(x,\xi)` is a set, defined for all :math:`x\in X` and :math:`\xi\in\Xi`, called the *second-stage feasible set*, and
- :math:`G` is a given vector of functions, defining the so-called *coupling constraints* between the uncertainty, the first- and the second-stage decisions.
in which :math:`f:\mathbb R^{n_x}\rightarrow\mathbb R` is a given function,
:math:`X\subseteq\mathbb R^{n_x}` is a given set, called the *first-stage feasible set*,
:math:`\Xi\subseteq\mathbb R^{n_\xi}` is a given set, called the *uncertainty set*, typically compact,
:math:`Y(x,\xi) \subseteq \mathbb R^{n_y}` is a set, defined for all :math:`x\in X` and :math:`\xi\in\Xi`, called the *second-stage feasible set*, and
:math:`G:\mathbb R^{n_x+n_y+n_\xi}\rightarrow\mathbb R^\ell` is a given vector of functions, defining the so-called *coupling constraints* between the uncertainty, the first- and the second-stage decisions.

.. admonition:: Regarding Coupling Constraints

It is clear that coupling constraints are redundant since they can be incorporated into the definition of the second-stage feasible set.
However, we will see that explicitly defining *coupling constraints* may lead to different implementations of the CCG algorithm.
We will dive into this aspect after introducing the concept of *separators*.

Min-Max-Min Problems
^^^^^^^^^^^^^^^^^^^^
.. hint::

Consider the following min-max-min problem:
Consider the Min-Max-Min problem

.. math::
.. math::
\min_{x\in X} \ \max_{\xi\in\Xi} \ \min_{y\in Y(x,\xi)} \ \psi(x,y,\xi).
\min_{x\in X} \ \max_{\xi\in\Xi} \ \min_{y\in Y(x,\xi)} \ \psi(x,y,\xi).
This class of problems is a special case of :math:numref:`eq:original-problem` since it can be written as
Clearly, this is a special case of :math:numref:`eq:original-problem` since it can be written as

.. math::
.. math::
\begin{align}
\min_{x_0,x} \quad & x_0 \\
\text{s.t.} \quad & (x_0,x) \in\mathbb R\times X, \\
& \forall \xi\in\Xi, \ \exists y\in Y(x,\xi), \ \psi(x,y,\xi) \le x_0.
\end{align}
\begin{align}
\min_{x_0,x} \quad & x_0 \\
\text{s.t.} \quad & (x_0,x) \in\mathbb R\times X, \\
& \forall \xi\in\Xi, \ \exists y\in Y(x,\xi), \ \psi(x,y,\xi) \le x_0.
\end{align}
Here, there is only one coupling constraint, which is :math:`\psi(x,y,\xi) \le x_0`.

Here, there is only one coupling constraint, which is :math:`\psi(x,y,\xi) \le x_0`.

The Algorithm
-------------
Expand All @@ -69,18 +71,20 @@ and to solve the following problem instead of :math:numref:`eq:original-problem`
:label: eq:master-problem
\begin{align}
\min_{x_0,x} \quad & f(x) \\
\min_{x_0,x,y^1,\dotsc,y^K} \quad & f(x) \\
\text{s.t.} \quad & x\in X, \\
& \left. \begin{array}{l}
G(x,y^t,\xi^t) \le 0, \\
y^t\in Y(x,\xi^t)
\end{array} \right\} \quad \forall t=1,...,k.
& G(x,y^t,\xi^t) \le 0 \qquad k=1,\dotsc,K, \\
& y^t\in Y(x,\xi^t) \qquad k=1,\dotsc,K.
\end{align}
Here, a new variable :math:`y^t` has been introduced for each :math:`t=1,...,k`, enforcing that :math:`\exists y^t\in Y(x,\xi^t)`.
Clearly, this problem is a relaxation of :math:numref:`eq:original-problem` since any feasible point of :math:numref:`eq:original-problem` is also feasible for this problem.
Here, a new variable :math:`y^t` has been introduced for each :math:`t=1,...,k`, enforcing that, indeed,
there exists :math:`y^t\in Y(x,\xi^t)` such that :math:`G(x,y^t,\xi^t) \le 0`.

Note that Problem :math:numref:`eq:master-problem` is a relaxation of Problem :math:numref:`eq:original-problem` since
any feasible point of :math:numref:`eq:original-problem` is also feasible for :math:numref:`eq:master-problem` (for some :math:`y^1,\dotsc,y^K`).

Now, given a solution :math:`\hat x\in X` of the above problem, one needs to check whether :math:`\hat x` is feasible for :math:numref:`eq:original-problem`.
Now, given a solution :math:`\hat x\in X` of the relaxed problem :math:numref:`eq:master-problem`,
one needs to check whether :math:`\hat x` is feasible for Problem :math:numref:`eq:original-problem`.
Thus, one seeks a scenario :math:`\xi^*\in\Xi` such that, either :math:`Y(\hat x, \xi^*)` is empty, or :math:`G(\hat x,y,\xi^*) > 0` for all :math:`y\in Y(\hat x, \xi^*)`.
If no such scenario exists, then :math:`\hat x` is feasible for :math:numref:`eq:original-problem`. Otherwise, the new scenario :math:`\xi^*` is added to the set of considered scenarios and the process is repeated.

Expand All @@ -101,41 +105,46 @@ Separators

Clearly, the separation problem :math:numref:`eq:separation-problem` can be solved in many different ways. In idol,
it is therefore possible to give a user-defined functor, called a *separator*, which solves the separation problem.
Yet, note that the most common ways to solve the separation problem are already implemented in idol.

Note that some of the most common ways to solve the separation problem are already implemented in idol. See :ref:`this page <api_ro_ccg_separators>`.
If you wish to implement your own separator, you should refer to :ref:`this tutorial <tutorial_write_ccg_separator>`.

If you wish to implement your own separator, beware that it should return a solution of
Shortly put, the separator solves problems of the form

.. math::
:label: eq:single-separation-problem
\max_{\xi\in \Xi} \ \min_{ y\in Y(\hat x,\xi) } \ G_\ell(\hat x,y,\xi),
for a given :math:`\ell\in\{1,...,L\}`.
for a given :math:`G_\ell` (:math:`\ell\in\{1,...,L\}`).

Then, a scenario :math:`\xi^{\ell^*}` is added if, and only if,
Note that it is ensured that the separator always solves a problem which is feasible.
Indeed, in case Problem :math:numref:`eq:separation-problem`
is not known to satisfy the *complete recourse assumption* (i.e., it is not known whether :math:`\forall x\in X, \forall\xi\in\Xi, \exists y\in Y(x,\xi)` holds),
the CCG algorithm will first solve a feasibility version of the separation problem to check whether
:math:`\hat x` is such that for all :math:`\xi\in\Xi` there exists :math:`y\in Y(\hat x,\xi)`.
Fortunately, it is also possible to specify that the complete recourse assumption holds, in which case the feasibility version of the separation problem is not solved.

Let :math:`\xi^{\ell}` denote the solution of the separation problem :math:numref:`eq:single-separation-problem` for a given :math:`\ell\in\{1,...,L\}`.
Then, a scenario :math:`\xi^{\ell^*}` is added to Problem :math:numref:`eq:master-problem` if and only if

.. math::
\ell^* \in \underset{\ell=1,...,L}{\text{argmax}} \ \min_{ y\in Y(\hat x,\xi^\ell) } \ G_\ell(\hat x,y,\xi^\ell) > \varepsilon_\text{feas}.
See :ref:`the dedicated page <api_ro_ccg_separators>` for more details.
See :ref:`the dedicated page <tutorial_write_ccg_separator>` for more details.

On the Impact of Coupling Constraints
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-------------------------------------

We now discuss the impact of the definition of the coupling constraints :math:`G` on the implementation of the CCG algorithm.
To this end, let :math:`\hat x\in X` be a given point.

As discussed in the previous sections, one needs to check whether :math:`\hat x` is feasible for :math:numref:`eq:original-problem`
by solving the separation problem :math:numref:`eq:separation-problem`.

Arguably, one obtains an equivalent problem to :math:numref:`eq:original-problem` by defining the second-stage feasible set as
Clearly, one obtains an equivalent problem to :math:numref:`eq:original-problem` by defining the second-stage feasible set as

.. math::
\tilde Y(x,\xi) = \{ y\in Y(x,\xi) \ | \ G(x,y,\xi) \le 0 \},
and by considering the following problem:
and by considering the problem

.. math::
Expand All @@ -145,7 +154,7 @@ and by considering the following problem:
& \forall \xi\in\Xi, \ \exists y\in \tilde Y(\hat x,\xi).
\end{align}
Then, the separation problem becomes
In this case, the separation problem becomes

.. math::
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
.. _tutorial_write_ccg_separator:

Writing Your Own Separator (Advanced) [TODO]
============================================

Expand Down
2 changes: 2 additions & 0 deletions examples/robust-optimization/robust_ccg.example.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "idol/optimizers/robust-optimization/column-and-constraint-generation/ColumnAndConstraintGeneration.h"
#include "idol/optimizers/robust-optimization/column-and-constraint-generation/separators/Bilevel.h"
#include "idol/modeling/robust-optimization/StageDescription.h"
#include "idol/optimizers/robust-optimization/column-and-constraint-generation/stabilizers/TrustRegion.h"

using namespace idol;

Expand Down Expand Up @@ -46,6 +47,7 @@ int main(int t_argc, const char** t_argv) {
.with_separator(
Robust::CCGSeparators::Bilevel()
)
//.with_stabilization(Robust::CCGStabilizers::TrustRegion())
.with_logs(true)
);

Expand Down
2 changes: 1 addition & 1 deletion lib/src/modeling/bilevel-optimization/write_to_file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ void MpsWriter::write() {

file << "BOUNDS\n";

for (const auto& var : integer_vars) {
for (const auto& var : m_model.vars()) {
const auto lb = m_model.get_var_lb(var);
const auto ub = m_model.get_var_ub(var);
const auto type = m_model.get_var_type(var);
Expand Down

0 comments on commit 873b455

Please sign in to comment.