aGrUM  0.20.3
a C++ library for (probabilistic) graphical models
MCBayesNetGenerator.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 /** @file
23  * @brief Class for generating Bayesian networks.using MC algorithm
24  * cf. [Ide and Cozman, 2002]
25  *
26  * @author Pierre-Henri WUILLEMIN(@LIP6) and Ariele-Paolo MAESANO
27  */
28 
29 #ifndef GUM_MC_BAYES_NET_GENERATOR
30 #define GUM_MC_BAYES_NET_GENERATOR
31 
32 #include <agrum/agrum.h>
33 
34 #include <fstream>
35 #include <iostream>
36 #include <set>
37 #include <vector>
38 
39 #include <sstream>
40 
41 #ifdef HAVE_DIRENT_H
42 # include <dirent.h>
43 #else
44 # include <agrum/tools/core/mvsc/dirent.h>
45 #endif
46 
47 #include <agrum/BN/BayesNet.h>
48 #include <agrum/BN/generator/IBayesNetGenerator.h>
49 #include <agrum/BN/generator/simpleCPTDisturber.h>
50 #include <agrum/BN/generator/simpleCPTGenerator.h>
51 #include <agrum/BN/inference/lazyPropagation.h>
52 #include <agrum/tools/core/hashTable.h>
53 #include <agrum/tools/multidim/potential.h>
54 #include <agrum/tools/variables/labelizedVariable.h>
55 
56 namespace gum {
57  /**
58  * @class MCBayesNetGenerator
59  * @headerfile MCBayesNetGenerator.h
60  * <agrum/BN/generator/MCayesNetGenerator.h>
61  * @brief Class for generating Bayesian networks with Markov chains.
62  * @ingroup bn_generator
63  *
64  * This class randomly generates a Bayesian network given 6 parameters: the
65  * number of nodes, the maximum number of arcs the and of iterations the
66  * maximum modality.
67  * @warning Be Careful when entering the parameters, high Values may cause
68  * the density of the Bayesian network to be too high resulting in the
69  * failure of most of the inference Methods.
70  *
71  * \anchor probability_p_q
72  *
73  * This Generation method require the use of two probability parameters(p, q)
74  * defining the choice of processes that will provoke the change of state.
75  * You can see in the graph below how the probabilities are used.
76  *
77  * \dot
78  digraph {
79  size=4
80  bgcolor="transparent"
81  //subgraph cluster_cond{
82  if[shape=none, color=white ]
83  //}
84 
85  subgraph cluster_state{ color=invis;
86 
87  polytree
88  multiconnected
89  }
90 
91  subgraph cluster_function {
92  color=invis;
93  AorR1[shape=box,label="AorR", color=white]
94  AR1[shape=box,label="AR", color=white]
95  jump1[shape=box,label="Jump", color=white]
96  AorR2[shape=box,label="AorR", color=white]
97  jump2[shape=box,label="jump", color=white]
98  }
99 
100  //subgraph cluster_verdict{
101  reject[shape=none, color=white]
102  accept[shape=none, color=white]
103  //}
104 
105  //subgraph cluster_cond2{
106  if2[label="if",shape=none, color=white]
107  //}
108 
109  subgraph cluster_intstate{ color=invis;
110 
111 
112  polytree2[label="polytree", color=white]
113  multiconnected2[label="multiconnected", color=white]
114  }
115  subgraph cluster_finstate{ color=invis;
116 
117 
118  polytree3[label="polytree", color=white]
119  multiconnected3[label="multiconnected", color=white]
120  }
121  or[shape=none, color=white]
122 
123  if -> polytree
124  if -> multiconnected
125 
126  polytree -> AorR1[label="p"]
127  polytree -> AR1[label="q"]
128  polytree -> jump1[label="1-p-q"]
129 
130  multiconnected -> AorR2[label="p+q"]
131  multiconnected -> jump2[label="1-p-q"]
132 
133  AorR1 -> multiconnected3[style=dotted]
134  AR1 -> polytree3[style=dotted]
135  jump1 -> multiconnected3[style=dotted]
136 
137  AorR2 -> if2
138  //jump2 -> polytree3[style=dotted]
139 
140  if2 -> polytree2
141  if2 -> multiconnected2
142  polytree2 -> reject[label="p/(p+q)"]
143  polytree2 -> accept[label="q/(p+q)"]
144 
145  accept -> polytree3[style=dotted]
146  multiconnected2 -> multiconnected3[style=dotted]
147 
148  jump2 -> or
149 
150  or -> polytree3[style=dotted]
151  or -> multiconnected3[style=dotted]
152 
153  }
154  \enddot
155  */
156  template < typename GUM_SCALAR,
157  template < typename > class ICPTGenerator = SimpleCPTGenerator,
158  template < typename > class ICPTDisturber = SimpleCPTDisturber >
159  class MCBayesNetGenerator:
160  public IBayesNetGenerator< GUM_SCALAR, ICPTGenerator >,
161  public ICPTDisturber< GUM_SCALAR > {
162  public:
163  // ############################################################################
164  /// @name Constructors / Destructor
165  // ############################################################################
166  /// @{
167  /**
168  * Constructor.
169  * Use by default the SimpleCPTGenerator for generating the BNs CPT
170  * and the SimpleCPTDisturber to tweak the CPT when the dimension of the
171  * table
172  * changes.
173  * @param nbrNodes The number of nodes in the generated BN.
174  * @param maxArcs The maximum number of Arcs.
175  * @param maxModality Each DRV has from 2 to maxModality modalities
176  * @param iteration The number of iterations wanted to repeat the algorithm
177  * @param p probability for the change of the state (see \ref
178  * probability_p_q
179  * "use of p and q" )
180  * @param q probability for the change of the state (see \ref
181  * probability_p_q
182  * "use of p and q" )
183  */
184  MCBayesNetGenerator(Size nbrNodes,
185  Size maxArcs,
186  Idx maxModality = 2,
187  Size iteration = 5000,
188  Idx p = 30,
189  Idx q = 40);
190 
191  /**
192  * Constructor.
193  * Use by default the SimpleCPTGenerator for generating the BNs CPT
194  * and the SimpleCPTDisturber to tweak the CPT when the dimension of the
195  * table
196  * changes.
197  * @param bayesNet the IBayesNet used as reference to fill the parameters
198  * nbrNodes, maxArcs and maxModality
199  * @param iteration The number of iterations wanted to repeat the algorithm
200  * @param p probability for the change of the state (see \ref probability_p_q
201  * )
202  * @param q probability for the change of the state (see \ref probability_p_q
203  * )
204  */
205  explicit MCBayesNetGenerator(BayesNet< GUM_SCALAR > bayesNet,
206  Size iteration = 5000,
207  Idx p = 30,
208  Idx q = 40);
209 
210  /**
211  * Destructor.
212  */
213 
214  ~MCBayesNetGenerator() override;
215 
216  /// @}
217 
218  // ############################################################################
219  /// @name BN generation methods
220  // ############################################################################
221  /// @{
222  /**
223  * Generates a random Bayesian network.
224  * @param bayesNet empty IBayesNet to generate.
225  * @return null but modify inputed Bayesian network
226  */
227  void generateBN(BayesNet< GUM_SCALAR >& bayesNet) override;
228 
229  /**
230  * Change randomly the topology of a specific Bayesian networks.
231  * @param bayesNetinit IBayesNet to be modify
232  * @param iteration The number of iterations wanted to repeat the algorithm
233  * @return null but modify inputed Bayesian network
234  * @throws OperationNotAllow if the initial state of the IBayesNet is not
235  * respecting the wanted conditions
236  * if iteration = 0, it is assumed that the number of iteration wanted is the
237  * same
238  * as the one specified in the constructor
239  */
240  void disturbBN(BayesNet< GUM_SCALAR >& bayesNetinit, Size iteration = 0);
241 
242  ///@}
243 
244  // ############################################################################
245  /// @name Getters and Setters
246  // ############################################################################
247  /// @{
248  ///@name Getters
249 
250  /**
251  * Return a constant reference to the number of iteration imposed on the
252  * Markov
253  * Chain BayesNetGenerator.
254  */
255  Size iteration() const;
256  /**
257  * Return a constant reference to the probabilité p imposed on the Markov
258  * Chain
259  * BayesNetGenerator.
260  */
261  Idx p() const;
262  /**
263  * Return a constant reference to the probabilité imposed on the Markov Chain
264  * BayesNetGenerator.
265  */
266  Idx q() const;
267 
268  ///@name Setters
269 
270  /**
271  * Modifies the value of the number of iterations impose on the
272  * BayesNetGenerator
273  */
274  void setIteration(Size iteration);
275  /**
276  * Modifies the value of the probability p imposed on the BayesNetGenerator
277  */
278  void setP(Idx p);
279  /**
280  * Modifies the value of the probability q imposed on the BayesNetGenerator
281  */
282  void setQ(Idx q);
283 
284  /// @}
285  protected:
286  Size iteration_;
287  Idx p_, q_;
288  bool disturbing_;
289  BayesNet< GUM_SCALAR > bayesNettemp_;
290  HashTable< NodeId, Potential< GUM_SCALAR >* > hashMarginal_;
291 
292  /**
293  * The function that verify if graph is a polytree.
294  **/
295  bool _isPolytree_();
296  /**
297  * The function that verify if node i and j are connected.
298  **/
299  bool _connect_(NodeId i, NodeId j);
300  /**
301  * The function that verify if there is a oriented path from node i to node
302  *j.
303  **/
304  bool _directedPath_(NodeId tail, NodeId head);
305  /**
306  * The function that will insert an arc between node i to node j, but only
307  *if
308  *there isn't any cycle created.
309  **/
310  void _insertArc_(NodeId i, NodeId j);
311  /**
312  * The function that will remove the arc between node i and node j. If the
313  *boolean parameter mustbeconnex is true, the function will assert that the
314  *graph
315  *remain connected and will restore the arc otherwise.
316  **/
317  void _eraseArc_(NodeId i, NodeId j, bool mustbeconnex = true);
318 
319  /**
320  * In the case that the graph is a polytree, the function will, according to
321  *the
322  *probability p and q, choose which change of state must occure( AorR or AR
323  *or
324  *jump) then will assert that the imposed constraint are respected and if
325  *not,
326  *will return to the previous topology.
327  **/
328 
329  void _PMMx_poly_();
330  /**
331  * In the case that the graph is a multiconnected graph, the function will,
332  *according to the probability p and q, choose which change of state must
333  *occure(
334  *AorR or jump) then will assert that the imposed constraint are respected
335  *and if
336  *not, will return to the previous topology.
337  **/
338  void _PMMx_multi_();
339  /**
340  * In the case that the graph is a polytree, the function will add a ramdom
341  *arc
342  *by the use of the function _insertArc_ if the arc does not exist allready.
343  **/
344 
345  void _jump_poly_();
346 
347  /**
348  * In the case that the graph is a multiconnect graph, the function will
349  *choose
350  *randomly two nodes and will remove the arc between them by the use of the
351  *function _insertArc_ if the arc exists.
352  **/
353 
354  void _jump_multi_();
355 
356  /**
357  * The function will add or remove a random arc in the graph using the
358  *functions
359  * _insertArc_ and _removeArc_.
360  **/
361  void _AorR_();
362  /**
363  * The function will remove and add a random arc changing the topology of the
364  *graph but asserting its connectivity.
365  **/
366  void _AR_();
367  /**
368  * The boolean function that will assert the respect of the constraint.
369  **/
370  virtual bool _checkConditions_();
371 
372  // NOT USED ? void _createDAG_( Size BNSize, Size iniRoot );
373 
374  // NOT USED ? std::vector<Idx>* _createPartDAG_( Size BNSize, Size iniRoot
375  // );
376 
377  /**
378  * The internal function used by the previous _connect_. It asserts the
379  *existence
380  *of an unoriented path between node i and node j avoiding passing through
381  *nodes
382  *listed in excluded.
383  **/
384 
385  bool _connect_(NodeId i, NodeId j, NodeSet& excluded);
386 
387  /**
388  * The internal function used by the previous _directedPath_. It asserts the
389  *existence of an oriented path between node i and node j avoiding passing
390  *through nodes listed in excluded.
391  **/
392  bool _directedPath_(NodeId tail, NodeId head, NodeSet& excluded);
393 
394  /**
395  * The function that randomly choose two nodes of the graph.
396  **/
397 
398  void _chooseNodes_(NodeId& i, NodeId& j);
399 
400  /**
401  * The function that randomly choose two neighbours nodes of the graph.
402  **/
403  void _chooseCloseNodes_(NodeId& i, NodeId& j);
404 
405  /**
406  * The function that randomly change the simple tree into a polytree.
407  **/
408 
409  void _transformPoly_(Idx nbiter);
410 
411  /**
412  * The function that randomly generate a simple tree.
413  **/
414  void _createTree_(Size BNSize);
415 
416  /**
417  * The internal function used by _createTree_ that randomly generate a
418  *simple
419  *tree.
420  * n : id number for node label
421  **/
422  NodeId _createPartTree_(Size BNSize, Idx& n);
423  };
424 
425 
426 #ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
427  extern template class MCBayesNetGenerator< double >;
428 #endif
429 
430 } /*namespace gum*/
431 
432 #include <agrum/BN/generator/MCBayesNetGenerator_tpl.h>
433 #endif // MCBAYESNETGENERATOR