ZonoOpt 2.4.1
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 template <typename T, typename Compare=std::less<T>>
94 class ThreadSafeSet
95 {
96 public:
97 // constructor
98 ThreadSafeSet() = default;
99
100 // add val
101 void add(const T val)
102 {
103 std::lock_guard<std::mutex> lock(mtx);
104 data.insert(val);
105 }
106
107 // remove val
108 void remove(const T val)
109 {
110 std::lock_guard<std::mutex> lock(mtx);
111 if (const auto it = data.find(val); it != data.end())
112 data.erase(it);
113 }
114
115 // clear
116 void clear()
117 {
118 std::lock_guard<std::mutex> lock(mtx);
119 data.clear();
120 }
121
122 // get min, bool indicates if valid (i.e. not empty)
123 std::pair<T, bool> get_min() const
124 {
125 std::lock_guard<std::mutex> lock(mtx);
126 if (data.empty())
127 {
128 T val;
129 return std::make_pair(val, false);
130 }
131 else
132 {
133 return std::make_pair(*data.begin(), true);
134 }
135 }
136
137 // get size
138 size_t size() const
139 {
140 std::lock_guard<std::mutex> lock(mtx);
141 return data.size();
142 }
143
144 private:
145 mutable std::mutex mtx;
146 std::set<T, Compare> data;
147 };
148
149 template <typename T>
150 class ThreadSafeVector
151 {
152 public:
153 // constructor
154 ThreadSafeVector() = default;
155
156 // add element
157 void push_back(const T& value)
158 {
159 std::lock_guard<std::mutex> lock(mtx);
160 data.push_back(value);
161 }
162
163 // clear vector
164 void clear()
165 {
166 std::lock_guard<std::mutex> lock(mtx);
167 data.clear();
168 }
169
170 // get size
171 size_t size() const
172 {
173 std::lock_guard<std::mutex> lock(mtx);
174 return data.size();
175 }
176
177 // get vector
178 std::vector<T> get() const
179 {
180 std::lock_guard<std::mutex> lock(mtx);
181 return data;
182 }
183
184 // check containment
185 bool contains(const T& value, std::function<bool(const OptSolution&, const OptSolution&)>& compare) const
186 {
187 std::lock_guard<std::mutex> lock(mtx);
188 for (auto it = data.begin(); it != data.end(); ++it)
189 {
190 if (compare(*it, value)) return true;
191 }
192 return false;
193 }
194
195 // atomically insert value only if no equivalent element already exists; returns true if inserted
196 bool push_back_if_not_contains(const T& value, std::function<bool(const OptSolution&, const OptSolution&)>& compare)
197 {
198 std::lock_guard<std::mutex> lock(mtx);
199 for (const auto& existing : data)
200 {
201 if (compare(existing, value)) return false;
202 }
203 data.push_back(value);
204 return true;
205 }
206
207 private:
208 mutable std::mutex mtx;
209 std::vector<T> data;
210 };
211
212 class Node final : public ADMM_solver
213 {
214 public:
215 // constructors
216 explicit Node(const std::shared_ptr<ADMM_data>& data) : ADMM_solver(data)
217 {
218 // init box constraints
219 this->x_box = *data->x_box;
220 }
221
222 // copy constructor
223 Node(const Node& other) : ADMM_solver(other)
224 {
225 this->x_box = other.x_box;
226 this->solution = other.solution;
227 this->width = this->x_box.width();
228 }
229
230 // public fields
231 OptSolution solution = OptSolution();
232 zono_float width = std::numeric_limits<zono_float>::infinity(); // width of the box
233
234 // run contractor
235 bool run_contractor()
236 {
237 const bool contractor_feasible = this->startup(this->x_box, this->solution);
238 this->width = this->x_box.width();
239 return contractor_feasible;
240 }
241
242 // fix bound
243 bool fix_bound(int ind, const zono_float val)
244 {
245 // update bounds
246 this->x_box.set_element(ind, Interval(val, val));
247
248 // run contractor
249 const bool contractor_feasible = this->startup(this->x_box, this->solution, {ind});
250 this->width = this->x_box.width();
251 return contractor_feasible;
252 }
253
254 // solve
255 void solve(std::atomic<bool>* stop = nullptr)
256 {
257 this->solve_core(this->x_box, this->solution, stop);
258 }
259
260 // update convergence tolerances
261 void update_convergence_tolerances(const zono_float eps_prim, const zono_float eps_dual)
262 {
263 this->eps_prim = eps_prim;
264 this->eps_dual = eps_dual;
265 }
266
267 // get box
268 const Box& get_box() const
269 {
270 return x_box;
271 }
272
273 private:
274 // members
275 Box x_box;
276 };
277
278 template <typename T, typename Compare=std::less<T>>
279 class PriorityQueuePrunable final : public std::priority_queue<T, std::vector<T>, Compare>
280 {
281 public:
282 // constructor
283 explicit PriorityQueuePrunable(const Compare& comp = Compare()) : std::priority_queue<
284 T, std::vector<T>, Compare>(comp)
285 {
286 }
287
288 // prune queue
289 void prune(const T& t)
290 {
291 auto it_prune = std::remove_if(this->c.begin(), this->c.end(), [&](const T& item)
292 {
293 return this->comp(item, t);
294 });
295 if (it_prune != this->c.end())
296 {
297 this->c.erase(it_prune, this->c.end());
298 std::make_heap(this->c.begin(), this->c.end(), this->comp);
299 }
300 }
301
302 // bottom
303 const T& bottom() const
304 {
305 return this->c.back();
306 }
307
308 // pop top
309 T pop_top()
310 {
311 T top = std::move(this->c.front());
312 this->pop();
313 return top;
314 }
315
316 // clear
317 void clear()
318 {
319 while (!this->empty())
320 this->pop();
321 }
322
323 };
324} // namespace ZonoOpt::detail
325
326
327#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