Skip to content

Commit

Permalink
start introducing quadratic constraints
Browse files Browse the repository at this point in the history
  • Loading branch information
hlefebvr committed Nov 19, 2024
1 parent 6fc3acc commit b5125cd
Show file tree
Hide file tree
Showing 38 changed files with 332 additions and 244 deletions.
16 changes: 7 additions & 9 deletions dev/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,26 +17,24 @@
#include "idol/mixed-integer/optimizers/branch-and-bound/branching-rules/factories/MostInfeasible.h"
#include "idol/mixed-integer/optimizers/branch-and-bound/node-selection-rules/factories/BestBound.h"
#include "idol/mixed-integer/optimizers/branch-and-bound/BranchAndBound.h"
#include "idol/mixed-integer/modeling/expressions/QuadExpr.h"

int main(int t_argc, const char** t_argv) {
using namespace idol;

int main(int t_argc, const char** t_argv) {

/*
Env env;
Model model(env);

const auto x = model.add_vars(Dim<1>(10), 0, 1, Binary, 1, "x");

LinExpr<CommutativePair<Var>, Expr<Var>> expr;
LinExpr<CommutativePair<Var>, Expr<Var>> expr2;
QuadExpr expr(2 * x[0] + 2);

expr.set({x[0], x[1]}, 1 + x[0]);
expr2.set({x[1], x[0]}, 1);
expr += expr2;
//expr += x[0] * x[0];

std::cout << expr << std::endl;
*/

std::cout << evaluate(expr, Point<Var>()) << std::endl;

return 0;
}
4 changes: 2 additions & 2 deletions docs/api/classes/common/Expr.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
.. _api_Expr:

Expr
AffExpr
====

.. doxygenclass:: idol::Expr
.. doxygenclass:: idol::AffExpr
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ Defining the Lower-Level Objective Function

Finally, we need to define the lower-level objective function.
This is done by calling the method :code:`set_follower_obj_expr` on the object of type :code:`Bilevel::LowerLevelDescription`.
An :code:`Expr` object is passed as argument to this method.
An :code:`AffExpr` object is passed as argument to this method.

.. code::
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ A more compact version of this code is obtained by making use of the ``Model::ad
As you can see, a constraint is created using the pattern :code:`{expression} {sign} {expression}` where

* :code:`{sign}` is one of :code:`<=`, :code:`>=` and :code:`==`;
* :code:`{expression}` is an expression, i.e., an instance of :code:`Expr`.
* :code:`{expression}` is an expression, i.e., an instance of :code:`AffExpr`.

Actually, the pattern :code:`{expression} {sign} {expression}` only creates a "temporary" constraint, i.e., a constraint
which is not associated to any model. This is why we need to add it to a model by calling the :code:`Model::add_ctr` method.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ Expressions
-----------

An expression generically refers to any mathematical expression involving variables or constraints. In idol, expressions
are represented by the :ref:`Expr <api_Expr>` class.
are represented by the :ref:`AffExpr <api_Expr>` class.

An expression can be created by adding, subtracting or multiplying variables with constants or other expressions. For instance,
the following code creates the mathematical expression :math:`1 + 3 x_0 + x_1 + x_0 + 2 x_0 x_1`.

.. code:: cpp
const Expr expr = 1 + 3 * x[0] + x[1] + x[0] + 2 * x[0] * x[1];
const AffExpr expr = 1 + 3 * x[0] + x[1] + x[0] + 2 * x[0] * x[1];
std::cout << expr << std::endl; // "1 + 4 * x[0] + 1 * x[1] + 2 * x[0] * x[1]"
Expand All @@ -19,7 +19,7 @@ Expressions are composed of three parts:
* A linear part which is an instance of the :ref:`LinExpr <api_LinExpr>` class;
* A quadratic part which is an instance of the :ref:`QuadExpr <api_QuadExpr>` class.

Each of these parts can be accessed using the methods :cpp:`Expr::constant`, :cpp:`Expr::linear` and :cpp:`Expr::quadratic`, respectively.
Each of these parts can be accessed using the methods :cpp:`AffExpr::constant`, :cpp:`AffExpr::linear` and :cpp:`AffExpr::quadratic`, respectively.
For instance, consider the following code.

.. code-block:: cpp
Expand All @@ -33,7 +33,7 @@ This code iterates over the linear part of the expression and prints the variabl

.. admonition:: About constants in expressions

Without going into too much detail, we should here precise that each constant multiplying a variable in an :cpp:`Expr`,
Without going into too much detail, we should here precise that each constant multiplying a variable in an :cpp:`AffExpr`,
as well as the offset constant, can actually be composite. For instance, this is the case when a variable is multiplied by
a parameter which is considered fixed in the current model but cannot be evaluated at the time the expression is created.

Expand All @@ -51,7 +51,7 @@ This code iterates over the linear part of the expression and prints the variabl
const Model model2(env);
const auto xi = model2.add_vars(Dim<1>(2), 0., 1., Continuous, "xi");
const Expr expr = (1 + 2 * !xi[0]) * x[0] + 3 * !xi[1] * x[1];
const AffExpr expr = (1 + 2 * !xi[0]) * x[0] + 3 * !xi[1] * x[1];
Here, ``1 + 2 * !xi_0`` is an instance of the ``Constant`` object and can be used as follows.

Expand Down
2 changes: 1 addition & 1 deletion lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ add_library(idol STATIC
src/mixed-integer/problems/knapsack-problem/KP_Instance.cpp
include/idol/mixed-integer/problems/multiple-knapsack-problem/MKP_Instance.h
src/mixed-integer/problems/multiple-knapsack-problem/MKP_Instance.cpp
include/idol/mixed-integer/modeling/expressions/Expr.h
include/idol/mixed-integer/modeling/expressions/AffExpr.h
include/idol/mixed-integer/modeling/expressions/operations/operators_Var.h
src/mixed-integer/modeling/expressions/operations/operators_Var.cpp
src/mixed-integer/modeling/expressions/operations/operators_Ctr.cpp
Expand Down
8 changes: 4 additions & 4 deletions lib/include/idol/bilevel/modeling/LowerLevelDescription.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ namespace idol::Bilevel {
class idol::Bilevel::LowerLevelDescription {
Annotation<Var> m_follower_variables;
Annotation<Ctr> m_follower_constraints;
Expr<Var> m_follower_objective;
AffExpr<Var> m_follower_objective;
public:
LowerLevelDescription(Env& t_env, const std::string& t_name)
: m_follower_variables(t_env, t_name + "_follower_variables", MasterId),
Expand All @@ -34,7 +34,7 @@ class idol::Bilevel::LowerLevelDescription {

LowerLevelDescription(const Annotation<Var>& t_follower_variables,
const Annotation<Ctr>& t_follower_constraints,
Expr<Var> t_follower_objective)
AffExpr<Var> t_follower_objective)
: m_follower_variables(t_follower_variables),
m_follower_constraints(t_follower_constraints),
m_follower_objective(std::move(t_follower_objective)) {}
Expand All @@ -43,7 +43,7 @@ class idol::Bilevel::LowerLevelDescription {

[[nodiscard]] const Annotation<Ctr>& follower_ctrs() const { return m_follower_constraints; }

[[nodiscard]] const Expr<Var>& follower_obj() const { return m_follower_objective; }
[[nodiscard]] const AffExpr<Var>& follower_obj() const { return m_follower_objective; }

void make_leader_var(const Var& t_var) { t_var.set(m_follower_variables, MasterId); }

Expand All @@ -53,7 +53,7 @@ class idol::Bilevel::LowerLevelDescription {

void make_follower_ctr(const Ctr& t_ctr) { t_ctr.set(m_follower_constraints, 0); }

void set_follower_obj_expr(Expr<Var> t_objective) { m_follower_objective = std::move(t_objective); }
void set_follower_obj_expr(AffExpr<Var> t_objective) { m_follower_objective = std::move(t_objective); }

bool is_leader(const Var& t_var) const { return t_var.get(m_follower_variables) == MasterId; }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
namespace idol {

/*
static std::list<Expr<Var>> to_rotated_quadratic_cone(const QuadExpr<Var> &t_expr) {
static std::list<AffExpr<Var>> to_rotated_quadratic_cone(const QuadExpr<Var> &t_expr) {
// Create index mapping
MatrixIndices indices;
Expand Down Expand Up @@ -69,7 +69,7 @@ namespace idol {
N = L * N * L.transpose();
// Build result
std::list<Expr<Var>> result;
std::list<AffExpr<Var>> result;
// Create head
for (const auto &[var1, i]: indices.indices()) {
Expand Down
28 changes: 14 additions & 14 deletions lib/include/idol/mixed-integer/modeling/constraints/TempCtr.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace idol {

class TempCtr;

template<class, class> class Expr;
template<class, class> class AffExpr;
}

/**
Expand All @@ -24,7 +24,7 @@ namespace idol {
* It contains all the arguments needed to create a real constraint
* as instantiated by the `Ctr` class. It is made of a row (see `Row`) and a type (see `CtrType.rst.rst`).
*
* Typically, one creates a `TempCtr` by using the overloaded operators `<=`, `>=` and `==` between variable expressions (i.e., `Expr`) and
* Typically, one creates a `TempCtr` by using the overloaded operators `<=`, `>=` and `==` between variable expressions (i.e., `AffExpr`) and
* constant terms (i.e., `Constant`).
*
* **Example 1**:
Expand Down Expand Up @@ -114,20 +114,20 @@ class idol::TempCtr {

};

idol::TempCtr operator<=(idol::Expr<idol::Var, double>&& t_lhs, idol::Expr<idol::Var, double>&& t_rhs);
idol::TempCtr operator<=(const idol::Expr<idol::Var, double>& t_lhs, idol::Expr<idol::Var, double>&& t_rhs);
idol::TempCtr operator<=(idol::Expr<idol::Var, double>&& t_lhs, const idol::Expr<idol::Var, double>& t_rhs);
idol::TempCtr operator<=(const idol::Expr<idol::Var, double>& t_lhs, const idol::Expr<idol::Var, double>& t_rhs);
idol::TempCtr operator<=(idol::AffExpr<idol::Var, double>&& t_lhs, idol::AffExpr<idol::Var, double>&& t_rhs);
idol::TempCtr operator<=(const idol::AffExpr<idol::Var, double>& t_lhs, idol::AffExpr<idol::Var, double>&& t_rhs);
idol::TempCtr operator<=(idol::AffExpr<idol::Var, double>&& t_lhs, const idol::AffExpr<idol::Var, double>& t_rhs);
idol::TempCtr operator<=(const idol::AffExpr<idol::Var, double>& t_lhs, const idol::AffExpr<idol::Var, double>& t_rhs);

idol::TempCtr operator>=(idol::Expr<idol::Var, double>&& t_lhs, idol::Expr<idol::Var, double>&& t_rhs);
idol::TempCtr operator>=(const idol::Expr<idol::Var, double>& t_lhs, idol::Expr<idol::Var, double>&& t_rhs);
idol::TempCtr operator>=(idol::Expr<idol::Var, double>&& t_lhs, const idol::Expr<idol::Var, double>& t_rhs);
idol::TempCtr operator>=(const idol::Expr<idol::Var, double>& t_lhs, const idol::Expr<idol::Var, double>& t_rhs);
idol::TempCtr operator>=(idol::AffExpr<idol::Var, double>&& t_lhs, idol::AffExpr<idol::Var, double>&& t_rhs);
idol::TempCtr operator>=(const idol::AffExpr<idol::Var, double>& t_lhs, idol::AffExpr<idol::Var, double>&& t_rhs);
idol::TempCtr operator>=(idol::AffExpr<idol::Var, double>&& t_lhs, const idol::AffExpr<idol::Var, double>& t_rhs);
idol::TempCtr operator>=(const idol::AffExpr<idol::Var, double>& t_lhs, const idol::AffExpr<idol::Var, double>& t_rhs);

idol::TempCtr operator==(idol::Expr<idol::Var, double>&& t_lhs, idol::Expr<idol::Var, double>&& t_rhs);
idol::TempCtr operator==(const idol::Expr<idol::Var, double>& t_lhs, idol::Expr<idol::Var, double>&& t_rhs);
idol::TempCtr operator==(idol::Expr<idol::Var, double>&& t_lhs, const idol::Expr<idol::Var, double>& t_rhs);
idol::TempCtr operator==(const idol::Expr<idol::Var, double>& t_lhs, const idol::Expr<idol::Var, double>& t_rhs);
idol::TempCtr operator==(idol::AffExpr<idol::Var, double>&& t_lhs, idol::AffExpr<idol::Var, double>&& t_rhs);
idol::TempCtr operator==(const idol::AffExpr<idol::Var, double>& t_lhs, idol::AffExpr<idol::Var, double>&& t_rhs);
idol::TempCtr operator==(idol::AffExpr<idol::Var, double>&& t_lhs, const idol::AffExpr<idol::Var, double>& t_rhs);
idol::TempCtr operator==(const idol::AffExpr<idol::Var, double>& t_lhs, const idol::AffExpr<idol::Var, double>& t_rhs);

namespace idol {
std::ostream &operator<<(std::ostream &t_os, const TempCtr &t_temp_ctr);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
// Created by henri on 21/10/22.
//

#ifndef IDOL_EXPR_H
#define IDOL_EXPR_H
#ifndef IDOL_AFFEXPR_H
#define IDOL_AFFEXPR_H

#include "LinExpr.h"
#include "idol/general/numericals.h"
Expand All @@ -12,33 +12,34 @@ namespace idol {
class Var;

template<class Key1, class ValueT>
class Expr;
class AffExpr;
}

template<class Key1 = idol::Var, class ValueT = double>
class idol::Expr {
class idol::AffExpr {
LinExpr<Key1, ValueT> m_linear;
double m_constant = 0.;
public:
Expr();
Expr(double t_constant); // NOLINT(google-explicit-constructor)
Expr(const Key1& t_var); // NOLINT(google-explicit-constructor)
Expr(LinExpr<Key1>&& t_expr); // NOLINT(google-explicit-constructor)
Expr(const LinExpr<Key1>& t_expr); // NOLINT(google-explicit-constructor)
AffExpr();
AffExpr(const ValueT& t_constant); // NOLINT(google-explicit-constructor)
AffExpr(ValueT&& t_constant); // NOLINT(google-explicit-constructor)
AffExpr(const Key1& t_var); // NOLINT(google-explicit-constructor)
AffExpr(LinExpr<Key1>&& t_expr); // NOLINT(google-explicit-constructor)
AffExpr(const LinExpr<Key1>& t_expr); // NOLINT(google-explicit-constructor)

virtual ~Expr() = default;
virtual ~AffExpr() = default;

Expr(const Expr& t_src);
Expr(Expr&&) noexcept = default;
AffExpr(const AffExpr& t_src) = default;
AffExpr(AffExpr&&) noexcept = default;

Expr& operator=(const Expr& t_rhs);
Expr& operator=(Expr&&) noexcept = default;
AffExpr& operator=(const AffExpr& t_rhs) = default;
AffExpr& operator=(AffExpr&&) noexcept = default;

Expr& operator+=(const Expr& t_rhs);
Expr& operator-=(const Expr& t_rhs);
Expr& operator*=(double t_rhs);
Expr& operator/=(double t_rhs);
Expr operator-() const;
AffExpr& operator+=(const AffExpr& t_rhs);
AffExpr& operator-=(const AffExpr& t_rhs);
AffExpr& operator*=(double t_rhs);
AffExpr& operator/=(double t_rhs);
AffExpr operator-() const;

LinExpr<Key1, ValueT>& linear() { return m_linear; }
[[nodiscard]] const LinExpr<Key1, ValueT>& linear() const { return m_linear; }
Expand All @@ -56,76 +57,66 @@ class idol::Expr {
};

template<class Key1, class ValueT>
idol::Expr<Key1, ValueT> idol::Expr<Key1, ValueT>::operator-() const {
idol::AffExpr<Key1, ValueT> idol::AffExpr<Key1, ValueT>::operator-() const {
auto result = *this;
result.constant() = -result.constant();
result.linear() = -result.linear();
return result;
}

template<class Key1, class ValueT>
idol::Expr<Key1, ValueT>::Expr() {
idol::AffExpr<Key1, ValueT>::AffExpr() {

}

template<class Key1, class ValueT>
idol::Expr<Key1, ValueT>::Expr(double t_constant) : m_constant(t_constant) {
idol::AffExpr<Key1, ValueT>::AffExpr(const ValueT& t_constant) : m_constant(t_constant) {

}

template<class Key1, class ValueT>
idol::Expr<Key1, ValueT>::Expr(const Key1 &t_var) : m_linear(t_var) {
idol::AffExpr<Key1, ValueT>::AffExpr(ValueT&& t_constant) : m_constant(t_constant) {

}

template<class Key1, class ValueT>
idol::Expr<Key1, ValueT>::Expr(LinExpr<Key1> &&t_expr) : m_linear(std::move(t_expr)) {
idol::AffExpr<Key1, ValueT>::AffExpr(const Key1 &t_var) : m_linear(t_var) {

}

template<class Key1, class ValueT>
idol::Expr<Key1, ValueT>::Expr(const LinExpr<Key1> &t_expr) : m_linear(t_expr) {
idol::AffExpr<Key1, ValueT>::AffExpr(LinExpr<Key1> &&t_expr) : m_linear(std::move(t_expr)) {

}

template<class Key1, class ValueT>
idol::Expr<Key1, ValueT>::Expr(const Expr &t_src)
: m_linear(t_src.m_linear),
m_constant(t_src.m_constant) {
idol::AffExpr<Key1, ValueT>::AffExpr(const LinExpr<Key1> &t_expr) : m_linear(t_expr) {

}

template<class Key1, class ValueT>
idol::Expr<Key1, ValueT> &idol::Expr<Key1, ValueT>::operator=(const Expr &t_rhs) {
if (this == &t_rhs) { return *this; }
m_linear = t_rhs.m_linear;
m_constant = t_rhs.m_constant;
return *this;
}

template<class Key1, class ValueT>
idol::Expr<Key1, ValueT> &idol::Expr<Key1, ValueT>::operator+=(const Expr &t_rhs) {
idol::AffExpr<Key1, ValueT> &idol::AffExpr<Key1, ValueT>::operator+=(const AffExpr &t_rhs) {
m_linear += t_rhs.m_linear;
m_constant += t_rhs.m_constant;
return *this;
}

template<class Key1, class ValueT>
idol::Expr<Key1, ValueT> &idol::Expr<Key1, ValueT>::operator-=(const Expr &t_rhs) {
idol::AffExpr<Key1, ValueT> &idol::AffExpr<Key1, ValueT>::operator-=(const AffExpr &t_rhs) {
m_linear -= t_rhs.m_linear;
m_constant -= t_rhs.m_constant;
return *this;
}

template<class Key1, class ValueT>
idol::Expr<Key1, ValueT> &idol::Expr<Key1, ValueT>::operator*=(double t_rhs) {
idol::AffExpr<Key1, ValueT> &idol::AffExpr<Key1, ValueT>::operator*=(double t_rhs) {
m_linear *= t_rhs;
m_constant *= t_rhs;
return *this;
}

template<class Key1, class ValueT>
idol::Expr<Key1, ValueT> &idol::Expr<Key1, ValueT>::operator/=(double t_rhs) {
idol::AffExpr<Key1, ValueT> &idol::AffExpr<Key1, ValueT>::operator/=(double t_rhs) {
m_linear /= t_rhs;
m_constant /= t_rhs;
return *this;
Expand All @@ -134,7 +125,7 @@ idol::Expr<Key1, ValueT> &idol::Expr<Key1, ValueT>::operator/=(double t_rhs) {
namespace idol {

template<class Key1, class ValueT>
std::ostream &operator<<(std::ostream &t_os, const idol::Expr<Key1, ValueT> &t_expr) {
std::ostream &operator<<(std::ostream &t_os, const idol::AffExpr<Key1, ValueT> &t_expr) {

if (std::abs(t_expr.constant()) < Tolerance::Sparsity) {

Expand All @@ -154,4 +145,4 @@ namespace idol {

}

#endif //IDOL_EXPR_H
#endif //IDOL_AFFEXPR_H
Loading

0 comments on commit b5125cd

Please sign in to comment.