aGrUM 3.1.1
a C++ library for (probabilistic) graphical models
PRMInference_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
52
53namespace gum {
54 namespace prm {
55
56 template < GUM_Numeric GUM_SCALAR >
58 for (const auto& elt: _evidences_) {
59 for (const auto& elt2: *elt.second)
60 delete elt2.second;
61
62 delete elt.second;
63 }
64
65 _evidences_.clear();
66 }
67
68 template < GUM_Numeric GUM_SCALAR >
70 prm_(source.prm_), sys_(source.sys_) {
71 GUM_CONS_CPY(PRMInference);
72
73 for (const auto& elt: source._evidences_) {
74 _evidences_.insert(elt.first, new PRMInference< GUM_SCALAR >::EMap());
75
76 for (const auto& elt2: *elt.second) {
77 Tensor< GUM_SCALAR >* e = new Tensor< GUM_SCALAR >();
78 e->add(*(elt2.second->variablesSequence().front()));
79 Instantiation i(*e);
80
81 for (i.setFirst(); !i.end(); i.inc())
82 e->set(i, elt2.second->get(i));
83
84 _evidences_[elt.first]->insert(elt2.first, e);
85 }
86 }
87 }
88
89 template < GUM_Numeric GUM_SCALAR >
93 prm_ = source.prm_;
94 sys_ = source.sys_;
96 for (const auto& elt: source._evidences_) {
97 _evidences_.insert(elt.first, new PRMInference< GUM_SCALAR >::EMap());
99 for (const auto& elt2: *elt.second) {
100 Tensor< GUM_SCALAR >* e = new Tensor< GUM_SCALAR >();
101 e->add(*(elt2.second->variablesSequence().front()));
102 Instantiation i(*e);
103
104 for (i.setFirst(); !i.end(); i.inc()) {
105 e->set(i, elt2.second->get(i));
106 }
107
108 _evidences_[elt.first]->insert(elt2.first, e);
109 }
110 }
111
112 return *this;
113 }
114
115 template < GUM_Numeric GUM_SCALAR >
118 if (auto p = _evidences_.tryGet(i)) {
119 return **p;
120 } else {
121 auto* emap = new PRMInference< GUM_SCALAR >::EMap();
122 _evidences_.insert(i, emap);
123 return *emap;
124 }
125 }
126
127 template < GUM_Numeric GUM_SCALAR >
129 const Tensor< GUM_SCALAR >& p) {
130 if (chain.first->exists(chain.second->id())) {
131 if ((p.nbrDim() != 1) || (!p.contains(chain.second->type().variable())))
132 GUM_ERROR(OperationNotAllowed, "illegal evidence for the given PRMAttribute.")
133
134 Tensor< GUM_SCALAR >* e = new Tensor< GUM_SCALAR >();
135 e->add(chain.second->type().variable());
136 Instantiation i(*e);
137
138 for (i.setFirst(); !i.end(); i.inc())
139 e->set(i, p.get(i));
141 PRMInference< GUM_SCALAR >::EMap& emap = _EMap_(chain.first);
142
143 if (emap.exists(chain.second->id())) {
144 delete emap[chain.second->id()];
145 emap[chain.second->id()] = e;
146 } else {
147 emap.insert(chain.second->id(), e);
148 }
149
151 } else {
153 "the given PRMAttribute does not belong to this "
154 "Instance<GUM_SCALAR>.");
155 }
156 }
157
158 template < GUM_Numeric GUM_SCALAR >
160 const PRMSystem< GUM_SCALAR >& system) :
161 prm_(&prm), sys_(&system) {
162 GUM_CONSTRUCTOR(PRMInference);
163 }
164
165 template < GUM_Numeric GUM_SCALAR >
170
171 template < GUM_Numeric GUM_SCALAR >
174 if (!_evidences_.exists(&i)) GUM_ERROR(NotFound, "this instance has no evidence.")
175 return *(_evidences_[&i]);
176 }
177
178 template < GUM_Numeric GUM_SCALAR >
181 if (!_evidences_.exists(&i)) GUM_ERROR(NotFound, "this instance has no evidence.")
182 return *(_evidences_[&i]);
183 }
184
185 template < GUM_Numeric GUM_SCALAR >
186 typename PRMInference< GUM_SCALAR >::EMap&
187 PRMInference< GUM_SCALAR >::evidence(const PRMInstance< GUM_SCALAR >* i) {
188 if (!_evidences_.exists(i)) GUM_ERROR(NotFound, "this instance has no evidence.")
189 return *(_evidences_[i]);
190 }
191
192 template < GUM_Numeric GUM_SCALAR >
195 if (!_evidences_.exists(i)) GUM_ERROR(NotFound, "this instance has no evidence.")
196 return *(_evidences_[i]);
197 }
198
199 template < GUM_Numeric GUM_SCALAR >
201 return _evidences_.exists(&i);
202 }
203
204 template < GUM_Numeric GUM_SCALAR >
206 return _evidences_.exists(i);
207 }
208
209 template < GUM_Numeric GUM_SCALAR >
211 return (hasEvidence(chain.first)) ? evidence(chain.first).exists(chain.second->id()) : false;
212 }
213
214 template < GUM_Numeric GUM_SCALAR >
216 return (_evidences_.size() != (Size)0);
217 }
218
219 template < GUM_Numeric GUM_SCALAR >
221 if (hasEvidence(chain.first)) {
222 if (_EMap_(chain.first).exists(chain.second->id())) {
223 evidenceRemoved_(chain);
224 delete _EMap_(chain.first)[chain.second->id()];
225 _EMap_(chain.first).erase(chain.second->id());
226 }
227 }
228 }
229
230 template < GUM_Numeric GUM_SCALAR >
232 const typename PRMInference< GUM_SCALAR >::Chain& chain,
233 Tensor< GUM_SCALAR >& m) {
234 if (m.nbrDim() > 0) { GUM_ERROR(OperationNotAllowed, "the given Tensor is not empty.") }
235
236 if (hasEvidence(chain)) {
237 m.add(chain.second->type().variable());
238 const Tensor< GUM_SCALAR >& e = *(evidence(chain.first)[chain.second->id()]);
239 Instantiation i(m), j(e);
240
241 for (i.setFirst(), j.setFirst(); !i.end(); i.inc(), j.inc())
242 m.set(i, e.get(j));
243 } else {
244 if (chain.second != &(chain.first->get(chain.second->safeName()))) {
245 typename PRMInference< GUM_SCALAR >::Chain good_chain
246 = std::make_pair(chain.first, &(chain.first->get(chain.second->safeName())));
247 m.add(good_chain.second->type().variable());
248 posterior_(good_chain, m);
249 } else {
250 m.add(chain.second->type().variable());
251 posterior_(chain, m);
252 }
253 }
254 }
255
256 template < GUM_Numeric GUM_SCALAR >
258 const std::vector< typename PRMInference< GUM_SCALAR >::Chain >& chains,
259 Tensor< GUM_SCALAR >& j) {
260 if (j.nbrDim() > 0) { GUM_ERROR(OperationNotAllowed, "the given Tensor is not empty.") }
261
262 for (auto chain = chains.begin(); chain != chains.end(); ++chain) {
263 j.add(chain->second->type().variable());
264 }
265
266 joint_(chains, j);
267 }
268
269 } /* namespace prm */
270} /* namespace gum */
Headers of PRMInference.
value_type & insert(const Key &key, const Val &val)
Adds a new element (actually a copy of this element) into the hash table.
bool exists(const Key &key) const
Checks whether there exists an element with a given key in the hashtable.
Class for assigning/browsing values to tuples of discrete variables.
bool end() const
Returns true if the Instantiation reached the end.
void inc()
Operator increment.
void setFirst()
Assign the first values to the tuple of the Instantiation.
Exception : the element we looked for cannot be found.
Exception : operation not allowed.
std::pair< const PRMInstance< GUM_SCALAR > *, const PRMAttribute< GUM_SCALAR > * > Chain
Code alias.
void addEvidence(const Chain &chain, const Tensor< GUM_SCALAR > &p)
Add an evidence to the given instance's elt.
PRMInference(const PRM< GUM_SCALAR > &prm, const PRMSystem< GUM_SCALAR > &system)
Default constructor.
virtual void joint_(const std::vector< Chain > &queries, Tensor< GUM_SCALAR > &j)=0
Generic method to compute the posterior of given element.
bool hasEvidence() const
Returns true if i has evidence on PRMAttribute<GUM_SCALAR> a.
HashTable< const PRMInstance< GUM_SCALAR > *, EMap * > _evidences_
Mapping of evidence over PRMInstance<GUM_SCALAR>'s nodes.
EMap & _EMap_(const PRMInstance< GUM_SCALAR > *i)
Private getter over evidences, if necessary creates an EMap for i.
EMap & evidence(const PRMInstance< GUM_SCALAR > &i)
Returns EMap of evidences over i.
void posterior(const Chain &chain, Tensor< GUM_SCALAR > &m)
Compute the posterior of the formal attribute pointed by chain and stores it in m.
PRMSystem< GUM_SCALAR > const * sys_
The Model on which inference is done.
PRMInference & operator=(const PRMInference &source)
Copy operator.
NodeProperty< const Tensor< GUM_SCALAR > * > EMap
Code alias.
PRM< GUM_SCALAR > const * prm_
The PRM<GUM_SCALAR> on which inference is done.
bool hasEvidence(const PRMInstance< GUM_SCALAR > &i) const
Returns true if i has evidence.
virtual void evidenceAdded_(const Chain &chain)=0
virtual ~PRMInference()
Destructor.
virtual void posterior_(const Chain &chain, Tensor< GUM_SCALAR > &m)=0
void joint(const std::vector< Chain > &chains, Tensor< GUM_SCALAR > &j)
Compute the joint probability of the formals attributes pointed by chains and stores it in m.
virtual void evidenceRemoved_(const Chain &chain)=0
This method is called whenever an evidence is removed, but BEFORE any processing made by PRMInference...
void removeEvidence(const Chain &chain)
Remove evidence on the given instance's elt.
void clearEvidence()
Remove all evidences.
An PRMInstance is a Bayesian network fragment defined by a Class and used in a PRMSystem.
Definition PRMInstance.h:79
const iterator & end()
Returns a reference over the iterator at the end of the list of gum::prm::PRMAttribute<GUM_SCALAR> in...
A PRMSystem is a container of PRMInstance and describe a relational skeleton.
Definition PRMSystem.h:72
This class represents a Probabilistic Relational PRMSystem<GUM_SCALAR>.
Definition PRM.h:74
Complete concept for GUM_SCALAR template parameter.
Definition concepts.h:148
#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
namespace for all probabilistic relational models entities
Definition agrum.h:68
gum is the global namespace for all aGrUM entities
Definition agrum.h:46