Loading...
Searching...
No Matches
KKT.h
1//
2// Created by henri on 21.11.24.
3//
4
5#ifndef IDOL_KKT_H
6#define IDOL_KKT_H
7
8#include <vector>
9#include <variant>
10#include <cassert>
11#include "idol/mixed-integer/modeling/models/Model.h"
12#include "idol/mixed-integer/modeling/variables/Var.h"
13#include "idol/mixed-integer/modeling/constraints/Ctr.h"
14#include "idol/mixed-integer/modeling/constraints/QCtr.h"
15#include "idol/mixed-integer/modeling/expressions/QuadExpr.h"
16
17namespace idol {
18 namespace Reformulators {
19 class KKT;
20 }
21 class Model;
22
23 namespace Bilevel {
24 class Description;
25 }
26}
27
29 const Model& m_primal;
30 const QuadExpr<Var, double>& m_primal_objective;
31 std::string m_prefix;
32
33 std::function<bool(const Var&)> m_primal_variable_indicator;
34 std::function<bool(const Ctr&)> m_primal_constraint_indicator;
35 std::function<bool(const QCtr&)> m_primal_qconstraint_indicator;
36
37 QuadExpr<Var, double> m_dual_objective;
38 std::vector<std::optional<Var>> m_dual_variables_for_constraints; // constraint index <-> dual variable
39 std::vector<std::optional<Var>> m_dual_variables_for_qconstraints; // qconstraint index <-> dual variable
40 std::vector<std::optional<Var>> m_dual_variables_for_lower_bounds; // variable index <-> dual variable
41 std::vector<std::optional<Var>> m_dual_variables_for_upper_bounds; // variable index <-> dual variable
42 std::vector<std::optional<std::variant<Ctr, QCtr>>> m_dual_constraints; // variable index <-> dual constraint
43
44 [[nodiscard]] bool primal_is_a_linear_problem() const;
45 [[nodiscard]] bool is_linear(const QuadExpr<Var, double>& t_expr) const;
46 void create_dual_variables();
47 [[nodiscard]] std::pair<double, double> bounds_for_dual_variable(idol::CtrType t_type) const;
48 void create_dual_constraints();
49public:
50 class BoundProvider;
51 class BoundProviderMap;
52
53 KKT(const Model& t_parent,
54 const QuadExpr<Var, double>& t_primal_objective,
55 const std::function<bool(const Var&)>& t_primal_variable_indicator = [](const Var&) { return true; },
56 const std::function<bool(const Ctr&)>& t_primal_constraint_indicator = [](const Ctr&) { return true; },
57 const std::function<bool(const QCtr&)>& t_primal_qconstraint_indicator = [](const QCtr&) { return true; });
58
59 explicit KKT(const Model& t_parent,
60 const std::function<bool(const Var&)>& t_primal_variable_indicator = [](const Var&) { return true; },
61 const std::function<bool(const Ctr&)>& t_primal_constraint_indicator = [](const Ctr&) { return true; },
62 const std::function<bool(const QCtr&)>& t_primal_qconstraint_indicator = [](const QCtr&) { return true; });
63
64 KKT(const Model& t_high_point_relaxation, const Bilevel::Description& t_bilevel_description);
65
66 void set_prefix(std::string t_prefix) { m_prefix = std::move(t_prefix); }
67
68 [[nodiscard]] const QuadExpr<Var, double>& get_dual_obj_expr() const { return m_dual_objective; }
69
74 void add_coupling(Model& t_destination);
75 void add_coupling_variables(Model& t_destination);
76 void add_coupling_constraints(Model& t_destination);
77
84 void add_dual(Model& t_destination, bool t_add_objective = true);
85 void add_dual_variables(Model& t_destination);
86 void add_dual_constraints(Model& t_destination);
87 void add_dual_objective(Model& t_destination);
88
94 void add_primal(Model& t_destination, bool t_add_objective = true);
95 void add_primal_variables(idol::Model &t_destination);
96 void add_primal_constraints(idol::Model &t_destination);
97 void add_primal_objective(idol::Model &t_destination);
98
105
111 void add_kkt_reformulation(idol::Model &t_destination, bool t_use_sos1 = false);
112
113 void add_kkt_reformulation(idol::Model &t_destination, BoundProvider& t_bound_provider);
114
115 void add_bounds_on_dual_variables(idol::Model &t_destination, BoundProvider& t_bound_provider);
116
117 [[nodiscard]] const Var& get_dual_var(const Ctr& t_ctr) const;
118 [[nodiscard]] const Var& get_dual_var_lb(const Var& t_var) const;
119 [[nodiscard]] const Var& get_dual_var_ub(const Var& t_var) const;
120 [[nodiscard]] const std::variant<Ctr, QCtr>& get_dual_ctr(const Var& t_var) const;
121};
122
124 const Model* m_model = nullptr;
125public:
126 virtual ~BoundProvider() = default;
127
128 [[nodiscard]] const Model& model() const { return *m_model; }
129
130 virtual double get_ctr_dual_lb(const Ctr& t_ctr) = 0;
131 virtual double get_ctr_dual_ub(const Ctr& t_ctr) = 0;
132 virtual double get_ctr_slack_lb(const Ctr& t_ctr) = 0;
133 virtual double get_ctr_slack_ub(const Ctr& t_ctr) = 0;
134 virtual double get_var_lb_dual_ub(const Var& t_var) = 0;
135 virtual double get_var_ub_dual_lb(const Var& t_var) = 0;
136 virtual double get_var_lb(const Var& t_var) { assert(m_model); return m_model->get_var_lb(t_var); }
137 virtual double get_var_ub(const Var& t_var) { assert(m_model); return m_model->get_var_ub(t_var); }
138
139 [[nodiscard]] virtual BoundProvider* clone() const = 0;
140
141 friend class idol::Reformulators::KKT;
142};
143
145 Map<std::string, double> m_ctr_dual;
146 Map<std::string, double> m_ctr_slack;
147 Map<std::string, double> m_var_lb_dual;
148 Map<std::string, double> m_var_lb;
149 Map<std::string, double> m_var_ub_dual;
150 Map<std::string, double> m_var_ub;
151
152 static void set(Map<std::string, double>& t_map, std::string const& t_name, double t_value);
153public:
154 double get_ctr_dual_lb(const Ctr& t_ctr) override;
155 double get_ctr_dual_ub(const Ctr& t_ctr) override;
156 double get_ctr_slack_lb(const Ctr& t_ctr) override;
157 double get_ctr_slack_ub(const Ctr& t_ctr) override;
158 double get_var_lb_dual_ub(const Var& t_var) override;
159 double get_var_ub_dual_lb(const Var& t_var) override;
160 double get_var_lb(const Var& t_var) override;
161 double get_var_ub(const Var& t_var) override;
162
163 void set_ctr_dual_lb(const Ctr& t_ctr, double t_value) { set(m_ctr_dual, t_ctr.name(), t_value); }
164 void set_ctr_dual_ub(const Ctr& t_ctr, double t_value) { set(m_ctr_dual, t_ctr.name(), t_value); }
165 void set_ctr_slack_lb(const Ctr& t_ctr, double t_value) { set(m_ctr_dual, t_ctr.name(), t_value); }
166 void set_ctr_slack_ub(const Ctr& t_ctr, double t_value) { set(m_ctr_dual, t_ctr.name(), t_value); }
167 void set_var_lb_dual_ub(const Var& t_var, double t_value) { set(m_var_lb_dual, t_var.name(), t_value); }
168 void set_var_ub_dual_lb(const Var& t_var, double t_value) { set(m_var_lb_dual, t_var.name(), t_value); }
169 void set_var_lb(const Var& t_var, double t_value) { set(m_var_lb, t_var.name(), t_value); }
170 void set_var_ub(const Var& t_var, double t_value) { set(m_var_lb, t_var.name(), t_value); }
171
172 [[nodiscard]] BoundProvider* clone() const override;
173
174 static BoundProviderMap from_file(const std::string& t_filename);
175};
176
177#endif //IDOL_KKT_H
const std::string & name() const
Definition Object.h:54
void add_primal(Model &t_destination, bool t_add_objective=true)
void add_strong_duality_reformulation(Model &t_destination)
void add_kkt_reformulation(idol::Model &t_destination, bool t_use_sos1=false)
void add_dual(Model &t_destination, bool t_add_objective=true)
void add_coupling(Model &t_destination)