idol
A C++ Framework for Optimization
Loading...
Searching...
No Matches
DefaultNodeUpdator.h
1//
2// Created by henri on 18.10.23.
3//
4
5#ifndef IDOL_DEFAULTNODEUPDATOR_H
6#define IDOL_DEFAULTNODEUPDATOR_H
7
8#include "NodeUpdator.h"
9#include "idol/mixed-integer/modeling/models/Model.h"
10#include "idol/general/utils/Map.h"
11#include "Node.h"
12#include "DefaultNodeInfo.h"
13#include "BranchingDecision.h"
14
15namespace idol {
16 template<class NodeT>
17 class DefaultNodeUpdator;
18}
19
20template<class NodeInfoT>
21class idol::DefaultNodeUpdator : public NodeUpdator<NodeInfoT> {
22
23 const Model& m_parent;
24 Model& m_relaxation;
25
26 Map<Var, double> m_changed_lower_bounds; // variable -> old_bound
27 Map<Var, double> m_changed_upper_bounds;
28 std::list<Ctr> m_added_constraints;
29
30 void apply_variable_branching_decisions(const Node<NodeInfoT> &t_node,
31 Map<Var, double> &t_changed_lower_bounds,
32 Map<Var, double> &t_changed_upper_bounds);
33
34 void apply_variable_branching_decision(const VarBranchingDecision& t_branching_decision,
35 Map<Var, double> &t_current_changed_bounds,
36 Map<Var, double> &t_changed_bounds);
37
38 void apply_constraint_branching_decisions(const Node<NodeInfoT> &t_node);
39public:
40 explicit DefaultNodeUpdator(const Model& t_parent, Model& t_relaxation);
41
43
44 void initialize() override {}
45
46 void prepare(const Node<NodeInfoT> &t_node) override;
47
48 void clear() override;
49
50protected:
51 Model& relaxation() { return m_relaxation; }
52
53 [[nodiscard]] const Model& relaxation() const { return m_relaxation; }
54};
55
56template<class NodeInfoT>
57void
59
60 if (t_node.level() == 0) {
61 return;
62 }
63
64 apply_constraint_branching_decisions(t_node.parent());
65
66 for (const auto& [ctr, temporary_constraint] : t_node.info().constraint_branching_decisions()) {
67 m_relaxation.add(ctr, temporary_constraint);
68 m_added_constraints.emplace_back(ctr);
69 }
70
71}
72
73template<class NodeT>
74idol::DefaultNodeUpdator<NodeT>::DefaultNodeUpdator(const Model& t_parent, idol::Model &t_relaxation)
75 : m_parent(t_parent), m_relaxation(t_relaxation) {
76
77}
78
79template<class NodeInfoT>
81
82 // Clear LB
83 for (const auto& [var, lb] : m_changed_lower_bounds) {
84 m_relaxation.set_var_lb(var, lb);
85 }
86 m_changed_lower_bounds.clear();
87
88 // Clear UB
89 for (const auto& [var, ub] : m_changed_upper_bounds) {
90 m_relaxation.set_var_ub(var, ub);
91 }
92 m_changed_upper_bounds.clear();
93
94 // Clear Ctr
95 for (const auto& ctr : m_added_constraints) {
96 m_relaxation.remove(ctr);
97 }
98 m_added_constraints.clear();
99}
100
101template<class NodeInfoT>
102void idol::DefaultNodeUpdator<NodeInfoT>::prepare(const Node<NodeInfoT> &t_node) {
103
104 Map<Var, double> changed_lower_bounds;
105 Map<Var, double> changed_upper_bounds;
106
107 apply_variable_branching_decisions(t_node, changed_lower_bounds, changed_upper_bounds);
108 clear();
109 m_changed_lower_bounds = changed_lower_bounds;
110 m_changed_upper_bounds = changed_upper_bounds;
111
112 apply_constraint_branching_decisions(t_node);
113}
114
115template<class NodeInfoT>
117 Map<Var, double> &t_changed_lower_bounds,
118 Map<Var, double> &t_changed_upper_bounds
119 ) {
120
121 for (const auto& branching_decision : t_node.info().variable_branching_decisions()) {
122
123 switch (branching_decision.type) {
124 case LessOrEqual:
125 apply_variable_branching_decision(branching_decision, m_changed_upper_bounds, t_changed_upper_bounds);
126 break;
127 case GreaterOrEqual:
128 apply_variable_branching_decision(branching_decision, m_changed_lower_bounds, t_changed_lower_bounds);
129 break;
130 default:
131 throw Exception("Branching on equality constraints is not implemented.");
132 }
133
134 }
135
136 if (t_node.level() == 0) {
137 return;
138 }
139
140 apply_variable_branching_decisions(t_node.parent(), t_changed_lower_bounds, t_changed_upper_bounds);
141
142}
143
144template<class NodeInfoT>
145void idol::DefaultNodeUpdator<NodeInfoT>::apply_variable_branching_decision(const VarBranchingDecision &t_branching_decision,
146 idol::Map<idol::Var, double> &t_current_changed_bounds,
147 idol::Map<idol::Var, double> &t_changed_bounds) {
148
149 const auto& var = t_branching_decision.variable;
150
151 if (const auto it = t_changed_bounds.find(var) ; it != t_changed_bounds.end()) {
152 return;
153 }
154
155 const double bound = t_branching_decision.bound;
156 double original_bound;
157
158 if (t_branching_decision.type == LessOrEqual) {
159
160 original_bound = m_relaxation.get_var_ub(var);
161 m_relaxation.set_var_ub(var, bound);
162
163 } else {
164
165 original_bound = m_relaxation.get_var_lb(var);
166 m_relaxation.set_var_lb(var, bound);
167
168 }
169
170 if (const auto it = t_current_changed_bounds.find(var) ; it != t_current_changed_bounds.end()) {
171 t_changed_bounds.emplace(*it);
172 t_current_changed_bounds.erase(it);
173 } else {
174 t_changed_bounds.emplace(var, original_bound);
175 }
176
177}
178
179#endif //IDOL_DEFAULTNODEUPDATOR_H