Skip to content

Commit

Permalink
set default tolerances and parameters for gurobi
Browse files Browse the repository at this point in the history
  • Loading branch information
hlefebvr committed Aug 17, 2023
1 parent 7e0c849 commit 8ef641f
Show file tree
Hide file tree
Showing 12 changed files with 190 additions and 133 deletions.
93 changes: 57 additions & 36 deletions lib/include/optimizers/Optimizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<double>::max();
unsigned int m_thread_limit = 1;
unsigned int m_iteration_count_limit = std::numeric_limits<unsigned int>::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<unsigned int>::max();

double m_param_time_limit = std::numeric_limits<double>::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:
Expand Down Expand Up @@ -123,70 +132,82 @@ 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; }

[[nodiscard]] double get_remaining_time() const;

[[nodiscard]] bool is_terminated() const { return m_is_terminated; }

void terminate();
virtual void terminate();

template<class T> T& as() {
auto* result = dynamic_cast<T*>(this);
if (!result) {
throw Exception("Bad cast.");
throw Exception("Optimizer could not be cast to desired type.");
}
return *result;
}

template<class T> const T& as() const {
auto* result = dynamic_cast<const T*>(this);
if (!result) {
throw Exception("Bad cast.");
throw Exception("Optimizer could not be cast to desired type.");
}
return *result;
}
Expand Down
30 changes: 15 additions & 15 deletions lib/include/optimizers/OptimizerFactory.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -271,7 +271,7 @@ template<class CRTP>
CRTP &idol::OptimizerFactoryWithDefaultParameters<CRTP>::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;
Expand Down Expand Up @@ -380,47 +380,47 @@ template<class CRTP>
void idol::OptimizerFactoryWithDefaultParameters<CRTP>::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());
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -351,8 +351,8 @@ void idol::Optimizers::BranchAndBound<NodeInfoT>::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;
Expand Down Expand Up @@ -465,8 +465,8 @@ void idol::Optimizers::BranchAndBound<NodeInfoT>::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() << ".");

Expand Down Expand Up @@ -640,7 +640,9 @@ void idol::Optimizers::BranchAndBound<NodeInfoT>::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 {
Expand Down Expand Up @@ -684,8 +686,8 @@ template<class NodeInfoT>
bool idol::Optimizers::BranchAndBound<NodeInfoT>::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<class NodeInfoT>
Expand Down
8 changes: 4 additions & 4 deletions lib/include/optimizers/solvers/Optimizers_GLPK.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,13 +89,13 @@ class idol::Optimizers::GLPK : public OptimizerWithLazyUpdates<int, int> {

[[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;

};

Expand Down
14 changes: 7 additions & 7 deletions lib/include/optimizers/solvers/Optimizers_Mosek.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,25 +94,25 @@ class idol::Optimizers::Mosek : public OptimizerWithLazyUpdates<MosekVar, MosekC

[[nodiscard]] std::string name() const override { return "mosek"; }

void set_time_limit(double t_time_limit) override;
void set_param_time_limit(double t_time_limit) override;

void set_thread_limit(unsigned int t_thread_limit) override;
void set_param_threads(unsigned int t_thread_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;

void set_infeasible_or_unbounded_info(bool t_value) override;
void set_param_infeasible_or_unbounded_info(bool t_value) override;

void set_parameter(const std::string& t_param, double t_value);

void set_parameter(const std::string& t_param, int t_value);

void set_parameter(const std::string& t_param, const std::string& t_value);

void set_log_level(LogLevel t_log_level) override;
void set_param_log_level(LogLevel t_log_level) override;
};

#endif
Expand Down
24 changes: 15 additions & 9 deletions lib/include/optimizers/solvers/gurobi/Optimizers_Gurobi.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,33 +80,39 @@ class idol::Optimizers::Gurobi : public OptimizerWithLazyUpdates<GRBVar, std::va

[[nodiscard]] std::string name() const override { return "gurobi"; }

void set_time_limit(double t_time_limit) override;
void set_param_time_limit(double t_time_limit) override;

void set_thread_limit(unsigned int t_thread_limit) override;
void set_param_threads(unsigned int t_thread_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;

void set_infeasible_or_unbounded_info(bool t_value) override;
void set_param_infeasible_or_unbounded_info(bool t_value) override;

void add_callback(Callback* t_ptr_to_callback);

void set_lazy_cut(bool t_value);

void set_max_n_solution_in_pool(unsigned int t_value);

void set_log_level(LogLevel t_log_level) override;
void set_param_log_level(LogLevel t_log_level) override;

void set_param(GRB_IntParam t_param, int t_value);

void set_param(GRB_DoubleParam t_param, double t_value);

void set_relative_gap_tolerance(double t_relative_gap_tolerance) override;
void set_tol_mip_relative_gap(double t_relative_gap_tolerance) override;

void set_absolute_gap_tolerance(double t_absolute_gap_tolerance) override;
void set_tol_mip_absolute_gap(double t_absolute_gap_tolerance) override;

void set_tol_feasibility(double t_tol_feasibility) override;

void set_tol_optimality(double t_tol_optimality) override;

void set_tol_integer(double t_tol_integer) override;
};

#endif
Expand Down
2 changes: 1 addition & 1 deletion lib/src/modeling/models/Model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ void idol::Model::use(const OptimizerFactory &t_optimizer_factory) {

void idol::Model::unuse() {
m_optimizer.reset();
m_optimizer.reset();
m_optimizer_factory.reset();
}

bool idol::Model::has_optimizer() const {
Expand Down
2 changes: 1 addition & 1 deletion lib/src/optimizers/Optimizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ void idol::impl::Optimizer::optimize() {
}

double idol::impl::Optimizer::get_remaining_time() const {
return std::max(0., m_time_limit - m_timer.count());
return std::max(0., m_param_time_limit - m_timer.count());
}

void idol::impl::Optimizer::terminate() {
Expand Down
Loading

0 comments on commit 8ef641f

Please sign in to comment.