aGrUM 2.3.2
a C++ library for (probabilistic) graphical models
structuredBayesBall_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
49
51
52namespace gum {
53 namespace prm {
54
55 template < typename GUM_SCALAR >
57 GUM_DESTRUCTOR(StructuredBayesBall);
58
59 for (const auto& elt: _reqMap_)
60 delete elt.second.first;
61 }
62
63 template < typename GUM_SCALAR >
65 for (const auto& elt: _reqMap_)
66 delete elt.second.first;
67
68 _keyMap_.clear();
69 _reqMap_.clear();
70 }
71
72 template < typename GUM_SCALAR >
74 NodeId n) {
75 try {
76 typename PRMInference< GUM_SCALAR >::Chain chain = std::make_pair(i, &(i->get(n)));
77
78 if (_inf_->hasEvidence(chain)) {
79 const Tensor< GUM_SCALAR >* e = _inf_->evidence(i)[n];
80 Instantiation inst(e);
81 Size count = 0;
82
83 for (inst.setFirst(); !inst.end(); inst.inc()) {
84 if ((e->get(inst) == (GUM_SCALAR)1.0)) ++count;
85 else if (e->get(inst) != (GUM_SCALAR)0.0) return false;
86 }
87
88 return (count == 1);
89 }
90
91 return false;
92 } catch (NotFound const&) { return false; }
93 }
94
95 template < typename GUM_SCALAR >
97 NodeId n) {
98 _clean_();
102 _fromChild_(i, n, marks);
103 _fillMaps_(marks);
104
105 for (const auto& elt: marks)
106 delete elt.second;
107 }
108
109 template < typename GUM_SCALAR >
111 NodeId n,
112 InstanceMap& marks) {
113 if (!marks.exists(i)) { marks.insert(i, new StructuredBayesBall< GUM_SCALAR >::MarkMap()); }
114
115 if (!marks[i]->exists(n)) { marks[i]->insert(n, std::pair< bool, bool >(false, false)); }
116
117 // Sending message to parents
118 switch (i->type().get(n).elt_type()) {
120 if (!_getMark_(marks, i, n).first) {
121 _getMark_(marks, i, n).first = true;
122
123 for (const auto inst: i->getInstances(n))
124 _fromChild_(inst, inst->get(_getSC_(i, n).lastElt().safeName()).id(), marks);
125 }
126
127 if (!_getMark_(marks, i, n).second) {
128 _getMark_(marks, i, n).second = true;
129
130 for (const auto chi: i->type().containerDag().children(n))
131 _fromParent_(i, chi, marks);
132 }
133
134 break;
135 }
136
139 if (!_getMark_(marks, i, n).first) {
140 _getMark_(marks, i, n).first = true;
141
142 if (!_isHardEvidence_(i, n))
143 for (const auto par: i->type().containerDag().parents(n))
144 _fromChild_(i, par, marks);
145 }
146
147 if (!_getMark_(marks, i, n).second) {
148 _getMark_(marks, i, n).second = true;
149
150 // In i.
151 for (const auto chi: i->type().containerDag().children(n))
152 _fromParent_(i, chi, marks);
153
154 // Out of i.
155 try {
156 const auto& refs = i->getRefAttr(n);
157
158 for (auto iter = refs.begin(); iter != refs.end(); ++iter)
159 _fromParent_(iter->first, iter->first->type().get(iter->second).id(), marks);
160 } catch (NotFound const&) {
161 // Not an inverse sc
162 }
163 }
164
165 break;
166 }
167
168 default : {
169 // We shouldn't reach any other PRMClassElement<GUM_DATA> than
170 // PRMAttribute
171 // or
172 // PRMSlotChain<GUM_SCALAR>.
173 GUM_ERROR(FatalError, "This case is impossible.")
174 }
175 }
176 }
177
178 template < typename GUM_SCALAR >
180 NodeId n,
181 InstanceMap& marks) {
182 if (!marks.exists(i)) { marks.insert(i, new StructuredBayesBall< GUM_SCALAR >::MarkMap()); }
183
184 if (!marks[i]->exists(n)) { marks[i]->insert(n, std::pair< bool, bool >(false, false)); }
185
186 // Concerns only PRMAttribute (because of the hard evidence)
187 if ((_isHardEvidence_(i, n)) && (!_getMark_(marks, i, n).first)) {
188 _getMark_(marks, i, n).first = true;
189
190 for (const auto par: i->type().containerDag().parents(n))
191 _fromChild_(i, par, marks);
192 } else if (!_getMark_(marks, i, n).second) {
193 _getMark_(marks, i, n).second = true;
194
195 // In i.
196 for (const auto chi: i->type().containerDag().children(n))
197 _fromParent_(i, chi, marks);
198
199 // Out of i.
200 try {
201 for (auto iter = i->getRefAttr(n).begin(); iter != i->getRefAttr(n).end(); ++iter)
202 _fromParent_(iter->first, iter->first->type().get(iter->second).id(), marks);
203 } catch (NotFound const&) {
204 // Not an inverse sc
205 }
206 }
207 }
208
209 template < typename GUM_SCALAR >
211 // First find for each instance it's requisite nodes
213
214 for (const auto& elt: marks) {
215 Set< NodeId >* req_set = new Set< NodeId >();
216
217 for (const auto& elt2: *elt.second)
218 if (elt2.second.first) req_set->insert(elt2.first);
219
220 req_map.insert(elt.first, req_set);
221 }
222
223 // Remove all instances with 0 requisite nodes
225
226 for (const auto& elt: req_map)
227 if (elt.second->size() == 0) to_remove.insert(elt.first);
228
229 for (const auto remo: to_remove) {
230 delete req_map[remo];
231 req_map.erase(remo);
232 }
233
234 // Fill _reqMap_ and _keyMap_
235 for (const auto& elt: req_map) {
236 std::string key = _buildHashKey_(elt.first, *elt.second);
237
238 if (_reqMap_.exists(key)) {
239 _keyMap_.insert(elt.first,
240 std::pair< std::string, Set< NodeId >* >(key, _reqMap_[key].first));
241 _reqMap_[key].second += 1;
242 delete elt.second;
243 req_map[elt.first] = 0;
244 } else {
245 _reqMap_.insert(key, std::pair< Set< NodeId >*, Size >(elt.second, 1));
246 _keyMap_.insert(elt.first, std::pair< std::string, Set< NodeId >* >(key, elt.second));
247 }
248 }
249 }
250
251 template < typename GUM_SCALAR >
252 std::string
254 Set< NodeId >& req_nodes) {
255 std::stringstream sBuff;
256 sBuff << i->type().name();
257
258 for (const auto node: i->type().containerDag().nodes())
259 if (req_nodes.exists(node)) sBuff << "-" << node;
260
261 return sBuff.str();
262 }
263
264 template < typename GUM_SCALAR >
266 const PRMInference< GUM_SCALAR >& inference) : _inf_(&inference) {
267 GUM_CONSTRUCTOR(StructuredBayesBall);
268 }
269
270 template < typename GUM_SCALAR >
272 const StructuredBayesBall< GUM_SCALAR >& source) : _inf_(0) {
273 GUM_CONS_CPY(StructuredBayesBall);
274 GUM_ERROR(FatalError, "Not allowed.")
275 }
276
277 template < typename GUM_SCALAR >
278 INLINE StructuredBayesBall< GUM_SCALAR >& StructuredBayesBall< GUM_SCALAR >::operator=(
279 const StructuredBayesBall< GUM_SCALAR >& source) {
280 GUM_ERROR(FatalError, "Not allowed.")
281 }
282
283 template < typename GUM_SCALAR >
284 INLINE const std::string&
288
289 template < typename GUM_SCALAR >
290 INLINE const std::string&
292 return _keyMap_[&i].first;
293 }
294
295 template < typename GUM_SCALAR >
297 const PRMInstance< GUM_SCALAR >* i) const {
298 return *(_keyMap_[i].second);
299 }
300
301 template < typename GUM_SCALAR >
303 const PRMInstance< GUM_SCALAR >& i) const {
304 return *(_keyMap_[&i].second);
305 }
306
307 template < typename GUM_SCALAR >
308 INLINE Size StructuredBayesBall< GUM_SCALAR >::occurrence(const std::string& key) const {
309 return _reqMap_[key].second;
310 }
311
312 template < typename GUM_SCALAR >
314 return ((float)_reqMap_.size()) / ((float)_keyMap_.size());
315 }
316
317 template < typename GUM_SCALAR >
318 INLINE bool
322
323 template < typename GUM_SCALAR >
324 INLINE bool
328
329 template < typename GUM_SCALAR >
334
335 template < typename GUM_SCALAR >
340
341 template < typename GUM_SCALAR >
342 INLINE const PRMSlotChain< GUM_SCALAR >&
344 return static_cast< const PRMSlotChain< GUM_SCALAR >& >(i->type().get(n));
345 }
346
347 template < typename GUM_SCALAR >
348 INLINE std::pair< bool, bool >&
351 NodeId n) {
352 return (*(marks[i]))[n];
353 }
354
355 } /* namespace prm */
356} /* namespace gum */
Exception : fatal (unknown ?) error.
The class for generic Hash Tables.
Definition hashTable.h:637
void erase(const Key &key)
Removes a given element from the hash table.
bool exists(const Key &key) const
Checks whether there exists an element with a given key in the hashtable.
value_type & insert(const Key &key, const Val &val)
Adds a new element (actually a copy of this element) into the hash table.
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.
bool exists(const Key &k) const
Indicates whether a given elements belong to the set.
Definition set_tpl.h:533
void insert(const Key &k)
Inserts a new element into the set.
Definition set_tpl.h:539
This abstract class is used as base class for all inference class on PRM<GUM_SCALAR>.
std::pair< const PRMInstance< GUM_SCALAR > *, const PRMAttribute< GUM_SCALAR > * > Chain
Code alias.
An PRMInstance is a Bayesian network fragment defined by a Class and used in a PRMSystem.
Definition PRMInstance.h:79
std::vector< std::pair< PRMInstance< GUM_SCALAR > *, std::string > > & getRefAttr(NodeId id)
Returns a vector of pairs of refering attributes of id.
PRMClass< GUM_SCALAR > & type()
Returns the type of this instance.
const Set< PRMInstance< GUM_SCALAR > * > & getInstances(NodeId id) const
Returns the Set of PRMInstance<GUM_SCALAR> referenced by id.
PRMAttribute< GUM_SCALAR > & get(NodeId id)
Getter on an PRMAttribute<GUM_SCALAR> of this PRMInstance<GUM_SCALAR>.
A PRMSlotChain represents a sequence of gum::prm::PRMClassElement<GUM_SCALAR> where the n-1 first gum...
<agrum/PRM/structuredBayesBall.h>
float liftRatio() const
Returns the ratio between the total number of instances and the number of instances with the same con...
HashTable< const PRMInstance< GUM_SCALAR > *, std::pair< std::string, Set< NodeId > * > > _keyMap_
Associate an PRMInstance<GUM_SCALAR> with a unique key w.r.t. d-separation and the set of requisite n...
const PRMInference< GUM_SCALAR > * _inf_
The PRM at which model belongs.
const Set< NodeId > & requisiteNodes(const PRMInstance< GUM_SCALAR > *i) const
Returns the set of requisite nodes w.r.t. d-separation for i.
const std::string & key(const PRMInstance< GUM_SCALAR > *i) const
Returns a unique key w.r.t. d-separation for i.
void _clean_()
Cleans this before a new computation.
HashTable< NodeId, std::pair< bool, bool > > MarkMap
Code alias.
HashTable< std::string, std::pair< Set< NodeId > *, Size > > _reqMap_
Associate a Key with the set of requisite nodes associated with it. The Size value is the number of i...
StructuredBayesBall & operator=(const StructuredBayesBall &source)
Copy operator.
void compute(const PRMInstance< GUM_SCALAR > *i, NodeId n)
Compute the set or requisite nodes for each required instance given the current set of observations....
StructuredBayesBall(const PRMInference< GUM_SCALAR > &inference)
Default Constructor.
void _fillMaps_(InstanceMap &marks)
Fill keyMap and reqMap.
Size occurrence(const std::string &key) const
Returns the number of occurrence of the given key, which is the number of PRMInstance<GUM_SCALAR> sha...
void _fromParent_(const PRMInstance< GUM_SCALAR > *i, NodeId n, InstanceMap &marks)
When the ball is receive on i->get(n) from a parent.
void _fromChild_(const PRMInstance< GUM_SCALAR > *i, NodeId n, InstanceMap &marks)
When the ball is received on i->get(n) from a child.
bool exists(const PRMInstance< GUM_SCALAR > *i) const
Returns true if i has requisite nodes.
void _compute_(const PRMInstance< GUM_SCALAR > *i, NodeId n)
The real compute method.
std::string _buildHashKey_(const PRMInstance< GUM_SCALAR > *i, Set< NodeId > &req_nodes)
Builds the HashKey for the given instance and requisite nodes set.
HashTable< const PRMInstance< GUM_SCALAR > *, MarkMap * > InstanceMap
const PRMSlotChain< GUM_SCALAR > & _getSC_(const PRMInstance< GUM_SCALAR > *i, NodeId n)
Code alias.
std::pair< bool, bool > & _getMark_(InstanceMap &marks, const PRMInstance< GUM_SCALAR > *i, NodeId n)
Code alias.
bool _isHardEvidence_(const PRMInstance< GUM_SCALAR > *i, NodeId n)
Returns true if there is a hard evidence on i->get(n).
#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.
namespace for all probabilistic relational models entities
Definition agrum.h:68
gum is the global namespace for all aGrUM entities
Definition agrum.h:46
Headers of StructuredBayesBall.