Skip to content

Commit

Permalink
add column and rows, change storage mode, add dump function
Browse files Browse the repository at this point in the history
  • Loading branch information
hlefebvr committed Oct 25, 2024
1 parent d3ce764 commit c265c00
Show file tree
Hide file tree
Showing 20 changed files with 574 additions and 141 deletions.
40 changes: 22 additions & 18 deletions dev/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,39 @@
#include "idol/mixed-integer/modeling/variables/Var.h"
#include "idol/mixed-integer/modeling/models/Model.h"
#include "idol/mixed-integer/modeling/objects/Env.h"
#include "idol/mixed-integer/modeling/expressions/operations/operators.h"

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), 1., 0., Continuous, "x");
Model model(env, Model::Storage::RowOriented);
const auto x = model.add_vars(Dim<1>(10), 0., 1., Continuous, "x");

SparseVector<Var, double> v1;
SparseVector<Var, double> v2;
Column col;
col.set_obj(1.);
model.add_var(0, 10, Continuous, col);

for (unsigned int i = 0 ; i < 10 ; ++i) {
v1.push_back(x[i], i);
//v1.push_back(x[i], 10 - i);
for (unsigned int i = 0; i < 9; ++i) {
model.add_ctr(x[i] + x[i+1] >= 0.5);
}
for (unsigned int i = 0 ; i < 10 ; ++i) {
v2.push_back(x[i], i);
v2.push_back(x[i], 10 - i);
}
std::cout << v1.is_reduced() << std::endl;
std::cout << v2.is_reduced() << std::endl;
std::cout << v1.is_sorted_by_index() << std::endl;
std::cout << v2.is_sorted_by_index() << std::endl;

auto sum = v1;
sum += v2;
//std::cout << model << std::endl;

const auto column = model.get_var_column(x[3]);

model.dump();

model.set_storage(Model::Storage::ColumnOriented, true);

const auto& row = model.get_ctr_row(model.get_ctr_by_index(2));

model.dump();

model.set_storage(Model::Storage::Both);

std::cout << sum << std::endl;
model.dump();

return 0;
}
25 changes: 4 additions & 21 deletions lib/include/idol/general/numericals.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,10 @@ namespace idol {
return std::abs(t_ub - t_lb);
}

static bool is_zero(double t_value, double t_tolerance) {
return std::abs(t_value) <= t_tolerance;
}

static bool is_integer(double t_value, double t_tolerance) {
return std::abs(t_value - std::round(t_value)) <= t_tolerance;
}
Expand All @@ -138,27 +142,6 @@ namespace idol {
return std::round(t_value * multiplier) / multiplier;
}

static double multiply_with_precision(double t_a, double t_b, unsigned int t_n_digits) {
const auto n_a = std::min<int>(std::floor( std::log10(t_a) ) + 1, t_n_digits);
const auto n_b = std::min<int>(std::floor( std::log10(t_b) ) + 1, t_n_digits);
const long scaled_a = long(long(t_a * std::pow<double>(10., t_n_digits - n_a)) * std::pow<long>(10, n_a));
const long scaled_b = long(long(t_b * std::pow<double>(10., t_n_digits - n_b)) * std::pow<long>(10, n_b));
const long exact_product = scaled_a * scaled_b;
const double result = exact_product / std::pow<double>(10, 2 * t_n_digits);
return result;
}

static double multiply_with_precision_by_power_of_10(double t_x, unsigned int t_exponent, unsigned int t_n_digits) {

if (equals(t_x, 0., Tolerance::Sparsity)) {
return 0.;
}

const auto n_x = std::min<int>(std::floor( std::log10(std::abs(t_x)) ) + 1, t_n_digits);
const double result = long(t_x * std::pow<double>(10., t_n_digits - n_x)) * std::pow(10, n_x + t_exponent - t_n_digits);
return result;
}

}

#endif //OPTIMIZE_NUMERICALS_H
75 changes: 73 additions & 2 deletions lib/include/idol/general/utils/SparseVector.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <optional>
#include "sort.h"
#include "idol/general/utils/exceptions/Exception.h"
#include "idol/general/numericals.h"

