ZonoOpt 2.2.0
Loading...
Searching...
No Matches
BnbDataStructures.hpp
Go to the documentation of this file.
1#ifndef ZONOOPT_BNB_DATA_STRUCTURES_
2#define ZONOOPT_BNB_DATA_STRUCTURES_
3
15#include <queue>
16#include <mutex>
17#include <utility>
18#include <memory>
19#include <set>
20#include <algorithm>
21#include <vector>
22#include <functional>
23
24#include "ADMM.hpp"
26
27namespace ZonoOpt::detail
28{
29 struct MI_data
30 {
31 std::shared_ptr<ADMM_data> admm_data;
32 std::pair<int, int> idx_b; // indices of binary variables
33 bool zero_one_form = false; // true: binary->{0,1}. false: binary->{-1,1}
34 };
35
36 template <typename T>
37 class ThreadSafeAccess
38 {
39 public:
40 ThreadSafeAccess() = default;
41
42 // get method
43 T get() const
44 {
45 std::lock_guard<std::mutex> lock(mtx);
46 return data;
47 }
48
49 // set method
50 void set(const T& value)
51 {
52 std::lock_guard<std::mutex> lock(mtx);
53 data = value;
54 }
55
56 private:
57 mutable std::mutex mtx;
58 T data;
59 };
60
61 template <typename T>
62 class ThreadSafeIncrementable
63 {
64 public:
65 explicit ThreadSafeIncrementable(T value) : data(value) {}
66
67 // get method
68 T get() const
69 {
70 std::lock_guard<std::mutex> lock(mtx);
71 return data;
72 }
73
74 // set method
75 void set(T value)
76 {
77 std::lock_guard<std::mutex> lock(mtx);
78 data = value;
79 }
80
81 // increment
82 void operator+=(T value)
83 {
84 std::lock_guard<std::mutex> lock(mtx);
85 data += value;
86 }
87
88 private:
89 mutable std::mutex mtx;
90 T data;
91 };
92
93 class ThreadSafeMultiset
94 {
95 public:
96 // constructor
97 ThreadSafeMultiset() = default;
98
99 // add J
100 void add(const zono_float J)
101 {
102 std::lock_guard<std::mutex> lock(mtx);
103 data.insert(J);
104 }
105
106 // remove J
107 void remove(const zono_float J)
108 {
109 std::lock_guard<std::mutex> lock(mtx);
110 if (const auto it = data.find(J); it != data.end())
111 data.erase(it);
112 }
113
114 // clear
115 void clear()
116 {
117 std::lock_guard<std::mutex> lock(mtx);
118 data.clear();
119 }
120
121 // get min, bool indicates if valid (i.e. not empty)
122 std::pair<zono_float, bool> get_min() const
123 {
124 std::lock_guard<std::mutex> lock(mtx);
125 if (data.empty())
126 return std::make_pair(std::numeric_limits<zono_float>::infinity(), false);
127 else
128 return std::make_pair(*data.begin(), true);
129 }
130
131 // get size
132 size_t size() const
133 {
134 std::lock_guard<std::mutex> lock(mtx);
135 return data.size();
136 }
137
138 private:
139 mutable std::mutex mtx;
140 std::multiset<zono_float> data;
141 };
142
143 template <typename T>
144 class ThreadSafeVector
145 {
146 public:
147 // constructor
148 ThreadSafeVector() = default;
149
150 // add element
151 void push_back(const T& value)
152 {
153 std::lock_guard<std::mutex> lock(mtx);
154 data.push_back(value);
155 }
156
157 // clear vector
158 void clear()
159 {
160 std::lock_guard<std::mutex> lock(mtx);
161 data.clear();
162 }
163
164 // get size
165 size_t size() const
166 {
167 std::lock_guard<std::mutex> lock(mtx);
168 return data.size();
169 }
170
171 // get vector
172 std::vector<T> get() const
173 {
174 std::lock_guard<std::mutex> lock(mtx);
175 return data;
176 }
177
178 // check containment
179 bool contains(const T& value, std::function<bool(const OptSolution&, const OptSolution&)>& compare) const
180 {
181 std::lock_guard<std::mutex> lock(mtx);
182 for (auto it = data.begin(); it != data.end(); ++it)
183 {
184 if (compare(*it, value)) return true;
185 }
186 return false;
187 }
188
189 private:
190 mutable std::mutex mtx;
191 std::vector<T> data;
192 };
193
194 class Node final : public ADMM_solver
195 {
196 public:
197 // constructors
198 explicit Node(const std::shared_ptr<ADMM_data>& data) : ADMM_solver(data)
199 {
200 // init box constraints
201 this->x_box = *data->x_box;
202 }
203
204 // copy constructor
205 Node(const Node& other) : ADMM_solver(other)
206 {
207 this->x_box = other.x_box;
208 this->solution = other.solution;
209 this->width = this->x_box.width();
210 }
211
212 // public fields
213 OptSolution solution = OptSolution();
214 zono_float width = std::numeric_limits<zono_float>::infinity(); // width of the box
215
216 // run contractor
217 bool run_contractor()
218 {
219 const bool contractor_feasible = this->startup(this->x_box, this->solution);
220 this->width = this->x_box.width();
221 return contractor_feasible;
222 }
223
224 // fix bound
225 bool fix_bound(int ind, const zono_float val)
226 {
227 // update bounds
228 this->x_box.set_element(ind, Interval(val, val));
229
230 // run contractor
231 const bool contractor_feasible = this->startup(this->x_box, this->solution, {ind});
232 this->width = this->x_box.width();
233 return contractor_feasible;
234 }
235
236 // solve
237 void solve(std::atomic<bool>* stop = nullptr)
238 {
239 this->solve_core(this->x_box, this->solution, stop);
240 }
241
242 // update convergence tolerances
243 void update_convergence_tolerances(const zono_float eps_prim, const zono_float eps_dual)
244 {
245 this->eps_prim = eps_prim;
246 this->eps_dual = eps_dual;
247 }
248
249 // get box
250 const Box& get_box() const
251 {
252 return x_box;
253 }
254
255 bool is_priority() const
256 {
257 return priority;
258 }
259
260 void set_priority(bool priority)
261 {
262 this->priority = priority;
263 }
264
265 private:
266 // members
267 Box x_box;
268 bool priority = false;
269 };
270
271 template <typename T, typename Compare=std::less<T>>
272 class PriorityQueuePrunable final : public std::priority_queue<T, std::vector<T>, Compare>
273 {
274 public:
275 // constructor
276 explicit PriorityQueuePrunable(const Compare& comp = Compare()) : std::priority_queue<
277 T, std::vector<T>, Compare>(comp)
278 {
279 }
280
281 // prune queue
282 void prune(const T& t)
283 {
284 auto it_prune = std::find_if(this->c.begin(), this->c.end(), [&](const T& item)
285 {
286 return this->comp(item, t);
287 });
288 if (it_prune != this->c.end())
289 {
290 this->c.erase(it_prune, this->c.end());
291 }
292 }
293
294 // bottom
295 const T& bottom() const
296 {
297 return this->c.back();
298 }
299
300 // pop top
301 T pop_top()
302 {
303 T top = std::move(this->c.front());
304 this->pop();
305 return top;
306 }
307
308 // clear
309 void clear()
310 {
311 while (!this->empty())
312 this->pop();
313 }
314 };
315} // namespace ZonoOpt::detail
316
317
318#endif
Convex and mixed-integer ADMM implementations used within ZonoOpt.
Optimization settings and solution data structures for ZonoOpt library.
#define zono_float
Defines the floating-point type used in ZonoOpt.
Definition ZonoOpt.hpp:45