aGrUM 3.1.1
a C++ library for (probabilistic) graphical models
marginalTargetedInference_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
49#include <iterator>
50
51#include <agrum/BN/inference/tools/marginalTargetedInference.h> // to ease IDE parser
52
53namespace gum {
54
55
56 // Default Constructor
57 template < GUM_Numeric GUM_SCALAR >
59 const IBayesNet< GUM_SCALAR >* bn) : BayesNetInference< GUM_SCALAR >(bn) {
60 // assign a BN if this has not been done before (due to virtual inheritance)
61 if (this->hasNoModel_()) {
63 }
64
65 // sets all the nodes as targets
66 if (bn != nullptr) {
67 _targeted_mode_ = false;
68 _targets_ = bn->dag().asNodeSet();
69 }
70
71 GUM_CONSTRUCTOR(MarginalTargetedInference);
72 }
73
74 // Destructor
75 template < GUM_Numeric GUM_SCALAR >
79
80 // fired when a new BN is assigned to the inference engine
81 template < GUM_Numeric GUM_SCALAR >
86
87 // ##############################################################################
88 // Targets
89 // ##############################################################################
90
91 // return true if variable is a target
92 template < GUM_Numeric GUM_SCALAR >
94 // check that the variable belongs to the bn
95 if (this->hasNoModel_())
97 "No Bayes net has been assigned to the "
98 "inference algorithm");
99 if (!this->BN().internalDag().exists(node)) {
100 GUM_ERROR(UndefinedElement, node << " is not a NodeId in the bn")
101 }
102
103 return _targets_.contains(node);
104 }
105
106 // Add a single target to the list of targets
107 template < GUM_Numeric GUM_SCALAR >
108 bool MarginalTargetedInference< GUM_SCALAR >::isTarget(std::string_view nodeName) const {
109 return isTarget(this->BN().idFromName(nodeName));
110 }
111
112 // Clear all previously defined targets (single targets and sets of targets)
113 template < GUM_Numeric GUM_SCALAR >
122
123 // Add a single target to the list of targets
124 template < GUM_Numeric GUM_SCALAR >
126 // check if the node belongs to the Bayesian network
127 if (this->hasNoModel_())
129 "No Bayes net has been assigned to the "
130 "inference algorithm");
131
132 if (!this->BN().internalDag().exists(target)) {
133 GUM_ERROR(UndefinedElement, target << " is not a NodeId in the bn")
134 }
135
136 setTargetedMode_(); // does nothing if already in targeted mode
137 // add the new target
138 if (!_targets_.contains(target)) {
139 _targets_.insert(target);
142 }
143 }
144
145 // Add all nodes as targets
146 template < GUM_Numeric GUM_SCALAR >
148 // check if the node belongs to the Bayesian network
149 if (this->hasNoModel_())
151 "No Bayes net has been assigned to the "
152 "inference algorithm");
153
154
155 setTargetedMode_(); // does nothing if already in targeted mode
156 for (const auto target: this->BN().internalDag()) {
157 if (!_targets_.contains(target)) {
158 _targets_.insert(target);
161 }
162 }
163 }
164
165 // Add a single target to the list of targets
166 template < GUM_Numeric GUM_SCALAR >
168 // check if the node belongs to the Bayesian network
169 if (this->hasNoModel_())
171 "No Bayes net has been assigned to the "
172 "inference algorithm");
173
174 addTarget(this->BN().idFromName(nodeName));
175 }
176
177 // removes an existing target
178 template < GUM_Numeric GUM_SCALAR >
180 // check if the node belongs to the Bayesian network
181 if (this->hasNoModel_())
183 "No Bayes net has been assigned to the "
184 "inference algorithm");
185
186 if (!this->BN().internalDag().exists(target)) {
187 GUM_ERROR(UndefinedElement, target << " is not a NodeId in the bn")
188 }
189
190
191 if (_targets_.contains(target)) {
192 _targeted_mode_ = true; // we do not use setTargetedMode_ because we do not
193 // want to clear the targets
195 _targets_.erase(target);
197 }
198 }
199
200 // Add a single target to the list of targets
201 template < GUM_Numeric GUM_SCALAR >
203 // check if the node belongs to the Bayesian network
204 if (this->hasNoModel_())
206 "No Bayes net has been assigned to the "
207 "inference algorithm");
208
209 eraseTarget(this->BN().idFromName(nodeName));
210 }
211
212 // returns the list of single targets
213 template < GUM_Numeric GUM_SCALAR >
215 return _targets_;
216 }
217
218 // returns the list of single targets
219 template < GUM_Numeric GUM_SCALAR >
221 return _targets_.size();
222 }
223
224 // indicates whether the inference is in a target mode
225 template < GUM_Numeric GUM_SCALAR >
229
231 template < GUM_Numeric GUM_SCALAR >
233 _targets_.clear();
234 if (!this->hasNoModel_()) {
235 _targets_ = this->BN().internalDag().asNodeSet();
237 }
238 }
239
240 // ##############################################################################
241 // Inference
242 // ##############################################################################
243
244 // Compute the posterior of a node.
245 template < GUM_Numeric GUM_SCALAR >
247 if (this->hardEvidenceNodes().contains(node)) { return *(this->evidence()[node]); }
248
249 if (!isTarget(node)) {
250 // throws UndefinedElement if var is not a target
251 GUM_ERROR(UndefinedElement, node << " is not a target node")
252 }
253
254 if (!this->isInferenceDone()) { this->makeInference(); }
255
256 return posterior_(node);
257 }
258
259 // Compute the posterior of a node.
260 template < GUM_Numeric GUM_SCALAR >
261 const Tensor< GUM_SCALAR >&
263 return posterior(this->BN().idFromName(nodeName));
264 }
265
266 /* Entropy
267 * Compute Shanon's entropy of a node given the observation
268 */
269 template < GUM_Numeric GUM_SCALAR >
271 return posterior(X).entropy();
272 }
273
274 /* Entropy
275 * Compute Shanon's entropy of a node given the observation
276 */
277 template < GUM_Numeric GUM_SCALAR >
278 GUM_SCALAR MarginalTargetedInference< GUM_SCALAR >::H(std::string_view nodeName) {
279 return H(this->BN().idFromName(nodeName));
280 }
281
282 template < GUM_Numeric GUM_SCALAR >
284 const NodeSet& evs) {
285 const auto& vtarget = this->BN().variable(target);
286
287 if (evs.contains(target)) {
289 "Target <" << vtarget.name() << "> (" << target << ") can not be in evs (" << evs
290 << ").");
291 }
292 auto condset = this->BN().minimalCondSet(target, evs);
293
294 Tensor< GUM_SCALAR > res;
295 this->eraseAllTargets();
296 this->eraseAllEvidence();
297 res.add(this->BN().variable(target));
298 this->addTarget(target);
299 for (const auto& n: condset) {
300 res.add(this->BN().variable(n));
301 this->addEvidence(n, 0);
302 }
303
304 Instantiation inst(res);
305 for (inst.setFirst(); !inst.end(); inst.incNotVar(vtarget)) {
306 // inferring
307 for (const auto& n: condset)
308 this->chgEvidence(n, inst.val(this->BN().variable(n)));
309 this->makeInference();
310 // populate res
311 const auto& pot = this->posterior(target);
312 for (inst.setFirstVar(vtarget); !inst.end(); inst.incVar(vtarget)) {
313 res.set(inst, pot[inst]);
314 }
315 inst.setFirstVar(vtarget); // remove inst.end() flag
316 }
317
318 return res;
319 }
320
321 template < GUM_Numeric GUM_SCALAR >
323 std::string_view target,
324 const std::vector< std::string >& evs) {
325 const auto& bn = this->BN();
326 return evidenceImpact(bn.idFromName(target), bn.nodeset(evs));
327 }
328
329 template < GUM_Numeric GUM_SCALAR >
333
334 template < GUM_Numeric GUM_SCALAR >
341} /* namespace gum */
void _setBayesNetDuringConstruction_(const IBayesNet< GUM_SCALAR > *bn)
assigns a BN during the inference engine construction
BayesNetInference(const IBayesNet< GUM_SCALAR > *bn)
default constructor
virtual const IBayesNet< GUM_SCALAR > & BN() const final
Returns a constant reference over the IBayesNet referenced by this class.
DAG dag() const
Returns a named copy of the internal DAG: each node id is assigned the name of the corresponding vari...
virtual void chgEvidence(NodeId id, const Idx val) final
change the value of an already existing hard evidence
virtual bool isInferenceDone() const noexcept final
returns whether the inference object is in a InferenceDone state
const NodeProperty< const Tensor< GUM_SCALAR > * > & evidence() const
returns the set of evidence
virtual void setState_(const StateOfInference state) final
set the state of the inference engine and call the notification onStateChanged_ when necessary (i....
const NodeSet & hardEvidenceNodes() const
returns the set of nodes with hard evidence
virtual void eraseAllEvidence() final
removes all the evidence entered into the network
virtual void makeInference() final
perform the heavy computations needed to compute the targets' posteriors
virtual void addEvidence(NodeId id, const Idx val) final
adds a new hard evidence on node id
Virtual base class for probabilistic graphical models.
Class representing the minimal interface for Bayesian network with no numerical data.
Definition IBayesNet.h:75
Class for assigning/browsing values to tuples of discrete variables.
bool end() const
Returns true if the Instantiation reached the end.
void incVar(const DiscreteVariable &v)
Operator increment for variable v only.
void setFirstVar(const DiscreteVariable &v)
Assign the first value in the Instantiation for var v.
void incNotVar(const DiscreteVariable &v)
Operator increment for vars which are not v.
Idx val(Idx i) const
Returns the current value of the variable at position i.
void setFirst()
Assign the first values to the tuple of the Instantiation.
Exception: at least one argument passed to a function is not what was expected.
NodeSet _targets_
the set of marginal targets
void onModelChanged_(const GraphicalModel *bn) override
fired after a new Bayes net has been assigned to the engine
virtual const Tensor< GUM_SCALAR > & posterior(NodeId node)
Computes and returns the posterior of a node.
virtual void eraseTarget(NodeId target) final
removes an existing (marginal) target
virtual void onAllMarginalTargetsErased_()=0
fired before a all marginal targets are removed
void _setAllMarginalTargets_()
sets all the nodes of the Bayes net as targets
virtual const Tensor< GUM_SCALAR > & posterior_(NodeId id)=0
asks derived classes for the posterior of a given variable
virtual bool isTarget(NodeId node) const final
return true if variable is a (marginal) target
virtual void onMarginalTargetErased_(const NodeId id)=0
fired before a marginal target is removed
virtual GUM_SCALAR H(NodeId X) final
Entropy Compute Shanon's entropy of a node given the observation.
virtual void onAllMarginalTargetsAdded_()=0
fired after all the nodes of the BN are added as marginal targets
virtual bool isInTargetMode() const noexcept final
indicates whether the inference is in a target mode
bool _targeted_mode_
whether the actual targets are default
virtual Size nbrTargets() const noexcept final
returns the number of marginal targets
MarginalTargetedInference(const IBayesNet< GUM_SCALAR > *bn)
default constructor
virtual const NodeSet & targets() const noexcept final
returns the list of marginal targets
virtual void addTarget(NodeId target) final
Add a marginal target to the list of targets.
virtual void addAllTargets() final
adds all nodes as targets
virtual void eraseAllTargets()
Clear all previously defined targets.
virtual void onMarginalTargetAdded_(const NodeId id)=0
fired after a new marginal target is inserted
Tensor< GUM_SCALAR > evidenceImpact(NodeId target, const NodeSet &evs)
Create a gum::Tensor for P(target|evs) (for all instantiation of target and evs).
NodeSet asNodeSet() const
returns a copy of the set of nodes represented by the NodeGraphPart
Exception : a pointer or a reference on a nullptr (0) object.
bool contains(const Key &k) const
Indicates whether a given elements belong to the set.
Definition set_tpl.h:468
Exception : a looked-for element could not be found.
#define GUM_ERROR(type, msg)
Definition exceptions.h:76
std::size_t Size
In aGrUM, hashed values are unsigned long int.
Definition types.h:74
Size NodeId
Type for node ids.
Set< NodeId > NodeSet
Some typdefs and define for shortcuts ...
bool contains(std::string_view s, std::string_view needle)
true if needle in s
This file contains the abstract inference class definition for computing (incrementally) marginal pos...
gum is the global namespace for all aGrUM entities
Definition agrum.h:46