aGrUM  0.18.1
a C++ library for (probabilistic) graphical models
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__();
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);
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.
void jump_multi__()
In the case that the graph is a multiconnect graph, the function will choose randomly two nodes and w...
const DiscreteVariable & variable(NodeId id) const final
Returns a gum::DiscreteVariable given its gum::NodeId in the gum::BayesNet.
Definition: BayesNet_tpl.h:214
class LabelizedVariable
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...
void AorR__()
The function will add or remove a random arc in the graph using the functions insertArc__ and removeA...
bool directedPath__(NodeId tail, NodeId head)
The function that verify if there is a oriented path from node i to node j.
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.
void transformPoly__(Idx nbiter)
The function that randomly change the simple tree into a polytree.
<agrum/BN/generator/MCayesNetGenerator.h>
void fillCPT()
function that insert random values in the CPT of each nodes according to the CPTGenerator.
void createTree__(Size BNSize)
The function that randomly generate a simple tree.
gum::Size getMaxModality(gum::BayesNet< GUM_SCALAR > &bayesNet)
void setQ(Idx q)
Modifies the value of the probability q imposed on the BayesNetGenerator.
virtual bool checkConditions__()
The boolean function that will assert the respect of the constraint.
Copyright 2005-2020 Pierre-Henri WUILLEMIN() & Christophe GONZALES() info_at_agrum_dot_org.
Definition: agrum.h:25
void eraseArc__(NodeId i, NodeId j, bool mustbeconnex=true)
The function that will remove the arc between node i and node j.
void PMMx_poly__()
In the case that the graph is a polytree, the function will, according to the probability p and q...
HashTable< NodeId, Potential< GUM_SCALAR > *> hashMarginal_
virtual void copy(const MultiDimContainer< GUM_SCALAR > &src)
Removes all variables in this MultiDimContainer and copy the content of src, variables included...
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
bool isPolytree__()
The function that verify if graph is a polytree.
const NodeGraphPart & nodes() const
Returns a constant reference to the dag of this Bayes Net.
Definition: DAGmodel_inl.h:70
const NodeSet & parents(const NodeId id) const
returns the set of nodes with arc ingoing to a given node
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
bool connect__(NodeId i, NodeId j)
The function that verify if node i and j are connected.
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...
virtual const Potential< GUM_SCALAR > & posterior(NodeId node) final
Computes and returns the posterior of a node.
<agrum/BN/inference/lazyPropagation.h>
void generateBN(BayesNet< GUM_SCALAR > &bayesNet) override
Generates a random bayesian network.
void PMMx_multi__()
In the case that the graph is a multiconnected graph, the function will, according to the probability...
Size Idx
Type for indexes.
Definition: types.h:53
void chooseCloseNodes__(NodeId &i, NodeId &j)
The function that randomly choose two neighbours nodes of the graph.
Size iteration() const
Return a constant reference to the number of iteration imposed on the Markov Chain BayesNetGenerator...
std::size_t Size
In aGrUM, hashed values are unsigned long int.
Definition: types.h:48
BayesNet< GUM_SCALAR > bayesNet_
BayesNet< GUM_SCALAR > bayesNettemp_
void AR__()
The function will remove and add a random arc changing the topology of the graph but asserting its co...
Copyright 2005-2020 Pierre-Henri WUILLEMIN() & Christophe GONZALES() info_at_agrum_dot_org.
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