aGrUM  0.14.2
defaultJunctionTreeStrategy.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (C) 2005 by Christophe GONZALES and Pierre-Henri WUILLEMIN *
3  * {prenom.nom}_at_lip6.fr *
4  * *
5  * This program is free software; you can redistribute it and/or modify *
6  * it under the terms of the GNU General Public License as published by *
7  * the Free Software Foundation; either version 2 of the License, or *
8  * (at your option) any later version. *
9  * *
10  * This program is distributed in the hope that it will be useful, *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13  * GNU General Public License for more details. *
14  * *
15  * You should have received a copy of the GNU General Public License *
16  * along with this program; if not, write to the *
17  * Free Software Foundation, Inc., *
18  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19  ***************************************************************************/
27 #include <numeric>
28 
29 #include <agrum/agrum.h>
32 
33 namespace gum {
34 
35  // default constructor
37  // for debugging purposes
38  GUM_CONSTRUCTOR(DefaultJunctionTreeStrategy);
39  }
40 
41  // copy constructor
43  const DefaultJunctionTreeStrategy& from) :
48  // for debugging purposes
49  GUM_CONS_CPY(DefaultJunctionTreeStrategy);
50  }
51 
52  // move constructor
55  JunctionTreeStrategy(std::move(from)),
57  __junction_tree(std::move(from.__junction_tree)),
59  // for debugging purposes
60  GUM_CONS_MOV(DefaultJunctionTreeStrategy);
61  }
62 
63  // destructor
65  // for debugging purposes
66  GUM_DESTRUCTOR(DefaultJunctionTreeStrategy);
67  }
68 
69  // clone factory
71  return new DefaultJunctionTreeStrategy;
72  }
73 
74  // virtual copy constructor
77  if (tr == nullptr) {
78  return new DefaultJunctionTreeStrategy(*this);
79  } else {
80  // here, we need to assign new triangulation "tr" to the new strategy
81 
82  // if there was already a triangulation associated with the current
83  // strategy, 2 cases can obtain:
84  // 1/ both __triangulation and tr point toward the same graph to be
85  // triangulated. In this case, no need to recompute anything
86  // 2/ they point toward different graphs. Then, we must indicate that
87  // the new strategy has not computed anything yet
88  if ((_triangulation != nullptr)
89  && (tr->originalGraph() == _triangulation->originalGraph())) {
90  auto new_strategy = new DefaultJunctionTreeStrategy(*this); // case 1/
91  new_strategy->_triangulation = tr;
92  return new_strategy;
93  } else { // case 2/
94  auto new_strategy = new DefaultJunctionTreeStrategy;
95  new_strategy->setTriangulation(tr);
96  return new_strategy;
97  }
98  }
99  }
100 
101  // indicates whether the junction tree strategy needs fill-ins to work
102  // properly
103  bool DefaultJunctionTreeStrategy::requiresFillIns() const { return false; }
104 
105  // assign the triangulation to the junction tree strategy
107  clear();
108  _triangulation = tr;
109  }
110 
111  // returns, for each node, the clique which was created by its deletion
113  // compute the junction tree only if it does not already exist
115 
117  }
118 
119  // returns the Id of the clique created by the elimination of a given
120  // node during the triangulation process */
122  // compute the junction tree only if it does not already exist
124 
125  return __node_2_junction_clique[id];
126  }
127 
128  // returns the junction tree asked by the triangulation
130  // compute the junction tree only if it does not already exist
132 
133  return __junction_tree;
134  }
135 
136  // resets the current junction tree strategy data structures
138  __has_junction_tree = false;
140  __node_2_junction_clique.clear();
141  }
142 
143  // computes a junction tree from an elimination tree
145  // if no triangulation is assigned to the strategy, we cannot compute
146  // the junction tree, so raise an exception
147  if (_triangulation == nullptr)
149  "No triangulation has been assigned to "
150  "the DefaultJunctionTreeStrategy");
151 
152  // copy the elimination tree into the junction tree
154 
155  // mark all the edges of the junction tree to false
157 
158  // create a vector indicating by which clique a given clique has been
159  // substituted during the transformation from the elimination tree to the
160  // junction tree. Assume that clique J of the elmination tree has been
161  // substituted by clique K of the elimination tree, and that clique J
162  // (resp. K) was the jth (resp. kth) one created during the triangulation
163  // process. Then, in the vector below, substitution[j] = k.
164  const std::vector< NodeId >& elim_order = _triangulation->eliminationOrder();
165 
166  auto size = elim_order.size();
167  std::vector< NodeId > substitution(size);
168  std::iota(substitution.begin(), substitution.end(), 0);
169 
170  // for all cliques C_i, from the last one created to the first one, check
171  // if there exists a parent C_j (a neighbor created before C_i) such that
172  // |C_j| = |C_i| + 1 and such that the edge is not marked. In this case,
173  // this means that C_j contains C_i. Hence, we should remove C_i, and link
174  // all of its neighbors to C_j. These links will be marked to true as no
175  // such neighbor can be included in C_j (and conversely).
176  if (size > 0) {
177  for (auto i = size; i >= 1; --i) {
178  const NodeId C_i = NodeId(i - 1);
179  const auto card_C_i_plus_1 = __junction_tree.clique(C_i).size() + 1;
180 
181  // search for C_j such that |C_j| = [C_i| + 1
182  NodeId C_j = C_i;
183 
184  for (const auto C_jj : __junction_tree.neighbours(C_i))
185  if ((C_i > C_jj) && !mark[Edge(C_jj, C_i)]
186  && (__junction_tree.clique(C_jj).size() == card_C_i_plus_1)) {
187  // ok, here we found a parent such that |C_jj| = [C_i| + 1
188  C_j = C_jj;
189  __junction_tree.eraseEdge(Edge(C_j, C_i));
190  break;
191  }
192 
193  // if we found a C_j, link the neighbors of C_i to C_j
194  if (C_j != C_i) {
195  for (const auto nei : __junction_tree.neighbours(C_i)) {
196  __junction_tree.addEdge(C_j, nei);
197  mark.insert(Edge(C_j, nei), true);
198  }
199 
200  // remove C_i
201  substitution[C_i] = C_j;
203  }
204  }
205  }
206 
207  // compute the transitive closure of vector substitution
208  for (std::size_t i = 0; i < size; ++i)
209  substitution[i] = substitution[substitution[i]];
210 
211  // using the transitive closure of vector substitution, compute for each
212  // node the clique of the junction tree that was created by its
213  // elimination during the triangulation
214  for (NodeId i = NodeId(0); i < size; ++i) {
215  __node_2_junction_clique.insert(elim_order[i], substitution[i]);
216  }
217 
218  __has_junction_tree = true;
219  }
220 
221 } /* namespace gum */
virtual NodeId createdClique(const NodeId id) final
returns the Id of the clique of the junction tree created by the elimination of a given node during t...
const UndiGraph * originalGraph() const
returns the graph to be triangulated
virtual DefaultJunctionTreeStrategy * copyFactory(StaticTriangulation *triangulation=nullptr) const final
virtual copy constructor
virtual void eraseNode(const NodeId node)
removes a given clique from the clique graph
virtual DefaultJunctionTreeStrategy * newFactory() const final
create a clone not assigned to any triangulation algorithm
STL namespace.
virtual void clear()
removes all the cliques and separators from the graph (as well as their adjacent edges) ...
virtual void setTriangulation(StaticTriangulation *triangulation) final
assigns the triangulation to the junction tree strategy
gum is the global namespace for all aGrUM entities
Definition: agrum.h:25
StaticTriangulation * _triangulation
the triangulation to which the junction tree is associated
The class for generic Hash Tables.
Definition: hashTable.h:676
void __computeJunctionTree()
computes a junction tree from an elimination tree
const NodeSet & neighbours(const NodeId id) const
returns the set of edges adjacent to a given node
EdgeProperty< VAL > edgesProperty(VAL(*f)(const Edge &), Size size=0) const
a method to create a hashMap of VAL from a set of edges (using for every edge, say x...
const CliqueGraph & eliminationTree()
returns the elimination tree of a compatible ordering
NodeProperty< NodeId > __node_2_junction_clique
indicates which clique of the junction tree was created by the elimination of a given node (the key o...
virtual const NodeProperty< NodeId > & createdCliques() final
returns, for each node, the clique of the junction tree which was created by its deletion ...
const std::vector< NodeId > & eliminationOrder()
returns an elimination ordering compatible with the triangulated graph
virtual void eraseEdge(const Edge &edge)
removes an edge (and its separator) from the clique graph
Base Class for all the algorithms producing a junction given a set of cliques/subcliques resulting fr...
base class for all non-incremental triangulations.
virtual bool requiresFillIns() const final
indicates whether the junction tree strategy needs fill-ins to work properly
virtual void addEdge(const NodeId first, const NodeId second)
inserts a new edge between two cliques
const NodeSet & clique(const NodeId idClique) const
returns the set of nodes included into a given clique
Basic graph of cliques.
Definition: cliqueGraph.h:55
CliqueGraph __junction_tree
the junction tree computed by the algorithm
An algorithms producing a junction given the elimination tree produced by the triangulation algorithm...
The base class for all undirected edges.
virtual void clear() final
resets the current junction tree strategy data structures
base class for all non-incremental triangulation methods
virtual const CliqueGraph & junctionTree() final
returns the junction tree computed
Size size() const noexcept
Returns the number of elements in the set.
Definition: set_tpl.h:698
value_type & insert(const Key &key, const Val &val)
Adds a new element (actually a copy of this element) into the hash table.
bool __has_junction_tree
a boolean indicating whether the junction tree has been constructed
Size NodeId
Type for node ids.
Definition: graphElements.h:97
#define GUM_ERROR(type, msg)
Definition: exceptions.h:52
An algorithm producing a junction given the elimination tree produced by a triangulation algorithm...