idol
A C++ Framework for Optimization
Loading...
Searching...
No Matches
OptimizerFactory.h
1//
2// Created by henri on 21/03/23.
3//
4
5#ifndef IDOL_OPTIMIZERFACTORY_H
6#define IDOL_OPTIMIZERFACTORY_H
7
8#include "Optimizer.h"
9
10#include <optional>
11#include <functional>
12#include <thread>
13
14namespace idol {
15 class Model;
16 class OptimizerFactory;
17 template<class CRTP>
18 class OptimizerFactoryWithDefaultParameters;
19}
20
28public:
29 virtual ~OptimizerFactory() = default;
30
36 virtual Optimizer* operator()(const Model& t_model) const = 0;
37
42 [[nodiscard]] virtual OptimizerFactory* clone() const = 0;
43
44
45 template<class T> T& as() {
46 auto* result = dynamic_cast<T*>(this);
47 if (!result) {
48 throw Exception("Optimizer factory could not be cast to desired type.");
49 }
50 return *result;
51 }
52
53 template<class T> const T& as() const {
54 auto* result = dynamic_cast<const T*>(this);
55 if (!result) {
56 throw Exception("Optimizer factory could not be cast to desired type.");
57 }
58 return *result;
59 }
60
61 template<class T> [[nodiscard]] bool is() const {
62 return dynamic_cast<const T*>(this);
63 }
64};
65
66template<class CRTP>
68 std::optional<bool> m_logs;
69 std::optional<double> m_time_limit;
70 std::optional<unsigned int> m_thread_limit;
71 std::optional<unsigned int> m_iteration_count_limit;
72 std::optional<double> m_best_bound_stop;
73 std::optional<double> m_best_obj_stop;
74 std::optional<double> m_relative_gap_tolerance;
75 std::optional<double> m_absolute_gap_tolerance;
76 std::optional<bool> m_presolve;
77 std::optional<bool> m_infeasible_or_unbounded_info;
78protected:
79 CRTP& crtp() { return static_cast<CRTP&>(*this); }
80 const CRTP& crtp() const { return static_cast<const CRTP&>(*this); }
81
82 void handle_default_parameters(Optimizer* t_optimizer) const;
83public:
96 CRTP& with_logs(bool t_value);
97
109 CRTP& with_time_limit(double t_time_limit);
110
122 CRTP& with_thread_limit(unsigned int t_max_n_threads);
123
135 CRTP& with_iteration_limit(unsigned int t_iteration_count_limit);
136
150 CRTP& with_best_bound_stop(double t_best_bound_stop);
151
165 CRTP& with_best_obj_stop(double t_user_best_obj);
166
179 CRTP& with_relative_gap_tolerance(double t_relative_gap_tolerance);
180
193 CRTP& with_absolute_gap_tolerance(double t_absolute_gap_tolerance);
194
206 CRTP& with_presolve(bool t_value);
207
221
239 CRTP& conditional(bool t_conditional_value, const std::function<void(CRTP&)>& t_if);
240
261 CRTP& conditional(bool t_conditional_value, const std::function<void(CRTP&)>& t_if, const std::function<void(CRTP&)>& t_else);
262
263};
264
265template<class CRTP>
266CRTP &
267idol::OptimizerFactoryWithDefaultParameters<CRTP>::conditional(bool t_conditional_value, const std::function<void(CRTP&)>& t_if, const std::function<void(CRTP&)>& t_else) {
268 t_conditional_value ? t_if(crtp()) : t_else(crtp());
269 return crtp();
270}
271
272template<class CRTP>
273CRTP &
274idol::OptimizerFactoryWithDefaultParameters<CRTP>::conditional(bool t_conditional_value, const std::function<void(CRTP&)>& t_if) {
275 return conditional(t_conditional_value, t_if, [](CRTP&){});
276}
277
278template<class CRTP>
280
281 if (m_infeasible_or_unbounded_info.has_value()) {
282 throw Exception("An infeasible-or-unbounded-info instruction has already been given.");
283 }
284
285 m_infeasible_or_unbounded_info = t_value;
286
287 return crtp();
288}
289
290template<class CRTP>
292
293 if (m_presolve.has_value()) {
294 throw Exception("A get_param_presolve instruction has already been given.");
295 }
296
297 m_presolve = t_value;
298
299 return crtp();
300}
301
302template<class CRTP>
304
305 if (m_absolute_gap_tolerance.has_value()) {
306 throw Exception("An absolute gap tolerance count limit has already been given.");
307 }
308
309 m_absolute_gap_tolerance = t_absolute_gap_tolerance;
310
311 return crtp();
312}
313
314template<class CRTP>
316
317 if (m_relative_gap_tolerance.has_value()) {
318 throw Exception("A relative gap tolerance count limit has already been given.");
319 }
320
321 m_relative_gap_tolerance = t_relative_gap_tolerance;
322
323 return crtp();
324}
325
326template<class CRTP>
328
329 if (m_best_obj_stop.has_value()) {
330 throw Exception("A user best obj count limit has already been given.");
331 }
332
333 m_best_obj_stop = t_user_best_obj;
334
335 return crtp();
336}
337
338template<class CRTP>
340
341 if (m_best_bound_stop.has_value()) {
342 throw Exception("A user best bound limit has already been given.");
343 }
344
345 m_best_bound_stop = t_user_best_bound;
346
347 return crtp();
348}
349
350template<class CRTP>
352
353 if (m_iteration_count_limit.has_value()) {
354 throw Exception("An iteration count limit has already been given.");
355 }
356
357 m_iteration_count_limit = t_iteration_count_limit;
358
359 return crtp();
360}
361
362template<class CRTP>
364
365 if (m_thread_limit.has_value()) {
366 throw Exception("A thread limit has already been given.");
367 }
368
369 m_thread_limit = t_max_n_threads;
370
371 return crtp();
372}
373
374template<class CRTP>
376
377 if (m_time_limit.has_value()) {
378 throw Exception("A time limit has already been given.");
379 }
380
381 m_time_limit = t_time_limit;
382
383 return crtp();
384}
385
386template<class CRTP>
388
389 if (m_logs.has_value()) {
390 throw Exception("Logging settings have already been given.");
391 }
392
393 m_logs = t_value;
394
395 return crtp();
396}
397
398template<class CRTP>
400
401 t_optimizer->set_param_logs(m_logs.value_or(false));
402 t_optimizer->set_param_time_limit(m_time_limit.value_or(std::numeric_limits<double>::max()));
403 t_optimizer->set_param_threads(m_thread_limit.value_or(std::max<unsigned int>(std::thread::hardware_concurrency(), 1)));
404 t_optimizer->set_param_best_bound_stop(m_best_bound_stop.value_or(Inf));
405 t_optimizer->set_param_best_obj_stop(m_best_obj_stop.value_or(-Inf));
406 t_optimizer->set_tol_mip_relative_gap(m_relative_gap_tolerance.value_or(Tolerance::MIPRelativeGap));
407 t_optimizer->set_tol_mip_absolute_gap(m_absolute_gap_tolerance.value_or(Tolerance::MIPAbsoluteGap));
408 t_optimizer->set_param_iteration_limit(m_iteration_count_limit.value_or(std::numeric_limits<unsigned int>::max()));
409 t_optimizer->set_param_presolve(m_presolve.value_or(true));
410 t_optimizer->set_param_infeasible_or_unbounded_info(m_infeasible_or_unbounded_info.value_or(false));
411
412}
413
414#endif //IDOL_OPTIMIZERFACTORY_H
CRTP & with_best_bound_stop(double t_best_bound_stop)
CRTP & conditional(bool t_conditional_value, const std::function< void(CRTP &)> &t_if)
CRTP & with_thread_limit(unsigned int t_max_n_threads)
CRTP & with_absolute_gap_tolerance(double t_absolute_gap_tolerance)
CRTP & with_iteration_limit(unsigned int t_iteration_count_limit)
CRTP & with_relative_gap_tolerance(double t_relative_gap_tolerance)
CRTP & with_best_obj_stop(double t_user_best_obj)
CRTP & conditional(bool t_conditional_value, const std::function< void(CRTP &)> &t_if, const std::function< void(CRTP &)> &t_else)
virtual Optimizer * operator()(const Model &t_model) const =0
virtual OptimizerFactory * clone() const =0