aGrUM  0.16.0
MCBayesNetGenerator_tpl.h
Go to the documentation of this file.
1 
31 
32 namespace gum {
33 
34 #ifdef _MSC_VER
35 # define IBNG IBayesNetGenerator
36 #else
37 # define IBNG IBayesNetGenerator< GUM_SCALAR, ICPTGenerator >
38 #endif
39 
40  template < typename GUM_SCALAR >
42  gum::Size maxMod = 0;
43 
44  for (auto node : bayesNet.nodes())
45  if (maxMod < bayesNet.variable(node).domainSize())
46  maxMod = bayesNet.variable(node).domainSize();
47 
48  return maxMod;
49  }
50 
51  // Default constructor.
52  // Use the SimpleCPTGenerator for generating the BNs CPT.
53  template < typename GUM_SCALAR,
54  template < typename >
55  class ICPTGenerator,
56  template < typename >
57  class ICPTDisturber >
60  Size maxArcs,
61  Idx maxModality,
62  Size iteration,
63  Idx p,
64  Idx q) :
65  IBNG(nbrNodes, maxArcs, maxModality),
66  _bayesNettemp(), _hashMarginal() {
67  if (p + q > 100)
68  GUM_ERROR(
70  "the sum of the probabilities p and q must be at most equal to 100");
71 
73  _p = p;
74  _q = q;
75  _disturbing = false;
76 
77  GUM_CONSTRUCTOR(MCBayesNetGenerator);
78  }
79 
80  template < typename GUM_SCALAR,
81  template < typename >
82  class ICPTGenerator,
83  template < typename >
84  class ICPTDisturber >
88  Idx p,
89  Idx q) :
90  MCBayesNetGenerator(bayesNet.size(),
91  (Size)(bayesNet.sizeArcs() * 1.1),
92  getMaxModality(bayesNet)) {
94  _p = p;
95  _q = q;
96  _disturbing = false;
97  }
98 
99  // Destructor.
100  template < typename GUM_SCALAR,
101  template < typename >
102  class ICPTGenerator,
103  template < typename >
104  class ICPTDisturber >
107  GUM_DESTRUCTOR(MCBayesNetGenerator);
108  }
109 
110  template < typename GUM_SCALAR,
111  template < typename >
112  class ICPTGenerator,
113  template < typename >
114  class ICPTDisturber >
116  BayesNet< GUM_SCALAR >& bayesNet) {
118 
119  // this->_bayesNet = bayesNet;
120  __createTree(this->_nbrNodes);
121  __transformPoly(this->_nbrNodes / 2);
122  _bayesNettemp = this->_bayesNet;
123  __PMMx_poly();
124 
125  this->fillCPT();
127 
128  bayesNet = this->_bayesNet;
129  }
130 
131  // density represent de
132  template < typename GUM_SCALAR,
133  template < typename >
134  class ICPTGenerator,
135  template < typename >
136  class ICPTDisturber >
138  BayesNet< GUM_SCALAR >& bayesNetinit,
139  Size iteration) { // insert option for the variation
140  _disturbing = true;
141  Size iter = _iteration;
142 
143  if (iteration) _iteration = iteration;
144 
145  this->_bayesNet = bayesNetinit;
146 
147  if (__checkConditions()) {
148  LazyPropagation< GUM_SCALAR > inf(&bayesNetinit);
149  inf.makeInference();
150 
151  for (auto node : bayesNetinit.nodes()) {
152  auto pottemp = new Potential< GUM_SCALAR >();
153  pottemp->copy(inf.posterior(node));
154  _hashMarginal.insert(node, pottemp);
155  }
156 
157  _bayesNettemp = this->_bayesNet;
158 
159  if (__isPolytree())
160  __PMMx_poly();
161  else
162  __PMMx_multi();
163 
164  bayesNetinit = (this->_bayesNet);
165 
166  while (_hashMarginal.size()) {
167  delete (_hashMarginal.begin().val());
168  _hashMarginal.erase(
169  _hashMarginal.beginSafe()); // safe iterator needed here.
170  }
171 
172  } else {
173  std::cout << this->_bayesNet.toDot() << std::endl;
175  "BN is not valid cause it does not respect constraint ");
176  }
177 
178  _iteration = iter;
179  _disturbing = false;
180  }
181 
182  template < typename GUM_SCALAR,
183  template < typename >
184  class ICPTGenerator,
185  template < typename >
186  class ICPTDisturber >
189  return this->_maxArcs >= this->_bayesNet.sizeArcs();
190  }
191 
192  // main algorithme for moving between state of the IBayesNet according on the
193  // nature of the topology polytree or multi-connected
194 
195  template < typename GUM_SCALAR,
196  template < typename >
197  class ICPTGenerator,
198  template < typename >
199  class ICPTDisturber >
202  if (!_iteration--) return;
203 
204  Idx per = randomValue(100);
205 
206  if (per < _p) {
207  __AorR();
208 
209  if (__checkConditions()) {
210  _bayesNettemp = this->_bayesNet;
211  __PMMx_multi();
212  } else {
213  this->_bayesNet = _bayesNettemp;
214  __PMMx_poly();
215  }
216  } else {
217  if (per < _p + _q) {
218  __AR();
219 
220  if (!__checkConditions()) {
221  this->_bayesNet = _bayesNettemp;
222  } else
223  _bayesNettemp = this->_bayesNet;
224 
225  __PMMx_poly();
226  } else {
227  __jump_poly();
228 
229  if (__checkConditions()) {
230  _bayesNettemp = this->_bayesNet;
231  __PMMx_multi();
232 
233  } else {
234  this->_bayesNet = _bayesNettemp;
235  __PMMx_poly();
236  }
237  }
238  }
239  }
240 
241  template < typename GUM_SCALAR,
242  template < typename >
243  class ICPTGenerator,
244  template < typename >
245  class ICPTDisturber >
248  if (!_iteration--) return;
249 
250  Idx per = randomValue(100);
251 
252  if (per < _p + _q) {
253  __AorR();
254 
255  if (__checkConditions()) {
256  if (__isPolytree()) {
257  if (per < _p) {
258  _bayesNettemp = this->_bayesNet;
259  __PMMx_poly();
260  } else {
261  this->_bayesNet = _bayesNettemp;
262  __PMMx_multi();
263  }
264  } else {
265  _bayesNettemp = this->_bayesNet;
266  __PMMx_multi();
267  }
268  } else {
269  this->_bayesNet = _bayesNettemp;
270  __PMMx_multi();
271  }
272  } else {
273  __jump_multi();
274 
275  if (__checkConditions()) {
276  _bayesNettemp = this->_bayesNet;
277 
278  if (__isPolytree())
279  __PMMx_poly();
280  else
281  __PMMx_multi(); // TODO verification required
282 
283  } else {
284  this->_bayesNet = _bayesNettemp;
285  __PMMx_multi();
286  }
287  }
288  }
289 
290  template < typename GUM_SCALAR,
291  template < typename >
292  class ICPTGenerator,
293  template < typename >
294  class ICPTDisturber >
296  NodeId i, j;
297  __chooseNodes(i, j);
298  const DAG __dag = this->_bayesNet.dag();
299 
300  if (__dag.existsArc(i, j)) {
301  __eraseArc(i, j);
302 
303  return;
304  } else
305  __insertArc(i, j);
306  }
307 
308  template < typename GUM_SCALAR,
309  template < typename >
310  class ICPTGenerator,
311  template < typename >
312  class ICPTDisturber >
314  NodeId i, j, head, tail;
315  __chooseNodes(i, j);
316  const DAG __dag = this->_bayesNet.dag();
317 
318  if (__dag.existsArc(i, j) || __dag.existsArc(j, i)) {
319  return;
320  } else {
321  Idx per = randomValue(100);
322 
323  if (per < 50) {
324  head = i;
325  tail = j;
326  } else {
327  head = j;
328  tail = i;
329  }
330 
331  for (auto node : __dag.parents(j)) {
332  NodeSet excluded;
333  excluded.insert(j);
334 
335  if (__connect(node, i, excluded)) {
336  this->_bayesNet.eraseArc(node, j); // TODO reflect
337  this->_bayesNet.addArc(head, tail);
338  return;
339  }
340  }
341 
342  for (auto node : __dag.children(j)) {
343  NodeSet excluded;
344  excluded.insert(j);
345 
346  if (__connect(node, i, excluded)) {
347  this->_bayesNet.eraseArc(j, node);
348  this->_bayesNet.addArc(head, tail);
349  return;
350  }
351  }
352  }
353  }
354 
355  template < typename GUM_SCALAR,
356  template < typename >
357  class ICPTGenerator,
358  template < typename >
359  class ICPTDisturber >
362  NodeId i, j;
363  __chooseNodes(i, j);
364  const DAG __dag = this->_bayesNet.dag();
365 
366  if (!__dag.existsArc(i, j)) __insertArc(i, j);
367  }
368 
369  template < typename GUM_SCALAR,
370  template < typename >
371  class ICPTGenerator,
372  template < typename >
373  class ICPTDisturber >
376  NodeId i, j;
377  __chooseNodes(i, j);
378  const DAG __dag = this->_bayesNet.dag();
379 
380  if (__dag.existsArc(i, j)) { __eraseArc(i, j); }
381  }
382 
383  template < typename GUM_SCALAR,
384  template < typename >
385  class ICPTGenerator,
386  template < typename >
387  class ICPTDisturber >
388  INLINE void
390  NodeId i, NodeId j) {
391  if (__directedPath(j, i)) return;
392 
393  if (_disturbing) {
394  auto potj = this->_bayesNet.cpt(j);
395  this->_bayesNet.addArc(i, j);
396 
397  this->disturbAugmCPT(j, this->_bayesNet, potj, (GUM_SCALAR)0.5);
398  } else
399  this->_bayesNet.addArc(i, j);
400  }
401 
402  template < typename GUM_SCALAR,
403  template < typename >
404  class ICPTGenerator,
405  template < typename >
406  class ICPTDisturber >
407  INLINE void
409  NodeId i, NodeId j, bool mustbeconnex) {
410  if (_disturbing) {
411  const BayesNet< GUM_SCALAR > bayesNet(this->_bayesNet);
413  potj.copy(this->_bayesNet.cpt(j));
414  this->_bayesNet.eraseArc(i, j);
415 
416  if (__connect(i, j) || !mustbeconnex) {
417  auto marg = *_hashMarginal[i];
418 
419  this->disturbReducCPT(j, this->_bayesNet, potj, marg);
420  } else
421  this->_bayesNet.addArc(i, j);
422  } else {
423  this->_bayesNet.eraseArc(i, j);
424 
425  if (!__connect(i, j) && mustbeconnex) { this->_bayesNet.addArc(i, j); }
426  }
427  }
428 
429  template < typename GUM_SCALAR,
430  template < typename >
431  class ICPTGenerator,
432  template < typename >
433  class ICPTDisturber >
436  i = randomValue(this->_bayesNet.size());
437  j = randomValue(this->_bayesNet.size());
438 
439  while (i == j)
440  j = randomValue(this->_bayesNet.size());
441  }
442 
443  template < typename GUM_SCALAR,
444  template < typename >
445  class ICPTGenerator,
446  template < typename >
447  class ICPTDisturber >
450  NodeId temp = randomValue(this->_bayesNet.size());
451  Size co = 0;
452 
453  if (this->_bayesNet.parents(temp).size()) {
454  j = temp;
455  auto it = this->_bayesNet.parents(j).begin();
456  co = randomValue(this->_bayesNet.parents(j).size());
457 
458  while (co--) {
459  ++it;
460  }
461 
462  i = *it;
463  } else if (this->_bayesNet.children(temp).size()) {
464  i = temp;
465  auto it = this->_bayesNet.children(i).begin();
466  co = randomValue(this->_bayesNet.children(i).size());
467 
468  while (co--) {
469  ++it;
470  }
471 
472  j = *it;
473  } else {
474  GUM_ERROR(FatalError, "Sorry Misconstructed BN because of isolated node.");
475  }
476  }
477 
478  template < typename GUM_SCALAR,
479  template < typename >
480  class ICPTGenerator,
481  template < typename >
482  class ICPTDisturber >
483  void
485  Size BNSize) {
486  Idx n = 0;
487  Size nb_mod = 2 + randomValue(this->_maxModality - 1);
488  std::stringstream strBuff;
489  strBuff << "n_" << n++;
490  NodeId root =
491  this->_bayesNet.add(LabelizedVariable(strBuff.str(), "", nb_mod));
492  Size maxNodes = BNSize - 1;
493  Size SubG = 0;
494 
495  while (maxNodes) {
496  SubG = randomValue(maxNodes) + 1;
497  maxNodes = maxNodes - SubG;
498  NodeId rootS = __createPartTree(SubG, n);
499  this->_bayesNet.addArc(root, rootS);
500  }
501  }
502 
503  template < typename GUM_SCALAR,
504  template < typename >
505  class ICPTGenerator,
506  template < typename >
507  class ICPTDisturber >
510  Size nb_mod = 2 + randomValue(this->_maxModality - 1);
511  std::stringstream strBuff;
512  strBuff << "n_" << n++;
513  NodeId root =
514  this->_bayesNet.add(LabelizedVariable(strBuff.str(), "", nb_mod));
515  Size maxNodes = BNSize - 1;
516  Size SubG = 0;
517 
518  while (maxNodes) {
519  SubG = randomValue(maxNodes) + 1;
520  maxNodes = maxNodes - SubG;
521  NodeId rootS = __createPartTree(SubG, n);
522  this->_bayesNet.addArc(root, rootS);
523  }
524 
525  return root;
526  }
527 
528  // Allow to invert maximum nbiter arc to use from polytree only
529  template < typename GUM_SCALAR,
530  template < typename >
531  class ICPTGenerator,
532  template < typename >
533  class ICPTDisturber >
536  while (nbiter--) {
537  NodeId i, j;
538  __chooseCloseNodes(i, j);
539  _bayesNettemp = this->_bayesNet;
540  __eraseArc(i, j, false);
541  this->_bayesNet.addArc(j, i);
542 
543  if (!__checkConditions()) this->_bayesNet = _bayesNettemp;
544  }
545  }
546 
547  template < typename GUM_SCALAR,
548  template < typename >
549  class ICPTGenerator,
550  template < typename >
551  class ICPTDisturber >
554  const DAG __dag = this->_bayesNet.dag();
555  return this->_bayesNet.size() - 1 == this->_bayesNet.sizeArcs();
556  }
557 
558  template < typename GUM_SCALAR,
559  template < typename >
560  class ICPTGenerator,
561  template < typename >
562  class ICPTDisturber >
564  const NodeId i, const NodeId j) {
565  const DAG __dag = this->_bayesNet.dag();
566 
567  if (__dag.existsArc(i, j) || __dag.existsArc(j, i))
568  return true;
569  else {
570  NodeSet excluded;
571  excluded.insert(i);
572 
573  for (auto par : __dag.parents(i)) {
574  if (!excluded.exists(par) && __connect(par, j, excluded)) return true;
575  }
576 
577  for (auto chi : __dag.children(i)) {
578  if (!excluded.exists(chi) && __connect(chi, j, excluded)) return true;
579  }
580 
581  return false;
582  }
583  }
584 
585  template < typename GUM_SCALAR,
586  template < typename >
587  class ICPTGenerator,
588  template < typename >
589  class ICPTDisturber >
591  const NodeId i, const NodeId j, NodeSet& excluded) {
592  const DAG __dag = this->_bayesNet.dag();
593 
594  if (__dag.existsArc(i, j) || __dag.existsArc(j, i))
595  return true;
596  else {
597  excluded.insert(i);
598 
599  for (auto par : __dag.parents(i)) {
600  if (!excluded.exists(par) && __connect(par, j, excluded)) return true;
601  }
602 
603  for (auto chi : __dag.children(i)) {
604  if (!excluded.exists(chi) && __connect(chi, j, excluded)) return true;
605  }
606 
607  return false;
608  }
609  }
610 
611  template < typename GUM_SCALAR,
612  template < typename >
613  class ICPTGenerator,
614  template < typename >
615  class ICPTDisturber >
618  const DAG __dag = this->_bayesNet.dag();
619 
620  if (__dag.existsArc(tail, head))
621  return true;
622  else {
623  NodeSet excluded;
624  excluded.insert(tail);
625 
626  for (auto node : __dag.children(tail)) {
627  if (__directedPath(node, head, excluded)) return true;
628  }
629 
630  return false;
631  }
632  }
633 
634  template < typename GUM_SCALAR,
635  template < typename >
636  class ICPTGenerator,
637  template < typename >
638  class ICPTDisturber >
640  __directedPath(NodeId tail, NodeId head, NodeSet& excluded) {
641  const DAG __dag = this->_bayesNet.dag();
642 
643  if (__dag.existsArc(tail, head))
644  return true;
645  else {
646  excluded.insert(tail);
647 
648  for (auto node : __dag.children(tail)) {
649  if (!excluded.exists(node) && __directedPath(node, head, excluded))
650  return true;
651  }
652 
653  return false;
654  }
655  }
656 
657  template < typename GUM_SCALAR,
658  template < typename >
659  class ICPTGenerator,
660  template < typename >
661  class ICPTDisturber >
662  INLINE Size
664  const {
665  return _iteration;
666  }
667 
668  template < typename GUM_SCALAR,
669  template < typename >
670  class ICPTGenerator,
671  template < typename >
672  class ICPTDisturber >
673  INLINE Idx
675  return _p;
676  }
677 
678  template < typename GUM_SCALAR,
679  template < typename >
680  class ICPTGenerator,
681  template < typename >
682  class ICPTDisturber >
683  INLINE Idx
685  return _q;
686  }
687 
688  template < typename GUM_SCALAR,
689  template < typename >
690  class ICPTGenerator,
691  template < typename >
692  class ICPTDisturber >
693  INLINE void
695  Size iteration) {
697  }
698  template < typename GUM_SCALAR,
699  template < typename >
700  class ICPTGenerator,
701  template < typename >
702  class ICPTDisturber >
703  INLINE void
705  _p = p;
706 
707  if (p + _q > 100)
708  GUM_ERROR(
710  "the sum of the probabilities p and q must be at most equal to 100");
711  }
712  template < typename GUM_SCALAR,
713  template < typename >
714  class ICPTGenerator,
715  template < typename >
716  class ICPTDisturber >
717  INLINE void
719  _q = q;
720 
721  if (_p + q > 100)
722  GUM_ERROR(
724  "the sum of the probabilities p and q must be at most equal to 100");
725  }
726 
727 } /* namespace gum */
aGrUM&#39;s Potential is a multi-dimensional array with tensor operators.
Definition: potential.h:60
Class representing a Bayesian Network.
Definition: BayesNet.h:78
MCBayesNetGenerator(Size nbrNodes, Size maxArcs, Idx maxModality=2, Size iteration=5000, Idx p=30, Idx q=40)
Constructor.
virtual bool __checkConditions()
The boolean function that will assert the respect of the constraint.
void __PMMx_poly()
In the case that the graph is a polytree, the function will, according to the probability p and q...
const DiscreteVariable & variable(NodeId id) const final
Returns a gum::DiscreteVariable given its gum::NodeId in the gum::BayesNet.
Definition: BayesNet_tpl.h:202
class LabelizedVariable
Idx q() const
Return a constant reference to the probabilité imposed on the Markov Chain BayesNetGenerator.
Idx randomValue(const Size max=2)
Returns a random Idx between 0 and max-1 included.
<agrum/BN/generator/MCayesNetGenerator.h>
void fillCPT()
function that insert random values in the CPT of each nodes according to the CPTGenerator.
gum::Size getMaxModality(gum::BayesNet< GUM_SCALAR > &bayesNet)
bool __connect(NodeId i, NodeId j)
The function that verify if node i and j are connected.
void setQ(Idx q)
Modifies the value of the probability q imposed on the BayesNetGenerator.
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
Definition: agrum.h:25
virtual void copy(const MultiDimContainer< GUM_SCALAR > &src)
Removes all variables in this MultiDimContainer and copy the content of src, variables included...
void __jump_multi()
In the case that the graph is a multiconnect graph, the function will choose randomly two nodes and w...
bool __isPolytree()
The function that verify if graph is a polytree.
virtual void makeInference() final
perform the heavy computations needed to compute the targets&#39; posteriors
#define IBNG
virtual Size domainSize() const =0
void setP(Idx p)
Modifies the value of the probability p imposed on the BayesNetGenerator.
~MCBayesNetGenerator() override
Destructor.
bool exists(const Key &k) const
Indicates whether a given elements belong to the set.
Definition: set_tpl.h:607
BayesNet< GUM_SCALAR > _bayesNet
BayesNet< GUM_SCALAR > _bayesNettemp
void __transformPoly(Idx nbiter)
The function that randomly change the simple tree into a polytree.
const NodeGraphPart & nodes() const
Returns a constant reference to the dag of this Bayes Net.
Definition: DAGmodel_inl.h:115
const NodeSet & parents(const NodeId id) const
returns the set of nodes with arc ingoing to a given node
void __jump_poly()
In the case that the graph is a polytree, the function will add a ramdom arc by the use of the functi...
NodeId __createPartTree(Size BNSize, Idx &n)
The internal function used by __createTree that randomly generate a simple tree.
void setIteration(Size iteration)
Modifies the value of the number of iterations impose on the BayesNetGenerator.
void disturbBN(BayesNet< GUM_SCALAR > &bayesNetinit, Size iteration=0)
Change randomly the topology of a specific bayesian networks.
void __chooseNodes(NodeId &i, NodeId &j)
The function that randomly choose two nodes of the graph.
const NodeSet & children(const NodeId id) const
returns the set of nodes with arc outgoing from a given node
virtual const Potential< GUM_SCALAR > & posterior(NodeId node) final
Computes and returns the posterior of a node.
void __AR()
The function will remove and add a random arc changing the topology of the graph but asserting its co...
<agrum/BN/inference/lazyPropagation.h>
void __insertArc(NodeId i, NodeId j)
The function that will insert an arc between node i to node j, but only if there isn&#39;t any cycle crea...
void generateBN(BayesNet< GUM_SCALAR > &bayesNet) override
Generates a random bayesian network.
void __eraseArc(NodeId i, NodeId j, bool mustbeconnex=true)
The function that will remove the arc between node i and node j.
void __chooseCloseNodes(NodeId &i, NodeId &j)
The function that randomly choose two neighbours nodes of the graph.
Size Idx
Type for indexes.
Definition: types.h:53
void __AorR()
The function will add or remove a random arc in the graph using the functions __insertArc and __remov...
Size iteration() const
Return a constant reference to the number of iteration imposed on the Markov Chain BayesNetGenerator...
void __PMMx_multi()
In the case that the graph is a multiconnected graph, the function will, according to the probability...
bool __directedPath(NodeId tail, NodeId head)
The function that verify if there is a oriented path from node i to node j.
std::size_t Size
In aGrUM, hashed values are unsigned long int.
Definition: types.h:48
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
void __createTree(Size BNSize)
The function that randomly generate a simple tree.
Base class for dag.
Definition: DAG.h:102
Idx p() const
Return a constant reference to the probabilité p imposed on the Markov Chain BayesNetGenerator.
bool existsArc(const Arc &arc) const
indicates whether a given arc exists
Size NodeId
Type for node ids.
Definition: graphElements.h:98
void insert(const Key &k)
Inserts a new element into the set.
Definition: set_tpl.h:613
#define GUM_ERROR(type, msg)
Definition: exceptions.h:55
HashTable< NodeId, Potential< GUM_SCALAR > *> _hashMarginal