From 8ef641f6adfbb9fa40de3f1f11ae77c68eda27f3 Mon Sep 17 00:00:00 2001 From: Henri Lefebvre Date: Thu, 17 Aug 2023 15:42:18 +0200 Subject: [PATCH] set default tolerances and parameters for gurobi --- lib/include/optimizers/Optimizer.h | 93 ++++++++++++------- lib/include/optimizers/OptimizerFactory.h | 30 +++--- .../Optimizers_BranchAndBound.h | 16 ++-- .../optimizers/solvers/Optimizers_GLPK.h | 8 +- .../optimizers/solvers/Optimizers_Mosek.h | 14 +-- .../solvers/gurobi/Optimizers_Gurobi.h | 24 +++-- lib/src/modeling/models/Model.cpp | 2 +- lib/src/optimizers/Optimizer.cpp | 2 +- .../Optimizers_ColumnGeneration.cpp | 24 ++--- .../optimizers/solvers/Optimizers_GLPK.cpp | 18 ++-- .../optimizers/solvers/Optimizers_Mosek.cpp | 28 +++--- .../solvers/gurobi/Optimizers_Gurobi.cpp | 64 +++++++++---- 12 files changed, 190 insertions(+), 133 deletions(-) diff --git a/lib/include/optimizers/Optimizer.h b/lib/include/optimizers/Optimizer.h index 64704c79..214e6b6a 100644 --- a/lib/include/optimizers/Optimizer.h +++ b/lib/include/optimizers/Optimizer.h @@ -29,17 +29,26 @@ class idol::impl::Optimizer { const ::idol::Model& m_parent; bool m_is_terminated = false; - LogLevel m_log_level = Warn; - Color m_log_color = Default; - double m_time_limit = std::numeric_limits::max(); - unsigned int m_thread_limit = 1; - unsigned int m_iteration_count_limit = std::numeric_limits::max(); - double m_best_obj_stop = -Inf; - double m_best_bound_stop = +Inf; - double m_relative_gap_tolerance = 1e-4; - double m_absolute_gap_tolerance = 1e-8; - bool m_presolve = true; - bool m_infeasible_or_unbounded_info = false; + + LogLevel m_param_log_level = Warn; + + Color m_param_log_color = Default; + + unsigned int m_param_threads = 1; + unsigned int m_param_iteration_limit = std::numeric_limits::max(); + + double m_param_time_limit = std::numeric_limits::max(); + double m_param_best_obj_stop = -Inf; + double m_param_best_bound_stop = +Inf; + + bool m_param_presolve = true; + bool m_param_infeasible_or_unbounded_info = false; + + double m_tol_mip_relative_gap = Tolerance::MIPRelativeGap; + double m_tol_mip_absolute_gap = Tolerance::MIPAbsoluteGap; + double m_tol_integer = Tolerance::Integer; + double m_tol_feasibility = Tolerance::Feasibility; + double m_tol_optimality = Tolerance::Optimality; Timer m_timer; protected: @@ -123,49 +132,61 @@ class idol::impl::Optimizer { [[nodiscard]] virtual const ::idol::Model& parent() const { return m_parent; } - [[nodiscard]] LogLevel log_level() const { return m_log_level; } + [[nodiscard]] LogLevel log_level() const { return m_param_log_level; } + + virtual void set_param_log_level(LogLevel t_log_level) { m_param_log_level = t_log_level; } + + [[nodiscard]] Color log_color() const { return m_param_log_color; } + + virtual void set_param_log_color(Color t_log_color) { m_param_log_color = t_log_color; } + + [[nodiscard]] double get_param_time_limit() const { return m_param_time_limit; } + + virtual void set_param_time_limit(double t_time_limit) { m_param_time_limit = t_time_limit; } + + [[nodiscard]] unsigned int get_param_threads() const { return m_param_threads; } - virtual void set_log_level(LogLevel t_log_level) { m_log_level = t_log_level; } + virtual void set_param_threads(unsigned int t_threads) { m_param_threads = t_threads; } - [[nodiscard]] Color log_color() const { return m_log_color; } + [[nodiscard]] double get_param_best_obj_stop() const { return m_param_best_obj_stop; } - virtual void set_log_color(Color t_log_color) { m_log_color = t_log_color; } + virtual void set_param_best_obj_stop(double t_best_obj_stop) { m_param_best_obj_stop = t_best_obj_stop; } - [[nodiscard]] double get_time_limit() const { return m_time_limit; } + [[nodiscard]] double get_param_best_bound_stop() const { return m_param_best_bound_stop; } - virtual void set_time_limit(double t_time_limit) { m_time_limit = t_time_limit; } + virtual void set_param_best_bound_stop(double t_best_bound_stop) { m_param_best_bound_stop = t_best_bound_stop; } - [[nodiscard]] unsigned int thread_limit() const { return m_thread_limit; } + [[nodiscard]] double get_tol_mip_relative_gap() const { return m_tol_mip_relative_gap; } - virtual void set_thread_limit(unsigned int t_thread_limit) { m_thread_limit = t_thread_limit; } + virtual void set_tol_mip_relative_gap(double t_tol_mip_relative_gap) { m_tol_mip_relative_gap = t_tol_mip_relative_gap; } - [[nodiscard]] double best_obj_stop() const { return m_best_obj_stop; } + [[nodiscard]] double get_tol_mip_absolute_gap() const { return m_tol_mip_absolute_gap; } - virtual void set_best_obj_stop(double t_best_obj_stop) { m_best_obj_stop = t_best_obj_stop; } + virtual void set_tol_mip_absolute_gap(double t_mip_tol_absolute_gap) { m_tol_mip_absolute_gap = t_mip_tol_absolute_gap; } - [[nodiscard]] double best_bound_stop() const { return m_best_bound_stop; } + [[nodiscard]] double get_tol_feasibility() const { return m_tol_feasibility; } - virtual void set_best_bound_stop(double t_best_bound_stop) { m_best_bound_stop = t_best_bound_stop; } + virtual void set_tol_feasibility(double t_tol_feasibility) { m_tol_feasibility = t_tol_feasibility; } - [[nodiscard]] double relative_gap_tolerance() const { return m_relative_gap_tolerance; } + [[nodiscard]] double get_tol_optimality() const { return m_tol_optimality; } - virtual void set_relative_gap_tolerance(double t_relative_gap_tolerance) { m_relative_gap_tolerance = t_relative_gap_tolerance; } + virtual void set_tol_optimality(double t_tol_optimality) { m_tol_optimality = t_tol_optimality; } - [[nodiscard]] double absolute_gap_tolerance() const { return m_absolute_gap_tolerance; } + [[nodiscard]] double get_tol_integer() const { return m_tol_integer; } - virtual void set_absolute_gap_tolerance(double t_absolute_gap_tolerance) { m_absolute_gap_tolerance = t_absolute_gap_tolerance; } + virtual void set_tol_integer(double t_tol_integer) { m_tol_integer = t_tol_integer; } - [[nodiscard]] unsigned int iteration_count_limit() const { return m_iteration_count_limit; } + [[nodiscard]] unsigned int get_param_iteration_count_limit() const { return m_param_iteration_limit; } - void set_iteration_count_limit(unsigned int t_iteration_count_limit) { m_iteration_count_limit = t_iteration_count_limit; } + void set_param_iteration_limit(unsigned int t_iteration_limit) { m_param_iteration_limit = t_iteration_limit; } - [[nodiscard]] bool presolve() const { return m_presolve; } + [[nodiscard]] bool get_param_presolve() const { return m_param_presolve; } - virtual void set_presolve(bool t_value) { m_presolve = t_value; } + virtual void set_param_presolve(bool t_value) { m_param_presolve = t_value; } - [[nodiscard]] bool infeasible_or_unbounded_info() const { return m_infeasible_or_unbounded_info; } + [[nodiscard]] bool get_param_infeasible_or_unbounded_info() const { return m_param_infeasible_or_unbounded_info; } - virtual void set_infeasible_or_unbounded_info(bool t_value) { m_infeasible_or_unbounded_info = t_value; } + virtual void set_param_infeasible_or_unbounded_info(bool t_value) { m_param_infeasible_or_unbounded_info = t_value; } [[nodiscard]] const Timer& time() const { return m_timer; } @@ -173,12 +194,12 @@ class idol::impl::Optimizer { [[nodiscard]] bool is_terminated() const { return m_is_terminated; } - void terminate(); + virtual void terminate(); template T& as() { auto* result = dynamic_cast(this); if (!result) { - throw Exception("Bad cast."); + throw Exception("Optimizer could not be cast to desired type."); } return *result; } @@ -186,7 +207,7 @@ class idol::impl::Optimizer { template const T& as() const { auto* result = dynamic_cast(this); if (!result) { - throw Exception("Bad cast."); + throw Exception("Optimizer could not be cast to desired type."); } return *result; } diff --git a/lib/include/optimizers/OptimizerFactory.h b/lib/include/optimizers/OptimizerFactory.h index a5fbbcf8..84fa5f1d 100644 --- a/lib/include/optimizers/OptimizerFactory.h +++ b/lib/include/optimizers/OptimizerFactory.h @@ -173,14 +173,14 @@ class idol::OptimizerFactoryWithDefaultParameters : public OptimizerFactory { CRTP& with_absolute_gap_tolerance(double t_absolute_gap_tolerance); /** - * Sets the presolve activation for the optimizer. + * Sets the get_param_presolve activation for the optimizer. * * Example: * ```cpp * auto algorithm = GLPK() - * .with_presolve(false); // turns off presolve phase + * .with_presolve(false); // turns off get_param_presolve phase * ``` - * @param t_value the activation level for the optimizer's presolve (0 for disabling, 1 for enabling) + * @param t_value the activation level for the optimizer's get_param_presolve (0 for disabling, 1 for enabling) * @return the optimizer factory itself */ CRTP& with_presolve(bool t_value); @@ -271,7 +271,7 @@ template CRTP &idol::OptimizerFactoryWithDefaultParameters::with_presolve(bool t_value) { if (m_presolve.has_value()) { - throw Exception("A presolve instruction has already been given."); + throw Exception("A get_param_presolve instruction has already been given."); } m_presolve = t_value; @@ -380,47 +380,47 @@ template void idol::OptimizerFactoryWithDefaultParameters::handle_default_parameters(Optimizer *t_optimizer) const { if (m_log_level.has_value()) { - t_optimizer->set_log_level(m_log_level.value()); + t_optimizer->set_param_log_level(m_log_level.value()); } if (m_log_color.has_value()) { - t_optimizer->set_log_color(m_log_color.value()); + t_optimizer->set_param_log_color(m_log_color.value()); } if (m_time_limit.has_value()) { - t_optimizer->set_time_limit(m_time_limit.value()); + t_optimizer->set_param_time_limit(m_time_limit.value()); } if (m_thread_limit.has_value()) { - t_optimizer->set_thread_limit(m_thread_limit.value()); + t_optimizer->set_param_threads(m_thread_limit.value()); } if (m_best_bound_stop.has_value()) { - t_optimizer->set_best_bound_stop(m_best_bound_stop.value()); + t_optimizer->set_param_best_bound_stop(m_best_bound_stop.value()); } if (m_best_obj_stop.has_value()) { - t_optimizer->set_best_obj_stop(m_best_obj_stop.value()); + t_optimizer->set_param_best_obj_stop(m_best_obj_stop.value()); } if (m_relative_gap_tolerance.has_value()) { - t_optimizer->set_relative_gap_tolerance(m_relative_gap_tolerance.value()); + t_optimizer->set_tol_mip_relative_gap(m_relative_gap_tolerance.value()); } if (m_absolute_gap_tolerance.has_value()) { - t_optimizer->set_absolute_gap_tolerance(m_absolute_gap_tolerance.value()); + t_optimizer->set_tol_mip_absolute_gap(m_absolute_gap_tolerance.value()); } if (m_iteration_count_limit.has_value()) { - t_optimizer->set_iteration_count_limit(m_iteration_count_limit.value()); + t_optimizer->set_param_iteration_limit(m_iteration_count_limit.value()); } if (m_presolve.has_value()) { - t_optimizer->set_presolve(m_presolve.value()); + t_optimizer->set_param_presolve(m_presolve.value()); } if (m_infeasible_or_unbounded_info.has_value()) { - t_optimizer->set_infeasible_or_unbounded_info(m_infeasible_or_unbounded_info.value()); + t_optimizer->set_param_infeasible_or_unbounded_info(m_infeasible_or_unbounded_info.value()); } } diff --git a/lib/include/optimizers/branch-and-bound/Optimizers_BranchAndBound.h b/lib/include/optimizers/branch-and-bound/Optimizers_BranchAndBound.h index 3149da84..0d3f8b35 100644 --- a/lib/include/optimizers/branch-and-bound/Optimizers_BranchAndBound.h +++ b/lib/include/optimizers/branch-and-bound/Optimizers_BranchAndBound.h @@ -351,8 +351,8 @@ void idol::Optimizers::BranchAndBound::hook_before_optimize() { Algorithm::hook_before_optimize(); // Reset solution - set_best_bound(std::max(-Inf, best_obj_stop())); - set_best_obj(std::min(+Inf, best_bound_stop())); + set_best_bound(std::max(-Inf, get_param_best_obj_stop())); + set_best_obj(std::min(+Inf, get_param_best_bound_stop())); m_incumbent.reset(); m_n_created_nodes = 0; @@ -465,8 +465,8 @@ void idol::Optimizers::BranchAndBound::solve(TreeNode& t_node) { m_node_updator->apply_local_updates(t_node.info()); - m_relaxation->optimizer().set_best_bound_stop(std::min(get_best_obj(), best_bound_stop())); - m_relaxation->optimizer().set_time_limit(get_remaining_time()); + m_relaxation->optimizer().set_param_best_bound_stop(std::min(get_best_obj(), get_param_best_bound_stop())); + m_relaxation->optimizer().set_param_time_limit(get_remaining_time()); idol_Log(Debug, "Beginning to solve node " << t_node.id() << "."); @@ -640,7 +640,9 @@ void idol::Optimizers::BranchAndBound::prune_nodes_by_bound(BranchAnd while (it != end) { if (const auto& node = *it ; node.info().objective_value() >= upper_bound) { - idol_Log(Trace, "Node " << node.id() << " was pruned by bound " << "(BestObj: " << get_best_obj() << ", Obj: " << node.info().objective_value() << ")."); + idol_Log(Trace, + "Node " << node.id() << " was pruned by bound " << "(BestObj: " << get_best_obj() << ", Obj: " + << node.info().objective_value() << ")."); it = t_active_nodes.erase(it); end = t_active_nodes.by_objective_value().end(); } else { @@ -684,8 +686,8 @@ template bool idol::Optimizers::BranchAndBound::gap_is_closed() const { return is_terminated() || get_remaining_time() == 0 - || get_relative_gap() <= relative_gap_tolerance() - || get_absolute_gap() <= absolute_gap_tolerance(); + || get_relative_gap() <= get_tol_mip_relative_gap() + || get_absolute_gap() <= get_tol_mip_absolute_gap(); } template diff --git a/lib/include/optimizers/solvers/Optimizers_GLPK.h b/lib/include/optimizers/solvers/Optimizers_GLPK.h index ce55565c..71370d6c 100644 --- a/lib/include/optimizers/solvers/Optimizers_GLPK.h +++ b/lib/include/optimizers/solvers/Optimizers_GLPK.h @@ -89,13 +89,13 @@ class idol::Optimizers::GLPK : public OptimizerWithLazyUpdates { [[nodiscard]] std::string name() const override { return "glpk"; } - void set_time_limit(double t_time_limit) override; + void set_param_time_limit(double t_time_limit) override; - void set_best_obj_stop(double t_best_obj_stop) override; + void set_param_best_obj_stop(double t_best_obj_stop) override; - void set_best_bound_stop(double t_best_bound_stop) override; + void set_param_best_bound_stop(double t_best_bound_stop) override; - void set_presolve(bool t_value) override; + void set_param_presolve(bool t_value) override; }; diff --git a/lib/include/optimizers/solvers/Optimizers_Mosek.h b/lib/include/optimizers/solvers/Optimizers_Mosek.h index 93aa7ada..f891fba4 100644 --- a/lib/include/optimizers/solvers/Optimizers_Mosek.h +++ b/lib/include/optimizers/solvers/Optimizers_Mosek.h @@ -94,17 +94,17 @@ class idol::Optimizers::Mosek : public OptimizerWithLazyUpdatesoptimizer().infeasible_or_unbounded_info()) { - m_master->optimizer().set_infeasible_or_unbounded_info(true); + if (m_farkas_pricing && !m_master->optimizer().get_param_infeasible_or_unbounded_info()) { + m_master->optimizer().set_param_infeasible_or_unbounded_info(true); } for (auto& subproblem : m_subproblems) { @@ -226,7 +226,7 @@ void idol::Optimizers::ColumnGeneration::run_column_generation() { ++m_iteration_count; - if (m_iteration_count >= iteration_count_limit()) { + if (m_iteration_count >= get_param_iteration_count_limit()) { set_reason(IterLimit); terminate(); break; @@ -234,7 +234,7 @@ void idol::Optimizers::ColumnGeneration::run_column_generation() { } while (true); - if (get_relative_gap() <= relative_gap_tolerance()) { + if (get_relative_gap() <= get_tol_mip_relative_gap()) { set_status(Optimal); set_reason(Proved); } @@ -389,7 +389,7 @@ void idol::Optimizers::ColumnGeneration::update_subproblems() { void idol::Optimizers::ColumnGeneration::solve_subproblems() { - const unsigned int n_threads = std::min(thread_limit(), m_parallel_pricing_limit); + const unsigned int n_threads = std::min(get_param_threads(), m_parallel_pricing_limit); #pragma omp parallel for num_threads(n_threads) default(none) for (auto& subproblem : m_subproblems) { @@ -469,12 +469,12 @@ void idol::Optimizers::ColumnGeneration::analyze_subproblems_solution() { set_best_bound(std::min(lower_bound, get_best_obj())); } - if (m_artificial_variables.empty() && get_best_bound() > best_bound_stop()) { + if (m_artificial_variables.empty() && get_best_bound() > get_param_best_bound_stop()) { set_status(get_relative_gap() > 0 ? Feasible : Optimal); set_reason(ObjLimit); terminate(); idol_Log(Trace, - "Terminate. Given best_bound_stop is " << best_bound_stop() + "Terminate. Given get_param_best_bound_stop is " << get_param_best_bound_stop() << " while current best bound is " << get_best_bound() ) } @@ -685,8 +685,8 @@ void idol::Optimizers::ColumnGeneration::Subproblem::optimize() { const auto [time_limit, relative_gap] = m_parent.m_non_optimal_pricing_phase.value(); const auto duals = save_dual(*m_parent.m_master); - m_model->optimizer().set_relative_gap_tolerance(relative_gap); - m_model->optimizer().set_time_limit(std::min(m_parent.get_remaining_time(), time_limit)); + m_model->optimizer().set_tol_mip_relative_gap(relative_gap); + m_model->optimizer().set_param_time_limit(std::min(m_parent.get_remaining_time(), time_limit)); m_model->optimize(); if (compute_reduced_cost(duals) < 0) { @@ -695,7 +695,7 @@ void idol::Optimizers::ColumnGeneration::Subproblem::optimize() { std::cout << "continuing with time limit" << std::endl; - m_model->optimizer().set_time_limit(std::min(m_parent.get_remaining_time(), 2 * time_limit)); + m_model->optimizer().set_param_time_limit(std::min(m_parent.get_remaining_time(), 2 * time_limit)); m_model->optimize(); if (compute_reduced_cost(duals) < 0) { @@ -707,8 +707,8 @@ void idol::Optimizers::ColumnGeneration::Subproblem::optimize() { } - m_model->optimizer().set_relative_gap_tolerance(1e-4); - m_model->optimizer().set_time_limit(m_parent.get_remaining_time()); + m_model->optimizer().set_tol_mip_relative_gap(1e-4); + m_model->optimizer().set_param_time_limit(m_parent.get_remaining_time()); m_model->optimize(); } diff --git a/lib/src/optimizers/solvers/Optimizers_GLPK.cpp b/lib/src/optimizers/solvers/Optimizers_GLPK.cpp index 0feec8ed..ef72cb5a 100644 --- a/lib/src/optimizers/solvers/Optimizers_GLPK.cpp +++ b/lib/src/optimizers/solvers/Optimizers_GLPK.cpp @@ -271,7 +271,7 @@ void idol::Optimizers::GLPK::hook_optimize() { save_simplex_solution_status(); - if (infeasible_or_unbounded_info()) { + if (get_param_infeasible_or_unbounded_info()) { if (m_solution_status == Infeasible) { compute_farkas_certificate(); @@ -582,29 +582,29 @@ void idol::Optimizers::GLPK::save_milp_solution_status() { } -void idol::Optimizers::GLPK::set_time_limit(double t_time_limit) { +void idol::Optimizers::GLPK::set_param_time_limit(double t_time_limit) { const int value = (int) std::min(std::numeric_limits::max(), std::ceil(t_time_limit) * 1000); m_simplex_parameters.tm_lim = value; m_mip_parameters.tm_lim = value; - Optimizer::set_time_limit(t_time_limit); + Optimizer::set_param_time_limit(t_time_limit); } -void idol::Optimizers::GLPK::set_best_obj_stop(double t_best_obj_stop) { +void idol::Optimizers::GLPK::set_param_best_obj_stop(double t_best_obj_stop) { m_simplex_parameters.obj_ul = t_best_obj_stop; - Optimizer::set_best_obj_stop(t_best_obj_stop); + Optimizer::set_param_best_obj_stop(t_best_obj_stop); } -void idol::Optimizers::GLPK::set_best_bound_stop(double t_best_bound_stop) { +void idol::Optimizers::GLPK::set_param_best_bound_stop(double t_best_bound_stop) { m_simplex_parameters.obj_ll = t_best_bound_stop; - Optimizer::set_best_bound_stop(t_best_bound_stop); + Optimizer::set_param_best_bound_stop(t_best_bound_stop); } -void idol::Optimizers::GLPK::set_presolve(bool t_value) { +void idol::Optimizers::GLPK::set_param_presolve(bool t_value) { m_simplex_parameters.presolve = t_value ? GLP_MSG_ERR : GLP_MSG_OFF; m_mip_parameters.presolve = t_value ? GLP_MSG_ERR : GLP_MSG_OFF; - Optimizer::set_presolve(t_value); + Optimizer::set_param_presolve(t_value); } idol::SolutionStatus idol::Optimizers::GLPK::get_status() const { diff --git a/lib/src/optimizers/solvers/Optimizers_Mosek.cpp b/lib/src/optimizers/solvers/Optimizers_Mosek.cpp index 8231e72c..7fa18e4d 100644 --- a/lib/src/optimizers/solvers/Optimizers_Mosek.cpp +++ b/lib/src/optimizers/solvers/Optimizers_Mosek.cpp @@ -388,34 +388,34 @@ void idol::Optimizers::Mosek::set_var_ub(MosekVar &t_mosek_var, double t_bound) } -void idol::Optimizers::Mosek::set_time_limit(double t_time_limit) { +void idol::Optimizers::Mosek::set_param_time_limit(double t_time_limit) { m_model->setSolverParam("optimizerMaxTime", t_time_limit); - Optimizer::set_time_limit(t_time_limit); + Optimizer::set_param_time_limit(t_time_limit); } -void idol::Optimizers::Mosek::set_thread_limit(unsigned int t_thread_limit) { +void idol::Optimizers::Mosek::set_param_threads(unsigned int t_thread_limit) { m_model->setSolverParam("numThreads", (int) t_thread_limit); - Optimizer::set_thread_limit(t_thread_limit); + Optimizer::set_param_threads(t_thread_limit); } -void idol::Optimizers::Mosek::set_best_obj_stop(double t_best_obj_stop) { +void idol::Optimizers::Mosek::set_param_best_obj_stop(double t_best_obj_stop) { m_model->setSolverParam("upperObjCut", t_best_obj_stop); - Optimizer::set_best_obj_stop(t_best_obj_stop); + Optimizer::set_param_best_obj_stop(t_best_obj_stop); } -void idol::Optimizers::Mosek::set_best_bound_stop(double t_best_bound_stop) { +void idol::Optimizers::Mosek::set_param_best_bound_stop(double t_best_bound_stop) { m_model->setSolverParam("lowerObjCut", t_best_bound_stop); - Optimizer::set_best_bound_stop(t_best_bound_stop); + Optimizer::set_param_best_bound_stop(t_best_bound_stop); } -void idol::Optimizers::Mosek::set_presolve(bool t_value) { +void idol::Optimizers::Mosek::set_param_presolve(bool t_value) { m_model->setSolverParam("presolveUse", t_value ? "on" : "off"); - Optimizer::set_presolve(t_value); + Optimizer::set_param_presolve(t_value); } -void idol::Optimizers::Mosek::set_infeasible_or_unbounded_info(bool t_value) { +void idol::Optimizers::Mosek::set_param_infeasible_or_unbounded_info(bool t_value) { m_model->acceptedSolutionStatus(t_value ? mosek::fusion::AccSolutionStatus::Anything : mosek::fusion::AccSolutionStatus::Feasible); - Optimizer::set_infeasible_or_unbounded_info(t_value); + Optimizer::set_param_infeasible_or_unbounded_info(t_value); } idol::SolutionStatus idol::Optimizers::Mosek::get_status() const { @@ -495,7 +495,7 @@ void idol::Optimizers::Mosek::set_parameter(const std::string &t_param, const st m_model->setSolverParam(t_param, t_value); } -void idol::Optimizers::Mosek::set_log_level(LogLevel t_log_level) { +void idol::Optimizers::Mosek::set_param_log_level(LogLevel t_log_level) { if (t_log_level == Mute) { @@ -509,7 +509,7 @@ void idol::Optimizers::Mosek::set_log_level(LogLevel t_log_level) { } - Optimizer::set_log_level(t_log_level); + Optimizer::set_param_log_level(t_log_level); } idol::MosekKiller::~MosekKiller() { diff --git a/lib/src/optimizers/solvers/gurobi/Optimizers_Gurobi.cpp b/lib/src/optimizers/solvers/gurobi/Optimizers_Gurobi.cpp index 7fa6a003..1143f3f7 100644 --- a/lib/src/optimizers/solvers/gurobi/Optimizers_Gurobi.cpp +++ b/lib/src/optimizers/solvers/gurobi/Optimizers_Gurobi.cpp @@ -83,6 +83,19 @@ idol::Optimizers::Gurobi::Gurobi(const Model &t_model, bool t_continuous_relaxat m_model.set(GRB_IntParam_OutputFlag, 0); + // Tolerances + m_model.set(GRB_DoubleParam_MIPGap, get_tol_mip_relative_gap()); + m_model.set(GRB_DoubleParam_MIPGapAbs, get_tol_mip_absolute_gap()); + m_model.set(GRB_DoubleParam_IntFeasTol, get_tol_integer()); + m_model.set(GRB_DoubleParam_FeasibilityTol, get_tol_feasibility()); + m_model.set(GRB_DoubleParam_OptimalityTol, get_tol_optimality()); + + // Parameters + m_model.set(GRB_DoubleParam_BestBdStop, get_param_best_bound_stop()); + m_model.set(GRB_DoubleParam_BestObjStop, get_param_best_obj_stop()); + m_model.set(GRB_DoubleParam_TimeLimit, get_param_time_limit()); + m_model.set(GRB_IntParam_Presolve, get_param_presolve()); + m_model.set(GRB_IntParam_Threads, (int) get_param_threads()); } void idol::Optimizers::Gurobi::hook_build() { @@ -301,34 +314,34 @@ void idol::Optimizers::Gurobi::hook_update() { m_model.update(); } -void idol::Optimizers::Gurobi::set_time_limit(double t_time_limit) { +void idol::Optimizers::Gurobi::set_param_time_limit(double t_time_limit) { m_model.set(GRB_DoubleParam_TimeLimit, t_time_limit); - Optimizer::set_time_limit(t_time_limit); + Optimizer::set_param_time_limit(t_time_limit); } -void idol::Optimizers::Gurobi::set_thread_limit(unsigned int t_thread_limit) { +void idol::Optimizers::Gurobi::set_param_threads(unsigned int t_thread_limit) { m_model.set(GRB_IntParam_Threads, t_thread_limit); - Optimizer::set_thread_limit(t_thread_limit); + Optimizer::set_param_threads(t_thread_limit); } -void idol::Optimizers::Gurobi::set_best_obj_stop(double t_best_obj_stop) { +void idol::Optimizers::Gurobi::set_param_best_obj_stop(double t_best_obj_stop) { m_model.set(GRB_DoubleParam_BestObjStop, t_best_obj_stop); - Optimizer::set_best_obj_stop(t_best_obj_stop); + Optimizer::set_param_best_obj_stop(t_best_obj_stop); } -void idol::Optimizers::Gurobi::set_best_bound_stop(double t_best_bound_stop) { +void idol::Optimizers::Gurobi::set_param_best_bound_stop(double t_best_bound_stop) { m_model.set(GRB_DoubleParam_BestBdStop, t_best_bound_stop); - Optimizer::set_best_bound_stop(t_best_bound_stop); + Optimizer::set_param_best_bound_stop(t_best_bound_stop); } -void idol::Optimizers::Gurobi::set_presolve(bool t_value) { +void idol::Optimizers::Gurobi::set_param_presolve(bool t_value) { m_model.set(GRB_IntParam_Presolve, t_value); - Optimizer::set_presolve(t_value); + Optimizer::set_param_presolve(t_value); } -void idol::Optimizers::Gurobi::set_infeasible_or_unbounded_info(bool t_value) { +void idol::Optimizers::Gurobi::set_param_infeasible_or_unbounded_info(bool t_value) { m_model.set(GRB_IntParam_InfUnbdInfo, t_value); - Optimizer::set_infeasible_or_unbounded_info(t_value); + Optimizer::set_param_infeasible_or_unbounded_info(t_value); } void idol::Optimizers::Gurobi::add_callback(Callback *t_ptr_to_callback) { @@ -450,9 +463,9 @@ void idol::Optimizers::Gurobi::set_max_n_solution_in_pool(unsigned int t_value) m_model.set(GRB_IntParam_PoolSolutions, (int) std::min(GRB_MAXINT, t_value)); } -void idol::Optimizers::Gurobi::set_log_level(LogLevel t_log_level) { +void idol::Optimizers::Gurobi::set_param_log_level(LogLevel t_log_level) { m_model.set(GRB_IntParam_OutputFlag, t_log_level != Mute); - Optimizer::set_log_level(t_log_level); + Optimizer::set_param_log_level(t_log_level); } void idol::Optimizers::Gurobi::set_param(GRB_IntParam t_param, int t_value) { @@ -463,14 +476,29 @@ void idol::Optimizers::Gurobi::set_param(GRB_DoubleParam t_param, double t_value m_model.set(t_param, t_value); } -void idol::Optimizers::Gurobi::set_relative_gap_tolerance(double t_relative_gap_tolerance) { - Optimizer::set_relative_gap_tolerance(t_relative_gap_tolerance); +void idol::Optimizers::Gurobi::set_tol_mip_relative_gap(double t_relative_gap_tolerance) { + Optimizer::set_tol_mip_relative_gap(t_relative_gap_tolerance); m_model.set(GRB_DoubleParam_MIPGap, t_relative_gap_tolerance); } -void idol::Optimizers::Gurobi::set_absolute_gap_tolerance(double t_absolute_gap_tolerance) { - Optimizer::set_absolute_gap_tolerance(t_absolute_gap_tolerance); +void idol::Optimizers::Gurobi::set_tol_mip_absolute_gap(double t_absolute_gap_tolerance) { + Optimizer::set_tol_mip_absolute_gap(t_absolute_gap_tolerance); m_model.set(GRB_DoubleParam_MIPGapAbs, t_absolute_gap_tolerance); } +void idol::Optimizers::Gurobi::set_tol_feasibility(double t_tol_feasibility) { + Optimizer::set_tol_feasibility(t_tol_feasibility); + m_model.set(GRB_DoubleParam_FeasibilityTol, t_tol_feasibility); +} + +void idol::Optimizers::Gurobi::set_tol_optimality(double t_tol_optimality) { + Optimizer::set_tol_optimality(t_tol_optimality); + m_model.set(GRB_DoubleParam_OptimalityTol, t_tol_optimality); +} + +void idol::Optimizers::Gurobi::set_tol_integer(double t_tol_integer) { + Optimizer::set_tol_integer(t_tol_integer); + m_model.set(GRB_DoubleParam_IntFeasTol, t_tol_integer); +} + #endif \ No newline at end of file