aGrUM 3.1.1
a C++ library for (probabilistic) graphical models
BayesNet_tpl.h
Go to the documentation of this file.
1/****************************************************************************
2 * This file is part of the aGrUM/pyAgrum library. *
3 * *
4 * Copyright (c) 2005-2026 by *
5 * - Pierre-Henri WUILLEMIN(_at_LIP6) *
6 * - Christophe GONZALES(_at_AMU) *
7 * *
8 * The aGrUM/pyAgrum library is free software; you can redistribute it *
9 * and/or modify it under the terms of either : *
10 * *
11 * - the GNU Lesser General Public License as published by *
12 * the Free Software Foundation, either version 3 of the License, *
13 * or (at your option) any later version, *
14 * - the MIT license (MIT), *
15 * - or both in dual license, as here. *
16 * *
17 * (see https://agrum.gitlab.io/articles/dual-licenses-lgplv3mit.html) *
18 * *
19 * This aGrUM/pyAgrum library is distributed in the hope that it will be *
20 * useful, but WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
21 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES MERCHANTABILITY or FITNESS *
22 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
25 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
26 * OTHER DEALINGS IN THE SOFTWARE. *
27 * *
28 * See LICENCES for more details. *
29 * *
30 * SPDX-FileCopyrightText: Copyright 2005-2026 *
31 * - Pierre-Henri WUILLEMIN(_at_LIP6) *
32 * - Christophe GONZALES(_at_AMU) *
33 * SPDX-License-Identifier: LGPL-3.0-or-later OR MIT *
34 * *
35 * Contact : info_at_agrum_dot_org *
36 * homepage : http://agrum.gitlab.io *
37 * gitlab : https://gitlab.com/agrumery/agrum *
38 * *
39 ****************************************************************************/
40
41#pragma once
42
43
50
51#include <algorithm>
52#include <limits>
53#include <set>
54
72#include <agrum/BN/BayesNet.h>
74
76
77namespace gum {
78 template < GUM_Numeric GUM_SCALAR >
80 std::string_view node,
81 std::string_view default_domain) {
82 auto v = fastVariable< GUM_SCALAR >(std::string{node}, std::string(default_domain));
83
84 NodeId res;
85 if (bn.exists(v->name())) res = bn.idFromName(v->name());
86 else res = bn.add(*v);
87 return res;
88 }
89
90 template < GUM_Numeric GUM_SCALAR >
91 BayesNet< GUM_SCALAR > BayesNet< GUM_SCALAR >::fastPrototype(std::string_view dotlike,
92 Size domainSize) {
93 return fastPrototype(dotlike, "[" + std::to_string(domainSize) + "]");
94 }
95
96 template < GUM_Numeric GUM_SCALAR >
97 BayesNet< GUM_SCALAR > BayesNet< GUM_SCALAR >::fastPrototype(std::string_view dotlike,
98 std::string_view domain) {
100
101 auto resolve = [&](const std::string& node) { return build_node(bn, node, domain); };
102 auto addArc = [&](NodeId tail, NodeId head, const std::string&) { bn.addArc(tail, head); };
103 auto addEdge = [&](NodeId, NodeId, const std::string& token) {
105 "fastPrototype: '" << token << "' is preceded by '-' but a BayesNet "
106 << "does not support edges")
107 };
108
109 for (const auto& chaine: split(remove_newline(dotlike), ";")) {
110 using namespace detail;
111 fastGraphWalkTokens(fastGraphTokenize(chaine), dotlike, resolve, addArc, addEdge);
112 }
113 bn.generateCPTs();
114 bn.setProperty("name", "anonymousBN");
115 return bn;
116 }
117
118 template < GUM_Numeric GUM_SCALAR >
120 GUM_CONSTRUCTOR(BayesNet)
121 }
122
123 template < GUM_Numeric GUM_SCALAR >
124 BayesNet< GUM_SCALAR >::BayesNet(std::string_view name) : IBayesNet< GUM_SCALAR >(name) {
125 GUM_CONSTRUCTOR(BayesNet)
126 }
128 template < GUM_Numeric GUM_SCALAR >
129 BayesNet< GUM_SCALAR >::BayesNet(const BayesNet< GUM_SCALAR >& source) :
130 IBayesNet< GUM_SCALAR >(source) {
131 GUM_CONS_CPY(BayesNet)
132
133 _copyTensors_(source);
134 }
135
136 template < GUM_Numeric GUM_SCALAR >
137 BayesNet< GUM_SCALAR >::BayesNet(BayesNet< GUM_SCALAR >&& source) :
138 IBayesNet< GUM_SCALAR >(std::move(source)), _probaMap_(std::move(source._probaMap_)) {
139 GUM_CONS_MOV(BayesNet)
140 }
141
142 template < GUM_Numeric GUM_SCALAR >
143 BayesNet< GUM_SCALAR >& BayesNet< GUM_SCALAR >::operator=(const BayesNet< GUM_SCALAR >& source) {
144 if (this != &source) {
147 _copyTensors_(source);
148 GUM_OP_CPY(BayesNet);
149 }
150
151 return *this;
152 }
153
154 template < GUM_Numeric GUM_SCALAR >
155 BayesNet< GUM_SCALAR >& BayesNet< GUM_SCALAR >::operator=(BayesNet< GUM_SCALAR >&& source) {
156 if (this != &source) {
157 IBayesNet< GUM_SCALAR >::operator=(std::move(source));
159 _probaMap_ = std::move(source._probaMap_);
160 GUM_OP_MOV(BayesNet);
161 }
162 return *this;
163 }
164
165 template < GUM_Numeric GUM_SCALAR >
167 GUM_DESTRUCTOR(BayesNet)
168 for (const auto& p: _probaMap_) {
169 delete p.second;
170 }
171 }
172
173 template < GUM_Numeric GUM_SCALAR >
174 void BayesNet< GUM_SCALAR >::changeVariableName(NodeId id, std::string_view new_name) {
175 this->varMap_.changeName(id, new_name);
176 }
177
178 template < GUM_Numeric GUM_SCALAR >
180 std::string_view old_label,
181 std::string_view new_label) {
182 if (variable(id).varType() != VarType::LABELIZED)
183 GUM_ERROR(NotFound, "Variable " << id << " is not a LabelizedVariable.")
184
185 auto* var = dynamic_cast< LabelizedVariable* >(const_cast< DiscreteVariable* >(&variable(id)));
186 if (var == nullptr) GUM_ERROR(TypeError, "Variable " << id << " is not a LabelizedVariable.")
187
188 var->changeLabel(var->posLabel(old_label), new_label);
189 }
190
191 template < GUM_Numeric GUM_SCALAR >
193 auto ptr = new MultiDimArray< GUM_SCALAR >();
194 try {
195 return add(var, ptr);
196 } catch (Exception const&) {
197 delete ptr;
198 throw;
199 }
200 }
201
202 template < GUM_Numeric GUM_SCALAR >
203 NodeId BayesNet< GUM_SCALAR >::add(std::string_view fast_description,
204 unsigned int default_nbrmod) {
205 auto v = fastVariable< GUM_SCALAR >(std::string(fast_description), default_nbrmod);
206 if (v->domainSize() < 2) GUM_ERROR(OperationNotAllowed, v->name() << " has a domain size <2")
207 return add(*v);
208 }
209
210 template < GUM_Numeric GUM_SCALAR >
213 NodeId proposedId = dag().nextNodeId();
214
215 return add(var, aContent, proposedId);
216 }
217
218 template < GUM_Numeric GUM_SCALAR >
221
222 try {
223 return add(var, ptr, id);
224 } catch (Exception const&) {
225 delete ptr;
226 throw;
227 }
228 }
229
230 template < GUM_Numeric GUM_SCALAR >
233 NodeId id) {
234 this->varMap_.insert(id, var);
235 this->dag_.addNodeWithId(id);
236
237 auto cpt = new Tensor< GUM_SCALAR >(aContent);
238 (*cpt) << variable(id);
239 _probaMap_.insert(id, cpt);
240 return id;
241 }
242
243 template < GUM_Numeric GUM_SCALAR >
244 const Tensor< GUM_SCALAR >& BayesNet< GUM_SCALAR >::cpt(NodeId varId) const {
245 return *(_probaMap_[varId]);
246 }
247
248 template < GUM_Numeric GUM_SCALAR >
250 erase(this->varMap_.get(var));
251 }
252
253 template < GUM_Numeric GUM_SCALAR >
255 if (this->varMap_.exists(varId)) {
256 // Reduce the variable child's CPT
257 for (const NodeSet& children = this->children(varId); const auto c: children) {
258 _probaMap_[c]->erase(variable(varId));
259 }
260
261 delete _probaMap_[varId];
262
263 _probaMap_.erase(varId);
264 this->varMap_.erase(varId);
265 this->dag_.eraseNode(varId);
266 }
267 }
268
269 template < GUM_Numeric GUM_SCALAR >
271 if (!this->empty()) {
272 auto l = this->nodes();
273 for (const auto no: l) {
274 this->erase(no);
275 }
276 }
277 }
278
279 template < GUM_Numeric GUM_SCALAR >
281 if (this->dag_.existsArc(tail, head)) {
282 GUM_ERROR(DuplicateElement, "The arc (" << tail << "," << head << ") already exists.")
283 }
284
285 this->dag_.addArc(tail, head);
286 // Add parent in the child's CPT
287 (*(_probaMap_[head])) << variable(tail);
288 }
289
290 template < GUM_Numeric GUM_SCALAR >
291 void BayesNet< GUM_SCALAR >::addArc(std::string_view tail, std::string_view head) {
292 try {
293 addArc(this->idFromName(tail), this->idFromName(head));
294 } catch (DuplicateElement const&) {
295 GUM_ERROR(DuplicateElement, "The arc " << tail << "->" << head << " already exists.")
296 }
297 }
298
299 template < GUM_Numeric GUM_SCALAR >
301 if (this->varMap_.exists(arc.tail()) && this->varMap_.exists(arc.head())) {
302 NodeId head = arc.head();
303 NodeId tail = arc.tail();
304 this->dag_.eraseArc(arc);
305 // Remove parent from child's CPT
306 (*(_probaMap_[head])) >> variable(tail);
307 }
308 }
309
310 template < GUM_Numeric GUM_SCALAR >
312 eraseArc(Arc(tail, head));
313 }
314
315 template < GUM_Numeric GUM_SCALAR >
317 // check that the arc exists
318 if (!this->varMap_.exists(arc.tail()) || !this->varMap_.exists(arc.head())
319 || !dag().existsArc(arc)) {
320 GUM_ERROR(InvalidArc, "a non-existing arc cannot be reversed")
321 }
322
323 NodeId tail = arc.tail();
324 NodeId head = arc.head();
325
326 // check that the reversal does not induce a cycle
327 try {
328 DAG d = dag();
329 d.eraseArc(arc);
330 d.addArc(head, tail);
331 } catch (Exception const&) {
332 GUM_ERROR(InvalidArc, "this arc reversal would induce a directed cycle")
333 }
334
335 // with the same notations as Shachter (1986), "evaluating influence
336 // diagrams", p.878, we shall first compute the product of probabilities:
337 // pi_j^old (x_j | x_c^old(j) ) * pi_i^old (x_i | x_c^old(i) )
338 Tensor< GUM_SCALAR > prod{cpt(tail) * cpt(head)};
339
340 // modify the topology of the graph: add to tail all the parents of head
341 // and add to head all the parents of tail
343 NodeSet new_parents;
344 for (const auto node: this->parents(tail))
345 new_parents.insert(node);
346 for (const auto node: this->parents(head))
347 new_parents.insert(node);
348 // remove arc (head, tail)
349 eraseArc(arc);
350
351 // add the necessary arcs to the tail
352 for (const auto p: new_parents) {
353 if ((p != tail) && !dag().existsArc(p, tail)) { addArc(p, tail); }
354 }
355
356 addArc(head, tail);
357 // add the necessary arcs to the head
358 new_parents.erase(tail);
359
360 for (const auto p: new_parents) {
361 if ((p != head) && !dag().existsArc(p, head)) { addArc(p, head); }
362 }
363
364 endTopologyTransformation();
365
366 // update the conditional distributions of head and tail
367 gum::VariableSet del_vars;
368 del_vars << &(variable(tail));
369 Tensor< GUM_SCALAR > new_cpt_head = prod.sumOut(del_vars).putFirst(&variable(head));
370
371 auto& cpt_head = const_cast< Tensor< GUM_SCALAR >& >(cpt(head));
372 cpt_head = std::move(new_cpt_head);
373
374 Tensor< GUM_SCALAR > new_cpt_tail{(prod / cpt_head).putFirst(&variable(tail))};
375 auto& cpt_tail = const_cast< Tensor< GUM_SCALAR >& >(cpt(tail));
376 cpt_tail = std::move(new_cpt_tail);
377 }
378
379 template < GUM_Numeric GUM_SCALAR >
381 reverseArc(Arc(tail, head));
382 }
383
384 //==============================================
385 // Aggregators
386 //=============================================
387 template < GUM_Numeric GUM_SCALAR >
391
392 template < GUM_Numeric GUM_SCALAR >
394 if (var.domainSize() > 2) GUM_ERROR(SizeError, "an AND has to be boolean")
395
396 return add(var, new aggregator::And< GUM_SCALAR >());
397 }
398
399 template < GUM_Numeric GUM_SCALAR >
403
404 template < GUM_Numeric GUM_SCALAR >
406 if (var.domainSize() > 2) GUM_ERROR(SizeError, "an EXISTS has to be boolean")
407
408 return add(var, new aggregator::Exists< GUM_SCALAR >(value));
409 }
410
411 template < GUM_Numeric GUM_SCALAR >
413 if (var.domainSize() > 2) GUM_ERROR(SizeError, "an EXISTS has to be boolean")
414
415 return add(var, new aggregator::Forall< GUM_SCALAR >(value));
416 }
417
418 template < GUM_Numeric GUM_SCALAR >
422
423 template < GUM_Numeric GUM_SCALAR >
428 template < GUM_Numeric GUM_SCALAR >
432
433 template < GUM_Numeric GUM_SCALAR >
435 if (var.domainSize() > 2) GUM_ERROR(SizeError, "an OR has to be boolean")
436
437 return add(var, new aggregator::Or< GUM_SCALAR >());
438 }
439
440 template < GUM_Numeric GUM_SCALAR >
445 template < GUM_Numeric GUM_SCALAR >
446 NodeId BayesNet< GUM_SCALAR >::_addAggregator_(std::string_view aggregatorType,
447 const DiscreteVariable& var,
448 Idx value) {
449 const std::string type = toLower(aggregatorType);
450 if (type == "and") return addAND(var);
451 if (type == "or") return addOR(var);
452 if (type == "amplitude") return addAMPLITUDE(var);
453 if (type == "count") return addCOUNT(var, value);
454 if (type == "exists") return addEXISTS(var, value);
455 if (type == "forall") return addFORALL(var, value);
456 if (type == "max") return addMAX(var);
457 if (type == "median") return addMEDIAN(var);
458 if (type == "min") return addMIN(var);
459 if (type == "sum") return addSUM(var);
460 GUM_ERROR(NotFound, "Unknown aggregator type: " << aggregatorType)
461 }
462
463 //================================
464 // ICIModels
465 //================================
466 template < GUM_Numeric GUM_SCALAR >
468 GUM_SCALAR external_weight) {
469 return addNoisyORCompound(var, external_weight);
470 }
471
472 template < GUM_Numeric GUM_SCALAR >
474 GUM_SCALAR external_weight) {
475 return add(var, new MultiDimNoisyORCompound< GUM_SCALAR >(external_weight));
477
478 template < GUM_Numeric GUM_SCALAR >
480 GUM_SCALAR external_weight) {
481 return add(var, new MultiDimNoisyORNet< GUM_SCALAR >(external_weight));
482 }
483
484 template < GUM_Numeric GUM_SCALAR >
486 GUM_SCALAR external_weight) {
487 return add(var, new MultiDimNoisyAND< GUM_SCALAR >(external_weight));
488 }
489
490 template < GUM_Numeric GUM_SCALAR >
491 NodeId BayesNet< GUM_SCALAR >::addLogit(const DiscreteVariable& var, GUM_SCALAR external_weight) {
492 return add(var, new MultiDimLogit< GUM_SCALAR >(external_weight));
493 }
494
495 template < GUM_Numeric GUM_SCALAR >
497 const DiscreteVariable& var,
498 GUM_SCALAR externalWeight) {
499 if (iciType == "MultiDimNoisyORCompound") return addNoisyORCompound(var, externalWeight);
500 if (iciType == "MultiDimNoisyORNet") return addNoisyORNet(var, externalWeight);
501 if (iciType == "MultiDimNoisyAND") return addNoisyAND(var, externalWeight);
502 if (iciType == "MultiDimLogit") return addLogit(var, externalWeight);
503 GUM_ERROR(NotFound, "Unknown ICI model type: " << iciType)
504 }
505
506 template < GUM_Numeric GUM_SCALAR >
508 GUM_SCALAR external_weight,
509 NodeId id) {
510 return addNoisyORCompound(var, external_weight, id);
511 }
512
513 template < GUM_Numeric GUM_SCALAR >
515 GUM_SCALAR external_weight,
516 NodeId id) {
517 return add(var, new MultiDimNoisyAND< GUM_SCALAR >(external_weight), id);
518 }
519
520 template < GUM_Numeric GUM_SCALAR >
522 GUM_SCALAR external_weight,
523 NodeId id) {
524 return add(var, new MultiDimLogit< GUM_SCALAR >(external_weight), id);
525 }
526
527 template < GUM_Numeric GUM_SCALAR >
529 GUM_SCALAR external_weight,
530 NodeId id) {
531 return add(var, new MultiDimNoisyORCompound< GUM_SCALAR >(external_weight), id);
533
534 template < GUM_Numeric GUM_SCALAR >
536 GUM_SCALAR external_weight,
537 NodeId id) {
538 return add(var, new MultiDimNoisyORNet< GUM_SCALAR >(external_weight), id);
539 }
540
541 template < GUM_Numeric GUM_SCALAR >
542 void BayesNet< GUM_SCALAR >::addWeightedArc(NodeId tail, NodeId head, GUM_SCALAR causalWeight) {
543 if (auto* CImodel
544 = dynamic_cast< const MultiDimICIModel< GUM_SCALAR >* >(cpt(head).content())) {
545 // or is OK
546 addArc(tail, head);
547
548 CImodel->causalWeight(variable(tail), causalWeight);
549 } else {
551 "Head variable (" << variable(head).name() << ") is not a CIModel variable !")
552 }
553 }
554
555 template < GUM_Numeric GUM_SCALAR >
556 std::ostream& operator<<(std::ostream& output, const BayesNet< GUM_SCALAR >& bn) {
557 output << bn.toString();
558 return output;
559 }
560
562 template < GUM_Numeric GUM_SCALAR >
564 for (const auto node: nodes())
565 _probaMap_[node]->beginMultipleChanges();
566 }
567
568 /// end Multiple Change for all CPTs
569 template < GUM_Numeric GUM_SCALAR >
571 for (const auto node: nodes())
572 _probaMap_[node]->endMultipleChanges();
573 }
575 /// clear all tensors
576 template < GUM_Numeric GUM_SCALAR >
578 // Removing previous tensors
579 for (const auto& elt: _probaMap_) {
580 delete elt.second;
582
583 _probaMap_.clear();
584 }
585
587 template < GUM_Numeric GUM_SCALAR >
588 void BayesNet< GUM_SCALAR >::_copyTensors_(const BayesNet< GUM_SCALAR >& source) {
589 // Copying tensors
590
591 for (const auto& src: source._probaMap_) {
592 // First we build the node's CPT
593 auto copy_array = new Tensor< GUM_SCALAR >();
594 copy_array->beginMultipleChanges();
595 for (gum::Idx i = 0; i < src.second->nbrDim(); i++) {
596 (*copy_array) << variableFromName(src.second->variable(i).name());
597 }
598 copy_array->endMultipleChanges();
599 copy_array->copyFrom(*(src.second));
600
601 // We add the CPT to the CPT hashmap
602 _probaMap_.insert(src.first, copy_array);
603 }
604 }
605
606 template < GUM_Numeric GUM_SCALAR >
608 for (const auto node: nodes())
609 generateCPT(node);
610 }
611
612 template < GUM_Numeric GUM_SCALAR >
616 generator.generateCPT(cpt(node).pos(variable(node)), cpt(node));
617 }
618
619 template < GUM_Numeric GUM_SCALAR >
620 void BayesNet< GUM_SCALAR >::changeTensor(NodeId id, Tensor< GUM_SCALAR >* newPot) {
621 if (cpt(id).nbrDim() != newPot->nbrDim()) {
623 "cannot exchange tensors with different "
624 "dimensions for variable with id "
625 << id)
626 }
627
628 for (Idx i = 0; i < cpt(id).nbrDim(); i++) {
629 if (&cpt(id).variable(i) != &(newPot->variable(i))) {
631 "cannot exchange tensors because, for variable with id " << id << ", dimension "
632 << i << " differs. ")
633 }
634 }
635
636 _unsafeChangeTensor_(id, newPot);
638
639 template < GUM_Numeric GUM_SCALAR >
640 void BayesNet< GUM_SCALAR >::_unsafeChangeTensor_(NodeId id, Tensor< GUM_SCALAR >* newPot) {
641 delete _probaMap_[id];
642 _probaMap_[id] = newPot;
643 }
644
645 template < GUM_Numeric GUM_SCALAR >
646 void BayesNet< GUM_SCALAR >::changeTensor(std::string_view name, Tensor< GUM_SCALAR >* newPot) {
647 changeTensor(idFromName(name), newPot);
648 }
649
650 template < GUM_Numeric GUM_SCALAR >
651 BayesNet< GUM_SCALAR >
653 const gum::Instantiation& interventions) const {
655 for (gum::Idx i = 0; i < observations.nbrDim(); i++) {
656 if (interventions.contains(observations.variable(i))) {
658 "Cannot have both an observation and an intervention on the same variable")
659 }
660 all.add(observations.variable(i));
661 }
662 for (gum::Idx i = 0; i < interventions.nbrDim(); i++) {
663 all.add(interventions.variable(i));
664 }
665 all.setVals(observations);
666 all.setVals(interventions);
667
668 NodeSet cpt_changed;
669
671
672 bn.beginTopologyTransformation();
673 for (gum::Idx i = 0; i < observations.nbrDim(); i++) {
674 const std::string& nam = observations.variable(i).name();
675 const gum::NodeId nod = this->idFromName(nam);
676 for (gum::NodeId child: this->children(nod)) {
677 bn.eraseArc(bn.idFromName(nam), bn.idFromName(this->variable(child).name()));
678 }
679 }
680 for (gum::Idx i = 0; i < interventions.nbrDim(); i++) {
681 const std::string& nam = interventions.variable(i).name();
682 const gum::NodeId nod = this->idFromName(nam);
683 for (gum::NodeId child: this->children(nod)) {
684 bn.eraseArc(bn.idFromName(nam), bn.idFromName(this->variable(child).name()));
685 }
686 for (gum::NodeId par: this->parents(nod)) {
687 const auto v1 = bn.idFromName(this->variable(par).name());
688 const auto v2 = bn.idFromName(nam);
689 if (bn.existsArc(v1, v2)) bn.eraseArc(v1, v2);
690 }
691 cpt_changed.insert(bn.idFromName(nam));
692 bn.cpt(bn.idFromName(nam))
693 .fillWith(Tensor< GUM_SCALAR >::deterministicTensor(bn.variable(bn.idFromName(nam)),
694 interventions.val(i)));
695 }
696 bn.endTopologyTransformation();
697
698 for (gum::Idx i = 0; i < all.nbrDim(); i++) {
699 const gum::NodeId nod = this->idFromName(all.variable(i).name());
700 for (gum::NodeId child: this->children(nod)) {
701 if (!cpt_changed.contains(child)) {
702 cpt_changed.insert(child);
703 bn.cpt(bn.idFromName(this->variable(child).name()))
704 .fillWith(this->cpt(child).extract(all));
705 }
706 }
707 }
708
709 return bn;
710 }
711
712 template < GUM_Numeric GUM_SCALAR >
713 const Tensor< GUM_SCALAR >& BayesNet< GUM_SCALAR >::cpt(std::string_view name) const {
714 return cpt(idFromName(name));
715 }
716
717 template < GUM_Numeric GUM_SCALAR >
718 void BayesNet< GUM_SCALAR >::erase(std::string_view name) {
719 erase(idFromName(name));
720 }
721
722 template < GUM_Numeric GUM_SCALAR >
723 const DiscreteVariable& BayesNet< GUM_SCALAR >::variable(std::string_view name) const {
724 return variable(idFromName(name));
725 }
726
727 template < GUM_Numeric GUM_SCALAR >
729 std::string_view new_name) {
730 changeVariableName(idFromName(name), new_name);
731 }
732
733 template < GUM_Numeric GUM_SCALAR >
735 std::string_view old_label,
736 std::string_view new_label) {
737 changeVariableLabel(idFromName(name), old_label, new_label);
738 }
739
740 template < GUM_Numeric GUM_SCALAR >
741 void BayesNet< GUM_SCALAR >::eraseArc(std::string_view tail, std::string_view head) {
742 eraseArc(idFromName(tail), idFromName(head));
743 }
744
745 template < GUM_Numeric GUM_SCALAR >
746 void BayesNet< GUM_SCALAR >::reverseArc(std::string_view tail, std::string_view head) {
747 reverseArc(idFromName(tail), idFromName(head));
748 }
749
750 template < GUM_Numeric GUM_SCALAR >
751 void BayesNet< GUM_SCALAR >::addWeightedArc(std::string_view tail,
752 std::string_view head,
753 GUM_SCALAR causalWeight) {
754 addWeightedArc(idFromName(tail), idFromName(head), causalWeight);
755 }
756
757 template < GUM_Numeric GUM_SCALAR >
758 void BayesNet< GUM_SCALAR >::generateCPT(std::string_view name) const {
759 generateCPT(idFromName(name));
760 }
761
762} /* namespace gum */
Class representing Bayesian networks.
amplitude aggregator
and aggregator
virtual void eraseArc(const Arc &arc)
removes an arc from the ArcGraphPart
The base class for all directed edges.
GUM_NODISCARD NodeId head() const
returns the head of the arc
GUM_NODISCARD NodeId tail() const
returns the tail of the arc
Exception base for argument error.
Class representing a Bayesian network.
Definition BayesNet.h:99
NodeId idFromName(std::string_view name) const override
Returns the NodeId of a variable given its name.
NodeId addLogit(const DiscreteVariable &var, GUM_SCALAR external_weight, NodeId id)
Add a variable, its associate node and a Logit implementation.
void eraseArc(const Arc &arc)
Removes an arc in the BN, and update head's CTP.
void endTopologyTransformation()
terminates a sequence of insertions/deletions of arcs by adjusting all CPTs dimensions.
NodeId addCOUNT(const DiscreteVariable &var, Idx value=1)
Others aggregators.
NodeId addAMPLITUDE(const DiscreteVariable &var)
Others aggregators.
static BayesNet< GUM_SCALAR > fastPrototype(std::string_view dotlike, Size domainSize)
Create a Bayesian network with a dot-like syntax which specifies:
NodeId addAND(const DiscreteVariable &var)
Add a variable, it's associate node and an AND implementation.
void beginTopologyTransformation()
When inserting/removing arcs, node CPTs change their dimension with a cost in time.
const Tensor< GUM_SCALAR > & cpt(NodeId varId) const final
Returns the CPT of a variable.
void erase(NodeId varId)
Remove a variable from the gum::BayesNet.
NodeId addMAX(const DiscreteVariable &var)
Others aggregators.
void clear()
clear the whole Bayes net *
void changeVariableLabel(NodeId id, std::string_view old_label, std::string_view new_label)
Changes a variable's label in the gum::BayesNet.
const DiscreteVariable & variable(std::string_view name) const
Returns a gum::DiscreteVariable given its name in the gum::BayesNet.
void changeTensor(NodeId id, Tensor< GUM_SCALAR > *newPot)
change the CPT associated to nodeId to newPot delete the old CPT associated to nodeId.
NodeId addEXISTS(const DiscreteVariable &var, Idx value=1)
Others aggregators.
void addWeightedArc(NodeId tail, NodeId head, GUM_SCALAR causalWeight)
Add an arc in the BN, and update arc.head's CPT.
NodeId addSUM(const DiscreteVariable &var)
Others aggregators.
BayesNet< GUM_SCALAR > contextualize(const gum::Instantiation &observations, const gum::Instantiation &interventions) const
create a contextual BN from this and a set of hard observations and hard interventions.
NodeId _addAggregator_(std::string_view aggregatorType, const DiscreteVariable &var, Idx value=1)
Generic factory for aggregator nodes, dispatching on the aggregator's name.
NodeId addNoisyORNet(const DiscreteVariable &var, GUM_SCALAR external_weight)
Add a variable, it's associate node and a gum::noisyOR implementation.
const DiscreteVariable & variableFromName(std::string_view name) const override
void _copyTensors_(const BayesNet< GUM_SCALAR > &source)
copy of tensors from a BN to another, using names of vars as ref.
NodeId addNoisyAND(const DiscreteVariable &var, GUM_SCALAR external_weight, NodeId id)
Add a variable, its associate node and a noisyAND implementation.
void addArc(NodeId tail, NodeId head)
Add an arc in the BN, and update arc.head's CPT.
NodeId addFORALL(const DiscreteVariable &var, Idx value=1)
Others aggregators.
NodeId add(const DiscreteVariable &var)
Add a variable to the gum::BayesNet.
void reverseArc(NodeId tail, NodeId head)
Reverses an arc while preserving the same joint distribution.
NodeId addMIN(const DiscreteVariable &var)
Others aggregators.
NodeId addNoisyORCompound(const DiscreteVariable &var, GUM_SCALAR external_weight)
Add a variable, it's associate node and a gum::noisyOR implementation.
NodeId addNoisyOR(const DiscreteVariable &var, GUM_SCALAR external_weight)
Add a variable, it's associate node and a gum::noisyOR implementation.
void generateCPT(NodeId node) const
randomly generate CPT for a given node in a given structure
NodeProperty< Tensor< GUM_SCALAR > * > _probaMap_
Mapping between the variable's id and their CPT.
Definition BayesNet.h:648
NodeId addMEDIAN(const DiscreteVariable &var)
Others aggregators.
void changeVariableName(NodeId id, std::string_view new_name)
Changes a variable's name in the gum::BayesNet.
void _clearTensors_()
clear all tensors
NodeId addOR(const DiscreteVariable &var)
Add a variable, it's associate node and an OR implementation.
void _unsafeChangeTensor_(NodeId id, Tensor< GUM_SCALAR > *newPot)
change the CPT associated to nodeId to newPot delete the old CPT associated to nodeId.
~BayesNet() override
Destructor.
void generateCPTs() const
randomly generates CPTs for a given structure
BayesNet()
Default constructor.
NodeId _addICIModel_(std::string_view iciType, const DiscreteVariable &var, GUM_SCALAR externalWeight)
Generic factory for ICI model nodes, dispatching on the implementation's name.
BayesNet< GUM_SCALAR > & operator=(const BayesNet< GUM_SCALAR > &source)
Copy operator.
const DiscreteVariable & variable(NodeId id) const override
Base class for dag.
Definition DAG.h:121
void addArc(NodeId tail, NodeId head) final
insert a new arc into the directed graph
Definition DAG_inl.h:75
DAG dag_
The DAG of this Directed Graphical Model.
Definition DAGmodel.h:284
bool existsArc(const NodeId tail, const NodeId head) const
return true if the arc tail->head exists in the DAGmodel
DAG dag() const
Returns a named copy of the internal DAG: each node id is assigned the name of the corresponding vari...
const NodeSet & children(const NodeId id) const
returns the set of nodes with arc outgoing from a given node
bool exists(NodeId node) const final
Return true if this node exists in this graphical model.
const NodeSet & parents(const NodeId id) const
const NodeGraphPart & nodes() const final
Returns a named copy of the internal DAG: each node id is assigned the name of the corresponding vari...
Base class for discrete random variable.
virtual Size domainSize() const =0
Exception : a similar element already exists.
Base class for all aGrUM's exceptions.
Definition exceptions.h:122
void setProperty(std::string_view name, std::string_view value)
Add or change a property of this GraphicalModel.
virtual bool empty() const
Return true if this graphical model is empty.
IBayesNet()
Default constructor.
IBayesNet< GUM_SCALAR > & operator=(const IBayesNet< GUM_SCALAR > &source)
Copy operator.
Class for assigning/browsing values to tuples of discrete variables.
Instantiation & setVals(const Instantiation &i)
Assign the values from i in the Instantiation.
void add(const DiscreteVariable &v) final
Adds a new variable in the Instantiation.
bool contains(const DiscreteVariable &v) const final
Indicates whether a given variable belongs to the Instantiation.
Idx val(Idx i) const
Returns the current value of the variable at position i.
const DiscreteVariable & variable(Idx i) const final
Returns the variable at position i in the tuple.
Idx nbrDim() const final
Returns the number of variables in the Instantiation.
Exception : there is something wrong with an arc.
Exception : there is something wrong with an edge.
class LabelizedVariable
void changeLabel(Idx pos, std::string_view aLabel) const
change a label for this index
Multidimensional matrix stored as an array in memory.
Logit representation.
Noisy AND representation.
Noisy OR representation.
Exception : the element we looked for cannot be found.
Exception : operation not allowed.
bool contains(const Key &k) const
Indicates whether a given elements belong to the set.
Definition set_tpl.h:468
void insert(const Key &k)
Inserts a new element into the set.
Definition set_tpl.h:510
<agrum/BN/generator/simpleCPTGenerator.h>
Exception : problem with size.
aGrUM's Tensor is a multi-dimensional array with tensor operators.
Definition tensor.h:85
static Tensor< GUM_SCALAR > deterministicTensor(const DiscreteVariable &var, Idx value)
Exception : wrong type for this operation.
const std::string & name() const
returns the name of the variable
amplitude aggregator
Definition amplitude.h:74
And aggregator.
Definition and.h:74
count aggregator
Definition count.h:76
exists aggregator
Definition exists.h:73
forall aggregator
Definition forall.h:74
max aggregator
Definition max.h:73
median aggregator
Definition median.h:79
min aggregator
Definition min.h:72
or aggregator
Definition or.h:75
Sum aggregator.
Definition sum.h:69
count aggregator
#define GUM_ERROR(type, msg)
Definition exceptions.h:76
exists aggregator
Builds a graph from a "fast" DOT-like textual description.
forall aggregator
std::size_t Size
In aGrUM, hashed values are unsigned long int.
Definition types.h:74
Size Idx
Type for indexes.
Definition types.h:79
Size NodeId
Type for node ids.
Set< NodeId > NodeSet
Some typdefs and define for shortcuts ...
std::string remove_newline(std::string_view s)
remove all newlines in a string
std::string toLower(std::string_view str)
Returns the lowercase version of str.
std::vector< std::string > split(std::string_view str, std::string_view delim)
Split str using the delimiter.
max aggregator
median aggregator
min aggregator
class for LOGIT implementation as multiDim
class for NoisyAND-net implementation as multiDim
class for multiDimNoisyORCompound
class for NoisyOR-net implementation as multiDim
gum is the global namespace for all aGrUM entities
Definition agrum.h:46
Set< const DiscreteVariable * > VariableSet
std::ostream & operator<<(std::ostream &stream, const AVLTree< Val, Cmp > &tree)
display the content of a tree
std::unique_ptr< DiscreteVariable > fastVariable(std::string var_description, Size default_domain_size)
Create a pointer on a Discrete Variable from a "fast" syntax.
NodeId build_node(gum::BayesNet< GUM_SCALAR > &bn, std::string_view node, std::string_view default_domain)
STL namespace.
or aggregator
Abstract class for generating Conditional Probability Tables.
sum aggregator
Utilities for manipulating strings.