aGrUM  0.21.0
a C++ library for (probabilistic) graphical models
defaultJunctionTreeStrategy.cpp
Go to the documentation of this file.
1 /**
2  *
3  * Copyright (c) 2005-2021 by Pierre-Henri WUILLEMIN(@LIP6) & Christophe GONZALES(@AMU)
4  * info_at_agrum_dot_org
5  *
6  * This library is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this library. If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 
22 /** @file
23  * @brief An algorithms producing a junction given the elimination tree
24  * produced by the triangulation algorithm
25  *
26  * @author Christophe GONZALES(@AMU) and Pierre-Henri WUILLEMIN(@LIP6)
27  */
28 
29 #include <numeric>
30 
31 #include <agrum/agrum.h>
32 #include <agrum/tools/graphs/algorithms/triangulations/junctionTreeStrategies/defaultJunctionTreeStrategy.h>
33 #include <agrum/tools/graphs/algorithms/triangulations/staticTriangulation.h>
34 
35 namespace gum {
36 
37  // default constructor
40  }
41 
42  // copy constructor
49  }
50 
51  // move constructor
57  }
58 
59  // destructor
62  ;
63  }
64 
65  // clone factory
67  return new DefaultJunctionTreeStrategy;
68  }
69 
70  // virtual copy constructor
73  if (tr == nullptr) {
74  return new DefaultJunctionTreeStrategy(*this);
75  } else {
76  // here, we need to assign new triangulation "tr" to the new strategy
77 
78  // if there was already a triangulation associated with the current
79  // strategy, 2 cases can obtain:
80  // 1/ both _triangulation_ and tr point toward the same graph to be
81  // triangulated. In this case, no need to recompute anything
82  // 2/ they point toward different graphs. Then, we must indicate that
83  // the new strategy has not computed anything yet
84  if ((triangulation_ != nullptr) && (tr->originalGraph() == triangulation_->originalGraph())) {
85  auto new_strategy = new DefaultJunctionTreeStrategy(*this); // case 1/
87  return new_strategy;
88  } else { // case 2/
91  return new_strategy;
92  }
93  }
94  }
95 
96  // indicates whether the junction tree strategy needs fill-ins to work
97  // properly
98  bool DefaultJunctionTreeStrategy::requiresFillIns() const { return false; }
99 
100  // assign the triangulation to the junction tree strategy
102  clear();
103  triangulation_ = tr;
104  }
105 
106  // returns, for each node, the clique which was created by its deletion
108  // compute the junction tree only if it does not already exist
110 
112  }
113 
114  // returns the Id of the clique created by the elimination of a given
115  // node during the triangulation process */
117  // compute the junction tree only if it does not already exist
119 
121  }
122 
123  // returns the junction tree asked by the triangulation
125  // compute the junction tree only if it does not already exist
127 
128  return _junction_tree_;
129  }
130 
131  // resets the current junction tree strategy data structures
133  _has_junction_tree_ = false;
136  }
137 
138  // computes a junction tree from an elimination tree
140  // if no triangulation is assigned to the strategy, we cannot compute
141  // the junction tree, so raise an exception
142  if (triangulation_ == nullptr)
144  "No triangulation has been assigned to "
145  "the DefaultJunctionTreeStrategy")
146 
147  // copy the elimination tree into the junction tree
149 
150  // mark all the edges of the junction tree to false
152 
153  // create a vector indicating by which clique a given clique has been
154  // substituted during the transformation from the elimination tree to the
155  // junction tree. Assume that clique J of the elimination tree has been
156  // substituted by clique K of the elimination tree, and that clique J
157  // (resp. K) was the jth (resp. kth) one created during the triangulation
158  // process. Then, in the vector below, substitution[j] = k.
160 
161  auto size = elim_order.size();
164 
165  // for all cliques C_i, from the last one created to the first one, check
166  // if there exists a parent C_j (a neighbor created before C_i) such that
167  // |C_j| = |C_i| + 1 and such that the edge is not marked. In this case,
168  // this means that C_j contains C_i. Hence, we should remove C_i, and link
169  // all of its neighbors to C_j. These links will be marked to true as no
170  // such neighbor can be included in C_j (and conversely).
171  if (size > 0) {
172  for (auto i = size; i >= 1; --i) {
173  const NodeId C_i = NodeId(i - 1);
174  const auto card_C_i_plus_1 = _junction_tree_.clique(C_i).size() + 1;
175 
176  // search for C_j such that |C_j| = [C_i| + 1
177  NodeId C_j = C_i;
178 
179  for (const auto C_jj: _junction_tree_.neighbours(C_i))
180  if ((C_i > C_jj) && !mark[Edge(C_jj, C_i)]
182  // ok, here we found a parent such that |C_jj| = [C_i| + 1
183  C_j = C_jj;
185  break;
186  }
187 
188  // if we found a C_j, link the neighbors of C_i to C_j
189  if (C_j != C_i) {
190  for (const auto nei: _junction_tree_.neighbours(C_i)) {
192  mark.insert(Edge(C_j, nei), true);
193  }
194 
195  // remove C_i
196  substitution[C_i] = C_j;
198  }
199  }
200  }
201 
202  // compute the transitive closure of vector substitution
203  for (std::size_t i = 0; i < size; ++i)
205 
206  // using the transitive closure of vector substitution, compute for each
207  // node the clique of the junction tree that was created by its
208  // elimination during the triangulation
209  for (NodeId i = NodeId(0); i < size; ++i) {
211  }
212 
213  _has_junction_tree_ = true;
214  }
215 
216 } /* namespace gum */
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:643