aGrUM  0.20.2
a C++ library for (probabilistic) graphical models
ShaferShenoyInference.h
Go to the documentation of this file.
1 /**
2  *
3  * Copyright 2005-2020 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 Bayesian networks.
26  */
27 #ifndef GUM_SHAFER_SHENOY_INFERENCE_H
28 #define GUM_SHAFER_SHENOY_INFERENCE_H
29 
30 #include <utility>
31 
32 #include <agrum/tools/core/math/math_utils.h>
33 #include <agrum/BN/algorithms/barrenNodesFinder.h>
34 #include <agrum/BN/inference/tools/evidenceInference.h>
35 #include <agrum/BN/inference/tools/jointTargetedInference.h>
36 #include <agrum/agrum.h>
37 #include <agrum/tools/graphs/algorithms/triangulations/defaultTriangulation.h>
38 
39 namespace gum {
40 
41 
42  // the function used to combine two tables
43  template < typename GUM_SCALAR >
44  INLINE static Potential< GUM_SCALAR >*
46  const Potential< GUM_SCALAR >& t2) {
47  return new Potential< GUM_SCALAR >(t1 * t2);
48  }
49 
50  // the function used to combine two tables
51  template < typename GUM_SCALAR >
52  INLINE static Potential< GUM_SCALAR >*
54  const Set< const DiscreteVariable* >& del_vars) {
55  return new Potential< GUM_SCALAR >(t1.margSumOut(del_vars));
56  }
57 
58 
59  /**
60  * @class ShaferShenoyInference ShaferShenoyInference.h
61  * <agrum/BN/inference/ShaferShenoyInference.h>
62  * @brief Implementation of Shafer-Shenoy's propagation algorithm
63  * for inference in Bayesian networks
64  * @ingroup bn_inference
65  */
66  template < typename GUM_SCALAR >
69  public EvidenceInference< GUM_SCALAR > {
70  public:
71  // ############################################################################
72  /// @name Constructors / Destructors
73  // ############################################################################
74  /// @{
75 
76  /// default constructor
77  explicit ShaferShenoyInference(const IBayesNet< GUM_SCALAR >* BN,
80  bool use_binary_join_tree = true);
81 
82  /// destructor
84 
85  /// @}
86 
87 
88  // ############################################################################
89  /// @name Accessors / Modifiers
90  // ############################################################################
91  /// @{
92 
93  /// use a new triangulation algorithm
95 
96  /// sets how we determine barren nodes
97  /** Barren nodes are unnecessary for probability inference, so they can
98  * be safely discarded in this case (type = FIND_BARREN_NODES). This
99  * speeds-up inference. However, there are some cases in which we do not
100  * want to remove barren nodes, typically when we want to answer queries
101  * such as Most Probable Explanations (MPE). */
103 
104  /// returns the current join tree used
105  /** Lazy Propagation does not use a junction tree but a binary join tree
106  * because this may enable faster inferences. So do not be surprised to
107  * see that somes cliques are contained into others in this tree. */
108  const JoinTree* joinTree();
109 
110  /// returns the current junction tree
111  /** Lazy Propagation does not use a junction tree but a binary join tree
112  * because this may enable faster inferences. This method return the junction
113  * tree, before optimizations
114  **/
115  const JunctionTree* junctionTree();
116 
117  /// returns the probability of evidence
119 
120  /// @}
121 
122 
123  protected:
124  /// fired when the stage is changed
126 
127  /// fired after a new evidence is inserted
128  void onEvidenceAdded_(const NodeId id, bool isHardEvidence) final;
129 
130  /// fired before an evidence is removed
131  void onEvidenceErased_(const NodeId id, bool isHardEvidence) final;
132 
133  /// fired before all the evidence are erased
135 
136  /** @brief fired after an evidence is changed, in particular when its status
137  * (soft/hard) changes
138  *
139  * @param nodeId the node of the changed evidence
140  * @param hasChangedSoftHard true if the evidence has changed from Soft to
141  * Hard or from Hard to Soft
142  */
144 
145  /// fired after a new single target is inserted
146  /** @param id The target variable's id. */
148 
149  /// fired before a single target is removed
150  /** @param id The target variable's id. */
152 
153  /// fired after a new Bayes net has been assigned to the engine
154  virtual void onModelChanged_(const GraphicalModel* bn) final;
155 
156  /// fired after a new joint target is inserted
157  /** @param set The set of target variable's ids. */
158  void onJointTargetAdded_(const NodeSet& set) final;
159 
160  /// fired before a joint target is removed
161  /** @param set The set of target variable's ids. */
162  void onJointTargetErased_(const NodeSet& set) final;
163 
164  /// fired after all the nodes of the BN are added as single targets
166 
167  /// fired before a all the single targets are removed
169 
170  /// fired before a all the joint targets are removed
172 
173  /// fired before a all single and joint_targets are removed
174  void onAllTargetsErased_() final;
175 
176  /// prepares inference when the latter is in OutdatedStructure state
177  /** Note that the values of evidence are not necessarily
178  * known and can be changed between updateOutdatedStructure_ and
179  * makeInference_. */
181 
182  /// prepares inference when the latter is in OutdatedPotentials state
183  /** Note that the values of evidence are not necessarily
184  * known and can be changed between updateOutdatedStructure_ and
185  * makeInference_. */
187 
188  /// called when the inference has to be performed effectively
189  /** Once the inference is done, fillPosterior_ can be called. */
190  void makeInference_() final;
191 
192 
193  /// returns the posterior of a given variable
194  /** @param id The variable's id. */
196 
197  /// returns the posterior of a declared target set
198  /** @param set The set of ids of the variables whose joint posterior is
199  * looked for. */
201 
202  /** @brief asks derived classes for the joint posterior of a set of
203  * variables not declared as a joint target
204  *
205  * @param wanted_target The set of ids of the variables whose joint
206  * posterior is looked for.
207  * @param declared_target the joint target declared by the user that
208  * contains set */
209  const Potential< GUM_SCALAR >&
211  const NodeSet& declared_target) final;
212 
213  /// returns a fresh potential equal to P(argument,evidence)
215 
216  /// returns a fresh potential equal to P(argument,evidence)
218 
219 
220  private:
221  typedef Set< const Potential< GUM_SCALAR >* > PotentialSet__;
222  typedef SetIteratorSafe< const Potential< GUM_SCALAR >* >
224 
225 
226  /// the type of barren nodes computation we wish
228 
229  /// the operator for performing the projections
231  const Potential< GUM_SCALAR >&,
232  const Set< const DiscreteVariable* >&){SSNewprojPotential};
233 
234  /// the operator for performing the combinations
236  const Potential< GUM_SCALAR >&){
238 
239  /// the triangulation class creating the junction tree used for inference
241 
242  /** @brief indicates whether we should transform junction trees into
243  * binary join trees */
245 
246  /// the undigraph extracted from the BN and used to construct the join tree
247  /** If all nodes are targets, this graph corresponds to the moral graph
248  * of the BN. Otherwise, it may be a subgraph of this moral graph. For
249  * instance if the BN is A->B->C and only B is a target, graph__ will be
250  * equal to A-B if we exploit barren nodes (C is a barren node and,
251  * therefore, can be removed for inference). */
253 
254  /// the join (or junction) tree used to answer the last inference query
255  JoinTree* JT__{nullptr};
256 
257  /// the junction tree to answer the last inference query
259 
260  /// indicates whether a new join tree is needed for the next inference
261  /** when modifying the set of hard evidence, we can determine that
262  * the current JT is no more appropriate for inference. This variable
263  * enables us to keep track of this. */
264  bool is_new_jt_needed__{true};
265 
266  /// a clique node used as a root in each connected component of JT__
267  /** For usual probabilistic inference, roots is useless. This is useful
268  * when computing the probability of evidence. In this case, we need to
269  * compute this probability in every connected component and multiply
270  * them to get the overall probability of evidence.
271  * @warning roots__ should be computed only when evidenceProbability
272  * is called. */
274 
275  /// for each node of graph__ (~ in the Bayes net), associate an ID in the JT
277 
278  /// for each set target, assign a clique in the JT that contains it
280 
281  /// the list of all potentials stored in the cliques
282  /** This structure contains a list for each clique in the join tree. If
283  * a clique did not received any potential, then its list is empty but
284  * the entry for the clique does exist. Note that clique potentials
285  * contain also soft evidence and the CPTs that were projected to
286  * remove their variables that received hard evidence. The product of all
287  * these potentials is precisely the potential stored into
288  * clique_ss_potential__ */
290 
291  /// the potentials stored into the cliques by Shafer-Shenoy
292  /** For a given clique, there is an entry in clique_ss_potential__ if and
293  * only if the clique received some potential(s). In this case, the
294  * potential stored is the combination of all the corresponding list of
295  * potentials in clique_potentials__. */
297 
298  /// the list of all potentials stored in the separators after inferences
299  /** This structure contains all the arcs of the join tree (edges in both
300  * directions) whether the arc received any potential or not. */
302 
303  /// the set of potentials created for the last inference messages
304  /** This structure contains only the arcs on which potentials have
305  * been created.
306  * @warning Note that the CPTs that were projected due to hard
307  * evidence do not belong to this structure, they are kept in
308  * hard_ev_projected_CPTs__. */
310 
311  /// the set of single posteriors computed during the last inference
312  /** the posteriors are owned by ShaferShenoyInference. */
314 
315  /// the set of set target posteriors computed during the last inference
316  /** the posteriors are owned by ShaferShenoyInference. */
318 
319  /** @brief the constants resulting from the projections of CPTs defined
320  * over only hard evidence nodes
321  * @TODO remove this constant and insert the notion of a constant into
322  * potentials/multidim arrays */
324 
325  /// indicates whether a message (from one clique to another) has been
326  /// computed
327  /** Here, all the messages, computed or not, are put into the property, only
328  * the Boolean makes the difference between messages computed and those that
329  * were not computed */
331 
332  /// the soft evidence stored in the cliques per their assigned node in the BN
333  /** This variable is useful for method updateOutdatedPotentials_: it
334  * enables to know which soft evidence should be removed/added into the
335  * cliques of the join tree.
336  * @warning These potentials are not owned by ShaferShenoyInference,
337  * they are only referenced by it. Only the cliques that contain evidence
338  * are filled in this structure. */
340 
341  /// the CPTs that were projected due to hard evidence nodes
342  /** For each node whose CPT is defined over some nodes that contain some
343  * hard evidence, assigns a new projected CPT that does not contain
344  * these nodes anymore.
345  * @warning These potentials are owned by LayPropagation. */
347 
348  /// the hard evidence nodes which were projected in CPTs
350 
351  /// the possible types of evidence changes
353  {
357  };
358 
359  /** @brief indicates which nodes of the BN have evidence that changed
360  * since the last inference */
362 
363  /// for comparisons with 1 - epsilon
365 
366 
367  /// check whether a new join tree is really needed for the next inference
368  bool isNewJTNeeded__() const;
369 
370  /// create a new junction tree as well as its related data structures
371  void createNewJT__();
372  /// sets the operator for performing the projections
374  Potential< GUM_SCALAR >* (*proj)(const Potential< GUM_SCALAR >&,
375  const Set< const DiscreteVariable* >&));
376 
377  /// sets the operator for performing the combinations
379  *comb)(const Potential< GUM_SCALAR >&, const Potential< GUM_SCALAR >&));
380 
381  /// invalidate all the messages sent from a given clique
383  NodeId to,
385 
386  /// invalidate all messages, posteriors and created potentials
388 
389  /// compute a root for each connected component of JT__
390  void computeJoinTreeRoots__();
391 
392  // remove barren variables and return the newly created projected potentials
395  Set< const DiscreteVariable* >& del_vars);
396 
397  /** @brief removes variables del_vars from a list of potentials and
398  * returns the resulting list */
400  Set< const DiscreteVariable* >& del_vars,
401  Set< const DiscreteVariable* >& kept_vars);
402 
403  /// creates the message sent by clique from_id to clique to_id
405 
406  /// actually perform the collect phase
408 
409  /// avoid copy constructors
411 
412  /// avoid copy operators
415  };
416 
417 
418 #ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
419  extern template class ShaferShenoyInference< double >;
420 #endif
421 
422 
423 } /* namespace gum */
424 
425 #include <agrum/BN/inference/ShaferShenoyInference_tpl.h>
426 
427 #endif /* SHAFER_SHENOY_INFERENCE_H */
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:669