aGrUM  0.18.1
a C++ library for (probabilistic) graphical models
credalNet_tpl.h
Go to the documentation of this file.
1 
23 #include <agrum/CN/credalNet.h>
24 #include <agrum/agrum.h>
26 
27 namespace gum {
28  namespace credal {
29 
30  template < typename GUM_SCALAR >
32  initParams__();
33 
34  src_bn__ = BayesNet< GUM_SCALAR >();
35  src_bn_min__ = BayesNet< GUM_SCALAR >();
36  src_bn_max__ = BayesNet< GUM_SCALAR >();
37 
38  GUM_CONSTRUCTOR(CredalNet);
39  }
40 
41  template < typename GUM_SCALAR >
43  const Size& card) {
44  LabelizedVariable var(name, "node " + name, card);
45 
46  NodeId a = src_bn__.add(var);
47  NodeId b = src_bn_min__.add(var);
48  NodeId c = src_bn_max__.add(var);
49 
50  if (a != b || a != c /*|| b != c*/)
52  "addVariable : not the same id over all networks : "
53  << a << ", " << b << ", " << c);
54 
55  return a;
56  }
57 
58  template < typename GUM_SCALAR >
59  void CredalNet< GUM_SCALAR >::addArc(const NodeId& tail, const NodeId& head) {
60  src_bn__.addArc(tail, head);
61  src_bn_min__.addArc(tail, head);
62  src_bn_max__.addArc(tail, head);
63  }
64 
65  template < typename GUM_SCALAR >
67  const NodeId& id,
68  const std::vector< std::vector< std::vector< GUM_SCALAR > > >& cpt) {
69  const Potential< GUM_SCALAR >* const potential(&src_bn__.cpt(id));
70 
71  auto var_dSize = src_bn__.variable(id).domainSize();
72  auto entry_size = potential->domainSize() / var_dSize;
73 
74  if (cpt.size() != entry_size)
76  "setCPTs : entry sizes of cpts does not match for node id : "
77  << id << " : " << cpt.size() << " != " << entry_size);
78 
79  for (const auto& cset: cpt) {
80  if (cset.size() == 0)
81  GUM_ERROR(
82  SizeError,
83  "setCPTs : vertices in credal set does not match for node id : "
84  << id << " with 0 vertices");
85 
86  for (const auto& vertex: cset) {
87  if (vertex.size() != var_dSize)
89  "setCPTs : variable modalities in cpts does "
90  "not match for node id : "
91  << id << " with vertex " << vertex << " : "
92  << vertex.size() << " != " << var_dSize);
93 
94  GUM_SCALAR sum = 0;
95 
96  for (const auto& prob: vertex) {
97  sum += prob;
98  }
99 
100  if (std::fabs(sum - 1) > 1e-6)
102  "setCPTs : a vertex coordinates does not "
103  "sum to one for node id : "
104  << id << " with vertex " << vertex);
105  }
106  }
107 
108  credalNet_src_cpt__.insert(id, cpt);
109  }
110 
111  template < typename GUM_SCALAR >
113  const NodeId& id,
114  Size& entry,
115  const std::vector< std::vector< GUM_SCALAR > >& cpt) {
116  const Potential< GUM_SCALAR >* const potential(&src_bn__.cpt(id));
117 
118  auto var_dSize = src_bn__.variable(id).domainSize();
119  auto entry_size = potential->domainSize() / var_dSize;
120 
121  if (entry >= entry_size)
123  "setCPT : entry is greater or equal than entry size "
124  "(entries start at 0 up to entry_size - 1) : "
125  << entry << " >= " << entry_size);
126 
127  if (cpt.size() == 0)
128  GUM_ERROR(SizeError, "setCPT : empty credal set for entry : " << entry);
129 
130  for (const auto& vertex: cpt) {
131  if (vertex.size() != var_dSize)
133  "setCPT : variable modalities in cpts does not "
134  "match for node id : "
135  << id << " with vertex " << vertex << " at entry " << entry
136  << " : " << vertex.size() << " != " << var_dSize);
137 
138  GUM_SCALAR sum = 0;
139 
140  for (const auto& prob: vertex) {
141  sum += prob;
142  }
143 
144  if (std::fabs(sum - 1) > 1e-6)
145  GUM_ERROR(
146  CPTNoSumTo1,
147  "setCPT : a vertex coordinates does not sum to one for node id : "
148  << id << " at entry " << entry << " with vertex " << vertex);
149  }
150 
151  // !! auto does NOT use adress (if available) unless explicitly asked !!
152  auto& node_cpt = credalNet_src_cpt__.getWithDefault(
153  id, std::vector< std::vector< std::vector< GUM_SCALAR > > >(entry_size));
154 
155  if (node_cpt[entry].size() != 0)
157  "setCPT : vertices of entry id "
158  << entry << " already set to : " << node_cpt[entry]
159  << ", cannot insert : " << cpt);
160 
161  node_cpt[entry] = cpt;
162 
164  }
165 
166  template < typename GUM_SCALAR >
168  const NodeId& id,
169  Instantiation ins,
170  const std::vector< std::vector< GUM_SCALAR > >& cpt) {
171  const Potential< GUM_SCALAR >* const potential(&src_bn__.cpt(id));
172 
173  auto var_dSize = src_bn__.variable(id).domainSize();
174  auto entry_size = potential->domainSize() / var_dSize;
175 
176  // to be sure of entry index reorder ins according to the bayes net
177  // potentials
178  // ( of the credal net )
179  // it WONT throw an error if the sequences are not equal not because of
180  // order
181  // but content, so we double check (before & after order correction)
182  // beware of slaves & master
183  Instantiation ref(potential);
184  ref.forgetMaster();
185 
186  ins.forgetMaster();
187 
188  const auto& vseq = ref.variablesSequence();
189 
190  if (ins.variablesSequence() != vseq) {
191  ins.reorder(ref);
192 
193  if (ins.variablesSequence() != vseq)
195  "setCPT : instantiation : "
196  << ins << " is not valid for node id " << id
197  << " which accepts instantiations such as (order is not "
198  "important) : "
199  << ref);
200  }
201 
202  Idx entry = 0, jump = 1;
203 
204  for (Idx i = 0, end = ins.nbrDim(); i < end; i++) {
205  if (src_bn__.nodeId(ins.variable(i)) == id) continue;
206 
207  entry += ins.val(i) * jump;
208 
209  jump *= ins.variable(i).domainSize();
210  }
211 
212  if (entry >= entry_size)
214  "setCPT : entry is greater or equal than entry size "
215  "(entries start at 0 up to entry_size - 1) : "
216  << entry << " >= " << entry_size);
217 
218  if (cpt.size() == 0)
219  GUM_ERROR(SizeError, "setCPT : empty credal set for entry : " << entry);
220 
221  for (const auto& vertex: cpt) {
222  if (vertex.size() != var_dSize)
224  "setCPT : variable modalities in cpts does not "
225  "match for node id : "
226  << id << " with vertex " << vertex << " at entry " << entry
227  << " : " << vertex.size() << " != " << var_dSize);
228 
229  GUM_SCALAR sum = 0;
230 
231  for (const auto& prob: vertex) {
232  sum += prob;
233  }
234 
235  if (std::fabs(sum - 1) > 1e-6)
236  GUM_ERROR(
237  CPTNoSumTo1,
238  "setCPT : a vertex coordinates does not sum to one for node id : "
239  << id << " at entry " << entry << " with vertex " << vertex);
240  }
241 
242  auto& node_cpt = credalNet_src_cpt__.getWithDefault(
243  id, std::vector< std::vector< std::vector< GUM_SCALAR > > >(entry_size));
244 
245  if (node_cpt[entry].size() != 0)
247  "setCPT : vertices of entry : "
248  << ins << " id " << entry << " already set to : "
249  << node_cpt[entry] << ", cannot insert : " << cpt);
250 
251  node_cpt[entry] = cpt;
252 
254  }
255 
256  template < typename GUM_SCALAR >
258  const NodeId& id,
259  const std::vector< GUM_SCALAR >& lower,
260  const std::vector< GUM_SCALAR >& upper) {
261  try {
262  src_bn_min__.cpt(id).fillWith(lower);
263  src_bn_max__.cpt(id).fillWith(upper);
264  } catch (const SizeError&) {
265  GUM_ERROR(
266  SizeError,
267  "fillConstraints : sizes does not match in fillWith for node id : "
268  << id);
269  }
270  }
271 
272  template < typename GUM_SCALAR >
274  const NodeId& id,
275  const Idx& entry,
276  const std::vector< GUM_SCALAR >& lower,
277  const std::vector< GUM_SCALAR >& upper) {
278  Potential< GUM_SCALAR >* const potential_min(
279  const_cast< Potential< GUM_SCALAR >* const >(&src_bn_min__.cpt(id)));
280  Potential< GUM_SCALAR >* const potential_max(
281  const_cast< Potential< GUM_SCALAR >* const >(&src_bn_max__.cpt(id)));
282 
283  auto var_dSize = src_bn__.variable(id).domainSize();
284 
285  if (lower.size() != var_dSize || upper.size() != var_dSize)
286  GUM_ERROR(
287  SizeError,
288  "setCPT : variable modalities in cpts does not match for node id : "
289  << id << " with sizes of constraints : ( " << lower.size() << " || "
290  << upper.size() << " ) != " << var_dSize);
291 
292  auto entry_size = potential_min->domainSize() / var_dSize;
293 
294  if (entry >= entry_size)
296  "setCPT : entry is greater or equal than entry size "
297  "(entries start at 0 up to entry_size - 1) : "
298  << entry << " >= " << entry_size);
299 
300  Instantiation min(potential_min);
301  Instantiation max(potential_max);
302  min.setFirst();
303  max.setFirst();
304 
305  Idx pos = 0;
306 
307  while (pos != entry) {
308  ++min;
309  ++max;
310  ++pos;
311  }
312 
313  for (Size i = 0; i < var_dSize; i++) {
314  potential_min->set(min, lower[i]);
315  potential_max->set(max, upper[i]);
316  ++min;
317  ++max;
318  }
319  }
320 
321  template < typename GUM_SCALAR >
323  const NodeId& id,
324  Instantiation ins,
325  const std::vector< GUM_SCALAR >& lower,
326  const std::vector< GUM_SCALAR >& upper) {
327  const Potential< GUM_SCALAR >* const potential(&src_bn__.cpt(id));
328  /*
329  auto var_dSize = src_bn__.variable ( id ).domainSize();
330  auto entry_size = potential->domainSize() / var_dSize;
331  */
332  // to be sure of entry index reorder ins according to the bayes net
333  // potentials
334  // ( of the credal net )
335  // it WONT throw an error if the sequences are not equal not because of
336  // order
337  // but content, so we double check (before & after order correction)
338  // beware of slaves & master
339  Instantiation ref(potential);
340  ref.forgetMaster();
341 
342  ins.forgetMaster();
343 
344  const auto& vseq = ref.variablesSequence();
345 
346  if (ins.variablesSequence() != vseq) {
347  ins.reorder(ref);
348 
349  if (ins.variablesSequence() != vseq)
351  "setCPT : instantiation : "
352  << ins << " is not valid for node id " << id
353  << " which accepts instantiations such as (order is not "
354  "important) : "
355  << ref);
356  }
357 
358  Idx entry = 0, jump = 1;
359 
360  for (Idx i = 0, end = ins.nbrDim(); i < end; i++) {
361  if (src_bn__.nodeId(ins.variable(i)) == id) continue;
362 
363  entry += ins.val(i) * jump;
364 
365  jump *= ins.variable(i).domainSize();
366  }
367 
368  /*
369  if ( entry >= entry_size )
370  GUM_ERROR ( SizeError, "setCPT : entry is greater or equal than entry
371  size
372  (entries start at 0 up to entry_size - 1) : " << entry << " >= " <<
373  entry_size
374  );
375 
376  if ( lower.size() != var_dSize || upper.size() != var_dSize )
377  GUM_ERROR ( SizeError, "setCPT : variable modalities in cpts does not
378  match
379  for node id : " << id << " with sizes of constraints : ( "<< lower.size()
380  << "
381  || " << upper.size() << " ) != " << var_dSize );
382  */
383  fillConstraint(id, entry, lower, upper);
384  }
385 
388 
389  template < typename GUM_SCALAR >
391  return Instantiation(src_bn__.cpt(id));
392  }
393 
394  template < typename GUM_SCALAR >
396  return src_bn__.variable(id).domainSize();
397  }
398 
400 
401  template < typename GUM_SCALAR >
402  CredalNet< GUM_SCALAR >::CredalNet(const std::string& src_min_num,
403  const std::string& src_max_den) {
404  try {
405  initParams__();
406  initCNNets__(src_min_num, src_max_den);
407  } catch (Exception& err) {
408  GUM_SHOWERROR(err);
409  throw(err);
410  }
411 
412  GUM_CONSTRUCTOR(CredalNet);
413  }
414 
415  template < typename GUM_SCALAR >
417  const BayesNet< GUM_SCALAR >& src_max_den) {
418  try {
419  initParams__();
420  initCNNets__(src_min_num, src_max_den);
421  } catch (Exception& err) {
422  GUM_SHOWERROR(err);
423  throw(err);
424  }
425 
426  GUM_CONSTRUCTOR(CredalNet);
427  }
428 
429  template < typename GUM_SCALAR >
431  if (current_bn__ != nullptr) delete current_bn__;
432 
433  if (credalNet_current_cpt__ != nullptr) delete credalNet_current_cpt__;
434 
435  if (current_nodeType__ != nullptr) delete current_nodeType__;
436 
437  GUM_DESTRUCTOR(CredalNet);
438  }
439 
440  // from BNs with numerators & denominators or cpts & denominators to credal
441  template < typename GUM_SCALAR >
442  void CredalNet< GUM_SCALAR >::bnToCredal(const GUM_SCALAR beta,
443  const bool oneNet,
444  const bool keepZeroes) {
445  GUM_SCALAR epsi_min = 1.;
446  GUM_SCALAR epsi_max = 0.;
447  GUM_SCALAR epsi_moy = 0.;
448  GUM_SCALAR epsi_den = 0.;
449 
450  for (auto node: src_bn().nodes()) {
451  const Potential< GUM_SCALAR >* const potential(&src_bn__.cpt(node));
452 
453  Potential< GUM_SCALAR >* const potential_min(
454  const_cast< Potential< GUM_SCALAR >* const >(&src_bn_min__.cpt(node)));
455  Potential< GUM_SCALAR >* const potential_max(
456  const_cast< Potential< GUM_SCALAR >* const >(&src_bn_max__.cpt(node)));
457 
458  Size var_dSize = src_bn__.variable(node).domainSize();
459  Size entry_size = potential->domainSize() / var_dSize;
460 
461  Instantiation ins(potential);
462  Instantiation ins_min(potential_min);
463  Instantiation ins_max(potential_max);
464 
465  ins.setFirst();
466  ins_min.setFirst();
467  ins_max.setFirst();
468 
469  std::vector< GUM_SCALAR > vertex(var_dSize);
470 
471  for (Size entry = 0; entry < entry_size; entry++) {
472  GUM_SCALAR den;
473 
474  if (oneNet)
475  den = 0;
476  else
477  den = potential_max->get(ins_max);
478 
479  Size nbm = 0;
480 
481  for (Size modality = 0; modality < var_dSize; modality++) {
482  vertex[modality] = potential->get(ins);
483 
484  if (oneNet) {
485  den += vertex[modality];
486 
487  if (vertex[modality] < 1 && vertex[modality] > 0)
489  "bnToCredal : the BayesNet contains "
490  "probabilities and not event counts "
491  "although user precised oneNet = "
492  << oneNet);
493  }
494 
495  if (vertex[modality] > 0) nbm++;
496 
497  ++ins;
498  }
499 
501  if (!oneNet) {
502  GUM_SCALAR sum = 0;
503 
504  for (auto modality = vertex.cbegin(), theEnd = vertex.cend();
505  modality != theEnd;
506  ++modality) {
507  sum += *modality;
508  }
509 
510  if (std::fabs(1. - sum) > epsRedund__) {
512  src_bn__.variable(node).name() << "(" << epsRedund__ << ")"
513  << " " << entry << std::endl
514  << vertex << std::endl
515  << ins << std::endl);
516  }
517  }
518 
520 
521  GUM_SCALAR epsilon;
522 
523  if (beta == 0)
524  epsilon = 0;
525  else if (den == 0 || beta == 1)
526  epsilon = GUM_SCALAR(1.0);
527  else
528  epsilon = GUM_SCALAR(std::pow(beta, std::log1p(den)));
529 
530  epsi_moy += epsilon;
531  epsi_den += 1;
532 
533  if (epsilon > epsi_max) epsi_max = epsilon;
534 
535  if (epsilon < epsi_min) epsi_min = epsilon;
536 
537  GUM_SCALAR min, max;
538 
539  for (Size modality = 0; modality < var_dSize; modality++) {
540  if ((vertex[modality] > 0 && nbm > 1) || !keepZeroes) {
541  min = GUM_SCALAR((1. - epsilon) * vertex[modality]);
542 
543  if (oneNet) min = GUM_SCALAR(min * 1.0 / den);
544 
545  max = GUM_SCALAR(min + epsilon);
546  } else { // if ( ( vertex[modality] == 0 && keepZeroes ) || (
547  // vertex[modality] > 0 && nbm <= 1 ) || ( vertex[modality] == 0
548  // && nbm <= 1 ) ) {
549  min = vertex[modality];
550 
551  if (oneNet) min = GUM_SCALAR(min * 1.0 / den);
552 
553  max = min;
554  }
555 
556  potential_min->set(ins_min, min);
557  potential_max->set(ins_max, max);
558 
559  ++ins_min;
560  ++ins_max;
561  } // end of : for each modality
562 
563  } // end of : for each entry
564 
565  } // end of : for each variable
566 
567  epsilonMin__ = epsi_min;
568  epsilonMax__ = epsi_max;
569  epsilonMoy__ = (GUM_SCALAR)epsi_moy / (GUM_SCALAR)epsi_den;
570 
571  intervalToCredal__();
572  }
573 
574  template < typename GUM_SCALAR >
576  for (auto node: src_bn__.nodes()) {
577  const Potential< GUM_SCALAR >* const potential(&src_bn__.cpt(node));
578 
579  auto var_dSize = src_bn__.variable(node).domainSize();
580  auto entry_size = potential->domainSize() / var_dSize;
581 
582  Instantiation ins(potential);
583 
584  ins.setFirst();
585 
586  std::vector< GUM_SCALAR > vertex(var_dSize);
587 
588  for (Size entry = 0; entry < entry_size; entry++) {
589  GUM_SCALAR den = 0;
590  bool zeroes = false;
591  Instantiation ins_prev = ins;
592 
593  for (Size modality = 0; modality < var_dSize; modality++) {
594  vertex[modality] = potential->get(ins);
595 
596  if (vertex[modality] < 1 && vertex[modality] > 0)
598  "lagrangeNormalization : the BayesNet "
599  "contains probabilities and not event "
600  "counts.");
601 
602  den += vertex[modality];
603 
604  if (!zeroes && vertex[modality] == 0) { zeroes = true; }
605 
606  ++ins;
607  }
608 
609  if (zeroes) {
610  ins = ins_prev;
611 
612  for (Size modality = 0; modality < var_dSize; modality++) {
613  potential->set(ins, potential->get(ins) + 1);
614  ++ins;
615  }
616  }
617 
618  } // end of : for each entry
619 
620  } // end of : for each variable
621  }
622 
623  template < typename GUM_SCALAR >
624  void CredalNet< GUM_SCALAR >::idmLearning(const Idx s, const bool keepZeroes) {
625  for (auto node: src_bn__.nodes()) {
626  const Potential< GUM_SCALAR >* const potential(&src_bn__.cpt(node));
627 
628  Potential< GUM_SCALAR >* const potential_min(
629  const_cast< Potential< GUM_SCALAR >* const >(&src_bn_min__.cpt(node)));
630  Potential< GUM_SCALAR >* const potential_max(
631  const_cast< Potential< GUM_SCALAR >* const >(&src_bn_max__.cpt(node)));
632 
633  Size var_dSize = src_bn__.variable(node).domainSize();
634  Size entry_size = potential->domainSize() / var_dSize;
635 
636  Instantiation ins(potential);
637  Instantiation ins_min(potential_min);
638  Instantiation ins_max(potential_max);
639 
640  ins.setFirst();
641  ins_min.setFirst();
642  ins_max.setFirst();
643 
644  std::vector< GUM_SCALAR > vertex(var_dSize);
645 
646  for (Size entry = 0; entry < entry_size; entry++) {
647  GUM_SCALAR den = 0;
648  Size nbm = 0;
649 
650  for (Size modality = 0; modality < var_dSize; modality++) {
651  vertex[modality] = potential->get(ins);
652 
653  if (vertex[modality] < 1 && vertex[modality] > 0)
655  "idmLearning : the BayesNet contains "
656  "probabilities and not event counts.");
657 
658  den += vertex[modality];
659 
660  if (vertex[modality] > 0) nbm++;
661 
662  ++ins;
663  }
664 
665  if (nbm > 1 || !keepZeroes) den += s;
666 
667  GUM_SCALAR min, max;
668 
669  for (Size modality = 0; modality < var_dSize; modality++) {
670  min = vertex[modality];
671  max = min;
672 
673  if ((vertex[modality] > 0 && nbm > 1) || !keepZeroes) { max += s; }
674 
675  min = GUM_SCALAR(min * 1.0 / den);
676  max = GUM_SCALAR(max * 1.0 / den);
677 
678  potential_min->set(ins_min, min);
679  potential_max->set(ins_max, max);
680 
681  ++ins_min;
682  ++ins_max;
683  } // end of : for each modality
684 
685  } // end of : for each entry
686 
687  } // end of : for each variable
688 
689  epsilonMin__ = GUM_SCALAR(s);
690  epsilonMax__ = GUM_SCALAR(s);
691  epsilonMoy__ = GUM_SCALAR(s);
692  intervalToCredal__();
693  }
694 
695  /* no need for lrs : (max ... min ... max) vertices from bnToCredal() */
696  template < typename GUM_SCALAR >
698  if (!credalNet_src_cpt__.empty()) credalNet_src_cpt__.clear();
699 
700  credalNet_src_cpt__.resize(src_bn__.size());
701 
702  for (auto node: src_bn__.nodes()) {
703  const Potential< GUM_SCALAR >* const potential_min(
704  &src_bn_min__.cpt(node));
705  const Potential< GUM_SCALAR >* const potential_max(
706  &src_bn_max__.cpt(node));
707 
708  Size var_dSize = src_bn__.variable(node).domainSize();
709  Size entry_size = potential_min->domainSize() / var_dSize;
710 
711  std::vector< std::vector< std::vector< GUM_SCALAR > > > var_cpt(
712  entry_size);
713 
714  Instantiation ins_min(potential_min);
715  Instantiation ins_max(potential_max);
716 
717  ins_min.setFirst();
718  ins_max.setFirst();
719 
720  std::vector< GUM_SCALAR > lower(var_dSize);
721  std::vector< GUM_SCALAR > upper(var_dSize);
722 
723  for (Size entry = 0; entry < entry_size; entry++) {
724  for (Size modality = 0; modality < var_dSize;
725  modality++, ++ins_min, ++ins_max) {
726  lower[modality] = potential_min->get(ins_min);
727  upper[modality] = potential_max->get(ins_max);
728  }
729 
730  bool all_equals = true;
731  std::vector< std::vector< GUM_SCALAR > > vertices;
732 
733  for (Size modality = 0; modality < var_dSize; modality++) {
734  if (std::fabs(upper[modality] - lower[modality]) < 1e-6) continue;
735 
736  all_equals = false;
737  std::vector< GUM_SCALAR > vertex(var_dSize);
738  vertex[modality] = upper[modality];
739 
740  for (Size mod = 0; mod < var_dSize; mod++) {
741  if (modality != mod) vertex[mod] = lower[mod];
742  }
743 
744  GUM_SCALAR total = 0;
745 
746  auto vsize = vertex.size();
747 
748  for (Size i = 0; i < vsize; i++)
749  total += vertex[i];
750 
751  if (std::fabs(total - 1.) > 1e-6)
753  src_bn__.variable(node).name() << " " << entry << std::endl
754  << vertex << std::endl);
755 
756  vertices.push_back(vertex);
757  }
758 
759  if (all_equals) {
760  std::vector< GUM_SCALAR > vertex(var_dSize);
761 
762  for (Size modality = 0; modality < var_dSize; modality++)
763  vertex[modality] = lower[modality];
764 
765  GUM_SCALAR total = 0.;
766 
767  auto vsize = vertex.size();
768 
769  for (Size i = 0; i < vsize; i++)
770  total += vertex[i];
771 
772  if (std::fabs(total - 1.) > 1e-6)
774  src_bn__.variable(node).name() << " " << entry << std::endl
775  << vertex << std::endl);
776 
777  vertices.push_back(vertex);
778  }
779 
780  var_cpt[entry] = vertices;
781  }
782 
783  credalNet_src_cpt__.insert(node, var_cpt);
784 
785  } // end of : for each variable (node)
786 
787  // get precise/credal/vacuous status of each variable
788  sort_varType__();
789  separatelySpecified__ = true;
790  }
791 
792  /* uses lrsWrapper */
793  template < typename GUM_SCALAR >
795  if (!credalNet_src_cpt__.empty()) credalNet_src_cpt__.clear();
796 
797  credalNet_src_cpt__.resize(src_bn__.size());
798 
799  LRSWrapper< GUM_SCALAR > lrsWrapper;
800 
801  for (auto node: src_bn__.nodes()) {
802  const Potential< GUM_SCALAR >* const potential_min(
803  &src_bn_min__.cpt(node));
804  const Potential< GUM_SCALAR >* const potential_max(
805  &src_bn_max__.cpt(node));
806 
807  Size var_dSize = src_bn__.variable(node).domainSize();
808  Size entry_size = potential_min->domainSize() / var_dSize;
809 
810  std::vector< std::vector< std::vector< GUM_SCALAR > > > var_cpt(
811  entry_size);
812 
813  Instantiation ins_min(potential_min);
814  Instantiation ins_max(potential_max);
815 
816  ins_min.setFirst();
817  ins_max.setFirst();
818 
819  lrsWrapper.setUpH(var_dSize);
820 
821  for (Size entry = 0; entry < entry_size; entry++) {
822  for (Size modality = 0; modality < var_dSize; modality++) {
823  lrsWrapper.fillH(
824  potential_min->get(ins_min), potential_max->get(ins_max), modality);
825  ++ins_min;
826  ++ins_max;
827  }
828 
829  lrsWrapper.H2V();
830  var_cpt[entry] = lrsWrapper.getOutput();
831  lrsWrapper.nextHInput();
832  }
833 
834  credalNet_src_cpt__.insert(node, var_cpt);
835 
836  } // end of : for each variable (node)
837 
838  // get precise/credal/vacuous status of each variable
839  sort_varType__();
840  separatelySpecified__ = true;
841  }
842 
843  /* call lrs */
844  template < typename GUM_SCALAR >
846  if (!credalNet_src_cpt__.empty()) credalNet_src_cpt__.clear();
847 
848  credalNet_src_cpt__.resize(src_bn__.size());
849 
850  for (auto node: src_bn__.nodes()) {
851  const Potential< GUM_SCALAR >* const potential_min(
852  &src_bn_min__.cpt(node));
853  const Potential< GUM_SCALAR >* const potential_max(
854  &src_bn_max__.cpt(node));
855 
856  auto var_dSize = src_bn__.variable(node).domainSize();
857  auto entry_size = potential_min->domainSize() / var_dSize;
858 
859  std::vector< std::vector< std::vector< GUM_SCALAR > > > var_cpt(
860  entry_size);
861 
862  Instantiation ins_min(potential_min);
863  Instantiation ins_max(potential_max);
864 
865  ins_min.setFirst();
866  ins_max.setFirst();
867 
868  // use iterator
869  for (Size entry = 0; entry < entry_size; entry++) {
870  std::vector< std::vector< GUM_SCALAR > > vertices;
871  std::vector< GUM_SCALAR > vertex(var_dSize); // if not interval
872 
873  std::vector< std::vector< GUM_SCALAR > > inequalities(
874  var_dSize * 2, std::vector< GUM_SCALAR >(var_dSize + 1, 0));
875 
876  std::vector< GUM_SCALAR > sum_ineq1(var_dSize + 1, -1);
877  std::vector< GUM_SCALAR > sum_ineq2(var_dSize + 1, 1);
878  sum_ineq1[0] = 1;
879  sum_ineq2[0] = -1;
880 
881  bool isInterval = false;
882 
883  for (Size modality = 0; modality < var_dSize; modality++) {
884  inequalities[modality * 2][0] = -potential_min->get(ins_min);
885  inequalities[modality * 2 + 1][0] = potential_max->get(ins_max);
886  inequalities[modality * 2][modality + 1] = 1;
887  inequalities[modality * 2 + 1][modality + 1] = -1;
888 
889  vertex[modality] = inequalities[modality * 2 + 1][0];
890 
891  if (!isInterval
892  && (-inequalities[modality * 2][0]
893  != inequalities[modality * 2 + 1][0]))
894  isInterval = true;
895 
896  ++ins_min;
897  ++ins_max;
898  }
899 
900  inequalities.push_back(sum_ineq1);
901  inequalities.push_back(sum_ineq2);
902 
903  if (!isInterval) {
904  vertices.push_back(vertex);
905  } else {
906  try {
907  H2Vlrs__(inequalities, vertices);
908  //__H2Vcdd ( inequalities, vertices );
909  } catch (const std::exception& err) {
910  std::cout << err.what() << std::endl;
911  throw;
912  }
913 
914  } // end of : is interval
915 
916  if (entry == 0 && vertices.size() >= 2) {
917  auto tmp = vertices[0];
918  vertices[0] = vertices[1];
919  vertices[1] = tmp;
920  }
921 
922  var_cpt[entry] = vertices;
923 
924  } // end of : for each entry
925 
926  credalNet_src_cpt__.insert(node, var_cpt);
927  // std::cout << src_bn__.variable(node_idIt).name() << std::endl;
928  // std::cout << var_cpt << std::endl;
929 
930  } // end of : for each variable (node)
931 
932  // get precise/credal/vacuous status of each variable
933  sort_varType__();
934  separatelySpecified__ = true;
935  }
936 
941  template < typename GUM_SCALAR >
942  void
943  CredalNet< GUM_SCALAR >::saveBNsMinMax(const std::string& min_path,
944  const std::string& max_path) const {
946 
947  std::string minfilename = min_path; //"min.bif";
948  std::string maxfilename = max_path; //"max.bif";
949  std::ofstream min_file(minfilename.c_str(), std::ios::out | std::ios::trunc);
950  std::ofstream max_file(maxfilename.c_str(), std::ios::out | std::ios::trunc);
951 
952  if (!min_file.good())
953  GUM_ERROR(
954  IOError,
955  "bnToCredal() : could not open stream : min_file : " << minfilename);
956 
957  if (!max_file.good()) {
958  min_file.close();
959  GUM_ERROR(
960  IOError,
961  "bnToCredal() : could not open stream : min_file : " << maxfilename);
962  }
963 
964  try {
965  writer.write(min_file, src_bn_min__);
966  writer.write(max_file, src_bn_max__);
967  } catch (Exception& err) {
968  GUM_SHOWERROR(err);
969  min_file.close();
970  max_file.close();
971  throw(err);
972  }
973 
974  min_file.close();
975  max_file.close();
976  }
977 
978  template < typename GUM_SCALAR >
980  // don't forget to delete the old one (current__), if necessary at the end
982 
983  //__bnCopy ( *bin_bn__ );
984  // delete old one too
985  auto credalNet_bin_cpt__ = new NodeProperty<
986  std::vector< std::vector< std::vector< GUM_SCALAR > > > >();
987 
988  // delete old one too
989  NodeProperty< NodeType >* bin_nodeType__ = new NodeProperty< NodeType >();
990 
991  const BayesNet< GUM_SCALAR >* current_bn__;
992  // const NodeProperty< nodeType > *current_nodeType__;
993  const NodeProperty<
994  std::vector< std::vector< std::vector< GUM_SCALAR > > > >*
995  credalNet_current_cpt__;
996 
997  if (this->current_bn__ == nullptr)
998  current_bn__ = &this->src_bn__;
999  else
1000  current_bn__ = this->current_bn__;
1001 
1002  if (this->credalNet_current_cpt__ == nullptr)
1003  credalNet_current_cpt__ = &this->credalNet_src_cpt__;
1004  else
1005  credalNet_current_cpt__ = this->credalNet_current_cpt__;
1006 
1007  /*if ( this->current_nodeType__ == nullptr )
1008  current_nodeType__ = & this->nodeType__;
1009  else
1010  current_nodeType__ = this->current_nodeType__;*/
1011 
1012  if (!var_bits__.empty()) var_bits__.clear();
1013 
1014  bin_bn__->beginTopologyTransformation();
1015 
1016  for (auto node: current_bn__->nodes()) {
1017  auto var_dSize = current_bn__->variable(node).domainSize();
1018 
1019  if (var_dSize != 2) {
1020  unsigned long b, c;
1021  superiorPow((unsigned long)var_dSize, b, c);
1022  Size nb_bits{Size(b)};
1023 
1024  std::string bit_name;
1025  std::vector< NodeId > bits(nb_bits);
1026 
1027  for (Size bit = 0; bit < nb_bits; bit++) {
1028  bit_name = current_bn__->variable(node).name() + " - bit - ";
1029  std::stringstream ss;
1030  ss << bit;
1031  bit_name += ss.str();
1032 
1033  LabelizedVariable var_bit(bit_name, "node " + bit_name, 2);
1034  NodeId iD = bin_bn__->add(var_bit);
1035 
1036  bits[bit] = iD;
1037  } // end of : for each bit
1038 
1039  var_bits__.insert(node, bits);
1040 
1041  } // end of : if variable is not binary
1042  else {
1043  std::string bit_name = current_bn__->variable(node).name();
1044  LabelizedVariable var_bit(bit_name, "node " + bit_name, 2);
1045  NodeId iD = bin_bn__->add(var_bit);
1046 
1047  var_bits__.insert(node, std::vector< NodeId >(1, iD));
1048  }
1049 
1050  } // end of : for each original variable
1051 
1052  for (auto node: current_bn__->nodes()) {
1053  NodeSet parents = current_bn__->parents(node);
1054 
1055  if (!parents.empty()) {
1056  for (auto par: current_bn__->parents(node)) {
1057  for (Size parent_bit = 0, spbits = Size(var_bits__[par].size());
1058  parent_bit < spbits;
1059  parent_bit++)
1060  for (Size var_bit = 0, mbits = Size(var_bits__[node].size());
1061  var_bit < mbits;
1062  var_bit++)
1063  bin_bn__->addArc(var_bits__[par][parent_bit],
1064  var_bits__[node][var_bit]);
1065  }
1066  }
1067 
1068  // arcs with one's bits
1069  auto bitsize = var_bits__[node].size();
1070 
1071  for (Size bit_c = 1; bit_c < bitsize; bit_c++)
1072  for (Size bit_p = 0; bit_p < bit_c; bit_p++)
1073  bin_bn__->addArc(var_bits__[node][bit_p], var_bits__[node][bit_c]);
1074 
1075  } // end of : for each original variable
1076 
1077  bin_bn__->endTopologyTransformation();
1078 
1079  // binarization of cpts
1080 
1081  auto varsize = current_bn__->size();
1082 
1083  for (Size var = 0; var < varsize; var++) {
1084  auto bitsize = var_bits__[var].size();
1085 
1086  for (Size i = 0; i < bitsize; i++) {
1087  Potential< GUM_SCALAR > const* potential(
1088  &bin_bn__->cpt(var_bits__[var][i]));
1089  Instantiation ins(potential);
1090  ins.setFirst();
1091 
1092  auto entry_size = potential->domainSize() / 2;
1093  std::vector< std::vector< std::vector< GUM_SCALAR > > > var_cpt(
1094  entry_size);
1095 
1096  Size old_conf = 0;
1097 
1098  for (Size conf = 0; conf < entry_size; conf++) {
1099  std::vector< std::vector< GUM_SCALAR > > pvar_cpt;
1100  auto verticessize = (*credalNet_current_cpt__)[var][old_conf].size();
1101 
1102  for (Size old_distri = 0; old_distri < verticessize; old_distri++) {
1103  const std::vector< GUM_SCALAR >& vertex =
1104  (*credalNet_current_cpt__)[var][old_conf][old_distri];
1105  auto vertexsize = vertex.size();
1106 
1107  std::vector< Idx > incc(vertexsize, 0);
1108 
1109  for (Size preced = 0; preced < i; preced++) {
1110  auto bit_pos =
1111  ins.pos(bin_bn__->variable(var_bits__[var][preced]));
1112  auto val = ins.val(bit_pos);
1113 
1114  Size pas = Size(int2Pow((unsigned long)preced));
1115  Size elem;
1116 
1117  if (val == 0)
1118  elem = 0;
1119  else
1120  elem = pas;
1121 
1122  while (elem < vertexsize) {
1123  incc[elem]++;
1124  elem++;
1125 
1126  if (elem % pas == 0) elem += pas;
1127  }
1128  }
1129 
1130  Size pas = Size(int2Pow((unsigned long)i));
1131 
1132  std::vector< GUM_SCALAR > distri(2, 0);
1133  int pos = 1;
1134 
1135  for (Size elem = 0; elem < vertexsize; elem++) {
1136  if (elem % pas == 0) pos = -pos;
1137 
1138  if (incc[elem] == i)
1139  (pos < 0) ? (distri[0] += vertex[elem])
1140  : (distri[1] += vertex[elem]);
1141  }
1142 
1143  if (i > 0) {
1144  GUM_SCALAR den = distri[0] + distri[1];
1145 
1146  if (den == 0) {
1147  distri[0] = 0;
1148  distri[1] = 0;
1149  } else {
1150  distri[0] /= den;
1151  distri[1] /= den;
1152  }
1153  }
1154 
1155  pvar_cpt.push_back(distri);
1156 
1157  } // end of old distris
1158 
1159  // get min/max approx, 2 vertices
1160  std::vector< std::vector< GUM_SCALAR > > vertices(
1161  2, std::vector< GUM_SCALAR >(2, 1));
1162  vertices[1][1] = 0;
1163 
1164  auto new_verticessize = pvar_cpt.size();
1165 
1166  for (Size v = 0; v < new_verticessize; v++) {
1167  if (pvar_cpt[v][1] < vertices[0][1]) vertices[0][1] = pvar_cpt[v][1];
1168 
1169  if (pvar_cpt[v][1] > vertices[1][1]) vertices[1][1] = pvar_cpt[v][1];
1170  }
1171 
1172  vertices[0][0] = 1 - vertices[0][1];
1173  vertices[1][0] = 1 - vertices[1][1];
1174 
1175  pvar_cpt = vertices;
1176 
1177  var_cpt[conf] = pvar_cpt;
1178 
1179  ++ins;
1180  ++ins;
1181 
1182  old_conf++;
1183 
1184  if (old_conf == (*credalNet_current_cpt__)[var].size()) old_conf = 0;
1185 
1186  } // end of new parent conf
1187 
1188  credalNet_bin_cpt__->insert(var_bits__[var][i], var_cpt);
1189 
1190  } // end of bit i
1191 
1192  } // end of old variable
1193 
1194  bin_bn__->beginTopologyTransformation();
1195 
1196  /* indicatrices variables */
1197  auto old_varsize = var_bits__.size();
1198 
1199  for (Size i = 0; i < old_varsize; i++) {
1200  auto bitsize = var_bits__[i].size();
1201 
1202  // binary variable
1203  if (bitsize == 1) continue;
1204 
1205  auto old_card = src_bn__.variable(i).domainSize();
1206 
1207  for (Size mod = 0; mod < old_card; mod++) {
1208  std::string s;
1209  s = "I-";
1210  std::stringstream ss;
1211  ss << src_bn__.variable(i).name();
1212  ss << "-";
1213  ss << mod;
1214  s += ss.str();
1215 
1216  LabelizedVariable var(s, "node " + s, 2);
1217  const NodeId indic = bin_bn__->add(var);
1218 
1219  // arcs from one's bits
1220  for (Size bit = 0; bit < bitsize; bit++)
1221  bin_bn__->addArc(var_bits__[i][bit], indic);
1222 
1223  // cpt
1224  Size num = Size(int2Pow(long(bitsize)));
1225 
1226  std::vector< std::vector< std::vector< GUM_SCALAR > > > icpt(num);
1227 
1228  for (Size entry = 0; entry < num; entry++) {
1229  std::vector< std::vector< GUM_SCALAR > > vertices(
1230  1, std::vector< GUM_SCALAR >(2, 0));
1231 
1232  if (i == entry)
1233  vertices[0][1] = 1;
1234  else
1235  vertices[0][0] = 1;
1236 
1237  icpt[entry] = vertices;
1238  }
1239 
1240  credalNet_bin_cpt__->insert(indic, icpt);
1241 
1242  bin_nodeType__->insert(indic, NodeType::Indic);
1243  } // end of each modality, i.e. as many indicatrice
1244  }
1245 
1246  bin_bn__->endTopologyTransformation();
1247 
1248  if (this->current_bn__ != nullptr) delete this->current_bn__;
1249 
1250  this->current_bn__ = bin_bn__;
1251 
1252  if (this->credalNet_current_cpt__ != nullptr)
1253  delete this->credalNet_current_cpt__;
1254 
1255  this->credalNet_current_cpt__ = credalNet_bin_cpt__;
1256 
1257  if (this->current_nodeType__ != nullptr) delete this->current_nodeType__;
1258 
1259  this->current_nodeType__ = bin_nodeType__;
1260 
1261  sort_varType__(); // will fill bin_nodeType__ except for NodeType::Indic
1262  // variables
1263  }
1264 
1265  template < typename GUM_SCALAR >
1268  if (credalNet_current_cpt__ != nullptr) return *credalNet_current_cpt__;
1269 
1270  return credalNet_src_cpt__;
1271  }
1272 
1273  template < typename GUM_SCALAR >
1276  return credalNet_src_cpt__;
1277  }
1278 
1279  template < typename GUM_SCALAR >
1282  if (current_nodeType__ != nullptr) return (*(current_nodeType__))[id];
1283 
1284  return original_nodeType__[id];
1285  }
1286 
1287  template < typename GUM_SCALAR >
1290  return original_nodeType__[id];
1291  }
1292 
1293  template < typename GUM_SCALAR >
1295  return separatelySpecified__;
1296  }
1297 
1298  template < typename GUM_SCALAR >
1300  return hasComputedCPTMinMax__;
1301  }
1302 
1303  // only if CN is binary !!
1304  template < typename GUM_SCALAR >
1306  binCptMin__.resize(current_bn().size());
1307  binCptMax__.resize(current_bn().size());
1308 
1309  for (auto node: current_bn().nodes()) {
1310  auto pConf = credalNet_currentCpt()[node].size();
1311  std::vector< GUM_SCALAR > min(pConf);
1312  std::vector< GUM_SCALAR > max(pConf);
1313 
1314  for (Size pconf = 0; pconf < pConf; pconf++) {
1315  GUM_SCALAR v1, v2;
1316  v1 = credalNet_currentCpt()[node][pconf][0][1];
1317 
1318  if (credalNet_currentCpt()[node][pconf].size() > 1)
1319  v2 = credalNet_currentCpt()[node][pconf][1][1];
1320  else
1321  v2 = v1;
1322 
1323  GUM_SCALAR delta = v1 - v2;
1324  min[pconf] = (delta >= 0) ? v2 : v1;
1325  max[pconf] = (delta >= 0) ? v1 : v2;
1326  }
1327 
1328  binCptMin__[node] = min;
1329  binCptMax__[node] = max;
1330  }
1331 
1332  hasComputedCPTMinMax__ = true;
1333  }
1334 
1335  template < typename GUM_SCALAR >
1336  const std::vector< std::vector< GUM_SCALAR > >&
1338  return binCptMin__;
1339  }
1340 
1341  template < typename GUM_SCALAR >
1342  const std::vector< std::vector< GUM_SCALAR > >&
1344  return binCptMax__;
1345  }
1346 
1347  template < typename GUM_SCALAR >
1348  const GUM_SCALAR& CredalNet< GUM_SCALAR >::epsilonMin() const {
1349  return epsilonMin__;
1350  }
1351 
1352  template < typename GUM_SCALAR >
1353  const GUM_SCALAR& CredalNet< GUM_SCALAR >::epsilonMax() const {
1354  return epsilonMax__;
1355  }
1356 
1357  template < typename GUM_SCALAR >
1358  const GUM_SCALAR& CredalNet< GUM_SCALAR >::epsilonMean() const {
1359  return epsilonMoy__;
1360  }
1361 
1362  template < typename GUM_SCALAR >
1364  std::stringstream output;
1365  const BayesNet< GUM_SCALAR >* current_bn__;
1366  const NodeProperty<
1367  std::vector< std::vector< std::vector< GUM_SCALAR > > > >*
1368  credalNet_current_cpt__;
1369 
1370  if (this->current_bn__ == nullptr)
1371  current_bn__ = &this->src_bn__;
1372  else
1373  current_bn__ = this->current_bn__;
1374 
1375  if (this->credalNet_current_cpt__ == nullptr)
1376  credalNet_current_cpt__ = &this->credalNet_src_cpt__;
1377  else
1378  credalNet_current_cpt__ = this->credalNet_current_cpt__;
1379 
1380  for (auto node: current_bn__->nodes()) {
1381  const Potential< GUM_SCALAR >* potential(&current_bn__->cpt(node));
1382  auto pconfs =
1383  potential->domainSize() / current_bn__->variable(node).domainSize();
1384 
1385  output << "\n" << current_bn__->variable(node) << "\n";
1386 
1387  Instantiation ins(potential);
1388  ins.forgetMaster();
1389  ins.erase(current_bn__->variable(node));
1390  ins.setFirst();
1391 
1392  for (Size pconf = 0; pconf < pconfs; pconf++) {
1393  output << ins << " : ";
1394  output << (*credalNet_current_cpt__)[node][pconf] << "\n";
1395 
1396  if (pconf < pconfs - 1) ++ins;
1397  }
1398  }
1399 
1400  output << "\n";
1401 
1402  return output.str();
1403  }
1404 
1405  template < typename GUM_SCALAR >
1407  if (current_bn__ != nullptr) return *current_bn__;
1408 
1409  return src_bn__;
1410  }
1411 
1412  template < typename GUM_SCALAR >
1414  return src_bn__;
1415  }
1416 
1418 
1420 
1421  template < typename GUM_SCALAR >
1423  epsilonMin__ = 0;
1424  epsilonMax__ = 0;
1425  epsilonMoy__ = 0;
1426 
1427  epsRedund__ = GUM_SCALAR(1e-6);
1428 
1429  // farey algorithm
1430  epsF__ = GUM_SCALAR(1e-6);
1431  denMax__ = GUM_SCALAR(1e6); // beware LRSWrapper
1432 
1433  // continued fractions, beware LRSWrapper
1434  // decimal paces (epsC__ * precisionC__ == 1)
1435  precisionC__ = GUM_SCALAR(1e6);
1436  deltaC__ = 5;
1437 
1438  // old custom algorithm
1439  precision__ = GUM_SCALAR(1e6); // beware LRSWrapper
1440 
1441  current_bn__ = nullptr;
1442  credalNet_current_cpt__ = nullptr;
1443  current_nodeType__ = nullptr;
1444 
1445  hasComputedCPTMinMax__ = false;
1446  }
1447 
1448  template < typename GUM_SCALAR >
1449  void CredalNet< GUM_SCALAR >::initCNNets__(const std::string& src_min_num,
1450  const std::string& src_max_den) {
1451  BIFReader< GUM_SCALAR > reader(&src_bn__, src_min_num);
1452  std::string other;
1453 
1454  if (src_max_den.compare("") != 0)
1455  other = src_max_den;
1456  else
1457  other = src_min_num;
1458 
1459  BIFReader< GUM_SCALAR > reader_min(&src_bn_min__, src_min_num);
1460  BIFReader< GUM_SCALAR > reader_max(&src_bn_max__, other);
1461 
1462  try {
1463  reader.proceed();
1464  } catch (Exception& err) {
1465  GUM_SHOWERROR(err);
1466  throw(err);
1467  }
1468 
1469  try {
1470  reader_min.proceed();
1471  } catch (Exception& err) {
1472  GUM_SHOWERROR(err);
1473  throw(err);
1474  }
1475 
1476  try {
1477  reader_max.proceed();
1478  } catch (Exception& err) {
1479  GUM_SHOWERROR(err);
1480  throw(err);
1481  }
1482  }
1483 
1484  template < typename GUM_SCALAR >
1486  const BayesNet< GUM_SCALAR >& src_min_num,
1487  const BayesNet< GUM_SCALAR >& src_max_den) {
1488  src_bn__ = src_min_num;
1489  src_bn_min__ = src_min_num;
1490 
1491  if (src_max_den.size() > 0)
1492  src_bn_max__ = src_max_den;
1493  else
1494  src_bn_max__ = src_min_num;
1495  }
1496 
1497  template < typename GUM_SCALAR >
1499  const std::vector< std::vector< std::vector< GUM_SCALAR > > >& var_cpt)
1500  const {
1501  Size vertices_size = 0;
1502 
1503  for (auto entry = var_cpt.cbegin(), theEnd = var_cpt.cend(); entry != theEnd;
1504  ++entry) {
1505  if (entry->size() > vertices_size) vertices_size = Size(entry->size());
1506  }
1507 
1508  return int(vertices_size);
1509  }
1510 
1511  template < typename GUM_SCALAR >
1513  const BayesNet< GUM_SCALAR >* current_bn__;
1514 
1515  if (this->current_bn__ == nullptr)
1516  current_bn__ = &this->src_bn__;
1517  else
1518  current_bn__ = this->current_bn__;
1519 
1520  for (auto node: current_bn__->nodes())
1521  dest.add(current_bn__->variable(node));
1522 
1524 
1525  for (auto node: current_bn__->nodes()) {
1526  for (auto parent_idIt: current_bn__->cpt(node).variablesSequence()) {
1527  if (current_bn__->nodeId(*parent_idIt) != node)
1528  dest.addArc(current_bn__->nodeId(*parent_idIt), node);
1529  } // end of : for each parent in order of appearence
1530  } // end of : for each variable
1531 
1533  }
1534 
1535  /*
1536  // cdd can use real values, not just rationals / integers
1537  template< typename GUM_SCALAR >
1538  void CredalNet< GUM_SCALAR >::H2Vcdd__ ( const std::vector< std::vector<
1539  GUM_SCALAR > > & h_rep, std::vector< std::vector< GUM_SCALAR > > & v_rep )
1540  const {
1541  dd_set_global_constants();
1542 
1543  dd_MatrixPtr M, G;
1544  dd_PolyhedraPtr poly;
1545  dd_ErrorType err;
1546 
1547  unsigned int rows = h_rep.size();
1548  unsigned int cols = 0;
1549  if( h_rep.size() > 0 )
1550  cols = h_rep[0].size();
1551 
1552  M = dd_CreateMatrix( rows, cols);
1553 
1554  for ( unsigned int row = 0; row < rows; row++ )
1555  for ( unsigned int col = 0; col < cols; col++ )
1556  dd_set_d( M->matrix[row][col], h_rep[row][col] );
1557 
1558  M->representation = dd_Inequality;
1559 
1560  poly = dd_DDMatrix2Poly(M, &err);
1561  G = dd_CopyGenerators(poly);
1562 
1563  rows = G->rowsize;
1564  cols = G->colsize;
1565 
1566  v_rep.clear();
1567  for ( unsigned int row = 0; row < rows; row++ ) {
1568  std::vector< GUM_SCALAR > aRow(cols - 1);
1569 
1570  if ( *G->matrix[row][0] != 1 )
1571  GUM_ERROR(OperationNotAllowed, "__H2Vcdd : not reading a vertex");
1572 
1573  for ( unsigned int col = 0; col < cols - 1; col++ )
1574  aRow[col] = *G->matrix[row][ col + 1 ];
1575 
1576  v_rep.push_back(aRow);
1577  }
1578 
1579  dd_FreeMatrix(M);
1580  dd_FreeMatrix(G);
1581  dd_FreePolyhedra(poly);
1582 
1583  dd_free_global_constants();
1584  }
1585  */
1586 
1587  template < typename GUM_SCALAR >
1589  const std::vector< std::vector< GUM_SCALAR > >& h_rep,
1590  std::vector< std::vector< GUM_SCALAR > >& v_rep) const {
1591  // write H rep file
1592  int64_t num, den;
1593 
1594  std::string sinefile =
1595  getUniqueFileName(); // generate unique file name, we
1596  // need to add .ine or .ext for lrs
1597  // to know which input it is (Hrep
1598  // to Vrep or Vrep to Hrep)
1599  sinefile += ".ine";
1600 
1601  std::ofstream h_file(sinefile.c_str(), std::ios::out | std::ios::trunc);
1602 
1603  if (!h_file.good())
1605  "__H2Vlrs : could not open lrs input file : " << sinefile);
1606 
1607  h_file << "H - representation\n";
1608  h_file << "begin\n";
1609  h_file << h_rep.size() << ' ' << h_rep[0].size() << " rational\n";
1610 
1611  for (auto it = h_rep.cbegin(), theEnd = h_rep.cend(); it != theEnd; ++it) {
1612  for (auto it2 = it->cbegin(), theEnd2 = it->cend(); it2 != theEnd2;
1613  ++it2) {
1614  // get integer fraction from decimal value
1615  // smallest numerator & denominator is farley, also
1616  // best precision
1618  num, den, ((*it2 > 0) ? *it2 : -*it2), int64_t(denMax__), epsF__);
1619 
1620  h_file << ((*it2 > 0) ? num : -num) << '/' << den << ' ';
1621  }
1622 
1623  h_file << '\n';
1624  }
1625 
1626  h_file << "end\n";
1627  h_file.close();
1628 
1629  // call lrs
1630  // lrs arguments
1631  char* args[3];
1632 
1633  std::string soft_name = "lrs";
1634  std::string extfile(sinefile);
1635  extfile += ".ext";
1636 
1637  args[0] = new char[soft_name.size()];
1638  args[1] = new char[sinefile.size()];
1639  args[2] = new char[extfile.size()];
1640 
1641  strcpy(args[0], soft_name.c_str());
1642  strcpy(args[1], sinefile.c_str());
1643  strcpy(args[2], extfile.c_str());
1644 
1645  // standard cout to null (avoid lrs flooding)
1646  int old_cout, new_cout;
1647  fflush(stdout);
1648  old_cout = dup(1);
1649 
1650  new_cout = open("/dev/null", O_WRONLY);
1651  dup2(new_cout, 1);
1652  close(new_cout);
1653 
1654  lrs_main(3, args);
1655 
1656  // restore standard cout
1657  fflush(stdout);
1658  dup2(old_cout, 1);
1659  close(old_cout);
1660 
1661  delete[] args[2];
1662  delete[] args[1];
1663  delete[] args[0];
1664 
1665  // read V rep file
1666  std::ifstream v_file(extfile.c_str() /*extfilename.c_str()*/, std::ios::in);
1667 
1668  if (!v_file.good())
1669  GUM_ERROR(IOError, "__H2Vlrs : could not open lrs ouput file : ");
1670 
1671  std::string line, tmp;
1672  char * cstr, *p;
1673  GUM_SCALAR probability;
1674 
1675  std::string::size_type pos;
1676  bool keep_going = true;
1677  // int vertices;
1678 
1679  std::vector< GUM_SCALAR > vertex;
1680 
1681  v_file.ignore(256, 'l');
1682 
1683  while (v_file.good() && keep_going) {
1684  getline(v_file, line);
1685 
1686  if (line.size() == 0)
1687  continue;
1688  else if (line.compare("end") == 0) {
1689  keep_going = false;
1690  // this is to get vertices number :
1691  /*getline ( v_file, line );
1692  std::string::size_type pos, end_pos;
1693  pos = line.find ( "vertices = " );
1694  end_pos = line.find ( "rays", pos + 9 );
1695  vertices = atoi ( line.substr ( pos + 9, end_pos - pos - 9 ).c_str()
1696  );*/
1697  break;
1698  } else if (line[1] != '1') {
1700  "__H2Vlrs : reading something other than a vertex from "
1701  "lrs output file : ");
1702  }
1703 
1704  line = line.substr(2);
1705  cstr = new char[line.size() + 1];
1706  strcpy(cstr, line.c_str());
1707 
1708  p = strtok(cstr, " ");
1709 
1710  while (p != nullptr) {
1711  tmp = p;
1712 
1713  if (tmp.compare("1") == 0 || tmp.compare("0") == 0)
1714  probability = GUM_SCALAR(atof(tmp.c_str()));
1715  else {
1716  pos = tmp.find("/");
1717  probability =
1718  GUM_SCALAR(atof(tmp.substr(0, pos).c_str())
1719  / atof(tmp.substr(pos + 1, tmp.size()).c_str()));
1720  }
1721 
1722  vertex.push_back(probability);
1723  p = strtok(nullptr, " ");
1724  } // end of : for all tokens
1725 
1726  delete[] p;
1727  delete[] cstr;
1728 
1729  bool is_redund = false;
1730 
1731 #pragma omp parallel
1732  {
1733  int this_thread = getThreadNumber();
1734  int num_threads = getNumberOfRunningThreads();
1735 
1736  auto begin_pos = (this_thread + 0) * v_rep.size() / num_threads;
1737  auto end_pos = (this_thread + 1) * v_rep.size() / num_threads;
1738 
1739  for (auto p = begin_pos; p < end_pos; p++) {
1740 #pragma omp flush(is_redund)
1741 
1742  if (is_redund) break;
1743 
1744  bool thread_redund = true;
1745 
1746  auto vsize = vertex.size();
1747 
1748  for (Size modality = 0; modality < vsize; modality++) {
1749  if (std::fabs(vertex[modality] - v_rep[p][modality]) > epsRedund__) {
1750  thread_redund = false;
1751  break;
1752  }
1753  }
1754 
1755  if (thread_redund) {
1756  is_redund = true;
1757 #pragma omp flush(is_redund)
1758  }
1759  } // end of : each thread for
1760  } // end of : parallel
1761 
1762  if (!is_redund) v_rep.push_back(vertex);
1763 
1764  vertex.clear();
1765 
1766  } // end of : file
1767 
1768  v_file.close();
1769 
1770  if (std::remove(sinefile.c_str()) != 0)
1771  GUM_ERROR(IOError, "error removing : " + sinefile);
1772 
1773  if (std::remove(extfile.c_str()) != 0)
1774  GUM_ERROR(IOError, "error removing : " + extfile);
1775  }
1776 
1777  template < typename GUM_SCALAR >
1779  NodeProperty< NodeType >* current_nodeType__;
1780  const NodeProperty<
1781  std::vector< std::vector< std::vector< GUM_SCALAR > > > >*
1782  credalNet_current_cpt__;
1783 
1784  const BayesNet< GUM_SCALAR >* current_bn__;
1785 
1786  if (this->current_bn__ == nullptr)
1787  current_bn__ = &src_bn__;
1788  else
1789  current_bn__ = this->current_bn__;
1790 
1791  if (this->credalNet_current_cpt__ == nullptr)
1792  credalNet_current_cpt__ = &credalNet_src_cpt__;
1793  else
1794  credalNet_current_cpt__ = this->credalNet_current_cpt__;
1795 
1796  if (this->current_nodeType__ == nullptr)
1797  current_nodeType__ = &original_nodeType__;
1798  else
1799  current_nodeType__ = this->current_nodeType__;
1800 
1801  /*if ( ! current_nodeType__->empty() )
1802  current_nodeType__->clear();*/
1803 
1804  for (auto node: current_bn__->nodes()) {
1805  // indicatrices are already present
1806  if (current_nodeType__->exists(node)) continue;
1807 
1808  bool precise = true, vacuous = true;
1809 
1810  for (auto entry = (*credalNet_current_cpt__)[node].cbegin(),
1811  theEnd2 = (*credalNet_current_cpt__)[node].cend();
1812  entry != theEnd2;
1813  ++entry) {
1814  auto vertices = entry->size();
1815  auto var_dSize = (*entry)[0].size();
1816 
1817  if (precise && vertices > 1) precise = false;
1818 
1819  if (vacuous && vertices == var_dSize) {
1820  std::vector< bool > elem(var_dSize, false);
1821 
1822  for (auto vertex = entry->cbegin(), vEnd = entry->cend();
1823  vertex != vEnd;
1824  ++vertex) {
1825  for (auto probability = vertex->cbegin(), pEnd = vertex->cend();
1826  probability != pEnd;
1827  ++probability) {
1828  if (*probability == 1) {
1829  elem[probability - vertex->begin()] = true;
1830  break;
1831  }
1832  } // end of : for each modality
1833 
1834  break; // not vacuous
1835  } // end of : for each vertex
1836 
1837  for (auto /*std::vector< bool >::const_iterator*/ probability =
1838  elem.cbegin();
1839  probability != elem.cend();
1840  ++probability)
1841  if (*probability == false) vacuous = false;
1842 
1843  } // end of : if vertices == dSize
1844  else
1845  vacuous = false;
1846 
1847  if (vacuous == false && precise == false) {
1848  current_nodeType__->insert(node, NodeType::Credal);
1849  break;
1850  }
1851 
1852  } // end of : for each parents entry
1853 
1854  if (vacuous)
1855  current_nodeType__->insert(node, NodeType::Vacuous);
1856  else if (precise)
1857  current_nodeType__->insert(node, NodeType::Precise);
1858 
1859  } // end of : for each variable
1860  }
1861 
1862  } // namespace credal
1863 } // namespace gum
void addArc(NodeId tail, NodeId head)
Add an arc in the BN, and update arc.head&#39;s CPT.
Definition: BayesNet_tpl.h:370
void setCPT(const NodeId &id, Size &entry, const std::vector< std::vector< GUM_SCALAR > > &cpt)
Set the vertices of one credal set of a given node ( any instantiation index )
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
void sort_varType__()
Set the NodeType of each node
const bool isSeparatelySpecified() const
void saveBNsMinMax(const std::string &min_path, const std::string &max_path) const
If this CredalNet was built over a perturbed BayesNet, one can save the intervals as two BayesNet...
std::string toString() const
virtual Size domainSize() const final
Returns the product of the variables domain size.
bool empty() const noexcept
Indicates whether the set is the empty set.
Definition: set_tpl.h:707
const DiscreteVariable & variable(NodeId id) const final
Returns a gum::DiscreteVariable given its gum::NodeId in the gum::BayesNet.
Definition: BayesNet_tpl.h:214
unsigned int getNumberOfRunningThreads()
Get the current number of running threads.
class LabelizedVariable
virtual GUM_SCALAR get(const Instantiation &i) const final
Default implementation of MultiDimContainer::get().
Idx nbrDim() const final
Returns the number of variables in the Instantiation.
Size size() const noexcept
Returns the number of elements stored into the hashtable.
unsigned int getThreadNumber()
Get the calling thread id.
std::string getUniqueFileName()
Returns a path to a unique file name.
void fillConstraints(const NodeId &id, const std::vector< GUM_SCALAR > &lower, const std::vector< GUM_SCALAR > &upper)
Set the interval constraints of the credal sets of a given node ( all instantiations ) ...
void write(std::ostream &output, const IBayesNet< GUM_SCALAR > &bn) final
Writes a Bayesian Network in the output stream using the BIF format.
#define GUM_SHOWERROR(e)
Definition: exceptions.h:61
int find_dNode_card__(const std::vector< std::vector< std::vector< GUM_SCALAR > > > &var_cpt) const
NodeId add(const DiscreteVariable &var)
Add a variable to the gum::BayesNet.
Definition: BayesNet_tpl.h:244
unsigned long int2Pow(unsigned long exponent)
Specialized base 2 pow function with integer.
Definition: pow_inl.h:49
virtual Size size() const final
Returns the number of variables in this Directed Graphical Model.
Definition: DAGmodel_inl.h:39
void setCPTs(const NodeId &id, const std::vector< std::vector< std::vector< GUM_SCALAR > > > &cpt)
Set the vertices of the credal sets ( all of the conditionals ) of a given node
Definition: credalNet_tpl.h:66
NodeType currentNodeType(const NodeId &id) const
void fillConstraint(const NodeId &id, const Idx &entry, const std::vector< GUM_SCALAR > &lower, const std::vector< GUM_SCALAR > &upper)
Set the interval constraints of a credal set of a given node ( from an instantiation index ) ...
bool forgetMaster()
Deassociate the master MultiDimAdressable, if any.
bool exists(const Key &key) const
Checks whether there exists an element with a given key in the hashtable.
void reorder(const Sequence< const DiscreteVariable * > &v)
Reorder vars of this instantiation giving the order in v.
Copyright 2005-2020 Pierre-Henri WUILLEMIN() & Christophe GONZALES() info_at_agrum_dot_org.
Definition: agrum.h:25
void computeCPTMinMax()
Used with binary networks to speed-up L2U inference.
const Sequence< const DiscreteVariable *> & variablesSequence() const final
Returns the sequence of DiscreteVariable of this instantiation.
The class for generic Hash Tables.
Definition: hashTable.h:679
const std::vector< std::vector< GUM_SCALAR > > & get_CPT_max() const
Used with binary networks to speed-up L2U inference.
void beginTopologyTransformation()
When inserting/removing arcs, node CPTs change their dimension with a cost in time.
Definition: BayesNet_tpl.h:639
Instantiation instantiation(const NodeId &id)
Get an Instantiation from a node id, usefull to fill the constraints of the network ...
Idx val(Idx i) const
Returns the current value of the variable at position i.
void approximatedBinarization()
Approximate binarization.
Size proceed() final
parse.
void lagrangeNormalization()
Normalize counts of a BayesNet storing counts of each events such that no probability is 0...
virtual Size domainSize() const =0
void fillH(const GUM_SCALAR &min, const GUM_SCALAR &max, const Size &modal)
Creates the H-representation of min <= p(X=modal | .) <= max and add it to the problem input input__...
Class template representing a Credal Network.
Definition: credalNet.h:89
Class template acting as a wrapper for Lexicographic Reverse Search by David Avis.
Definition: LrsWrapper.h:107
void setUpH(const Size &card)
Sets up an H-representation.
NodeId addVariable(const std::string &name, const Size &card)
Adds a discrete node into the network.
Definition: credalNet_tpl.h:42
void intervalToCredal__()
Computes the vertices of each credal set according to their interval definition (does not use lrs)...
Writes a IBayesNet in the BIF format.
Definition: BIFWriter.h:60
const NodeProperty< std::vector< std::vector< std::vector< GUM_SCALAR > > > > & credalNet_srcCpt() const
const GUM_SCALAR & epsilonMean() const
void nextHInput()
Reset the wrapper for next computation for a H-representation with the same variable cardinality and ...
const NodeGraphPart & nodes() const
Returns a constant reference to the dag of this Bayes Net.
Definition: DAGmodel_inl.h:70
static void farey(int64_t &numerator, int64_t &denominator, const GUM_SCALAR &number, const int64_t &den_max=1000000L, const GUM_SCALAR &zero=1e-6)
Find the rational close enough to a given ( decimal ) number in [-1,1] and whose denominator is not h...
Definition: rational_tpl.h:36
virtual const DiscreteVariable & variable(Idx) const final
Returns a const ref to the ith var.
Base class for all aGrUM&#39;s exceptions.
Definition: exceptions.h:106
NodeType
NodeType to speed-up computations in some algorithms.
Definition: credalNet.h:92
const GUM_SCALAR & epsilonMin() const
NodeType nodeType(const NodeId &id) const
const std::vector< std::vector< GUM_SCALAR > > & get_CPT_min() const
Used with binary networks to speed-up L2U inference.
CredalNet()
Constructor used to create a CredalNet step by step, i.e.
Definition: credalNet_tpl.h:31
const Potential< GUM_SCALAR > & cpt(NodeId varId) const final
Returns the CPT of a variable.
Definition: BayesNet_tpl.h:327
void superiorPow(unsigned long card, unsigned long &num_bits, unsigned long &new_card)
Compute the superior and closest power of two of an integer.
Definition: pow_inl.h:55
Definition of templatized reader of BIF files for Bayesian Networks.
Definition: BIFReader.h:126
const BayesNet< GUM_SCALAR > & current_bn() const
Size domainSize(const NodeId &id)
Get the cardinality of a node
Class for assigning/browsing values to tuples of discrete variables.
Definition: instantiation.h:83
virtual Idx pos(const DiscreteVariable &var) const final
Returns the index of a variable.
void intervalToCredal()
Computes the vertices of each credal set according to their interval definition (uses lrs)...
Copyright 2005-2020 Pierre-Henri WUILLEMIN() & Christophe GONZALES() info_at_agrum_dot_org.
void clear()
Removes all the elements in the hash table.
const bool hasComputedCPTMinMax() const
void H2V()
H-representation to V-representation.
void bnToCredal(const GUM_SCALAR beta, const bool oneNet, const bool keepZeroes=false)
Perturbates the BayesNet provided as input for this CredalNet by generating intervals instead of poin...
NodeId nodeId(const DiscreteVariable &var) const final
Returns a variable&#39;s id in the gum::BayesNet.
Definition: BayesNet_tpl.h:239
virtual void set(const Instantiation &i, const GUM_SCALAR &value) const final
Default implementation of MultiDimContainer::set().
void setFirst()
Assign the first values to the tuple of the Instantiation.
void endTopologyTransformation()
terminates a sequence of insertions/deletions of arcs by adjusting all CPTs dimensions.
Definition: BayesNet_tpl.h:646
const matrix & getOutput() const
Get the output matrix solution of the problem.
Size Idx
Type for indexes.
Definition: types.h:53
~CredalNet()
Destructor.
Copyright 2005-2020 Pierre-Henri WUILLEMIN() & Christophe GONZALES() info_at_agrum_dot_org.
const GUM_SCALAR & epsilonMax() const
void erase(const DiscreteVariable &v) final
Removes a variable from the Instantiation.
std::size_t Size
In aGrUM, hashed values are unsigned long int.
Definition: types.h:48
void addArc(const NodeId &tail, const NodeId &head)
Adds an arc between two nodes.
Definition: credalNet_tpl.h:59
virtual const Sequence< const DiscreteVariable *> & variablesSequence() const final
Returns a const ref to the sequence of DiscreteVariable*.
value_type & insert(const Key &key, const Val &val)
Adds a new element (actually a copy of this element) into the hash table.
void H2Vlrs__(const std::vector< std::vector< GUM_SCALAR > > &h_rep, std::vector< std::vector< GUM_SCALAR > > &v_rep) const
const DiscreteVariable & variable(Idx i) const final
Returns the variable at position i in the tuple.
const BayesNet< GUM_SCALAR > & src_bn() const
void initCNNets__(const std::string &src_min_num, const std::string &src_max_den)
Initialize private BayesNet variables after the Constructor has been called.
const NodeProperty< std::vector< std::vector< std::vector< GUM_SCALAR > > > > & credalNet_currentCpt() const
void idmLearning(const Idx s=0, const bool keepZeroes=false)
Learns parameters from a BayesNet storing counts of events.
Size NodeId
Type for node ids.
Definition: graphElements.h:98
void bnCopy__(BayesNet< GUM_SCALAR > &bn_dest)
#define GUM_ERROR(type, msg)
Definition: exceptions.h:55
void initParams__()
Initialize private constant variables after the Constructor has been called.