Skip to content

Commit

Permalink
introduce generation pattern
Browse files Browse the repository at this point in the history
  • Loading branch information
hlefebvr committed Nov 20, 2024
1 parent 9cc8a84 commit ed72b02
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 34 deletions.
12 changes: 8 additions & 4 deletions dev/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#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"
#include "idol/general/utils/GenerationPattern.h"

using namespace idol;

Expand All @@ -28,13 +29,16 @@ int main(int t_argc, const char** t_argv) {

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

QuadExpr expr(2 * x[0] + 2);
Point<Var> point;
point.set(x[0], 5);

expr += x[0] * x[0];
GenerationPattern<Ctr> pattern;
pattern.constant() += 2 + 2 * x[0];

std::cout << expr << std::endl;
pattern.linear().set(x[1], x[0]);
pattern.linear().set(x[2], 10 * x[0] + 4);

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

return 0;
}
1 change: 1 addition & 0 deletions lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ add_library(idol STATIC
src/mixed-integer/modeling/constraints/TempQCtr.cpp
src/mixed-integer/modeling/constraints/QCtrVersion.cpp
src/mixed-integer/modeling/constraints/QCtr.cpp
include/idol/general/utils/GenerationPattern.h
)

find_package(OpenMP REQUIRED)
Expand Down
59 changes: 59 additions & 0 deletions lib/include/idol/general/utils/GenerationPattern.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
//
// Created by henri on 20.11.24.
//

#ifndef IDOL_GENERATIONPATTERN_H
#define IDOL_GENERATIONPATTERN_H

#include "idol/mixed-integer/modeling/expressions/AffExpr.h"
#include "Point.h"
#include "idol/mixed-integer/modeling/expressions/operations/operators.h"

namespace idol {
template<class, class> class GenerationPattern;
}

template<class GeneratedT,
class CoefficientT = idol::Var
>
class idol::GenerationPattern {
using KeyT = std::conditional_t<std::is_same_v<GeneratedT, Var>, Ctr, Var>;
idol::AffExpr<CoefficientT> m_constant;
SparseVector<KeyT, idol::AffExpr<CoefficientT>> m_linear;
public:
GenerationPattern() = default;

GenerationPattern(idol::AffExpr<CoefficientT> t_constant, SparseVector<KeyT, idol::AffExpr<CoefficientT>> t_linear)
: m_constant(std::move(t_constant)), m_linear(std::move(t_linear)) {}

auto& constant() { return m_constant; }

const auto& constant() const { return m_constant; }

auto& linear() { return m_linear; }

const auto& linear() const { return m_linear; }

double generate_constant(const Point<CoefficientT>& t_values) const {
return evaluate(m_constant, t_values);
}

LinExpr<KeyT> generate_linear(const Point<CoefficientT>& t_values) const {
LinExpr<KeyT> result;

for (const auto& [key, value] : m_linear) {
result += key * evaluate(value, t_values);
}

return result;
}

AffExpr<KeyT> operator()(const Point<CoefficientT>& t_values) const {
AffExpr<KeyT> result(generate_linear(t_values));
result.constant() = generate_constant(t_values);
return result;
}

};

#endif //IDOL_GENERATIONPATTERN_H
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include "idol/mixed-integer/modeling/models/Model.h"
#include "idol/general/utils/GeneratorPool.h"
#include "idol/general/utils/GenerationPattern.h"
#include "idol/general/utils/Map.h"

