aGrUM  0.14.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((unsigned long)var_dSize, b, c);
1020  Size nb_bits{Size(b)};
1021 
1022  std::string bit_name;
1023  std::vector< NodeId > bits(nb_bits);
1024 
1025  for (Size bit = 0; bit < nb_bits; bit++) {
1026  bit_name = __current_bn->variable(node).name() + " - bit - ";
1027  std::stringstream ss;
1028  ss << bit;
1029  bit_name += ss.str();
1030 
1031  LabelizedVariable var_bit(bit_name, "node " + bit_name, 2);
1032  NodeId iD = __bin_bn->add(var_bit);
1033 
1034  bits[bit] = iD;
1035  } // end of : for each bit
1036 
1037  __var_bits.insert(node, bits);
1038 
1039  } // end of : if variable is not binary
1040  else {
1041  std::string bit_name = __current_bn->variable(node).name();
1042  LabelizedVariable var_bit(bit_name, "node " + bit_name, 2);
1043  NodeId iD = __bin_bn->add(var_bit);
1044 
1045  __var_bits.insert(node, std::vector< NodeId >(1, iD));
1046  }
1047 
1048  } // end of : for each original variable
1049 
1050  for (auto node : __current_bn->nodes()) {
1051  NodeSet parents = __current_bn->parents(node);
1052 
1053  if (!parents.empty()) {
1054  for (auto par : __current_bn->parents(node)) {
1055  for (Size parent_bit = 0, spbits = Size(__var_bits[par].size());
1056  parent_bit < spbits;
1057  parent_bit++)
1058  for (Size var_bit = 0, mbits = Size(__var_bits[node].size());
1059  var_bit < mbits;
1060  var_bit++)
1061  __bin_bn->addArc(__var_bits[par][parent_bit],
1062  __var_bits[node][var_bit]);
1063  }
1064  }
1065 
1066  // arcs with one's bits
1067  auto bitsize = __var_bits[node].size();
1068 
1069  for (Size bit_c = 1; bit_c < bitsize; bit_c++)
1070  for (Size bit_p = 0; bit_p < bit_c; bit_p++)
1071  __bin_bn->addArc(__var_bits[node][bit_p], __var_bits[node][bit_c]);
1072 
1073  } // end of : for each original variable
1074 
1075  __bin_bn->endTopologyTransformation();
1076 
1077  // binarization of cpts
1078 
1079  auto varsize = __current_bn->size();
1080 
1081  for (Size var = 0; var < varsize; var++) {
1082  auto bitsize = __var_bits[var].size();
1083 
1084  for (Size i = 0; i < bitsize; i++) {
1085  Potential< GUM_SCALAR > const* potential(
1086  &__bin_bn->cpt(__var_bits[var][i]));
1087  Instantiation ins(potential);
1088  ins.setFirst();
1089 
1090  auto entry_size = potential->domainSize() / 2;
1091  std::vector< std::vector< std::vector< GUM_SCALAR > > > var_cpt(
1092  entry_size);
1093 
1094  Size old_conf = 0;
1095 
1096  for (Size conf = 0; conf < entry_size; conf++) {
1097  std::vector< std::vector< GUM_SCALAR > > pvar_cpt;
1098  auto verticessize = (*__credalNet_current_cpt)[var][old_conf].size();
1099 
1100  for (Size old_distri = 0; old_distri < verticessize; old_distri++) {
1101  const std::vector< GUM_SCALAR >& vertex =
1102  (*__credalNet_current_cpt)[var][old_conf][old_distri];
1103  auto vertexsize = vertex.size();
1104 
1105  std::vector< Idx > incc(vertexsize, 0);
1106 
1107  for (Size preced = 0; preced < i; preced++) {
1108  auto bit_pos =
1109  ins.pos(__bin_bn->variable(__var_bits[var][preced]));
1110  auto val = ins.val(bit_pos);
1111 
1112  Size pas = Size(int2Pow((unsigned long)preced));
1113  Size elem;
1114 
1115  if (val == 0)
1116  elem = 0;
1117  else
1118  elem = pas;
1119 
1120  while (elem < vertexsize) {
1121  incc[elem]++;
1122  elem++;
1123 
1124  if (elem % pas == 0) elem += pas;
1125  }
1126  }
1127 
1128  Size pas = Size(int2Pow((unsigned long)i));
1129 
1130  std::vector< GUM_SCALAR > distri(2, 0);
1131  int pos = 1;
1132 
1133  for (Size elem = 0; elem < vertexsize; elem++) {
1134  if (elem % pas == 0) pos = -pos;
1135 
1136  if (incc[elem] == i)
1137  (pos < 0) ? (distri[0] += vertex[elem])
1138  : (distri[1] += vertex[elem]);
1139  }
1140 
1141  if (i > 0) {
1142  GUM_SCALAR den = distri[0] + distri[1];
1143 
1144  if (den == 0) {
1145  distri[0] = 0;
1146  distri[1] = 0;
1147  } else {
1148  distri[0] /= den;
1149  distri[1] /= den;
1150  }
1151  }
1152 
1153  pvar_cpt.push_back(distri);
1154 
1155  } // end of old distris
1156 
1157  // get min/max approx, 2 vertices
1158  std::vector< std::vector< GUM_SCALAR > > vertices(
1159  2, std::vector< GUM_SCALAR >(2, 1));
1160  vertices[1][1] = 0;
1161 
1162  auto new_verticessize = pvar_cpt.size();
1163 
1164  for (Size v = 0; v < new_verticessize; v++) {
1165  if (pvar_cpt[v][1] < vertices[0][1]) vertices[0][1] = pvar_cpt[v][1];
1166 
1167  if (pvar_cpt[v][1] > vertices[1][1]) vertices[1][1] = pvar_cpt[v][1];
1168  }
1169 
1170  vertices[0][0] = 1 - vertices[0][1];
1171  vertices[1][0] = 1 - vertices[1][1];
1172 
1173  pvar_cpt = vertices;
1174 
1175  var_cpt[conf] = pvar_cpt;
1176 
1177  ++ins;
1178  ++ins;
1179 
1180  old_conf++;
1181 
1182  if (old_conf == (*__credalNet_current_cpt)[var].size()) old_conf = 0;
1183 
1184  } // end of new parent conf
1185 
1186  __credalNet_bin_cpt->insert(__var_bits[var][i], var_cpt);
1187 
1188  } // end of bit i
1189 
1190  } // end of old variable
1191 
1192  __bin_bn->beginTopologyTransformation();
1193 
1194  /* indicatrices variables */
1195  auto old_varsize = __var_bits.size();
1196 
1197  for (Size i = 0; i < old_varsize; i++) {
1198  auto bitsize = __var_bits[i].size();
1199 
1200  // binary variable
1201  if (bitsize == 1) continue;
1202 
1203  auto old_card = __src_bn.variable(i).domainSize();
1204 
1205  for (Size mod = 0; mod < old_card; mod++) {
1206  std::string s;
1207  s = "I-";
1208  std::stringstream ss;
1209  ss << __src_bn.variable(i).name();
1210  ss << "-";
1211  ss << mod;
1212  s += ss.str();
1213 
1214  LabelizedVariable var(s, "node " + s, 2);
1215  const NodeId indic = __bin_bn->add(var);
1216 
1217  // arcs from one's bits
1218  for (Size bit = 0; bit < bitsize; bit++)
1219  __bin_bn->addArc(__var_bits[i][bit], indic);
1220 
1221  // cpt
1222  Size num = Size(int2Pow(long(bitsize)));
1223 
1224  std::vector< std::vector< std::vector< GUM_SCALAR > > > icpt(num);
1225 
1226  for (Size entry = 0; entry < num; entry++) {
1227  std::vector< std::vector< GUM_SCALAR > > vertices(
1228  1, std::vector< GUM_SCALAR >(2, 0));
1229 
1230  if (i == entry)
1231  vertices[0][1] = 1;
1232  else
1233  vertices[0][0] = 1;
1234 
1235  icpt[entry] = vertices;
1236  }
1237 
1238  __credalNet_bin_cpt->insert(indic, icpt);
1239 
1240  __bin_nodeType->insert(indic, NodeType::Indic);
1241  } // end of each modality, i.e. as many indicatrice
1242  }
1243 
1244  __bin_bn->endTopologyTransformation();
1245 
1246  if (this->__current_bn != nullptr) delete this->__current_bn;
1247 
1248  this->__current_bn = __bin_bn;
1249 
1250  if (this->__credalNet_current_cpt != nullptr)
1251  delete this->__credalNet_current_cpt;
1252 
1253  this->__credalNet_current_cpt = __credalNet_bin_cpt;
1254 
1255  if (this->__current_nodeType != nullptr) delete this->__current_nodeType;
1256 
1257  this->__current_nodeType = __bin_nodeType;
1258 
1259  __sort_varType(); // will fill __bin_nodeType except for NodeType::Indic
1260  // variables
1261  }
1262 
1263  template < typename GUM_SCALAR >
1266  if (__credalNet_current_cpt != nullptr) return *__credalNet_current_cpt;
1267 
1268  return __credalNet_src_cpt;
1269  }
1270 
1271  template < typename GUM_SCALAR >
1274  return __credalNet_src_cpt;
1275  }
1276 
1277  template < typename GUM_SCALAR >
1280  if (__current_nodeType != nullptr) return (*(__current_nodeType))[id];
1281 
1282  return __original_nodeType[id];
1283  }
1284 
1285  template < typename GUM_SCALAR >
1288  return __original_nodeType[id];
1289  }
1290 
1291  template < typename GUM_SCALAR >
1293  return __separatelySpecified;
1294  }
1295 
1296  template < typename GUM_SCALAR >
1298  return __hasComputedCPTMinMax;
1299  }
1300 
1301  // only if CN is binary !!
1302  template < typename GUM_SCALAR >
1304  __binCptMin.resize(current_bn().size());
1305  __binCptMax.resize(current_bn().size());
1306 
1307  for (auto node : current_bn().nodes()) {
1308  auto pConf = credalNet_currentCpt()[node].size();
1309  std::vector< GUM_SCALAR > min(pConf);
1310  std::vector< GUM_SCALAR > max(pConf);
1311 
1312  for (Size pconf = 0; pconf < pConf; pconf++) {
1313  GUM_SCALAR v1, v2;
1314  v1 = credalNet_currentCpt()[node][pconf][0][1];
1315 
1316  if (credalNet_currentCpt()[node][pconf].size() > 1)
1317  v2 = credalNet_currentCpt()[node][pconf][1][1];
1318  else
1319  v2 = v1;
1320 
1321  GUM_SCALAR delta = v1 - v2;
1322  min[pconf] = (delta >= 0) ? v2 : v1;
1323  max[pconf] = (delta >= 0) ? v1 : v2;
1324  }
1325 
1326  __binCptMin[node] = min;
1327  __binCptMax[node] = max;
1328  }
1329 
1330  __hasComputedCPTMinMax = true;
1331  }
1332 
1333  template < typename GUM_SCALAR >
1334  const std::vector< std::vector< GUM_SCALAR > >&
1336  return __binCptMin;
1337  }
1338 
1339  template < typename GUM_SCALAR >
1340  const std::vector< std::vector< GUM_SCALAR > >&
1342  return __binCptMax;
1343  }
1344 
1345  template < typename GUM_SCALAR >
1346  const GUM_SCALAR& CredalNet< GUM_SCALAR >::epsilonMin() const {
1347  return __epsilonMin;
1348  }
1349 
1350  template < typename GUM_SCALAR >
1351  const GUM_SCALAR& CredalNet< GUM_SCALAR >::epsilonMax() const {
1352  return __epsilonMax;
1353  }
1354 
1355  template < typename GUM_SCALAR >
1356  const GUM_SCALAR& CredalNet< GUM_SCALAR >::epsilonMean() const {
1357  return __epsilonMoy;
1358  }
1359 
1360  template < typename GUM_SCALAR >
1362  std::stringstream output;
1363  const BayesNet< GUM_SCALAR >* __current_bn;
1364  const NodeProperty<
1365  std::vector< std::vector< std::vector< GUM_SCALAR > > > >*
1366  __credalNet_current_cpt;
1367 
1368  if (this->__current_bn == nullptr)
1369  __current_bn = &this->__src_bn;
1370  else
1371  __current_bn = this->__current_bn;
1372 
1373  if (this->__credalNet_current_cpt == nullptr)
1374  __credalNet_current_cpt = &this->__credalNet_src_cpt;
1375  else
1376  __credalNet_current_cpt = this->__credalNet_current_cpt;
1377 
1378  for (auto node : __current_bn->nodes()) {
1379  const Potential< GUM_SCALAR >* potential(&__current_bn->cpt(node));
1380  auto pconfs =
1381  potential->domainSize() / __current_bn->variable(node).domainSize();
1382 
1383  output << "\n" << __current_bn->variable(node) << "\n";
1384 
1385  Instantiation ins(potential);
1386  ins.forgetMaster();
1387  ins.erase(__current_bn->variable(node));
1388  ins.setFirst();
1389 
1390  for (Size pconf = 0; pconf < pconfs; pconf++) {
1391  output << ins << " : ";
1392  output << (*__credalNet_current_cpt)[node][pconf] << "\n";
1393 
1394  if (pconf < pconfs - 1) ++ins;
1395  }
1396  }
1397 
1398  output << "\n";
1399 
1400  return output.str();
1401  }
1402 
1403  template < typename GUM_SCALAR >
1405  if (__current_bn != nullptr) return *__current_bn;
1406 
1407  return __src_bn;
1408  }
1409 
1410  template < typename GUM_SCALAR >
1412  return __src_bn;
1413  }
1414 
1416 
1418 
1419  template < typename GUM_SCALAR >
1421  __epsilonMin = 0;
1422  __epsilonMax = 0;
1423  __epsilonMoy = 0;
1424 
1425  __epsRedund = GUM_SCALAR(1e-6);
1426 
1427  // farey algorithm
1428  __epsF = GUM_SCALAR(1e-6);
1429  __denMax = GUM_SCALAR(1e6); // beware LRSWrapper
1430 
1431  // continued fractions, beware LRSWrapper
1432  // decimal paces (__epsC * __precisionC == 1)
1433  __precisionC = GUM_SCALAR(1e6);
1434  __deltaC = 5;
1435 
1436  // old custom algorithm
1437  __precision = GUM_SCALAR(1e6); // beware LRSWrapper
1438 
1439  __current_bn = nullptr;
1440  __credalNet_current_cpt = nullptr;
1441  __current_nodeType = nullptr;
1442 
1443  __hasComputedCPTMinMax = false;
1444  }
1445 
1446  template < typename GUM_SCALAR >
1447  void CredalNet< GUM_SCALAR >::__initCNNets(const std::string& src_min_num,
1448  const std::string& src_max_den) {
1449  BIFReader< GUM_SCALAR > reader(&__src_bn, src_min_num);
1450  std::string other;
1451 
1452  if (src_max_den.compare("") != 0)
1453  other = src_max_den;
1454  else
1455  other = src_min_num;
1456 
1457  BIFReader< GUM_SCALAR > reader_min(&__src_bn_min, src_min_num);
1458  BIFReader< GUM_SCALAR > reader_max(&__src_bn_max, other);
1459 
1460  try {
1461  reader.proceed();
1462  } catch (Exception& err) {
1463  GUM_SHOWERROR(err);
1464  throw(err);
1465  }
1466 
1467  try {
1468  reader_min.proceed();
1469  } catch (Exception& err) {
1470  GUM_SHOWERROR(err);
1471  throw(err);
1472  }
1473 
1474  try {
1475  reader_max.proceed();
1476  } catch (Exception& err) {
1477  GUM_SHOWERROR(err);
1478  throw(err);
1479  }
1480  }
1481 
1482  template < typename GUM_SCALAR >
1484  const BayesNet< GUM_SCALAR >& src_min_num,
1485  const BayesNet< GUM_SCALAR >& src_max_den) {
1486  __src_bn = src_min_num;
1487  __src_bn_min = src_min_num;
1488 
1489  if (src_max_den.size() > 0)
1490  __src_bn_max = src_max_den;
1491  else
1492  __src_bn_max = src_min_num;
1493  }
1494 
1495  template < typename GUM_SCALAR >
1497  const std::vector< std::vector< std::vector< GUM_SCALAR > > >& var_cpt)
1498  const {
1499  Size vertices_size = 0;
1500 
1501  for (auto entry = var_cpt.cbegin(), theEnd = var_cpt.cend(); entry != theEnd;
1502  ++entry) {
1503  if (entry->size() > vertices_size) vertices_size = Size(entry->size());
1504  }
1505 
1506  return int(vertices_size);
1507  }
1508 
1509  template < typename GUM_SCALAR >
1511  const BayesNet< GUM_SCALAR >* __current_bn;
1512 
1513  if (this->__current_bn == nullptr)
1514  __current_bn = &this->__src_bn;
1515  else
1516  __current_bn = this->__current_bn;
1517 
1518  for (auto node : __current_bn->nodes())
1519  dest.add(__current_bn->variable(node));
1520 
1522 
1523  for (auto node : __current_bn->nodes()) {
1524  for (auto parent_idIt : __current_bn->cpt(node).variablesSequence()) {
1525  if (__current_bn->nodeId(*parent_idIt) != node)
1526  dest.addArc(__current_bn->nodeId(*parent_idIt), node);
1527  } // end of : for each parent in order of appearence
1528  } // end of : for each variable
1529 
1531  }
1532 
1533  /*
1534  // cdd can use real values, not just rationals / integers
1535  template< typename GUM_SCALAR >
1536  void CredalNet< GUM_SCALAR >::__H2Vcdd ( const std::vector< std::vector<
1537  GUM_SCALAR > > & h_rep, std::vector< std::vector< GUM_SCALAR > > & v_rep )
1538  const {
1539  dd_set_global_constants();
1540 
1541  dd_MatrixPtr M, G;
1542  dd_PolyhedraPtr poly;
1543  dd_ErrorType err;
1544 
1545  unsigned int rows = h_rep.size();
1546  unsigned int cols = 0;
1547  if( h_rep.size() > 0 )
1548  cols = h_rep[0].size();
1549 
1550  M = dd_CreateMatrix( rows, cols);
1551 
1552  for ( unsigned int row = 0; row < rows; row++ )
1553  for ( unsigned int col = 0; col < cols; col++ )
1554  dd_set_d( M->matrix[row][col], h_rep[row][col] );
1555 
1556  M->representation = dd_Inequality;
1557 
1558  poly = dd_DDMatrix2Poly(M, &err);
1559  G = dd_CopyGenerators(poly);
1560 
1561  rows = G->rowsize;
1562  cols = G->colsize;
1563 
1564  v_rep.clear();
1565  for ( unsigned int row = 0; row < rows; row++ ) {
1566  std::vector< GUM_SCALAR > aRow(cols - 1);
1567 
1568  if ( *G->matrix[row][0] != 1 )
1569  GUM_ERROR(OperationNotAllowed, "__H2Vcdd : not reading a vertex");
1570 
1571  for ( unsigned int col = 0; col < cols - 1; col++ )
1572  aRow[col] = *G->matrix[row][ col + 1 ];
1573 
1574  v_rep.push_back(aRow);
1575  }
1576 
1577  dd_FreeMatrix(M);
1578  dd_FreeMatrix(G);
1579  dd_FreePolyhedra(poly);
1580 
1581  dd_free_global_constants();
1582  }
1583  */
1584 
1585  template < typename GUM_SCALAR >
1587  const std::vector< std::vector< GUM_SCALAR > >& h_rep,
1588  std::vector< std::vector< GUM_SCALAR > >& v_rep) const {
1589  // write H rep file
1590  int64_t num, den;
1591 
1592  std::string sinefile =
1593  getUniqueFileName(); // generate unique file name, we
1594  // need to add .ine or .ext for lrs
1595  // to know which input it is (Hrep
1596  // to Vrep or Vrep to Hrep)
1597  sinefile += ".ine";
1598 
1599  std::ofstream h_file(sinefile.c_str(), std::ios::out | std::ios::trunc);
1600 
1601  if (!h_file.good())
1603  "__H2Vlrs : could not open lrs input file : " << sinefile);
1604 
1605  h_file << "H - representation\n";
1606  h_file << "begin\n";
1607  h_file << h_rep.size() << ' ' << h_rep[0].size() << " rational\n";
1608 
1609  for (auto it = h_rep.cbegin(), theEnd = h_rep.cend(); it != theEnd; ++it) {
1610  for (auto it2 = it->cbegin(), theEnd2 = it->cend(); it2 != theEnd2;
1611  ++it2) {
1612  // get integer fraction from decimal value
1613  // smallest numerator & denominator is farley, also
1614  // best precision
1616  num, den, ((*it2 > 0) ? *it2 : -*it2), int64_t(__denMax), __epsF);
1617 
1618  h_file << ((*it2 > 0) ? num : -num) << '/' << den << ' ';
1619  }
1620 
1621  h_file << '\n';
1622  }
1623 
1624  h_file << "end\n";
1625  h_file.close();
1626 
1627  // call lrs
1628  // lrs arguments
1629  char* args[3];
1630 
1631  std::string soft_name = "lrs";
1632  std::string extfile(sinefile);
1633  extfile += ".ext";
1634 
1635  args[0] = new char[soft_name.size()];
1636  args[1] = new char[sinefile.size()];
1637  args[2] = new char[extfile.size()];
1638 
1639  strcpy(args[0], soft_name.c_str());
1640  strcpy(args[1], sinefile.c_str());
1641  strcpy(args[2], extfile.c_str());
1642 
1643  // standard cout to null (avoid lrs flooding)
1644  int old_cout, new_cout;
1645  fflush(stdout);
1646  old_cout = dup(1);
1647 
1648  new_cout = open("/dev/null", O_WRONLY);
1649  dup2(new_cout, 1);
1650  close(new_cout);
1651 
1652  lrs_main(3, args);
1653 
1654  // restore standard cout
1655  fflush(stdout);
1656  dup2(old_cout, 1);
1657  close(old_cout);
1658 
1659  delete[] args[2];
1660  delete[] args[1];
1661  delete[] args[0];
1662 
1663  // read V rep file
1664  std::ifstream v_file(extfile.c_str() /*extfilename.c_str()*/, std::ios::in);
1665 
1666  if (!v_file.good())
1667  GUM_ERROR(IOError, "__H2Vlrs : could not open lrs ouput file : ");
1668 
1669  std::string line, tmp;
1670  char * cstr, *p;
1671  GUM_SCALAR probability;
1672 
1673  std::string::size_type pos;
1674  bool keep_going = true;
1675  // int vertices;
1676 
1677  std::vector< GUM_SCALAR > vertex;
1678 
1679  v_file.ignore(256, 'l');
1680 
1681  while (v_file.good() && keep_going) {
1682  getline(v_file, line);
1683 
1684  if (line.size() == 0)
1685  continue;
1686  else if (line.compare("end") == 0) {
1687  keep_going = false;
1688  // this is to get vertices number :
1689  /*getline ( v_file, line );
1690  std::string::size_type pos, end_pos;
1691  pos = line.find ( "vertices = " );
1692  end_pos = line.find ( "rays", pos + 9 );
1693  vertices = atoi ( line.substr ( pos + 9, end_pos - pos - 9 ).c_str()
1694  );*/
1695  break;
1696  } else if (line[1] != '1') {
1698  "__H2Vlrs : reading something other than a vertex from "
1699  "lrs output file : ");
1700  }
1701 
1702  line = line.substr(2);
1703  cstr = new char[line.size() + 1];
1704  strcpy(cstr, line.c_str());
1705 
1706  p = strtok(cstr, " ");
1707 
1708  while (p != nullptr) {
1709  tmp = p;
1710 
1711  if (tmp.compare("1") == 0 || tmp.compare("0") == 0)
1712  probability = GUM_SCALAR(atof(tmp.c_str()));
1713  else {
1714  pos = tmp.find("/");
1715  probability =
1716  GUM_SCALAR(atof(tmp.substr(0, pos).c_str())
1717  / atof(tmp.substr(pos + 1, tmp.size()).c_str()));
1718  }
1719 
1720  vertex.push_back(probability);
1721  p = strtok(nullptr, " ");
1722  } // end of : for all tokens
1723 
1724  delete[] p;
1725  delete[] cstr;
1726 
1727  bool is_redund = false;
1728 
1729 #pragma omp parallel
1730  {
1731  int this_thread = getThreadNumber();
1732  int num_threads = getNumberOfRunningThreads();
1733 
1734  auto begin_pos = (this_thread + 0) * v_rep.size() / num_threads;
1735  auto end_pos = (this_thread + 1) * v_rep.size() / num_threads;
1736 
1737  for (auto p = begin_pos; p < end_pos; p++) {
1738 #pragma omp flush(is_redund)
1739 
1740  if (is_redund) break;
1741 
1742  bool thread_redund = true;
1743 
1744  auto vsize = vertex.size();
1745 
1746  for (Size modality = 0; modality < vsize; modality++) {
1747  if (std::fabs(vertex[modality] - v_rep[p][modality]) > __epsRedund) {
1748  thread_redund = false;
1749  break;
1750  }
1751  }
1752 
1753  if (thread_redund) {
1754  is_redund = true;
1755 #pragma omp flush(is_redund)
1756  }
1757  } // end of : each thread for
1758  } // end of : parallel
1759 
1760  if (!is_redund) v_rep.push_back(vertex);
1761 
1762  vertex.clear();
1763 
1764  } // end of : file
1765 
1766  v_file.close();
1767 
1768  if (std::remove(sinefile.c_str()) != 0)
1769  GUM_ERROR(IOError, "error removing : " + sinefile);
1770 
1771  if (std::remove(extfile.c_str()) != 0)
1772  GUM_ERROR(IOError, "error removing : " + extfile);
1773  }
1774 
1775  template < typename GUM_SCALAR >
1777  NodeProperty< NodeType >* __current_nodeType;
1778  const NodeProperty<
1779  std::vector< std::vector< std::vector< GUM_SCALAR > > > >*
1780  __credalNet_current_cpt;
1781 
1782  const BayesNet< GUM_SCALAR >* __current_bn;
1783 
1784  if (this->__current_bn == nullptr)
1785  __current_bn = &__src_bn;
1786  else
1787  __current_bn = this->__current_bn;
1788 
1789  if (this->__credalNet_current_cpt == nullptr)
1790  __credalNet_current_cpt = &__credalNet_src_cpt;
1791  else
1792  __credalNet_current_cpt = this->__credalNet_current_cpt;
1793 
1794  if (this->__current_nodeType == nullptr)
1795  __current_nodeType = &__original_nodeType;
1796  else
1797  __current_nodeType = this->__current_nodeType;
1798 
1799  /*if ( ! __current_nodeType->empty() )
1800  __current_nodeType->clear();*/
1801 
1802  for (auto node : __current_bn->nodes()) {
1803  // indicatrices are already present
1804  if (__current_nodeType->exists(node)) continue;
1805 
1806  bool precise = true, vacuous = true;
1807 
1808  for (auto entry = (*__credalNet_current_cpt)[node].cbegin(),
1809  theEnd2 = (*__credalNet_current_cpt)[node].cend();
1810  entry != theEnd2;
1811  ++entry) {
1812  auto vertices = entry->size();
1813  auto var_dSize = (*entry)[0].size();
1814 
1815  if (precise && vertices > 1) precise = false;
1816 
1817  if (vacuous && vertices == var_dSize) {
1818  std::vector< bool > elem(var_dSize, false);
1819 
1820  for (auto vertex = entry->cbegin(), vEnd = entry->cend();
1821  vertex != vEnd;
1822  ++vertex) {
1823  for (auto probability = vertex->cbegin(), pEnd = vertex->cend();
1824  probability != pEnd;
1825  ++probability) {
1826  if (*probability == 1) {
1827  elem[probability - vertex->begin()] = true;
1828  break;
1829  }
1830  } // end of : for each modality
1831 
1832  break; // not vacuous
1833  } // end of : for each vertex
1834 
1835  for (auto /*std::vector< bool >::const_iterator*/ probability =
1836  elem.cbegin();
1837  probability != elem.cend();
1838  ++probability)
1839  if (*probability == false) vacuous = false;
1840 
1841  } // end of : if vertices == dSize
1842  else
1843  vacuous = false;
1844 
1845  if (vacuous == false && precise == false) {
1846  __current_nodeType->insert(node, NodeType::Credal);
1847  break;
1848  }
1849 
1850  } // end of : for each parents entry
1851 
1852  if (vacuous)
1853  __current_nodeType->insert(node, NodeType::Vacuous);
1854  else if (precise)
1855  __current_nodeType->insert(node, NodeType::Precise);
1856 
1857  } // end of : for each variable
1858  }
1859 
1860  } // namespace credal
1861 } // 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:345
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
void __bnCopy(BayesNet< GUM_SCALAR > &bn_dest)
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:704
const DiscreteVariable & variable(NodeId id) const final
Returns a gum::DiscreteVariable given its gum::NodeId in the gum::BayesNet.
Definition: BayesNet_tpl.h:199
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:58
NodeId add(const DiscreteVariable &var)
Add a variable to the gum::BayesNet.
Definition: BayesNet_tpl.h:229
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
NodeType currentNodeType(const NodeId &id) 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.
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 __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
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:676
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:591
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
Size size() const
Returns the number of variables in this Directed Graphical Model.
Definition: DAGmodel_inl.h:93
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:87
Class template acting as a wrapper for Lexicographic Reverse Search by David Avis.
Definition: LrsWrapper.h:105
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:40
Writes a IBayesNet in the BIF format.
Definition: BIFWriter.h:57
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:112
int __find_dNode_card(const std::vector< std::vector< std::vector< GUM_SCALAR > > > &var_cpt) 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
void __H2Vlrs(const std::vector< std::vector< GUM_SCALAR > > &h_rep, std::vector< std::vector< GUM_SCALAR > > &v_rep) 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 & 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.
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 Potential< GUM_SCALAR > & cpt(NodeId varId) const final
Returns the CPT of a variable.
Definition: BayesNet_tpl.h:312
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 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: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.
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:224
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:598
const matrix & getOutput() const
Get the output matrix solution of the problem.
Size Idx
Type for indexes.
Definition: types.h:50
~CredalNet()
Destructor.
Utilities for manipulating strings.
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:45
void addArc(const NodeId &tail, const NodeId &head)
Adds an arc between two nodes.
Definition: credalNet_tpl.h:57
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.
const DiscreteVariable & variable(Idx i) const final
Returns the variable at position i in the tuple.
const BayesNet< GUM_SCALAR > & src_bn() const
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:97
#define GUM_ERROR(type, msg)
Definition: exceptions.h:52