namespace idol {
template<class, class, class>
Expand All @@ -19,8 +20,6 @@ namespace idol {
template<class IndexT, class ValueT, class IndexExtractorT = std::conditional_t<std::is_arithmetic_v<IndexT>, idol::identity<IndexT>, idol::get_id<IndexT>>>
class idol::SparseVector {
public:
//static_assert(std::is_default_constructible_v<ValueT>);

enum class SortingCriteria {
Index,
Value,
Expand Down Expand Up @@ -60,6 +59,8 @@ class idol::SparseVector {

[[nodiscard]] const ValueT& value_at(unsigned int t_index) const { return m_values[t_index]; }

[[nodiscard]] bool has_index(const IndexT& t_index) const;

[[nodiscard]] ValueT get(const IndexT& t_index1) const;

/**
Expand Down Expand Up @@ -135,9 +136,32 @@ class idol::SparseVector {

[[nodiscard]] const_iterator cend() const { return const_iterator(size(), *this); }

void sparsify();

SparseVector& merge_without_conflict(const SparseVector& t_vec);
};

template<class IndexT, class ValueT, class IndexExtractorT>
void idol::SparseVector<IndexT, ValueT, IndexExtractorT>::sparsify() {

unsigned int i = 0, j = 0;
const unsigned int n = m_indices.size();
while (i < n) {
if (!is_zero(m_values[i], Tolerance::Sparsity)) {
m_indices[j] = std::move(m_indices[i]);
m_values[j] = std::move(m_values[i]);
++j;
}
++i;
}

for (unsigned int k = j; k < n; ++k) {
m_indices.pop_back();
m_values.pop_back();
}

}

template<class IndexT, class ValueT, class IndexExtractorT>
idol::SparseVector<IndexT, ValueT, IndexExtractorT> &
idol::SparseVector<IndexT, ValueT, IndexExtractorT>::merge_without_conflict(const SparseVector &t_vec) {
Expand Down Expand Up @@ -179,6 +203,18 @@ idol::SparseVector<IndexT, ValueT, IndexExtractorT>::binary_operation_on_sorted_
return *this;
}

if (empty()) {
reserve(t_vec2.size());
for (unsigned int i = 0, n = t_vec2.size() ; i < n ; ++i) {
push_back(t_vec2.index_at(i), t_operation(ValueT{}, t_vec2.value_at(i)));
}
return *this;
}

if (t_vec2.empty()) {
return *this;
}

SparseVector result;

if (IndexExtractorT()(m_indices.back()) < IndexExtractorT()(t_vec2.m_indices.front())) {
Expand Down Expand Up @@ -609,6 +645,41 @@ void idol::SparseVector<IndexT, ValueT, IndexExtractorT>::reduce() {

}

template<class IndexT, class ValueT, class IndexExtractorT>
bool idol::SparseVector<IndexT, ValueT, IndexExtractorT>::has_index(const IndexT &t_index) const {

if (!m_is_reduced) {
for (unsigned int i = 0, n = m_indices.size() ; i < n ; ++i) {
if (IndexExtractorT()(m_indices[i]) == IndexExtractorT()(t_index)) {
return true;
}
}
return false;
}

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)) {
return true;
}
}
return false;
}

const auto it = std::lower_bound(
m_indices.begin(),
m_indices.end(),
t_index,
[](const IndexT& t_index1, const IndexT& t_index2) { return IndexExtractorT()(t_index1) < IndexExtractorT()(t_index2); }
);

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

return true;
}

template<class IndexT, class ValueT, class IndexExtractorT>
ValueT idol::SparseVector<IndexT, ValueT, IndexExtractorT>::get(const IndexT &t_index) const {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ class idol::CtrVersion : public Version, public TempCtr {
public:
CtrVersion(unsigned int t_index, TempCtr&& t_temp_ctr) : Version(t_index), TempCtr(std::move(t_temp_ctr)) {}
CtrVersion(unsigned int t_index, const TempCtr& t_temp_ctr) : Version(t_index), TempCtr(t_temp_ctr) {}

using TempCtr::has_row;
using TempCtr::reset_row;
using TempCtr::set_row;
};

#endif //IDOL_CTRVERSION_H
14 changes: 9 additions & 5 deletions lib/include/idol/mixed-integer/modeling/constraints/TempCtr.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,12 @@ namespace idol {
* ```
*/
class idol::TempCtr {
Row m_row;
std::unique_ptr<Row> m_row;
CtrType m_type = LessOrEqual;
protected:
void set_row(Row&& t_row) { m_row = std::make_unique<Row>(std::move(t_row)); }
bool has_row() const { return (bool) m_row; }
void reset_row() { m_row.reset(); }
public:
/**
* Default constructor.
Expand All @@ -54,13 +58,13 @@ class idol::TempCtr {
* @param t_row The desired row.
* @param t_type The desired constraint type.
*/
TempCtr(Row&& t_row, CtrType t_type) : m_row(std::move(t_row)), m_type(t_type) {}
TempCtr(Row&& t_row, CtrType t_type) : m_row(std::make_unique<Row>(std::move(t_row))), m_type(t_type) {}

/**
* Copy constructor.
* @param t_src The object to copy.
*/
TempCtr(const TempCtr& t_src) = default;
TempCtr(const TempCtr& t_src) : m_row(t_src.m_row ? std::make_unique<Row>(*t_src.m_row) : std::unique_ptr<Row>()), m_type(t_src.m_type) {}

/**
* Move constructor.
Expand All @@ -84,13 +88,13 @@ class idol::TempCtr {
* Returns the row of the temporary constraint (see Row).
* @return The row of the temporary constraint.
*/
[[nodiscard]] const Row& row() const { return m_row; }
[[nodiscard]] const Row& row() const { return *m_row; }

/**
* Returns the row of the temporary constraint (see Row).
* @return The row of the temporary constraint.
*/
Row& row() { return m_row; }
Row& row() { return *m_row; }

/**
* Returns the temporary constraint type.
Expand Down
6 changes: 4 additions & 2 deletions lib/include/idol/mixed-integer/modeling/expressions/Expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,14 +125,16 @@ idol::impl::Expr<Key1, Key2>::Expr(const QuadExpr<Key1> &t_expr) : m_quadratic(t
template<class Key1, class Key2>
idol::impl::Expr<Key1, Key2>::Expr(const LinExpr<Key1> &t_lin_expr, const QuadExpr<Key1, Key2> &t_quad_expr, double t_constant)
: m_linear(t_lin_expr),
m_quadratic(t_quad_expr) {
m_quadratic(t_quad_expr),
m_constant(t_constant) {

}

template<class Key1, class Key2>
idol::impl::Expr<Key1, Key2>::Expr(const Expr &t_src)
: m_linear(t_src.m_linear),
m_quadratic(t_src.m_quadratic) {
m_quadratic(t_src.m_quadratic),
m_constant(t_src.m_constant) {

}

Expand Down
19 changes: 19 additions & 0 deletions lib/include/idol/mixed-integer/modeling/expressions/LinExpr.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,23 @@ template<class Key>
idol::LinExpr<Key>::LinExpr(double t_factor, const Key &t_key) : SparseVector<Key, double>({ t_key }, { t_factor }, SparseVector<Key, double>::SortingCriteria::Index, true) {
}

namespace idol {
template<class Key>
std::ostream& operator<<(std::ostream& t_os, const LinExpr<Key>& t_expr) {

if (t_expr.empty()) {
return t_os << "0";
}

unsigned int i = 0;
t_os << t_expr.value_at(i) << " " << t_expr.index_at(i);
++i;
for (unsigned int n = t_expr.size() ; i < n ; ++i) {
t_os << " + " << t_expr.value_at(i) << " " << t_expr.index_at(i);
}

return t_os;
}
}

#endif //OPTIMIZE_EXPR_H
19 changes: 19 additions & 0 deletions lib/include/idol/mixed-integer/modeling/expressions/QuadExpr.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,23 @@ double idol::QuadExpr<Key1, Key2>::get(const Key1 &t_a, const Key2 &t_b) const {
return SparseVector<idol::Pair<Key1, Key2>, double>::get({ t_a, t_b });
}

namespace idol {
template<class Key1, class Key2>
std::ostream& operator<<(std::ostream& t_os, const QuadExpr<Key1, Key2>& t_expr) {

if (t_expr.empty()) {
return t_os << "0";
}

unsigned int i = 0;
t_os << t_expr.value_at(i) << " " << t_expr.index_at(i) << " + ";
++i;
for (unsigned int n = t_expr.size() ; i < n ; ++i) {
t_os << t_expr.value_at(i) << " " << t_expr.index_at(i) << " + ";
}

return t_os;
}
}

#endif //IDOL_QUADEXPR_H
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ namespace idol {

idol::LinExpr<idol::Var> operator+(const idol::Var &t_a, const idol::Var &t_b);

idol::Expr<idol::Var> operator+(double t_term, idol::LinExpr<idol::Var> &&t_lin_expr);

idol::Expr<idol::Var> operator+(idol::LinExpr<idol::Var> &&t_lin_expr, double t_term);

idol::LinExpr<idol::Var> operator+(idol::LinExpr<idol::Var> &&t_lin_expr, const idol::Var &t_var);

idol::LinExpr<idol::Var> operator+(const idol::Var &t_var, idol::LinExpr<idol::Var> &&t_lin_expr);
Expand All @@ -77,6 +81,10 @@ namespace idol {

idol::LinExpr<idol::Var> operator+(const idol::LinExpr<idol::Var> &t_a, const idol::LinExpr<idol::Var> &t_b);

idol::Expr<idol::Var> operator+(double t_term, idol::QuadExpr<idol::Var> &&t_quad_expr);

idol::Expr<idol::Var> operator+(idol::QuadExpr<idol::Var> &&t_quad_expr, double t_term);

idol::QuadExpr<idol::Var> operator+(idol::QuadExpr<idol::Var> &&t_a, const idol::QuadExpr<idol::Var> &t_b);

idol::QuadExpr<idol::Var> operator+(const idol::QuadExpr<idol::Var> &t_a, idol::QuadExpr<idol::Var> &&t_b);
Expand Down
Loading

0 comments on commit c265c00

Please sign in to comment.