1 #include "tree_builder.hh"
2
3 #include "../cpp-integration/message.hpp"
4
5 #include "utils/perf_helper.hh"
6 #include "utils/debug.hh"
7 #include "execution.hh"
8
9 #include "tree/node_tree.hh"
10 #include "name_map.hh"
11
12 #include <thread>
13
14 namespace cpprofiler
15 {
16
operator <<(std::ostream & os,const NodeUID & uid)17 static std::ostream &operator<<(std::ostream &os, const NodeUID &uid)
18 {
19 return os << "{" << uid.nid << ", " << uid.rid << ", " << uid.tid << "}";
20 }
21
operator <<(std::ostream & os,const NodeStatus & status)22 static std::ostream &operator<<(std::ostream &os, const NodeStatus &status)
23 {
24 switch (status)
25 {
26 case SOLVED:
27 os << "SOLVED";
28 break;
29 case FAILED:
30 os << "FAILED";
31 break;
32 case BRANCH:
33 os << "BRANCH";
34 break;
35 case SKIPPED:
36 os << "SKIPPED";
37 break;
38 }
39 return os;
40 }
41
42 /// works correctly for node messages only atm
operator <<(std::ostream & os,const Message & msg)43 static std::ostream &operator<<(std::ostream &os, const Message &msg)
44 {
45 os << "nid: " << msg.nodeUID() << ", pid: " << msg.parentUID();
46 os << ", alt: " << msg.alt() << ", kids: " << msg.kids();
47 os << ", " << msg.status();
48 // if (msg.has_label()) os << ", label: " << msg.label();
49 // if (msg.has_nogood()) os << ", nogood: " << msg.nogood();
50 // if (msg.has_info()) os << ", info: " << msg.info();
51 return os;
52 }
53
TreeBuilder(Execution & ex)54 TreeBuilder::TreeBuilder(Execution &ex) : m_execution(ex)
55 {
56 std::cerr << " TreeBuilder()\n";
57 startBuilding();
58 }
59
startBuilding()60 void TreeBuilder::startBuilding()
61 {
62 perfHelper.begin("tree building");
63 print("Builder: start building");
64 }
65
finishBuilding()66 void TreeBuilder::finishBuilding()
67 {
68 perfHelper.end();
69 print("Builder: done building");
70 emit buildingDone();
71 }
72
handleNode(Message * node)73 void TreeBuilder::handleNode(Message *node)
74 {
75
76 std::unique_ptr<Message> node_msg{node};
77 // print("node: {}", *node);
78
79 const auto n_uid = node->nodeUID();
80 const auto p_uid = node->parentUID();
81
82 auto &tree = m_execution.tree();
83
84 tree::NodeID pid = tree::NodeID::NoNode;
85
86 if (p_uid.nid != -1)
87 {
88 /// should solver data be moved to node tree?
89 pid = m_execution.solver_data().getNodeId({p_uid.nid, p_uid.rid, p_uid.tid});
90 }
91
92 const auto kids = node->kids();
93 const auto alt = node->alt();
94 const auto status = static_cast<tree::NodeStatus>(node->status());
95 const auto &label = node->has_label() ? node->label() : tree::emptyLabel;
96
97 NodeID nid;
98
99 {
100 utils::MutexLocker tree_lock(&tree.treeMutex(), "builder");
101
102 if (pid == NodeID::NoNode)
103 {
104
105 if (m_execution.doesRestarts())
106 {
107 tree.addExtraChild(NodeID{0});
108 nid = tree.promoteNode(NodeID{0}, restart_count++, kids, status, label);
109 }
110 else
111 {
112 nid = tree.createRoot(kids);
113 }
114 }
115 else
116 {
117 nid = tree.promoteNode(pid, alt, kids, status, label);
118 }
119 }
120
121 m_execution.solver_data().setNodeId({n_uid.nid, n_uid.rid, n_uid.tid}, nid);
122
123 if (node->has_nogood())
124 {
125 const auto nm = m_execution.nameMap();
126
127 if (nm)
128 {
129 /// Construct a renamed nogood using the name map
130 const auto renamed = m_execution.nameMap()->replaceNames(node->nogood());
131 m_execution.solver_data().setNogood(nid, node->nogood(), renamed);
132 }
133 else
134 {
135 m_execution.solver_data().setNogood(nid, node->nogood());
136 }
137 }
138
139 if (node->has_info() && !node->info().empty())
140 {
141 m_execution.solver_data().processInfo(nid, node->info());
142 }
143 }
144
145 } // namespace cpprofiler