aGrUM  0.20.3
a C++ library for (probabilistic) graphical models
ShaferShenoyMNInference.h
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 /**
23  * @file
24  * @brief Implementation of Shafer-Shenoy's algorithm for inference
25  * in Markov Networks.
26  */
27 #ifndef GUM_SHAFER_SHENOY_MN_INFERENCE_H
28 #define GUM_SHAFER_SHENOY_MN_INFERENCE_H
29 
30 #include <utility>
31 
32 #include <agrum/agrum.h>
33 #include <agrum/tools/core/math/math_utils.h>
34 #include <agrum/MN/inference/tools/evidenceMNInference.h>
35 #include <agrum/MN/inference/tools/jointTargetedMNInference.h>
36 #include <agrum/tools/graphs/algorithms/triangulations/defaultTriangulation.h>
37 
38 namespace gum {
39 
40 
41  // the function used to combine two tables
42  template < typename GUM_SCALAR >
44  const Potential< GUM_SCALAR >& t2) {
45  return new Potential< GUM_SCALAR >(t1 * t2);
46  }
47 
48  // the function used to combine two tables
49  template < typename GUM_SCALAR >
50  INLINE static Potential< GUM_SCALAR >*
52  const Set< const DiscreteVariable* >& del_vars) {
53  return new Potential< GUM_SCALAR >(t1.margSumOut(del_vars));
54  }
55 
56 
57  /**
58  * @class ShaferShenoyMNInference ShaferShenoyMNInference.h
59  * <agrum/MN/inference/ShaferShenoyMNInference.h>
60  * @brief Implementation of Shafer-Shenoy's propagation algorithm
61  * for inference in Markov Networks
62  * @ingroup mn_inference
63  */
64  template < typename GUM_SCALAR >
68  public:
69  // ############################################################################
70  /// @name Constructors / Destructors
71  // ############################################################################
72  /// @{
73 
74  /// default constructor
76  bool use_binary_join_tree = true);
77 
78  /// destructor
80 
81  /// @}
82 
83 
84  // ############################################################################
85  /// @name Accessors / Modifiers
86  // ############################################################################
87  /// @{
88 
89  /// use a new triangulation algorithm
91 
92  /// returns the current join tree used
93  const JoinTree* joinTree();
94 
95  /// returns the current junction tree
96  const JunctionTree* junctionTree();
97 
98  /// returns the probability of evidence
100 
101  /// @}
102 
103 
104  protected:
105  /// check if the vars form a possible computable joint (can be redefined by
106  /// subclass)
107  virtual bool isExactJointComputable_(const NodeSet& vars) final;
109 
110  /// fired when the stage is changed
112 
113  /// fired after a new evidence is inserted
114  void onEvidenceAdded_(const NodeId id, bool isHardEvidence) final;
115 
116  /// fired before an evidence is removed
117  void onEvidenceErased_(const NodeId id, bool isHardEvidence) final;
118 
119  /// fired before all the evidence are erased
121 
122  /** @brief fired after an evidence is changed, in particular when its status
123  * (soft/hard) changes
124  *
125  * @param nodeId the node of the changed evidence
126  * @param hasChangedSoftHard true if the evidence has changed from Soft to
127  * Hard or from Hard to Soft
128  */
130 
131  /// fired after a new single target is inserted
132  /** @param id The target variable's id. */
134 
135  /// fired before a single target is removed
136  /** @param id The target variable's id. */
138 
139  /// fired after a new Markov net has been assigned to the engine
140  virtual void onMarkovNetChanged_(const IMarkovNet< GUM_SCALAR >* mn) final;
141 
142  /// fired after a new joint target is inserted
143  /** @param set The set of target variable's ids. */
144  void onJointTargetAdded_(const NodeSet& set) final;
145 
146  /// fired before a joint target is removed
147  /** @param set The set of target variable's ids. */
148  void onJointTargetErased_(const NodeSet& set) final;
149 
150  /// fired after all the nodes of the MN are added as single targets
152 
153  /// fired before a all the single targets are removed
155 
156  /// fired before a all the joint targets are removed
158 
159  /// fired before a all single and joint_targets are removed
160  void onAllTargetsErased_() final;
161 
162  /// prepares inference when the latter is in OutdatedStructure state
163  /** Note that the values of evidence are not necessarily
164  * known and can be changed between updateOutdatedStructure_ and
165  * makeMNInference_. */
167 
168  /// prepares inference when the latter is in OutdatedPotentials state
169  /** Note that the values of evidence are not necessarily
170  * known and can be changed between updateOutdatedStructure_ and
171  * makeMNInference_. */
173 
174  /// called when the inference has to be performed effectively
175  /** Once the inference is done, fillPosterior_ can be called. */
176  void makeInference_() final;
177 
178 
179  /// returns the posterior of a given variable
180  /** @param id The variable's id. */
182 
183  /// returns the posterior of a declared target set
184  /** @param set The set of ids of the variables whose joint posterior is
185  * looked for. */
187 
188  /** @brief asks derived classes for the joint posterior of a set of
189  * variables not declared as a joint target
190  *
191  * @param wanted_target The set of ids of the variables whose joint
192  * posterior is looked for.
193  * @param declared_target the joint target declared by the user that
194  * contains set */
196  const NodeSet& declared_target) final;
197 
198  /// returns a fresh potential equal to P(argument,evidence)
200 
201  /// returns a fresh potential equal to P(argument,evidence)
203 
204 
205  private:
206  typedef Set< const Potential< GUM_SCALAR >* > _PotentialSet_;
208 
209  /// the operator for performing the projections
211  const Set< const DiscreteVariable* >&){
213 
214  /// the operator for performing the combinations
216  const Potential< GUM_SCALAR >&){
218 
219  /// the triangulation class creating the junction tree used for inference
221 
222  /** @brief indicates whether we should transform junction trees into
223  * binary join trees */
225 
226  /// the undigraph extracted from the MN and used to construct the join tree
227  /** If all nodes are targets, this graph corresponds to the graph
228  * of the MN. Otherwise, it may be a subgraph of this moral graph. */
230 
231  /// the join (or junction) tree used to answer the last inference query
233 
234  /// the junction tree to answer the last inference query
236 
237  /// indicates whether a new join tree is needed for the next inference
238  /** when modifying the set of hard evidence, we can determine that
239  * the current JT is no more appropriate for inference. This variable
240  * enables us to keep track of this. */
241  bool _is_new_jt_needed_{true};
242 
243  /// a clique node used as a root in each connected component of _propagator_
244  /** For usual probabilistic inference, roots is useless. This is useful
245  * when computing the probability of evidence. In this case, we need to
246  * compute this probability in every connected component and multiply
247  * them to get the overall probability of evidence.
248  * @warning _roots_ should be computed only when evidenceProbability
249  * is called. */
251 
252  /// for each node of _reduced_graph_ (~ in the Markov net), associate an ID in
253  /// the JT
255 
257 
258  /// for each joint target, assign a clique in the JT that contains it
260 
261  /// the list of all potentials stored in the cliques
262  /** This structure contains a list for each clique in the join tree. If
263  * a clique did not received any potential, then its list is empty but
264  * the entry for the clique does exist. Note that clique potentials
265  * contain also soft evidence and the factors that were projected to
266  * remove their variables that received hard evidence. The product of all
267  * these potentials is precisely the potential stored into
268  * _clique_potentials_ */
270 
271  /// the potentials stored into the cliques by Shafer-Shenoy
272  /** For a given clique, there is an entry in _clique_potentials_ if and
273  * only if the clique received some potential(s). In this case, the
274  * potential stored is the combination of all the corresponding list of
275  * potentials in _clique_potentials_list_. */
277 
278  /// the list of all potentials stored in the separators after inferences
279  /** This structure contains all the arcs of the join tree (edges in both
280  * directions) whether the arc received any potential or not. */
282 
283  /// the set of potentials created for the last inference messages
284  /** This structure contains only the arcs on which potentials have
285  * been created.
286  * @warning Note that the factors that were projected due to hard
287  * evidence do not belong to this structure, they are kept in
288  * _hard_ev_projected_factors_. */
290 
291  /// the set of single posteriors computed during the last inference
292  /** the posteriors are owned by ShaferShenoyMNInference. */
294 
295  /// the set of set target posteriors computed during the last inference
296  /** the posteriors are owned by ShaferShenoyMNInference. */
298 
299  /** @brief the constants resulting from the projections of CPTs defined
300  * over only hard evidence nodes
301  * @TODO remove this constant and insert the notion of a constant into
302  * potentials/multidim arrays */
303  // NodeProperty< GUM_SCALAR > _constants_;
304 
305  /// indicates whether a message (from one clique to another) has been
306  /// computed
307  /** Here, all the messages, computed or not, are put into the property, only
308  * the Boolean makes the difference between messages computed and those that
309  * were not computed */
311 
312  /// the soft evidence stored in the cliques per their assigned node in the MN
313  /** This variable is useful for method updateOutdatedPotentials_: it
314  * enables to know which soft evidence should be removed/added into the
315  * cliques of the join tree.
316  * @warning These potentials are not owned by ShaferShenoyMNInference,
317  * they are only referenced by it. Only the cliques that contain evidence
318  * are filled in this structure. */
320 
321  /// the factors that were projected due to hard evidence nodes
322  /** For each factor containing the nodes that contain some
323  * hard evidence, assigns a new projected factor that does not contain
324  * these nodes anymore.
325  * @warning These potentials are owned by the inference class. */
327 
328  /// the hard evidence nodes which were projected in factors
330 
331  /// the possible types of evidence changes
333  {
337  };
338 
339  /** @brief indicates which nodes of the MN have evidence that changed
340  * since the last inference */
342 
343  /// for comparisons with 1 - epsilon
345 
346 
347  /// check whether a new join tree is really needed for the next inference
348  bool _isNewJTNeeded_() const;
349 
350  /// create a new junction tree as well as its related data structures
351  void _createNewJT_();
352 
353  /// sets the operator for performing the projections
355  *proj)(const Potential< GUM_SCALAR >&, const Set< const DiscreteVariable* >&));
356 
357  /// sets the operator for performing the combinations
359  const Potential< GUM_SCALAR >&));
360 
361  /// invalidate all the messages sent from a given clique
363 
364  /// invalidate all messages, posteriors and created potentials
366 
367  /// compute a root for each connected component of _propagator_
368  void _computeJoinTreeRoots_();
369 
370  /** @brief removes variables del_vars from a list of potentials and
371  * returns the resulting list */
373  Set< const DiscreteVariable* >& del_vars,
374  Set< const DiscreteVariable* >& kept_vars);
375 
376  /// creates the message sent by clique from_id to clique to_id
378 
379  /// actually perform the collect phase
381 
382  /// avoid copy constructors
384 
385  /// avoid copy operators
387  };
388 
389 
390 #ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
391  extern template class ShaferShenoyMNInference< double >;
392 #endif
393 
394 } /* namespace gum */
395 
396 #include <agrum/MN/inference/ShaferShenoyMNInference_tpl.h>
397 
398 #endif /* SHAFER_SHENOY_INFERENCE_H */
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:643