aGrUM  0.20.3
a C++ library for (probabilistic) graphical models
credalNet_tpl.h
Go to the documentation of this file.
1 /**
2  *
3  * Copyright (c) 2005-2021 by Pierre-Henri WUILLEMIN(@LIP6) & Christophe GONZALES(@AMU)
4  * info_at_agrum_dot_org
5  *
6  * This library is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this library. If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 
22 #include <agrum/agrum.h>
23 
24 #include <agrum/tools/core/utils_string.h>
25 #include <agrum/CN/credalNet.h>
26 
27 namespace gum {
28  namespace credal {
29 
30  template < typename GUM_SCALAR >
31  CredalNet< GUM_SCALAR >::CredalNet() {
32  _initParams_();
33 
34  _src_bn_ = BayesNet< GUM_SCALAR >();
35  _src_bn_min_ = BayesNet< GUM_SCALAR >();
36  _src_bn_max_ = BayesNet< GUM_SCALAR >();
37 
38  GUM_CONSTRUCTOR(CredalNet);
39  }
40 
41  template < typename GUM_SCALAR >
43  LabelizedVariable var(name, "node " + name, card);
44 
45  NodeId a = _src_bn_.add(var);
48 
49  if (a != b || a != c /*|| b != c*/)
51  "addVariable : not the same id over all networks : " << a << ", " << b << ", "
52  << c);
53 
54  return a;
55  }
56 
57  template < typename GUM_SCALAR >
58  void CredalNet< GUM_SCALAR >::addArc(const NodeId& tail, const NodeId& head) {
62  }
63 
64  template < typename GUM_SCALAR >
66  const NodeId& id,
67  const std::vector< std::vector< std::vector< GUM_SCALAR > > >& cpt) {
68  const Potential< GUM_SCALAR >* const potential(&_src_bn_.cpt(id));
69 
72 
73  if (cpt.size() != entry_size)
75  "setCPTs : entry sizes of cpts does not match for node id : "
76  << id << " : " << cpt.size() << " != " << entry_size);
77 
78  for (const auto& cset: cpt) {
79  if (cset.size() == 0)
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 << " : " << vertex.size()
90  << " != " << 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 
107  }
108 
109  template < typename GUM_SCALAR >
111  Size& entry,
112  const std::vector< std::vector< GUM_SCALAR > >& cpt) {
113  const Potential< GUM_SCALAR >* const potential(&_src_bn_.cpt(id));
114 
117 
118  if (entry >= entry_size)
120  "setCPT : entry is greater or equal than entry size "
121  "(entries start at 0 up to entry_size - 1) : "
122  << entry << " >= " << entry_size);
123 
124  if (cpt.size() == 0) GUM_ERROR(SizeError, "setCPT : empty credal set for entry : " << entry)
125 
126  for (const auto& vertex: cpt) {
127  if (vertex.size() != var_dSize)
129  "setCPT : variable modalities in cpts does not "
130  "match for node id : "
131  << id << " with vertex " << vertex << " at entry " << entry << " : "
132  << vertex.size() << " != " << var_dSize);
133 
134  GUM_SCALAR sum = 0;
135 
136  for (const auto& prob: vertex) {
137  sum += prob;
138  }
139 
140  if (std::fabs(sum - 1) > 1e-6)
142  "setCPT : a vertex coordinates does not sum to one for node id : "
143  << id << " at entry " << entry << " with vertex " << vertex);
144  }
145 
146  // !! auto does NOT use adress (if available) unless explicitly asked !!
148  id,
150 
151  if (node_cpt[entry].size() != 0)
153  "setCPT : vertices of entry id " << entry
154  << " already set to : " << node_cpt[entry]
155  << ", cannot insert : " << cpt);
156 
157  node_cpt[entry] = cpt;
158 
159  /// __credalNet_src_cpt.set ( id, node_cpt );
160  }
161 
162  template < typename GUM_SCALAR >
165  const std::vector< std::vector< GUM_SCALAR > >& cpt) {
166  const Potential< GUM_SCALAR >* const potential(&_src_bn_.cpt(id));
167 
170 
171  // to be sure of entry index reorder ins according to the bayes net
172  // potentials
173  // ( of the credal net )
174  // it WONT throw an error if the sequences are not equal not because of
175  // order
176  // but content, so we double check (before & after order correction)
177  // beware of slaves & master
179  ref.forgetMaster();
180 
181  ins.forgetMaster();
182 
183  const auto& vseq = ref.variablesSequence();
184 
185  if (ins.variablesSequence() != vseq) {
186  ins.reorder(ref);
187 
188  if (ins.variablesSequence() != vseq)
190  "setCPT : instantiation : "
191  << ins << " is not valid for node id " << id
192  << " which accepts instantiations such as (order is not "
193  "important) : "
194  << ref);
195  }
196 
197  Idx entry = 0, jump = 1;
198 
199  for (Idx i = 0, end = ins.nbrDim(); i < end; i++) {
200  if (_src_bn_.nodeId(ins.variable(i)) == id) continue;
201 
202  entry += ins.val(i) * jump;
203 
204  jump *= ins.variable(i).domainSize();
205  }
206 
207  if (entry >= entry_size)
209  "setCPT : entry is greater or equal than entry size "
210  "(entries start at 0 up to entry_size - 1) : "
211  << entry << " >= " << entry_size);
212 
213  if (cpt.size() == 0) GUM_ERROR(SizeError, "setCPT : empty credal set for entry : " << entry)
214 
215  for (const auto& vertex: cpt) {
216  if (vertex.size() != var_dSize)
218  "setCPT : variable modalities in cpts does not "
219  "match for node id : "
220  << id << " with vertex " << vertex << " at entry " << entry << " : "
221  << vertex.size() << " != " << var_dSize);
222 
223  GUM_SCALAR sum = 0;
224 
225  for (const auto& prob: vertex) {
226  sum += prob;
227  }
228 
229  if (std::fabs(sum - 1) > 1e-6)
231  "setCPT : a vertex coordinates does not sum to one for node id : "
232  << id << " at entry " << entry << " with vertex " << vertex);
233  }
234 
236  id,
238 
239  if (node_cpt[entry].size() != 0)
241  "setCPT : vertices of entry : " << ins << " id " << entry
242  << " already set to : " << node_cpt[entry]
243  << ", cannot insert : " << cpt);
244 
245  node_cpt[entry] = cpt;
246 
247  /// __credalNet_src_cpt.set ( id, node_cpt );
248  }
249 
250  template < typename GUM_SCALAR >
252  const std::vector< GUM_SCALAR >& lower,
253  const std::vector< GUM_SCALAR >& upper) {
254  try {
257  } catch (const SizeError&) {
259  "fillConstraints : sizes does not match in fillWith for node id : " << id);
260  }
261  }
262 
263  template < typename GUM_SCALAR >
265  const Idx& entry,
266  const std::vector< GUM_SCALAR >& lower,
267  const std::vector< GUM_SCALAR >& upper) {
269  const_cast< Potential< GUM_SCALAR >* const >(&_src_bn_min_.cpt(id)));
271  const_cast< Potential< GUM_SCALAR >* const >(&_src_bn_max_.cpt(id)));
272 
274 
275  if (lower.size() != var_dSize || upper.size() != var_dSize)
277  "setCPT : variable modalities in cpts does not match for node id : "
278  << id << " with sizes of constraints : ( " << lower.size() << " || "
279  << upper.size() << " ) != " << var_dSize);
280 
282 
283  if (entry >= entry_size)
285  "setCPT : entry is greater or equal than entry size "
286  "(entries start at 0 up to entry_size - 1) : "
287  << entry << " >= " << entry_size);
288 
291  min.setFirst();
292  max.setFirst();
293 
294  Idx pos = 0;
295 
296  while (pos != entry) {
297  ++min;
298  ++max;
299  ++pos;
300  }
301 
302  for (Size i = 0; i < var_dSize; i++) {
305  ++min;
306  ++max;
307  }
308  }
309 
310  template < typename GUM_SCALAR >
313  const std::vector< GUM_SCALAR >& lower,
314  const std::vector< GUM_SCALAR >& upper) {
315  const Potential< GUM_SCALAR >* const potential(&_src_bn_.cpt(id));
316  /*
317  auto var_dSize = _src_bn_.variable ( id ).domainSize();
318  auto entry_size = potential->domainSize() / var_dSize;
319  */
320  // to be sure of entry index reorder ins according to the bayes net
321  // potentials
322  // ( of the credal net )
323  // it WONT throw an error if the sequences are not equal not because of
324  // order
325  // but content, so we double check (before & after order correction)
326  // beware of slaves & master
328  ref.forgetMaster();
329 
330  ins.forgetMaster();
331 
332  const auto& vseq = ref.variablesSequence();
333 
334  if (ins.variablesSequence() != vseq) {
335  ins.reorder(ref);
336 
337  if (ins.variablesSequence() != vseq)
339  "setCPT : instantiation : "
340  << ins << " is not valid for node id " << id
341  << " which accepts instantiations such as (order is not "
342  "important) : "
343  << ref);
344  }
345 
346  Idx entry = 0, jump = 1;
347 
348  for (Idx i = 0, end = ins.nbrDim(); i < end; i++) {
349  if (_src_bn_.nodeId(ins.variable(i)) == id) continue;
350 
351  entry += ins.val(i) * jump;
352 
353  jump *= ins.variable(i).domainSize();
354  }
355 
356  /*
357  if ( entry >= entry_size )
358  GUM_ERROR ( SizeError, "setCPT : entry is greater or equal than entry
359  size
360  (entries start at 0 up to entry_size - 1) : " << entry << " >= " <<
361  entry_size
362  );
363 
364  if ( lower.size() != var_dSize || upper.size() != var_dSize )
365  GUM_ERROR ( SizeError, "setCPT : variable modalities in cpts does not
366  match
367  for node id : " << id << " with sizes of constraints : ( "<< lower.size()
368  << "
369  || " << upper.size() << " ) != " << var_dSize );
370  */
372  }
373 
374  ////////////////////////////////////////////////
375  /// bnet accessors / shortcuts
376 
377  template < typename GUM_SCALAR >
379  return Instantiation(_src_bn_.cpt(id));
380  }
381 
382  template < typename GUM_SCALAR >
384  return _src_bn_.variable(id).domainSize();
385  }
386 
387  ///////////////////////////////////////////////
388 
389  template < typename GUM_SCALAR >
391  const std::string& src_max_den) {
392  _initParams_();
394 
396  }
397 
398  template < typename GUM_SCALAR >
400  const BayesNet< GUM_SCALAR >& src_max_den) {
401  _initParams_();
403 
405  }
406 
407  template < typename GUM_SCALAR >
409  if (_current_bn_ != nullptr) delete _current_bn_;
410 
411  if (_credalNet_current_cpt_ != nullptr) delete _credalNet_current_cpt_;
412 
413  if (_current_nodeType_ != nullptr) delete _current_nodeType_;
414 
416  }
417 
418  // from BNs with numerators & denominators or cpts & denominators to credal
419  template < typename GUM_SCALAR >
421  const bool oneNet,
422  const bool keepZeroes) {
423  GUM_SCALAR epsi_min = 1.;
424  GUM_SCALAR epsi_max = 0.;
425  GUM_SCALAR epsi_moy = 0.;
426  GUM_SCALAR epsi_den = 0.;
427 
428  for (auto node: src_bn().nodes()) {
429  const Potential< GUM_SCALAR >* const potential(&_src_bn_.cpt(node));
430 
432  const_cast< Potential< GUM_SCALAR >* const >(&_src_bn_min_.cpt(node)));
434  const_cast< Potential< GUM_SCALAR >* const >(&_src_bn_max_.cpt(node)));
435 
438 
442 
443  ins.setFirst();
444  ins_min.setFirst();
445  ins_max.setFirst();
446 
448 
449  for (Size entry = 0; entry < entry_size; entry++) {
450  GUM_SCALAR den;
451 
452  if (oneNet)
453  den = 0;
454  else
456 
457  Size nbm = 0;
458 
459  for (Size modality = 0; modality < var_dSize; modality++) {
461 
462  if (oneNet) {
463  den += vertex[modality];
464 
465  if (vertex[modality] < 1 && vertex[modality] > 0)
467  "bnToCredal : the BayesNet contains "
468  "probabilities and not event counts "
469  "although user precised oneNet = "
470  << oneNet);
471  }
472 
473  if (vertex[modality] > 0) nbm++;
474 
475  ++ins;
476  }
477 
478  /// check sum is 1 if not oneNet (we are not using counts)
479  if (!oneNet) {
480  GUM_SCALAR sum = 0;
481 
482  for (auto modality = vertex.cbegin(), theEnd = vertex.cend(); modality != theEnd;
483  ++modality) {
484  sum += *modality;
485  }
486 
487  if (std::fabs(1. - sum) > _epsRedund_) {
489  _src_bn_.variable(node).name() << "(" << _epsRedund_ << ")"
490  << " " << entry << std::endl
491  << vertex << std::endl
492  << ins << std::endl);
493  }
494  }
495 
496  /// end check sum is 1
497 
499 
500  if (beta == 0)
501  epsilon = 0;
502  else if (den == 0 || beta == 1)
503  epsilon = GUM_SCALAR(1.0);
504  else
506 
507  epsi_moy += epsilon;
508  epsi_den += 1;
509 
510  if (epsilon > epsi_max) epsi_max = epsilon;
511 
512  if (epsilon < epsi_min) epsi_min = epsilon;
513 
514  GUM_SCALAR min, max;
515 
516  for (Size modality = 0; modality < var_dSize; modality++) {
517  if ((vertex[modality] > 0 && nbm > 1) || !keepZeroes) {
518  min = GUM_SCALAR((1. - epsilon) * vertex[modality]);
519 
520  if (oneNet) min = GUM_SCALAR(min * 1.0 / den);
521 
522  max = GUM_SCALAR(min + epsilon);
523  } else { // if ( ( vertex[modality] == 0 && keepZeroes ) || (
524  // vertex[modality] > 0 && nbm <= 1 ) || ( vertex[modality] == 0
525  // && nbm <= 1 ) ) {
526  min = vertex[modality];
527 
528  if (oneNet) min = GUM_SCALAR(min * 1.0 / den);
529 
530  max = min;
531  }
532 
535 
536  ++ins_min;
537  ++ins_max;
538  } // end of : for each modality
539 
540  } // end of : for each entry
541 
542  } // end of : for each variable
543 
547 
549  }
550 
551  template < typename GUM_SCALAR >
553  for (auto node: _src_bn_.nodes()) {
554  const Potential< GUM_SCALAR >* const potential(&_src_bn_.cpt(node));
555 
558 
560 
561  ins.setFirst();
562 
564 
565  for (Size entry = 0; entry < entry_size; entry++) {
566  GUM_SCALAR den = 0;
567  bool zeroes = false;
569 
570  for (Size modality = 0; modality < var_dSize; modality++) {
572 
573  if (vertex[modality] < 1 && vertex[modality] > 0)
575  "lagrangeNormalization : the BayesNet "
576  "contains probabilities and not event "
577  "counts.");
578 
579  den += vertex[modality];
580 
581  if (!zeroes && vertex[modality] == 0) { zeroes = true; }
582 
583  ++ins;
584  }
585 
586  if (zeroes) {
587  ins = ins_prev;
588 
589  for (Size modality = 0; modality < var_dSize; modality++) {
590  potential->set(ins, potential->get(ins) + 1);
591  ++ins;
592  }
593  }
594 
595  } // end of : for each entry
596 
597  } // end of : for each variable
598  }
599 
600  template < typename GUM_SCALAR >
601  void CredalNet< GUM_SCALAR >::idmLearning(const Idx s, const bool keepZeroes) {
602  for (auto node: _src_bn_.nodes()) {
603  const Potential< GUM_SCALAR >* const potential(&_src_bn_.cpt(node));
604 
606  const_cast< Potential< GUM_SCALAR >* const >(&_src_bn_min_.cpt(node)));
608  const_cast< Potential< GUM_SCALAR >* const >(&_src_bn_max_.cpt(node)));
609 
612 
616 
617  ins.setFirst();
618  ins_min.setFirst();
619  ins_max.setFirst();
620 
622 
623  for (Size entry = 0; entry < entry_size; entry++) {
624  GUM_SCALAR den = 0;
625  Size nbm = 0;
626 
627  for (Size modality = 0; modality < var_dSize; modality++) {
629 
630  if (vertex[modality] < 1 && vertex[modality] > 0)
632  "idmLearning : the BayesNet contains "
633  "probabilities and not event counts.");
634 
635  den += vertex[modality];
636 
637  if (vertex[modality] > 0) nbm++;
638 
639  ++ins;
640  }
641 
642  if (nbm > 1 || !keepZeroes) den += s;
643 
644  GUM_SCALAR min, max;
645 
646  for (Size modality = 0; modality < var_dSize; modality++) {
647  min = vertex[modality];
648  max = min;
649 
650  if ((vertex[modality] > 0 && nbm > 1) || !keepZeroes) { max += s; }
651 
652  min = GUM_SCALAR(min * 1.0 / den);
653  max = GUM_SCALAR(max * 1.0 / den);
654 
657 
658  ++ins_min;
659  ++ins_max;
660  } // end of : for each modality
661 
662  } // end of : for each entry
663 
664  } // end of : for each variable
665 
670  }
671 
672  /* no need for lrs : (max ... min ... max) vertices from bnToCredal() */
673  template < typename GUM_SCALAR >
676 
678 
679  for (auto node: _src_bn_.nodes()) {
682 
685 
687 
690 
691  ins_min.setFirst();
692  ins_max.setFirst();
693 
696 
697  for (Size entry = 0; entry < entry_size; entry++) {
698  for (Size modality = 0; modality < var_dSize; modality++, ++ins_min, ++ins_max) {
701  }
702 
703  bool all_equals = true;
705 
706  for (Size modality = 0; modality < var_dSize; modality++) {
707  if (std::fabs(upper[modality] - lower[modality]) < 1e-6) continue;
708 
709  all_equals = false;
712 
713  for (Size mod = 0; mod < var_dSize; mod++) {
714  if (modality != mod) vertex[mod] = lower[mod];
715  }
716 
717  GUM_SCALAR total = 0;
718 
719  auto vsize = vertex.size();
720 
721  for (Size i = 0; i < vsize; i++)
722  total += vertex[i];
723 
724  if (std::fabs(total - 1.) > 1e-6)
726  _src_bn_.variable(node).name() << " " << entry << std::endl
727  << vertex << std::endl);
728 
730  }
731 
732  if (all_equals) {
734 
735  for (Size modality = 0; modality < var_dSize; modality++)
737 
738  GUM_SCALAR total = 0.;
739 
740  auto vsize = vertex.size();
741 
742  for (Size i = 0; i < vsize; i++)
743  total += vertex[i];
744 
745  if (std::fabs(total - 1.) > 1e-6)
747  _src_bn_.variable(node).name() << " " << entry << std::endl
748  << vertex << std::endl);
749 
751  }
752 
754  }
755 
757 
758  } // end of : for each variable (node)
759 
760  // get precise/credal/vacuous status of each variable
761  _sort_varType_();
762  _separatelySpecified_ = true;
763  }
764 
765  /* uses lrsWrapper */
766  template < typename GUM_SCALAR >
769 
771 
773 
774  for (auto node: _src_bn_.nodes()) {
777 
780 
782 
785 
786  ins_min.setFirst();
787  ins_max.setFirst();
788 
790 
791  for (Size entry = 0; entry < entry_size; entry++) {
792  for (Size modality = 0; modality < var_dSize; modality++) {
795  "For variable "
796  << _src_bn_.variable(node).name() << " (at " << ins_min
797  << "), the min is greater than the max : " << potential_min->get(ins_min)
798  << ">" << potential_max->get(ins_max) << ".");
799  }
801  ++ins_min;
802  ++ins_max;
803  }
804 
805  lrsWrapper.H2V();
808  }
809 
811 
812  } // end of : for each variable (node)
813 
814  // get precise/credal/vacuous status of each variable
815  _sort_varType_();
816  _separatelySpecified_ = true;
817  }
818 
819  /* call lrs */
820  template < typename GUM_SCALAR >
823 
825 
826  for (auto node: _src_bn_.nodes()) {
829 
832 
834 
837 
838  ins_min.setFirst();
839  ins_max.setFirst();
840 
841  // use iterator
842  for (Size entry = 0; entry < entry_size; entry++) {
844  std::vector< GUM_SCALAR > vertex(var_dSize); // if not interval
845 
847  var_dSize * 2,
848  std::vector< GUM_SCALAR >(var_dSize + 1, 0));
849 
850  std::vector< GUM_SCALAR > sum_ineq1(var_dSize + 1, -1);
852  sum_ineq1[0] = 1;
853  sum_ineq2[0] = -1;
854 
855  bool isInterval = false;
856 
857  for (Size modality = 0; modality < var_dSize; modality++) {
860  inequalities[modality * 2][modality + 1] = 1;
861  inequalities[modality * 2 + 1][modality + 1] = -1;
862 
863  vertex[modality] = inequalities[modality * 2 + 1][0];
864 
865  if (!isInterval
866  && (-inequalities[modality * 2][0] != inequalities[modality * 2 + 1][0]))
867  isInterval = true;
868 
869  ++ins_min;
870  ++ins_max;
871  }
872 
875 
876  if (!isInterval) {
878  } else {
879  try {
881  // __H2Vcdd ( inequalities, vertices );
882  } catch (const std::exception& err) {
883  std::cout << err.what() << std::endl;
884  throw;
885  }
886 
887  } // end of : is interval
888 
889  if (entry == 0 && vertices.size() >= 2) {
890  auto tmp = vertices[0];
891  vertices[0] = vertices[1];
892  vertices[1] = tmp;
893  }
894 
896 
897  } // end of : for each entry
898 
900  // std::cout << _src_bn_.variable(node_idIt).name() << std::endl;
901  // std::cout << var_cpt << std::endl;
902 
903  } // end of : for each variable (node)
904 
905  // get precise/credal/vacuous status of each variable
906  _sort_varType_();
907  _separatelySpecified_ = true;
908  }
909 
910  /**
911  * to call after bnToCredal( GUM_SCALAR beta )
912  * save a BN with lower probabilities and a BN with upper ones
913  */
914  template < typename GUM_SCALAR >
916  const std::string& max_path) const {
918 
919  std::string minfilename = min_path; //"min.bif";
920  std::string maxfilename = max_path; //"max.bif";
923 
924  if (!min_file.good())
925  GUM_ERROR(IOError, "bnToCredal() : could not open stream : min_file : " << minfilename);
926 
927  if (!max_file.good()) {
928  min_file.close();
929  GUM_ERROR(IOError, "bnToCredal() : could not open stream : min_file : " << maxfilename);
930  }
931 
932  try {
935  } catch (Exception& err) {
937  min_file.close();
938  max_file.close();
939  throw(err);
940  }
941 
942  min_file.close();
943  max_file.close();
944  }
945 
946  template < typename GUM_SCALAR >
948  // don't forget to delete the old one ( _current_), if necessary at the end
949  auto bin_bn = new BayesNet< GUM_SCALAR >();
950 
951  // __bnCopy ( * _bin_bn_ );
952  // delete old one too
953  auto credalNet_bin_cpt
954  = new NodeProperty< std::vector< std::vector< std::vector< GUM_SCALAR > > > >();
955 
956  // delete old one too
957  auto bin_nodeType = new NodeProperty< NodeType >();
958 
959  const BayesNet< GUM_SCALAR >* current_bn;
960  // const NodeProperty< nodeType > * _current_nodeType_;
961  const NodeProperty< std::vector< std::vector< std::vector< GUM_SCALAR > > > >*
963 
964  if (this->_current_bn_ == nullptr)
965  current_bn = &this->_src_bn_;
966  else
967  current_bn = this->_current_bn_;
968 
969  if (this->_credalNet_current_cpt_ == nullptr)
971  else
973 
974  /*if ( this-> _current_nodeType_ == nullptr )
975  _current_nodeType_ = & this-> _nodeType_;
976  else
977  _current_nodeType_ = this-> _current_nodeType_;*/
978 
979  if (!_var_bits_.empty()) _var_bits_.clear();
980 
982 
983  for (auto node: current_bn->nodes()) {
985 
986  if (var_dSize != 2) {
987  unsigned long b, c;
988  superiorPow((unsigned long)var_dSize, b, c);
989  Size nb_bits{Size(b)};
990 
993 
994  for (Size bit = 0; bit < nb_bits; bit++) {
995  bit_name = current_bn->variable(node).name() + "-b";
997  ss << bit;
998  bit_name += ss.str();
999 
1000  LabelizedVariable var_bit(bit_name, "node " + bit_name, 2);
1001  NodeId iD = bin_bn->add(var_bit);
1002 
1003  bits[bit] = iD;
1004  } // end of : for each bit
1005 
1007 
1008  } // end of : if variable is not binary
1009  else {
1011  LabelizedVariable var_bit(bit_name, "node " + bit_name, 2);
1012  NodeId iD = bin_bn->add(var_bit);
1013 
1014  _var_bits_.insert(node, std::vector< NodeId >(1, iD));
1015  }
1016 
1017  } // end of : for each original variable
1018 
1019  for (auto node: current_bn->nodes()) {
1021 
1022  if (!parents.empty()) {
1023  for (auto par: current_bn->parents(node)) {
1025  parent_bit++)
1026  for (Size var_bit = 0, mbits = Size(_var_bits_[node].size()); var_bit < mbits;
1027  var_bit++)
1029  }
1030  }
1031 
1032  // arcs with one's bits
1033  auto bitsize = _var_bits_[node].size();
1034 
1035  for (Size bit_c = 1; bit_c < bitsize; bit_c++)
1036  for (Size bit_p = 0; bit_p < bit_c; bit_p++)
1038 
1039  } // end of : for each original variable
1040 
1042 
1043  // binarization of cpts
1044 
1045  auto varsize = current_bn->size();
1046 
1047  for (Size var = 0; var < varsize; var++) {
1048  auto bitsize = _var_bits_[var].size();
1049 
1050  for (Size i = 0; i < bitsize; i++) {
1053  ins.setFirst();
1054 
1055  auto entry_size = potential->domainSize() / 2;
1057 
1058  Size old_conf = 0;
1059 
1060  for (Size conf = 0; conf < entry_size; conf++) {
1063 
1065  const std::vector< GUM_SCALAR >& vertex
1067  auto vertexsize = vertex.size();
1068 
1069  std::vector< Idx > incc(vertexsize, 0);
1070 
1071  for (Size preced = 0; preced < i; preced++) {
1073  auto val = ins.val(bit_pos);
1074 
1075  Size pas = Size(int2Pow((unsigned long)preced));
1076  Size elem;
1077 
1078  if (val == 0)
1079  elem = 0;
1080  else
1081  elem = pas;
1082 
1083  while (elem < vertexsize) {
1084  incc[elem]++;
1085  elem++;
1086 
1087  if (elem % pas == 0) elem += pas;
1088  }
1089  }
1090 
1091  Size pas = Size(int2Pow((unsigned long)i));
1092 
1093  std::vector< GUM_SCALAR > distri(2, 0);
1094  int pos = 1;
1095 
1096  for (Size elem = 0; elem < vertexsize; elem++) {
1097  if (elem % pas == 0) pos = -pos;
1098 
1099  if (incc[elem] == i)
1100  (pos < 0) ? (distri[0] += vertex[elem]) : (distri[1] += vertex[elem]);
1101  }
1102 
1103  if (i > 0) {
1104  GUM_SCALAR den = distri[0] + distri[1];
1105 
1106  if (den == 0) {
1107  distri[0] = 0;
1108  distri[1] = 0;
1109  } else {
1110  distri[0] /= den;
1111  distri[1] /= den;
1112  }
1113  }
1114 
1116 
1117  } // end of old distris
1118 
1119  // get min/max approx, 2 vertices
1120  std::vector< std::vector< GUM_SCALAR > > vertices(2, std::vector< GUM_SCALAR >(2, 1));
1121  vertices[1][1] = 0;
1122 
1123  auto new_verticessize = pvar_cpt.size();
1124 
1125  for (Size v = 0; v < new_verticessize; v++) {
1126  if (pvar_cpt[v][1] < vertices[0][1]) vertices[0][1] = pvar_cpt[v][1];
1127 
1128  if (pvar_cpt[v][1] > vertices[1][1]) vertices[1][1] = pvar_cpt[v][1];
1129  }
1130 
1131  vertices[0][0] = 1 - vertices[0][1];
1132  vertices[1][0] = 1 - vertices[1][1];
1133 
1134  pvar_cpt = vertices;
1135 
1136  var_cpt[conf] = pvar_cpt;
1137 
1138  ++ins;
1139  ++ins;
1140 
1141  old_conf++;
1142 
1143  if (old_conf == (*credalNet_current_cpt)[var].size()) old_conf = 0;
1144 
1145  } // end of new parent conf
1146 
1148 
1149  } // end of bit i
1150 
1151  } // end of old variable
1152 
1154 
1155  /* indicatrices variables */
1156  auto old_varsize = _var_bits_.size();
1157 
1158  for (Size i = 0; i < old_varsize; i++) {
1159  auto bitsize = _var_bits_[i].size();
1160 
1161  // binary variable
1162  if (bitsize == 1) continue;
1163 
1165 
1166  for (Size mod = 0; mod < old_card; mod++) {
1167  std::stringstream ss;
1168  ss << _src_bn_.variable(i).name();
1169  ss << "-v";
1170  ss << mod;
1171 
1172  LabelizedVariable var(ss.str(), "node " + ss.str(), 2);
1173  const NodeId indic = bin_bn->add(var);
1174 
1175  // arcs from one's bits
1176  for (Size bit = 0; bit < bitsize; bit++)
1178 
1179  // cpt
1180  Size num = Size(int2Pow(long(bitsize)));
1181 
1182  std::vector< std::vector< std::vector< GUM_SCALAR > > > icpt(num);
1183 
1184  for (Size entry = 0; entry < num; entry++) {
1185  std::vector< std::vector< GUM_SCALAR > > vertices(1, std::vector< GUM_SCALAR >(2, 0));
1186 
1187  if (mod == entry)
1188  vertices[0][1] = 1;
1189  else
1190  vertices[0][0] = 1;
1191 
1192  icpt[entry] = vertices;
1193  }
1194 
1196 
1198  } // end of each modality, i.e. as many indicatrice
1199  }
1200 
1202 
1203  if (this->_current_bn_ != nullptr) delete this->_current_bn_;
1204 
1205  this->_current_bn_ = bin_bn;
1206 
1207  if (this->_credalNet_current_cpt_ != nullptr) delete this->_credalNet_current_cpt_;
1208 
1210 
1211  if (this->_current_nodeType_ != nullptr) delete this->_current_nodeType_;
1212 
1214 
1215  _sort_varType_(); // will fill _bin_nodeType_ except for NodeType::Indic
1216  // variables
1217 
1219  }
1220 
1221  template < typename GUM_SCALAR >
1222  const NodeProperty< std::vector< std::vector< std::vector< GUM_SCALAR > > > >&
1224  if (_credalNet_current_cpt_ != nullptr) return *_credalNet_current_cpt_;
1225 
1226  return _credalNet_src_cpt_;
1227  }
1228 
1229  template < typename GUM_SCALAR >
1230  const NodeProperty< std::vector< std::vector< std::vector< GUM_SCALAR > > > >&
1232  return _credalNet_src_cpt_;
1233  }
1234 
1235  template < typename GUM_SCALAR >
1236  typename CredalNet< GUM_SCALAR >::NodeType
1238  if (_current_nodeType_ != nullptr) return (*(_current_nodeType_))[id];
1239 
1240  return _original_nodeType_[id];
1241  }
1242 
1243  template < typename GUM_SCALAR >
1244  typename CredalNet< GUM_SCALAR >::NodeType
1245  CredalNet< GUM_SCALAR >::nodeType(const NodeId& id) const {
1246  return _original_nodeType_[id];
1247  }
1248 
1249  template < typename GUM_SCALAR >
1250  const bool CredalNet< GUM_SCALAR >::isSeparatelySpecified() const {
1251  return _separatelySpecified_;
1252  }
1253 
1254  template < typename GUM_SCALAR >
1257  }
1258 
1259  // only if CN is binary !!
1260  template < typename GUM_SCALAR >
1264 
1265  for (auto node: current_bn().nodes()) {
1266  auto pConf = credalNet_currentCpt()[node].size();
1267  std::vector< GUM_SCALAR > min(pConf);
1268  std::vector< GUM_SCALAR > max(pConf);
1269 
1270  for (Size pconf = 0; pconf < pConf; pconf++) {
1271  GUM_SCALAR v1, v2;
1272  v1 = credalNet_currentCpt()[node][pconf][0][1];
1273 
1274  if (credalNet_currentCpt()[node][pconf].size() > 1)
1275  v2 = credalNet_currentCpt()[node][pconf][1][1];
1276  else
1277  v2 = v1;
1278 
1279  GUM_SCALAR delta = v1 - v2;
1280  min[pconf] = (delta >= 0) ? v2 : v1;
1281  max[pconf] = (delta >= 0) ? v1 : v2;
1282  }
1283 
1284  _binCptMin_[node] = min;
1285  _binCptMax_[node] = max;
1286  }
1287 
1289  }
1290 
1291  template < typename GUM_SCALAR >
1292  const std::vector< std::vector< GUM_SCALAR > >&
1294  return _binCptMin_;
1295  }
1296 
1297  template < typename GUM_SCALAR >
1298  const std::vector< std::vector< GUM_SCALAR > >&
1300  return _binCptMax_;
1301  }
1302 
1303  template < typename GUM_SCALAR >
1305  return _epsilonMin_;
1306  }
1307 
1308  template < typename GUM_SCALAR >
1310  return _epsilonMax_;
1311  }
1312 
1313  template < typename GUM_SCALAR >
1315  return _epsilonMoy_;
1316  }
1317 
1318  template < typename GUM_SCALAR >
1321  const BayesNet< GUM_SCALAR >* _current_bn_;
1322  const NodeProperty< std::vector< std::vector< std::vector< GUM_SCALAR > > > >*
1324 
1325  if (this->_current_bn_ == nullptr)
1326  _current_bn_ = &this->_src_bn_;
1327  else
1328  _current_bn_ = this->_current_bn_;
1329 
1330  if (this->_credalNet_current_cpt_ == nullptr)
1332  else
1334 
1335  for (auto node: _current_bn_->nodes()) {
1338 
1339  output << "\n" << _current_bn_->variable(node) << "\n";
1340 
1342  ins.forgetMaster();
1344  ins.setFirst();
1345 
1346  for (Size pconf = 0; pconf < pconfs; pconf++) {
1347  output << ins << " : ";
1348  output << (*_credalNet_current_cpt_)[node][pconf] << "\n";
1349 
1350  if (pconf < pconfs - 1) ++ins;
1351  }
1352  }
1353 
1354  output << "\n";
1355 
1356  return output.str();
1357  }
1358 
1359  template < typename GUM_SCALAR >
1361  if (_current_bn_ != nullptr) return *_current_bn_;
1362 
1363  return _src_bn_;
1364  }
1365 
1366  template < typename GUM_SCALAR >
1368  return _src_bn_;
1369  }
1370 
1371  /////////// protected stuff //////////
1372 
1373  /////////// private stuff ////////////
1374 
1375  template < typename GUM_SCALAR >
1377  _epsilonMin_ = 0;
1378  _epsilonMax_ = 0;
1379  _epsilonMoy_ = 0;
1380 
1381  _epsRedund_ = GUM_SCALAR(1e-6);
1382 
1383  // farey algorithm
1384  _epsF_ = GUM_SCALAR(1e-6);
1385  _denMax_ = GUM_SCALAR(1e6); // beware LRSWrapper
1386 
1387  // continued fractions, beware LRSWrapper
1388  // decimal paces ( _epsC_ * _precisionC_ == 1)
1389  _precisionC_ = GUM_SCALAR(1e6);
1390  _deltaC_ = 5;
1391 
1392  // old custom algorithm
1393  _precision_ = GUM_SCALAR(1e6); // beware LRSWrapper
1394 
1395  _current_bn_ = nullptr;
1396  _credalNet_current_cpt_ = nullptr;
1397  _current_nodeType_ = nullptr;
1398 
1400  }
1401 
1402  template < typename GUM_SCALAR >
1404  const std::string& src_max_den) {
1406  std::string other;
1407 
1408  if (src_max_den.compare("") != 0)
1409  other = src_max_den;
1410  else
1411  other = src_min_num;
1412 
1415 
1416  reader.proceed();
1417  reader_min.proceed();
1418  reader_max.proceed();
1419  }
1420 
1421  template < typename GUM_SCALAR >
1423  const BayesNet< GUM_SCALAR >& src_max_den) {
1426 
1427  if (src_max_den.size() > 0)
1429  else
1431  }
1432 
1433  template < typename GUM_SCALAR >
1435  const std::vector< std::vector< std::vector< GUM_SCALAR > > >& var_cpt) const {
1436  Size vertices_size = 0;
1437 
1438  for (auto entry = var_cpt.cbegin(), theEnd = var_cpt.cend(); entry != theEnd; ++entry) {
1440  }
1441 
1442  return int(vertices_size);
1443  }
1444 
1445  template < typename GUM_SCALAR >
1447  const BayesNet< GUM_SCALAR >* _current_bn_;
1448 
1449  if (this->_current_bn_ == nullptr)
1450  _current_bn_ = &this->_src_bn_;
1451  else
1452  _current_bn_ = this->_current_bn_;
1453 
1454  for (auto node: _current_bn_->nodes())
1456 
1458 
1459  for (auto node: _current_bn_->nodes()) {
1461  if (_current_bn_->nodeId(*parent_idIt) != node)
1463  } // end of : for each parent in order of appearence
1464  } // end of : for each variable
1465 
1467  }
1468 
1469  /*
1470  // cdd can use real values, not just rationals / integers
1471  template< typename GUM_SCALAR >
1472  void CredalNet< GUM_SCALAR >:: _H2Vcdd_ ( const std::vector< std::vector<
1473  GUM_SCALAR > > & h_rep, std::vector< std::vector< GUM_SCALAR > > & v_rep )
1474  const {
1475  dd_set_global_constants();
1476 
1477  dd_MatrixPtr M, G;
1478  dd_PolyhedraPtr poly;
1479  dd_ErrorType err;
1480 
1481  unsigned int rows = h_rep.size();
1482  unsigned int cols = 0;
1483  if( h_rep.size() > 0 )
1484  cols = h_rep[0].size();
1485 
1486  M = dd_CreateMatrix( rows, cols);
1487 
1488  for ( unsigned int row = 0; row < rows; row++ )
1489  for ( unsigned int col = 0; col < cols; col++ )
1490  dd_set_d( M->matrix[row][col], h_rep[row][col] );
1491 
1492  M->representation = dd_Inequality;
1493 
1494  poly = dd_DDMatrix2Poly(M, &err);
1495  G = dd_CopyGenerators(poly);
1496 
1497  rows = G->rowsize;
1498  cols = G->colsize;
1499 
1500  v_rep.clear();
1501  for ( unsigned int row = 0; row < rows; row++ ) {
1502  std::vector< GUM_SCALAR > aRow(cols - 1);
1503 
1504  if ( *G->matrix[row][0] != 1 )
1505  GUM_ERROR(OperationNotAllowed, " __H2Vcdd : not reading a vertex")
1506 
1507  for ( unsigned int col = 0; col < cols - 1; col++ )
1508  aRow[col] = *G->matrix[row][ col + 1 ];
1509 
1510  v_rep.push_back(aRow);
1511  }
1512 
1513  dd_FreeMatrix(M);
1514  dd_FreeMatrix(G);
1515  dd_FreePolyhedra(poly);
1516 
1517  dd_free_global_constants();
1518  }
1519  */
1520 
1521  template < typename GUM_SCALAR >
1523  std::vector< std::vector< GUM_SCALAR > >& v_rep) const {
1524  // write H rep file
1525  int64_t num, den;
1526 
1527  std::string sinefile = getUniqueFileName(); // generate unique file name, we
1528  // need to add .ine or .ext for lrs
1529  // to know which input it is (Hrep
1530  // to Vrep or Vrep to Hrep)
1531  sinefile += ".ine";
1532 
1534 
1535  if (!h_file.good())
1536  GUM_ERROR(IOError, " __H2Vlrs : could not open lrs input file : " << sinefile)
1537 
1538  h_file << "H - representation\n";
1539  h_file << "begin\n";
1540  h_file << h_rep.size() << ' ' << h_rep[0].size() << " rational\n";
1541 
1542  for (auto it = h_rep.cbegin(), theEnd = h_rep.cend(); it != theEnd; ++it) {
1543  for (auto it2 = it->cbegin(), theEnd2 = it->cend(); it2 != theEnd2; ++it2) {
1544  // get integer fraction from decimal value
1545  // smallest numerator & denominator is farley, also
1546  // best precision
1548  den,
1549  ((*it2 > 0) ? *it2 : -*it2),
1550  int64_t(_denMax_),
1551  _epsF_);
1552 
1553  h_file << ((*it2 > 0) ? num : -num) << '/' << den << ' ';
1554  }
1555 
1556  h_file << '\n';
1557  }
1558 
1559  h_file << "end\n";
1560  h_file.close();
1561 
1562  // call lrs
1563  // lrs arguments
1564  char* args[3];
1565 
1566  std::string soft_name = "lrs";
1568  extfile += ".ext";
1569 
1570  args[0] = new char[soft_name.size()];
1571  args[1] = new char[sinefile.size()];
1572  args[2] = new char[extfile.size()];
1573 
1574  strcpy(args[0], soft_name.c_str());
1575  strcpy(args[1], sinefile.c_str());
1576  strcpy(args[2], extfile.c_str());
1577 
1578  // standard cout to null (avoid lrs flooding)
1579  int old_cout, new_cout;
1580  fflush(stdout);
1581  old_cout = dup(1);
1582 
1583  new_cout = open("/dev/null", O_WRONLY);
1584  dup2(new_cout, 1);
1585  close(new_cout);
1586 
1587  lrs_main(3, args);
1588 
1589  // restore standard cout
1590  fflush(stdout);
1591  dup2(old_cout, 1);
1592  close(old_cout);
1593 
1594  delete[] args[2];
1595  delete[] args[1];
1596  delete[] args[0];
1597 
1598  // read V rep file
1599  std::ifstream v_file(extfile.c_str() /*extfilename.c_str()*/, std::ios::in);
1600 
1601  if (!v_file.good()) GUM_ERROR(IOError, " __H2Vlrs : could not open lrs ouput file : ")
1602 
1603  std::string line, tmp;
1604  char * cstr, *p;
1606 
1607  std::string::size_type pos;
1608  bool keep_going = true;
1609  // int vertices;
1610 
1612 
1613  v_file.ignore(256, 'l');
1614 
1615  while (v_file.good() && keep_going) {
1616  getline(v_file, line);
1617 
1618  if (line.size() == 0)
1619  continue;
1620  else if (line.compare("end") == 0) {
1621  keep_going = false;
1622  // this is to get vertices number :
1623  /*getline ( v_file, line );
1624  std::string::size_type pos, end_pos;
1625  pos = line.find ( "vertices = " );
1626  end_pos = line.find ( "rays", pos + 9 );
1627  vertices = atoi ( line.substr ( pos + 9, end_pos - pos - 9 ).c_str()
1628  );*/
1629  break;
1630  } else if (line[1] != '1') {
1632  " __H2Vlrs : reading something other than a vertex from "
1633  "lrs output file : ");
1634  }
1635 
1636  line = line.substr(2);
1637  cstr = new char[line.size() + 1];
1638  strcpy(cstr, line.c_str());
1639 
1640  p = strtok(cstr, " ");
1641 
1642  while (p != nullptr) {
1643  tmp = p;
1644 
1645  if (tmp.compare("1") == 0 || tmp.compare("0") == 0)
1647  else {
1648  pos = tmp.find("/");
1650  / atof(tmp.substr(pos + 1, tmp.size()).c_str()));
1651  }
1652 
1654  p = strtok(nullptr, " ");
1655  } // end of : for all tokens
1656 
1657  delete[] p;
1658  delete[] cstr;
1659 
1660  bool is_redund = false;
1661 
1662 #pragma omp parallel
1663  {
1664  int this_thread = getThreadNumber();
1666 
1667  auto begin_pos = (this_thread + 0) * v_rep.size() / num_threads;
1668  auto end_pos = (this_thread + 1) * v_rep.size() / num_threads;
1669 
1670  for (auto p = begin_pos; p < end_pos; p++) {
1671 #pragma omp flush(is_redund)
1672 
1673  if (is_redund) break;
1674 
1675  bool thread_redund = true;
1676 
1677  auto vsize = vertex.size();
1678 
1679  for (Size modality = 0; modality < vsize; modality++) {
1680  if (std::fabs(vertex[modality] - v_rep[p][modality]) > _epsRedund_) {
1681  thread_redund = false;
1682  break;
1683  }
1684  }
1685 
1686  if (thread_redund) {
1687  is_redund = true;
1688 #pragma omp flush(is_redund)
1689  }
1690  } // end of : each thread for
1691  } // end of : parallel
1692 
1694 
1695  vertex.clear();
1696 
1697  } // end of : file
1698 
1699  v_file.close();
1700 
1701  if (std::remove(sinefile.c_str()) != 0) GUM_ERROR(IOError, "error removing : " + sinefile)
1702 
1703  if (std::remove(extfile.c_str()) != 0) GUM_ERROR(IOError, "error removing : " + extfile)
1704  }
1705 
1706  template < typename GUM_SCALAR >
1709  const NodeProperty< std::vector< std::vector< std::vector< GUM_SCALAR > > > >*
1711 
1712  const BayesNet< GUM_SCALAR >* _current_bn_;
1713 
1714  if (this->_current_bn_ == nullptr)
1716  else
1717  _current_bn_ = this->_current_bn_;
1718 
1719  if (this->_credalNet_current_cpt_ == nullptr)
1721  else
1723 
1724  if (this->_current_nodeType_ == nullptr)
1726  else
1728 
1729  /*if ( ! _current_nodeType_->empty() )
1730  _current_nodeType_->clear();*/
1731 
1732  for (auto node: _current_bn_->nodes()) {
1733  // indicatrices are already present
1734  if (_current_nodeType_->exists(node)) continue;
1735 
1736  bool precise = true, vacuous = true;
1737 
1738  for (auto entry = (*_credalNet_current_cpt_)[node].cbegin(),
1740  entry != theEnd2;
1741  ++entry) {
1742  auto vertices = entry->size();
1743  auto var_dSize = (*entry)[0].size();
1744 
1745  if (precise && vertices > 1) precise = false;
1746 
1747  if (vacuous && vertices == var_dSize) {
1748  std::vector< bool > elem(var_dSize, false);
1749 
1750  for (auto vertex = entry->cbegin(), vEnd = entry->cend(); vertex != vEnd; ++vertex) {
1751  for (auto probability = vertex->cbegin(), pEnd = vertex->cend(); probability != pEnd;
1752  ++probability) {
1753  if (*probability == 1) {
1754  elem[probability - vertex->begin()] = true;
1755  break;
1756  }
1757  } // end of : for each modality
1758 
1759  break; // not vacuous
1760  } // end of : for each vertex
1761 
1762  for (auto /*std::vector< bool >::const_iterator*/ probability = elem.cbegin();
1763  probability != elem.cend();
1764  ++probability)
1765  if (*probability == false) vacuous = false;
1766 
1767  } // end of : if vertices == dSize
1768  else
1769  vacuous = false;
1770 
1771  if (vacuous == false && precise == false) {
1773  break;
1774  }
1775 
1776  } // end of : for each parents entry
1777 
1778  if (vacuous)
1780  else if (precise)
1782 
1783  } // end of : for each variable
1784  }
1785 
1786  } // namespace credal
1787 } // namespace gum
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:643
namespace for all credal networks entities
Definition: LpInterface.cpp:37