namespace idol::DantzigWolfe {
Expand All @@ -18,14 +19,9 @@ class idol::DantzigWolfe::Formulation {

Annotation<unsigned int> m_decomposition;

struct GenerationPattern {
AffExpr<Var> objective;
SparseVector<Ctr, AffExpr<Var>> column;
};

Model m_master;
std::vector<Model> m_sub_problems;
std::vector<GenerationPattern> m_generation_patterns;
std::vector<GenerationPattern<Var>> m_generation_patterns;
std::vector<GeneratorPool<Var>> m_pools;
std::vector<PresentGeneratorsList> m_present_generators;

Expand Down
3 changes: 2 additions & 1 deletion lib/include/idol/mixed-integer/optimizers/padm/Formulation.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,9 @@ class idol::ADM::Formulation {
std::pair<bool, double> m_rescaling;

std::vector<Model> m_sub_problems;
std::vector<std::optional<AffExpr<Var>>> m_objective_patterns;
std::vector<std::optional<QuadExpr<Var>>> m_objective_patterns;
std::vector<std::list<std::pair<Ctr, AffExpr<Var>>>> m_constraint_patterns; // as ctr: row <= 0
std::vector<std::list<std::pair<QCtr, AffExpr<Var>>>> m_qconstraint_patterns; // as ctr: row <= 0
std::vector<std::list<Var>> m_l1_vars_in_sub_problem;
Map<Ctr, Var> m_l1_vars;

Expand Down
36 changes: 19 additions & 17 deletions lib/src/mixed-integer/optimizers/dantzig-wolfe/Formulation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ void idol::DantzigWolfe::Formulation::initialize_sub_problems(unsigned int t_n_s

void idol::DantzigWolfe::Formulation::initialize_generation_patterns(unsigned int t_n_sub_problems) {

m_generation_patterns = std::vector<GenerationPattern>(t_n_sub_problems);
m_generation_patterns = std::vector<GenerationPattern<Var>>(t_n_sub_problems);

}

Expand Down Expand Up @@ -187,7 +187,7 @@ void idol::DantzigWolfe::Formulation::dispatch_linking_constraint(const idol::Ct
m_master.add(t_original_ctr, TempCtr(std::move(master_part), t_type, t_rhs));

for (unsigned int i = 0 ; i < n_sub_problems ; ++i) {
m_generation_patterns[i].column.set(t_original_ctr, std::move(sub_problem_parts[i]));
m_generation_patterns[i].linear().set(t_original_ctr, std::move(sub_problem_parts[i]));
}

}
Expand Down Expand Up @@ -231,7 +231,7 @@ void idol::DantzigWolfe::Formulation::dispatch_objective_function(const idol::Mo
m_master.set_obj_expr(AffExpr(std::move(master_part)) += objective.affine().constant());

for (unsigned int i = 0 ; i < n_subproblems ; ++i) {
m_generation_patterns[i].objective += std::move(sub_problem_parts[i]);
m_generation_patterns[i].constant() += std::move(sub_problem_parts[i]);
}

}
Expand Down Expand Up @@ -266,15 +266,15 @@ void idol::DantzigWolfe::Formulation::add_aggregation_constraint(unsigned int t_

Ctr lower(env, GreaterOrEqual, t_lower_multiplicity);
m_master.add(lower);
m_generation_patterns[t_sub_problem_id].column.set(lower, 1);
m_generation_patterns[t_sub_problem_id].linear().set(lower, 1);

}

if (!is_pos_inf(t_upper_multiplicity)) {

Ctr upper(env, LessOrEqual, t_upper_multiplicity);
m_master.add(upper);
m_generation_patterns[t_sub_problem_id].column.set(upper, 1);
m_generation_patterns[t_sub_problem_id].linear().set(upper, 1);

}

Expand All @@ -283,11 +283,13 @@ void idol::DantzigWolfe::Formulation::add_aggregation_constraint(unsigned int t_
void idol::DantzigWolfe::Formulation::generate_column(unsigned int t_sub_problem_id,
idol::PrimalPoint t_generator) {

auto generated = m_generation_patterns[t_sub_problem_id](t_generator);

auto alpha = m_master.add_var(0.,
Inf,
Continuous,
evaluate(m_generation_patterns[t_sub_problem_id].objective, t_generator),
evaluate(m_generation_patterns[t_sub_problem_id].column, t_generator)
std::move(generated.constant()),
std::move(generated.linear())
);

auto& pool = m_pools[t_sub_problem_id];
Expand All @@ -306,11 +308,11 @@ double idol::DantzigWolfe::Formulation::compute_reduced_cost(unsigned int t_sub_

const auto generation_pattern = m_generation_patterns[t_sub_problem_id];

for (const auto &[ctr, constant] : generation_pattern.column) {
for (const auto &[ctr, constant] : generation_pattern.linear()) {
result += evaluate(constant, t_generator) * -t_master_dual.get(ctr);
}

result += evaluate(generation_pattern.objective, t_generator);
result += evaluate(generation_pattern.constant(), t_generator);

return result;

Expand All @@ -324,12 +326,12 @@ void idol::DantzigWolfe::Formulation::update_sub_problem_objective(unsigned int

const auto generation_pattern = m_generation_patterns[t_sub_problem_id];

for (const auto &[ctr, constant] : generation_pattern.column) {
for (const auto &[ctr, constant] : generation_pattern.linear()) {
objective += constant * -t_master_dual.get(ctr);
}

if (!t_use_farkas) {
objective += generation_pattern.objective;
objective += generation_pattern.constant();
}

m_sub_problems[t_sub_problem_id].set_obj_expr(std::move(objective));
Expand Down Expand Up @@ -419,7 +421,7 @@ void idol::DantzigWolfe::Formulation::apply_sub_problem_bound_on_master(bool t_i
Ctr bound_constraint(m_master.env(), Equal, 0);

m_master.add(bound_constraint, TempCtr(LinExpr(expanded), type, t_value));
m_generation_patterns[t_sub_problem_id].column.set(bound_constraint, t_var);
m_generation_patterns[t_sub_problem_id].linear().set(bound_constraint, t_var);

applied_bounds.emplace(t_var, bound_constraint);

Expand Down Expand Up @@ -474,7 +476,7 @@ void idol::DantzigWolfe::Formulation::update_obj(const idol::QuadExpr<idol::Var>
m_master.set_var_obj(var, evaluate(sub_problem_parts[i], generator));
}

m_generation_patterns[i].objective = std::move(sub_problem_parts[i]);
m_generation_patterns[i].constant() = std::move(sub_problem_parts[i]);

}
}
Expand Down Expand Up @@ -594,7 +596,7 @@ void idol::DantzigWolfe::Formulation::remove(const idol::Var &t_var) {
const auto sub_problem_id = t_var.get(m_decomposition);

if (sub_problem_id != MasterId) {
m_generation_patterns[sub_problem_id].objective.linear().remove(t_var);
m_generation_patterns[sub_problem_id].constant().linear().remove(t_var);
m_sub_problems[sub_problem_id].remove(t_var);
return;
}
Expand All @@ -613,7 +615,7 @@ void idol::DantzigWolfe::Formulation::remove(const idol::Ctr &t_ctr) {
}

m_sub_problems[sub_problem_id].remove(t_ctr);
m_generation_patterns[sub_problem_id].column.remove(t_ctr);
m_generation_patterns[sub_problem_id].linear().remove(t_ctr);

}

Expand Down Expand Up @@ -642,8 +644,8 @@ void idol::DantzigWolfe::Formulation::load_columns_from_pool() {
0,
Inf,
Continuous,
evaluate(m_generation_patterns[sub_problem_id].objective, generator),
evaluate(m_generation_patterns[sub_problem_id].column, generator)
evaluate(m_generation_patterns[sub_problem_id].constant(), generator),
evaluate(m_generation_patterns[sub_problem_id].linear(), generator)
));
m_present_generators[sub_problem_id].emplace_back(var, generator);

Expand Down
10 changes: 4 additions & 6 deletions lib/src/mixed-integer/optimizers/padm/Formulation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ void idol::ADM::Formulation::dispatch_ctr(const idol::Model &t_src_model, const
const double rhs = t_src_model.get_ctr_rhs(t_ctr);
const auto type = t_src_model.get_ctr_type(t_ctr);

auto [pattern, is_pure] = dispatch(t_src_model, row, /* row.quadratic(), */ t_sub_problem_id);
auto [pattern, is_pure] = dispatch(t_src_model, row, t_sub_problem_id);
pattern.constant() -= rhs;

if (pattern.linear().empty()) {
Expand Down Expand Up @@ -179,11 +179,8 @@ idol::ADM::Formulation::dispatch_obj(const Model &t_src_model) {

std::pair<idol::AffExpr<idol::Var>, bool> idol::ADM::Formulation::dispatch(const idol::Model &t_src_model,
const idol::LinExpr<idol::Var> &t_lin_expr,
// const idol::QuadExpr<idol::Var> &t_quad_expr,
unsigned int t_sub_problem_id) {

throw Exception("TODO: Was using Constant");
/*
bool is_pure = true; // true if the row only has variables from the same sub-problem

const auto belongs_to_sub_problem = [&](const Var& t_var) {
Expand All @@ -197,13 +194,14 @@ std::pair<idol::AffExpr<idol::Var>, bool> idol::ADM::Formulation::dispatch(const

if (!belongs_to_sub_problem(var)) {
is_pure = false;
pattern.constant() += coefficient * !var;
pattern += coefficient * var;
continue;
}

pattern.linear() += coefficient * var;
}

/*
for (const auto& [var1, var2, constant] : t_quad_expr) {
const unsigned int var1_sub_problem_id = var1.get(m_decomposition);
Expand All @@ -230,12 +228,12 @@ std::pair<idol::AffExpr<idol::Var>, bool> idol::ADM::Formulation::dispatch(const
pattern.quadratic() += constant * var1 * var2;
}
*/

return {
std::move(pattern),
is_pure
};
*/
}

void
Expand Down

0 comments on commit ed72b02

Please sign in to comment.