20 std::list<Var> m_branching_candidates;
25 const auto& primal_solution = t_node.info().primal_solution();
27 for (
const auto& var : m_branching_candidates) {
28 if (
const double value = primal_solution.get(var) ; !is_integer(value,
Tolerance::Integer)) {
36 virtual std::list<std::pair<Var, double>> scoring_function(
const std::list<Var>& t_variables,
const Node<NodeInfoT> &t_node) = 0;
38 virtual std::list<NodeInfoT *> create_child_nodes_for_selected_variable(
const Node<NodeInfoT> &t_node,
const Var& t_var) {
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);
45 auto* n1 = t_node.info().create_child();
46 n1->add_branching_variable(t_var, GreaterOrEqual, lb);
48 auto* n2 = t_node.info().create_child();
49 n2->add_branching_variable(t_var, LessOrEqual, ub);
54 virtual std::list<NodeInfoT *> create_child_nodes(
const Node<NodeInfoT> &t_node) {
56 const auto& primal_solution = t_node.info().primal_solution();
58 auto invalid_variables = get_invalid_variables(primal_solution);
60 if (invalid_variables.empty()) {
64 Var selected_variable = invalid_variables.front();
66 if (invalid_variables.size() > 1) {
67 auto scores = scoring_function(invalid_variables, t_node);
68 selected_variable = get_argmax_score(scores);
71 return create_child_nodes_for_selected_variable(t_node, selected_variable);
74 [[nodiscard]]
const std::list<Var>& branching_candidates()
const {
return m_branching_candidates; }
78 m_branching_candidates(std::move(t_branching_candidates)) {
83 std::list<Var> get_invalid_variables(
const PrimalPoint& t_primal_solution) {
85 std::list<Var> result;
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);
96 Var get_argmax_score(
const std::list<std::pair<Var, double>>& t_scores) {
98 if (t_scores.empty()) {
99 throw Exception(
"VariableScoringFunction returned an empty list.");
102 double max = std::numeric_limits<double>::lowest();
103 std::optional<Var> argmax;
105 for (
const auto& [var, score] : t_scores) {
112 if (!argmax.has_value()) {
113 throw Exception(
"Could not compute argmax of scores while searching for branching variable.");
116 return argmax.value();