aGrUM  0.16.0
staticTriangulation.cpp
Go to the documentation of this file.
1 
33 
34 #ifdef GUM_NO_INLINE
36 #endif // GUM_NO_INLINE
37 
38 namespace gum {
39 
40  // default constructor
42  const UndiGraph* theGraph,
43  const NodeProperty< Size >* domsizes,
44  const EliminationSequenceStrategy& elimSeq,
45  const JunctionTreeStrategy& JTStrategy,
46  bool minimality) :
47  Triangulation(domsizes),
48  _elimination_sequence_strategy(elimSeq.newFactory()),
49  _junction_tree_strategy(JTStrategy.newFactory()), __original_graph(theGraph),
50  __minimality_required(minimality) {
51  // for debugging purposes
52  GUM_CONSTRUCTOR(StaticTriangulation);
53 
54  // if the graph is not empty, resize several structures in order to speed-up
55  // their fillings.
56  if (theGraph != nullptr) {
57  __elim_order.resize(theGraph->size());
58  __reverse_elim_order.resize(theGraph->size());
59  __elim_cliques.resize(theGraph->size());
60  __node_2_max_prime_clique.resize(theGraph->size());
61  __added_fill_ins.resize(theGraph->size());
62  }
63 
64  // register the triangulation to its junction tree strategy
66  }
67 
68  // default constructor
70  const EliminationSequenceStrategy& elimSeq,
71  const JunctionTreeStrategy& JTStrategy,
72  bool minimality) :
74  _junction_tree_strategy(JTStrategy.newFactory()),
75  __minimality_required(minimality) {
76  // for debugging purposes
77  GUM_CONSTRUCTOR(StaticTriangulation);
78 
79  // register the triangulation to its junction tree strategy
81  }
82 
83  // copy constructor
101  // copy the strategies
105 
106  // if from has a junction tree, copy it
107  if (from.__junction_tree != nullptr) {
109  }
110 
111  // for debugging purposes
112  GUM_CONS_CPY(StaticTriangulation);
113  }
114 
115  // move constructor
117  Triangulation(std::move(from)),
122  __fill_ins(std::move(from.__fill_ins)),
123  __elim_order(std::move(from.__elim_order)),
125  __elim_cliques(std::move(from.__elim_cliques)),
126  __elim_tree(std::move(from.__elim_tree)),
138  // move the factories contained in from
139  from._elimination_sequence_strategy = new DefaultEliminationSequenceStrategy;
140  from._junction_tree_strategy = new DefaultJunctionTreeStrategy;
142 
143  // if from has a junction tree, copy it
144  if (from.__junction_tree != nullptr) {
146  }
147 
148  // for debugging purposes
149  GUM_CONS_MOV(StaticTriangulation);
150  }
151 
154  // for debugging purposes
155  GUM_DESTRUCTOR(StaticTriangulation);
156 
159 
160  // no need to deallocate __original_graph nor __junction_tree because
161  // they are not owned by the static triangulation class
162  }
163 
166  // clear the factories
169 
170  // remove the current graphs
171  __original_graph = nullptr;
172  __junction_tree = nullptr;
174  __elim_tree.clear();
176  __elim_cliques.clear();
178 
179  // remove all fill-ins and orderings
180  __fill_ins.clear();
181  __added_fill_ins.clear();
182  __elim_order.clear();
183  __reverse_elim_order.clear();
184 
185  // indicates that the junction tree, the max prime tree, etc, are updated
186  __has_triangulation = true;
188  __has_elimination_tree = true;
189  __has_junction_tree = true;
191  __has_fill_ins = true;
192  }
193 
194  // removes redondant fill-ins and compute proper elimination cliques and order
196  // apply recursive thinning (fmint, see Kjaerulff (90), "triangulation of
197  // graphs - algorithms giving small total state space")
198  NodeId node1, node2;
199  bool incomplete;
200  std::vector< NodeId > adj;
201  EdgeSet T_prime;
203 
204  for (const auto node : __triangulated_graph)
205  R.insert(node, 0);
206 
207  // the FMINT loop
208  if (__added_fill_ins.size() > 0) {
209  for (auto iter = __added_fill_ins.rbegin(); iter != __added_fill_ins.rend();
210  ++iter) {
211  if (iter->size()) {
212  // here apply MINT to T_i = __added_fill_ins[i]
213  EdgeSet& T = *iter;
214 
215  // compute R: by default, R is equal to all the nodes in the graph
216  // when R[...] >= j (see the j in the loop below), this means that the
217  // node belongs to an extremal edge in R
218  for (std::size_t k = 0; k < __elim_order.size(); ++k)
219  R[__elim_order[k]] =
220  0; // WARNING: do not replace R[__elim_order[k]] by
221 
222  // R[k] because the node ids may not be
223  // consecutive numbers
224 
225  // apply MINT while some edges can possibly be deleted
226  bool require_mint = true;
227 
228  for (unsigned int j = 0; require_mint; ++j) {
229  // find T' (it is equal to the edges (v,w) of T such that
230  // the intersection of adj(v,G) and adj(w,G) is complete and such
231  // that
232  // v and/or w belongs to an extremal node in R
233  for (const auto& edge : T) {
234  node1 = edge.first();
235  node2 = edge.second();
236 
237  // check if at least one extremal node belongs to R
238  if ((R[node1] < j) && (R[node2] < j)) continue;
239 
240  // check if the intersection of adj(v,G) and adj(w,G) is a
241  // complete subgraph
242  if (__triangulated_graph.neighbours(node2).size()
243  < __triangulated_graph.neighbours(node1).size()) {
244  NodeId tmp = node1;
245  node1 = node2;
246  node2 = tmp;
247  }
248 
249  incomplete = false;
250 
251  // find the nodes belonging to the intersection of adj(v,G)
252  // and adj(w,G)
253  for (const auto adjnode : __triangulated_graph.neighbours(node1))
254  if (__triangulated_graph.existsEdge(node2, adjnode))
255  adj.push_back(adjnode);
256 
257  // check if the intersection is complete
258  for (unsigned int k = 0; k < adj.size() && !incomplete; ++k) {
259  for (unsigned int m = k + 1; m < adj.size(); ++m) {
260  if (!__triangulated_graph.existsEdge(adj[k], adj[m])) {
261  incomplete = true;
262  break;
263  }
264  }
265  }
266 
267  adj.clear();
268 
269  if (!incomplete) {
270  T_prime.insert(edge);
271  R[node1] = j + 1;
272  R[node2] = j + 1;
273  }
274  }
275 
276  // compute the new value of T (i.e. T\T') and update the
277  // triangulated graph
278  for (const auto& edge : T_prime) {
279  T.erase(edge);
280  __triangulated_graph.eraseEdge(edge);
281 
282  if (__has_fill_ins) __fill_ins.erase(edge);
283  }
284 
285  if (T_prime.size() == 0) require_mint = false;
286 
287  T_prime.clear();
288  }
289  }
290  }
291  }
292 
293  // here, the recursive thinning has removed all the superfluous edges.
294  // Hence some cliques have been split and, as a result, the elimination
295  // order has changed. We should thus compute a new perfect ordering. To
296  // do so, we use a Maximal Cardinality Search: it has indeed the nice
297  // property that, when the graph is already triangulated, it finds a
298  // compatible order of elimination that does not require any edge addition
299 
300  // a structure storing the number of neighbours previously processed
302  numbered_neighbours(std::greater< unsigned int >(),
303  __triangulated_graph.size());
304 
305  for (Size i = 0; i < __elim_order.size(); ++i)
306  numbered_neighbours.insert(__elim_order[i], 0);
307 
308  // perform the maximum cardinality search
309  if (__elim_order.size() > 0) {
310  for (Size i = Size(__elim_order.size()); i >= 1; --i) {
311  NodeId ni = NodeId(i - 1);
312  NodeId node = numbered_neighbours.pop();
313  __elim_order[ni] = node;
314  __reverse_elim_order[node] = ni;
315 
316  for (const auto neighbour : __triangulated_graph.neighbours(node)) {
317  try {
318  numbered_neighbours.setPriority(
319  neighbour, 1 + numbered_neighbours.priority(neighbour));
320  } catch (NotFound&) {}
321  }
322  }
323  }
324 
325  // here the elimination order is ok. We now need to update the
326  // __elim_cliques
327  for (Size i = 0; i < __elim_order.size(); ++i) {
328  NodeSet& cliques = __elim_cliques.insert(__elim_order[i], NodeSet()).second;
329  cliques << __elim_order[i];
330 
331  for (const auto neighbour : __triangulated_graph.neighbours(__elim_order[i]))
332  if (__reverse_elim_order[neighbour] > i) cliques << neighbour;
333  }
334  }
335 
338  // if there already exists an elimination tree, no need to compute it again
339  if (__has_elimination_tree) return;
340 
341  // if the graph is not triangulated, triangulate it
343 
344  // create the nodes of the elimination tree
345  __elim_tree.clear();
346 
347  Size size = Size(__elim_order.size());
348  for (NodeId i = NodeId(0); i < size; ++i)
350 
351  // create the edges of the elimination tree: join a node to the one in
352  // its clique that is eliminated first
353  for (NodeId i = NodeId(0); i < size; ++i) {
354  NodeId clique_i_creator = __elim_order[i];
355  const NodeSet& list_of_nodes = __elim_cliques[clique_i_creator];
356  Idx child = __original_graph->bound() + 1;
357 
358  for (const auto node : list_of_nodes) {
359  Idx it_elim_step = __reverse_elim_order[node];
360 
361  if ((node != clique_i_creator) && (child > it_elim_step))
362  child = it_elim_step;
363  }
364 
365  if (child <= __original_graph->bound()) {
366  // WARNING: here, we assume that the nodes of the elimination tree are
367  // indexed from 0 to n-1
368  __elim_tree.addEdge(i, child);
369  }
370  }
371 
372  __has_elimination_tree = true;
373  }
374 
377  const NodeId node,
378  const NodeId from,
379  std::vector< Arc >& merged_cliques,
380  NodeSet& mark) const {
381  mark << node;
382 
383  for (const auto other_node : __junction_tree->neighbours(node))
384  if (other_node != from) {
385  const NodeSet& separator = __junction_tree->separator(node, other_node);
386  // check that the separator between node and other_node is complete
387  bool complete = true;
388 
389  for (auto iter_sep1 = separator.begin();
390  iter_sep1 != separator.end() && complete;
391  ++iter_sep1) {
392  auto iter_sep2 = iter_sep1;
393 
394  for (++iter_sep2; iter_sep2 != separator.end(); ++iter_sep2) {
395  if (!__original_graph->existsEdge(*iter_sep1, *iter_sep2)) {
396  complete = false;
397  break;
398  }
399  }
400  }
401 
402  // here complete indicates whether the separator is complete or not
403  if (!complete) merged_cliques.push_back(Arc(other_node, node));
404 
405  __computeMaxPrimeMergings(other_node, node, merged_cliques, mark);
406  }
407  }
408 
411  // if there already exists a max prime junction tree, no need
412  // to recompute it
413  if (__has_max_prime_junction_tree) return;
414 
415  // if there is no junction tree, create it
417 
418  // the maximal prime subgraph join tree is created by aggregation of some
419  // cliques. More precisely, when the separator between 2 cliques is not
420  // complete in the original graph, then the two cliques must be merged.
421  // Create a hashtable indicating which clique has been absorbed by some
422  // other
423  // clique.
424  NodeProperty< NodeId > T_mpd_cliques(__junction_tree->size());
425 
426  for (const auto clik : __junction_tree->nodes())
427  T_mpd_cliques.insert(clik, clik);
428 
429  // parse all the separators of the junction tree and test those that are not
430  // complete in the orginal graph
431  std::vector< Arc > merged_cliques;
432 
433  NodeSet mark;
434 
435  for (const auto clik : __junction_tree->nodes())
436  if (!mark.contains(clik))
437  __computeMaxPrimeMergings(clik, clik, merged_cliques, mark);
438 
439  // compute the transitive closure of merged_cliques. This one will contain
440  // pairs (X,Y) indicating that clique X must be merged with clique Y.
441  // Actually clique X will be inserted into clique Y.
442  for (unsigned int i = 0; i < merged_cliques.size(); ++i) {
443  T_mpd_cliques[merged_cliques[i].tail()] =
444  T_mpd_cliques[merged_cliques[i].head()];
445  }
446 
447  // now we can create the max prime junction tree. First, create the cliques
448  for (const auto& elt : T_mpd_cliques)
449  if (elt.first == elt.second)
451  __junction_tree->clique(elt.second));
452 
453  // add to the cliques previously created the nodes of the cliques that were
454  // merged into them
455  for (const auto& elt : T_mpd_cliques)
456  if (elt.first != elt.second)
457  for (const auto node : __junction_tree->clique(elt.first)) {
458  try {
459  __max_prime_junction_tree.addToClique(elt.second, node);
460  } catch (DuplicateElement&) {}
461  }
462 
463  // add the edges to the graph
464  for (const auto& edge : __junction_tree->edges()) {
465  NodeId node1 = T_mpd_cliques[edge.first()];
466  NodeId node2 = T_mpd_cliques[edge.second()];
467 
468  if (node1 != node2) {
469  try {
470  __max_prime_junction_tree.addEdge(node1, node2);
471  } catch (DuplicateElement&) {}
472  }
473  }
474 
475  // compute for each node which clique of the max prime junction tree was
476  // created by the elimination of the node
477  const NodeProperty< NodeId >& node_2_junction_clique =
479 
480  for (const auto& elt : node_2_junction_clique)
481  __node_2_max_prime_clique.insert(elt.first, T_mpd_cliques[elt.second]);
482 
484  }
485 
489 
490  // if we did not construct the triangulated graph during the triangulation,
491  // that is, we just constructed the junction tree, we shall construct it now
493  // just in case, be sure that the junction tree has been constructed
495 
496  // copy the original graph
498 
499  for (const auto clik_id : *__junction_tree) {
500  // for each clique, add the edges necessary to make it complete
501  const NodeSet& clique = __junction_tree->clique(clik_id);
502  std::vector< NodeId > clique_nodes(clique.size());
503  unsigned int i = 0;
504 
505  for (const auto node : clique) {
506  clique_nodes[i] = node;
507  i += 1;
508  }
509 
510  for (i = 0; i < clique_nodes.size(); ++i) {
511  for (unsigned int j = i + 1; j < clique_nodes.size(); ++j) {
512  try {
513  __triangulated_graph.addEdge(clique_nodes[i], clique_nodes[j]);
514  } catch (DuplicateElement&) {}
515  }
516  }
517  }
518 
520  }
521 
522  return __triangulated_graph;
523  }
524 
525  // initialize the triangulation algorithm for a new graph
527  const NodeProperty< Size >* domsizes) {
528  // remove the old graph
529  clear();
530 
531  if (graph != nullptr) {
532  // prepare the size of the data for the new graph
533  __elim_order.resize(graph->size());
534  __reverse_elim_order.resize(graph->size());
535  __elim_cliques.resize(graph->size());
536  __added_fill_ins.resize(graph->size());
537  __node_2_max_prime_clique.resize(graph->size());
538  }
539 
540  // keep track of the variables passed in argument
541  __original_graph = graph;
542  _domain_sizes = domsizes;
543 
544  // indicate that no triangulation was performed for this graph
545  __has_triangulation = false;
546  __has_triangulated_graph = false;
547  __has_elimination_tree = false;
548  __has_junction_tree = false;
550  __has_fill_ins = false;
551  }
552 
555  // if the graph is already triangulated, no need to triangulate it again
556  if (__has_triangulation) return;
557 
558  // copy the graph to be triangulated, so that we can modify it
559  UndiGraph tmp_graph = *__original_graph;
560 
561  _initTriangulation(tmp_graph);
563 
564  // if we are to do recursive thinning, we will have to add fill-ins to the
565  // triangulated graph each time we eliminate a node. Hence, we shall
566  // initialize the triangulated graph by a copy of the original graph
567  if (__minimality_required) {
570  }
571 
572  // perform the triangulation
573  NodeId removable_node = 0;
574 
575  for (unsigned int nb_elim = 0; tmp_graph.size() != 0; ++nb_elim) {
577 
578  // when minimality is not required, i.e., we won't apply recursive
579  // thinning, the cliques sets can be computed
580  if (!__minimality_required) {
581  NodeSet& cliques = __elim_cliques.insert(removable_node, NodeSet()).second;
582  cliques.resize(tmp_graph.neighbours(removable_node).size() / 2);
583  cliques << removable_node;
584  for (const auto clik : tmp_graph.neighbours(removable_node))
585  cliques << clik;
586  } else {
587  // here recursive thinning will be applied, hence we need store the
588  // fill-ins added by the current node removal
589  EdgeSet& current_fill = __added_fill_ins[nb_elim];
590  NodeId node1, node2;
591 
592  const NodeSet& nei = tmp_graph.neighbours(removable_node);
593 
594  for (auto iter_edges1 = nei.begin(); iter_edges1 != nei.end();
595  ++iter_edges1) {
596  node1 = *iter_edges1;
597  auto iter_edges2 = iter_edges1;
598 
599  for (++iter_edges2; iter_edges2 != nei.end(); ++iter_edges2) {
600  node2 = *iter_edges2;
601  Edge edge(node1, node2);
602 
603  if (!tmp_graph.existsEdge(edge)) {
604  current_fill.insert(edge);
605  __triangulated_graph.addEdge(node1, node2);
606  }
607  }
608  }
609  }
610 
611  // if we want fill-ins but the elimination sequence strategy does not
612  // compute them, we shall compute them here
615  NodeId node1, node2;
616 
617  // add edges between removable_node's neighbours in order to create
618  // a clique
619  const NodeSet& nei = tmp_graph.neighbours(removable_node);
620 
621  for (auto iter_edges1 = nei.begin(); iter_edges1 != nei.end();
622  ++iter_edges1) {
623  node1 = *iter_edges1;
624  auto iter_edges2 = iter_edges1;
625 
626  for (++iter_edges2; iter_edges2 != nei.end(); ++iter_edges2) {
627  node2 = *iter_edges2;
628  Edge edge(node1, node2);
629 
630  if (!tmp_graph.existsEdge(edge)) { __fill_ins.insert(edge); }
631  }
632  }
633 
634  // delete removable_node and its adjacent edges
635  tmp_graph.eraseNode(removable_node);
636  }
637 
638  // inform the elimination sequence that we are actually removing
639  // removable_node (this enables, for instance, to update the weights of
640  // the nodes in the graph)
642 
644  NodeId node1, node2;
645 
646  const NodeSet& nei = tmp_graph.neighbours(removable_node);
647 
648  for (auto iter_edges1 = nei.begin(); iter_edges1 != nei.end();
649  ++iter_edges1) {
650  node1 = *iter_edges1;
651  auto iter_edges2 = iter_edges1;
652 
653  for (++iter_edges2; iter_edges2 != nei.end(); ++iter_edges2) {
654  node2 = *iter_edges2;
655  Edge edge(node1, node2);
656 
657  if (!tmp_graph.existsEdge(edge)) { tmp_graph.addEdge(node1, node2); }
658  }
659  }
660 
661  tmp_graph.eraseNode(removable_node);
662  }
663 
664  // update the elimination order
665  __elim_order[nb_elim] = removable_node;
666  __reverse_elim_order.insert(removable_node, nb_elim);
667  }
668 
669  // indicate whether we actually computed fill-ins
671 
672  // if minimality is required, remove the redondant edges
674 
675  __has_triangulation = true;
676  }
677 
680  // if we did not compute the triangulation yet, do it and commpute
681  // the fill-ins at the same time
682  if (!__has_triangulation) {
683  bool want_fill_ins = __we_want_fill_ins;
684  __we_want_fill_ins = true;
685  __triangulate();
686  __we_want_fill_ins = want_fill_ins;
687  __has_fill_ins = true;
688  }
689 
690  // here, we already computed a triangulation and we already computed
691  // the fill-ins, so return them
692  if (__has_fill_ins) {
695  else
696  return __fill_ins;
697  } else {
698  // ok, here, we shall compute the fill-ins as they were not precomputed
699  if (!__original_graph) return __fill_ins;
700 
701  // just in case, be sure that the junction tree has been constructed
703 
704  for (const auto clik_id : __junction_tree->nodes()) {
705  // for each clique, add the edges necessary to make it complete
706  const NodeSet& clique = __junction_tree->clique(clik_id);
707  std::vector< NodeId > clique_nodes(clique.size());
708  unsigned int i = 0;
709 
710  for (const auto node : clique) {
711  clique_nodes[i] = node;
712  i += 1;
713  }
714 
715  for (i = 0; i < clique_nodes.size(); ++i) {
716  for (unsigned int j = i + 1; j < clique_nodes.size(); ++j) {
717  Edge edge(clique_nodes[i], clique_nodes[j]);
718 
719  if (!__original_graph->existsEdge(edge)) {
720  try {
721  __fill_ins.insert(edge);
722  } catch (DuplicateElement&) {}
723  }
724  }
725  }
726  }
727 
728  return __fill_ins;
729  }
730  }
731 
735  }
736 
737 } /* namespace gum */
const CliqueGraph & junctionTree()
returns a compatible junction tree
bool contains(const Key &k) const
Indicates whether a given elements belong to the set.
Definition: set_tpl.h:581
virtual void clear()
clears the sequence (to prepare, for instance, a new elimination sequence)
const UndiGraph & triangulatedGraph()
returns the triangulated graph
virtual void eliminationUpdate(const NodeId node)
performs all the graph/fill-ins updates provided (if any)
virtual const EdgeSet & fillIns()
in case fill-ins are provided, this function returns the fill-ins due to all the nodes eliminated so ...
NodeId addNode(const NodeSet &clique)
adds a new clique to the graph
virtual const NodeProperty< NodeId > & createdCliques()=0
returns, for each node, the clique of the junction tree which was created by its deletion ...
virtual void clear()
removes all the nodes and edges from the graph
Definition: undiGraph_inl.h:43
void clear()
reinitialize the graph to be triangulated to an empty graph
virtual EliminationSequenceStrategy * copyFactory() const =0
virtual copy constructor
NodeProperty< NodeId > __node_2_max_prime_clique
indicates which clique of the max prime junction tree was created by the elmination of a given node (...
void __triangulate()
the function that performs the triangulation
bool __has_max_prime_junction_tree
indicates whether a maximal prime subgraph junction tree has been constructed
const NodeSet & separator(const Edge &edge) const
returns the separator included in a given edge
Set< NodeId > NodeSet
Some typdefs and define for shortcuts ...
virtual ~StaticTriangulation()
destructor
EliminationSequenceStrategy * _elimination_sequence_strategy
the elimination sequence strategy used by the triangulation
const UndiGraph * __original_graph
a pointer to the (external) original graph (which will be triangulated)
virtual void _initTriangulation(UndiGraph &graph)
the function called to initialize the triangulation process
Size size() const
alias for sizeNodes
virtual void addEdge(const NodeId first, const NodeId second)
insert a new edge into the undirected graph
Definition: undiGraph_inl.h:35
const EdgeSet & fillIns()
returns the fill-ins added by the triangulation algorithm
STL namespace.
void __computeMaxPrimeJunctionTree()
computes the junction tree of the maximal prime subgraphs
bool __has_triangulated_graph
a boolean indicating whether we have constructed the triangulated graph
virtual void clear()
removes all the cliques and separators from the graph (as well as their adjacent edges) ...
JunctionTreeStrategy * _junction_tree_strategy
the junction tree strategy used by the triangulation
void erase(const Key &k)
Erases an element from the set.
Definition: set_tpl.h:656
UndiGraph __triangulated_graph
the triangulated graph
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
Definition: agrum.h:25
NodeProperty< NodeId > __reverse_elim_order
the elimination order (access by NodeId)
const iterator & end() const noexcept
The usual unsafe end iterator to parse the set.
Definition: set_tpl.h:530
iterator begin() const
The usual unsafe begin iterator to parse the set.
Definition: set_tpl.h:517
std::vector< EdgeSet > __added_fill_ins
a vector containing the set of fill-ins added after each node elimination (used by recursive thinning...
The class for generic Hash Tables.
Definition: hashTable.h:679
An efficient unconstrained elimination sequence algorithm.
const NodeProperty< Size > * _domain_sizes
the domain sizes of the variables/nodes of the graph
const NodeSet & neighbours(const NodeId id) const
returns the set of edges adjacent to a given node
virtual void eraseNode(const NodeId id)
remove a node and its adjacent edges from the graph
Definition: undiGraph_inl.h:58
bool __has_triangulation
a boolean indicating whether we have parformed a triangulation
virtual void clear()=0
resets the current junction tree strategy data structures
const EdgeSet & edges() const
returns the set of edges stored within the EdgeGraphPart
A priorityQueue is a heap in which each element has a mutable priorityA priority queue is quite simil...
Definition: priorityQueue.h:51
virtual JunctionTreeStrategy * copyFactory(StaticTriangulation *triangulation=nullptr) const =0
virtual copy constructor
virtual void addToClique(const NodeId clique_id, const NodeId node_id)
changes the set of nodes included into a given clique and returns the new set
bool __has_junction_tree
a boolean indicating whether the junction tree has been constructed
bool existsEdge(const Edge &edge) const
indicates whether a given edge exists
void resize(Size new_capacity)
Changes the size of the underlying hash table containing the set.
Definition: set_tpl.h:552
virtual void setTriangulation(StaticTriangulation *triangulation)=0
assigns the triangulation to the junction tree strategy
The base class for all directed edgesThis class is used as a basis for manipulating all directed edge...
CliqueGraph __max_prime_junction_tree
the maximal prime subgraph junction tree computed from the junction tree
Base Class for all the algorithms producing a junction given a set of cliques/subcliques resulting fr...
const NodeGraphPart & nodes() const
return *this as a NodeGraphPart
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
virtual bool providesGraphUpdate() const =0
indicates whether the elimination sequence updates by itself the graph after a node has been eliminat...
virtual NodeId nextNodeToEliminate()=0
returns the new node to be eliminated within the triangulation algorithm
virtual void addEdge(const NodeId first, const NodeId second)
inserts a new edge between two cliques
NodeProperty< NodeSet > __elim_cliques
the cliques formed by the elimination of the nodes
Size insert(const Val &val, const Priority &priority)
Inserts a new (a copy) element in the priority queue.
const NodeSet & clique(const NodeId idClique) const
returns the set of nodes included into a given clique
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
virtual StaticTriangulation * newFactory() const =0
returns a fresh triangulation of the same type as the current object but over an empty graph ...
virtual bool setGraph(UndiGraph *graph, const NodeProperty< Size > *dom_sizes)
sets a new graph to be triangulated
The base class for all elimination sequence algorithms used by triangulation algorithms.
The base class for all undirected edges.
bool __we_want_fill_ins
a boolean indicating if we want fill-ins list with the standard triangulation method ...
bool __has_fill_ins
indicates whether we actually computed fill-ins
bool __minimality_required
indicates whether the triangulation must be minimal
NodeId bound() const
returns a number n such that all node ids are strictly lower than n
base class for all non-incremental triangulation methods
const CliqueGraph * __junction_tree
the junction tree computed by the algorithm
void __computeEliminationTree()
returns an elimination tree from a triangulated graph
Base class for undirected graphs.
Definition: undiGraph.h:109
Size Idx
Type for indexes.
Definition: types.h:53
bool __has_elimination_tree
a boolean indicating whether the elimination tree has been computed
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
virtual void setGraph(const UndiGraph *graph, const NodeProperty< Size > *domsizes)
initialize the triangulation data structures for a new graph
void clear()
Removes all the elements, if any, from the set.
Definition: set_tpl.h:375
void __computeMaxPrimeMergings(const NodeId node, const NodeId from, std::vector< Arc > &merged_cliques, NodeSet &mark) const
used for computing the junction tree of the maximal prime subgraphs
std::size_t Size
In aGrUM, hashed values are unsigned long int.
Definition: types.h:48
EdgeSet __fill_ins
the fill-ins added during the whole triangulation process
Interface for all the triangulation methods.
Definition: triangulation.h:47
Size size() const noexcept
Returns the number of elements in the set.
Definition: set_tpl.h:701
value_type & insert(const Key &key, const Val &val)
Adds a new element (actually a copy of this element) into the hash table.
void __computeRecursiveThinning()
removes redondant fill-ins and compute proper elimination cliques and order
virtual const CliqueGraph & junctionTree()=0
returns the junction tree computed
std::vector< NodeId > __elim_order
the order in which nodes are eliminated by the algorithm
virtual void moveTriangulation(StaticTriangulation *triangulation)
assigns a new triangulation to the junction tree strategy during a move construction ...
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
virtual bool providesFillIns() const =0
indicates whether the fill-ins generated by the eliminated nodes, if needed, will be computed by the ...
CliqueGraph __elim_tree
the elimination tree computed by the algorithm
StaticTriangulation(const EliminationSequenceStrategy &elimSeq, const JunctionTreeStrategy &JTStrategy, bool minimality=false)
default constructor: without any graph
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
virtual void askFillIns(bool do_it)=0
if the elimination sequence is able to compute fill-ins, we indicate whether we want this feature to ...
An algorithm producing a junction given the elimination tree produced by a triangulation algorithm...