aGrUM 2.3.2
a C++ library for (probabilistic) graphical models
multiDimBucket_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
50
52
53namespace gum {
54
55 template < typename GUM_SCALAR >
57 MultiDimReadOnly< GUM_SCALAR >(), _bufferSize_(bufferSize), _bucket_(0), _changed_(false),
58 _name_("MultiDimBucket") {
59 GUM_CONSTRUCTOR(MultiDimBucket);
60 }
61
62 template < typename GUM_SCALAR >
64 MultiDimReadOnly< GUM_SCALAR >(source), _bufferSize_(source._bufferSize_), _bucket_(0),
66 _allVarsInst_(source._allVarsInst_), _changed_(source._changed_), _name_("MultiDimBucket") {
67 GUM_CONS_CPY(MultiDimBucket);
68 }
69
70 template < typename GUM_SCALAR >
72 GUM_DESTRUCTOR(MultiDimBucket);
74
75 for (BiIter iter = _instantiations_.beginSafe(); iter != _instantiations_.endSafe(); ++iter) {
76 delete iter.second();
77 }
78
79 if (_bucket_) { delete _bucket_; }
80
82 = _multiDims_.beginSafe();
83 iter != _multiDims_.endSafe();
84 ++iter) {
85 delete iter.val();
86 }
87 }
88
89 template < typename GUM_SCALAR >
91 this->add(&impl);
92 }
93
94 template < typename GUM_SCALAR >
96 _multiDims_.insert(impl, new Instantiation(*impl));
97
99 for (const auto var: impl->variablesSequence()) {
100 _addVariable_(var);
101 }
102 }
103
104 _changed_ = true;
105 }
106
107 template < typename GUM_SCALAR >
109 this->erase(&impl);
110 }
111
112 template < typename GUM_SCALAR >
114 try {
115 delete _multiDims_[impl];
116 _multiDims_.erase(impl);
117
119 for (auto var: impl->variablesSequence()) {
120 _eraseVariable_(var);
121 }
122 }
123
124 _changed_ = true;
125 } catch (NotFound const&) {
126 // Do nothing
127 }
128 }
129
130 template < typename GUM_SCALAR >
131 INLINE bool
133 return _multiDims_.exists(&impl);
134 }
135
136 template < typename GUM_SCALAR >
140
141 template < typename GUM_SCALAR >
143 return _multiDims_.size();
144 }
145
146 template < typename GUM_SCALAR >
148 return _multiDims_.empty();
149 }
150
151 template < typename GUM_SCALAR >
153 return _changed_;
154 }
155
156 template < typename GUM_SCALAR >
160
161 template < typename GUM_SCALAR >
163 _bufferSize_ = ammount;
164
165 if ((this->domainSize() > _bufferSize_) && (_bucket_ != 0)) {
167 } else if (_bucket_ == 0) {
169 }
170 }
171
172 template < typename GUM_SCALAR >
174 if ((_bucket_) && (_changed_ || force)) {
175 Instantiation values(*_bucket_);
176
177 for (values.setFirst(); !values.end(); values.inc()) {
178 _bucket_->set(values, _computeValue_(values));
179 }
180 } else if ((_bucket_ == 0) && _changed_) {
181 _slavesValue_.clear();
182 _changed_ = false;
183 }
184
185 _changed_ = false;
186 }
187
188 template < typename GUM_SCALAR >
189 const std::string& MultiDimBucket< GUM_SCALAR >::name() const {
190 return _name_;
191 }
192
193 template < typename GUM_SCALAR >
196
198 if (this->domainSize() <= _bufferSize_) {
199 if (_bucket_) _bucket_->add(v);
200 else _initializeBuffer_();
201 } else if (_bucket_) {
203 }
204 }
205 }
206
207 template < typename GUM_SCALAR >
210
212 && (this->domainSize() <= _bufferSize_)) {
213 if (_bucket_) {
214 _bucket_->erase(v);
215 } else {
217 }
218 }
219 }
220
221 template < typename GUM_SCALAR >
223 return (_bucket_) ? _bucket_->realSize() : (Size)0;
224 }
225
226 template < typename GUM_SCALAR >
230
231 template < typename GUM_SCALAR >
232 INLINE GUM_SCALAR MultiDimBucket< GUM_SCALAR >::get(const Instantiation& i) const {
233 compute();
234
235 if (_bucket_) {
236 try {
237 return _bucket_->get(*(_instantiations_.second(const_cast< Instantiation* >(&i))));
238 } catch (NotFound const&) { return _bucket_->get(i); }
239 } else if (i.isMaster(this)) {
240 if (!_slavesValue_.exists(&i)) { _slavesValue_.insert(&i, _computeValue_(i)); }
241
242 return _slavesValue_[&i];
243 } else {
244 return _computeValue_(i);
245 }
246 }
247
248 template < typename GUM_SCALAR >
250 const DiscreteVariable* const var,
251 Idx oldval,
252 Idx newval) {
253 if (_bucket_) {
254 try {
255 _bucket_->changeNotification(*(_instantiations_).second(const_cast< Instantiation* >(&i)),
256 var,
257 oldval,
258 newval);
259 } catch (NotFound const&) {
260 // Then i is not a slave of this
261 }
262 } else {
263 _slavesValue_.erase(&i);
264 }
265 }
266
267 template < typename GUM_SCALAR >
269 if (_bucket_) {
270 try {
271 _bucket_->setFirstNotification(
272 *(_instantiations_).second(const_cast< Instantiation* >(&i)));
273 } catch (NotFound const&) {
274 // Then i is not a slave of this
275 }
276 } else {
277 _slavesValue_.erase(&i);
278 }
279 }
280
281 template < typename GUM_SCALAR >
283 if (_bucket_) {
284 try {
285 _bucket_->setLastNotification(*(_instantiations_).second(const_cast< Instantiation* >(&i)));
286 } catch (NotFound const&) {
287 // Then i is not a slave of this
288 }
289 } else {
290 _slavesValue_.erase(&i);
291 }
292 }
293
294 template < typename GUM_SCALAR >
296 if (_bucket_) {
297 try {
298 _bucket_->setIncNotification(*(_instantiations_.second(const_cast< Instantiation* >(&i))));
299 } catch (NotFound const&) {
300 // Then i is not a slave of this
301 }
302 } else {
303 _slavesValue_.erase(&i);
304 }
305 }
306
307 template < typename GUM_SCALAR >
309 if (_bucket_) {
310 try {
311 _bucket_->setDecNotification(*(_instantiations_.second(const_cast< Instantiation* >(&i))));
312 } catch (NotFound const&) {
313 // Then i is not a slave of this
314 }
315 } else {
316 _slavesValue_.erase(&i);
317 }
318 }
319
320 template < typename GUM_SCALAR >
322 if (_bucket_) {
323 try {
324 _bucket_->setChangeNotification(
325 *(_instantiations_.second(const_cast< Instantiation* >(&i))));
326 } catch (NotFound const&) {
327 // Then i is not a slave of this
328 }
329 } else {
330 _slavesValue_.erase(&i);
331 }
332 }
333
334 template < typename GUM_SCALAR >
336 if (_bucket_) {
337 try {
338 _instantiations_.insert(&i, new Instantiation(*_bucket_));
339 } catch (DuplicateElement const&) { return false; }
340 }
341
343 }
344
345 template < typename GUM_SCALAR >
348
349 if (_bucket_) {
350 try {
351 delete _instantiations_.second(&i);
352 _instantiations_.eraseFirst(&i);
353 return true;
354 } catch (NotFound const&) { return false; }
355 } else {
356 if (_slavesValue_.exists(&i)) {
357 _slavesValue_.erase(&i);
358 return true;
359 } else {
360 return false;
361 }
362 }
363 }
364
365 template < typename GUM_SCALAR >
367 if (_bucket_) {
368 return *_bucket_;
369 } else {
370 return *this;
371 }
372 }
373
374 template < typename GUM_SCALAR >
376 if (_bucket_) {
377 return *_bucket_;
378 } else {
379 return *this;
380 }
381 }
382
383 template < typename GUM_SCALAR >
384 INLINE std::string MultiDimBucket< GUM_SCALAR >::toString(const Instantiation* i) const {
385 std::stringstream sBuff;
386 sBuff << (*i) << " = " << get(*i);
387 return sBuff.str();
388 }
389
390 template < typename GUM_SCALAR >
393
394 if (this->domainSize() <= _bufferSize_) {
396 } else {
398 }
399
400 _allVariables_.clear();
401
402 while (!_allVarsInst_.empty()) {
403 _allVarsInst_.erase(**(_allVarsInst_.variablesSequence().beginSafe()));
404 }
405
406 for ( // HashTableIteratorSafe<const MultiDimContainer<GUM_SCALAR>*,
407 // Instantiation*>
408 auto iter = _multiDims_.beginSafe(); iter != _multiDims_.endSafe(); ++iter) {
409 for (auto var: iter.key()->variablesSequence()) {
410 _addVariable_(var);
411 }
412 }
413
414 _changed_ = true;
415 }
416
417 template < typename GUM_SCALAR >
418 INLINE GUM_SCALAR& MultiDimBucket< GUM_SCALAR >::get_(const Instantiation& i) const {
419 GUM_ERROR(OperationNotAllowed, "a MultiDimBucket is a read only MultiDim")
420 }
421
422 template < typename GUM_SCALAR >
424 try {
425 _allVariables_.insert(var);
426 _allVarsInst_.add(*var);
427 } catch (DuplicateElement const&) {
428 // Nothing to do then!
429 }
430 }
431
432 template < typename GUM_SCALAR >
434 bool found = false;
435
437 = _multiDims_.beginSafe();
438 iter != _multiDims_.endSafe();
439 ++iter) {
440 if (iter.key()->contains(*var)) {
441 found = true;
442 break;
443 }
444 }
445
446 // No one use it, we can safely remove it
447 if (!found) {
448 _allVariables_.erase(var);
449 _allVarsInst_.erase(*var);
450 }
451 }
452
453 template < typename GUM_SCALAR >
455 if (_bucket_) {
456 for (auto iter = _instantiations_.beginSafe(); iter != _instantiations_.endSafe(); ++iter) {
457 delete iter.second();
458 }
459
460 _instantiations_.clear();
461 delete _bucket_;
462 _bucket_ = 0;
463 }
464
465 // Creating the table.
467
468 for (auto var: this->variablesSequence()) {
469 _bucket_->add(*var);
470 }
471
472 if (!this->slaves_().empty()) {
473 for (List< Instantiation* >::const_iterator_safe iter = this->slaves_().cbeginSafe();
474 iter != this->slaves_().cendSafe();
475 ++iter) {
476 _instantiations_.insert(*iter, new Instantiation(*_bucket_));
477 }
478 }
479
480 _changed_ = true;
481 }
482
483 template < typename GUM_SCALAR >
485 if (_bucket_) {
486 for (auto iter = _instantiations_.beginSafe(); iter != _instantiations_.endSafe(); ++iter) {
487 delete iter.second();
488 }
489
490 _instantiations_.clear();
491 delete _bucket_;
492 _bucket_ = 0;
493 }
494 }
495
496 template < typename GUM_SCALAR >
498 try {
499 GUM_SCALAR sum = (GUM_SCALAR)0;
500 GUM_SCALAR current;
501 _allVarsInst_.setVals(value);
502
503 for (_allVarsInst_.setFirstOut(value); !_allVarsInst_.end(); _allVarsInst_.incOut(value)) {
504 current = (GUM_SCALAR)1;
505
507 = _multiDims_.beginSafe();
508 iter != _multiDims_.endSafe();
509 ++iter) {
510 (iter.val())->setVals(_allVarsInst_);
511 current *= iter.key()->get(*(iter.val()));
512 }
513
514 sum += current;
515 }
516
517 return sum;
518 } catch (NotFound& e) {
519 std::cerr << std::endl << e.errorContent() << std::endl;
520 // This happens if the bucket is empty.
521 GUM_ERROR(SizeError, "This MultiDimBucket is empty.")
522 }
523 }
524
525 template < typename GUM_SCALAR >
529
530 template < typename GUM_SCALAR >
532 if (_bucket_) {
533 return *_bucket_;
534 } else {
535 GUM_ERROR(OperationNotAllowed, "bucket not used.")
536 }
537 }
538
539 template < typename GUM_SCALAR >
541 const DiscreteVariable* y) {
543 for (auto iter = _instantiations_.beginSafe(); iter != _instantiations_.endSafe(); ++iter) {
544 iter.first()->replace(*x, *y);
545 iter.second()->replace(*x, *y);
546 }
547
548 if (_bucket_) _bucket_->replace(*x, *y);
549
550 _allVariables_.erase(x);
551 _allVariables_.insert(y);
552 _allVarsInst_.replace(*x, *y);
553 }
554
555 template < typename GUM_SCALAR >
560
561} /* namespace gum */
Safe Iterators for hashtables.
BijectionIteratorSafe< T1, T2 > iterator_safe
types for STL compliance
Definition bijection.h:1612
Base class for discrete random variable.
Exception : a similar element already exists.
GUM_NODISCARD std::string errorContent() const
Returns the message content.
Definition exceptions.h:144
The class for generic Hash Tables.
Definition hashTable.h:637
Class for assigning/browsing values to tuples of discrete variables.
bool end() const
Returns true if the Instantiation reached the end.
bool isMaster(const MultiDimAdressable *m) const
Indicates whether m is the master of this instantiation.
void inc()
Operator increment.
void setFirst()
Assign the first values to the tuple of the Instantiation.
ListConstIteratorSafe< Val > const_iterator_safe
Types for STL compliance.
Definition list.h:393
Abstract base class for all multi dimensionnal addressable.
virtual bool unregisterSlave(Instantiation &i)=0
Unregister i as a slave of this MultiDimAdressable.
Multidimensional matrix stored as an array in memory.
HashTable< const Instantiation *, GUM_SCALAR > _slavesValue_
This table is used to keep the last value computed for an instantiation when the value are computed o...
bool bucketChanged() const
Returns true if the bucket need re-computation since the last computation.
bool isBucketEmpty() const
Returns true if this bucket is empty.
virtual void setChangeNotification(const Instantiation &i) override
Listen to an assignment of a value in a Instantiation.
virtual GUM_SCALAR get(const Instantiation &i) const override
Returns the value pointed by i.
Size bucketSize() const
Returns the number of MultiDimContainer in in this bukcet.
virtual void setDecNotification(const Instantiation &i) override
Listen to increment in each recorded Instantiation.
Instantiation _allVarsInst_
Instantiation over all variable in this.
MultiDimArray< GUM_SCALAR > * _bucket_
The result table of this bucket.
virtual Size realSize() const override
Returns the real number of parameters used for this table.
virtual MultiDimContainer< GUM_SCALAR > * newFactory() const override
Default constructor.
virtual bool unregisterSlave(Instantiation &i) override
Unregister i as a slave of this MultiDimAdressable.
virtual void commitMultipleChanges_() override
Synchronize content after MultipleChanges.
const gum::VariableSet & allVariables() const
Returns the sequence of all the variables contained in the bucket.
void _initializeBuffer_()
Initialize the internal buffer.
Size _bufferSize_
The number of element allowed in bucket.
const MultiDimArray< GUM_SCALAR > & bucket() const
Returns the MultiDimArray used by this MultiDimBucket.
void setBufferSize(Size amount)
Changes the amount of memory allowed for this bucket.
Bijection< Instantiation *, Instantiation * > _instantiations_
Bijection between instantiations registered on this and their equivalent on bucket.
void _eraseVariable_(const DiscreteVariable *var)
Erase a variable from allVariables if no other multidimensional table uses it in this bucket.
GUM_SCALAR _computeValue_(const Instantiation &value) const
Compute the value of the final table of this bucket given i.
virtual MultiDimAdressable & getMasterRef() override
In order to insure the dereference for decorators, we need to virtualize the access to master pointer...
bool contains(const MultiDimContainer< GUM_SCALAR > &impl) const
Returns true if the MultiDimContainer is in this bucket.
void _eraseBuffer_()
Clean the buffer and switch it's instantiation to this bucket.
virtual ~MultiDimBucket()
Destructor.
bool _changed_
Flag used to know if changes has occurred in the bucket since last computation.
virtual bool registerSlave(Instantiation &i) override
Register i as a slave of this MultiDimAdressable.
void erase(const MultiDimContainer< GUM_SCALAR > &impl)
Remove a MultiDimContainer from this bucket.
const HashTable< const MultiDimContainer< GUM_SCALAR > *, Instantiation * > & multidims() const
Returns the MultiDimContainer and their respective Instantiation.
void add(const MultiDimContainer< GUM_SCALAR > &impl)
Add a MultiDimContainer in the bucket.
virtual void setLastNotification(const Instantiation &i) override
Listen to setLast in a given Instantiation.
const std::string & name() const override
Returns the real name of the multiDim implementation.
virtual void setFirstNotification(const Instantiation &i) override
Listen to setFirst in a given Instantiation.
std::string _name_
The class name.
virtual void replace_(const DiscreteVariable *x, const DiscreteVariable *y) override
Replace variable x by y.
Size bufferSize() const
Returns the amount of memory allowed for this bucket.
HashTable< const MultiDimContainer< GUM_SCALAR > *, Instantiation * > _multiDims_
The set of MultiDimContainer in this bucket.
void _addVariable_(const DiscreteVariable *var)
Add a variable to allVariables, and do nothing if var is already in the set.
void compute(bool force=false) const
This method computes the final table of this bucket.
virtual void changeNotification(const Instantiation &i, const DiscreteVariable *const var, Idx oldval, Idx newval) override
Listen to changes in a given Instantiation.
MultiDimBucket(Size bufferSize=INT_MAX)
Default constructor.
virtual void setIncNotification(const Instantiation &i) override
Listen to increment in a given Instantiation.
virtual GUM_SCALAR & get_(const Instantiation &i) const override
gum::VariableSet _allVariables_
The set of all variables of the multidims in this bucket.
Abstract base class for all multi dimensionnal containers.
virtual std::string toString() const
Returns a representation of this MultiDimContainer.
virtual bool empty() const override
Returns true if no var is in *this.
virtual void add(const DiscreteVariable &v) override
Adds a new var to the variables of the multidimensional matrix.
virtual void commitMultipleChanges_()
Synchronize content after MultipleChanges.
const List< Instantiation * > & slaves_() const
Returns a constant reference over the list of slaved instantiations.
virtual Size domainSize() const override
Returns the product of the variables domain size.
virtual void replace_(const DiscreteVariable *x, const DiscreteVariable *y) override
Replace variable x by y.
virtual const Sequence< const DiscreteVariable * > & variablesSequence() const override
Returns a const ref to the sequence of DiscreteVariable*.
virtual void erase(const DiscreteVariable &v) override
Removes a var from the variables of the multidimensional matrix.
virtual bool contains(const DiscreteVariable &v) const override
Returns true if var is in *this.
virtual bool registerSlave(Instantiation &slave) override
Register i as a slave of this MultiDimAdressable.
bool isInMultipleChangeMethod_() const
Get the actual change method of this MultiDimImplementation.
virtual const Sequence< const DiscreteVariable * > & variablesSequence() const =0
Returns a const ref to the sequence of DiscreteVariable*.
MultiDimReadOnly()
Default constructor.
Exception : the element we looked for cannot be found.
Exception : operation not allowed.
Exception : problem with size.
#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 Idx
Type for indexes.
Definition types.h:79
Headers of the MultiDimBucket class.
gum is the global namespace for all aGrUM entities
Definition agrum.h:46
Set< const DiscreteVariable * > VariableSet