aGrUM  0.20.3
a C++ library for (probabilistic) graphical models
CNLoopyPropagation.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 Class implementing loopy-propagation with binary networks - L2U
25  * algorithm.
26  * @author Matthieu HOURBRACQ and Pierre-Henri WUILLEMIN(@LIP6)
27  */
28 
29 #ifndef __CN_LOOPY_PROPAGATION__H__
30 #define __CN_LOOPY_PROPAGATION__H__
31 
32 #include <cstdlib>
33 #include <ctime>
34 #include <limits>
35 
36 #include <agrum/CN/credalNet.h>
37 #include <agrum/CN/inference/inferenceEngine.h>
38 #include <agrum/tools/core/approximations/approximationScheme.h>
39 #include <agrum/tools/core/math/pow.h>
40 #include <agrum/tools/core/sequence.h>
41 
42 #define INF_ std::numeric_limits< GUM_SCALAR >::infinity()
43 
44 namespace gum {
45  namespace credal {
46 
47  /**
48  * @class CNLoopyPropagation CNLoopyPropagation.h
49  * <agrum/CN/CNLoopyPropagation.h>
50  * @ingroup cn_group
51  * @brief Class implementing loopy-propagation with binary networks - L2U
52  * algorithm.
53  * @tparam GUM_SCALAR A floating type ( float, double, long double ... ).
54  * @author Matthieu HOURBRACQ and Pierre-Henri WUILLEMIN(@LIP6)
55  */
56  template < typename GUM_SCALAR >
58  public:
59  using msg = std::vector< Potential< GUM_SCALAR >* >;
60  using cArcP = const Arc*;
61 
62  /**
63  * Inference type to be used by the algorithm.
64  */
65  enum class InferenceType : char
66  {
67  nodeToNeighbours, /**< Uses a node-set so we don't iterate on nodes that
68  can't send a new message. Should be the fastest
69  inference type. A step is going through the
70  node-set. */
71 
72  ordered, /**< Chooses an arc ordering and sends messages accordingly at
73  all
74  steps. Avoid it since it can give slightly worse results
75  than
76  other inference types. A step is going through all arcs. */
77 
78  randomOrder /**< Chooses a random arc ordering and sends messages
79  accordingly. A new order is set at each step. A step is
80  going
81  through all arcs. */
82  };
83 
84  /// @name Public algorithm methods
85  /// @{
86 
87  /** Starts the inference. */
88  void makeInference();
89 
90  /// @}
91 
92  /// @name Getters and setters
93  /// @{
94 
95  /**
96  * %Set the inference type.
97  * @param inft The choosen \c InferenceType.
98  */
99  void inferenceType(InferenceType inft);
100 
101  /**
102  * Get the inference type.
103  * @return The inference type.
104  */
106 
107  /// @}
108 
109  /// @name Post-inference methods
110  /// @{
111 
112  /**
113  * Erase all inference related data to perform another one. You need to
114  * insert
115  * evidence again if needed but modalities are kept. You can insert new
116  * ones by
117  * using the appropriate method which will delete the old ones.
118  */
119  void eraseAllEvidence();
120 
121  /**
122  * @deprecated
123  * Use saveMarginals() from InferenceEngine instead.
124  * This one is easier to read but harder for scripts to parse.
125  * @param path The path to the file to save marginals.
126  */
127  void saveInference(const std::string& path);
128 
129  /// @}
130 
131  /// @name Constructors / Destructors
132  /// @{
133  /**
134  * Constructor.
135  * @param cnet The CredalNet to be used with this algorithm.
136  */
137  explicit CNLoopyPropagation(const CredalNet< GUM_SCALAR >& cnet);
138  /** Destructor. */
139  virtual ~CNLoopyPropagation();
140  /// @}
141 
142  protected:
143  /// @name Protected initialization methods
144  /// @{
145 
146  /** Topological forward propagation to initialize old marginals &
147  * messages. */
148  void initialize_();
149 
150  /// @}
151 
152  /// @name Protected algorithm methods
153  /// @{
154  /** Starts the inference with this inference type. */
156  /** Starts the inference with this inference type. */
158  /** Starts the inference with this inference type. */
160 
161  /** Compute marginals from up-to-date messages. */
162  void updateMarginals_();
163 
164  /**
165  * Sends a message to one's parent, i.e. X is sending a message to a
166  * demanding_parent.
167  * @param X The constant node id of the node sending the message.
168  * @param demanding_parent The constant node id of the node receiving the
169  * message.
170  */
171  void msgL_(const NodeId X,
172  const NodeId demanding_parent); // allways sent from X to demanding_X
173 
174  /**
175  * Used by msgL_. Compute the final message for the given parent's message
176  * and
177  * likelihood (children's messages), numerators & denominators.
178  * @param msg_l_min The reference to the current lower value of the
179  * message to
180  * be sent.
181  * @param msg_l_max The reference to the current upper value of the
182  * message to
183  * be sent.
184  * @param lx The lower and upper likelihood.
185  * @param num_min The reference to the previously computed lower
186  * numerator.
187  * @param num_max The reference to the previously computed upper
188  * numerator.
189  * @param den_min The reference to the previously computed lower
190  * denominator.
191  * @param den_max The reference to the previously computed upper
192  * denominator.
193  */
194  void compute_ext_(GUM_SCALAR& msg_l_min,
195  GUM_SCALAR& msg_l_max,
196  std::vector< GUM_SCALAR >& lx,
197  GUM_SCALAR& num_min,
198  GUM_SCALAR& num_max,
199  GUM_SCALAR& den_min,
200  GUM_SCALAR& den_max);
201 
202  /**
203  * Used by msgL_. Compute the numerators & denominators for the given
204  * parent's
205  * message and likelihood (children's messages). Marginalisation.
206  * @param combi_msg_p The parent's choosen message.
207  * @param id The constant id of the node sending the message.
208  * @param msg_l_min The reference to the current lower value of the
209  * message to
210  * be sent.
211  * @param msg_l_max The reference to the current upper value of the
212  * message to
213  * be sent.
214  * @param lx The lower and upper likelihood.
215  * @param pos The position of the parent node to receive the message in
216  * the CPT
217  * of the one sending the message ( first parent, second ... ).
218  */
220  const NodeId& id,
223  std::vector< GUM_SCALAR >& lx,
224  const Idx& pos);
225 
226  /**
227  * Used by msgL_. Enumerate parent's messages.
228  * @param msgs_p All the messages from the parents which will be
229  * enumerated.
230  * @param id The constant id of the node sending the message.
231  * @param msg_l_min The reference to the current lower value of the
232  * message to
233  * be sent.
234  * @param msg_l_max The reference to the current upper value of the
235  * message to
236  * be sent.
237  * @param lx The lower and upper likelihood.
238  * @param pos The position of the parent node to receive the message in
239  * the CPT
240  * of the one sending the message ( first parent, second ... ).
241  */
243  const NodeId& id,
246  std::vector< GUM_SCALAR >& lx,
247  const Idx& pos);
248 
249  /**
250  * Sends a message to one's child, i.e. X is sending a message to a
251  * demanding_child.
252  * @param X The constant node id of the node sending the message.
253  * @param demanding_child The constant node id of the node receiving the
254  * message.
255  */
256  void msgP_(const NodeId X, const NodeId demanding_child);
257 
258  /**
259  * Used by msgP_. Enumerate parent's messages.
260  * @param msgs_p All the messages from the parents which will be
261  * enumerated.
262  * @param id The constant id of the node sending the message.
263  * @param msg_p_min The reference to the current lower value of the
264  * message to
265  * be sent.
266  * @param msg_p_max The reference to the current upper value of the
267  * message to
268  * be sent.
269  */
271  const NodeId& id,
274 
275  /**
276  * Used by msgP_. Marginalisation.
277  * @param combi_msg_p The parent's choosen message.
278  * @param id The constant id of the node sending the message.
279  * @param msg_p_min The reference to the current lower value of the
280  * message to
281  * be sent.
282  * @param msg_p_max The reference to the current upper value of the
283  * message to
284  * be sent.
285  */
287  const NodeId& id,
290 
291  /** Get the last messages from one's parents and children. */
292  void refreshLMsPIs_(bool refreshIndic = false);
293 
294  /**
295  * Compute epsilon.
296  * @return Epsilon.
297  */
298  GUM_SCALAR calculateEpsilon_();
299 
300  /// @}
301 
302  /// @name Post-inference protected methods
303  /// @{
304 
305  /** Since the network is binary, expectations can be computed from the
306  * final
307  * marginals which give us the credal set vertices. */
308  void computeExpectations_();
309 
310  /** @brief Only update indicatrices variables at the end of computations (
311  * calls msgP_ ). */
312  void updateIndicatrices_();
313 
314  /// @}
315 
316  /** Used to keep track of which node needs to update it's information
317  * coming
318  * from it's parents. */
320  /** Used to keep track of which node needs to update it's information
321  * coming
322  * from it's children. */
324 
325  /** The current node-set to iterate through at this current step. */
327  /** The next node-set, i.e. the nodes that will send messages at the next
328  * step.
329  */
331 
332  /** Used to keep track of one's messages sent to it's parents. */
334 
335  /** "Lower" information \f$ \Lambda \f$ coming from one's children. */
337  /** "Lower" information \f$ \pi \f$ coming from one's parent. */
339  /** "Lower" node information \f$ \Lambda \f$ obtained by combinaison of
340  * children messages. */
342  /** "Lower" node information \f$ \pi \f$ obtained by combinaison of
343  * parent's
344  * messages. */
346 
347  /** "Upper" information \f$ \Lambda \f$ coming from one's children. */
349  /** "Upper" information \f$ \pi \f$ coming from one's parent. */
351  /** "Upper" node information \f$ \Lambda \f$ obtained by combinaison of
352  * children messages. */
354  /** "Upper" node information \f$ \pi \f$ obtained by combinaison of
355  * parent's
356  * messages. */
358 
359  /** \c TRUE if inference has already been performed, \c FALSE otherwise.
360  */
362 
363  private:
364  /** To easily access InferenceEngine< GUM_SCALAR > methods. */
366 
367  /** The choosen inference type. nodeToNeighbours by Default. */
369 
370  /** A pointer to the CredalNet to be used. */
372 
373  /** A pointer to it's IBayesNet used as a DAG. */
375 
376  // typedef const CredalNet< GUM_SCALAR > * (infE::*cnfunc) ();
377  // cnfunc getCN = &infE::getCN;
378  public:
379  virtual void insertEvidenceFile(const std::string& path) {
380  InferenceEngine< GUM_SCALAR >::insertEvidenceFile(path);
381  };
382  };
383 
384 
385 #ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
386  extern template class CNLoopyPropagation< double >;
387 #endif
388  } // namespace credal
389 } // namespace gum
390 
391 #include <agrum/CN/inference/CNLoopyPropagation_tpl.h>
392 
393 #endif
void refreshLMsPIs_(bool refreshIndic=false)
Get the last messages from one&#39;s parents and children.
NodeProperty< NodeSet *> msg_l_sent_
Used to keep track of one&#39;s messages sent to it&#39;s parents.
void makeInferenceByOrderedArcs_()
Starts the inference with this inference type.
const CredalNet< GUM_SCALAR > * _cn_
A pointer to the CredalNet to be used.
GUM_SCALAR calculateEpsilon_()
Compute epsilon.
NodeProperty< bool > update_l_
Used to keep track of which node needs to update it&#39;s information coming from it&#39;s children...
InferenceType _inferenceType_
The choosen inference type.
virtual void insertEvidenceFile(const std::string &path)
Insert evidence from file.
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:643
void makeInferenceNodeToNeighbours_()
Starts the inference with this inference type.
void eraseAllEvidence()
Erase all inference related data to perform another one.
ArcProperty< GUM_SCALAR > ArcsP_min_
"Lower" information coming from one&#39;s parent.
NodeSet active_nodes_set
The current node-set to iterate through at this current step.
ArcProperty< GUM_SCALAR > ArcsL_max_
"Upper" information coming from one&#39;s children.
NodeProperty< GUM_SCALAR > NodesL_min_
"Lower" node information obtained by combinaison of children messages.
NodeProperty< GUM_SCALAR > NodesP_max_
"Upper" node information obtained by combinaison of parent&#39;s messages.
<agrum/CN/CNLoopyPropagation.h>
Chooses an arc ordering and sends messages accordingly at all steps.
NodeProperty< GUM_SCALAR > NodesP_min_
"Lower" node information obtained by combinaison of parent&#39;s messages.
void compute_ext_(std::vector< std::vector< GUM_SCALAR > > &combi_msg_p, const NodeId &id, GUM_SCALAR &msg_p_min, GUM_SCALAR &msg_p_max)
Used by msgP_.
NodeProperty< bool > update_p_
Used to keep track of which node needs to update it&#39;s information coming from it&#39;s parents...
ArcProperty< GUM_SCALAR > ArcsP_max_
"Upper" information coming from one&#39;s parent.
InferenceType inferenceType()
Get the inference type.
NodeProperty< GUM_SCALAR > NodesL_max_
"Upper" node information obtained by combinaison of children messages.
CNLoopyPropagation(const CredalNet< GUM_SCALAR > &cnet)
Constructor.
bool InferenceUpToDate_
TRUE if inference has already been performed, FALSE otherwise.
Uses a node-set so we don&#39;t iterate on nodes that can&#39;t send a new message.
const IBayesNet< GUM_SCALAR > * _bnet_
A pointer to it&#39;s IBayesNet used as a DAG.
void msgP_(const NodeId X, const NodeId demanding_child)
Sends a message to one&#39;s child, i.e.
void saveInference(const std::string &path)
void makeInferenceByRandomOrder_()
Starts the inference with this inference type.
void makeInference()
Starts the inference.
void initialize_()
Topological forward propagation to initialize old marginals & messages.
void enum_combi_(std::vector< std::vector< std::vector< GUM_SCALAR > > > &msgs_p, const NodeId &id, GUM_SCALAR &msg_p_min, GUM_SCALAR &msg_p_max)
Used by msgP_.
void inferenceType(InferenceType inft)
Set the inference type.
void updateIndicatrices_()
Only update indicatrices variables at the end of computations ( calls msgP_ ).
void compute_ext_(GUM_SCALAR &msg_l_min, GUM_SCALAR &msg_l_max, std::vector< GUM_SCALAR > &lx, GUM_SCALAR &num_min, GUM_SCALAR &num_max, GUM_SCALAR &den_min, GUM_SCALAR &den_max)
Used by msgL_.
void updateMarginals_()
Compute marginals from up-to-date messages.
InferenceType
Inference type to be used by the algorithm.
void msgL_(const NodeId X, const NodeId demanding_parent)
Sends a message to one&#39;s parent, i.e.
Chooses a random arc ordering and sends messages accordingly.
NodeSet next_active_nodes_set
The next node-set, i.e.
void computeExpectations_()
Since the network is binary, expectations can be computed from the final marginals which give us the ...
namespace for all credal networks entities
Definition: LpInterface.cpp:37
ArcProperty< GUM_SCALAR > ArcsL_min_
"Lower" information coming from one&#39;s children.