aGrUM 3.1.1
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-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
51
53
54namespace gum {
55
56 template < typename GUM_SCALAR >
58 MultiDimReadOnly< GUM_SCALAR >(), _bufferSize_(bufferSize), _bucket_(0), _changed_(false),
59 _name_("MultiDimBucket") {
60 GUM_CONSTRUCTOR(MultiDimBucket);
61 }
62
63 template < typename GUM_SCALAR >
65 MultiDimReadOnly< GUM_SCALAR >(source), _bufferSize_(source._bufferSize_), _bucket_(0),
66 _multiDims_(source._multiDims_), _allVariables_(source._allVariables_),
67 _allVarsInst_(source._allVarsInst_), _changed_(source._changed_), _name_("MultiDimBucket") {
68 GUM_CONS_CPY(MultiDimBucket);
69 }
70
71 template < typename GUM_SCALAR >
73 GUM_DESTRUCTOR(MultiDimBucket);
75
76 for (BiIter iter = _instantiations_.beginSafe(); iter != _instantiations_.endSafe(); ++iter) {
77 delete iter.second();
78 }
79
80 if (_bucket_) { delete _bucket_; }
81
83 = _multiDims_.beginSafe();
84 iter != _multiDims_.endSafe();
85 ++iter) {
86 delete iter.val();
87 }
88 }
89
90 template < typename GUM_SCALAR >
92 this->add(&impl);
93 }
94
95 template < typename GUM_SCALAR >
96 void MultiDimBucket< GUM_SCALAR >::add(const MultiDimContainer< GUM_SCALAR >* impl) {
97 _multiDims_.insert(impl, new Instantiation(*impl));
98
99 if (!MultiDimImplementation< GUM_SCALAR >::isInMultipleChangeMethod_()) {
100 for (const auto var: impl->variablesSequence()) {
101 _addVariable_(var);
102 }
103 }
104
105 _changed_ = true;
106 }
107
108 template < typename GUM_SCALAR >
110 this->erase(&impl);
111 }
112
113 template < typename GUM_SCALAR >
115 if (auto p = _multiDims_.tryGet(impl)) {
116 delete *p;
117 _multiDims_.erase(impl);
118
120 for (auto var: impl->variablesSequence()) {
121 _eraseVariable_(var);
122 }
123 }
124
125 _changed_ = true;
126 }
127 }
128
129 template < typename GUM_SCALAR >
131 return _multiDims_.exists(&impl);
132 }
133
134 template < typename GUM_SCALAR >
138
139 template < typename GUM_SCALAR >
143
144 template < typename GUM_SCALAR >
146 return _multiDims_.empty();
147 }
148
149 template < typename GUM_SCALAR >
153
154 template < typename GUM_SCALAR >
158
159 template < typename GUM_SCALAR >
161 _bufferSize_ = ammount;
162
163 if ((this->domainSize() > _bufferSize_) && (_bucket_ != 0)) {
165 } else if (_bucket_ == 0) {
167 }
168 }
169
170 template < typename GUM_SCALAR >
172 if ((_bucket_) && (_changed_ || force)) {
173 Instantiation values(*_bucket_);
174
175 for (values.setFirst(); !values.end(); values.inc()) {
176 _bucket_->set(values, _computeValue_(values));
177 }
178 } else if ((_bucket_ == 0) && _changed_) {
179 _slavesValue_.clear();
180 _changed_ = false;
181 }
182
183 _changed_ = false;
184 }
185
186 template < typename GUM_SCALAR >
187 const std::string& MultiDimBucket< GUM_SCALAR >::name() const {
188 return _name_;
189 }
190
191 template < typename GUM_SCALAR >
204
205 template < typename GUM_SCALAR >
218
219 template < typename GUM_SCALAR >
221 return (_bucket_) ? _bucket_->realSize() : (Size)0;
222 }
223
224 template < typename GUM_SCALAR >
228
229 template < typename GUM_SCALAR >
231 compute();
232
233 if (_bucket_) {
234 if (_instantiations_.existsFirst(const_cast< Instantiation* >(&i))) {
235 return _bucket_->get(*(_instantiations_.second(const_cast< Instantiation* >(&i))));
236 } else {
237 return _bucket_->get(i);
238 }
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 if (_instantiations_.existsFirst(const_cast< Instantiation* >(&i))) {
255 _bucket_->changeNotification(*(_instantiations_).second(const_cast< Instantiation* >(&i)),
256 var,
257 oldval,
258 newval);
259 }
260 // else i is not a slave of this
261 } else {
262 _slavesValue_.erase(&i);
263 }
264 }
265
266 template < typename GUM_SCALAR >
268 if (_bucket_) {
269 if (_instantiations_.existsFirst(const_cast< Instantiation* >(&i))) {
270 _bucket_->setFirstNotification(
271 *(_instantiations_).second(const_cast< Instantiation* >(&i)));
272 }
273 // else i is not a slave of this
274 } else {
275 _slavesValue_.erase(&i);
276 }
277 }
278
279 template < typename GUM_SCALAR >
281 if (_bucket_) {
282 if (_instantiations_.existsFirst(const_cast< Instantiation* >(&i))) {
283 _bucket_->setLastNotification(*(_instantiations_).second(const_cast< Instantiation* >(&i)));
284 }
285 // else i is not a slave of this
286 } else {
287 _slavesValue_.erase(&i);
288 }
289 }
290
291 template < typename GUM_SCALAR >
293 if (_bucket_) {
294 if (_instantiations_.existsFirst(const_cast< Instantiation* >(&i))) {
295 _bucket_->setIncNotification(*(_instantiations_.second(const_cast< Instantiation* >(&i))));
296 }
297 // else i is not a slave of this
298 } else {
299 _slavesValue_.erase(&i);
300 }
301 }
302
303 template < typename GUM_SCALAR >
305 if (_bucket_) {
306 if (_instantiations_.existsFirst(const_cast< Instantiation* >(&i))) {
307 _bucket_->setDecNotification(*(_instantiations_.second(const_cast< Instantiation* >(&i))));
308 }
309 // else i is not a slave of this
310 } else {
311 _slavesValue_.erase(&i);
312 }
313 }
314
315 template < typename GUM_SCALAR >
317 if (_bucket_) {
318 if (_instantiations_.existsFirst(const_cast< Instantiation* >(&i))) {
319 _bucket_->setChangeNotification(
320 *(_instantiations_.second(const_cast< Instantiation* >(&i))));
321 }
322 // else i is not a slave of this
323 } else {
324 _slavesValue_.erase(&i);
325 }
326 }
327
328 template < typename GUM_SCALAR >
330 if (_bucket_) {
331 try {
332 _instantiations_.insert(&i, new Instantiation(*_bucket_));
333 } catch (DuplicateElement const&) { return false; }
334 }
335
337 }
338
339 template < typename GUM_SCALAR >
342
343 if (_bucket_) {
344 if (_instantiations_.existsFirst(&i)) {
345 delete _instantiations_.second(&i);
346 _instantiations_.eraseFirst(&i);
347 return true;
348 } else {
349 return false;
350 }
351 } else {
352 if (_slavesValue_.exists(&i)) {
353 _slavesValue_.erase(&i);
354 return true;
355 } else {
356 return false;
357 }
358 }
359 }
360
361 template < typename GUM_SCALAR >
363 if (_bucket_) {
364 return *_bucket_;
365 } else {
366 return *this;
367 }
368 }
369
370 template < typename GUM_SCALAR >
372 if (_bucket_) {
373 return *_bucket_;
374 } else {
375 return *this;
376 }
377 }
378
379 template < typename GUM_SCALAR >
381 std::stringstream sBuff;
382 sBuff << (*i) << " = " << get(*i);
383 return sBuff.str();
384 }
385
386 template < typename GUM_SCALAR >
389
390 if (this->domainSize() <= _bufferSize_) {
392 } else {
394 }
395
396 _allVariables_.clear();
397
398 while (!_allVarsInst_.empty()) {
399 _allVarsInst_.erase(**(_allVarsInst_.variablesSequence().beginSafe()));
400 }
401
402 for ( // HashTableIteratorSafe<const MultiDimContainer<GUM_SCALAR>*,
403 // Instantiation*>
404 auto iter = _multiDims_.beginSafe(); iter != _multiDims_.endSafe(); ++iter) {
405 for (auto var: iter.key()->variablesSequence()) {
406 _addVariable_(var);
407 }
408 }
409
410 _changed_ = true;
411 }
412
413 template < typename GUM_SCALAR >
415 GUM_ERROR(OperationNotAllowed, "a MultiDimBucket is a read only MultiDim")
416 }
417
418 template < typename GUM_SCALAR >
420 try {
421 _allVariables_.insert(var);
422 _allVarsInst_.add(*var);
423 } catch (DuplicateElement const&) {
424 // Nothing to do then!
425 }
426 }
427
428 template < typename GUM_SCALAR >
430 bool found = false;
431
433 = _multiDims_.beginSafe();
434 iter != _multiDims_.endSafe();
435 ++iter) {
436 if (iter.key()->contains(*var)) {
437 found = true;
438 break;
439 }
440 }
441
442 // No one use it, we can safely remove it
443 if (!found) {
444 _allVariables_.erase(var);
445 _allVarsInst_.erase(*var);
446 }
447 }
448
449 template < typename GUM_SCALAR >
451 if (_bucket_) {
452 for (auto iter = _instantiations_.beginSafe(); iter != _instantiations_.endSafe(); ++iter) {
453 delete iter.second();
454 }
455
456 _instantiations_.clear();
457 delete _bucket_;
458 _bucket_ = 0;
459 }
460
461 // Creating the table.
463
464 for (auto var: this->variablesSequence()) {
465 _bucket_->add(*var);
466 }
467
468 if (!this->slaves_().empty()) {
469 for (List< Instantiation* >::const_iterator_safe iter = this->slaves_().cbeginSafe();
470 iter != this->slaves_().cendSafe();
471 ++iter) {
472 _instantiations_.insert(*iter, new Instantiation(*_bucket_));
473 }
474 }
475
476 _changed_ = true;
477 }
478
479 template < typename GUM_SCALAR >
481 if (_bucket_) {
482 for (auto iter = _instantiations_.beginSafe(); iter != _instantiations_.endSafe(); ++iter) {
483 delete iter.second();
484 }
485
486 _instantiations_.clear();
487 delete _bucket_;
488 _bucket_ = 0;
489 }
490 }
491
492 template < typename GUM_SCALAR >
494 if (_multiDims_.empty()) { GUM_ERROR(SizeError, "This MultiDimBucket is empty.") }
495
496 GUM_SCALAR sum = (GUM_SCALAR)0;
497 GUM_SCALAR current;
498 _allVarsInst_.setVals(value);
499
500 for (_allVarsInst_.setFirstOut(value); !_allVarsInst_.end(); _allVarsInst_.incOut(value)) {
501 current = (GUM_SCALAR)1;
502
504 = _multiDims_.beginSafe();
505 iter != _multiDims_.endSafe();
506 ++iter) {
507 (iter.val())->setVals(_allVarsInst_);
508 current *= iter.key()->get(*(iter.val()));
509 }
510
511 sum += current;
512 }
513
514 return sum;
515 }
516
517 template < typename GUM_SCALAR >
521
522 template < typename GUM_SCALAR >
524 if (_bucket_) {
525 return *_bucket_;
526 } else {
527 GUM_ERROR(OperationNotAllowed, "bucket not used.")
528 }
529 }
530
531 template < typename GUM_SCALAR >
533 const DiscreteVariable* y) {
535 for (auto iter = _instantiations_.beginSafe(); iter != _instantiations_.endSafe(); ++iter) {
536 iter.first()->replace(*x, *y);
537 iter.second()->replace(*x, *y);
538 }
539
540 if (_bucket_) _bucket_->replace(*x, *y);
541
542 _allVariables_.erase(x);
543 _allVariables_.insert(y);
544 _allVarsInst_.replace(*x, *y);
545 }
546
547 template < typename GUM_SCALAR >
552
553} /* namespace gum */
Safe Iterators for hashtables.
BijectionIteratorSafe< T1, T2 > iterator_safe
types for STL compliance
Definition bijection.h:1658
Base class for discrete random variable.
Exception : a similar element already exists.
The class for generic Hash Tables.
Definition hashTable.h:640
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.
bool isMaster(const MultiDimAdressable *m) const
Indicates whether m is the master of this instantiation.
void setFirst()
Assign the first values to the tuple of the Instantiation.
ListConstIteratorSafe< Val > const_iterator_safe
Types for STL compliance.
Definition list.h:392
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.
A multidim implementation for buckets.
Bijection< Instantiation *, Instantiation * > _instantiations_
Bijection between instantiations registered on this and their equivalent on bucket.
GUM_ELEMENT get(const Instantiation &i) const override
Returns the value pointed by i.
bool isBucketEmpty() const
Returns true if this bucket is empty.
void replace_(const DiscreteVariable *x, const DiscreteVariable *y) override
This is called by MultiDimContainer::replace() to proceed with the replacing between x and y.
void setFirstNotification(const Instantiation &i) override
Listen to setFirst in a given Instantiation.
void setLastNotification(const Instantiation &i) override
Listen to setLast in a given Instantiation.
const gum::VariableSet & allVariables() const
Returns the sequence of all the variables contained in the bucket.
void erase(const MultiDimContainer< GUM_ELEMENT > &impl)
Remove a MultiDimContainer from this bucket.
void commitMultipleChanges_() override
Synchronize content after MultipleChanges.
gum::VariableSet _allVariables_
The set of all variables of the multidims in this bucket.
void changeNotification(const Instantiation &i, const DiscreteVariable *const var, Idx oldval, Idx newval) override
Listen to changes in a given Instantiation.
Size bufferSize() const
Returns the amount of memory allowed for this bucket.
void _initializeBuffer_()
Initialize the internal buffer.
Instantiation _allVarsInst_
Instantiation over all variable in this.
void setChangeNotification(const Instantiation &i) override
Listen to an assignment of a value in a Instantiation.
void _eraseVariable_(const DiscreteVariable *var)
Erase a variable from allVariables if no other multidimensional table uses it in this bucket.
GUM_ELEMENT _computeValue_(const Instantiation &value) const
Compute the value of the final table of this bucket given i.
~MultiDimBucket() override
Destructor.
void setIncNotification(const Instantiation &i) override
Listen to increment in a given Instantiation.
const HashTable< const MultiDimContainer< GUM_ELEMENT > *, Instantiation * > & multidims() const
Returns the MultiDimContainer and their respective Instantiation.
void _eraseBuffer_()
Clean the buffer and switch it's instantiation to this bucket.
void setBufferSize(Size amount)
Changes the amount of memory allowed for this bucket.
MultiDimArray< GUM_ELEMENT > * _bucket_
The result table of this bucket.
const MultiDimArray< GUM_ELEMENT > & bucket() const
Returns the MultiDimArray used by this MultiDimBucket.
Size _bufferSize_
The number of element allowed in bucket.
MultiDimContainer< GUM_ELEMENT > * newFactory() const override
Default constructor.
const std::string & name() const override
Returns the real name of the multiDim implementation.
bool bucketChanged() const
Returns true if the bucket need re-computation since the last computation.
HashTable< const MultiDimContainer< GUM_ELEMENT > *, Instantiation * > _multiDims_
The set of MultiDimContainer in this bucket.
void add(const MultiDimContainer< GUM_ELEMENT > &impl)
Add a MultiDimContainer in the bucket.
MultiDimAdressable & getMasterRef() override
In order to insure the dereference for decorators, we need to virtualize the access to master pointer...
bool _changed_
Flag used to know if changes has occurred in the bucket since last computation.
GUM_ELEMENT & get_(const Instantiation &i) const override
Size bucketSize() const
Returns the number of MultiDimContainer in this bucket.
bool registerSlave(Instantiation &i) override
Register i as a slave of this MultiDimAdressable.
void _addVariable_(const DiscreteVariable *var)
Add a variable to allVariables, and do nothing if var is already in the set.
bool unregisterSlave(Instantiation &i) override
Unregister i as a slave of this MultiDimAdressable.
void setDecNotification(const Instantiation &i) override
Listen to increment in each recorded Instantiation.
void compute(bool force=false) const
This method computes the final table of this bucket.
Size realSize() const override
Returns the real number of parameters used for this table.
MultiDimBucket(Size bufferSize=INT_MAX)
Default constructor.
std::string _name_
The class name.
bool contains(const MultiDimContainer< GUM_ELEMENT > &impl) const
Returns true if the MultiDimContainer is in this bucket.
HashTable< const Instantiation *, GUM_ELEMENT > _slavesValue_
This table is used to keep the last value computed for an instantiation when the value are computed o...
virtual std::string toString() const
Returns a representation of this MultiDimContainer.
<agrum/base/multidim/multiDimImplementation.h>
void erase(const DiscreteVariable &v) override
Removes a var from the variables of the multidimensional matrix.
Size domainSize() const override
Returns the product of the variables domain size.
bool isInMultipleChangeMethod_() const
Get the actual change method of this MultiDimImplementation.
const Sequence< const DiscreteVariable * > & variablesSequence() const override
Returns a const ref to the sequence of DiscreteVariable*.
void add(const DiscreteVariable &v) override
Adds a new var to the variables of the multidimensional matrix.
bool registerSlave(Instantiation &slave) override
Register i as a slave of this MultiDimAdressable.
const List< Instantiation * > & slaves_() const
Returns a constant reference over the list of slaved instantiations.
bool empty() const override
Returns true if no var is in *this.
void replace_(const DiscreteVariable *x, const DiscreteVariable *y) override
Replace variable x by y.
virtual void commitMultipleChanges_()
Synchronize content after MultipleChanges.
bool contains(const DiscreteVariable &v) const override
Returns true if var is in *this.
Abstract base class for all multi dimensionnal read only structure.
MultiDimReadOnly()
Default constructor.
Exception : operation not allowed.
Exception : problem with size.
#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 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