Belle II Software  release-05-02-19
DynTree.h
1 /**************************************************************************
2 * BASF2 (Belle Analysis Framework 2) *
3 * Copyright(C) 2015 - Belle II Collaboration *
4 * *
5 * Author: The Belle II Collaboration *
6 * Contributors: Viktor Trusov, Thomas Hauth, Oliver Frost *
7 * *
8 * This software is provided "as is" without any warranty. *
9 **************************************************************************/
10 #pragma once
11 
12 #include <tracking/trackFindingCDC/utilities/Algorithms.h>
13 #include <tracking/trackFindingCDC/utilities/Functional.h>
14 #include <framework/logging/Logger.h>
15 #include <vector>
16 #include <deque>
17 #include <map>
18 #include <functional>
19 #include <type_traits>
20 
21 #include <cmath>
22 #include <cassert>
23 
24 namespace Belle2 {
29  namespace TrackFindingCDC {
30 
36  template<class AProperties, class ASubPropertiesFactory>
37  class DynTree {
38 
40  using This = DynTree<AProperties, ASubPropertiesFactory>;
41 
43  using Properties = AProperties;
44 
46  using SubPropertiesFactory = ASubPropertiesFactory;
47 
48  public:
50  class Node : public AProperties {
51 
52  public:
54  using Tree = This;
55 
57  friend Tree;
58 
60  using Properties = AProperties;
61 
63  using Children = std::vector<Node>;
64 
65  private:
70  using AProperties::AProperties;
71 
72  public:
73  using AProperties::operator=;
74 
75  public:
81  { return m_children; }
82 
87  const Children* getChildren() const
88  { return m_children; }
89 
91  void createChildren()
92  {
93  // ensure the level value fits into unsigned char
94  B2ASSERT("DynTree datastructure only supports levels < 255", getLevel() < 255);
95 
96  // Call out to the tree, which is providing the memory for the nodes.
97  Node* parentNode = this;
98  m_children = getTree()->createChildren(parentNode);
99 
100  for (Node& child : *m_children) {
101  child.m_level = getLevel() + 1;
102  child.m_parent = this;
103  child.m_tree = getTree();
104  }
105  }
106 
107  private:
109  void unlink()
110  {
111  m_parent = nullptr;
112  m_level = 0;
113  m_children = nullptr;
114  m_tree = nullptr;
115  }
116 
117  public:
121  template<class AWalker>
122  void walk(AWalker& walker)
123  {
124  static_assert(std::is_assignable<std::function<bool(Node*)>, AWalker>(), "");
125 
126  bool walkChildren = walker(this);
127  Children* children = getChildren();
128  if (children and walkChildren) {
129  for (Node& childNode : *children) {
130  childNode.walk(walker);
131  }
132  }
133  }
134 
140  template<class AWalker, class APriorityMeasure>
141  void walk(AWalker& walker, APriorityMeasure& priority)
142  {
143  static_assert(std::is_assignable<std::function<bool(Node*)>, AWalker>(), "");
144  static_assert(std::is_assignable<std::function<float(Node*)>, APriorityMeasure>(), "");
145 
146  bool walkChildren = walker(this);
147  Children* children = getChildren();
148  if (children and walkChildren) {
149  std::vector<std::pair<float, Node*> > prioritisedChildNodes;
150  size_t nChildren = children->size();
151 
152  prioritisedChildNodes.reserve(nChildren);
153  // Priorities the child nodes with the priority function.
154  for (Node& childNode : *children) {
155  float childPriority = priority(&childNode);
156  if (std::isnan(childPriority)) continue;
157  prioritisedChildNodes.push_back(std::make_pair(childPriority, &childNode));
158  }
159 
160  std::make_heap(prioritisedChildNodes.begin(), prioritisedChildNodes.end());
161 
162  while (not prioritisedChildNodes.empty()) {
163  std::pop_heap(prioritisedChildNodes.begin(), prioritisedChildNodes.end());
164  Node* priorityChildNode = prioritisedChildNodes.back().second;
165  prioritisedChildNodes.pop_back();
166 
167  priorityChildNode->walk(walker, priority);
168 
169  // After the walking the children we reevaluate the priority
170  bool reheap = false;
171  erase_remove_if(prioritisedChildNodes,
172  [&reheap, &priority](std::pair<float, Node*>& prioritisedChildNode) {
173  float childPriority = priority(prioritisedChildNode.second);
174  if (std::isnan(childPriority)) return true;
175  // Check if weights changed and a reordering is due.
176  reheap |= prioritisedChildNode.first != childPriority;
177  prioritisedChildNode.first = childPriority;
178  return false;
179  });
180 
181  if (reheap) {
182  std::make_heap(prioritisedChildNodes.begin(), prioritisedChildNodes.end());
183  }
184  }
185  assert(prioritisedChildNodes.empty());
186  }
187  }
188 
190  int getLevel() const { return m_level; }
191 
196  Node* getParent() { return m_parent; }
197 
202  const Node* getParent() const { return m_parent; }
203 
205  Tree* getTree() const { return m_tree; }
206 
207  private:
209  Tree* m_tree = nullptr;
210 
212  Children* m_children = nullptr;
213 
215  int m_level = 0;
216 
218  Node* m_parent = nullptr;
219  };
220 
221  public:
223  DynTree(const Properties& properties,
224  const SubPropertiesFactory& subPropertiesFactory = SubPropertiesFactory()) :
225  m_subPropertiesFactory(subPropertiesFactory),
226  m_topNode(properties),
227  m_children()
228  {
229  m_topNode.m_tree = this;
230  }
231 
233  DynTree(const DynTree& node) = delete;
234 
236  DynTree& operator=(const DynTree&) = delete;
237 
239  Node& getTopNode()
240  { return m_topNode; }
241 
243  const Node& getTopNode() const
244  { return m_topNode; }
245 
250  int getNNodes() const
251  {
252  int nNodes = 0;
253  auto countNodes = [&nNodes](const Node*) -> bool {
254  ++nNodes;
255  return true;
256  };
257  const_cast<DynTree&>(*this).walk(countNodes);
258  //walk(countNodes);
259  return nNodes;
260  }
261 
266  std::map<int, int> getNNodesByLevel() const
267  {
268  std::map<int, int> nNodesByLevel;
269  auto countNodes = [&nNodesByLevel](const Node * node) -> bool {
270  if (nNodesByLevel.count(node->getLevel()) == 0)
271  {
272  nNodesByLevel[node->getLevel()] = 1;
273  } else {
274  nNodesByLevel[node->getLevel()]++;
275  }
276  return true;
277  };
278  const_cast<DynTree&>(*this).walk(countNodes);
279  //walk(countNodes);
280  return nNodesByLevel;
281  }
282 
283  private:
285  std::vector<Node>* createChildren(Node* parentNode)
286  {
287  std::vector<Node>* result = getUnusedChildren();
288  auto subProperties = m_subPropertiesFactory(*parentNode);
289  if (subProperties.empty()) {
290  result->clear();
291  } else {
292  // Initialize new elements with dummy property.
293  result->resize(subProperties.size(), Node(subProperties.back()));
294  size_t iSubNode = 0;
295  for (auto& properties : subProperties) {
296  clearIfApplicable(result->at(iSubNode));
297  result->at(iSubNode) = properties;
298  ++iSubNode;
299  }
300  }
301  return result;
302  }
303 
305  std::vector<Node>* getUnusedChildren()
306  {
307  if (m_nUsedChildren >= m_children.size()) {
308  m_children.emplace_back();
309  }
310  ++m_nUsedChildren;
311  return &(m_children[m_nUsedChildren - 1]);
312  }
313 
314  public:
316  template<class AWalker>
317  void walk(AWalker& walker)
318  {
319  static_assert(std::is_assignable<std::function<bool(Node*)>, AWalker>(), "");
320 
321  getTopNode().walk(walker);
322  }
323 
325  template<class AWalker, class APriorityMeasure>
326  void walk(AWalker& walker, APriorityMeasure& priority)
327  {
328  static_assert(std::is_assignable<std::function<bool(Node*)>, AWalker>(), "");
329  static_assert(std::is_assignable<std::function<float(Node*)>, APriorityMeasure>(), "");
330 
331  getTopNode().walk(walker, priority);
332  }
333 
335  void fell()
336  {
337  clearIfApplicable(m_topNode);
338  m_topNode.unlink();
339  m_topNode.m_tree = this;
340  for (typename Node::Children& children : m_children) {
341  for (Node& node : children) {
342  clearIfApplicable(node);
343  node.unlink();
344  }
345  }
346  m_nUsedChildren = 0;
347  }
348 
350  void raze()
351  {
352  this->fell();
353  m_children.clear();
354  m_children.shrink_to_fit();
355  }
356 
357  public:
360 
362  Node m_topNode;
363 
365  std::deque<typename Node::Children> m_children;
366 
368  size_t m_nUsedChildren = 0;
369  };
370  }
372 }
Belle2::TrackFindingCDC::DynTree::m_nUsedChildren
size_t m_nUsedChildren
Last index of used children.
Definition: DynTree.h:376
Belle2::TrackFindingCDC::DynTree::Node::Properties
AProperties Properties
Type of the Properties.
Definition: DynTree.h:68
Belle2::TrackFindingCDC::DynTree::getUnusedChildren
std::vector< Node > * getUnusedChildren()
Aquire the next unused child node structure, recycling all memory.
Definition: DynTree.h:313
Belle2::TrackFindingCDC::DynTree::m_subPropertiesFactory
SubPropertiesFactory m_subPropertiesFactory
Instance of the properties factory for the sub nodes.
Definition: DynTree.h:367
Belle2::TrackFindingCDC::DynTree::Node::Tree
This Tree
Type of the tree containing this node.
Definition: DynTree.h:62
Belle2::TrackFindingCDC::DynTree::raze
void raze()
Like fell but also releases all memory the tree has aquired during long execution.
Definition: DynTree.h:358
Belle2::TrackFindingCDC::DynTree::m_topNode
Node m_topNode
Memory for the top node of the tree.
Definition: DynTree.h:370
Belle2::TrackFindingCDC::DynTree::walk
void walk(AWalker &walker)
Forward walk to the top node.
Definition: DynTree.h:325
Belle2::TrackFindingCDC::DynTree::Node::m_level
int m_level
Level of the node within the tree.
Definition: DynTree.h:223
Belle2::TrackFindingCDC::DynTree::createChildren
std::vector< Node > * createChildren(Node *parentNode)
Create child nodes for the given parents.
Definition: DynTree.h:293
Belle2::TrackFindingCDC::DynTree::Node::getLevel
int getLevel() const
Get the level of the node.
Definition: DynTree.h:198
Belle2::TrackFindingCDC::DynTree::fell
void fell()
Fell to tree meaning deleting all child nodes from the tree. Keeps the top node.
Definition: DynTree.h:343
Belle2::TrackFindingCDC::DynTree::Properties
AProperties Properties
Type of the Properties.
Definition: DynTree.h:51
Belle2::TrackFindingCDC::DynTree::Node::getTree
Tree * getTree() const
Getter for the tree containing this node.
Definition: DynTree.h:213
Belle2::TrackFindingCDC::DynTree::Node::m_parent
Node * m_parent
Parent in the tree hierachy of this node.
Definition: DynTree.h:226
Belle2::TrackFindingCDC::DynTree::This
DynTree< AProperties, ASubPropertiesFactory > This
Type of this class.
Definition: DynTree.h:48
Belle2::TrackFindingCDC::DynTree::operator=
DynTree & operator=(const DynTree &)=delete
Forbid copy assignment.
Belle2::TrackFindingCDC::DynTree::getTopNode
Node & getTopNode()
Getter for the top node of the tree.
Definition: DynTree.h:247
Belle2
Abstract base class for different kinds of events.
Definition: MillepedeAlgorithm.h:19
Belle2::TrackFindingCDC::DynTree::getNNodesByLevel
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:274
Belle2::TrackFindingCDC::DynTree
This is the base class for all hough trees.
Definition: DynTree.h:45
Belle2::TrackFindingCDC::DynTree::m_children
std::deque< typename Node::Children > m_children
Central point to provide memory for the child structures.
Definition: DynTree.h:373
Belle2::TrackFindingCDC::DynTree::DynTree
DynTree(const Properties &properties, const SubPropertiesFactory &subPropertiesFactory=SubPropertiesFactory())
Constructor taking properties with which the top node of the tree is initialised.
Definition: DynTree.h:231
Belle2::TrackFindingCDC::DynTree::Node::unlink
void unlink()
Remove to node from the tree hierachy.
Definition: DynTree.h:117
Belle2::TrackFindingCDC::DynTree::Node::getChildren
Children * getChildren()
Getter for the children.
Definition: DynTree.h:88
Belle2::TrackFindingCDC::DynTree::Node::createChildren
void createChildren()
Creates the children of the node.
Definition: DynTree.h:99
Belle2::TrackFindingCDC::DynTree::getNNodes
int getNNodes() const
Gets the number of nodes currently contained in the tree Also demonstrates how to walk over the tree.
Definition: DynTree.h:258
Belle2::TrackFindingCDC::DynTree::Node::walk
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:130
Belle2::TrackFindingCDC::DynTree::Node::Children
std::vector< Node > Children
Type of the container of the children of the node.
Definition: DynTree.h:71
Belle2::TrackFindingCDC::DynTree::Node
Class for a node in the tree.
Definition: DynTree.h:58
Belle2::TrackFindingCDC::DynTree::Node::m_children
Children * m_children
Children that are created only if needed.
Definition: DynTree.h:220
Belle2::TrackFindingCDC::DynTree::SubPropertiesFactory
ASubPropertiesFactory SubPropertiesFactory
Type of the factory for the sub node properties.
Definition: DynTree.h:54
Belle2::TrackFindingCDC::DynTree::Node::getParent
Node * getParent()
Getter of the node one up the hierarchy.
Definition: DynTree.h:204
Belle2::TrackFindingCDC::DynTree::Node::m_tree
Tree * m_tree
Reference to the tree that contains this node.
Definition: DynTree.h:217