Belle II Software  release-06-02-00
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  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  nNodesByLevel[node->getLevel()]++;
273  }
274  return true;
275  };
276  const_cast<DynTree&>(*this).walk(countNodes);
277  //walk(countNodes);
278  return nNodesByLevel;
279  }
280 
281  private:
283  std::vector<Node>* createChildren(Node* parentNode)
284  {
285  std::vector<Node>* result = getUnusedChildren();
286  auto subProperties = m_subPropertiesFactory(*parentNode);
287  if (subProperties.empty()) {
288  result->clear();
289  } else {
290  // Initialize new elements with dummy property.
291  result->resize(subProperties.size(), Node(subProperties.back()));
292  size_t iSubNode = 0;
293  for (auto& properties : subProperties) {
294  clearIfApplicable(result->at(iSubNode));
295  result->at(iSubNode) = properties;
296  ++iSubNode;
297  }
298  }
299  return result;
300  }
301 
303  std::vector<Node>* getUnusedChildren()
304  {
305  if (m_nUsedChildren >= m_children.size()) {
306  m_children.emplace_back();
307  }
308  ++m_nUsedChildren;
309  return &(m_children[m_nUsedChildren - 1]);
310  }
311 
312  public:
314  template<class AWalker>
315  void walk(AWalker& walker)
316  {
317  static_assert(std::is_assignable<std::function<bool(Node*)>, AWalker>(), "");
318 
319  getTopNode().walk(walker);
320  }
321 
323  template<class AWalker, class APriorityMeasure>
324  void walk(AWalker& walker, APriorityMeasure& priority)
325  {
326  static_assert(std::is_assignable<std::function<bool(Node*)>, AWalker>(), "");
327  static_assert(std::is_assignable<std::function<float(Node*)>, APriorityMeasure>(), "");
328 
329  getTopNode().walk(walker, priority);
330  }
331 
333  void fell()
334  {
335  clearIfApplicable(m_topNode);
336  m_topNode.unlink();
337  m_topNode.m_tree = this;
338  for (typename Node::Children& children : m_children) {
339  for (Node& node : children) {
340  clearIfApplicable(node);
341  node.unlink();
342  }
343  }
344  m_nUsedChildren = 0;
345  }
346 
348  void raze()
349  {
350  this->fell();
351  m_children.clear();
352  m_children.shrink_to_fit();
353  }
354 
355  public:
358 
361 
363  std::deque<typename Node::Children> m_children;
364 
366  size_t m_nUsedChildren = 0;
367  };
368  }
370 }
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:333
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:348
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:360
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:363
void walk(AWalker &walker, APriorityMeasure &priority)
Forward walk to the top node.
Definition: DynTree.h:324
std::vector< Node > * getUnusedChildren()
Aquire the next unused child node structure, recycling all memory.
Definition: DynTree.h:303
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:315
SubPropertiesFactory m_subPropertiesFactory
Instance of the properties factory for the sub nodes.
Definition: DynTree.h:357
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:366
std::vector< Node > * createChildren(Node *parentNode)
Create child nodes for the given parents.
Definition: DynTree.h:283
Abstract base class for different kinds of events.