Skip to content

Commit

Permalink
add InternalLinExpr
Browse files Browse the repository at this point in the history
  • Loading branch information
hlefebvr committed Oct 28, 2024
1 parent 749599c commit c9b6111
Show file tree
Hide file tree
Showing 12 changed files with 95 additions and 38 deletions.
2 changes: 2 additions & 0 deletions lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,8 @@ add_library(idol STATIC
include/idol/general/utils/sort.h
include/idol/general/utils/Point.h
src/mixed-integer/modeling/variables/VarVersion.cpp
include/idol/mixed-integer/modeling/expressions/InternalLinExpr.h
src/mixed-integer/modeling/expressions/InternalLinExpr.cpp
)

find_package(OpenMP REQUIRED)
Expand Down
56 changes: 30 additions & 26 deletions lib/include/idol/general/utils/SparseVector.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ class idol::SparseVector {
Value,
None
};

protected:
using IndexRawT = typename std::invoke_result<idol::get_id<IndexT>, const IndexT&>::type;
virtual IndexRawT get_raw_index(const IndexT& t_index) const { return IndexExtractorT()(t_index); }
private:
std::vector<IndexT> m_indices;
std::vector<ValueT> m_values;
Expand Down Expand Up @@ -217,7 +221,7 @@ idol::SparseVector<IndexT, ValueT, IndexExtractorT>::binary_operation_on_sorted_

SparseVector result;

