5#ifndef IDOL_BRANCHANDBOUND_H
6#define IDOL_BRANCHANDBOUND_H
9#include "idol/general/optimizers/OptimizerFactory.h"
10#include "Optimizers_BranchAndBound.h"
11#include "idol/mixed-integer/optimizers/branch-and-bound/callbacks/BranchAndBoundCallbackFactory.h"
12#include "idol/mixed-integer/optimizers/branch-and-bound/callbacks/BranchAndBoundCallback.h"
13#include "idol/mixed-integer/optimizers/branch-and-bound/callbacks/CallbackAsBranchAndBoundCallback.h"
14#include "idol/mixed-integer/optimizers/callbacks/CallbackFactory.h"
15#include "idol/mixed-integer/optimizers/branch-and-bound/nodes/DefaultNodeInfo.h"
16#include "idol/mixed-integer/optimizers/branch-and-bound/logs/Factory.h"
17#include "idol/mixed-integer/optimizers/branch-and-bound/logs/Info.h"
28template<
class NodeT =
idol::DefaultNodeInfo>
30 std::unique_ptr<OptimizerFactory> m_relaxation_optimizer_factory;
31 std::unique_ptr<BranchingRuleFactory<NodeT>> m_branching_rule_factory;
32 std::unique_ptr<NodeSelectionRuleFactory<NodeT>> m_node_selection_rule_factory;
33 std::unique_ptr<Logs::BranchAndBound::Factory<NodeT>> m_logger_factory;
35 std::list<std::unique_ptr<BranchAndBoundCallbackFactory<NodeT>>> m_callbacks;
37 std::optional<unsigned int> m_subtree_depth;
38 std::optional<unsigned int> m_log_frequency;
46 template<
class ReturnT,
class T>
using only_if_has_Strategy =
typename std::pair<typename T::template Strategy<NodeT>, ReturnT>::second_type;
111 template<
class BranchingRuleFactoryT>
142 template<
class NodeSelectionRuleFactoryT>
211 m_relaxation_optimizer_factory.reset(t_node_optimizer.clone());
218 if (m_logger_factory) {
219 throw Exception(
"Logs have already been configured.");
222 m_logger_factory.reset(t_log_factory.clone());
241 m_callbacks.emplace_back(t_callback.clone());
249 if (m_subtree_depth.has_value()) {
250 throw Exception(
"A subtree depth has already been given");
253 m_subtree_depth = t_depth;
259template<
class NodeSelectionRuleFactoryT>
262 return with_node_selection_rule(
typename NodeSelectionRuleFactoryT::template Strategy<NodeT>(t_node_selection_rule));
269 if (m_node_selection_rule_factory) {
270 throw Exception(
"A node selection rule has already been set.");
273 m_node_selection_rule_factory.reset(t_node_selection.clone());
279template<
class BranchingRuleFactoryT>
282 return with_branching_rule(
typename BranchingRuleFactoryT::template Strategy<NodeT>(t_branching_rule));
288 if (m_branching_rule_factory) {
289 throw Exception(
"A branching rule has already been set.");
292 m_branching_rule_factory.reset(t_branching_rule.clone());
300 if (m_relaxation_optimizer_factory) {
301 throw Exception(
"A node solver has already been set.");
304 m_relaxation_optimizer_factory.reset(t_node_optimizer.
clone());
313 m_relaxation_optimizer_factory(t_rhs.m_relaxation_optimizer_factory ? t_rhs.m_relaxation_optimizer_factory->
clone() : nullptr),
314 m_branching_rule_factory(t_rhs.m_branching_rule_factory ? t_rhs.m_branching_rule_factory->
clone() : nullptr),
315 m_node_selection_rule_factory(t_rhs.m_node_selection_rule_factory ? t_rhs.m_node_selection_rule_factory->
clone() : nullptr),
316 m_subtree_depth(t_rhs.m_subtree_depth),
317 m_logger_factory(t_rhs.m_logger_factory ? t_rhs.m_logger_factory->
clone() : nullptr) {
319 for (
auto& cb : t_rhs.m_callbacks) {
320 m_callbacks.emplace_back(cb->clone());
328 if (!m_relaxation_optimizer_factory) {
329 throw Exception(
"No node solver has been given, please call BranchAndBound::with_node_optimizer to configure.");
332 if (!m_branching_rule_factory) {
333 throw Exception(
"No branching rule has been given, please call BranchAndBound::with_branching_rule to configure.");
336 if (!m_node_selection_rule_factory) {
337 throw Exception(
"No node selection rule has been given, please call BranchAndBound::with_node_selection_rule to configure.");
340 std::unique_ptr<Logs::BranchAndBound::Factory<NodeT>> default_logger_factory;
341 if (!m_logger_factory) {
342 default_logger_factory = std::make_unique<Logs::BranchAndBound::Info<NodeT>>();
346 *m_relaxation_optimizer_factory,
347 *m_branching_rule_factory,
348 *m_node_selection_rule_factory,
350 m_logger_factory ? *m_logger_factory : *default_logger_factory);
352 this->handle_default_parameters(result);
354 if (m_subtree_depth.has_value()) {
355 result->set_subtree_depth(m_subtree_depth.value());
358 for (
auto& cb : m_callbacks) {
359 result->add_callback(cb->operator()());
371 template<
class NodeInfoT>
374 result += t_node_optimizer;
only_if_has_Strategy< BranchAndBound< NodeT > &, BranchingRuleFactoryT > with_branching_rule(const BranchingRuleFactoryT &t_branching_rule)
BranchAndBound< NodeT > & with_branching_rule(const BranchingRuleFactory< NodeT > &t_branching_rule)
BranchAndBound< NodeT > & with_node_selection_rule(const NodeSelectionRuleFactory< NodeT > &t_node_selection)
BranchAndBound< NodeT > & with_node_optimizer(const OptimizerFactory &t_node_optimizer)
BranchAndBound< NodeT > & add_callback(const BranchAndBoundCallbackFactory< NodeT > &t_callback)
OptimizerFactory * clone() const override
typename std::pair< typename T::template Strategy< NodeT >, ReturnT >::second_type only_if_has_Strategy
BranchAndBound< NodeT > & with_subtree_depth(unsigned int t_depth)
only_if_has_Strategy< BranchAndBound< NodeT > &, NodeSelectionRuleFactoryT > with_node_selection_rule(const NodeSelectionRuleFactoryT &t_node_selection_rule)
Optimizer * operator()(const Model &t_model) const override
virtual OptimizerFactory * clone() const =0