From d3ce76494e2313d1d6bbf0667886d6c0d4e51c90 Mon Sep 17 00:00:00 2001 From: Henri Lefebvre Date: Thu, 24 Oct 2024 17:21:16 +0200 Subject: [PATCH] mock all methods using exprs in Model --- dev/main.cpp | 8 +- lib/CMakeLists.txt | 8 - .../to_rotated_quadratic_cone.h | 14 +- lib/include/idol/general/utils/Pair.h | 9 + lib/include/idol/general/utils/SparseVector.h | 13 +- lib/include/idol/general/utils/sort.h | 8 +- .../modeling/expressions/AbstractExpr.h | 446 ------------------ .../mixed-integer/modeling/expressions/Expr.h | 89 +--- .../modeling/expressions/LinExpr.h | 101 +--- .../modeling/expressions/QuadExpr.h | 82 +--- .../expressions/operations/operators_Ctr.h | 1 + .../matrix/AbstractMatrixCoefficient.h | 32 -- .../mixed-integer/modeling/matrix/Column.h | 3 +- .../mixed-integer/modeling/matrix/Matrix.h | 36 -- .../modeling/matrix/MatrixCoefficient.h | 29 -- .../matrix/MatrixCoefficientReference.h | 45 -- .../idol/mixed-integer/modeling/matrix/Row.h | 4 +- .../mixed-integer/modeling/models/Model.h | 24 +- .../nodes/DefaultNodeUpdator.h | 1 + .../optimizers/dantzig-wolfe/Formulation.h | 1 + .../optimizers/padm/Formulation.h | 1 + .../mixed-integer/modeling/matrix/Matrix.cpp | 164 ------- .../modeling/matrix/MatrixCoefficient.cpp | 15 - .../matrix/MatrixCoefficientReference.cpp | 20 - lib/src/mixed-integer/modeling/matrix/Row.cpp | 8 +- lib/src/mixed-integer/modeling/models/KKT.cpp | 5 +- .../mixed-integer/modeling/models/Model.cpp | 72 +-- .../optimizers/dantzig-wolfe/Formulation.cpp | 16 +- .../optimizers/padm/Formulation.cpp | 8 +- .../optimizers/padm/Optimizers_PADM.cpp | 4 +- .../wrappers/Gurobi/Optimizers_Gurobi.cpp | 10 +- 31 files changed, 161 insertions(+), 1116 deletions(-) delete mode 100644 lib/include/idol/mixed-integer/modeling/expressions/AbstractExpr.h delete mode 100644 lib/include/idol/mixed-integer/modeling/matrix/AbstractMatrixCoefficient.h delete mode 100644 lib/include/idol/mixed-integer/modeling/matrix/Matrix.h delete mode 100644 lib/include/idol/mixed-integer/modeling/matrix/MatrixCoefficient.h delete mode 100644 lib/include/idol/mixed-integer/modeling/matrix/MatrixCoefficientReference.h delete mode 100644 lib/src/mixed-integer/modeling/matrix/Matrix.cpp delete mode 100644 lib/src/mixed-integer/modeling/matrix/MatrixCoefficient.cpp delete mode 100644 lib/src/mixed-integer/modeling/matrix/MatrixCoefficientReference.cpp diff --git a/dev/main.cpp b/dev/main.cpp index 3e83819d..2d70b099 100644 --- a/dev/main.cpp +++ b/dev/main.cpp @@ -1,8 +1,8 @@ #include -#include "idol/containers/SparseVector.h" -#include "idol/modeling/variables/Var.h" -#include "idol/modeling/models/Model.h" -#include "idol/modeling/objects/Env.h" +#include "idol/general/utils/SparseVector.h" +#include "idol/mixed-integer/modeling/variables/Var.h" +#include "idol/mixed-integer/modeling/models/Model.h" +#include "idol/mixed-integer/modeling/objects/Env.h" using namespace idol; diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 3350bc6a..eda15caa 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -7,11 +7,6 @@ add_library(idol STATIC include/idol/mixed-integer/modeling/Types.h include/idol/mixed-integer/modeling/expressions/Constant.h src/mixed-integer/modeling/expressions/Constant.cpp - include/idol/mixed-integer/modeling/matrix/AbstractMatrixCoefficient.h - include/idol/mixed-integer/modeling/matrix/MatrixCoefficientReference.h - include/idol/mixed-integer/modeling/matrix/MatrixCoefficient.h - src/mixed-integer/modeling/matrix/MatrixCoefficient.cpp - src/mixed-integer/modeling/matrix/MatrixCoefficientReference.cpp include/idol/mixed-integer/modeling/constraints/TempCtr.h src/mixed-integer/modeling/constraints/TempCtr.cpp include/idol/general/utils/IteratorForward.h @@ -23,8 +18,6 @@ add_library(idol STATIC src/mixed-integer/modeling/matrix/Row.cpp src/mixed-integer/modeling/matrix/Column.cpp include/idol/mixed-integer/modeling/matrix/Column.h - include/idol/mixed-integer/modeling/matrix/Matrix.h - src/mixed-integer/modeling/matrix/Matrix.cpp src/mixed-integer/problems/generalized-assignment-problem/GAP_Instance.cpp include/idol/mixed-integer/problems/knapsack-problem/KP_Instance.h src/mixed-integer/problems/knapsack-problem/KP_Instance.cpp @@ -46,7 +39,6 @@ add_library(idol STATIC include/idol/mixed-integer/problems/helpers/parse_delimited.h include/idol/mixed-integer/modeling/expressions/operations/operators_utils.h include/idol/mixed-integer/modeling/expressions/QuadExpr.h - include/idol/mixed-integer/modeling/expressions/AbstractExpr.h include/idol/mixed-integer/modeling/models/Model.h include/idol/mixed-integer/modeling/objects/Env.h include/idol/mixed-integer/modeling/variables/Var.h diff --git a/lib/include/idol/general/linear-algebra/to_rotated_quadratic_cone.h b/lib/include/idol/general/linear-algebra/to_rotated_quadratic_cone.h index c16a4e1e..74d262e2 100644 --- a/lib/include/idol/general/linear-algebra/to_rotated_quadratic_cone.h +++ b/lib/include/idol/general/linear-algebra/to_rotated_quadratic_cone.h @@ -18,19 +18,19 @@ namespace idol { // Create index mapping MatrixIndices indices; - for (const auto &[var1, var2, constant]: t_expr) { - indices.add(var1); - indices.add(var2); + for (const auto &[vars, constant]: t_expr) { + indices.add(vars.first); + indices.add(vars.second); } // Create quadratic form matrix s.t. quadratic_part = x^TQx SquareMatrix Q(indices); - for (const auto &[var1, var2, constant]: t_expr) { - if (var1.id() == var2.id()) { - Q.set(var1, var2, constant); + for (const auto &[vars, constant]: t_expr) { + if (vars.first.id() == vars.second.id()) { + Q.set(vars.first, vars.second, constant); } else { - Q.set(var1, var2, constant / 2.); + Q.set(vars.first, vars.second, constant / 2.); } } diff --git a/lib/include/idol/general/utils/Pair.h b/lib/include/idol/general/utils/Pair.h index d906e790..fcc46f91 100644 --- a/lib/include/idol/general/utils/Pair.h +++ b/lib/include/idol/general/utils/Pair.h @@ -5,6 +5,8 @@ #ifndef IDOL_PAIR_H #define IDOL_PAIR_H +#include + namespace idol { template struct Pair; } @@ -26,4 +28,11 @@ struct idol::Pair { } }; +namespace idol { + template + static std::ostream &operator<<(std::ostream &t_os, const Pair &t_pair) { + return t_os << t_pair.first << " " << t_pair.second; + } +} + #endif //IDOL_PAIR_H diff --git a/lib/include/idol/general/utils/SparseVector.h b/lib/include/idol/general/utils/SparseVector.h index 9cec9c14..ebf5f0b0 100644 --- a/lib/include/idol/general/utils/SparseVector.h +++ b/lib/include/idol/general/utils/SparseVector.h @@ -18,14 +18,15 @@ namespace idol { template, idol::identity, idol::get_id>> class idol::SparseVector { - static_assert(std::is_default_constructible_v); +public: + //static_assert(std::is_default_constructible_v); enum class SortingCriteria { Index, Value, None }; - +private: std::vector m_indices; std::vector m_values; SortingCriteria m_sorting_criteria; @@ -53,6 +54,8 @@ class idol::SparseVector { [[nodiscard]] unsigned int size() const { return m_indices.size(); } + [[nodiscard]] bool empty() const { return m_indices.empty(); } + [[nodiscard]] const IndexT& index_at(unsigned int t_index) const { return m_indices[t_index]; } [[nodiscard]] const ValueT& value_at(unsigned int t_index) const { return m_values[t_index]; } @@ -381,9 +384,9 @@ void idol::SparseVector::remove_at(unsigned int template idol::SparseVector::SparseVector(std::vector t_indices, - std::vector t_values, - SortingCriteria t_sorting_criteria, - bool t_is_reduced) + std::vector t_values, + SortingCriteria t_sorting_criteria, + bool t_is_reduced) : m_indices(std::move(t_indices)), m_values(std::move(t_values)), m_sorting_criteria(t_sorting_criteria), diff --git a/lib/include/idol/general/utils/sort.h b/lib/include/idol/general/utils/sort.h index 6251b5a7..1ae1ba29 100644 --- a/lib/include/idol/general/utils/sort.h +++ b/lib/include/idol/general/utils/sort.h @@ -9,13 +9,14 @@ #include #include #include +#include "idol/general/utils/Pair.h" namespace idol { template struct get_id; template struct get_id> { - auto operator()(const std::pair& t) const { return std::make_pair(get_id(t.first), get_id(t.second)); } + auto operator()(const std::pair& t) const { return std::make_pair(get_id()(t.first), get_id()(t.second)); } }; template @@ -23,6 +24,11 @@ namespace idol { unsigned int operator()(const T& t) const { return t.id(); } }; + template + struct get_id> { + auto operator()(const idol::Pair& t) const { return std::make_pair(get_id()(t.first), get_id()(t.second)); } + }; + template struct identity { const T& operator()(const T& t) const { return t; } diff --git a/lib/include/idol/mixed-integer/modeling/expressions/AbstractExpr.h b/lib/include/idol/mixed-integer/modeling/expressions/AbstractExpr.h deleted file mode 100644 index 13caaf03..00000000 --- a/lib/include/idol/mixed-integer/modeling/expressions/AbstractExpr.h +++ /dev/null @@ -1,446 +0,0 @@ -// -// Created by henri on 21/11/22. -// - -#ifndef IDOL_ABSTRACTEXPR_H -#define IDOL_ABSTRACTEXPR_H - -#include "idol/general/utils/Map.h" -#include "idol/general/utils/IteratorForward.h" -#include "idol/mixed-integer/modeling/matrix/AbstractMatrixCoefficient.h" -#include "Constant.h" -#include "idol/mixed-integer/modeling/expressions/operations/operators_Constant.h" -#include "idol/mixed-integer/modeling/matrix/MatrixCoefficient.h" -#include "idol/mixed-integer/modeling/variables/Var.h" -#include "idol/general/utils/exceptions/Exception.h" -#include "idol/general/utils/Pair.h" -#include -#include -#include -#include -#include - -namespace idol { - - namespace impl { - template - class AbstractExpr; - } - - template - class AbstractExpr; -} - -template -class idol::impl::AbstractExpr { - using MapType = Map, Hash, EqualTo>; - MapType m_map; -protected: - virtual void set(const Key& t_key, double t_coefficient); - virtual double get(const Key& t_key) const; - virtual void remove(const Key& t_key); - void internal_fix(const PrimalPoint& t_primals); - - class References; - References refs(); -public: - AbstractExpr() = default; - - /** - * Copy constructor. - * - * Each term are copied by value. - * - * @param t_src The source object to copy. - */ - AbstractExpr(const AbstractExpr& t_src); - - /** - * Move constructor. - * - * Each term is moved. - * - * In particular, MatrixCoefficientReference-s remain MatrixCoefficientReference-s. - * - * @param t_src - */ - AbstractExpr(AbstractExpr&& t_src) noexcept = default; - - /** - * Assignment operator. - * - * Each term is copied by value. - * - * @param t_src The source object to assign. - * @return The object itself. - */ - AbstractExpr& operator=(const AbstractExpr& t_src); - - /** - * Assignment move operator. - * - * Each term is moved. - * - * In particular, MatrixCoefficientReference-s remain MatrixCoefficientReference-s. - * @param t_src The source object to assign. - * @return The object itself. - */ - AbstractExpr& operator=(AbstractExpr&& t_src) noexcept = default; - - /** - * Adds each term of `t_rhs` to the expression. - * - * Zero entries are removed from the resulting expression. - * - * @param t_rhs the expression whose terms are to be added up. - * @return The object itself. - */ - AbstractExpr& operator+=(const AbstractExpr& t_rhs); - - /** - * Subtracts each term of `t_rhs` to the expression. - * - * Zero entries are removed from the resulting expression. - * - * @param t_rhs The object whose terms are to be subtracted. - * @return The object itself. - */ - AbstractExpr& operator-=(const AbstractExpr& t_rhs); - - /** - * Multiplies every term of the expression by `t_factor`. - * - * If `t_factor` equals zero with tolerance `Tolerance::Sparsity`, then the expression is emptied. - * - * @param t_factor The multiplying factor. - * @return The object itself. - */ - AbstractExpr& operator*=(double t_factor); - - AbstractExpr& operator/=(double t_factor); - - /** - * Returns the size of the expression (i.e., number of non-zero entries which are currently stored). - * - * @return the size of the expression - */ - [[nodiscard]] unsigned int size() const { return m_map.size(); } - - /** - * Returns true if and only if the size is zero. - * - * @return true if and only if the size is zero - */ - [[nodiscard]] bool empty() const { return m_map.empty(); } - - class const_iterator; - - /** - * Returns an iterator pointing to the first term of the expression. - * @return an iterator pointing to the first term of the expression - */ - const_iterator begin() const { return const_iterator(m_map.begin()); } - - /** - * Returns an iterator pointing to the end of the expression. - * @return an iterator pointing to the end the expression - */ - const_iterator end() const { return const_iterator(m_map.end()); } - - /** - * Removes all entries from the expression. - */ - void clear() { m_map.clear(); } - - void round(); - - AbstractExpr multiply_with_precision(double t_factor, unsigned int t_n_digits); - - AbstractExpr multiply_with_precision_by_power_of_10(unsigned int t_exponent, unsigned int t_n_digits); - - long gcd() const; -}; - -template -void idol::impl::AbstractExpr::internal_fix(const idol::PrimalPoint &t_primals) { - - for (auto& [key, ptr_to_value] : m_map) { - ptr_to_value->value() = ptr_to_value->value().fix(t_primals); - } - -} - -template -idol::impl::AbstractExpr -idol::impl::AbstractExpr::multiply_with_precision_by_power_of_10(unsigned int t_exponent, unsigned int t_n_digits) { - - for (const auto& [key, ptr_to_value] : m_map) { - ptr_to_value->value().multiply_with_precision_by_power_of_10(t_exponent, t_n_digits); - } - - return *this; -} - -template -idol::impl::AbstractExpr -idol::impl::AbstractExpr::multiply_with_precision(double t_factor, unsigned int t_n_digits) { - - for (const auto& [key, ptr_to_value] : m_map) { - ptr_to_value->value().multiply_with_precision(t_factor, t_n_digits); - } - - return *this; -} - -template -long idol::impl::AbstractExpr::gcd() const { - long result = 0; - for (const auto& [key, ptr_to_value] : m_map) { - result = std::gcd(result, (long) ptr_to_value->value()); - } - return result; -} - -template -void idol::impl::AbstractExpr::round() { - for (const auto& [key, ptr_to_value] : m_map) { - ptr_to_value->value().round(); - } -} - -template -idol::impl::AbstractExpr::AbstractExpr(const impl::AbstractExpr &t_src) { - - for (const auto& [key, ptr_to_value] : t_src.m_map) { - m_map.template emplace(key, std::make_unique(ptr_to_value->value())); - } - -} - -template -idol::impl::AbstractExpr & -idol::impl::AbstractExpr::operator=(const impl::AbstractExpr &t_src) { - - if (this == &t_src) { - return *this; - } - - m_map.clear(); - for (const auto& [key, ptr_to_value] : t_src.m_map) { - m_map.template emplace(key, std::make_unique(ptr_to_value->value())); - } - - return *this; -} - -template -idol::impl::AbstractExpr & -idol::impl::AbstractExpr::operator+=(const impl::AbstractExpr &t_rhs) { - - for (const auto& [key, ptr_to_value] : t_rhs.m_map) { - auto it = m_map.find(key); - if (it == m_map.end()) { - m_map.template emplace(key, std::make_unique(ptr_to_value->value())); - } else { - it->second->value() += ptr_to_value->value(); - if (std::abs(it->second->value()) < Tolerance::Sparsity) { - m_map.erase(it); - } - } - } - - return *this; - -} - -template -idol::impl::AbstractExpr & -idol::impl::AbstractExpr::operator-=( - const impl::AbstractExpr &t_rhs) { - - for (const auto& [key, ptr_to_value] : t_rhs.m_map) { - auto it = m_map.find(key); - if (it == m_map.end()) { - m_map.template emplace(key, std::make_unique(-ptr_to_value->value())); - } else { - it->second->value() -= ptr_to_value->value(); - if (std::abs(it->second->value()) < Tolerance::Sparsity) { - m_map.erase(it); - } - } - } - return *this; - -} - -template -idol::impl::AbstractExpr & -idol::impl::AbstractExpr::operator*=(double t_factor) { - - if (equals(t_factor, 0., Tolerance::Sparsity)) { - m_map.clear(); - return *this; - } - - for (const auto& [key, ptr_to_value] : m_map) { - ptr_to_value->value() *= t_factor; - } - - return *this; -} - -template -idol::impl::AbstractExpr & -idol::impl::AbstractExpr::operator/=(double t_factor) { - - if (equals(t_factor, 1., Tolerance::Sparsity)) { - return *this; - } - - for (const auto& [key, ptr_to_value] : m_map) { - ptr_to_value->value() /= t_factor; - } - - return *this; -} - -template -void idol::impl::AbstractExpr::set(const Key &t_key, double t_coefficient) { - - if (std::abs(t_coefficient) < Tolerance::Sparsity) { - m_map.erase(t_key); - return; - } - - auto it = m_map.find(t_key); - if (it == m_map.end()) { - m_map.emplace(t_key, std::make_unique(t_coefficient)); - return; - } - - it->second->set_value(t_coefficient); - -} - -template -double idol::impl::AbstractExpr::get(const Key &t_key) const { - auto it = m_map.find(t_key); - return it == m_map.end() ? 0 : it->second->value(); -} - -template -void idol::impl::AbstractExpr::remove(const Key &t_key) { - m_map.erase(t_key); -} - -template -class idol::impl::AbstractExpr::References { - - friend class impl::AbstractExpr; - using ParentT = impl::AbstractExpr; - - ParentT* m_parent; - - explicit References(ParentT* t_parent) : m_parent(t_parent) {} -public: - class iterator { - friend class References; - typename ParentT::MapType::iterator m_it; - public: - explicit iterator(typename ParentT::MapType::iterator&& t_it) : m_it(std::move(t_it)) {} - explicit iterator(const typename ParentT::MapType::iterator& t_it) : m_it(t_it) {} - bool operator!=(const iterator& t_rhs) const { return m_it != t_rhs.m_it; } - bool operator==(const iterator& t_rhs) const { return m_it == t_rhs.m_it; } - iterator& operator++() { ++m_it; return *this; } - std::pair operator*() const { - return { m_it->first, MatrixCoefficientReference(*m_it->second) }; - } - }; - - iterator begin() { return iterator(m_parent->m_map.begin()); } - iterator end() { return iterator(m_parent->m_map.end()); } - - iterator find(const Key& t_key) { return iterator(m_parent->m_map.find(t_key)); } - - iterator emplace(const Key& t_key, MatrixCoefficientReference&& t_coefficient) { - auto [inserted, success] = m_parent->m_map.emplace(t_key, std::make_unique(std::move(t_coefficient))); - if (!success) { throw Exception("Could not insert reference."); } - return iterator(inserted); - } - - void set(const Key& t_key, MatrixCoefficientReference&& t_coefficient) { - if (std::abs(t_coefficient.value()) < Tolerance::Sparsity) { - m_parent->m_map.erase(t_key); - return; - } - emplace(t_key, std::move(t_coefficient)); - } - - iterator erase(const iterator& t_it) { - auto result = m_parent->m_map.erase(t_it.m_it); - return iterator(result); - } -}; - -template -typename idol::impl::AbstractExpr::References idol::impl::AbstractExpr::refs() { - return References(this); -} - -template -class idol::impl::AbstractExpr::const_iterator { - typename AbstractExpr::MapType::const_iterator m_it; -public: - explicit const_iterator(const typename AbstractExpr::MapType::const_iterator& t_it) : m_it(t_it) {} - bool operator!=(const const_iterator& t_rhs) const { return m_it != t_rhs.m_it; } - bool operator==(const const_iterator& t_rhs) const { return m_it == t_rhs.m_it; } - const_iterator operator++() { ++m_it; return *this; } - IteratorOutputT operator*() const { return IteratorOutputT(m_it->first, m_it->second->value()); } -}; - -template, - class Hash = std::hash, - class EqualTo = std::equal_to -> -class idol::AbstractExpr : public impl::AbstractExpr { -public: - AbstractExpr() = default; - AbstractExpr(const AbstractExpr& t_src) = default; - AbstractExpr(AbstractExpr&& t_src) noexcept = default; - - AbstractExpr& operator=(const AbstractExpr& t_src) = default; - AbstractExpr& operator=(AbstractExpr&& t_src) noexcept = default; -}; - -namespace idol { - - template - std::ostream &operator<<(std::ostream &t_os, const AbstractExpr &t_expr) { - - if (t_expr.empty()) { - return t_os << "0"; - } - - auto it = t_expr.begin(); - const auto end = t_expr.end(); - - t_os << *it; - - for (++it; it != end; ++it) { - t_os << " + " << *it; - } - - return t_os; - } - -} - -#endif //IDOL_ABSTRACTEXPR_H diff --git a/lib/include/idol/mixed-integer/modeling/expressions/Expr.h b/lib/include/idol/mixed-integer/modeling/expressions/Expr.h index 8807c73e..376ab43d 100644 --- a/lib/include/idol/mixed-integer/modeling/expressions/Expr.h +++ b/lib/include/idol/mixed-integer/modeling/expressions/Expr.h @@ -7,6 +7,7 @@ #include "LinExpr.h" #include "QuadExpr.h" +#include "idol/general/numericals.h" namespace idol { namespace impl { @@ -22,27 +23,10 @@ template class idol::impl::Expr { LinExpr m_linear; QuadExpr m_quadratic; - std::unique_ptr m_constant; -protected: - class References { - friend class impl::Expr; - using ParentT = impl::Expr; - - ParentT* m_parent; - explicit References(ParentT* t_parent) : m_parent(t_parent) {} - public: - void set_constant(MatrixCoefficientReference&& t_coefficient) { m_parent->m_constant = std::make_unique(std::move(t_coefficient)); } - void reset_constant() { m_parent->m_constant = std::make_unique(0.); } - [[nodiscard]] MatrixCoefficientReference get_constant() const { return MatrixCoefficientReference(*m_parent->m_constant); } - }; - - References refs() { return References(this); } - - void internal_fix(const PrimalPoint& t_primals); + double m_constant = 0.; public: Expr(); - Expr(double t_num); // NOLINT(google-explicit-constructor) - Expr(const Param& t_param); // NOLINT(google-explicit-constructor) + Expr(double t_constant); // NOLINT(google-explicit-constructor) Expr(const Key1& t_var); // NOLINT(google-explicit-constructor) Expr(LinExpr&& t_expr); // NOLINT(google-explicit-constructor) Expr(const LinExpr& t_expr); // NOLINT(google-explicit-constructor) @@ -69,15 +53,17 @@ class idol::impl::Expr { QuadExpr& quadratic() { return m_quadratic; } const QuadExpr& quadratic() const { return m_quadratic; } - double& constant() { return m_constant->value(); } + double& constant() { return m_constant; } - double constant() const { return m_constant->value(); } + double constant() const { return m_constant; } [[nodiscard]] bool is_zero() const { return std::abs(constant()) < Tolerance::Sparsity && linear().empty() && quadratic().empty(); } + /* void round(); [[nodiscard]] double gcd() const; + */ void clear() { constant() = 0; @@ -86,6 +72,7 @@ class idol::impl::Expr { } }; +/* template double idol::impl::Expr::gcd() const { return std::gcd((long) m_constant->value(),std::gcd(m_linear.gcd(), m_quadratic.gcd())); @@ -98,73 +85,54 @@ void idol::impl::Expr::round() { m_linear.round(); m_quadratic.round(); } +*/ template -idol::impl::Expr::Expr() - : m_constant(std::make_unique(0.)) { +idol::impl::Expr::Expr() { } template -idol::impl::Expr::Expr(double t_num) - : m_constant(std::make_unique(t_num)) { +idol::impl::Expr::Expr(double t_constant) : m_constant(t_constant) { } template -idol::impl::Expr::Expr(const Param &t_param) - : m_constant(std::make_unique(t_param)) { +idol::impl::Expr::Expr(const Key1 &t_var) : m_linear(t_var) { } template -idol::impl::Expr::Expr(const Key1 &t_var) - : m_linear(t_var), - m_constant(std::make_unique(0.)) { +idol::impl::Expr::Expr(LinExpr &&t_expr) : m_linear(std::move(t_expr)) { } template -idol::impl::Expr::Expr(LinExpr &&t_expr) - : m_linear(std::move(t_expr)), - m_constant(std::make_unique(0.)) { +idol::impl::Expr::Expr(const LinExpr &t_expr) : m_linear(t_expr) { } template -idol::impl::Expr::Expr(const LinExpr &t_expr) - : m_linear(t_expr), - m_constant(std::make_unique(0.)) { +idol::impl::Expr::Expr(QuadExpr &&t_expr) : m_quadratic(std::move(t_expr)) { } template -idol::impl::Expr::Expr(QuadExpr &&t_expr) - : m_quadratic(std::move(t_expr)), - m_constant(std::make_unique(0.)) { - -} - -template -idol::impl::Expr::Expr(const QuadExpr &t_expr) - : m_quadratic(t_expr), - m_constant(std::make_unique(0.)) { +idol::impl::Expr::Expr(const QuadExpr &t_expr) : m_quadratic(t_expr) { } template idol::impl::Expr::Expr(const LinExpr &t_lin_expr, const QuadExpr &t_quad_expr, double t_constant) : m_linear(t_lin_expr), - m_quadratic(t_quad_expr), - m_constant(std::make_unique(t_constant)) { + m_quadratic(t_quad_expr) { } template idol::impl::Expr::Expr(const Expr &t_src) : m_linear(t_src.m_linear), - m_quadratic(t_src.m_quadratic), - m_constant(std::make_unique(t_src.m_constant->value())) { + m_quadratic(t_src.m_quadratic) { } @@ -173,7 +141,7 @@ idol::impl::Expr &idol::impl::Expr::operator=(const Expr if (this == &t_rhs) { return *this; } m_linear = t_rhs.m_linear; m_quadratic = t_rhs.m_quadratic; - m_constant->value() = t_rhs.m_constant->value(); + m_constant = t_rhs.m_constant; return *this; } @@ -181,7 +149,7 @@ template idol::impl::Expr &idol::impl::Expr::operator+=(const impl::Expr &t_rhs) { m_linear += t_rhs.m_linear; m_quadratic += t_rhs.m_quadratic; - m_constant->value() += t_rhs.m_constant->value(); + m_constant += t_rhs.m_constant; return *this; } @@ -189,7 +157,7 @@ template idol::impl::Expr &idol::impl::Expr::operator-=(const impl::Expr &t_rhs) { m_linear -= t_rhs.m_linear; m_quadratic -= t_rhs.m_quadratic; - m_constant->value() -= t_rhs.m_constant->value(); + m_constant -= t_rhs.m_constant; return *this; } @@ -197,7 +165,7 @@ template idol::impl::Expr &idol::impl::Expr::operator*=(double t_rhs) { m_linear *= t_rhs; m_quadratic *= t_rhs; - m_constant->value() *= t_rhs; + m_constant *= t_rhs; return *this; } @@ -205,17 +173,15 @@ template idol::impl::Expr &idol::impl::Expr::operator/=(double t_rhs) { m_linear /= t_rhs; m_quadratic /= t_rhs; - m_constant->value() /= t_rhs; + m_constant /= t_rhs; return *this; } template class idol::Expr : public impl::Expr { - friend class Matrix; public: Expr() = default; Expr(double t_num) : impl::Expr(t_num) {} // NOLINT(google-explicit-constructor) - Expr(const Param& t_param) : impl::Expr(t_param) {} // NOLINT(google-explicit-constructor) Expr(const Key1& t_var) : impl::Expr(t_var) {} // NOLINT(google-explicit-constructor) Expr(LinExpr&& t_expr) : impl::Expr(std::move(t_expr)) {} // NOLINT(google-explicit-constructor) Expr(const LinExpr& t_expr) : impl::Expr(t_expr) {} // NOLINT(google-explicit-constructor) @@ -228,17 +194,8 @@ class idol::Expr : public impl::Expr { Expr& operator=(const Expr& t_rhs) = default; Expr& operator=(Expr&&) noexcept = default; - - Expr fix(const PrimalPoint& t_primals) const; }; -template -idol::Expr idol::Expr::fix(const PrimalPoint& t_primals) const { - auto result = *this; - result.internal_fix(t_primals); - return result; -} - namespace idol { template diff --git a/lib/include/idol/mixed-integer/modeling/expressions/LinExpr.h b/lib/include/idol/mixed-integer/modeling/expressions/LinExpr.h index b0ef1dea..6d7f3373 100644 --- a/lib/include/idol/mixed-integer/modeling/expressions/LinExpr.h +++ b/lib/include/idol/mixed-integer/modeling/expressions/LinExpr.h @@ -5,15 +5,10 @@ #ifndef OPTIMIZE_EXPR_H #define OPTIMIZE_EXPR_H -#include "idol/general/utils/Map.h" +#include "idol/general/utils/SparseVector.h" #include "idol/general/utils/IteratorForward.h" -#include "idol/mixed-integer/modeling/matrix/AbstractMatrixCoefficient.h" -#include "Constant.h" -#include "idol/mixed-integer/modeling/expressions/operations/operators_Constant.h" -#include "idol/mixed-integer/modeling/matrix/MatrixCoefficient.h" #include "idol/mixed-integer/modeling/variables/Var.h" #include "idol/general/utils/exceptions/Exception.h" -#include "AbstractExpr.h" #include #include #include @@ -21,116 +16,28 @@ #include namespace idol { - template - struct LinTerm; - template class LinExpr; } -template -struct idol::LinTerm { - const Key& key; - const double constant; - LinTerm(const Key& t_key, double t_constant) - : key(t_key), constant(t_constant) {} -}; - /** * @tparam Key the class representing keys */ template -class idol::LinExpr : public AbstractExpr> { - friend class Matrix; +class idol::LinExpr : public SparseVector { public: LinExpr() = default; LinExpr(const Key& t_key); // NOLINT(google-explicit-constructor) LinExpr(double t_factor, const Key& t_key); - - /** - * Sets the value of a key's coefficient - * - * The constant is copied. - * - * Example: - * ```cpp - * LinExpr lin_expr; - * lin_expr.set(x[0], -1); - * ``` - * @param t_key the key - * @param t_coefficient the key's coefficient - */ - void set(const Key& t_key, double t_coefficient); - - /** - * Returns a key's coefficient - * - * Example: - * ```cpp - * LinExpr lin_expr = 2 * x[0] + 3 * x[1]; - * - * std::cout << lin_expr.get(x[0]) << std::endl; // output: 2 - * ``` - * @param t_key the key - * @return the key's coefficient - */ - double get(const Key& t_key) const override; - - /** - * Sets the coefficient of a key to zero - * - * This is equivalent to calling `LinExpr::set` with a zero coefficient. - * @param t_key the key - */ - void remove(const Key& t_key) override; - - LinExpr fix(const PrimalPoint& t_primals) const; }; template -idol::LinExpr idol::LinExpr::fix(const idol::PrimalPoint &t_primals) const { - auto result = *this; - result.internal_fix(t_primals); - return result; -} - -template -void idol::LinExpr::remove(const Key &t_key) { - AbstractExpr>::remove(t_key); -} - -template -double idol::LinExpr::get(const Key &t_key) const { - return AbstractExpr>::get(t_key); -} +idol::LinExpr::LinExpr(const Key &t_key) : SparseVector({ t_key }, { 1. }, SparseVector::SortingCriteria::Index, true) { -template -idol::LinExpr::LinExpr(const Key &t_key) { - set(t_key, 1.); } template -idol::LinExpr::LinExpr(double t_factor, const Key &t_key) { - set(t_key, std::move(t_factor)); -} - -template -void idol::LinExpr::set(const Key &t_key, double t_coefficient) { - AbstractExpr>::set(t_key, t_coefficient); -} - -namespace idol { - - template - std::ostream &operator<<(std::ostream &t_os, const LinTerm &t_term) { - - if (std::abs(t_term.constant) < Tolerance::Sparsity) { - return t_os << "0"; - } - - return t_os << t_term.constant << ' ' << t_term.key; - } - +idol::LinExpr::LinExpr(double t_factor, const Key &t_key) : SparseVector({ t_key }, { t_factor }, SparseVector::SortingCriteria::Index, true) { } #endif //OPTIMIZE_EXPR_H diff --git a/lib/include/idol/mixed-integer/modeling/expressions/QuadExpr.h b/lib/include/idol/mixed-integer/modeling/expressions/QuadExpr.h index 5c262fc5..5a8162cf 100644 --- a/lib/include/idol/mixed-integer/modeling/expressions/QuadExpr.h +++ b/lib/include/idol/mixed-integer/modeling/expressions/QuadExpr.h @@ -5,49 +5,15 @@ #ifndef IDOL_QUADEXPR_H #define IDOL_QUADEXPR_H -#include "AbstractExpr.h" #include "idol/general/utils/Pair.h" namespace idol { template - struct QuadTerm; - - template class QuadExpr; } template -struct idol::QuadTerm { - const Key1& key1; - const Key2& key2; - const double constant; - QuadTerm(const Pair& t_vars, double t_constant) - : key1(t_vars.first), key2(t_vars.second), constant(t_constant) {} -}; - -template, - idol::impl::symmetric_pair_hash, - std::hash> - >, - class EqualTo = std::conditional_t< - std::is_same_v, - idol::impl::symmetric_pair_equal_to, - std::equal_to> - > - > -class idol::QuadExpr : public AbstractExpr, QuadTerm, Hash, EqualTo> { - friend class Matrix; - - using ParentT = AbstractExpr, QuadTerm, Hash, EqualTo>; - using ParentT::get; - using ParentT::set; +class idol::QuadExpr : public SparseVector, double> { public: QuadExpr() = default; QuadExpr(const Key1& t_a, const Key2& t_b); @@ -66,37 +32,35 @@ class idol::QuadExpr : public AbstractExpr, QuadTerm -idol::QuadExpr::QuadExpr(const Key1 &t_a, const Key2 &t_b) { - set(t_a, t_b, 1); -} +template +idol::QuadExpr::QuadExpr(const Key1 &t_a, const Key2 &t_b) + : SparseVector, double>( + { {t_a, t_b} }, + { 1. }, + SparseVector, double>::SortingCriteria::Index, + true) { -template -idol::QuadExpr::QuadExpr(double t_factor, const Key1 &t_a, const Key2 &t_b) { - set(t_a, t_b, t_factor); } -template -void idol::QuadExpr::set(const Key1 &t_a, const Key2& t_b, double t_coefficient) { - return set({ t_a, t_b }, std::move(t_coefficient)); -} +template +idol::QuadExpr::QuadExpr(double t_factor, const Key1 &t_a, const Key2 &t_b) + : SparseVector, double>( + { {t_a, t_b} }, + { t_factor }, + SparseVector, double>::SortingCriteria::Index, + true + ) { -template -double idol::QuadExpr::get(const Key1 &t_a, const Key2 &t_b) const { - return get({ t_a, t_b }); } -namespace idol { - - template - std::ostream &operator<<(std::ostream &t_os, const QuadTerm &t_term) { - if (std::abs(t_term.constant) < Tolerance::Sparsity) { - return t_os << "0"; - } - - return t_os << t_term.constant << ' ' << t_term.key1 << ' ' << t_term.key2; - } +template +void idol::QuadExpr::set(const Key1 &t_a, const Key2& t_b, double t_coefficient) { + return SparseVector, double>::set({ t_a, t_b }, std::move(t_coefficient)); +} +template +double idol::QuadExpr::get(const Key1 &t_a, const Key2 &t_b) const { + return SparseVector, double>::get({ t_a, t_b }); } #endif //IDOL_QUADEXPR_H diff --git a/lib/include/idol/mixed-integer/modeling/expressions/operations/operators_Ctr.h b/lib/include/idol/mixed-integer/modeling/expressions/operations/operators_Ctr.h index 79537d39..85476100 100644 --- a/lib/include/idol/mixed-integer/modeling/expressions/operations/operators_Ctr.h +++ b/lib/include/idol/mixed-integer/modeling/expressions/operations/operators_Ctr.h @@ -6,6 +6,7 @@ #define IDOL_OPERATORS_CTR_H #include "idol/mixed-integer/modeling/expressions/Expr.h" +#include "idol/mixed-integer/modeling/expressions/Constant.h" namespace idol { diff --git a/lib/include/idol/mixed-integer/modeling/matrix/AbstractMatrixCoefficient.h b/lib/include/idol/mixed-integer/modeling/matrix/AbstractMatrixCoefficient.h deleted file mode 100644 index 02c3acf1..00000000 --- a/lib/include/idol/mixed-integer/modeling/matrix/AbstractMatrixCoefficient.h +++ /dev/null @@ -1,32 +0,0 @@ -// -// Created by henri on 07/09/22. -// - -#ifndef OPTIMIZE_ABSTRACTMATRIXCOEFFICIENT_H -#define OPTIMIZE_ABSTRACTMATRIXCOEFFICIENT_H - -namespace idol { - - class Constant; - - class AbstractMatrixCoefficient; -} - -class idol::AbstractMatrixCoefficient { -public: - virtual ~AbstractMatrixCoefficient() = default; - - virtual void set_value(double t_coefficient) = 0; - - virtual double& value() = 0; - - virtual bool is_ref() const = 0; - - [[nodiscard]] virtual double value() const = 0; - - virtual AbstractMatrixCoefficient& operator*=(double t_factor) = 0; - - virtual AbstractMatrixCoefficient& operator+=(const AbstractMatrixCoefficient& t_rhs) = 0; -}; - -#endif //OPTIMIZE_ABSTRACTMATRIXCOEFFICIENT_H diff --git a/lib/include/idol/mixed-integer/modeling/matrix/Column.h b/lib/include/idol/mixed-integer/modeling/matrix/Column.h index af079678..393bff50 100644 --- a/lib/include/idol/mixed-integer/modeling/matrix/Column.h +++ b/lib/include/idol/mixed-integer/modeling/matrix/Column.h @@ -6,8 +6,8 @@ #define OPTIMIZE_COLUMN_H #include -#include "AbstractMatrixCoefficient.h" #include "idol/mixed-integer/modeling/expressions/Expr.h" +#include "idol/mixed-integer/modeling/constraints/Ctr.h" namespace idol { @@ -165,7 +165,6 @@ class idol::impl::Column { * pairs representing the coefficient (`Constant`) of the column in each row (`Ctr`). Such pairs are called components. */ class idol::Column : public impl::Column { - friend class Matrix; public: /** * Default constructor. diff --git a/lib/include/idol/mixed-integer/modeling/matrix/Matrix.h b/lib/include/idol/mixed-integer/modeling/matrix/Matrix.h deleted file mode 100644 index 0135f93c..00000000 --- a/lib/include/idol/mixed-integer/modeling/matrix/Matrix.h +++ /dev/null @@ -1,36 +0,0 @@ -// -// Created by henri on 04/10/22. -// - -#ifndef OPTIMIZE_MATRIX_H -#define OPTIMIZE_MATRIX_H - -#include -#include "idol/mixed-integer/modeling/variables/VarVersion.h" -#include "idol/mixed-integer/modeling/constraints/CtrVersion.h" - -namespace idol { - class Matrix; -} - -class idol::Matrix { - virtual Expr& access_obj() = 0; - virtual LinExpr& access_rhs() = 0; - virtual Column& access_column(const Var& t_var) = 0; - virtual Row& access_row(const Ctr& t_ctr) = 0; -protected: - void add_row_to_columns(const Ctr& t_ctr); - void add_column_to_rows(const Var& t_var); - void remove_row_from_columns(const Ctr& t_ctr); - void remove_column_from_rows(const Var& t_var); - void replace_objective(Expr&& t_objective); - void replace_right_handside(LinExpr&& t_right_handside); - void add_to_obj(const Var& t_var, double t_constant); - void add_to_rhs(const Ctr& t_ctr, double t_constant); - void update_matrix_coefficient(const Ctr &t_ctr, const Var &t_var, double t_constant); -public: - virtual ~Matrix() = default; -}; - - -#endif //OPTIMIZE_MATRIX_H diff --git a/lib/include/idol/mixed-integer/modeling/matrix/MatrixCoefficient.h b/lib/include/idol/mixed-integer/modeling/matrix/MatrixCoefficient.h deleted file mode 100644 index 46437cd3..00000000 --- a/lib/include/idol/mixed-integer/modeling/matrix/MatrixCoefficient.h +++ /dev/null @@ -1,29 +0,0 @@ -// -// Created by henri on 07/09/22. -// - -#ifndef OPTIMIZE_MATRIXCOEFFICIENT_H -#define OPTIMIZE_MATRIXCOEFFICIENT_H - -#include "MatrixCoefficientReference.h" - -namespace idol { - class MatrixCoefficient; -} - -class idol::MatrixCoefficient : public MatrixCoefficientReference { -public: - explicit MatrixCoefficient(double t_coefficient); - - MatrixCoefficient(const MatrixCoefficient&) = delete; - MatrixCoefficient(MatrixCoefficient&&) noexcept = default; - - MatrixCoefficient& operator=(const MatrixCoefficient&) = delete; - MatrixCoefficient& operator=(MatrixCoefficient&&) noexcept = default; - - bool is_ref() const override { return false; } - - ~MatrixCoefficient() override; -}; - -#endif //OPTIMIZE_MATRIXCOEFFICIENT_H diff --git a/lib/include/idol/mixed-integer/modeling/matrix/MatrixCoefficientReference.h b/lib/include/idol/mixed-integer/modeling/matrix/MatrixCoefficientReference.h deleted file mode 100644 index 4c4a5f6f..00000000 --- a/lib/include/idol/mixed-integer/modeling/matrix/MatrixCoefficientReference.h +++ /dev/null @@ -1,45 +0,0 @@ -// -// Created by henri on 07/09/22. -// - -#ifndef OPTIMIZE_MATRIXCOEFFICIENTREFERENCE_H -#define OPTIMIZE_MATRIXCOEFFICIENTREFERENCE_H - -#include "AbstractMatrixCoefficient.h" - - - -namespace idol { - class Constant; - class MatrixCoefficientReference; -} - -class idol::MatrixCoefficientReference : public AbstractMatrixCoefficient { -protected: - double* m_coefficient = nullptr; - explicit MatrixCoefficientReference(double* t_src) : m_coefficient(t_src) {} -public: - explicit MatrixCoefficientReference(AbstractMatrixCoefficient& t_src) : m_coefficient(&t_src.value()) {} - - MatrixCoefficientReference(const MatrixCoefficientReference&) = delete; - MatrixCoefficientReference(MatrixCoefficientReference&&) noexcept = default; - - MatrixCoefficientReference& operator=(const MatrixCoefficientReference&) = delete; - MatrixCoefficientReference& operator=(MatrixCoefficientReference&&) noexcept = default; - - bool is_ref() const override { return true; } - - [[nodiscard]] bool empty() const { return !m_coefficient; } - - void set_value(double t_coefficient) override; - - double &value() override { return *m_coefficient; } - - [[nodiscard]] double value() const override { return *m_coefficient; } - - MatrixCoefficientReference &operator*=(double t_factor) override; - - MatrixCoefficientReference &operator+=(const AbstractMatrixCoefficient &t_rhs) override; -}; - -#endif //OPTIMIZE_MATRIXCOEFFICIENTREFERENCE_H diff --git a/lib/include/idol/mixed-integer/modeling/matrix/Row.h b/lib/include/idol/mixed-integer/modeling/matrix/Row.h index f68c0d84..9353fdf0 100644 --- a/lib/include/idol/mixed-integer/modeling/matrix/Row.h +++ b/lib/include/idol/mixed-integer/modeling/matrix/Row.h @@ -6,8 +6,8 @@ #define OPTIMIZE_ROW_H #include -#include "AbstractMatrixCoefficient.h" #include "idol/mixed-integer/modeling/expressions/Expr.h" +#include "idol/general/utils/Point.h" namespace idol { @@ -119,7 +119,6 @@ class idol::impl::Row { Row& operator/=(double t_rhs) { m_impl /= t_rhs; return *this; } - double gcd() const; }; /** @@ -137,7 +136,6 @@ class idol::impl::Row { * ``` */ class idol::Row : public impl::Row { - friend class Matrix; public: /* * Default constructor. diff --git a/lib/include/idol/mixed-integer/modeling/models/Model.h b/lib/include/idol/mixed-integer/modeling/models/Model.h index 7c08fd8e..53e3ad33 100644 --- a/lib/include/idol/mixed-integer/modeling/models/Model.h +++ b/lib/include/idol/mixed-integer/modeling/models/Model.h @@ -11,13 +11,13 @@ #include "idol/general/utils/Vector.h" -#include "idol/mixed-integer/modeling/matrix/Matrix.h" #include "idol/mixed-integer/modeling/constraints/CtrVersion.h" #include "idol/mixed-integer/modeling/variables/VarVersion.h" #include "idol/mixed-integer/modeling/expressions/Expr.h" #include "idol/general/utils/Point.h" -#include "Model.h" +#include "idol/mixed-integer/modeling/constraints/Ctr.h" +#include "idol/mixed-integer/modeling/variables/Var.h" #include "idol/general/optimizers/Optimizer.h" #include "idol/general/optimizers/OptimizerFactory.h" @@ -39,29 +39,23 @@ namespace idol { /** * This class is used to represent a mathematical optimization model. */ -class idol::Model : public Matrix { +class idol::Model { Env& m_env; const unsigned int m_id; bool m_has_been_moved = false; ObjectiveSense m_sense = Minimize; - Expr m_objective; - LinExpr m_rhs; - + std::unique_ptr> m_objective; + std::unique_ptr> m_rhs; std::vector m_variables; std::vector m_constraints; + bool m_is_row_oriented = true; std::unique_ptr m_optimizer; std::unique_ptr m_optimizer_factory; void throw_if_no_optimizer() const { if (!m_optimizer) { throw Exception("No optimizer was found."); } } - // Matrix hooks - Expr &access_obj() override; - LinExpr &access_rhs() override; - Column &access_column(const Var &t_var) override; - Row &access_row(const Ctr &t_ctr) override; - Model(const Model& t_src); public: /** @@ -83,7 +77,7 @@ class idol::Model : public Matrix { Model& operator=(const Model&) = delete; Model& operator=(Model&&) noexcept = delete; - ~Model() override; + ~Model(); /** * Creates a new decision variable in the model and returns it. @@ -1362,11 +1356,11 @@ namespace idol { stream << '\t' << ctr << ": "; if (linear.empty()) { - stream << quadratic; + stream << "ERROR CANNOT WRITE DOWN QUADRATIC TERMS"; // quadratic; } else { stream << linear; if (!quadratic.empty()) { - stream << " + " << quadratic; + stream << " + " << "ERROR CANNOT WRITE DOWN QUADRATIC TERMS"; //quadratic; } } diff --git a/lib/include/idol/mixed-integer/optimizers/branch-and-bound/nodes/DefaultNodeUpdator.h b/lib/include/idol/mixed-integer/optimizers/branch-and-bound/nodes/DefaultNodeUpdator.h index 41eeaf96..2df81a2e 100644 --- a/lib/include/idol/mixed-integer/optimizers/branch-and-bound/nodes/DefaultNodeUpdator.h +++ b/lib/include/idol/mixed-integer/optimizers/branch-and-bound/nodes/DefaultNodeUpdator.h @@ -7,6 +7,7 @@ #include "NodeUpdator.h" #include "idol/mixed-integer/modeling/models/Model.h" +#include "idol/general/utils/Map.h" #include "Node.h" #include "DefaultNodeInfo.h" #include "BranchingDecision.h" diff --git a/lib/include/idol/mixed-integer/optimizers/dantzig-wolfe/Formulation.h b/lib/include/idol/mixed-integer/optimizers/dantzig-wolfe/Formulation.h index 94a1175c..b9770c71 100644 --- a/lib/include/idol/mixed-integer/optimizers/dantzig-wolfe/Formulation.h +++ b/lib/include/idol/mixed-integer/optimizers/dantzig-wolfe/Formulation.h @@ -7,6 +7,7 @@ #include "idol/mixed-integer/modeling/models/Model.h" #include "idol/general/utils/GeneratorPool.h" +#include "idol/general/utils/Map.h" namespace idol::DantzigWolfe { class Formulation; diff --git a/lib/include/idol/mixed-integer/optimizers/padm/Formulation.h b/lib/include/idol/mixed-integer/optimizers/padm/Formulation.h index cf041a56..2f681b50 100644 --- a/lib/include/idol/mixed-integer/optimizers/padm/Formulation.h +++ b/lib/include/idol/mixed-integer/optimizers/padm/Formulation.h @@ -8,6 +8,7 @@ #include #include "idol/mixed-integer/modeling/models/Model.h" +#include "idol/general/utils/Map.h" namespace idol { class PenaltyUpdate; diff --git a/lib/src/mixed-integer/modeling/matrix/Matrix.cpp b/lib/src/mixed-integer/modeling/matrix/Matrix.cpp deleted file mode 100644 index 51d11e9a..00000000 --- a/lib/src/mixed-integer/modeling/matrix/Matrix.cpp +++ /dev/null @@ -1,164 +0,0 @@ -// -// Created by henri on 04/10/22. -// -#include -#include "idol/mixed-integer/modeling/matrix/Matrix.h" -#include "idol/mixed-integer/modeling/models/Model.h" - -void idol::Matrix::add_row_to_columns(const Ctr &t_ctr) { - - auto& row = access_row(t_ctr); - - for (auto [var, ref] : row.linear().refs()) { - access_column(var).linear().refs().set(t_ctr, std::move(ref)); - } - - for (auto [pair, ref] : row.quadratic().refs()) { - access_column(pair.first).quadratic().refs().set({ t_ctr, pair.second }, std::move(ref)); - } - for (auto [pair, ref] : row.quadratic().refs()) { - if (pair.first.id() != pair.second.id()) { - access_column(pair.second).quadratic().refs().set({t_ctr, pair.first}, std::move(ref)); - } - } - - if (std::abs(row.rhs()) >= Tolerance::Sparsity) { - auto &rhs = access_rhs(); - rhs.refs().set(t_ctr, row.impl().refs().get_constant()); - } -} - -void idol::Matrix::add_column_to_rows(const Var &t_var) { - - auto& column = access_column(t_var); - - for (auto [ctr, ref] : column.linear().refs()) { - access_row(ctr).linear().refs().set(t_var, std::move(ref)); - } - - for (auto [pair, ref] : column.quadratic().refs()) { - access_row(pair.first).quadratic().refs().set({ t_var, pair.second }, std::move(ref)); - } - for (auto [pair, ref] : column.quadratic().refs()) { - access_column(pair.second).quadratic().refs().set({ pair.first, t_var }, std::move(ref)); - } - - if (std::abs(column.obj()) >= Tolerance::Sparsity) { - auto &obj = access_obj(); - obj.linear().refs().set(t_var, column.impl().refs().get_constant()); - } -} - -void idol::Matrix::remove_row_from_columns(const Ctr &t_ctr) { - auto& row = access_row(t_ctr); - for (const auto& [var, ptr_to_coeff] : row.linear().refs()) { - access_column(var).impl().linear().remove(t_ctr); - } - for (const auto& [pair, ptr_to_coeff] : row.quadratic().refs()) { - access_column(pair.first).impl().quadratic().remove({ t_ctr, pair.second }); - if (pair.first.id() != pair.second.id()) { - access_column(pair.second).impl().quadratic().remove({ t_ctr, pair.first }); - } - } - - auto& rhs = access_rhs(); - rhs.remove(t_ctr); -} - -void idol::Matrix::remove_column_from_rows(const Var &t_var) { - auto& column = access_column(t_var); - for (const auto& [ctr, ptr_to_coeff] : column.impl().linear().refs()) { - access_row(ctr).linear().remove(t_var); - } - for (const auto& [pair, ptr_to_coeff] : column.impl().quadratic().refs()) { - access_row(pair.first).quadratic().remove({ t_var, pair.second }); - } - - auto& obj = access_obj(); - obj.linear().remove(t_var); -} - -void idol::Matrix::replace_objective(Expr &&t_objective) { - auto& obj = access_obj(); - - for (const auto& [var, coeff] : obj.linear()) { - access_column(var).impl().refs().reset_constant(); - } - - obj = std::move(t_objective); - - for (auto [var, ref] : obj.linear().refs()) { - access_column(var).impl().refs().set_constant(std::move(ref)); - } - -} - -void idol::Matrix::replace_right_handside(LinExpr &&t_right_handside) { - auto& rhs = access_rhs(); - - for (const auto& [ctr, coeff] : rhs) { - access_row(ctr).impl().refs().reset_constant(); - } - - rhs = std::move(t_right_handside); - - for (auto [ctr, ref] : rhs.refs()) { - access_row(ctr).impl().refs().set_constant(std::move(ref)); - } -} - -void idol::Matrix::add_to_obj(const Var& t_var, double t_constant) { - - auto& column = access_column(t_var); - - if (std::abs(column.obj()) < Tolerance::Sparsity) { - column.set_obj(t_constant); - access_obj().linear().refs().set(t_var, column.impl().refs().get_constant()); - return; - } - - if (std::abs(t_constant) < Tolerance::Sparsity) { - access_obj().linear().remove(t_var); - } - column.set_obj(t_constant); - -} - -void idol::Matrix::add_to_rhs(const Ctr &t_ctr, double t_constant) { - - auto& row = access_row(t_ctr); - - if (std::abs(row.rhs()) < Tolerance::Sparsity && std::abs(t_constant) >= Tolerance::Sparsity) { - row.set_rhs(t_constant); - access_rhs().refs().set(t_ctr, row.impl().refs().get_constant()); - return; - } - - if (std::abs(t_constant) < Tolerance::Sparsity) { - access_rhs().remove(t_ctr); - } - - row.set_rhs(t_constant); - -} - -void idol::Matrix::update_matrix_coefficient(const Ctr &t_ctr, const Var &t_var, double t_constant) { - - if (std::abs(t_constant) < Tolerance::Sparsity) { - access_column(t_var).impl().linear().remove(t_ctr); - access_row(t_ctr).linear().remove(t_var); - return; - } - - auto& column = access_column(t_var); - - auto it = column.impl().linear().refs().find(t_ctr); - - if (it == column.impl().linear().refs().end()) { - auto inserted = column.impl().linear().refs().emplace(t_ctr, MatrixCoefficient(t_constant)); - access_row(t_ctr).linear().refs().emplace(t_var, (*inserted).second); - } else { - (*it).second.value() = t_constant; - } - -} diff --git a/lib/src/mixed-integer/modeling/matrix/MatrixCoefficient.cpp b/lib/src/mixed-integer/modeling/matrix/MatrixCoefficient.cpp deleted file mode 100644 index 9d20080e..00000000 --- a/lib/src/mixed-integer/modeling/matrix/MatrixCoefficient.cpp +++ /dev/null @@ -1,15 +0,0 @@ -// -// Created by henri on 07/09/22. -// -#include "idol/mixed-integer/modeling/matrix/MatrixCoefficient.h" -#include "idol/mixed-integer/modeling/expressions/Constant.h" - -idol::MatrixCoefficient::~MatrixCoefficient() { - delete m_coefficient; -} - -idol::MatrixCoefficient::MatrixCoefficient(double t_coefficient) - : MatrixCoefficientReference(new double(t_coefficient)){ - -} - diff --git a/lib/src/mixed-integer/modeling/matrix/MatrixCoefficientReference.cpp b/lib/src/mixed-integer/modeling/matrix/MatrixCoefficientReference.cpp deleted file mode 100644 index 0c3f6f84..00000000 --- a/lib/src/mixed-integer/modeling/matrix/MatrixCoefficientReference.cpp +++ /dev/null @@ -1,20 +0,0 @@ -// -// Created by henri on 08/09/22. -// -#include "idol/mixed-integer/modeling/matrix/MatrixCoefficientReference.h" -#include "idol/mixed-integer/modeling/expressions/Constant.h" - -void idol::MatrixCoefficientReference::set_value(double t_coefficient) { - *m_coefficient = t_coefficient; -} - -idol::MatrixCoefficientReference &idol::MatrixCoefficientReference::operator*=(double t_factor) { - *m_coefficient *= t_factor; - return *this; -} - -idol::MatrixCoefficientReference &idol::MatrixCoefficientReference::operator+=(const AbstractMatrixCoefficient &t_rhs) { - *m_coefficient += t_rhs.value(); - return *this; -} - diff --git a/lib/src/mixed-integer/modeling/matrix/Row.cpp b/lib/src/mixed-integer/modeling/matrix/Row.cpp index e5e20012..8d89e938 100644 --- a/lib/src/mixed-integer/modeling/matrix/Row.cpp +++ b/lib/src/mixed-integer/modeling/matrix/Row.cpp @@ -17,8 +17,8 @@ double idol::Row::value(const idol::PrimalPoint &t_primals) const { result += constant * t_primals.get(var); } - for (const auto& [var1, var2, constant] : quadratic()) { - result += constant * t_primals.get(var1) * t_primals.get(var2); + for (const auto& [vars, constant] : quadratic()) { + result += constant * t_primals.get(vars.first) * t_primals.get(vars.second); } return result; @@ -74,7 +74,3 @@ idol::impl::Row::Row(const ::idol::Expr &t_lhs, const ::idol::Expr &t_ ) { } - -double idol::impl::Row::gcd() const { - return m_impl.gcd(); -} diff --git a/lib/src/mixed-integer/modeling/models/KKT.cpp b/lib/src/mixed-integer/modeling/models/KKT.cpp index e7a3d6a6..0b346183 100644 --- a/lib/src/mixed-integer/modeling/models/KKT.cpp +++ b/lib/src/mixed-integer/modeling/models/KKT.cpp @@ -176,7 +176,10 @@ void idol::Reformulators::KKT::create_dual_constraint(const idol::Var &t_var) { } - for (const auto& [ctr, var, constant] : col.quadratic()) { + for (const auto& [pair, constant] : col.quadratic()) { + + const auto& ctr = pair.first; + const auto& var = pair.second; if (m_description.is_leader(ctr)) { continue; diff --git a/lib/src/mixed-integer/modeling/models/Model.cpp b/lib/src/mixed-integer/modeling/models/Model.cpp index e9816322..d834f301 100644 --- a/lib/src/mixed-integer/modeling/models/Model.cpp +++ b/lib/src/mixed-integer/modeling/models/Model.cpp @@ -11,13 +11,10 @@ idol::Model::Model(idol::Env &t_env, idol::ObjectiveSense t_sense) : Model(t_env set_obj_sense(t_sense); } - idol::Model::Model(idol::Model && t_src) noexcept : m_env(t_src.m_env), m_id(t_src.m_id), m_sense(t_src.m_sense), - m_objective(std::move(t_src.m_objective)), - m_rhs(std::move(t_src.m_rhs)), m_variables(std::move(t_src.m_variables)), m_constraints(std::move(t_src.m_constraints)), m_optimizer_factory(std::move(t_src.m_optimizer_factory)) @@ -64,7 +61,8 @@ void idol::Model::add(const Var &t_var, TempVar t_temp_var) { optimizer().add(t_var); } - add_column_to_rows(t_var); + // add_column_to_rows(t_var); + throw Exception("Model. Work in progress..."); } void idol::Model::add(const Var &t_var) { @@ -83,7 +81,8 @@ void idol::Model::remove(const Var &t_var) { optimizer().remove(t_var); } - remove_column_from_rows(t_var); + // remove_column_from_rows(t_var); + throw Exception("Model. Work in progress..."); const auto index = m_env.version(*this, t_var).index(); m_env.version(*this, m_variables.back()).set_index(index); m_variables[index] = m_variables.back(); @@ -97,7 +96,8 @@ void idol::Model::remove(const Ctr &t_ctr) { optimizer().remove(t_ctr); } - remove_row_from_columns(t_ctr); + //remove_row_from_columns(t_ctr); + throw Exception("Model. Work in progress..."); const auto index = m_env.version(*this, t_ctr).index(); m_env.version(*this, m_constraints.back()).set_index(index); m_constraints[index] = m_constraints.back(); @@ -113,7 +113,8 @@ void idol::Model::add(const Ctr &t_ctr, TempCtr t_temp_ctr) { optimizer().add(t_ctr); } - add_row_to_columns(t_ctr); + //add_row_to_columns(t_ctr); + throw Exception("Model. Work in progress..."); } void idol::Model::add(const Ctr &t_ctr) { @@ -124,32 +125,22 @@ void idol::Model::add(const Ctr &t_ctr) { ); } -idol::Expr &idol::Model::access_obj() { - return m_objective; -} - -idol::LinExpr &idol::Model::access_rhs() { - return m_rhs; -} - -idol::Column &idol::Model::access_column(const Var &t_var) { - return m_env.version(*this, t_var).column(); -} - -idol::Row &idol::Model::access_row(const Ctr &t_ctr) { - return m_env.version(*this, t_ctr).row(); -} - idol::ObjectiveSense idol::Model::get_obj_sense() const { return m_sense; } const idol::Expr &idol::Model::get_obj_expr() const { - return m_objective; + if (!m_objective) { + throw Exception("Objective expression is not available."); + } + return *m_objective; } const idol::LinExpr &idol::Model::get_rhs_expr() const { - return m_rhs; + if (!m_rhs) { + throw Exception("Right hand side expression is not available."); + } + return *m_rhs; } double idol::Model::get_mat_coeff(const Ctr &t_ctr, const Var &t_var) const { @@ -306,7 +297,8 @@ void idol::Model::set_obj_expr(const Expr &t_objective) { void idol::Model::set_obj_expr(Expr &&t_objective) { - replace_objective(Expr(t_objective)); + //replace_objective(Expr(t_objective)); + throw Exception("Model. Work in progress..."); if (has_optimizer()) { optimizer().update_obj(); @@ -320,7 +312,8 @@ void idol::Model::set_rhs_expr(const LinExpr &t_rhs) { void idol::Model::set_rhs_expr(LinExpr &&t_rhs) { - replace_right_handside(LinExpr(t_rhs)); + //replace_right_handside(LinExpr(t_rhs)); + throw Exception("Model. Work in progress..."); if (has_optimizer()) { optimizer().update_rhs(); @@ -330,7 +323,7 @@ void idol::Model::set_rhs_expr(LinExpr &&t_rhs) { void idol::Model::set_obj_const(double t_constant) { - m_objective.constant() = t_constant; + m_objective->constant() = t_constant; if (has_optimizer()) { optimizer().update_obj_constant(); @@ -340,7 +333,8 @@ void idol::Model::set_obj_const(double t_constant) { void idol::Model::set_mat_coeff(const Ctr &t_ctr, const Var &t_var, double t_coeff) { - update_matrix_coefficient(t_ctr, t_var, t_coeff); + throw Exception("Model. Work in progress..."); + // update_matrix_coefficient(t_ctr, t_var, t_coeff); if (has_optimizer()) { optimizer().update(); @@ -351,7 +345,8 @@ void idol::Model::set_mat_coeff(const Ctr &t_ctr, const Var &t_var, double t_coe void idol::Model::set_ctr_rhs(const Ctr &t_ctr, double t_rhs) { - add_to_rhs(t_ctr, t_rhs); + throw Exception("Model. Work in progress..."); + // add_to_rhs(t_ctr, t_rhs); if (has_optimizer()) { optimizer().update_ctr_rhs(t_ctr); @@ -389,11 +384,13 @@ void idol::Model::set_ctr_row(const Ctr &t_ctr, Row &&t_row) { } - remove_row_from_columns(t_ctr); + throw Exception("Model. Work in progress..."); + //remove_row_from_columns(t_ctr); m_env.version(*this, t_ctr).row() = std::move(t_row); - add_row_to_columns(t_ctr); + throw Exception("Model. Work in progress..."); + //add_row_to_columns(t_ctr); // TODO: Do this properly if (has_optimizer()) { @@ -445,7 +442,8 @@ void idol::Model::set_var_ub(const Var &t_var, double t_ub) { void idol::Model::set_var_obj(const Var &t_var, double t_obj) { - add_to_obj(t_var, std::move(t_obj)); + throw Exception("Model. Work in progress..."); + //add_to_obj(t_var, std::move(t_obj)); if (has_optimizer()) { optimizer().update_var_obj(t_var); @@ -459,11 +457,13 @@ void idol::Model::set_var_column(const Var &t_var, const Column &t_column) { void idol::Model::set_var_column(const Var &t_var, Column &&t_column) { - remove_column_from_rows(t_var); + throw Exception("Model. Work in progress..."); + //remove_column_from_rows(t_var); m_env.version(*this, t_var).column() = std::move(t_column); - add_column_to_rows(t_var); + throw Exception("Model. Work in progress..."); + //add_column_to_rows(t_var); if (has_optimizer()) { throw Exception("Updating column is not implemented."); @@ -512,7 +512,7 @@ idol::Var idol::Model::get_var_by_index(unsigned int t_index) const { } idol::Model idol::Model::copy() const { - return Model(*this); + return Model(*this); // NOLINT(*-return-braced-init-list) } void idol::Model::reserve_vars(unsigned int t_size) { diff --git a/lib/src/mixed-integer/optimizers/dantzig-wolfe/Formulation.cpp b/lib/src/mixed-integer/optimizers/dantzig-wolfe/Formulation.cpp index 770bfdae..a5154842 100644 --- a/lib/src/mixed-integer/optimizers/dantzig-wolfe/Formulation.cpp +++ b/lib/src/mixed-integer/optimizers/dantzig-wolfe/Formulation.cpp @@ -108,9 +108,9 @@ void idol::DantzigWolfe::Formulation::set_decomposition_by_var(const Model& t_or set_decomposition_by_var(var, sub_problem_id); } - for (const auto &[var1, var2, constant]: row.quadratic()) { - set_decomposition_by_var(var1, sub_problem_id); - set_decomposition_by_var(var2, sub_problem_id); + for (const auto &[vars, constant]: row.quadratic()) { + set_decomposition_by_var(vars.first, sub_problem_id); + set_decomposition_by_var(vars.second, sub_problem_id); } } @@ -227,21 +227,21 @@ idol::DantzigWolfe::Formulation::decompose_expression(const LinExpr &t_line } - for (const auto& [var1, var2, constant] : t_quadratic) { + for (const auto& [vars, constant] : t_quadratic) { - const unsigned int sub_problem_id1 = var1.get(m_decomposition_by_var); - const unsigned int sub_problem_id2 = var2.get(m_decomposition_by_var); + const unsigned int sub_problem_id1 = vars.first.get(m_decomposition_by_var); + const unsigned int sub_problem_id2 = vars.second.get(m_decomposition_by_var); if (sub_problem_id1 != sub_problem_id2) { throw Exception("Impossible decomposition."); } if (sub_problem_id1 == MasterId) { - master_part += constant * var1 * var2; + master_part += constant * vars.first * vars.second; continue; } - sub_problem_parts[sub_problem_id1] += constant * (!var1 * !var2); + sub_problem_parts[sub_problem_id1] += constant * (!vars.first * !vars.second); } diff --git a/lib/src/mixed-integer/optimizers/padm/Formulation.cpp b/lib/src/mixed-integer/optimizers/padm/Formulation.cpp index 73974f3d..f895b822 100644 --- a/lib/src/mixed-integer/optimizers/padm/Formulation.cpp +++ b/lib/src/mixed-integer/optimizers/padm/Formulation.cpp @@ -267,8 +267,8 @@ void idol::ADM::Formulation::fix_sub_problem(unsigned int t_sub_problem_id, lhs += fix(coefficient, t_primals) * var; } - for (const auto& [var1, var2, coefficient] : pattern.quadratic()) { - lhs += fix(coefficient, t_primals) * var1 * var2; + for (const auto& [vars, coefficient] : pattern.quadratic()) { + lhs += fix(coefficient, t_primals) * vars.first * vars.second; } m_sub_problems[t_sub_problem_id].set_ctr_row(ctr, Row(std::move(lhs), 0)); @@ -283,8 +283,8 @@ void idol::ADM::Formulation::fix_sub_problem(unsigned int t_sub_problem_id, obj += fix(coefficient, t_primals) * var; } - for (const auto& [var1, var2, coefficient] : obj_pattern.quadratic()) { - obj += fix(coefficient, t_primals) * var1 * var2; + for (const auto& [vars, coefficient] : obj_pattern.quadratic()) { + obj += fix(coefficient, t_primals) * vars.first * vars.second; } m_sub_problems[t_sub_problem_id].set_obj_expr(std::move(obj)); diff --git a/lib/src/mixed-integer/optimizers/padm/Optimizers_PADM.cpp b/lib/src/mixed-integer/optimizers/padm/Optimizers_PADM.cpp index 486851e1..2b2a2ab5 100644 --- a/lib/src/mixed-integer/optimizers/padm/Optimizers_PADM.cpp +++ b/lib/src/mixed-integer/optimizers/padm/Optimizers_PADM.cpp @@ -428,8 +428,8 @@ void idol::Optimizers::PADM::compute_objective_value() { result += constant * get_var_primal(var); } - for (const auto& [var1, var2, constant] : obj.quadratic()) { - result += constant * get_var_primal(var1) * get_var_primal(var2); + for (const auto& [vars, constant] : obj.quadratic()) { + result += constant * get_var_primal(vars.first) * get_var_primal(vars.second); } set_best_obj(result); diff --git a/lib/src/mixed-integer/optimizers/wrappers/Gurobi/Optimizers_Gurobi.cpp b/lib/src/mixed-integer/optimizers/wrappers/Gurobi/Optimizers_Gurobi.cpp index 5121c490..f2006d6d 100644 --- a/lib/src/mixed-integer/optimizers/wrappers/Gurobi/Optimizers_Gurobi.cpp +++ b/lib/src/mixed-integer/optimizers/wrappers/Gurobi/Optimizers_Gurobi.cpp @@ -175,8 +175,8 @@ std::variant idol::Optimizers::Gurobi::hook_add(const Ctr for (const auto &[var, constant]: row.linear()) { expr.addTerm(constant, lazy(var).impl()); } - for (const auto& [var1, var2, constant] : row.quadratic()) { - expr.addTerm(constant, lazy(var1).impl(), lazy(var2).impl()); + for (const auto& [vars, constant] : row.quadratic()) { + expr.addTerm(constant, lazy(vars.first).impl(), lazy(vars.second).impl()); } GUROBI_CATCH(return m_model.addQConstr(expr, type, rhs, name);) @@ -237,8 +237,8 @@ void idol::Optimizers::Gurobi::hook_update_objective() { GRBQuadExpr quadratic_expr; - for (const auto& [var1, var2, constant] : objective.quadratic()) { - quadratic_expr.addTerm(gurobi_numeric(constant), lazy(var1).impl(), lazy(var2).impl()); + for (const auto& [vars, constant] : objective.quadratic()) { + quadratic_expr.addTerm(gurobi_numeric(constant), lazy(vars.first).impl(), lazy(vars.second).impl()); } m_model.setObjective(linear_expr + quadratic_expr, sense); @@ -317,7 +317,7 @@ void idol::Optimizers::Gurobi::set_param_time_limit(double t_time_limit) { } void idol::Optimizers::Gurobi::set_param_threads(unsigned int t_thread_limit) { - m_model.set(GRB_IntParam_Threads, t_thread_limit); + m_model.set(GRB_IntParam_Threads, (int) t_thread_limit); Optimizer::set_param_threads(t_thread_limit); }