if (IndexExtractorT()(m_indices.back()) < IndexExtractorT()(t_vec2.m_indices.front())) {
if (get_raw_index(m_indices.back()) < get_raw_index(t_vec2.m_indices.front())) {
/**
* The last index of the first vector is less than the first index of the second vector.
* We can simply concatenate the vectors.
Expand All @@ -233,7 +237,7 @@ idol::SparseVector<IndexT, ValueT, IndexExtractorT>::binary_operation_on_sorted_
return *this;
}

if (IndexExtractorT()(t_vec2.m_indices.back()) < IndexExtractorT()(m_indices.front())) {
if (get_raw_index(t_vec2.m_indices.back()) < get_raw_index(m_indices.front())) {
/**
* The last index of the second vector is less than the first index of the first vector.
* We can simply concatenate the vectors.
Expand Down Expand Up @@ -264,13 +268,13 @@ idol::SparseVector<IndexT, ValueT, IndexExtractorT>::binary_operation_on_sorted_
const auto& index1 = index_at(i);
const auto& index2 = t_vec2.index_at(j);

if (IndexExtractorT()(index1) < IndexExtractorT()(index2)) {
if (get_raw_index(index1) < get_raw_index(index2)) {
result.push_back(index1, t_operation(value_at(i), ValueT{}));
++i;
continue;
}

if (IndexExtractorT()(index2) < IndexExtractorT()(index1)) {
if (get_raw_index(index2) < get_raw_index(index1)) {
result.push_back(index2, t_operation(ValueT{}, t_vec2.value_at(j)));
++j;
continue;
Expand Down Expand Up @@ -312,7 +316,7 @@ void idol::SparseVector<IndexT, ValueT, IndexExtractorT>::set(const IndexT &t_in
m_indices.begin(),
m_indices.end(),
t_index,
[](const IndexT& t_index1, const IndexT& t_index2) { return IndexExtractorT()(t_index1) < IndexExtractorT()(t_index2); }
[this](const IndexT& t_index1, const IndexT& t_index2) { return get_raw_index(t_index1) < get_raw_index(t_index2); }
);

if (it == m_indices.end()) {
Expand All @@ -321,7 +325,7 @@ void idol::SparseVector<IndexT, ValueT, IndexExtractorT>::set(const IndexT &t_in
return;
}

if (IndexExtractorT()(*it) != IndexExtractorT()(t_index)) {
if (get_raw_index(*it) != get_raw_index(t_index)) {
m_indices.insert(it, t_index);
m_values.insert(m_values.begin() + (it - m_indices.begin()), t_value);
return;
Expand All @@ -330,7 +334,7 @@ void idol::SparseVector<IndexT, ValueT, IndexExtractorT>::set(const IndexT &t_in
m_values[it - m_indices.begin()] = t_value;

for (unsigned int i = it - m_indices.begin() + 1, n = m_indices.size() ; i < n ; ++i) {
if (IndexExtractorT()(m_indices[i]) == IndexExtractorT()(t_index)) {
if (get_raw_index(m_indices[i]) == get_raw_index(t_index)) {
m_values[i] = 0;
}
}
Expand All @@ -347,7 +351,7 @@ void idol::SparseVector<IndexT, ValueT, IndexExtractorT>::set(const IndexT &t_in

bool found = false;
for (unsigned int i = 0, n = m_indices.size() ; i < n ; ++i) {
if (IndexExtractorT()(m_indices[i]) == IndexExtractorT()(t_index)) {
if (get_raw_index(m_indices[i]) == get_raw_index(t_index)) {
m_values[i] = found ? 0 : t_value;
found = true;
}
Expand All @@ -367,7 +371,7 @@ void idol::SparseVector<IndexT, ValueT, IndexExtractorT>::set(const IndexT &t_in
*/

for (unsigned int i = 0, n = m_indices.size() ; i < n ; ++i) {
if (IndexExtractorT()(m_indices[i]) == IndexExtractorT()(t_index)) {
if (get_raw_index(m_indices[i]) == get_raw_index(t_index)) {
m_values[i] = t_value;
return;
}
Expand All @@ -387,7 +391,7 @@ void idol::SparseVector<IndexT, ValueT, IndexExtractorT>::set(const IndexT &t_in
m_indices.begin(),
m_indices.end(),
t_index,
[](const IndexT& t_index1, const IndexT& t_index2) { return IndexExtractorT()(t_index1) < IndexExtractorT()(t_index2); }
[this](const IndexT& t_index1, const IndexT& t_index2) { return get_raw_index(t_index1) < get_raw_index(t_index2); }
);

if (it == m_indices.end()) {
Expand All @@ -396,7 +400,7 @@ void idol::SparseVector<IndexT, ValueT, IndexExtractorT>::set(const IndexT &t_in
return;
}

if (IndexExtractorT()(*it) != IndexExtractorT()(t_index)) {
if (get_raw_index(*it) != get_raw_index(t_index)) {
m_indices.insert(it, t_index);
m_values.insert(m_values.begin() + (it - m_indices.begin()), t_value);
return;
Expand Down Expand Up @@ -457,10 +461,10 @@ void idol::SparseVector<IndexT, ValueT, IndexExtractorT>::push_back(const IndexT

const auto &last_index = m_indices.back();

if (IndexExtractorT()(last_index) > IndexExtractorT()(t_index)) {
if (get_raw_index(last_index) > get_raw_index(t_index)) {
m_sorting_criteria = SortingCriteria::None;
m_is_reduced = false;
} else if (IndexExtractorT()(last_index) == IndexExtractorT()(t_index)) {
} else if (get_raw_index(last_index) == get_raw_index(t_index)) {
m_is_reduced = false;
}

Expand All @@ -471,7 +475,7 @@ void idol::SparseVector<IndexT, ValueT, IndexExtractorT>::push_back(const IndexT

} else {
if (m_sorting_criteria == SortingCriteria::Index) {
if (IndexExtractorT()(m_indices.back()) > IndexExtractorT()(t_index)) {
if (get_raw_index(m_indices.back()) > get_raw_index(t_index)) {
m_sorting_criteria = SortingCriteria::None;
}
} else {
Expand Down Expand Up @@ -625,7 +629,7 @@ void idol::SparseVector<IndexT, ValueT, IndexExtractorT>::reduce() {

const auto& next_index = m_indices[i];

if (current_index.has_value() && IndexExtractorT()(*current_index) == IndexExtractorT()(next_index)) {
if (current_index.has_value() && get_raw_index(*current_index) == get_raw_index(next_index)) {
new_values[current] += m_values[i];
continue;
}
Expand All @@ -650,7 +654,7 @@ bool idol::SparseVector<IndexT, ValueT, IndexExtractorT>::has_index(const IndexT

if (!m_is_reduced) {
for (unsigned int i = 0, n = m_indices.size() ; i < n ; ++i) {
if (IndexExtractorT()(m_indices[i]) == IndexExtractorT()(t_index)) {
if (get_raw_index(m_indices[i]) == get_raw_index(t_index)) {
return true;
}
}
Expand All @@ -659,7 +663,7 @@ bool idol::SparseVector<IndexT, ValueT, IndexExtractorT>::has_index(const IndexT

if (m_sorting_criteria != SortingCriteria::Index) {
for (unsigned int i = 0, n = m_indices.size() ; i < n ; ++i) {
if (IndexExtractorT()(m_indices[i]) == IndexExtractorT()(t_index)) {
if (get_raw_index(m_indices[i]) == get_raw_index(t_index)) {
return true;
}
}
Expand All @@ -670,10 +674,10 @@ bool idol::SparseVector<IndexT, ValueT, IndexExtractorT>::has_index(const IndexT
m_indices.begin(),
m_indices.end(),
t_index,
[](const IndexT& t_index1, const IndexT& t_index2) { return IndexExtractorT()(t_index1) < IndexExtractorT()(t_index2); }
[this](const IndexT& t_index1, const IndexT& t_index2) { return get_raw_index(t_index1) < get_raw_index(t_index2); }
);

if (it == m_indices.end() || IndexExtractorT()(*it) != IndexExtractorT()(t_index)) {
if (it == m_indices.end() || get_raw_index(*it) != get_raw_index(t_index)) {
return false;
}

Expand All @@ -686,7 +690,7 @@ ValueT idol::SparseVector<IndexT, ValueT, IndexExtractorT>::get(const IndexT &t_
if (!m_is_reduced) {
double result = 0.;
for (unsigned int i = 0, n = m_indices.size() ; i < n ; ++i) {
if (IndexExtractorT()(m_indices[i]) == IndexExtractorT()(t_index)) {
if (get_raw_index(m_indices[i]) == get_raw_index(t_index)) {
result += m_values[i];
}
}
Expand All @@ -695,7 +699,7 @@ ValueT idol::SparseVector<IndexT, ValueT, IndexExtractorT>::get(const IndexT &t_

if (m_sorting_criteria != SortingCriteria::Index) {
for (unsigned int i = 0, n = m_indices.size() ; i < n ; ++i) {
if (IndexExtractorT()(m_indices[i]) == IndexExtractorT()(t_index)) {
if (get_raw_index(m_indices[i]) == get_raw_index(t_index)) {
return m_values[i];
}
}
Expand All @@ -706,10 +710,10 @@ ValueT idol::SparseVector<IndexT, ValueT, IndexExtractorT>::get(const IndexT &t_
m_indices.begin(),
m_indices.end(),
t_index,
[](const IndexT& t_index1, const IndexT& t_index2) { return IndexExtractorT()(t_index1) < IndexExtractorT()(t_index2); }
[this](const IndexT& t_index1, const IndexT& t_index2) { return get_raw_index(t_index1) < get_raw_index(t_index2); }
);

if (it == m_indices.end() || IndexExtractorT()(*it) != IndexExtractorT()(t_index)) {
if (it == m_indices.end() || get_raw_index(*it) != get_raw_index(t_index)) {
return ValueT{};
}

Expand All @@ -723,7 +727,7 @@ void idol::SparseVector<IndexT, ValueT, IndexExtractorT>::remove(const IndexT &t

for (unsigned int i = 0, n = m_indices.size() ; i < n ; ++i) {

if (IndexExtractorT()(m_indices[i]) != IndexExtractorT()(t_index)) {
if (get_raw_index(m_indices[i]) != get_raw_index(t_index)) {
continue;
}

Expand All @@ -744,10 +748,10 @@ void idol::SparseVector<IndexT, ValueT, IndexExtractorT>::remove(const IndexT &t
m_indices.begin(),
m_indices.end(),
t_index,
[](const IndexT& t_index1, const IndexT& t_index2) { return IndexExtractorT()(t_index1) < IndexExtractorT()(t_index2); }
[this](const IndexT& t_index1, const IndexT& t_index2) { return get_raw_index(t_index1) < get_raw_index(t_index2); }
);

if (it == m_indices.end() || IndexExtractorT()(*it) != IndexExtractorT()(t_index)) {
if (it == m_indices.end() || get_raw_index(*it) != get_raw_index(t_index)) {
return;
}

Expand Down
2 changes: 2 additions & 0 deletions lib/include/idol/mixed-integer/modeling/constraints/Ctr.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ class idol::Ctr : public Object<CtrVersion, Ctr> {
return Ctr(t_env, t_type, t_constant, t_name_i);
});
}

unsigned int index(const Model& t_index) const;
};

IDOL_MAKE_HASHABLE(Ctr)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <ostream>
#include <idol/mixed-integer/modeling/expressions/LinExpr.h>
#include <idol/mixed-integer/modeling/Types.h>
#include <idol/mixed-integer/modeling/variables/Var.h>

namespace idol {

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//
// Created by henri on 28.10.24.
//

#ifndef IDOL_INTERNALLINEXPR_H
#define IDOL_INTERNALLINEXPR_H

#include "idol/mixed-integer/modeling/expressions/LinExpr.h"

namespace idol {
class Model;

template<class>
class InternalLinExpr;
}

template<class Key>
class idol::InternalLinExpr : public LinExpr<Key> {
const Model* m_model;
protected:
unsigned int get_raw_index(const Key &t_index) const override {
return t_index.index(*m_model);
}
public:
InternalLinExpr() = default;
InternalLinExpr(const Key& t_key) : LinExpr<Key>(t_key) {} // NOLINT(google-explicit-constructor)
InternalLinExpr(double t_factor, const Key& t_key) : LinExpr<Key>(t_factor, t_key) {}

InternalLinExpr(const Model* t_model) : m_model(t_model) {}
InternalLinExpr(const Model* t_model, LinExpr<Key>&& t_other) : LinExpr<Key>(std::move(t_other)), m_model(t_model) {}
InternalLinExpr(const Model* t_model, const LinExpr<Key>& t_other) : LinExpr<Key>(t_other), m_model(t_model) {}
};

#endif //IDOL_INTERNALLINEXPR_H
2 changes: 2 additions & 0 deletions lib/include/idol/mixed-integer/modeling/variables/Var.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ class idol::Var : public Object<VarVersion, Var> {
return Var(t_env, t_lb, t_ub, t_type, t_obj, t_name_i);
});
}

unsigned int index(const Model& t_model) const;
};

IDOL_MAKE_HASHABLE(Var)
Expand Down
10 changes: 5 additions & 5 deletions lib/include/idol/mixed-integer/modeling/variables/VarVersion.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#define IDOL_VARVERSION_H

#include "idol/mixed-integer/modeling/objects/Version.h"
#include "idol/mixed-integer/modeling/expressions/LinExpr.h"
#include "idol/mixed-integer/modeling/expressions/InternalLinExpr.h"
#include "idol/mixed-integer/modeling/constraints/Ctr.h"

namespace idol {
Expand All @@ -19,9 +19,9 @@ class idol::VarVersion : public Version {
double m_ub;
VarType m_type;
double m_obj;
std::unique_ptr<LinExpr<Ctr>> m_column;
std::unique_ptr<InternalLinExpr<Ctr>> m_column;
public:
VarVersion(unsigned int t_index, double t_lb, double t_ub, VarType t_type, double t_obj, LinExpr<Ctr>&& t_column);
VarVersion(unsigned int t_index, double t_lb, double t_ub, VarType t_type, double t_obj, InternalLinExpr<Ctr>&& t_column);
VarVersion(unsigned int t_index, TempVar&& t_temp_var);
VarVersion(unsigned int t_index, const TempVar& t_temp_var);

Expand All @@ -48,11 +48,11 @@ class idol::VarVersion : public Version {

const LinExpr<Ctr>& column() const { return *m_column; }

void set_column(LinExpr<Ctr>&& t_column) { m_column = std::make_unique<LinExpr<Ctr>>(std::move(t_column)); }
void set_column(InternalLinExpr<Ctr>&& t_column) { m_column = std::make_unique<InternalLinExpr<Ctr>>(std::move(t_column)); }

bool has_column() const { return m_column != nullptr; }

void set_column(const LinExpr<Ctr>& t_column) { m_column = std::make_unique<LinExpr<Ctr>>(t_column); }
void set_column(const InternalLinExpr<Ctr>& t_column) { m_column = std::make_unique<InternalLinExpr<Ctr>>(t_column); }

void reset_column() { m_column.reset(); }

Expand Down
4 changes: 4 additions & 0 deletions lib/src/mixed-integer/modeling/constraints/Ctr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,7 @@ idol::Ctr::Ctr(idol::Env &t_env, idol::CtrType t_type, double t_constant, std::s
: Ctr(t_env, TempCtr(LinExpr<Var>(), t_type, t_constant), std::move(t_name)) {

}

unsigned int idol::Ctr::index(const idol::Model &t_index) const {
return t_index.get_ctr_index(*this);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
//
// Created by henri on 28.10.24.
//
#include "idol/mixed-integer/modeling/expressions/InternalLinExpr.h"
4 changes: 2 additions & 2 deletions lib/src/mixed-integer/modeling/models/Model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ void idol::Model::add(const Var &t_var, TempVar t_temp_var) {
t_temp_var.ub(),
t_temp_var.type(),
t_temp_var.obj(),
std::move(t_temp_var.column())
InternalLinExpr<Ctr>(this, std::move(t_temp_var.column()))
);

m_variables.emplace_back(t_var);
Expand Down Expand Up @@ -662,7 +662,7 @@ void idol::Model::build_row(const idol::Ctr &t_ctr) {

void idol::Model::build_column(const idol::Var &t_var) {

LinExpr<Ctr> column;
InternalLinExpr<Ctr> column(this);
for (const auto& ctr : ctrs()) {
const auto& lhs = get_ctr_row(ctr);
column.push_back(ctr, lhs.get(t_var));
Expand Down
4 changes: 4 additions & 0 deletions lib/src/mixed-integer/modeling/variables/Var.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,7 @@ idol::Var::Var(Env &t_env, double t_lb, double t_ub, VarType t_type, double t_ob
: Var(t_env, t_lb, t_ub, t_type, t_obj, LinExpr<Ctr>(t_column), std::move(t_name)) {

}

unsigned int idol::Var::index(const idol::Model &t_model) const {
return t_model.get_var_index(*this);
}
Loading

0 comments on commit c9b6111

Please sign in to comment.