idol
A C++ Framework for Optimization
Loading...
Searching...
No Matches
VariableBranching.h
1//
2// Created by henri on 16.10.23.
3//
4
5#ifndef IDOL_VARIABLEBRANCHING_BRANCHINGRULE_H
6#define IDOL_VARIABLEBRANCHING_BRANCHINGRULE_H
7
8#include <list>
9#include "BranchingRule.h"
10#include "idol/mixed-integer/modeling/variables/Var.h"
11#include "idol/general/utils/Point.h"
12
13namespace idol::BranchingRules {
14 template<class>
15 class VariableBranching;
16}
17
18template<class NodeInfoT>
20 std::list<Var> m_branching_candidates;
21public:
22
23 virtual bool is_valid(const Node<NodeInfoT> &t_node) {
24
25 const auto& primal_solution = t_node.info().primal_solution();
26
27 for (const auto& var : m_branching_candidates) {
28 if (const double value = primal_solution.get(var) ; !is_integer(value, Tolerance::Integer)) {
29 return false;
30 }
31 }
32
33 return true;
34 }
35
36 virtual std::list<std::pair<Var, double>> scoring_function(const std::list<Var>& t_variables, const Node<NodeInfoT> &t_node) = 0;
37
38 virtual std::list<NodeInfoT *> create_child_nodes_for_selected_variable(const Node<NodeInfoT> &t_node, const Var& t_var) {
39
40 const auto& primal_solution = t_node.info().primal_solution();
41 const double value = primal_solution.get(t_var);
42 const double lb = std::ceil(value);
43 const double ub = std::floor(value);
44
45 auto* n1 = t_node.info().create_child();
46 n1->add_branching_variable(t_var, GreaterOrEqual, lb);
47
48 auto* n2 = t_node.info().create_child();
49 n2->add_branching_variable(t_var, LessOrEqual, ub);
50
51 return { n1, n2 };
52 }
53
54 virtual std::list<NodeInfoT *> create_child_nodes(const Node<NodeInfoT> &t_node) {
55
56 const auto& primal_solution = t_node.info().primal_solution();
57
58 auto invalid_variables = get_invalid_variables(primal_solution);
59
60 if (invalid_variables.empty()) {
61 return {};
62 }
63
64 Var selected_variable = invalid_variables.front();
65
66 if (invalid_variables.size() > 1) {
67 auto scores = scoring_function(invalid_variables, t_node);
68 selected_variable = get_argmax_score(scores);
69 }
70
71 return create_child_nodes_for_selected_variable(t_node, selected_variable);
72 }
73
74 [[nodiscard]] const std::list<Var>& branching_candidates() const { return m_branching_candidates; }
75
76 VariableBranching(const Optimizers::BranchAndBound<NodeInfoT>& t_parent, std::list<Var> t_branching_candidates)
77 : BranchingRule<NodeInfoT>(t_parent),
78 m_branching_candidates(std::move(t_branching_candidates)) {
79
80 }
81
82protected:
83 std::list<Var> get_invalid_variables(const PrimalPoint& t_primal_solution) {
84
85 std::list<Var> result;
86
87 for (const auto& var : m_branching_candidates) {
88 if (const double value = t_primal_solution.get(var) ; !is_integer(value, Tolerance::Integer)) {
89 result.emplace_back(var);
90 }
91 }
92
93 return result;
94 }
95
96 Var get_argmax_score(const std::list<std::pair<Var, double>>& t_scores) {
97
98 if (t_scores.empty()) {
99 throw Exception("VariableScoringFunction returned an empty list.");
100 }
101
102 double max = std::numeric_limits<double>::lowest();
103 std::optional<Var> argmax;
104
105 for (const auto& [var, score] : t_scores) {
106 if (max < score) {
107 max = score;
108 argmax = var;
109 }
110 }
111
112 if (!argmax.has_value()) {
113 throw Exception("Could not compute argmax of scores while searching for branching variable.");
114 }
115
116 return argmax.value();
117 }
118
119};
120
121#endif //IDOL_VARIABLEBRANCHING_BRANCHINGRULE_H
static double Integer
Definition numericals.h:73