aGrUM 3.2.0
a C++ library for (probabilistic) graphical models
defaultJunctionTreeStrategy.cpp
Go to the documentation of this file.
1/****************************************************************************
2 * This file is part of the aGrUM/pyAgrum library. *
3 * *
4 * Copyright (c) 2005-2026 by *
5 * - Pierre-Henri WUILLEMIN(_at_LIP6) *
6 * - Christophe GONZALES(_at_AMU) *
7 * *
8 * The aGrUM/pyAgrum library is free software; you can redistribute it *
9 * and/or modify it under the terms of either : *
10 * *
11 * - the GNU Lesser General Public License as published by *
12 * the Free Software Foundation, either version 3 of the License, *
13 * or (at your option) any later version, *
14 * - the MIT license (MIT), *
15 * - or both in dual license, as here. *
16 * *
17 * (see https://agrum.gitlab.io/articles/dual-licenses-lgplv3mit.html) *
18 * *
19 * This aGrUM/pyAgrum library is distributed in the hope that it will be *
20 * useful, but WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
21 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES MERCHANTABILITY or FITNESS *
22 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
25 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
26 * OTHER DEALINGS IN THE SOFTWARE. *
27 * *
28 * See LICENCES for more details. *
29 * *
30 * SPDX-FileCopyrightText: Copyright 2005-2026 *
31 * - Pierre-Henri WUILLEMIN(_at_LIP6) *
32 * - Christophe GONZALES(_at_AMU) *
33 * SPDX-License-Identifier: LGPL-3.0-or-later OR MIT *
34 * *
35 * Contact : info_at_agrum_dot_org *
36 * homepage : http://agrum.gitlab.io *
37 * gitlab : https://gitlab.com/agrumery/agrum *
38 * *
39 ****************************************************************************/
40
41
48
49#include <numeric>
50
51#include <agrum/agrum.h>
52
55
56namespace gum {
57
58 // default constructor
62
63 // copy constructor
71
72 // move constructor
79
80 // destructor
85
86 // clone factory
90
91 // virtual copy constructor
94 if (tr == nullptr) {
95 return new DefaultJunctionTreeStrategy(*this);
96 } else {
97 // here, we need to assign new triangulation "tr" to the new strategy
98
99 // if there was already a triangulation associated with the current
100 // strategy, 2 cases can obtain:
101 // 1/ both _triangulation_ and tr point toward the same graph to be
102 // triangulated. In this case, no need to recompute anything
103 // 2/ they point toward different graphs. Then, we must indicate that
104 // the new strategy has not computed anything yet
105 if ((triangulation_ != nullptr) && (tr->originalGraph() == triangulation_->originalGraph())) {
106 auto new_strategy = new DefaultJunctionTreeStrategy(*this); // case 1/
107 new_strategy->triangulation_ = tr;
108 return new_strategy;
109 } else { // case 2/
110 auto new_strategy = new DefaultJunctionTreeStrategy;
111 new_strategy->setTriangulation(tr);
112 return new_strategy;
113 }
114 }
115 }
116
117 // indicates whether the junction tree strategy needs fill-ins to work
118 // properly
119 bool DefaultJunctionTreeStrategy::requiresFillIns() const { return false; }
120
121 // assign the triangulation to the junction tree strategy
126
127 // returns, for each node, the clique which was created by its deletion
129 // compute the junction tree only if it does not already exist
131
133 }
134
135 // returns the Id of the clique created by the elimination of a given
136 // node during the triangulation process */
138 // compute the junction tree only if it does not already exist
140
141 return _node_2_junction_clique_[id];
142 }
143
144 // returns the junction tree asked by the triangulation
146 // compute the junction tree only if it does not already exist
148
149 return _junction_tree_;
150 }
151
152 // resets the current junction tree strategy data structures
158
159 // computes a junction tree from an elimination tree
161 // if no triangulation is assigned to the strategy, we cannot compute
162 // the junction tree, so raise an exception
163 if (triangulation_ == nullptr)
165 "No triangulation has been assigned to "
166 "the DefaultJunctionTreeStrategy")
167
168 // copy the elimination tree into the junction tree
170
171 // mark all the edges of the junction tree to false
173
174 // create a vector indicating by which clique a given clique has been
175 // substituted during the transformation from the elimination tree to the
176 // junction tree. Assume that clique J of the elimination tree has been
177 // substituted by clique K of the elimination tree, and that clique J
178 // (resp. K) was the jth (resp. kth) one created during the triangulation
179 // process. Then, in the vector below, substitution[j] = k.
180 const std::vector< NodeId >& elim_order = triangulation_->eliminationOrder();
181
182 auto size = elim_order.size();
183 std::vector< NodeId > substitution(size);
184 std::iota(substitution.begin(), substitution.end(), 0);
185
186 // for all cliques C_i, from the last one created to the first one, check
187 // if there exists a parent C_j (a neighbor created before C_i) such that
188 // |C_j| = |C_i| + 1 and such that the edge is not marked. In this case,
189 // this means that C_j contains C_i. Hence, we should remove C_i, and link
190 // all of its neighbors to C_j. These links will be marked to true as no
191 // such neighbor can be included in C_j (and conversely).
192 if (size > 0) {
193 for (auto i = size; i >= 1; --i) {
194 const NodeId C_i = NodeId(i - 1);
195 const auto card_C_i_plus_1 = _junction_tree_.clique(C_i).size() + 1;
196
197 // search for C_j such that |C_j| = [C_i| + 1
198 NodeId C_j = C_i;
199
200 for (const auto C_jj: _junction_tree_.neighbours(C_i))
201 if ((C_i > C_jj) && !mark[Edge(C_jj, C_i)]
202 && (_junction_tree_.clique(C_jj).size() == card_C_i_plus_1)) {
203 // ok, here we found a parent such that |C_jj| = [C_i| + 1
204 C_j = C_jj;
205 _junction_tree_.eraseEdge(Edge(C_j, C_i));
206 break;
207 }
208
209 // if we found a C_j, link the neighbors of C_i to C_j
210 if (C_j != C_i) {
211 for (const auto nei: _junction_tree_.neighbours(C_i)) {
212 _junction_tree_.addEdge(C_j, nei);
213 mark.insert(Edge(C_j, nei), true);
214 }
215
216 // remove C_i
217 substitution[C_i] = C_j;
219 }
220 }
221 }
222
223 // compute the transitive closure of vector substitution
224 for (std::size_t i = 0; i < size; ++i)
225 substitution[i] = substitution[substitution[i]];
226
227 // using the transitive closure of vector substitution, compute for each
228 // node the clique of the junction tree that was created by its
229 // elimination during the triangulation
230 for (NodeId i = NodeId(0); i < size; ++i) {
231 _node_2_junction_clique_.insert(elim_order[i], substitution[i]);
232 }
233
234 _has_junction_tree_ = true;
235 }
236
237} /* namespace gum */
Basic graph of cliques.
Definition cliqueGraph.h:77
void eraseNode(const NodeId node) override
removes a given clique from the clique graph
void addEdge(NodeId first, NodeId second) override
inserts a new edge between two cliques
void eraseEdge(const Edge &edge) override
removes an edge (and its separator) from the clique graph
void clear() override
removes all the cliques and separators from the graph (as well as their adjacent edges)
const NodeSet & clique(const NodeId idClique) const
returns the set of nodes included into a given clique
An algorithm producing a junction given the elimination tree produced by a triangulation algorithm.
const NodeProperty< NodeId > & createdCliques() final
returns, for each node, the clique of the junction tree which was created by its deletion
bool _has_junction_tree_
a boolean indicating whether the junction tree has been constructed
DefaultJunctionTreeStrategy * newFactory() const final
create a clone not assigned to any triangulation algorithm
DefaultJunctionTreeStrategy * copyFactory(StaticTriangulation *triangulation=nullptr) const final
virtual copy constructor
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...
void _computeJunctionTree_()
computes a junction tree from an elimination tree
CliqueGraph _junction_tree_
the junction tree computed by the algorithm
void setTriangulation(StaticTriangulation *triangulation) final
assigns the triangulation to the junction tree strategy
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...
bool requiresFillIns() const final
indicates whether the junction tree strategy needs fill-ins to work properly
void clear() final
resets the current junction tree strategy data structures
const CliqueGraph & junctionTree() final
returns the junction tree computed
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 NodeSet & neighbours(NodeId id) const
returns the set of node neighbours to a given node
Edge(NodeId aN1, NodeId aN2)
constructs a new edge (aN1,aN2)
value_type & insert(const Key &key, const Val &val)
Adds a new element (actually a copy of this element) into the hash table.
JunctionTreeStrategy()
default constructor
StaticTriangulation * triangulation_
the triangulation to which the junction tree is associated
Size size() const noexcept
Returns the number of elements in the set.
Definition set_tpl.h:607
base class for all non-incremental triangulation methods
const UndiGraph * originalGraph() const
returns the graph to be triangulated
const std::vector< NodeId > & eliminationOrder() override
returns an elimination ordering compatible with the triangulated graph
const CliqueGraph & eliminationTree() override
returns the elimination tree of a compatible ordering
Exception : a looked-for element could not be found.
An algorithms producing a junction given the elimination tree produced by the triangulation algorithm...
#define GUM_ERROR(type, msg)
Definition exceptions.h:76
Size NodeId
Type for node ids.
HashTable< Edge, VAL > EdgeProperty
Property on graph elements.
HashTable< NodeId, VAL > NodeProperty
Property on graph elements.
gum is the global namespace for all aGrUM entities
Definition agrum.h:46
STL namespace.
base class for all non-incremental triangulations.