aGrUM  0.20.2
a C++ library for (probabilistic) graphical models
variableElimination.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 a variable elimination algorithm
25  * for inference in Bayesian networks.
26  *
27  * @author Christophe GONZALES(@AMU) and Pierre-Henri WUILLEMIN(@LIP6)
28  */
29 #ifndef GUM_VARIABLE_ELIMINATION_H
30 #define GUM_VARIABLE_ELIMINATION_H
31 
32 #include <utility>
33 
34 #include <agrum/tools/core/math/math_utils.h>
35 #include <agrum/BN/algorithms/barrenNodesFinder.h>
36 #include <agrum/BN/inference/tools/jointTargetedInference.h>
37 #include <agrum/BN/inference/tools/relevantPotentialsFinderType.h>
38 #include <agrum/agrum.h>
39 #include <agrum/tools/graphs/algorithms/triangulations/defaultTriangulation.h>
40 
41 namespace gum {
42 
43 
44  // the function used to combine two tables
45  template < typename GUM_SCALAR >
46  INLINE static Potential< GUM_SCALAR >*
48  const Potential< GUM_SCALAR >& t2) {
49  return new Potential< GUM_SCALAR >(t1 * t2);
50  }
51 
52  // the function used to combine two tables
53  template < typename GUM_SCALAR >
54  INLINE static Potential< GUM_SCALAR >*
56  const Set< const DiscreteVariable* >& del_vars) {
57  return new Potential< GUM_SCALAR >(t1.margSumOut(del_vars));
58  }
59 
60 
61  /**
62  * @class VariableElimination VariableElimination.h
63  * <agrum/BN/inference/variableElimination.h>
64  * @brief Implementation of a Shafer-Shenoy's-like version of lazy
65  * propagation for inference in Bayesian networks
66  * @ingroup bn_inference
67  */
68  template < typename GUM_SCALAR >
70  public:
71  // ############################################################################
72  /// @name Constructors / Destructors
73  // ############################################################################
74  /// @{
75 
76  /// default constructor
77  explicit VariableElimination(
78  const IBayesNet< GUM_SCALAR >* BN,
82 
83  /// avoid copy constructors
85 
86  /// avoid copy operators
89  = delete;
90 
91  /// destructor
93 
94  /// @}
95 
96 
97  // ############################################################################
98  /// @name Accessors / Modifiers
99  // ############################################################################
100  /// @{
101 
102  /// use a new triangulation algorithm
104 
105  /// sets how we determine the relevant potentials to combine
106  /** When a clique sends a message to a separator, it first constitute the
107  * set of the potentials it contains and of the potentials contained in the
108  * messages it received. If RelevantPotentialsFinderType = FIND_ALL,
109  * all these potentials are combined and projected to produce the message
110  * sent to the separator.
111  * If RelevantPotentialsFinderType = DSEP_BAYESBALL_NODES, then only the
112  * set of potentials d-connected to the variables of the separator are kept
113  * for combination and projection. */
115 
116  /// sets how we determine barren nodes
117  /** Barren nodes are unnecessary for probability inference, so they can
118  * be safely discarded in this case (type = FIND_BARREN_NODES). This
119  * speeds-up inference. However, there are some cases in which we do not
120  * want to remove barren nodes, typically when we want to answer queries
121  * such as Most Probable Explanations (MPE). */
123 
124  /// returns the join tree used for compute the posterior of node id
126 
127  /// @}
128 
129 
130  protected:
131  /// fired when the stage is changed
133 
134  /// fired after a new evidence is inserted
135  void onEvidenceAdded_(const NodeId id, bool isHardEvidence) final;
136 
137  /// fired before an evidence is removed
138  void onEvidenceErased_(const NodeId id, bool isHardEvidence) final;
139 
140  /// fired before all the evidence are erased
142 
143  /** @brief fired after an evidence is changed, in particular when its status
144  * (soft/hard) changes
145  *
146  * @param nodeId the node of the changed evidence
147  * @param hasChangedSoftHard true if the evidence has changed from Soft to
148  * Hard or from Hard to Soft
149  */
151 
152  /// fired after a new single target is inserted
153  /** @param id The target variable's id. */
155 
156  /// fired before a single target is removed
157  /** @param id The target variable's id. */
159 
160  /// fired after a new Bayes net has been assigned to the engine
161  virtual void onModelChanged_(const GraphicalModel* bn) final;
162 
163  /// fired after a new joint target is inserted
164  /** @param set The set of target variable's ids. */
165  void onJointTargetAdded_(const NodeSet& set) final;
166 
167  /// fired before a joint target is removed
168  /** @param set The set of target variable's ids. */
169  void onJointTargetErased_(const NodeSet& set) final;
170 
171  /// fired after all the nodes of the BN are added as single targets
173 
174  /// fired before a all the single targets are removed
176 
177  /// fired before a all the joint targets are removed
179 
180  /// fired before a all single and joint_targets are removed
181  void onAllTargetsErased_() final;
182 
183  /// prepares inference when the latter is in OutdatedStructure state
184  /** Note that the values of evidence are not necessarily
185  * known and can be changed between updateOutdatedStructure_ and
186  * makeInference_. */
188 
189  /// prepares inference when the latter is in OutdatedPotentials state
190  /** Note that the values of evidence are not necessarily
191  * known and can be changed between updateOutdatedPotentials_ and
192  * makeInference_. */
194 
195  /// called when the inference has to be performed effectively
196  /** Once the inference is done, fillPosterior_ can be called. */
197  void makeInference_() final;
198 
199 
200  /// returns the posterior of a given variable
201  /** @param id The variable's id. */
203 
204  /// returns the posterior of a declared target set
205  /** @param set The set of ids of the variables whose joint posterior is
206  * looked for. */
208 
209  /** @brief asks derived classes for the joint posterior of a set of
210  * variables not declared as a joint target
211  *
212  * @param wanted_target The set of ids of the variables whose joint
213  * posterior is looked for.
214  * @param declared_target the joint target declared by the user that contains
215  * set */
216  const Potential< GUM_SCALAR >&
218  const NodeSet& declared_target) final;
219 
220  /// returns a fresh potential equal to P(argument,evidence)
222 
223  /// returns a fresh potential equal to P(argument,evidence)
225 
226 
227  private:
228  typedef Set< const Potential< GUM_SCALAR >* > PotentialSet__;
229  typedef SetIteratorSafe< const Potential< GUM_SCALAR >* >
231 
232 
233  /// the type of relevant potential finding algorithm to be used
235 
236  /** @brief update a set of potentials: the remaining are those to be
237  * combined to produce a message on a separator */
239  Set< const Potential< GUM_SCALAR >* >& pot_list,
240  Set< const DiscreteVariable* >& kept_vars);
241 
242  /// the type of barren nodes computation we wish
244 
245  /// the operator for performing the projections
247  const Potential< GUM_SCALAR >&,
248  const Set< const DiscreteVariable* >&){VENewprojPotential};
249 
250  /// the operator for performing the combinations
252  const Potential< GUM_SCALAR >&){
254 
255  /// the triangulation class creating the junction tree used for inference
257 
258  /// the undigraph extracted from the BN and used to construct the join tree
259  /** If all nodes are targets, this graph corresponds to the moral graph
260  * of the BN. Otherwise, it may be a subgraph of this moral graph. For
261  * instance if the BN is A->B->C and only B is a target, graph__ will be
262  * equal to A-B if we exploit barren nodes (C is a barren node and,
263  * therefore, can be removed for inference). */
265 
266  /// the junction tree used to answer the last inference query
267  JunctionTree* JT__{nullptr};
268 
269  /// for each node of graph__ (~ in the Bayes net), associate an ID in the JT
271 
272  /// for each BN node, indicate in which clique its CPT will be stored
274 
275  /// indicate a clique that contains all the nodes of the target
277 
278  /// the posterior computed during the last inference
279  /** the posterior is owned by VariableElimination. */
281 
282  /// for comparisons with 1 - epsilon
284 
285 
286  /// create a new junction tree as well as its related data structures
287  void createNewJT__(const NodeSet& targets);
288 
289  /// sets the operator for performing the projections
291  Potential< GUM_SCALAR >* (*proj)(const Potential< GUM_SCALAR >&,
292  const Set< const DiscreteVariable* >&));
293 
294  /// sets the operator for performing the combinations
296  *comb)(const Potential< GUM_SCALAR >&, const Potential< GUM_SCALAR >&));
297 
298  /** @brief update a set of potentials: the remaining are those to be
299  * combined
300  * to produce a message on a separator */
303  Set< const DiscreteVariable* >& kept_vars);
304 
305  /** @brief update a set of potentials: the remaining are those to be
306  * combined
307  * to produce a message on a separator */
310  Set< const DiscreteVariable* >& kept_vars);
311 
312  /** @brief update a set of potentials: the remaining are those to be
313  * combined
314  * to produce a message on a separator */
317  Set< const DiscreteVariable* >& kept_vars);
318 
319  /** @brief update a set of potentials: the remaining are those to be
320  * combined
321  * to produce a message on a separator */
323  Set< const DiscreteVariable* >& kept_vars);
324 
325  /** @brief update a set of potentials: the remaining are those to be
326  * combined
327  * to produce a message on a separator */
329  Set< const DiscreteVariable* >& kept_vars);
330 
331  // remove barren variables and return the newly created projected potentials
334  Set< const DiscreteVariable* >& del_vars);
335 
336  /// actually perform the collect phase
338  NodeId from);
339 
340  /// returns the CPT + evidence of a node projected w.r.t. hard evidence
342 
343  /// creates the message sent by clique from_id to clique to_id
345  NodeId from_id,
346  NodeId to_id,
348 
349  /** @brief removes variables del_vars from a list of potentials and
350  * returns the resulting list */
352  Set< const DiscreteVariable* >& del_vars,
353  Set< const DiscreteVariable* >& kept_vars);
354  };
355 
356 
357 #ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
358  extern template class VariableElimination< double >;
359 #endif
360 
361 
362 } /* namespace gum */
363 
364 
365 #include <agrum/BN/inference/variableElimination_tpl.h>
366 
367 
368 #endif /* GUM_VARIABLE_ELIMINATION_ */
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:669