aGrUM  0.16.0
DFSTree_tpl.h
Go to the documentation of this file.
1 
32 
33 namespace gum {
34  namespace prm {
35  namespace gspan {
36  template < typename GUM_SCALAR >
38  GUM_DESTRUCTOR(DFSTree);
39 
40  for (const auto& elt : __data) {
41  delete elt.first;
42  delete elt.second;
43  }
44 
45  delete __strategy;
46  }
47 
48  template < typename GUM_SCALAR >
52 
53  for (const auto edge : __graph->edges(&label)) {
54  bool u_first = (edge->l_u->id < edge->l_v->id);
55  Idx u_idx = (u_first) ? edge->l_u->id : edge->l_v->id;
56  Idx v_idx = (!u_first) ? edge->l_u->id : edge->l_v->id;
57 
58  bool found = false;
59 
60  for (const auto& elt : roots)
61  if ((elt.second.first == u_idx) && (elt.second.second == v_idx)) {
62  roots_edges[elt.first]->insert(edge);
63  found = true;
64  break;
65  }
66 
68  if (!found) {
69  Pattern* p = new Pattern();
70  roots.insert(p, std::make_pair(u_idx, v_idx));
71  roots_edges.insert(p, new Sequence< EdgeData< GUM_SCALAR >* >());
72  roots_edges[p]->insert(edge);
75  NodeId u = p->addNodeWithLabel((u_first) ? *edge->l_u : *edge->l_v);
76  NodeId v = p->addNodeWithLabel((!u_first) ? *edge->l_u : *edge->l_v);
77  p->addArc(u, v, label);
78  __node_map.insert(DiGraph::addNode(), p);
79  __data.insert(p, data);
80  __roots.push_back(__node_map.first(p));
81  }
82  }
83 
84  // This is used to compute the max independent set of p->max_indep_set
85  for (const auto& elt : roots_edges) {
86  __initialiaze_root(elt.first, *elt.second);
87  strategy().accept_root(elt.first);
88  delete elt.second;
89  }
90  }
91 
92  template < typename GUM_SCALAR >
94  Pattern* p, Sequence< EdgeData< GUM_SCALAR >* >& edge_seq) {
95  DFSTree< GUM_SCALAR >::PatternData* data = __data[p];
96  std::vector< NodeId > degree_list;
97 
98  for (auto iter = edge_seq.begin(); iter != edge_seq.end(); ++iter) {
99  const auto& edge = *iter;
102 
103  // Creating the multiset of instances matching p
104  bool u_first = (edge->l_u->id < edge->l_v->id);
105  seq->insert((u_first) ? edge->u : edge->v);
106  seq->insert((!u_first) ? edge->u : edge->v);
107 
108  NodeId an_id = data->iso_graph.addNode();
109  data->iso_map.insert(an_id, seq);
110  degree_list.push_back(an_id);
111 
112  // Adding edges between two isomorphisms of p sharing at least one
113  // instance
114  for (const auto& elt : data->iso_map)
115  if (elt.first != an_id)
116  for (auto iter = elt.second->begin(); iter != elt.second->end();
117  ++iter)
118  if (seq->exists(*iter)) {
119  data->iso_graph.addEdge(an_id, elt.first);
120  break;
121  }
122  }
123 
124  // Computing p->max_indep_set using a greedy algorithm
126  std::sort(degree_list.begin(), degree_list.end(), my_operator);
127  Set< NodeId > removed;
128 
129  for (const auto node : degree_list) {
130  if (!removed.exists(node)) {
131  removed.insert(node);
132 
133  for (const auto neighbor : data->iso_graph.neighbours(node))
134  removed.insert(neighbor);
135 
136  data->max_indep_set.insert(node);
137  }
138  }
139  }
140 
141  template < typename GUM_SCALAR >
145  for (const auto& elt : iso_map) {
146  bool found = false;
147 
148  for (const auto& inst : seq)
149  if (!(elt.second->exists(inst))) {
150  found = true;
151  break;
152  }
153 
154  if (!found) { return false; }
155  }
156 
157  return true;
158  }
159 
160  template < typename GUM_SCALAR >
162  Pattern& p, Pattern* child, EdgeGrowth< GUM_SCALAR >& edge_growth) {
163  // Adding child to the tree
164  NodeId node = DiGraph::addNode();
165  __node_map.insert(node, child);
166  // Adding child in p's children list
167  std::list< NodeId >& children = __data[&p]->children;
168 
169  if (children.empty()) {
170  children.push_back(node);
171  } else {
172  size_t size = children.size();
173 
174  for (std::list< NodeId >::iterator iter = children.begin();
175  iter != children.end();
176  ++iter) {
177  if (child->code() < pattern(*iter).code()) {
178  children.insert(iter, node);
179  break;
180  }
181  }
182 
183  if (size == children.size()) { children.push_back(node); }
184  }
185  }
186 
187  template < typename GUM_SCALAR >
189  Pattern& p, Pattern* child, EdgeGrowth< GUM_SCALAR >& edge_growth) {
190  NodeId v = edge_growth.v;
191 
192  // First we check if the edge is legal
193  if (v == 0) { v = child->addNodeWithLabel(*(edge_growth.l_v)); }
194 
195  child->addArc(edge_growth.u, v, *(edge_growth.edge));
196  // Neighborhood restriction is checked by the Pattern class
197  EdgeCode& edge = child->edgeCode(edge_growth.u, v);
198 
199  // Then we check if the edge we added is valid
200  if (edge < *(child->code().codes.front())) {
202  "added edge code is lesser than the first "
203  "one in the pattern's DFSCode");
204  }
205 
206  if (edge.isBackward()) {
207  typedef std::vector< EdgeCode* >::iterator EdgeIter;
208 
209  for (EdgeIter iter = child->code().codes.begin();
210  (iter + 1) != child->code().codes.end();
211  ++iter) {
212  if ((((**iter).i == v) || ((**iter).j == v)) && edge < (**iter)) {
213  GUM_ERROR(
215  "added backward edge is lesser than an existing edge on v");
216  }
217  }
218  }
219 
220  // Finally we check if child is minimal.
221  if (!child->isMinimal()) {
223  "the DFSCode for this growth is not minimal");
224  }
225  }
226 
227  template < typename GUM_SCALAR >
229  Pattern& p, EdgeGrowth< GUM_SCALAR >& edge_growth, Size min_freq) {
230  Pattern* child = new Pattern(p);
231 
232  try {
233  __checkGrowth(p, child, edge_growth);
234  } catch (OperationNotAllowed&) {
235  delete child;
236  throw;
237  }
238 
239  // Now we need to build the pattern data about child
242  std::vector< NodeId > degree_list;
244  __data[&p]->iso_map;
245  typename NodeProperty<
246  std::pair< PRMInstance< GUM_SCALAR >*,
247  PRMInstance< GUM_SCALAR >* > >::iterator_safe match;
248  // Using p information to build child's isomorphism graph
249  NodeId id = 0;
250 
251  for (const auto& elt : p_iso_map) {
252  auto match = edge_growth.matches.begin();
253 
254  for (; match != edge_growth.matches.end(); ++match) {
255  // Adding the isomorphism in the iso_graph and building the iso_map.
256  if (child->code().codes.back()->isForward()) {
257  if (elt.second->exists(match.val().first)
258  && !(elt.second->exists(match.val().second))) {
259  // Let's see if the new match is already matched
261  new Sequence< PRMInstance< GUM_SCALAR >* >(*elt.second);
262  new_seq->insert(match.val().second);
263 
264  if (__is_new_seq(*new_seq, data->iso_map)) {
265  id = data->iso_graph.addNode();
266  data->iso_map.insert(id, new_seq);
267  } else {
268  delete new_seq;
269  }
270 
271  break;
272  }
273  } else {
274  if (elt.second->exists(match.val().first)
275  && elt.second->exists(match.val().second)) {
277  new Sequence< PRMInstance< GUM_SCALAR >* >(*elt.second);
278 
279  if (__is_new_seq(*new_seq, data->iso_map)) {
280  id = data->iso_graph.addNode();
281  data->iso_map.insert(id, new_seq);
282  } else {
283  delete new_seq;
284  }
285 
286  break;
287  }
288  }
289  }
290 
291  if (match != edge_growth.matches.end()) {
292  // Adding edges in the iso_graph
293  for (const auto node : data->iso_graph.nodes())
294  if (node != id)
295  for (const auto m : *data->iso_map[id])
296  if (data->iso_map[node]->exists(m)) {
297  data->iso_graph.addEdge(node, id);
298  break;
299  }
300 
301  degree_list.push_back(id);
302  edge_growth.matches.erase(match.key());
303  }
304  }
305 
306  if (data->iso_graph.size() < min_freq) {
307  delete data;
308  delete child;
309  GUM_ERROR(OperationNotAllowed, "child is not frequent enough");
310  }
311 
312  // Now we can compute the maximal independent set of child
314  std::sort(degree_list.begin(), degree_list.end(), my_operator);
315  Set< NodeId > removed;
316 
317  for (const auto node : degree_list) {
318  if (!removed.exists(node)) {
319  removed.insert(node);
320 
321  for (const auto neighbor : data->iso_graph.neighbours(node))
322  removed.insert(neighbor);
323 
324  data->max_indep_set.insert(node);
325  }
326  }
327 
328  __data.insert(child, data);
329 
330  if (!__strategy->accept_growth(&p, child, edge_growth)) {
331  __data.erase(child);
332  delete data;
333  delete child;
334  GUM_ERROR(OperationNotAllowed, "child is not frequent enough");
335  }
336 
337  __addChild(p, child, edge_growth);
338  return *child;
339  }
340 
341  template < typename GUM_SCALAR >
345  try {
346  for (const auto& elt : x)
347  if (y[elt.first] != elt.second) return false;
348  } catch (NotFound&) { return false; }
349 
350  return true;
351  }
352 
353  // PatternData
354  template < typename GUM_SCALAR >
356  pattern(from.pattern), children(from.children),
357  iso_graph(from.iso_graph), max_indep_set(from.max_indep_set),
358  cost(from.cost), gain(from.gain) {
360 
361  for (const auto& elt : from.iso_map)
362  iso_map.insert(elt.first,
363  new Sequence< PRMInstance< GUM_SCALAR >* >(*elt.second));
364  }
365 
366  template < typename GUM_SCALAR >
368  GUM_DESTRUCTOR(DFSTree< GUM_SCALAR >::PatternData);
369 
370  for (const auto& elt : iso_map)
371  delete elt.second;
372  }
373 
374  template < typename GUM_SCALAR >
378  __graph(&graph),
379  __strategy(strategy) {
380  GUM_CONSTRUCTOR(DFSTree);
381 
383 
384  __strategy->setTree(this);
385  }
386 
387  template < typename GUM_SCALAR >
388  INLINE std::list< NodeId >& DFSTree< GUM_SCALAR >::roots() {
389  return __roots;
390  }
391 
392  template < typename GUM_SCALAR >
393  INLINE const std::list< NodeId >& DFSTree< GUM_SCALAR >::roots() const {
394  return __roots;
395  }
396 
397  template < typename GUM_SCALAR >
399  try {
400  return *(__node_map.second(
401  *(DiGraph::parents(__node_map.first(const_cast< Pattern* >(&p)))
402  .begin())));
403  } catch (NotFound&) {
404  if (__node_map.existsSecond(const_cast< Pattern* >(&p))) {
405  GUM_ERROR(NotFound, "the given pattern is a root node");
406  } else {
407  GUM_ERROR(NotFound, "pattern not found in this DFSTree");
408  }
409  }
410  }
411 
412  template < typename GUM_SCALAR >
413  INLINE const Pattern& DFSTree< GUM_SCALAR >::parent(const Pattern& p) const {
414  try {
415  return *(__node_map.second(
416  *(DiGraph::parents(__node_map.first(const_cast< Pattern* >(&p)))
417  .begin())));
418  } catch (NotFound&) {
419  if (__node_map.existsSecond(const_cast< Pattern* >(&p))) {
420  GUM_ERROR(NotFound, "the given pattern is a root node");
421  } else {
422  GUM_ERROR(NotFound, "pattern not found in this DFSTree");
423  }
424  }
425  }
426 
427  template < typename GUM_SCALAR >
428  INLINE std::list< NodeId >&
430  try {
431  return __data[const_cast< Pattern* >(&p)]->children;
432  } catch (NotFound&) {
433  GUM_ERROR(NotFound, "pattern not found in this DFSTree");
434  }
435  }
436 
437  template < typename GUM_SCALAR >
438  INLINE const std::list< NodeId >&
440  try {
441  return __data[const_cast< Pattern* >(&p)]->children;
442  } catch (NotFound&) {
443  GUM_ERROR(NotFound, "pattern not found in this DFSTree");
444  }
445  }
446 
447  template < typename GUM_SCALAR >
449  try {
450  return *(__node_map.second(id));
451  } catch (NotFound&) {
452  GUM_ERROR(NotFound, "no pattern matching the given id");
453  }
454  }
455 
456  template < typename GUM_SCALAR >
458  try {
459  return *(__node_map.second(id));
460  } catch (NotFound&) {
461  GUM_ERROR(NotFound, "no pattern matching the given id");
462  }
463  }
464 
465  template < typename GUM_SCALAR >
467  try {
468  return __data[const_cast< Pattern* >(&p)]->iso_graph;
469  } catch (NotFound&) {
470  GUM_ERROR(NotFound, "pattern not found in this DFSTree");
471  }
472  }
473 
474  template < typename GUM_SCALAR >
477  try {
478  return *(__data[const_cast< Pattern* >(&p)]->iso_map[node]);
479  } catch (NotFound&) {
480  if (__data.exists(const_cast< Pattern* >(&p))) {
481  GUM_ERROR(NotFound, "node not found in Pattern's isomorphism graph");
482  } else {
483  GUM_ERROR(NotFound, "pattern not found in this DFSTree");
484  }
485  }
486  }
487 
488  template < typename GUM_SCALAR >
489  INLINE Set< NodeId >&
491  try {
492  return __data[const_cast< Pattern* >(&p)]->max_indep_set;
493  } catch (NotFound&) {
494  GUM_ERROR(NotFound, "pattern not found in this DFSTree");
495  }
496  }
497 
498  template < typename GUM_SCALAR >
499  INLINE const InterfaceGraph< GUM_SCALAR >&
501  return *__graph;
502  }
503 
504  template < typename GUM_SCALAR >
505  INLINE std::ostream& operator<<(std::ostream& out,
506  const EdgeGrowth< GUM_SCALAR >& edge) {
507  out << edge.u << ", " << *(edge.edge) << ", " << *(edge.l_v) << ", "
508  << edge.v;
509  return out;
510  }
511 
512  template < typename GUM_SCALAR >
513  INLINE double DFSTree< GUM_SCALAR >::frequency(const Pattern& p) const {
514  return (double)__data[const_cast< Pattern* >(&p)]->max_indep_set.size();
515  }
516 
517  template < typename GUM_SCALAR >
518  INLINE typename DFSTree< GUM_SCALAR >::PatternData&
520  return *(__data[const_cast< Pattern* >(&p)]);
521  }
522 
523  template < typename GUM_SCALAR >
524  INLINE const typename DFSTree< GUM_SCALAR >::PatternData&
526  return *(__data[const_cast< Pattern* >(&p)]);
527  }
528 
529  template < typename GUM_SCALAR >
531  return *__strategy;
532  }
533 
534  template < typename GUM_SCALAR >
535  INLINE const SearchStrategy< GUM_SCALAR >&
537  return *__strategy;
538  }
539 
540  // NeighborDegreeSort
541 
542  template < typename GUM_SCALAR >
544  UndiGraph& graph) :
545  g(graph) {
547  }
548 
549  template < typename GUM_SCALAR >
551  const NeighborDegreeSort& source) :
552  g(source.g) {
554  }
555 
556  template < typename GUM_SCALAR >
559  }
560 
561  template < typename GUM_SCALAR >
563  NodeId j) {
564  return g.neighbours(i).size() < g.neighbours(j).size();
565  }
566 
567  // PatternData
568 
569  template < typename GUM_SCALAR >
571  pattern(p), cost(0), gain(0) {
572  GUM_CONSTRUCTOR(DFSTree< GUM_SCALAR >::PatternData);
573  }
574 
575  } /* namespace gspan */
576  } /* namespace prm */
577 } /* namespace gum */
PatternData(Pattern *p)
Constructor.
Definition: DFSTree_tpl.h:570
const InterfaceGraph< GUM_SCALAR > * __graph
The interface graph on which this DFSTree applies.
Definition: DFSTree.h:264
~DFSTree()
Destructor.
Definition: DFSTree_tpl.h:37
EdgeCode & edgeCode(NodeId tail, NodeId head)
Returns the EdgeCode of an edge of this Pattern.
Definition: pattern_inl.h:179
UndiGraph & iso_graph(const Pattern &p)
Returns the isomorphism graph of p in the interface graph.
Definition: DFSTree_tpl.h:466
This class is used to define an edge growth of a pattern in this DFSTree.
Definition: edgeGrowth.h:63
LabelData * l_v
The LabelData over the node of this edge growth.
Definition: edgeGrowth.h:80
std::list< NodeId > & children(const Pattern &p)
Returns the list of p children in this DFSTree.
Definition: DFSTree_tpl.h:429
std::ostream & operator<<(std::ostream &out, const DFSCode &code)
Print code in out.
Definition: DFSCode.cpp:40
SearchStrategy< GUM_SCALAR > * __strategy
The strategy used to prune the search tree.
Definition: DFSTree.h:277
void __addChild(Pattern &p, Pattern *child, EdgeGrowth< GUM_SCALAR > &edge_growth)
Add a child to this DFSTree.
Definition: DFSTree_tpl.h:161
Inner class to handle data about labels in this interface graph.
bool operator()(NodeId i, NodeId j)
The operator used to sort stuff.
Definition: DFSTree_tpl.h:562
An PRMInstance is a Bayesian Network fragment defined by a Class and used in a PRMSystem.
Definition: PRMInstance.h:63
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
DFSCode & code()
Returns the DFSCode of this Pattern.
Definition: pattern_inl.h:173
Size size() const
alias for sizeNodes
The generic class for storing (ordered) sequences of objects.
Definition: sequence.h:1022
virtual void addEdge(const NodeId first, const NodeId second)
insert a new edge into the undirected graph
Definition: undiGraph_inl.h:35
NodeId addNodeWithLabel(LabelData &l)
Insert a node with the given LabelData.
Definition: pattern_inl.h:41
Pattern & growPattern(Pattern &p, EdgeGrowth< GUM_SCALAR > &edge_growth, Size min_freq)
Add a one edge growth of p as one of its child.
Definition: DFSTree_tpl.h:228
NodeProperty< std::pair< PRMInstance< GUM_SCALAR > *, PRMInstance< GUM_SCALAR > *> > matches
The mapping between the u and v for each match in the interface graph.
Definition: edgeGrowth.h:90
Abstract class representing an element of PRM class.
std::list< NodeId > __roots
The list of root patterns in this DFSTree.
Definition: DFSTree.h:267
UndiGraph & g
The isomorphism graph.
Definition: DFSTree.h:257
bool isMinimal()
Returns the DFSCode of this Pattern.
Definition: pattern.cpp:56
Inner class to handle data about edges in __graph.
NeighborDegreeSort(UndiGraph &graph)
Constructor.
Definition: DFSTree_tpl.h:543
This is used to generate the max_indep_set of a Pattern.
Definition: DFSTree.h:247
This class represent the interface graph of a given gum::prm::PRMSystem<GUM_SCALAR>.
void addRoot(LabelData &data)
Add a one edge Pattern in this DFSTree.
Definition: DFSTree_tpl.h:49
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
Definition: agrum.h:25
bool __is_new_seq(Sequence< PRMInstance< GUM_SCALAR > * > &seq, NodeProperty< Sequence< PRMInstance< GUM_SCALAR > * > * > &iso_map)
Check if an instance match is redundant.
Definition: DFSTree_tpl.h:142
LabelData * edge
The LabelData over the edge of this edge growth.
Definition: edgeGrowth.h:78
std::vector< EdgeCode *> codes
The vector containing the EdgeCode composing this DFSCode.
Definition: DFSCode.h:90
virtual NodeId addNode()
insert a new node and return its id
The class for generic Hash Tables.
Definition: hashTable.h:679
const NodeSet & neighbours(const NodeId id) const
returns the set of edges adjacent to a given node
std::list< NodeId > & roots()
Returns the list of root patterns in this DFSTree.
Definition: DFSTree_tpl.h:388
const InterfaceGraph< GUM_SCALAR > & graph() const
Returns the list of root patterns in this DFSTree.
Definition: DFSTree_tpl.h:500
NodeId u
The id of the node from which we grow an edge.
Definition: edgeGrowth.h:76
A DFSTree is used by gspan to sort lexicographically patterns discovered in an interface graph...
Definition: DFSTree.h:71
represent a DFS code used by gspan.
Definition: edgeCode.h:52
node_iterator begin() const noexcept
a begin iterator to parse the set of nodes contained in the NodeGraphPart
NodeId v
If the growth is backward you must assigned the subscript of v, otherwise 0 is assigned (recall that ...
Definition: edgeGrowth.h:83
bool isBackward() const
Returns true if this EdgeCode is a backward edge.
Definition: edgeCode_inl.h:59
const NodeSet & parents(const NodeId id) const
returns the set of nodes with arc ingoing to a given node
Sequence< PRMInstance< GUM_SCALAR > *> & iso_map(const Pattern &p, NodeId node)
Given a pattern and a node in its isomorphism graph, this methods returns the sequence of instance ma...
Definition: DFSTree_tpl.h:476
const NodeGraphPart & nodes() const
return *this as a NodeGraphPart
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
bool exists(const Key &k) const
Check the existence of k in the sequence.
Definition: sequence_tpl.h:402
Set< NodeId > max_indep_set
The maximal independent set of p.
Definition: DFSTree.h:110
Pattern & pattern(NodeId id)
Returns the pattern represented by id in this DFSTree.
Definition: DFSTree_tpl.h:448
NodeProperty< Sequence< PRMInstance< GUM_SCALAR > *> *> iso_map
The instances matching p in the interface graph.
Definition: DFSTree.h:108
Set< NodeId > & max_indep_set(const Pattern &p)
Returns the maximal independent set of p isomorphism graph.
Definition: DFSTree_tpl.h:490
SearchStrategy< GUM_SCALAR > & strategy()
strategy getter
Definition: DFSTree_tpl.h:530
This is class is an implementation of a simple serach strategy for the gspan algorithm: it accept a g...
void __initialiaze_root(Pattern *p, Sequence< EdgeData< GUM_SCALAR > * > &seq)
This initialize the DSFTree with a new root.
Definition: DFSTree_tpl.h:93
Base class for undirected graphs.
Definition: undiGraph.h:109
Size Idx
Type for indexes.
Definition: types.h:53
PatternData & data(const Pattern &p)
Definition: DFSTree_tpl.h:519
void addArc(NodeId i, NodeId j, LabelData &l)
Add an arc to this Pattern.
Definition: pattern_inl.h:118
HashTable< Pattern *, PatternData *> __data
Data about patterns in this DFSTree.
Definition: DFSTree.h:274
double frequency(const Pattern &p) const
Returns the frequency of p respecting it&#39;s maximal independent set.
Definition: DFSTree_tpl.h:513
bool __test_equality(HashTable< PRMClassElement< GUM_SCALAR > *, Size > &x, HashTable< PRMClassElement< GUM_SCALAR > *, Size > &y)
Definition: DFSTree_tpl.h:342
void __checkGrowth(Pattern &p, Pattern *child, EdgeGrowth< GUM_SCALAR > &edge_growth)
Raise different exceptions if child is invalid or illegal.
Definition: DFSTree_tpl.h:188
std::size_t Size
In aGrUM, hashed values are unsigned long int.
Definition: types.h:48
Pattern & parent(const Pattern &p)
Returns the parent of p in this DFSTree.
Definition: DFSTree_tpl.h:398
UndiGraph iso_graph
The isomorphism graph of the pattern.
Definition: DFSTree.h:106
Size size() const noexcept
Returns the number of elements in the set.
Definition: set_tpl.h:701
Bijection< NodeId, Pattern *> __node_map
The mapping between nodes in this DFSTree and the patterns they represents.
Definition: DFSTree.h:271
value_type & insert(const Key &key, const Val &val)
Adds a new element (actually a copy of this element) into the hash table.
This contains all the information we want for a node in a DFSTree.
Definition: pattern.h:73
DFSTree(const InterfaceGraph< GUM_SCALAR > &graph, SearchStrategy< GUM_SCALAR > *strategy=0)
Default constructor.
Definition: DFSTree_tpl.h:375
This is an abstract class used to tune search strategies in the gspan algorithm.
Definition: DFSTree.h:61
Size NodeId
Type for node ids.
Definition: graphElements.h:98
void insert(const Key &k)
Inserts a new element into the set.
Definition: set_tpl.h:613
#define GUM_ERROR(type, msg)
Definition: exceptions.h:55
void insert(const Key &k)
Insert an element at the end of the sequence.
Definition: sequence_tpl.h:408