aGrUM  0.20.2
a C++ library for (probabilistic) graphical models
ShaferShenoyMNInference.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 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 >
43  INLINE static Potential< GUM_SCALAR >*
45  const Potential< GUM_SCALAR >& t2) {
46  return new Potential< GUM_SCALAR >(t1 * t2);
47  }
48 
49  // the function used to combine two tables
50  template < typename GUM_SCALAR >
51  INLINE static Potential< GUM_SCALAR >*
53  const Set< const DiscreteVariable* >& del_vars) {
54  return new Potential< GUM_SCALAR >(t1.margSumOut(del_vars));
55  }
56 
57 
58  /**
59  * @class ShaferShenoyMNInference ShaferShenoyMNInference.h
60  * <agrum/MN/inference/ShaferShenoyMNInference.h>
61  * @brief Implementation of Shafer-Shenoy's propagation algorithm
62  * for inference in Markov Networks
63  * @ingroup mn_inference
64  */
65  template < typename GUM_SCALAR >
69  public:
70  // ############################################################################
71  /// @name Constructors / Destructors
72  // ############################################################################
73  /// @{
74 
75  /// default constructor
77  bool use_binary_join_tree = true);
78 
79  /// destructor
81 
82  /// @}
83 
84 
85  // ############################################################################
86  /// @name Accessors / Modifiers
87  // ############################################################################
88  /// @{
89 
90  /// use a new triangulation algorithm
92 
93  /// returns the current join tree used
94  const JoinTree* joinTree();
95 
96  /// returns the current junction tree
97  const JunctionTree* junctionTree();
98 
99  /// returns the probability of evidence
101 
102  /// @}
103 
104 
105  protected:
106  /// check if the vars form a possible computable joint (can be redefined by
107  /// subclass)
108  virtual bool isExactJointComputable_(const NodeSet& vars) final;
110 
111  /// fired when the stage is changed
113 
114  /// fired after a new evidence is inserted
115  void onEvidenceAdded_(const NodeId id, bool isHardEvidence) final;
116 
117  /// fired before an evidence is removed
118  void onEvidenceErased_(const NodeId id, bool isHardEvidence) final;
119 
120  /// fired before all the evidence are erased
122 
123  /** @brief fired after an evidence is changed, in particular when its status
124  * (soft/hard) changes
125  *
126  * @param nodeId the node of the changed evidence
127  * @param hasChangedSoftHard true if the evidence has changed from Soft to
128  * Hard or from Hard to Soft
129  */
131 
132  /// fired after a new single target is inserted
133  /** @param id The target variable's id. */
135 
136  /// fired before a single target is removed
137  /** @param id The target variable's id. */
139 
140  /// fired after a new Markov net has been assigned to the engine
141  virtual void onMarkovNetChanged_(const IMarkovNet< GUM_SCALAR >* mn) final;
142 
143  /// fired after a new joint target is inserted
144  /** @param set The set of target variable's ids. */
145  void onJointTargetAdded_(const NodeSet& set) final;
146 
147  /// fired before a joint target is removed
148  /** @param set The set of target variable's ids. */
149  void onJointTargetErased_(const NodeSet& set) final;
150 
151  /// fired after all the nodes of the MN are added as single targets
153 
154  /// fired before a all the single targets are removed
156 
157  /// fired before a all the joint targets are removed
159 
160  /// fired before a all single and joint_targets are removed
161  void onAllTargetsErased_() final;
162 
163  /// prepares inference when the latter is in OutdatedStructure state
164  /** Note that the values of evidence are not necessarily
165  * known and can be changed between updateOutdatedStructure_ and
166  * makeMNInference_. */
168 
169  /// prepares inference when the latter is in OutdatedPotentials state
170  /** Note that the values of evidence are not necessarily
171  * known and can be changed between updateOutdatedStructure_ and
172  * makeMNInference_. */
174 
175  /// called when the inference has to be performed effectively
176  /** Once the inference is done, fillPosterior_ can be called. */
177  void makeInference_() final;
178 
179 
180  /// returns the posterior of a given variable
181  /** @param id The variable's id. */
183 
184  /// returns the posterior of a declared target set
185  /** @param set The set of ids of the variables whose joint posterior is
186  * looked for. */
188 
189  /** @brief asks derived classes for the joint posterior of a set of
190  * variables not declared as a joint target
191  *
192  * @param wanted_target The set of ids of the variables whose joint
193  * posterior is looked for.
194  * @param declared_target the joint target declared by the user that
195  * contains set */
196  const Potential< GUM_SCALAR >&
198  const NodeSet& declared_target) final;
199 
200  /// returns a fresh potential equal to P(argument,evidence)
202 
203  /// returns a fresh potential equal to P(argument,evidence)
205 
206 
207  private:
208  typedef Set< const Potential< GUM_SCALAR >* > PotentialSet__;
209  typedef SetIteratorSafe< const Potential< GUM_SCALAR >* >
211 
212  /// the operator for performing the projections
214  const Potential< GUM_SCALAR >&,
215  const Set< const DiscreteVariable* >&){SSNewMNprojPotential};
216 
217  /// the operator for performing the combinations
219  const Potential< GUM_SCALAR >&){
221 
222  /// the triangulation class creating the junction tree used for inference
224 
225  /** @brief indicates whether we should transform junction trees into
226  * binary join trees */
228 
229  /// the undigraph extracted from the MN and used to construct the join tree
230  /** If all nodes are targets, this graph corresponds to the graph
231  * of the MN. Otherwise, it may be a subgraph of this moral graph. */
233 
234  /// the join (or junction) tree used to answer the last inference query
236 
237  /// the junction tree to answer the last inference query
239 
240  /// indicates whether a new join tree is needed for the next inference
241  /** when modifying the set of hard evidence, we can determine that
242  * the current JT is no more appropriate for inference. This variable
243  * enables us to keep track of this. */
244  bool is_new_jt_needed__{true};
245 
246  /// a clique node used as a root in each connected component of propagator__
247  /** For usual probabilistic inference, roots is useless. This is useful
248  * when computing the probability of evidence. In this case, we need to
249  * compute this probability in every connected component and multiply
250  * them to get the overall probability of evidence.
251  * @warning roots__ should be computed only when evidenceProbability
252  * is called. */
254 
255  /// for each node of reduced_graph__ (~ in the Markov net), associate an ID in
256  /// the JT
258 
260 
261  /// for each joint target, assign a clique in the JT that contains it
263 
264  /// the list of all potentials stored in the cliques
265  /** This structure contains a list for each clique in the join tree. If
266  * a clique did not received any potential, then its list is empty but
267  * the entry for the clique does exist. Note that clique potentials
268  * contain also soft evidence and the factors that were projected to
269  * remove their variables that received hard evidence. The product of all
270  * these potentials is precisely the potential stored into
271  * clique_potentials__ */
273 
274  /// the potentials stored into the cliques by Shafer-Shenoy
275  /** For a given clique, there is an entry in clique_potentials__ if and
276  * only if the clique received some potential(s). In this case, the
277  * potential stored is the combination of all the corresponding list of
278  * potentials in clique_potentials_list__. */
280 
281  /// the list of all potentials stored in the separators after inferences
282  /** This structure contains all the arcs of the join tree (edges in both
283  * directions) whether the arc received any potential or not. */
285 
286  /// the set of potentials created for the last inference messages
287  /** This structure contains only the arcs on which potentials have
288  * been created.
289  * @warning Note that the factors that were projected due to hard
290  * evidence do not belong to this structure, they are kept in
291  * hard_ev_projected_factors__. */
293 
294  /// the set of single posteriors computed during the last inference
295  /** the posteriors are owned by ShaferShenoyMNInference. */
297 
298  /// the set of set target posteriors computed during the last inference
299  /** the posteriors are owned by ShaferShenoyMNInference. */
301 
302  /** @brief the constants resulting from the projections of CPTs defined
303  * over only hard evidence nodes
304  * @TODO remove this constant and insert the notion of a constant into
305  * potentials/multidim arrays */
306  // NodeProperty< GUM_SCALAR > constants__;
307 
308  /// indicates whether a message (from one clique to another) has been
309  /// computed
310  /** Here, all the messages, computed or not, are put into the property, only
311  * the Boolean makes the difference between messages computed and those that
312  * were not computed */
314 
315  /// the soft evidence stored in the cliques per their assigned node in the MN
316  /** This variable is useful for method updateOutdatedPotentials_: it
317  * enables to know which soft evidence should be removed/added into the
318  * cliques of the join tree.
319  * @warning These potentials are not owned by ShaferShenoyMNInference,
320  * they are only referenced by it. Only the cliques that contain evidence
321  * are filled in this structure. */
323 
324  /// the factors that were projected due to hard evidence nodes
325  /** For each factor containing the nodes that contain some
326  * hard evidence, assigns a new projected factor that does not contain
327  * these nodes anymore.
328  * @warning These potentials are owned by the inference class. */
329  HashTable< NodeSet, const Potential< GUM_SCALAR >* >
331 
332  /// the hard evidence nodes which were projected in factors
334 
335  /// the possible types of evidence changes
337  {
341  };
342 
343  /** @brief indicates which nodes of the MN have evidence that changed
344  * since the last inference */
346 
347  /// for comparisons with 1 - epsilon
349 
350 
351  /// check whether a new join tree is really needed for the next inference
352  bool isNewJTNeeded__() const;
353 
354  /// create a new junction tree as well as its related data structures
355  void createNewJT__();
356 
357  /// sets the operator for performing the projections
359  Potential< GUM_SCALAR >* (*proj)(const Potential< GUM_SCALAR >&,
360  const Set< const DiscreteVariable* >&));
361 
362  /// sets the operator for performing the combinations
364  *comb)(const Potential< GUM_SCALAR >&, const Potential< GUM_SCALAR >&));
365 
366  /// invalidate all the messages sent from a given clique
368  NodeId to,
370 
371  /// invalidate all messages, posteriors and created potentials
373 
374  /// compute a root for each connected component of propagator__
375  void computeJoinTreeRoots__();
376 
377  /** @brief removes variables del_vars from a list of potentials and
378  * returns the resulting list */
380  Set< const DiscreteVariable* >& del_vars,
381  Set< const DiscreteVariable* >& kept_vars);
382 
383  /// creates the message sent by clique from_id to clique to_id
385 
386  /// actually perform the collect phase
388 
389  /// avoid copy constructors
391 
392  /// avoid copy operators
395  };
396 
397 
398 #ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
399  extern template class ShaferShenoyMNInference< double >;
400 #endif
401 
402 } /* namespace gum */
403 
404 #include <agrum/MN/inference/ShaferShenoyMNInference_tpl.h>
405 
406 #endif /* SHAFER_SHENOY_INFERENCE_H */
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:669