Belle II Software  release-08-01-10
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 
22 namespace 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 
210  Children* m_children = nullptr;
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  }
309  ++m_nUsedChildren;
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);
337  m_topNode.unlink();
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
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
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
Node * getParent()
Getter of the node one up the hierarchy.
Definition: DynTree.h:194
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
const Node * getParent() const
Const getter of the node one up the hierarchy.
Definition: DynTree.h:200
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
Children * getChildren()
Getter for the children.
Definition: DynTree.h:78
std::vector< Node > Children
Type of the container of the children of the node.
Definition: DynTree.h:61
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
DynTree & operator=(const DynTree &)=delete
Forbid copy assignment.
ASubPropertiesFactory SubPropertiesFactory
Type of the factory for the sub node properties.
Definition: DynTree.h:44
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 & getTopNode()
Getter for the top node of the tree.
Definition: DynTree.h:237
Node m_topNode
Memory for the top node of the tree.
Definition: DynTree.h:361
const Node & getTopNode() const
Constant getter for the top node of the tree.
Definition: DynTree.h:241
DynTree(const DynTree &node)=delete
Forbid copy construction.
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
std::vector< Node > * getUnusedChildren()
Aquire the next unused child node structure, recycling all memory.
Definition: DynTree.h:304
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
void walk(AWalker &walker)
Forward walk to the top node.
Definition: DynTree.h:316
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
std::vector< Node > * createChildren(Node *parentNode)
Create child nodes for the given parents.
Definition: DynTree.h:284
Abstract base class for different kinds of events.