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
13namespace idol {
14 class Model;
15 class OptimizerFactory;
16 template<class CRTP>
17 class OptimizerFactoryWithDefaultParameters;
18}
19
27public:
28 virtual ~OptimizerFactory() = default;
29
35 virtual Optimizer* operator()(const Model& t_model) const = 0;
36
41 [[nodiscard]] virtual OptimizerFactory* clone() const = 0;
42
43
44 template<class T> T& as() {
45 auto* result = dynamic_cast<T*>(this);
46 if (!result) {
47 throw Exception("Optimizer factory could not be cast to desired type.");
48 }
49 return *result;
50 }
51
52 template<class T> const T& as() const {
53 auto* result = dynamic_cast<const T*>(this);
54 if (!result) {
55 throw Exception("Optimizer factory could not be cast to desired type.");
56 }
57 return *result;
58 }
59
60 template<class T> [[nodiscard]] bool is() const {
61 return dynamic_cast<const T*>(this);
62 }
63};
64
65template<class CRTP>
67 std::optional<bool> m_logs;
68 std::optional<double> m_time_limit;
69 std::optional<unsigned int> m_thread_limit;
70 std::optional<unsigned int> m_iteration_count_limit;
71 std::optional<double> m_best_bound_stop;
72 std::optional<double> m_best_obj_stop;
73 std::optional<double> m_relative_gap_tolerance;
74 std::optional<double> m_absolute_gap_tolerance;
75 std::optional<bool> m_presolve;
76 std::optional<bool> m_infeasible_or_unbounded_info;
77protected:
78 CRTP& crtp() { return static_cast<CRTP&>(*this); }
79 const CRTP& crtp() const { return static_cast<const CRTP&>(*this); }
80
81 void handle_default_parameters(Optimizer* t_optimizer) const;
82public:
95 CRTP& with_logs(bool t_value);
96
108 CRTP& with_time_limit(double t_time_limit);
109
121 CRTP& with_thread_limit(unsigned int t_max_n_threads);
122
134 CRTP& with_iteration_limit(unsigned int t_iteration_count_limit);
135
149 CRTP& with_best_bound_stop(double t_best_bound_stop);
150
164 CRTP& with_best_obj_stop(double t_user_best_obj);
165
178 CRTP& with_relative_gap_tolerance(double t_relative_gap_tolerance);
179
192 CRTP& with_absolute_gap_tolerance(double t_absolute_gap_tolerance);
193
205 CRTP& with_presolve(bool t_value);
206
220
238 CRTP& conditional(bool t_conditional_value, const std::function<void(CRTP&)>& t_if);
239
260 CRTP& conditional(bool t_conditional_value, const std::function<void(CRTP&)>& t_if, const std::function<void(CRTP&)>& t_else);
261
262};
263
264template<class CRTP>
265CRTP &
266idol::OptimizerFactoryWithDefaultParameters<CRTP>::conditional(bool t_conditional_value, const std::function<void(CRTP&)>& t_if, const std::function<void(CRTP&)>& t_else) {
267 t_conditional_value ? t_if(crtp()) : t_else(crtp());
268 return crtp();
269}
270
271template<class CRTP>
272CRTP &
273idol::OptimizerFactoryWithDefaultParameters<CRTP>::conditional(bool t_conditional_value, const std::function<void(CRTP&)>& t_if) {
274 return conditional(t_conditional_value, t_if, [](CRTP&){});
275}
276
277template<class CRTP>
279
280 if (m_infeasible_or_unbounded_info.has_value()) {
281 throw Exception("An infeasible-or-unbounded-info instruction has already been given.");
282 }
283
284 m_infeasible_or_unbounded_info = t_value;
285
286 return crtp();
287}
288
289template<class CRTP>
291
292 if (m_presolve.has_value()) {
293 throw Exception("A get_param_presolve instruction has already been given.");
294 }
295
296 m_presolve = t_value;
297
298 return crtp();
299}
300
301template<class CRTP>
303
304 if (m_absolute_gap_tolerance.has_value()) {
305 throw Exception("An absolute gap tolerance count limit has already been given.");
306 }
307
308 m_absolute_gap_tolerance = t_absolute_gap_tolerance;
309
310 return crtp();
311}
312
313template<class CRTP>
315
316 if (m_relative_gap_tolerance.has_value()) {
317 throw Exception("A relative gap tolerance count limit has already been given.");
318 }
319
320 m_relative_gap_tolerance = t_relative_gap_tolerance;
321
322 return crtp();
323}
324
325template<class CRTP>
327
328 if (m_best_obj_stop.has_value()) {
329 throw Exception("A user best obj count limit has already been given.");
330 }
331
332 m_best_obj_stop = t_user_best_obj;
333
334 return crtp();
335}
336
337template<class CRTP>
339
340 if (m_best_bound_stop.has_value()) {
341 throw Exception("A user best bound limit has already been given.");
342 }
343
344 m_best_bound_stop = t_user_best_bound;
345
346 return crtp();
347}
348
349template<class CRTP>
351
352 if (m_iteration_count_limit.has_value()) {
353 throw Exception("An iteration count limit has already been given.");
354 }
355
356 m_iteration_count_limit = t_iteration_count_limit;
357
358 return crtp();
359}
360
361template<class CRTP>
363
364 if (m_thread_limit.has_value()) {
365 throw Exception("A thread limit has already been given.");
366 }
367
368 m_thread_limit = t_max_n_threads;
369
370 return crtp();
371}
372
373template<class CRTP>
375
376 if (m_time_limit.has_value()) {
377 throw Exception("A time limit has already been given.");
378 }
379
380 m_time_limit = t_time_limit;
381
382 return crtp();
383}
384
385template<class CRTP>
387
388 if (m_logs.has_value()) {
389 throw Exception("Logging settings have already been given.");
390 }
391
392 m_logs = t_value;
393
394 return crtp();
395}
396
397template<class CRTP>
399
400 if (m_logs.has_value()) {
401 t_optimizer->set_param_logs(m_logs.value());
402 }
403
404 if (m_time_limit.has_value()) {
405 t_optimizer->set_param_time_limit(m_time_limit.value());
406 }
407
408 if (m_thread_limit.has_value()) {
409 t_optimizer->set_param_threads(m_thread_limit.value());
410 }
411
412 if (m_best_bound_stop.has_value()) {
413 t_optimizer->set_param_best_bound_stop(m_best_bound_stop.value());
414 }
415
416 if (m_best_obj_stop.has_value()) {
417 t_optimizer->set_param_best_obj_stop(m_best_obj_stop.value());
418 }
419
420 if (m_relative_gap_tolerance.has_value()) {
421 t_optimizer->set_tol_mip_relative_gap(m_relative_gap_tolerance.value());
422 }
423
424 if (m_absolute_gap_tolerance.has_value()) {
425 t_optimizer->set_tol_mip_absolute_gap(m_absolute_gap_tolerance.value());
426 }
427
428 if (m_iteration_count_limit.has_value()) {
429 t_optimizer->set_param_iteration_limit(m_iteration_count_limit.value());
430 }
431
432 if (m_presolve.has_value()) {
433 t_optimizer->set_param_presolve(m_presolve.value());
434 }
435
436 if (m_infeasible_or_unbounded_info.has_value()) {
437 t_optimizer->set_param_infeasible_or_unbounded_info(m_infeasible_or_unbounded_info.value());
438 }
439
440}
441
442#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