48 template < GUM_Numeric GUM_SCALAR >
50 const std::string spath(path);
51 std::string path_name = spath.substr(0, spath.size() - 4);
52 path_name = path_name +
".res";
54 std::ofstream res(path_name.c_str(), std::ios::out | std::ios::trunc);
58 "CNLoopyPropagation<GUM_SCALAR>::saveInference(std::"
59 "string & path) : could not open file : "
64 if (std::string ext = spath.substr(spath.size() - 3, spath.size());
65 std::strcmp(ext.c_str(),
"evi") == 0) {
66 std::ifstream evi(spath.c_str(), std::ios::in);
71 "CNLoopyPropagation<GUM_SCALAR>::saveInference(std::"
72 "string & path) : could not open file : "
87 for (
auto node:
_bnet_->nodes()) {
89 GUM_SCALAR msg_p_min = 1.0;
90 GUM_SCALAR msg_p_max = 0.0;
100 msg_p_max = msg_p_min;
123 if (min ==
INF_ && lmin == 0.) {
124 std::cout <<
"proba ERR (negatif) : pi = inf, l = 0" << std::endl;
128 msg_p_min = GUM_SCALAR(1.);
129 }
else if (min == 0. || lmin == 0.) {
130 msg_p_min = GUM_SCALAR(0.);
132 msg_p_min = GUM_SCALAR(1. / (1. + ((1. / min - 1.) * 1. / lmin)));
136 if (max ==
INF_ && lmax == 0.) {
137 std::cout <<
"proba ERR (negatif) : pi = inf, l = 0" << std::endl;
141 msg_p_max = GUM_SCALAR(1.);
142 }
else if (max == 0. || lmax == 0.) {
143 msg_p_max = GUM_SCALAR(0.);
145 msg_p_max = GUM_SCALAR(1. / (1. + ((1. / max - 1.) * 1. / lmax)));
149 if (msg_p_min != msg_p_min && msg_p_max == msg_p_max) { msg_p_min = msg_p_max; }
151 if (msg_p_max != msg_p_max && msg_p_min == msg_p_min) { msg_p_max = msg_p_min; }
153 if (msg_p_max != msg_p_max && msg_p_min != msg_p_min) {
154 std::cout << std::endl;
155 std::cout <<
"pas de proba calculable (verifier observations)" << std::endl;
158 res <<
"P(" <<
_bnet_->variable(node).name() <<
" | e) = ";
161 res <<
"(observe)" << std::endl;
166 res <<
"\t\t" <<
_bnet_->variable(node).label(0) <<
" [ " << (GUM_SCALAR)1. - msg_p_max;
168 if (msg_p_min != msg_p_max) {
169 res <<
", " << (GUM_SCALAR)1. - msg_p_min <<
" ] | ";
174 res <<
_bnet_->variable(node).label(1) <<
" [ " << msg_p_min;
176 if (msg_p_min != msg_p_max) {
177 res <<
", " << msg_p_max <<
" ]" << std::endl;
179 res <<
" ]" << std::endl;
195 template < GUM_Numeric GUM_SCALAR >
197 GUM_SCALAR& msg_l_max,
198 std::vector< GUM_SCALAR >& lx,
202 GUM_SCALAR& den_max) {
203 GUM_SCALAR num_min_tmp = 1.;
204 GUM_SCALAR den_min_tmp = 1.;
205 GUM_SCALAR num_max_tmp = 1.;
206 GUM_SCALAR den_max_tmp = 1.;
208 GUM_SCALAR res_min = 1.0;
209 GUM_SCALAR res_max = 0.0;
211 auto lsize = lx.size();
213 for (
decltype(lsize) i = 0; i < lsize; i++) {
214 bool non_defini_min =
false;
215 bool non_defini_max =
false;
218 num_min_tmp = num_min;
219 den_min_tmp = den_max;
220 num_max_tmp = num_max;
221 den_max_tmp = den_min;
222 }
else if (lx[i] == (GUM_SCALAR)1.) {
223 num_min_tmp = GUM_SCALAR(1.);
224 den_min_tmp = GUM_SCALAR(1.);
225 num_max_tmp = GUM_SCALAR(1.);
226 den_max_tmp = GUM_SCALAR(1.);
227 }
else if (lx[i] > (GUM_SCALAR)1.) {
228 GUM_SCALAR li = GUM_SCALAR(1.) / (lx[i] - GUM_SCALAR(1.));
229 num_min_tmp = num_min + li;
230 den_min_tmp = den_max + li;
231 num_max_tmp = num_max + li;
232 den_max_tmp = den_min + li;
233 }
else if (lx[i] < (GUM_SCALAR)1.) {
234 GUM_SCALAR li = GUM_SCALAR(1.) / (lx[i] - GUM_SCALAR(1.));
235 num_min_tmp = num_max + li;
236 den_min_tmp = den_min + li;
237 num_max_tmp = num_min + li;
238 den_max_tmp = den_max + li;
241 if (den_min_tmp == 0. && num_min_tmp == 0.) {
242 non_defini_min =
true;
243 }
else if (den_min_tmp == 0. && num_min_tmp != 0.) {
245 }
else if (den_min_tmp !=
INF_ || num_min_tmp !=
INF_) {
246 res_min = num_min_tmp / den_min_tmp;
249 if (den_max_tmp == 0. && num_max_tmp == 0.) {
250 non_defini_max =
true;
251 }
else if (den_max_tmp == 0. && num_max_tmp != 0.) {
253 }
else if (den_max_tmp !=
INF_ || num_max_tmp !=
INF_) {
254 res_max = num_max_tmp / den_max_tmp;
257 if (non_defini_max && non_defini_min) {
258 std::cout <<
"undefined msg" << std::endl;
260 }
else if (non_defini_min && !non_defini_max) {
262 }
else if (non_defini_max && !non_defini_min) {
266 if (res_min < 0.) { res_min = 0.; }
268 if (res_max < 0.) { res_max = 0.; }
270 if (msg_l_min == msg_l_max && msg_l_min == -2.) {
275 if (res_max > msg_l_max) { msg_l_max = res_max; }
277 if (res_min < msg_l_min) { msg_l_min = res_min; }
285 template < GUM_Numeric GUM_SCALAR >
287 std::vector< std::vector< GUM_SCALAR > >& combi_msg_p,
289 GUM_SCALAR& msg_l_min,
290 GUM_SCALAR& msg_l_max,
291 std::vector< GUM_SCALAR >& lx,
293 GUM_SCALAR num_min = 0.;
294 GUM_SCALAR num_max = 0.;
295 GUM_SCALAR den_min = 0.;
296 GUM_SCALAR den_max = 0.;
298 auto taille = combi_msg_p.size();
300 std::vector< typename std::vector< GUM_SCALAR >::iterator > it(taille);
302 for (
decltype(taille) i = 0; i < taille; i++) {
303 it[i] = combi_msg_p[i].begin();
312 while (it[taille - 1] != combi_msg_p[taille - 1].end()) {
313 GUM_SCALAR prod = 1.;
315 for (
decltype(taille) k = 0; k < taille; k++) {
319 den_min += (
_cn_->get_binaryCPT_min()[
id][combi_den] * prod);
320 den_max += (
_cn_->get_binaryCPT_max()[
id][combi_den] * prod);
322 num_min += (
_cn_->get_binaryCPT_min()[
id][combi_num] * prod);
323 num_max += (
_cn_->get_binaryCPT_max()[
id][combi_num] * prod);
329 if (combi_den % pp == 0) {
338 for (
decltype(taille) i = 0; (i < taille - 1) && (it[i] == combi_msg_p[i].end()); ++i) {
339 it[i] = combi_msg_p[i].begin();
344 compute_ext_(msg_l_min, msg_l_max, lx, num_min, num_max, den_min, den_max);
351 template < GUM_Numeric GUM_SCALAR >
353 std::vector< std::vector< GUM_SCALAR > >& combi_msg_p,
355 GUM_SCALAR& msg_p_min,
356 GUM_SCALAR& msg_p_max) {
360 auto taille = combi_msg_p.size();
362 std::vector< typename std::vector< GUM_SCALAR >::iterator > it(taille);
364 for (
decltype(taille) i = 0; i < taille; i++) {
365 it[i] = combi_msg_p[i].begin();
369 auto theEnd = combi_msg_p[taille - 1].end();
371 while (it[taille - 1] != theEnd) {
372 GUM_SCALAR prod = 1.;
374 for (
decltype(taille) k = 0; k < taille; k++) {
378 min += (
_cn_->get_binaryCPT_min()[
id][combi] * prod);
379 max += (
_cn_->get_binaryCPT_max()[
id][combi] * prod);
386 for (
decltype(taille) i = 0; (i < taille - 1) && (it[i] == combi_msg_p[i].end()); ++i) {
387 it[i] = combi_msg_p[i].begin();
392 if (min < msg_p_min) { msg_p_min = min; }
394 if (max > msg_p_max) { msg_p_max = max; }
400 template < GUM_Numeric GUM_SCALAR >
402 std::vector< std::vector< std::vector< GUM_SCALAR > > >& msgs_p,
404 GUM_SCALAR& msg_p_min,
405 GUM_SCALAR& msg_p_max) {
406 auto taille = msgs_p.size();
410 msg_p_min =
_cn_->get_binaryCPT_min()[id][0];
411 msg_p_max =
_cn_->get_binaryCPT_max()[id][0];
416 for (
Size i = 0; i < taille; i++) {
417 msgPerm *= msgs_p[i].size();
426 if (nb_threads < 1) nb_threads = 1;
429 const auto real_nb_threads = ranges.size();
430 std::vector< GUM_SCALAR > msg_pmin(real_nb_threads, msg_p_min);
431 std::vector< GUM_SCALAR > msg_pmax(real_nb_threads, msg_p_max);
435 = [
this, &msg_pmin, &msg_pmax, msgs_p, taille, ranges, id](
const std::size_t this_thread,
436 const std::size_t nb_threads) {
437 std::vector< std::vector< GUM_SCALAR > > combi_msg_p(taille);
439 const auto& [first, second] = ranges[this_thread];
440 for (
Idx j = first; j < second; ++j) {
444 for (
Idx i = 0; i < taille; i++) {
445 if (msgs_p[i].size() == 2) {
446 combi_msg_p[i] = (jvalue & 1) ? msgs_p[i][1] : msgs_p[i][0];
449 combi_msg_p[i] = msgs_p[i][0];
453 compute_ext_(combi_msg_p,
id, msg_pmin[this_thread], msg_pmax[this_thread]);
460 for (
Idx j = 0; j < real_nb_threads; ++j) {
461 if (msg_p_min > msg_pmin[j]) { msg_p_min = msg_pmin[j]; }
462 if (msg_p_max < msg_pmax[j]) { msg_p_max = msg_pmax[j]; }
470 template < GUM_Numeric GUM_SCALAR >
472 std::vector< std::vector< std::vector< GUM_SCALAR > > >& msgs_p,
474 GUM_SCALAR& real_msg_l_min,
475 GUM_SCALAR& real_msg_l_max,
476 std::vector< GUM_SCALAR >& lx,
478 GUM_SCALAR msg_l_min = real_msg_l_min;
479 GUM_SCALAR msg_l_max = real_msg_l_max;
481 auto taille = msgs_p.size();
485 GUM_SCALAR num_min =
_cn_->get_binaryCPT_min()[id][1];
486 GUM_SCALAR num_max =
_cn_->get_binaryCPT_max()[id][1];
487 GUM_SCALAR den_min =
_cn_->get_binaryCPT_min()[id][0];
488 GUM_SCALAR den_max =
_cn_->get_binaryCPT_max()[id][0];
490 compute_ext_(msg_l_min, msg_l_max, lx, num_min, num_max, den_min, den_max);
492 real_msg_l_min = msg_l_min;
493 real_msg_l_max = msg_l_max;
498 for (
Size i = 0; i < taille; i++) {
499 msgPerm *= msgs_p[i].size();
508 if (nb_threads < 1) nb_threads = 1;
511 const auto real_nb_threads = ranges.size();
512 std::vector< GUM_SCALAR > msg_lmin(real_nb_threads, msg_l_min);
513 std::vector< GUM_SCALAR > msg_lmax(real_nb_threads, msg_l_max);
516 auto threadedExec = [
this, &msg_lmin, &msg_lmax, msgs_p, taille, ranges, id, &lx, pos](
517 const std::size_t this_thread,
518 const std::size_t nb_threads) {
519 std::vector< std::vector< GUM_SCALAR > > combi_msg_p(taille);
521 const auto& [first, second] = ranges[this_thread];
522 for (
Idx j = first; j < second; ++j) {
526 for (
Idx i = 0; i < taille; i++) {
527 if (msgs_p[i].size() == 2) {
528 combi_msg_p[i] = (jvalue & 1) ? msgs_p[i][1] : msgs_p[i][0];
531 combi_msg_p[i] = msgs_p[i][0];
534 compute_ext_(combi_msg_p,
id, msg_lmin[this_thread], msg_lmax[this_thread], lx, pos);
541 for (
Idx j = 0; j < real_nb_threads; ++j) {
542 if ((msg_l_min > msg_lmin[j] || msg_l_min == -2) && msg_lmin[j] > 0) {
543 msg_l_min = msg_lmin[j];
545 if ((msg_l_max < msg_lmax[j] || msg_l_max == -2) && msg_lmax[j] > 0) {
546 msg_l_max = msg_lmax[j];
550 real_msg_l_min = msg_l_min;
551 real_msg_l_max = msg_l_max;
554 template < GUM_Numeric GUM_SCALAR >
578 template < GUM_Numeric GUM_SCALAR >
594 for (
auto node:
_bnet_->nodes()) {
607 template < GUM_Numeric GUM_SCALAR >
612 for (
auto node:
_bnet_->topologicalOrder()) {
636 std::vector< GUM_SCALAR > marg(2);
638 marg[0] = 1 - marg[1];
665 const auto parents = &
_bnet_->cpt(node).variablesSequence();
667 std::vector< std::vector< std::vector< GUM_SCALAR > > > msgs_p;
668 std::vector< std::vector< GUM_SCALAR > > msg_p;
669 std::vector< GUM_SCALAR > distri(2);
673 for (
auto jt = ++parents->begin(), theEnd = parents->end(); jt != theEnd; ++jt) {
678 distri[0] = (GUM_SCALAR)1. - distri[1];
679 msg_p.push_back(distri);
683 distri[0] = (GUM_SCALAR)1. - distri[1];
684 msg_p.push_back(distri);
687 msgs_p.push_back(msg_p);
691 GUM_SCALAR msg_p_min = 1.;
692 GUM_SCALAR msg_p_max = 0.;
698 if (msg_p_min <= (GUM_SCALAR)0.) { msg_p_min = (GUM_SCALAR)0.; }
700 if (msg_p_max <= (GUM_SCALAR)0.) { msg_p_max = (GUM_SCALAR)0.; }
703 std::vector< GUM_SCALAR > marg(2);
705 marg[0] = 1 - msg_p_min;
709 if (msg_p_min != msg_p_max) {
711 marg[0] = 1 - msg_p_max;
720 for (
auto arc:
_bnet_->arcs()) {
729 template < GUM_Numeric GUM_SCALAR >
739 for (
auto chil: graphe.
children(node)) {
745 for (
auto par: graphe.
parents(node)) {
767 template < GUM_Numeric GUM_SCALAR >
771 std::vector< cArcP > seq;
772 seq.reserve(nbrArcs);
774 for (
const auto& arc:
_bnet_->arcs()) {
783 for (
Size j = 0, theEnd = nbrArcs / 2; j < theEnd; j++) {
787 if (w1 == w2) {
continue; }
789 std::swap(seq[w1], seq[w2]);
792 for (
const auto it: seq) {
798 msgP_(it->tail(), it->head());
799 msgL_(it->head(), it->tail());
812 template < GUM_Numeric GUM_SCALAR >
816 std::vector< cArcP > seq;
817 seq.reserve(nbrArcs);
819 for (
const auto& arc:
_bnet_->arcs()) {
828 for (
const auto it: seq) {
834 msgP_(it->tail(), it->head());
835 msgL_(it->head(), it->tail());
845 template < GUM_Numeric GUM_SCALAR >
850 const auto parents = &
_bnet_->cpt(Y).variablesSequence();
859 if (!update_p && !update_l) {
return; }
872 GUM_SCALAR lmin = 1.;
873 GUM_SCALAR lmax = 1.;
875 for (
const NodeId chil: children) {
876 const Arc arc_YC{Y, chil};
888 if (lmax != lmax && lmin == lmin) { lmax = lmin; }
890 if (lmax != lmax && lmin != lmin) {
891 std::cout <<
"no likelihood defined [lmin, lmax] (incompatibles "
896 if (lmin < 0.) { lmin = 0.; }
898 if (lmax < 0.) { lmax = 0.; }
927 const Arc arc_XY{X, Y};
928 if (lmin == lmax && lmin == 1.) {
940 if (update_p || update_l) {
941 std::vector< std::vector< std::vector< GUM_SCALAR > > > msgs_p;
942 std::vector< std::vector< GUM_SCALAR > > msg_p;
943 std::vector< GUM_SCALAR > distri(2);
949 for (
auto jt = ++parents->begin(), theEnd = parents->end(); jt != theEnd; ++jt) {
950 if (
_bnet_->nodeId(**jt) == X) {
952 pos = parents->pos(*jt) - 1;
958 const Arc arc_PY{
_bnet_->nodeId(**jt), Y};
960 distri[0] = GUM_SCALAR(1.) - distri[1];
961 msg_p.push_back(distri);
965 distri[0] = GUM_SCALAR(1.) - distri[1];
966 msg_p.push_back(distri);
969 msgs_p.push_back(msg_p);
973 GUM_SCALAR min = -2.;
974 GUM_SCALAR max = -2.;
976 std::vector< GUM_SCALAR > lx;
979 if (lmin != lmax) { lx.push_back(lmax); }
983 if (min == -2. || max == -2.) {
986 }
else if (max != -2.) {
989 std::cout << std::endl;
990 std::cout <<
"!!!! pas de message L calculable !!!!" << std::endl;
995 if (min < 0.) { min = 0.; }
997 if (max < 0.) { max = 0.; }
1031 template < GUM_Numeric GUM_SCALAR >
1035 const auto parents = &
_bnet_->cpt(X).variablesSequence();
1044 const Arc arc_XDC{X, demanding_child};
1056 if (!update_p && !update_l) {
return; }
1058 GUM_SCALAR lmin = 1.;
1059 GUM_SCALAR lmax = 1.;
1062 for (
auto chil: children) {
1063 if (chil == demanding_child) {
continue; }
1065 const Arc arc_XC{X, chil};
1075 if (lmin != lmin && lmax == lmax) { lmin = lmax; }
1077 if (lmax != lmax && lmin == lmin) { lmax = lmin; }
1079 if (lmax != lmax && lmin != lmin) {
1080 std::cout <<
"pas de vraisemblance definie [lmin, lmax] (observations "
1086 if (lmin < 0.) { lmin = 0.; }
1088 if (lmax < 0.) { lmax = 0.; }
1091 GUM_SCALAR min =
INF_;
1092 GUM_SCALAR max = 0.;
1095 std::vector< std::vector< std::vector< GUM_SCALAR > > > msgs_p;
1096 std::vector< std::vector< GUM_SCALAR > > msg_p;
1097 std::vector< GUM_SCALAR > distri(2);
1101 for (
auto jt = ++parents->begin(), theEnd = parents->end(); jt != theEnd; ++jt) {
1104 const Arc arc_PX{
_bnet_->nodeId(**jt), X};
1106 distri[0] = GUM_SCALAR(1.) - distri[1];
1107 msg_p.push_back(distri);
1111 distri[0] = GUM_SCALAR(1.) - distri[1];
1112 msg_p.push_back(distri);
1115 msgs_p.push_back(msg_p);
1121 if (min < 0.) { min = 0.; }
1123 if (max < 0.) { max = 0.; }
1126 std::cout <<
" ERREUR msg P min = max = INF " << std::endl;
1152 if (update_p || update_l) {
1153 GUM_SCALAR msg_p_min;
1154 GUM_SCALAR msg_p_max;
1157 if (min ==
INF_ && lmin == 0.) {
1158 std::cout <<
"MESSAGE P ERR (negatif) : pi = inf, l = 0" << std::endl;
1162 msg_p_min = GUM_SCALAR(1.);
1163 }
else if (min == 0. || lmin == 0.) {
1166 msg_p_min = GUM_SCALAR(1. / (1. + ((1. / min - 1.) * 1. / lmin)));
1170 if (max ==
INF_ && lmax == 0.) {
1171 std::cout <<
"MESSAGE P ERR (negatif) : pi = inf, l = 0" << std::endl;
1175 msg_p_max = GUM_SCALAR(1.);
1176 }
else if (max == 0. || lmax == 0.) {
1179 msg_p_max = GUM_SCALAR(1. / (1. + ((1. / max - 1.) * 1. / lmax)));
1182 if (msg_p_min != msg_p_min && msg_p_max == msg_p_max) {
1183 msg_p_min = msg_p_max;
1184 std::cout << std::endl;
1185 std::cout <<
"msg_p_min is NaN" << std::endl;
1188 if (msg_p_max != msg_p_max && msg_p_min == msg_p_min) {
1189 msg_p_max = msg_p_min;
1190 std::cout << std::endl;
1191 std::cout <<
"msg_p_max is NaN" << std::endl;
1194 if (msg_p_max != msg_p_max && msg_p_min != msg_p_min) {
1195 std::cout << std::endl;
1196 std::cout <<
"pas de message P calculable (verifier observations)" << std::endl;
1200 if (msg_p_min < 0.) { msg_p_min = 0.; }
1202 if (msg_p_max < 0.) { msg_p_max = 0.; }
1204 bool update =
false;
1213 if (msg_p_max != msg_p_min) {
1222 if (msg_p_max != msg_p_min) {
1236 template < GUM_Numeric GUM_SCALAR >
1238 for (
auto node:
_bnet_->nodes()) {
1246 auto parents = &
_bnet_->cpt(node).variablesSequence();
1249 GUM_SCALAR lmin = 1.;
1250 GUM_SCALAR lmax = 1.;
1253 for (
auto chil: children) {
1254 const Arc arc_NC{node, chil};
1264 if (lmin != lmin && lmax == lmax) { lmin = lmax; }
1268 if (lmax != lmax && lmin != lmin) {
1269 std::cout <<
"pas de vraisemblance definie [lmin, lmax] (observations "
1275 if (lmin < 0.) { lmin = 0.; }
1277 if (lmax < 0.) { lmax = 0.; }
1292 std::vector< std::vector< std::vector< GUM_SCALAR > > > msgs_p;
1293 std::vector< std::vector< GUM_SCALAR > > msg_p;
1294 std::vector< GUM_SCALAR > distri(2);
1298 for (
auto jt = ++parents->begin(), theEnd = parents->end(); jt != theEnd; ++jt) {
1301 const Arc arc_PN{
_bnet_->nodeId(**jt), node};
1303 distri[0] = GUM_SCALAR(1.) - distri[1];
1304 msg_p.push_back(distri);
1308 distri[0] = GUM_SCALAR(1.) - distri[1];
1309 msg_p.push_back(distri);
1312 msgs_p.push_back(msg_p);
1316 GUM_SCALAR min =
INF_;
1317 GUM_SCALAR max = 0.;
1321 if (min < 0.) { min = 0.; }
1323 if (max < 0.) { max = 0.; }
1340 template < GUM_Numeric GUM_SCALAR >
1342 for (
auto node:
_bnet_->nodes()) {
1343 GUM_SCALAR msg_p_min = 1.;
1344 GUM_SCALAR msg_p_max = 0.;
1348 msg_p_min = (GUM_SCALAR)0.;
1353 msg_p_max = msg_p_min;
1373 std::cout <<
" min ou max === INF_ !!!!!!!!!!!!!!!!!!!!!!!!!! " << std::endl;
1377 if (min ==
INF_ && lmin == 0.) {
1378 std::cout <<
"proba ERR (negatif) : pi = inf, l = 0" << std::endl;
1383 msg_p_min = GUM_SCALAR(1.);
1384 }
else if (min == 0. || lmin == 0.) {
1385 msg_p_min = GUM_SCALAR(0.);
1387 msg_p_min = GUM_SCALAR(1. / (1. + ((1. / min - 1.) * 1. / lmin)));
1390 if (max ==
INF_ && lmax == 0.) {
1391 std::cout <<
"proba ERR (negatif) : pi = inf, l = 0" << std::endl;
1396 msg_p_max = GUM_SCALAR(1.);
1397 }
else if (max == 0. || lmax == 0.) {
1398 msg_p_max = GUM_SCALAR(0.);
1400 msg_p_max = GUM_SCALAR(1. / (1. + ((1. / max - 1.) * 1. / lmax)));
1404 if (msg_p_min != msg_p_min && msg_p_max == msg_p_max) {
1405 msg_p_min = msg_p_max;
1406 std::cout << std::endl;
1407 std::cout <<
"msg_p_min is NaN" << std::endl;
1410 if (msg_p_max != msg_p_max && msg_p_min == msg_p_min) {
1411 msg_p_max = msg_p_min;
1412 std::cout << std::endl;
1413 std::cout <<
"msg_p_max is NaN" << std::endl;
1416 if (msg_p_max != msg_p_max && msg_p_min != msg_p_min) {
1417 std::cout << std::endl;
1418 std::cout <<
"Please check the observations (no proba can be computed)" << std::endl;
1422 if (msg_p_min < 0.) { msg_p_min = 0.; }
1424 if (msg_p_max < 0.) { msg_p_max = 0.; }
1433 template < GUM_Numeric GUM_SCALAR >
1441 template < GUM_Numeric GUM_SCALAR >
1443 for (
auto node:
_bnet_->nodes()) {
1446 for (
auto pare:
_bnet_->parents(node)) {
1455 template < GUM_Numeric GUM_SCALAR >
1459 std::vector< std::vector< GUM_SCALAR > >
vertices(2, std::vector< GUM_SCALAR >(2));
1461 for (
auto node:
_bnet_->nodes()) {
1468 for (
auto vertex = 0, vend = 2; vertex != vend; vertex++) {
1479 template < GUM_Numeric GUM_SCALAR >
1482 if (!
credalNet.isSeparatelySpecified()) {
1483 GUM_ERROR(OperationNotAllowed,
1484 "CNLoopyPropagation is only available "
1485 "with separately specified nets");
1489 for (
auto node:
credalNet.current_bn().nodes())
1490 if (
credalNet.current_bn().variable(node).domainSize() != 2) {
1491 GUM_ERROR(OperationNotAllowed,
1492 "CNLoopyPropagation is only available "
1493 "with binary credal networks")
1497 if (!
credalNet.hasComputedBinaryCPTMinMax()) {
1498 GUM_ERROR(OperationNotAllowed,
1499 "CNLoopyPropagation only works when "
1500 "\"computeBinaryCPTMinMax()\" has been called for "
1513 template < GUM_Numeric GUM_SCALAR >
1524 template < GUM_Numeric GUM_SCALAR >
1529 template < GUM_Numeric GUM_SCALAR >
1535 template < GUM_Numeric GUM_SCALAR >
Class implementing loopy-propagation with binary networks - L2U algorithm.
void updateApproximationScheme(unsigned int incr=1)
Update the scheme w.r.t the new error and increment steps.
bool continueApproximationScheme(double error)
Update the scheme w.r.t the new error.
void initApproximationScheme()
Initialise the scheme.
void stopApproximationScheme()
Stop the approximation scheme.
const NodeSet & parents(NodeId id) const
returns the set of nodes with arc ingoing to a given node
NodeSet children(const NodeSet &ids) const
returns the set of nodes which consists in the node and its parents returns the set of children of a ...
The base class for all directed edges.
Exception : the element we looked for cannot be found.
Exception : operation not allowed.
bool empty() const noexcept
Indicates whether the set is the empty set.
Size size() const noexcept
Returns the number of elements in the set.
void insertEvidenceFile(std::string_view path) override
Starts the inference.
void makeInference() override
Starts the inference.
NodeProperty< GUM_SCALAR > NodesL_min_
"Lower" node information obtained by combinaison of children messages.
void eraseAllEvidence() override
Erase all inference related data to perform another one.
NodeProperty< GUM_SCALAR > NodesP_min_
"Lower" node information obtained by combinaison of parent's messages.
NodeProperty< GUM_SCALAR > NodesL_max_
"Upper" node information obtained by combinaison of children messages.
void msgL_(const NodeId X, const NodeId demanding_parent)
Sends a message to one's parent, i.e.
NodeProperty< NodeSet * > msg_l_sent_
Used to keep track of one's messages sent to it's parents.
InferenceType _inferenceType_
The chosen inference type.
void compute_ext_(GUM_SCALAR &msg_l_min, GUM_SCALAR &msg_l_max, std::vector< GUM_SCALAR > &lx, GUM_SCALAR &num_min, GUM_SCALAR &num_max, GUM_SCALAR &den_min, GUM_SCALAR &den_max)
Used by msgL_.
NodeProperty< bool > update_p_
Used to keep track of which node needs to update it's information coming from it's parents.
void refreshLMsPIs_(bool refreshIndic=false)
Get the last messages from one's parents and children.
NodeProperty< bool > update_l_
Used to keep track of which node needs to update it's information coming from it's children.
void makeInferenceNodeToNeighbours_()
Starts the inference with this inference type.
void initialize_()
Topological forward propagation to initialize old marginals & messages.
~CNLoopyPropagation() override
Destructor.
GUM_SCALAR calculateEpsilon_()
Compute epsilon.
void saveInference(std::string_view path)
void makeInferenceByRandomOrder_()
Starts the inference with this inference type.
const IBayesNet< GUM_SCALAR > * _bnet_
A pointer to it's IBayesNet used as a DAG.
ArcProperty< GUM_SCALAR > ArcsP_min_
"Lower" information coming from one's parent.
InferenceType
Inference type to be used by the algorithm.
@ nodeToNeighbours
Uses a node-set so we don't iterate on nodes that can't send a new message.
@ randomOrder
Chooses a random arc ordering and sends messages accordingly.
@ ordered
Chooses an arc ordering and sends messages accordingly at all steps.
void msgP_(const NodeId X, const NodeId demanding_child)
Sends a message to one's child, i.e.
ArcProperty< GUM_SCALAR > ArcsL_max_
"Upper" information coming from one's children.
void updateMarginals_()
Compute marginals from up-to-date messages.
const CredalNet< GUM_SCALAR > * _cn_
A pointer to the CredalNet to be used.
void computeExpectations_()
Since the network is binary, expectations can be computed from the final marginals which give us the ...
NodeProperty< GUM_SCALAR > NodesP_max_
"Upper" node information obtained by combinaison of parent's messages.
void enum_combi_(std::vector< std::vector< std::vector< GUM_SCALAR > > > &msgs_p, const NodeId &id, GUM_SCALAR &msg_l_min, GUM_SCALAR &msg_l_max, std::vector< GUM_SCALAR > &lx, const Idx &pos)
Used by msgL_.
InferenceType inferenceType()
Get the inference type.
void makeInferenceByOrderedArcs_()
Starts the inference with this inference type.
NodeSet active_nodes_set_
The current node-set to iterate through at this current step.
void updateIndicatrices_()
Only update indicatrices variables at the end of computations ( calls msgP_ ).
NodeSet next_active_nodes_set_
The next node-set, i.e.
CNLoopyPropagation(const CredalNet< GUM_SCALAR > &credalNet)
Constructor.
bool inference_up_to_date_
TRUE if inference has already been performed, FALSE otherwise.
ArcProperty< GUM_SCALAR > ArcsL_min_
"Lower" information coming from one's children.
ArcProperty< GUM_SCALAR > ArcsP_max_
"Upper" information coming from one's parent.
Class template representing a Credal Network.
void updateExpectations_(const NodeId &id, const std::vector< GUM_SCALAR > &vertex)
Given a node id and one of it's possible vertex obtained during inference, update this node lower and...
margi oldMarginalMax_
Old upper marginals used to compute epsilon.
margi evidence_
Holds observed variables states.
margi marginalMax_
Upper marginals.
void updateCredalSets_(const NodeId &id, const std::vector< GUM_SCALAR > &vertex, const bool &elimRedund=false)
Given a node id and one of it's possible vertex, update it's credal set.
virtual const GUM_SCALAR computeEpsilon_()
Compute approximation scheme epsilon using the old marginals and the new ones.
const std::vector< std::vector< GUM_SCALAR > > & vertices(const NodeId id) const
Get the vertice of a given node id.
InferenceEngine(const CredalNet< GUM_SCALAR > &credalNet)
Construtor.
margi oldMarginalMin_
Old lower marginals used to compute epsilon.
virtual void eraseAllEvidence()
removes all the evidence entered into the network
virtual void insertEvidenceFile(std::string_view path)
Insert evidence from file.
const CredalNet< GUM_SCALAR > & credalNet() const
Get this credal network.
margi marginalMin_
Lower marginals.
dynExpe modal_
Variables modalities used to compute expectations.
#define GUM_ERROR(type, msg)
std::size_t Size
In aGrUM, hashed values are unsigned long int.
Size Idx
Type for indexes.
Size NodeId
Type for node ids.
Set< NodeId > NodeSet
Some typdefs and define for shortcuts ...
Idx randomValue(const Size max=2)
Returns a random Idx between 0 and max-1 included.
namespace for all credal networks entities
std::vector< std::pair< Idx, Idx > > dispatchRangeToThreads(const Idx beg, const Idx end, const unsigned int nb_threads)
returns a vector equally splitting elements of a range among threads
unsigned int getNumberOfThreads()
returns the max number of threads used by default when entering the next parallel region
static void execute(std::size_t nb_threads, FUNCTION exec_func, ARGS &&... func_args)
executes a function using several threads
static int nbRunningThreadsExecutors()
indicates how many threadExecutors are currently running