Belle II Software development
DynTree.h
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8#pragma once
9
10#include <tracking/trackFindingCDC/utilities/Algorithms.h>
11#include <tracking/trackFindingCDC/utilities/Functional.h>
12#include <framework/logging/Logger.h>
13#include <vector>
14#include <deque>
15#include <map>
16#include <functional>
17#include <type_traits>
18
19#include <cmath>
20#include <cassert>
21
22namespace Belle2 {
27 namespace TrackFindingCDC {
28
34 template<class AProperties, class ASubPropertiesFactory>
35 class DynTree {
36
39
41 using Properties = AProperties;
42
44 using SubPropertiesFactory = ASubPropertiesFactory;
45
46 public:
48 class Node : public AProperties {
49
50 public:
52 using Tree = This;
53
55 friend Tree;
56
58 using Properties = AProperties;
59
61 using Children = std::vector<Node>;
62
63 private:
68 using AProperties::AProperties;
69
70 public:
71 using AProperties::operator=;
72
73 public:
79 { return m_children; }
80
85 const Children* getChildren() const
86 { return m_children; }
87
90 {
91 // ensure the level value fits into unsigned char
92 B2ASSERT("DynTree datastructure only supports levels < 255", getLevel() < 255);
93
94 // Call out to the tree, which is providing the memory for the nodes.
95 Node* parentNode = this;
96 m_children = getTree()->createChildren(parentNode);
97
98 for (Node& child : *m_children) {
99 child.m_level = getLevel() + 1;
100 child.m_parent = this;
101 child.m_tree = getTree();
102 }
103 }
104
105 private:
107 void unlink()
108 {
109 m_parent = nullptr;
110 m_level = 0;
111 m_children = nullptr;
112 m_tree = nullptr;
113 }
114
115 public:
119 template<class AWalker>
120 void walk(AWalker& walker)
121 {
122 static_assert(std::is_assignable<std::function<bool(Node*)>, AWalker>(), "");
123
124 bool walkChildren = walker(this);
125 Children* children = getChildren();
126 if (children and walkChildren) {
127 for (Node& childNode : *children) {
128 childNode.walk(walker);
129 }
130 }
131 }
132
138 template<class AWalker, class APriorityMeasure>
139 void walk(AWalker& walker, APriorityMeasure& priority)
140 {
141 static_assert(std::is_assignable<std::function<bool(Node*)>, AWalker>(), "");
142 static_assert(std::is_assignable<std::function<float(Node*)>, APriorityMeasure>(), "");
143
144 bool walkChildren = walker(this);
145 Children* children = getChildren();
146 if (children and walkChildren) {
147 std::vector<std::pair<float, Node*> > prioritisedChildNodes;
148 size_t nChildren = children->size();
149
150 prioritisedChildNodes.reserve(nChildren);
151 // Priorities the child nodes with the priority function.
152 for (Node& childNode : *children) {
153 float childPriority = priority(&childNode);
154 if (std::isnan(childPriority)) continue;
155 prioritisedChildNodes.push_back(std::make_pair(childPriority, &childNode));
156 }
157
158 std::make_heap(prioritisedChildNodes.begin(), prioritisedChildNodes.end());
159
160 while (not prioritisedChildNodes.empty()) {
161 std::pop_heap(prioritisedChildNodes.begin(), prioritisedChildNodes.end());
162 Node* priorityChildNode = prioritisedChildNodes.back().second;
163 prioritisedChildNodes.pop_back();
164
165 priorityChildNode->walk(walker, priority);
166
167 // After the walking the children we reevaluate the priority
168 bool reheap = false;
169 erase_remove_if(prioritisedChildNodes,
170 [&reheap, &priority](std::pair<float, Node*>& prioritisedChildNode) {
171 float childPriority = priority(prioritisedChildNode.second);
172 if (std::isnan(childPriority)) return true;
173 // Check if weights changed and a reordering is due.
174 reheap |= prioritisedChildNode.first != childPriority;
175 prioritisedChildNode.first = childPriority;
176 return false;
177 });
178
179 if (reheap) {
180 std::make_heap(prioritisedChildNodes.begin(), prioritisedChildNodes.end());
181 }
182 }
183 assert(prioritisedChildNodes.empty());
184 }
185 }
186
188 int getLevel() const { return m_level; }
189
194 Node* getParent() { return m_parent; }
195
200 const Node* getParent() const { return m_parent; }
201
203 Tree* getTree() const { return m_tree; }
204
205 private:
207 Tree* m_tree = nullptr;
208
211
213 int m_level = 0;
214
216 Node* m_parent = nullptr;
217 };
218
219 public:
221 explicit DynTree(const Properties& properties,
222 const SubPropertiesFactory& subPropertiesFactory = SubPropertiesFactory()) :
223 m_subPropertiesFactory(subPropertiesFactory),
224 m_topNode(properties),
225 m_children()
226 {
227 m_topNode.m_tree = this;
228 }
229
231 DynTree(const DynTree& node) = delete;
232
234 DynTree& operator=(const DynTree&) = delete;
235
238 { return m_topNode; }
239
241 const Node& getTopNode() const
242 { return m_topNode; }
243
248 int getNNodes() const
249 {
250 int nNodes = 0;
251 auto countNodes = [&nNodes](const Node*) -> bool {
252 ++nNodes;
253 return true;
254 };
255 const_cast<DynTree&>(*this).walk(countNodes);
256 //walk(countNodes);
257 return nNodes;
258 }
259
264 std::map<int, int> getNNodesByLevel() const
265 {
266 std::map<int, int> nNodesByLevel;
267 auto countNodes = [&nNodesByLevel](const Node * node) -> bool {
268 if (nNodesByLevel.count(node->getLevel()) == 0)
269 {
270 nNodesByLevel[node->getLevel()] = 1;
271 } else
272 {
273 nNodesByLevel[node->getLevel()]++;
274 }
275 return true;
276 };
277 const_cast<DynTree&>(*this).walk(countNodes);
278 //walk(countNodes);
279 return nNodesByLevel;
280 }
281
282 private:
284 std::vector<Node>* createChildren(Node* parentNode)
285 {
286 std::vector<Node>* result = getUnusedChildren();
287 auto subProperties = m_subPropertiesFactory(*parentNode);
288 if (subProperties.empty()) {
289 result->clear();
290 } else {
291 // Initialize new elements with dummy property.
292 result->resize(subProperties.size(), Node(subProperties.back()));
293 size_t iSubNode = 0;
294 for (auto& properties : subProperties) {
295 clearIfApplicable(result->at(iSubNode));
296 result->at(iSubNode) = properties;
297 ++iSubNode;
298 }
299 }
300 return result;
301 }
302
304 std::vector<Node>* getUnusedChildren()
305 {
306 if (m_nUsedChildren >= m_children.size()) {
307 m_children.emplace_back();
308 }
310 return &(m_children[m_nUsedChildren - 1]);
311 }
312
313 public:
315 template<class AWalker>
316 void walk(AWalker& walker)
317 {
318 static_assert(std::is_assignable<std::function<bool(Node*)>, AWalker>(), "");
319
320 getTopNode().walk(walker);
321 }
322
324 template<class AWalker, class APriorityMeasure>
325 void walk(AWalker& walker, APriorityMeasure& priority)
326 {
327 static_assert(std::is_assignable<std::function<bool(Node*)>, AWalker>(), "");
328 static_assert(std::is_assignable<std::function<float(Node*)>, APriorityMeasure>(), "");
329
330 getTopNode().walk(walker, priority);
331 }
332
334 void fell()
335 {
336 clearIfApplicable(m_topNode);
338 m_topNode.m_tree = this;
339 for (typename Node::Children& children : m_children) {
340 for (Node& node : children) {
341 clearIfApplicable(node);
342 node.unlink();
343 }
344 }
345 m_nUsedChildren = 0;
346 }
347
349 void raze()
350 {
351 this->fell();
352 m_children.clear();
353 m_children.shrink_to_fit();
354 }
355
356 public:
359
362
364 std::deque<typename Node::Children> m_children;
365
367 size_t m_nUsedChildren = 0;
368 };
369 }
371}
Class for a node in the tree.
Definition: DynTree.h:48
Children * m_children
Children that are created only if needed.
Definition: DynTree.h:210
const Node * getParent() const
Const getter of the node one up the hierarchy.
Definition: DynTree.h:200
friend Tree
Allow the tree access to the node constructor to create the top node.
Definition: DynTree.h:55
Tree * m_tree
Reference to the tree that contains this node.
Definition: DynTree.h:207
int m_level
Level of the node within the tree.
Definition: DynTree.h:213
void walk(AWalker &walker, APriorityMeasure &priority)
Calls the walker with each node starting with the top node and continues depth first The walker can s...
Definition: DynTree.h:139
void createChildren()
Creates the children of the node.
Definition: DynTree.h:89
int getLevel() const
Get the level of the node.
Definition: DynTree.h:188
void walk(AWalker &walker)
Calls the walker with each node starting with the top node and continues depth first The walker can s...
Definition: DynTree.h:120
Children * getChildren()
Getter for the children.
Definition: DynTree.h:78
AProperties Properties
Type of the Properties.
Definition: DynTree.h:58
Node * m_parent
Parent in the tree hierachy of this node.
Definition: DynTree.h:216
void unlink()
Remove to node from the tree hierachy.
Definition: DynTree.h:107
Tree * getTree() const
Getter for the tree containing this node.
Definition: DynTree.h:203
const Children * getChildren() const
Const getter for the children.
Definition: DynTree.h:85
std::vector< Node > Children
Type of the container of the children of the node.
Definition: DynTree.h:61
Node * getParent()
Getter of the node one up the hierarchy.
Definition: DynTree.h:194
This is the base class for all hough trees.
Definition: DynTree.h:35
void fell()
Fell to tree meaning deleting all child nodes from the tree. Keeps the top node.
Definition: DynTree.h:334
ASubPropertiesFactory SubPropertiesFactory
Type of the factory for the sub node properties.
Definition: DynTree.h:44
std::vector< Node > * getUnusedChildren()
Aquire the next unused child node structure, recycling all memory.
Definition: DynTree.h:304
void raze()
Like fell but also releases all memory the tree has aquired during long execution.
Definition: DynTree.h:349
DynTree(const Properties &properties, const SubPropertiesFactory &subPropertiesFactory=SubPropertiesFactory())
Constructor taking properties with which the top node of the tree is initialised.
Definition: DynTree.h:221
Node m_topNode
Memory for the top node of the tree.
Definition: DynTree.h:361
DynTree & operator=(const DynTree &)=delete
Forbid copy assignment.
DynTree(const DynTree &node)=delete
Forbid copy construction.
Node & getTopNode()
Getter for the top node of the tree.
Definition: DynTree.h:237
std::deque< typename Node::Children > m_children
Central point to provide memory for the child structures.
Definition: DynTree.h:364
void walk(AWalker &walker, APriorityMeasure &priority)
Forward walk to the top node.
Definition: DynTree.h:325
void walk(AWalker &walker)
Forward walk to the top node.
Definition: DynTree.h:316
std::vector< Node > * createChildren(Node *parentNode)
Create child nodes for the given parents.
Definition: DynTree.h:284
const Node & getTopNode() const
Constant getter for the top node of the tree.
Definition: DynTree.h:241
std::map< int, int > getNNodesByLevel() const
Gets the number of nodes by level in the tree Also demonstrates how to walk over the tree.
Definition: DynTree.h:264
SubPropertiesFactory m_subPropertiesFactory
Instance of the properties factory for the sub nodes.
Definition: DynTree.h:358
AProperties Properties
Type of the Properties.
Definition: DynTree.h:41
int getNNodes() const
Gets the number of nodes currently contained in the tree Also demonstrates how to walk over the tree.
Definition: DynTree.h:248
DynTree< AProperties, ASubPropertiesFactory > This
Type of this class.
Definition: DynTree.h:38
size_t m_nUsedChildren
Last index of used children.
Definition: DynTree.h:367
Abstract base class for different kinds of events.