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