5#ifndef IDOL_OPTIMIZERFACTORY_H
6#define IDOL_OPTIMIZERFACTORY_H
23 std::optional<bool> m_logs;
24 std::optional<double> m_time_limit;
25 std::optional<unsigned int> m_thread_limit;
26 std::optional<unsigned int> m_iteration_count_limit;
27 std::optional<double> m_best_bound_stop;
28 std::optional<double> m_best_obj_stop;
29 std::optional<bool> m_presolve;
30 std::optional<bool> m_infeasible_or_unbounded_info;
32 std::optional<double> m_tol_mip_relative_gap;
33 std::optional<double> m_tol_mip_absolute_gap;
34 std::optional<double> m_tol_integer;
35 std::optional<double> m_tol_feasibility;
36 std::optional<double> m_tol_optimality;
38 [[nodiscard]]
virtual Optimizer* create(
const Model& t_model)
const = 0;
46 template<
class T> T& as() {
47 auto* result =
dynamic_cast<T*
>(
this);
49 throw Exception(
"Optimizer factory could not be cast to desired type.");
54 template<
class T>
const T& as()
const {
55 auto* result =
dynamic_cast<const T*
>(
this);
57 throw Exception(
"Optimizer factory could not be cast to desired type.");
62 template<
class T> [[nodiscard]]
bool is()
const {
63 return dynamic_cast<const T*
>(
this);
70 CRTP& crtp() {
return static_cast<CRTP&
>(*this); }
71 const CRTP& crtp()
const {
return static_cast<const CRTP&
>(*this); }
73 CRTP& with_logs(
bool t_value);
74 CRTP& with_time_limit(
double t_time_limit);
75 CRTP& with_thread_limit(
unsigned int t_max_n_threads);
76 CRTP& with_iteration_limit(
unsigned int t_iteration_count_limit);
77 CRTP& with_best_bound_stop(
double t_best_bound_stop);
78 CRTP& with_best_obj_stop(
double t_user_best_obj);
79 CRTP& with_presolve(
bool t_value);
80 CRTP& with_infeasible_or_unbounded_info(
bool t_value);
82 CRTP& with_tol_mip_relative_gap(
double t_tol_mip_relative_gap);
83 CRTP& with_tol_mip_absolute_gap(
double t_tol_mip_absolute_gap);
84 CRTP& with_tol_integer(
double t_tol_integer);
85 CRTP& with_tol_feasibility(
double t_tol_feasibility);
86 CRTP& with_tol_optimality(
double t_tol_optimality);
88 CRTP& conditional(
bool t_conditional_value,
const std::function<
void(CRTP&)>& t_if);
89 CRTP& conditional(
bool t_conditional_value,
const std::function<
void(CRTP&)>& t_if,
const std::function<
void(CRTP&)>& t_else);
95idol::OptimizerFactoryWithDefaultParameters<CRTP>::conditional(
bool t_conditional_value,
const std::function<
void(CRTP&)>& t_if,
const std::function<
void(CRTP&)>& t_else) {
96 t_conditional_value ? t_if(crtp()) : t_else(crtp());
102idol::OptimizerFactoryWithDefaultParameters<CRTP>::conditional(
bool t_conditional_value,
const std::function<
void(CRTP&)>& t_if) {
103 return conditional(t_conditional_value, t_if, [](CRTP&){});
107CRTP &idol::OptimizerFactoryWithDefaultParameters<CRTP>::with_infeasible_or_unbounded_info(
bool t_value) {
109 if (m_infeasible_or_unbounded_info.has_value()) {
110 throw Exception(
"An infeasible-or-unbounded-info instruction has already been given.");
113 m_infeasible_or_unbounded_info = t_value;
119CRTP &idol::OptimizerFactoryWithDefaultParameters<CRTP>::with_presolve(
bool t_value) {
121 if (m_presolve.has_value()) {
122 throw Exception(
"A get_param_presolve instruction has already been given.");
125 m_presolve = t_value;
131CRTP &idol::OptimizerFactoryWithDefaultParameters<CRTP>::with_tol_mip_absolute_gap(
double t_tol_mip_absolute_gap) {
133 if (m_tol_mip_absolute_gap.has_value()) {
134 throw Exception(
"An absolute gap tolerance count limit has already been given.");
137 m_tol_mip_absolute_gap = t_tol_mip_absolute_gap;
143CRTP& idol::OptimizerFactoryWithDefaultParameters<CRTP>::with_tol_integer(
double t_tol_integer) {
144 if (m_tol_mip_absolute_gap.has_value()) {
145 throw Exception(
"A tolerance for integrality has already been given.");
147 m_tol_integer = t_tol_integer;
152CRTP& idol::OptimizerFactoryWithDefaultParameters<CRTP>::with_tol_feasibility(
double t_tol_feasibility) {
153 if (m_tol_feasibility.has_value()) {
154 throw Exception(
"A tolerance for feasibility has already been given.");
156 m_tol_feasibility = t_tol_feasibility;
161CRTP& idol::OptimizerFactoryWithDefaultParameters<CRTP>::with_tol_optimality(
double t_tol_optimality) {
163 if (m_tol_optimality.has_value()) {
164 throw Exception(
"An optimality tolerance has already been given.");
167 m_tol_optimality = t_tol_optimality;
173CRTP &idol::OptimizerFactoryWithDefaultParameters<CRTP>::with_tol_mip_relative_gap(
double t_tol_mip_relative_gap) {
175 if (m_tol_mip_relative_gap.has_value()) {
176 throw Exception(
"A relative gap tolerance count limit has already been given.");
179 m_tol_mip_relative_gap = t_tol_mip_relative_gap;
185CRTP &idol::OptimizerFactoryWithDefaultParameters<CRTP>::with_best_obj_stop(
double t_user_best_obj) {
187 if (m_best_obj_stop.has_value()) {
188 throw Exception(
"A user best obj count limit has already been given.");
191 m_best_obj_stop = t_user_best_obj;
197CRTP &idol::OptimizerFactoryWithDefaultParameters<CRTP>::with_best_bound_stop(
double t_best_bound_stop) {
199 if (m_best_bound_stop.has_value()) {
200 throw Exception(
"A user best bound limit has already been given.");
203 m_best_bound_stop = t_best_bound_stop;
209CRTP &idol::OptimizerFactoryWithDefaultParameters<CRTP>::with_iteration_limit(
unsigned int t_iteration_count_limit) {
211 if (m_iteration_count_limit.has_value()) {
212 throw Exception(
"An iteration count limit has already been given.");
215 m_iteration_count_limit = t_iteration_count_limit;
221CRTP &idol::OptimizerFactoryWithDefaultParameters<CRTP>::with_thread_limit(
unsigned int t_max_n_threads) {
223 if (m_thread_limit.has_value()) {
224 throw Exception(
"A thread limit has already been given.");
227 m_thread_limit = t_max_n_threads;
233CRTP &idol::OptimizerFactoryWithDefaultParameters<CRTP>::with_time_limit(
double t_time_limit) {
235 if (m_time_limit.has_value()) {
236 throw Exception(
"A time limit has already been given.");
239 m_time_limit = t_time_limit;
245CRTP &idol::OptimizerFactoryWithDefaultParameters<CRTP>::with_logs(
bool t_value) {
247 if (m_logs.has_value()) {
248 throw Exception(
"Logging settings have already been given.");