idol
A C++ Framework for Optimization
Loading...
Searching...
No Matches
ExportBranchAndBoundTreeToCSV.h
1//
2// Created by henri on 27.10.23.
3//
4
5#ifndef IDOL_EXPORTBRANCHANDBOUNDTREETOCSV_H
6#define IDOL_EXPORTBRANCHANDBOUNDTREETOCSV_H
7
8
9#include "idol/mixed-integer/optimizers/branch-and-bound/nodes/DefaultNodeInfo.h"
10#include "idol/mixed-integer/optimizers/branch-and-bound/callbacks/BranchAndBoundCallbackFactory.h"
11#include "idol/mixed-integer/optimizers/branch-and-bound/callbacks/BranchAndBoundCallback.h"
12#include <fstream>
13
14namespace idol::Utils {
15 template<class NodeInfoT>
16 class ExportBranchAndBoundTreeToCSV;
17}
18
19template<class NodeInfoT = idol::DefaultNodeInfo>
21 const std::string m_filename;
22public:
23 explicit ExportBranchAndBoundTreeToCSV(std::string t_filename);
24
25 BranchAndBoundCallback<NodeInfoT> *operator()() override;
26
27 BranchAndBoundCallbackFactory<NodeInfoT> *clone() const override;
28
29 class Strategy : public BranchAndBoundCallback<NodeInfoT> {
30 const std::string m_filename;
31 protected:
32 void operator()(CallbackEvent t_event) override;
33 public:
34 explicit Strategy(std::string t_filename);
35 };
36};
37
38template<class NodeInfoT>
39idol::Utils::ExportBranchAndBoundTreeToCSV<NodeInfoT>::ExportBranchAndBoundTreeToCSV(std::string t_filename) : m_filename(std::move(t_filename)) {
40
41}
42
43template<class NodeInfoT>
46 return new ExportBranchAndBoundTreeToCSV(*this);
47}
48
49template<class NodeInfoT>
52 return new Strategy(m_filename);
53}
54
55template<class NodeInfoT>
56idol::Utils::ExportBranchAndBoundTreeToCSV<NodeInfoT>::Strategy::Strategy(std::string t_filename) : m_filename(std::move(t_filename)) {
57
58 std::ofstream file(m_filename);
59
60 if (!file.is_open()) {
61 throw Exception("Could not open destination file.");
62 }
63
64 file.close();
65
66}
67
68template<class NodeInfoT>
70
71 if (t_event != InvalidSolution && t_event != IncumbentSolution && t_event != PrunedSolution) {
72 return;
73 }
74
75 const auto& side_effect_registry = this->side_effect_registry();
76
77 if (side_effect_registry.n_added_lazy_cuts > 0 || side_effect_registry.n_added_user_cuts > 0) {
78 return;
79 }
80
81 std::ofstream file(m_filename, std::ios::app);
82
83 if (!file.is_open()) {
84 throw Exception("Could not open destination file.");
85 }
86
87 const auto& node = this->node();
88
89 const unsigned int id = node.id();
90 const auto status = node.info().status();
91 unsigned int parent_id;
92 std::stringstream branch_label;
93 double sum_of_infeasibilities = Inf;
94
95 if (id == 0) {
96 parent_id = 0;
97 } else {
98 parent_id = node.parent().id();
99
100 for (const auto& branching_decision : node.info().variable_branching_decisions()) {
101 branch_label << branching_decision.variable.name() << " ";
102 if (branching_decision.type == LessOrEqual) {
103 branch_label << "&le;";
104 } else {
105 branch_label << "&ge;";
106 }
107 branch_label << " " << branching_decision.bound;
108 }
109
110 for (const auto& branching_decisions : node.info().constraint_branching_decisions()) {
111 branch_label << branching_decisions.temporary_constraint;
112 }
113 }
114
115 if (status == Optimal || status == Feasible) {
116 sum_of_infeasibilities = node.info().sum_of_infeasibilities();
117 }
118
119 file << this->time().count() << ","
120 << id << ","
121 << parent_id << ","
122 << node.level() << ","
123 << status << ","
124 << node.info().objective_value() << ","
125 << branch_label.str() << ","
126 << t_event << ","
127 << sum_of_infeasibilities
128 << std::endl;
129
130 file.close();
131
132}
133
134#endif //IDOL_EXPORTBRANCHANDBOUNDTREETOCSV_H