Tenncor
traveler.hpp
Go to the documentation of this file.
1 
9 #include "estd/estd.hpp"
10 #include "estd/range.hpp"
11 
12 #include "teq/ileaf.hpp"
13 #include "teq/ifunctor.hpp"
14 
15 #ifndef TEQ_TRAVELER_HPP
16 #define TEQ_TRAVELER_HPP
17 
18 namespace teq
19 {
20 
22 struct OnceTraveler : public iTraveler
23 {
24  virtual ~OnceTraveler (void) = default;
25 
27  void visit (iLeaf* leaf) override
28  {
29  if (false == estd::has(visited_, leaf))
30  {
31  visited_.emplace(leaf);
32  visit_leaf(leaf);
33  }
34  }
35 
37  void visit (iFunctor* func) override
38  {
39  if (false == estd::has(visited_, func))
40  {
41  visited_.emplace(func);
42  visit_func(func);
43  }
44  }
45 
47  virtual void visit_leaf (iLeaf* leaf) = 0;
48 
50  virtual void visit_func (iFunctor* func) = 0;
51 
53  std::unordered_set<iTensor*> visited_;
54 };
55 
57 struct GraphStat final : public iTraveler
58 {
60  void visit (iLeaf* leaf) override
61  {
62  graphsize_.emplace(leaf, estd::NumRange<size_t>());
63  }
64 
66  void visit (iFunctor* func) override
67  {
68  if (false == estd::has(graphsize_, func))
69  {
70  ArgsT children = func->get_children();
71  size_t nchildren = children.size();
72  std::vector<size_t> max_heights;
73  std::vector<size_t> min_heights;
74  max_heights.reserve(nchildren);
75  min_heights.reserve(nchildren);
76  for (auto& child : children)
77  {
78  iTensor* tens = child.get_tensor().get();
79  tens->accept(*this);
80  estd::NumRange<size_t> range = estd::must_getf(graphsize_, tens,
81  "GraphStat failed to visit child `%s` of functor `%s`",
82  tens->to_string().c_str(), func->to_string().c_str());
83  max_heights.push_back(range.upper_);
84  min_heights.push_back(range.lower_);
85  }
86  size_t max_height = 1;
87  size_t min_height = 1;
88  auto max_it = std::max_element(
89  max_heights.begin(), max_heights.end());
90  auto min_it = std::min_element(
91  min_heights.begin(), min_heights.end());
92  if (max_heights.end() != max_it)
93  {
94  max_height += *max_it;
95  }
96  if (min_heights.end() != max_it)
97  {
98  min_height += *min_it;
99  }
100  graphsize_.emplace(func, estd::NumRange<size_t>(min_height, max_height));
101  }
102  }
103 
104  // Maximum depth of the subtree of mapped tensors
105  std::unordered_map<iTensor*,estd::NumRange<size_t>> graphsize_;
106 };
107 
109 using ParentMapT = std::unordered_map<iTensor*,std::vector<size_t>>;
110 
116 struct PathFinder final : public iTraveler
117 {
118  PathFinder (const iTensor* target) : target_(target) {}
119 
121  void visit (iLeaf* leaf) override {}
122 
124  void visit (iFunctor* func) override
125  {
126  if (false == estd::has(parents_, func))
127  {
128  auto& children = func->get_children();
129  size_t n = children.size();
130  std::unordered_set<size_t> path;
131  for (size_t i = 0; i < n; ++i)
132  {
133  TensptrT tens = children[i].get_tensor();
134  if (tens.get() == target_)
135  {
136  path.emplace(i);
137  }
138  else
139  {
140  tens->accept(*this);
141  if (estd::has(parents_, tens.get()))
142  {
143  path.emplace(i);
144  }
145  }
146  }
147  if (false == path.empty())
148  {
149  parents_[func] = std::vector<size_t>(path.begin(), path.end());
150  }
151  }
152  }
153 
155  const iTensor* target_;
156 
159 };
160 
162 struct ParentFinder final : public iTraveler
163 {
165  void visit (iLeaf* leaf) override
166  {
167  parents_.emplace(leaf, ParentMapT());
168  }
169 
171  void visit (iFunctor* func) override
172  {
173  if (false == estd::has(parents_, func))
174  {
175  auto& children = func->get_children();
176  for (size_t i = 0, n = children.size(); i < n; ++i)
177  {
178  auto& child = children[i];
179  auto tens = child.get_tensor();
180  tens->accept(*this);
181  parents_[tens.get()][func].push_back(i);
182  }
183  parents_.emplace(func, ParentMapT());
184  }
185  }
186 
189  std::unordered_map<iTensor*,ParentMapT> parents_;
190 };
191 
193 using OwnerMapT = std::unordered_map<iTensor*,TensrefT>;
194 
198 
201 {
202  HeightMatrix (const TensptrsT& roots) // todo: make this a function
203  {
204  GraphStat stat;
205  for (TensptrT root : roots)
206  {
207  root->accept(stat);
208  }
209 
210  std::vector<size_t> root_heights;
211  root_heights.reserve(roots.size());
212  std::transform(roots.begin(), roots.end(),
213  std::back_inserter(root_heights),
214  [&stat](const TensptrT& root)
215  {
216  return stat.graphsize_[root.get()].upper_;
217  });
218  // max of the maxheight of roots should be the maxheight of the whole graph
219  size_t maxheight = *std::max_element(
220  root_heights.begin(), root_heights.end());
221  funcs_ = std::vector<std::unordered_set<iFunctor*>>(maxheight);
222 
223  for (auto& gpair : stat.graphsize_)
224  {
225  auto tens = gpair.first;
226  size_t height = gpair.second.upper_;
227  if (0 == height)
228  {
229  leaves_.emplace(static_cast<iLeaf*>(tens));
230  }
231  else
232  {
233  funcs_[height - 1].emplace(static_cast<iFunctor*>(tens));
234  }
235  }
236  }
237 
239  std::unordered_set<iLeaf*> leaves_;
240 
242  std::vector<std::unordered_set<iFunctor*>> funcs_;
243 };
244 
245 }
246 
247 #endif // TEQ_TRAVELER_HPP
void visit(iFunctor *func) override
Implementation of iTraveler.
Definition: traveler.hpp:66
std::unordered_map< iTensor *, estd::NumRange< size_t > > graphsize_
Definition: traveler.hpp:105
virtual const ArgsT & get_children(void) const =0
Return children nodes as a vector of raw pointers.
Interface of iOperation-defined operation node.
Definition: ifunctor.hpp:28
std::vector< FuncArg > ArgsT
Type of functor arguments.
Definition: funcarg.hpp:101
std::unordered_map< iTensor *, ParentMapT > parents_
Definition: traveler.hpp:189
void visit(iFunctor *func) override
Implementation of iTraveler.
Definition: traveler.hpp:171
void visit(iLeaf *leaf) override
Implementation of iTraveler.
Definition: traveler.hpp:60
std::unordered_set< iTensor * > visited_
Set of tensors visited.
Definition: traveler.hpp:53
Traveler that for each child tracks the relationship to all parents.
Definition: traveler.hpp:162
HeightMatrix(const TensptrsT &roots)
Definition: traveler.hpp:202
Definition: traveler.hpp:116
Traveler that maps each tensor to its subtree&#39;s maximum depth.
Definition: traveler.hpp:57
virtual void visit_leaf(iLeaf *leaf)=0
Do something during unique visit to leaf.
PathFinder(const iTensor *target)
Definition: traveler.hpp:118
void visit(iFunctor *func) override
Implementation of iTraveler.
Definition: traveler.hpp:124
Interface to travel through graph, treating iLeaf and iFunctor differently.
Definition: itensor.hpp:24
std::unordered_map< iTensor *, TensrefT > OwnerMapT
Map between tensor and its corresponding smart pointer.
Definition: traveler.hpp:193
const iTensor * target_
Target of tensor all paths are travelling to.
Definition: traveler.hpp:155
std::shared_ptr< iTensor > TensptrT
Tensor smart pointer.
Definition: itensor.hpp:51
std::vector< TensptrT > TensptrsT
Vector of tensor smart pointers.
Definition: itensor.hpp:60
void visit(iLeaf *leaf) override
Implementation of iTraveler.
Definition: traveler.hpp:165
std::vector< std::unordered_set< iFunctor * > > funcs_
Functors of subgraph ordered by ascending maximum height.
Definition: traveler.hpp:242
std::unordered_map< iTensor *, std::vector< size_t > > ParentMapT
Map tensors to indices of children.
Definition: traveler.hpp:109
Leaves set and sets of functors ordered by height (by ascending order)
Definition: traveler.hpp:200
void visit(iLeaf *leaf) override
Implementation of iTraveler.
Definition: traveler.hpp:27
virtual std::string to_string(void) const =0
Return the string representation of the tensor.
Definition: coord.hpp:16
Interface of traversible and differentiable nodes with shape information.
Definition: itensor.hpp:36
virtual void accept(iTraveler &visiter)=0
Obtain concrete information on either leaf or functor implementations.
Extremely generic traveler that visits every node in the graph once.
Definition: traveler.hpp:22
void visit(iLeaf *leaf) override
Implementation of iTraveler.
Definition: traveler.hpp:121
virtual ~OnceTraveler(void)=default
ParentMapT parents_
Map of parent to child indices that lead to target tensor.
Definition: traveler.hpp:158
std::unordered_set< iLeaf * > leaves_
Leaves of specified subroot.
Definition: traveler.hpp:239
void visit(iFunctor *func) override
Implementation of iTraveler.
Definition: traveler.hpp:37
virtual void visit_func(iFunctor *func)=0
Do something during unique visit to functor.
OwnerMapT track_owners(TensptrsT roots)
Leaf of the graph commonly representing the variable in an equation.
Definition: ileaf.hpp:19