5#ifndef IDOL_BRANCHANDBOUNDCALLBACK_H
6#define IDOL_BRANCHANDBOUNDCALLBACK_H
8#include "idol/mixed-integer/optimizers/callbacks/Callback.h"
9#include "idol/mixed-integer/optimizers/branch-and-bound/nodes/Node.h"
10#include "idol/mixed-integer/optimizers/branch-and-bound/Optimizers_BranchAndBound.h"
11#include "AbstractBranchAndBoundCallbackI.h"
12#include "CallbackAsBranchAndBoundCallback.h"
16 template<
class NodeInfoT>
17 class BranchAndBoundCallback;
19 template<
class NodeInfoT>
20 class BranchAndBoundCallbackI;
26template<
class NodeInfoT>
30 std::list<std::unique_ptr<BranchAndBoundCallback<NodeInfoT>>> m_callbacks;
33 std::optional<Node<NodeInfoT>> m_node;
34 Model* m_relaxation =
nullptr;
40 void add_user_cut(
const TempCtr &t_cut);
42 void add_lazy_cut(
const TempCtr &t_cut);
44 void add_local_variable_branching(
const idol::Var &t_var, CtrType t_type,
double t_rhs);
48 [[nodiscard]]
const Model& relaxation()
const;
50 [[nodiscard]]
const Model& original_model()
const;
52 [[nodiscard]]
const Timer& time()
const;
56 void submit_heuristic_solution(NodeInfoT* t_info);
58 void submit_bound(
double t_bound);
60 [[nodiscard]]
double best_bound()
const;
62 [[nodiscard]]
double best_obj()
const;
68 CallbackEvent t_event,
70 Model *t_relaxation)
override;
76 void log_after_termination()
override;
79template<
class NodeInfoT>
81 m_node->info().add_branching_variable(t_var, t_type, t_rhs);
82 m_registry->n_added_local_variable_branching++;
85template<
class NodeInfoT>
87 m_parent->terminate();
90template<
class NodeInfoT>
92 return m_parent->get_best_obj();
95template<
class NodeInfoT>
97 return m_parent->get_best_bound();
100template<
class NodeInfoT>
103 if (m_callbacks.empty()) {
107 std::cout <<
"Callbacks:" << std::endl;
109 for (
auto& ptr_to_cb : m_callbacks) {
110 ptr_to_cb->log_after_termination();
113 std::cout << std::endl;
117template<
class NodeInfoT>
120 throw Exception(
"No side effect registry was found");
125template<
class NodeInfoT>
127 return m_parent->time();
130template<
class NodeInfoT>
147 virtual void log_after_termination() {}
161 void add_local_variable_branching(
const Var &t_var, CtrType t_type,
double t_rhs);
204 [[nodiscard]]
const Timer& time()
const;
206 double best_bound()
const;
208 double best_obj()
const;
214 void throw_if_no_interface()
const;
219template<
class NodeInfoT>
221 throw_if_no_interface();
222 m_interface->add_local_variable_branching(t_var, t_type, t_rhs);
225template<
class NodeInfoT>
227 throw_if_no_interface();
228 return m_interface->best_obj();
231template<
class NodeInfoT>
233 throw_if_no_interface();
234 return m_interface->best_bound();
237template<
class NodeInfoT>
239 throw_if_no_interface();
240 m_interface->terminate();
243template<
class NodeInfoT>
245 throw_if_no_interface();
246 return m_interface->side_effect_registry();
249template<
class NodeInfoT>
251 throw_if_no_interface();
252 return m_interface->time();
255template<
class NodeInfoT>
257 throw_if_no_interface();
258 m_interface->submit_bound(t_bound);
261template<
class NodeInfoT>
263 throw_if_no_interface();
264 m_interface->submit_heuristic_solution(t_info);
267template<
class NodeInfoT>
269 throw_if_no_interface();
270 return m_interface->original_model();
273template<
class NodeInfoT>
275 throw_if_no_interface();
276 return m_interface->relaxation();
279template<
class NodeInfoT>
281 throw_if_no_interface();
282 return m_interface->node();
285template<
class NodeInfoT>
287 throw_if_no_interface();
288 m_interface->add_lazy_cut(t_cut);
291template<
class NodeInfoT>
293 throw_if_no_interface();
294 m_interface->add_user_cut(t_cut);
297template<
class NodeInfoT>
300 throw Exception(
"No interface was found.");
304template<
class NodeInfoT>
307 CallbackEvent t_event,
308 const Node<NodeInfoT> &t_current_node,
309 Model *t_relaxation) {
310 SideEffectRegistry result;
313 m_node = t_current_node;
314 m_relaxation = t_relaxation;
315 m_registry = &result;
317 for (
auto &cb: m_callbacks) {
318 cb->m_interface =
this;
319 cb->operator()(t_event);
320 cb->m_interface =
nullptr;
325 m_relaxation =
nullptr;
326 m_registry =
nullptr;
331template<
class NodeInfoT>
333 m_callbacks.emplace_back(t_cb);
336template<
class NodeInfoT>
341 for (
auto& ptr_callback : m_callbacks) {
342 ptr_callback->m_interface =
this;
343 ptr_callback->initialize();
344 ptr_callback->m_interface =
nullptr;
351template<
class NodeInfoT>
354 throw Exception(
"submit_bound is not accessible in this context.");
356 m_parent->submit_lower_bound(t_bound);
359template<
class NodeInfoT>
362 throw Exception(
"submit_heuristic_solution is not accessible in this context.");
364 m_parent->submit_heuristic_solution(t_info);
367template<
class NodeInfoT>
370 throw Exception(
"original_model is not accessible in this context.");
372 return m_parent->parent();
375template<
class NodeInfoT>
378 throw Exception(
"relaxation is not accessible in this context.");
380 return *m_relaxation;
383template<
class NodeInfoT>
386 throw Exception(
"node is not accessible in this context.");
391template<
class NodeInfoT>
393 m_relaxation->add_ctr(t_cut);
394 ++m_registry->n_added_lazy_cuts;
397template<
class NodeInfoT>
399 m_relaxation->add_ctr(t_cut);
400 ++m_registry->n_added_user_cuts;
virtual void operator()(CallbackEvent t_event)=0
void submit_heuristic_solution(NodeInfoT *t_info)
void add_user_cut(const TempCtr &t_cut)
const Model & relaxation() const
const SideEffectRegistry & side_effect_registry() const
const Node< NodeInfoT > & node() const
void add_lazy_cut(const TempCtr &t_cut)
virtual void initialize()
void submit_bound(double t_bound)
const Model & original_model() const