aGrUM 2.3.2
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-2025 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-2025 *
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#pragma once
41
42
48#include <iterator>
49
50namespace gum {
51
52
53 // Default Constructor
54 template < typename GUM_SCALAR >
56 const IBayesNet< GUM_SCALAR >* bn) : BayesNetInference< GUM_SCALAR >(bn) {
57 // assign a BN if this has not been done before (due to virtual inheritance)
58 if (this->hasNoModel_()) {
60 }
61
62 // sets all the nodes as targets
63 if (bn != nullptr) {
64 _targeted_mode_ = false;
65 _targets_ = bn->dag().asNodeSet();
66 }
67
68 GUM_CONSTRUCTOR(MarginalTargetedInference);
69 }
70
71 // Destructor
72 template < typename GUM_SCALAR >
76
77 // fired when a new BN is assigned to the inference engine
78 template < typename GUM_SCALAR >
83
84 // ##############################################################################
85 // Targets
86 // ##############################################################################
87
88 // return true if variable is a target
89 template < typename GUM_SCALAR >
91 // check that the variable belongs to the bn
92 if (this->hasNoModel_())
94 "No Bayes net has been assigned to the "
95 "inference algorithm");
96 if (!this->BN().dag().exists(node)) {
97 GUM_ERROR(UndefinedElement, node << " is not a NodeId in the bn")
98 }
99
100 return _targets_.contains(node);
101 }
102
103 // Add a single target to the list of targets
104 template < typename GUM_SCALAR >
105 INLINE bool MarginalTargetedInference< GUM_SCALAR >::isTarget(const std::string& nodeName) const {
106 return isTarget(this->BN().idFromName(nodeName));
107 }
108
109 // Clear all previously defined targets (single targets and sets of targets)
110 template < typename GUM_SCALAR >
119
120 // Add a single target to the list of targets
121 template < typename GUM_SCALAR >
123 // check if the node belongs to the Bayesian network
124 if (this->hasNoModel_())
126 "No Bayes net has been assigned to the "
127 "inference algorithm");
128
129 if (!this->BN().dag().exists(target)) {
130 GUM_ERROR(UndefinedElement, target << " is not a NodeId in the bn")
131 }
132
133 setTargetedMode_(); // does nothing if already in targeted mode
134 // add the new target
135 if (!_targets_.contains(target)) {
136 _targets_.insert(target);
139 }
140 }
141
142 // Add all nodes as targets
143 template < typename GUM_SCALAR >
145 // check if the node belongs to the Bayesian network
146 if (this->hasNoModel_())
148 "No Bayes net has been assigned to the "
149 "inference algorithm");
150
151
152 setTargetedMode_(); // does nothing if already in targeted mode
153 for (const auto target: this->BN().dag()) {
154 if (!_targets_.contains(target)) {
155 _targets_.insert(target);
158 }
159 }
160 }
161
162 // Add a single target to the list of targets
163 template < typename GUM_SCALAR >
164 void MarginalTargetedInference< GUM_SCALAR >::addTarget(const std::string& nodeName) {
165 // check if the node belongs to the Bayesian network
166 if (this->hasNoModel_())
168 "No Bayes net has been assigned to the "
169 "inference algorithm");
170
171 addTarget(this->BN().idFromName(nodeName));
172 }
173
174 // removes an existing target
175 template < typename GUM_SCALAR >
177 // check if the node belongs to the Bayesian network
178 if (this->hasNoModel_())
180 "No Bayes net has been assigned to the "
181 "inference algorithm");
182
183 if (!this->BN().dag().exists(target)) {
184 GUM_ERROR(UndefinedElement, target << " is not a NodeId in the bn")
185 }
186
187
188 if (_targets_.contains(target)) {
189 _targeted_mode_ = true; // we do not use setTargetedMode_ because we do not
190 // want to clear the targets
192 _targets_.erase(target);
194 }
195 }
196
197 // Add a single target to the list of targets
198 template < typename GUM_SCALAR >
200 // check if the node belongs to the Bayesian network
201 if (this->hasNoModel_())
203 "No Bayes net has been assigned to the "
204 "inference algorithm");
205
206 eraseTarget(this->BN().idFromName(nodeName));
207 }
208
209 // returns the list of single targets
210 template < typename GUM_SCALAR >
212 return _targets_;
213 }
214
215 // returns the list of single targets
216 template < typename GUM_SCALAR >
218 return _targets_.size();
219 }
220
221 // indicates whether the inference is in a target mode
222 template < typename GUM_SCALAR >
224 return _targeted_mode_;
225 }
226
228 template < typename GUM_SCALAR >
230 _targets_.clear();
231 if (!this->hasNoModel_()) {
232 _targets_ = this->BN().dag().asNodeSet();
234 }
235 }
236
237 // ##############################################################################
238 // Inference
239 // ##############################################################################
240
241 // Compute the posterior of a node.
242 template < typename GUM_SCALAR >
244 if (this->hardEvidenceNodes().contains(node)) { return *(this->evidence()[node]); }
245
246 if (!isTarget(node)) {
247 // throws UndefinedElement if var is not a target
248 GUM_ERROR(UndefinedElement, node << " is not a target node")
249 }
250
251 if (!this->isInferenceDone()) { this->makeInference(); }
252
253 return posterior_(node);
254 }
255
256 // Compute the posterior of a node.
257 template < typename GUM_SCALAR >
258 const Tensor< GUM_SCALAR >&
260 return posterior(this->BN().idFromName(nodeName));
261 }
262
263 /* Entropy
264 * Compute Shanon's entropy of a node given the observation
265 */
266 template < typename GUM_SCALAR >
268 return posterior(X).entropy();
269 }
270
271 /* Entropy
272 * Compute Shanon's entropy of a node given the observation
273 */
274 template < typename GUM_SCALAR >
275 INLINE GUM_SCALAR MarginalTargetedInference< GUM_SCALAR >::H(const std::string& nodeName) {
276 return H(this->BN().idFromName(nodeName));
277 }
278
279 template < typename GUM_SCALAR >
281 const NodeSet& evs) {
282 const auto& vtarget = this->BN().variable(target);
283
284 if (evs.contains(target)) {
286 "Target <" << vtarget.name() << "> (" << target << ") can not be in evs (" << evs
287 << ").");
288 }
289 auto condset = this->BN().minimalCondSet(target, evs);
290
291 Tensor< GUM_SCALAR > res;
292 this->eraseAllTargets();
293 this->eraseAllEvidence();
294 res.add(this->BN().variable(target));
295 this->addTarget(target);
296 for (const auto& n: condset) {
297 res.add(this->BN().variable(n));
298 this->addEvidence(n, 0);
299 }
300
301 Instantiation inst(res);
302 for (inst.setFirst(); !inst.end(); inst.incNotVar(vtarget)) {
303 // inferring
304 for (const auto& n: condset)
305 this->chgEvidence(n, inst.val(this->BN().variable(n)));
306 this->makeInference();
307 // populate res
308 const auto& pot = this->posterior(target);
309 for (inst.setFirstVar(vtarget); !inst.end(); inst.incVar(vtarget)) {
310 res.set(inst, pot[inst]);
311 }
312 inst.setFirstVar(vtarget); // remove inst.end() flag
313 }
314
315 return res;
316 }
317
318 template < typename GUM_SCALAR >
320 const std::string& target,
321 const std::vector< std::string >& evs) {
322 const auto& bn = this->BN();
323 return evidenceImpact(bn.idFromName(target), bn.nodeset(evs));
324 }
325
326 template < typename GUM_SCALAR >
330
331 template < typename GUM_SCALAR >
333 if (!_targeted_mode_) {
334 _targets_.clear();
335 _targeted_mode_ = true;
336 }
337 }
338} /* 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.
const DAG & dag() const
Returns a constant reference to the dag of this Bayes Net.
virtual void setState_(const StateOfInference state) final
set the state of the inference engine and call the notification onStateChanged_ when necessary (i....
virtual void chgEvidence(NodeId id, const Idx val) final
change the value of an already existing hard evidence
virtual void addEvidence(NodeId id, const Idx val) final
adds a new hard evidence on node id
virtual void eraseAllEvidence() final
removes all the evidence entered into the network
const NodeSet & hardEvidenceNodes() const
returns the set of nodes with hard evidence
const NodeProperty< const Tensor< GUM_SCALAR > * > & evidence() const
returns the set of evidence
virtual void makeInference() final
perform the heavy computations needed to compute the targets' posteriors
virtual bool isInferenceDone() const noexcept final
returns whether the inference object is in a InferenceDone state
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 incNotVar(const DiscreteVariable &v)
Operator increment for vars which are not v.
void setFirstVar(const DiscreteVariable &v)
Assign the first value in the Instantiation for var 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
virtual Size nbrTargets() const noexcept final
returns the number of marginal targets
virtual bool isInTargetMode() const noexcept final
indicates whether the inference is in a target mode
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 void onMarginalTargetErased_(const NodeId id)=0
fired before a marginal target is removed
virtual void eraseAllTargets()
Clear all previously defined targets.
virtual void onAllMarginalTargetsAdded_()=0
fired after all the nodes of the BN are added as marginal targets
virtual GUM_SCALAR H(NodeId X) final
Entropy Compute Shanon's entropy of a node given the observation.
bool _targeted_mode_
whether the actual targets are default
virtual const NodeSet & targets() const noexcept final
returns the list of marginal targets
MarginalTargetedInference(const IBayesNet< GUM_SCALAR > *bn)
default constructor
virtual bool isTarget(NodeId node) const final
return true if variable is a (marginal) target
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 onModelChanged_(const GraphicalModel *bn)
fired after a new Bayes net has been assigned to the engine
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 instanciation 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:497
Exception : a looked-for element could not be found.
#define GUM_ERROR(type, msg)
Definition exceptions.h:72
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 ...
gum is the global namespace for all aGrUM entities
Definition agrum.h:46