aGrUM  0.14.2
multiDimBucket_tpl.h
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (C) 2005 by Pierre-Henri WUILLEMIN et Christophe GONZALES *
3  * {prenom.nom}_at_lip6.fr *
4  * *
5  * This program is free software; you can redistribute it and/or modify *
6  * it under the terms of the GNU General Public License as published by *
7  * the Free Software Foundation; either version 2 of the License, or *
8  * (at your option) any later version. *
9  * *
10  * This program is distributed in the hope that it will be useful, *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13  * GNU General Public License for more details. *
14  * *
15  * You should have received a copy of the GNU General Public License *
16  * along with this program; if not, write to the *
17  * Free Software Foundation, Inc., *
18  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19  ***************************************************************************/
29 
30 namespace gum {
31 
32  template < typename GUM_SCALAR >
34  MultiDimReadOnly< GUM_SCALAR >(), __bufferSize(bufferSize), __bucket(0),
35  __changed(false), __name("MultiDimBucket") {
36  GUM_CONSTRUCTOR(MultiDimBucket);
37  }
38 
39  template < typename GUM_SCALAR >
41  const MultiDimBucket< GUM_SCALAR >& source) :
42  MultiDimReadOnly< GUM_SCALAR >(source),
46  __name("MultiDimBucket") {
47  GUM_CONS_CPY(MultiDimBucket);
48  }
49 
50  template < typename GUM_SCALAR >
52  GUM_DESTRUCTOR(MultiDimBucket);
54 
55  for (BiIter iter = __instantiations.beginSafe();
56  iter != __instantiations.endSafe();
57  ++iter) {
58  delete iter.second();
59  }
60 
61  if (__bucket) { delete __bucket; }
62 
64  Instantiation* > iter = __multiDims.beginSafe();
65  iter != __multiDims.endSafe();
66  ++iter) {
67  delete iter.val();
68  }
69  }
70 
71  template < typename GUM_SCALAR >
73  const MultiDimContainer< GUM_SCALAR >& impl) {
74  this->add(&impl);
75  }
76 
77  template < typename GUM_SCALAR >
79  const MultiDimContainer< GUM_SCALAR >* impl) {
80  __multiDims.insert(impl, new Instantiation(*impl));
81 
83  for (const auto var : impl->variablesSequence()) {
84  __addVariable(var);
85  }
86  }
87 
88  __changed = true;
89  }
90 
91  template < typename GUM_SCALAR >
93  const MultiDimContainer< GUM_SCALAR >& impl) {
94  this->erase(&impl);
95  }
96 
97  template < typename GUM_SCALAR >
99  const MultiDimContainer< GUM_SCALAR >* impl) {
100  try {
101  delete __multiDims[impl];
102  __multiDims.erase(impl);
103 
105  for (auto var : impl->variablesSequence()) {
106  __eraseVariable(var);
107  }
108  }
109 
110  __changed = true;
111  } catch (NotFound&) {
112  // Do nothing
113  }
114  }
115 
116  template < typename GUM_SCALAR >
118  const MultiDimContainer< GUM_SCALAR >& impl) const {
119  return __multiDims.exists(&impl);
120  }
121 
122  template < typename GUM_SCALAR >
123  INLINE const Set< const DiscreteVariable* >&
125  return __allVariables;
126  }
127 
128  template < typename GUM_SCALAR >
130  return __multiDims.size();
131  }
132 
133  template < typename GUM_SCALAR >
135  return __multiDims.empty();
136  }
137 
138  template < typename GUM_SCALAR >
140  return __changed;
141  }
142 
143  template < typename GUM_SCALAR >
145  return __bufferSize;
146  }
147 
148  template < typename GUM_SCALAR >
150  __bufferSize = ammount;
151 
152  if ((this->domainSize() > __bufferSize) && (__bucket != 0)) {
153  __eraseBuffer();
154  } else if (__bucket == 0) {
156  }
157  }
158 
159  template < typename GUM_SCALAR >
160  void MultiDimBucket< GUM_SCALAR >::compute(bool force) const {
161  if ((__bucket) && (__changed || force)) {
162  Instantiation values(*__bucket);
163 
164  for (values.setFirst(); !values.end(); values.inc()) {
165  __bucket->set(values, __computeValue(values));
166  }
167  } else if ((__bucket == 0) && __changed) {
168  __slavesValue.clear();
169  __changed = false;
170  }
171 
172  __changed = false;
173  }
174 
175  template < typename GUM_SCALAR >
176  const std::string& MultiDimBucket< GUM_SCALAR >::name() const {
177  return __name;
178  }
179 
180  template < typename GUM_SCALAR >
183 
185  if (this->domainSize() <= __bufferSize) {
186  if (__bucket)
187  __bucket->add(v);
188  else
190  } else if (__bucket) {
191  __eraseBuffer();
192  }
193  }
194  }
195 
196  template < typename GUM_SCALAR >
199 
201  && (this->domainSize() <= __bufferSize)) {
202  if (__bucket) {
203  __bucket->erase(v);
204  } else {
206  }
207  }
208  }
209 
210  template < typename GUM_SCALAR >
212  return (__bucket) ? __bucket->realSize() : (Size)0;
213  }
214 
215  template < typename GUM_SCALAR >
216  INLINE bool
219  }
220 
221  template < typename GUM_SCALAR >
222  INLINE GUM_SCALAR
224  compute();
225 
226  if (__bucket) {
227  try {
228  return __bucket->get(
229  *(__instantiations.second(const_cast< Instantiation* >(&i))));
230  } catch (NotFound&) { return __bucket->get(i); }
231  } else if (i.isMaster(this)) {
232  if (!__slavesValue.exists(&i)) {
233  __slavesValue.insert(&i, __computeValue(i));
234  }
235 
236  return __slavesValue[&i];
237  } else {
238  return __computeValue(i);
239  }
240  }
241 
242  template < typename GUM_SCALAR >
244  const Instantiation& i,
245  const DiscreteVariable* const var,
246  Idx oldval,
247  Idx newval) {
248  if (__bucket) {
249  try {
250  __bucket->changeNotification(
251  *(__instantiations).second(const_cast< Instantiation* >(&i)),
252  var,
253  oldval,
254  newval);
255  } catch (NotFound&) {
256  // Then i is not a slave of this
257  }
258  } else {
259  __slavesValue.erase(&i);
260  }
261  }
262 
263  template < typename GUM_SCALAR >
264  INLINE void
266  if (__bucket) {
267  try {
268  __bucket->setFirstNotification(
269  *(__instantiations).second(const_cast< Instantiation* >(&i)));
270  } catch (NotFound&) {
271  // Then i is not a slave of this
272  }
273  } else {
274  __slavesValue.erase(&i);
275  }
276  }
277 
278  template < typename GUM_SCALAR >
279  INLINE void
281  if (__bucket) {
282  try {
283  __bucket->setLastNotification(
284  *(__instantiations).second(const_cast< Instantiation* >(&i)));
285  } catch (NotFound&) {
286  // Then i is not a slave of this
287  }
288  } else {
289  __slavesValue.erase(&i);
290  }
291  }
292 
293  template < typename GUM_SCALAR >
294  INLINE void
296  if (__bucket) {
297  try {
298  __bucket->setIncNotification(
299  *(__instantiations.second(const_cast< Instantiation* >(&i))));
300  } catch (NotFound&) {
301  // Then i is not a slave of this
302  }
303  } else {
304  __slavesValue.erase(&i);
305  }
306  }
307 
308  template < typename GUM_SCALAR >
309  INLINE void
311  if (__bucket) {
312  try {
313  __bucket->setDecNotification(
314  *(__instantiations.second(const_cast< Instantiation* >(&i))));
315  } catch (NotFound&) {
316  // Then i is not a slave of this
317  }
318  } else {
319  __slavesValue.erase(&i);
320  }
321  }
322 
323  template < typename GUM_SCALAR >
324  INLINE void
326  if (__bucket) {
327  try {
328  __bucket->setChangeNotification(
329  *(__instantiations.second(const_cast< Instantiation* >(&i))));
330  } catch (NotFound&) {
331  // Then i is not a slave of this
332  }
333  } else {
334  __slavesValue.erase(&i);
335  }
336  }
337 
338  template < typename GUM_SCALAR >
340  if (__bucket) {
341  try {
342  __instantiations.insert(&i, new Instantiation(*__bucket));
343  } catch (DuplicateElement&) { return false; }
344  }
345 
347  }
348 
349  template < typename GUM_SCALAR >
352 
353  if (__bucket) {
354  try {
355  delete __instantiations.second(&i);
356  __instantiations.eraseFirst(&i);
357  return true;
358  } catch (NotFound&) { return false; }
359  } else {
360  if (__slavesValue.exists(&i)) {
361  __slavesValue.erase(&i);
362  return true;
363  } else {
364  return false;
365  }
366  }
367  }
368 
369  template < typename GUM_SCALAR >
371  if (__bucket) {
372  return *__bucket;
373  } else {
374  return *this;
375  }
376  }
377 
378  template < typename GUM_SCALAR >
379  INLINE const MultiDimAdressable&
381  if (__bucket) {
382  return *__bucket;
383  } else {
384  return *this;
385  }
386  }
387 
388  template < typename GUM_SCALAR >
389  INLINE const std::string
391  std::stringstream sBuff;
392  sBuff << (*i) << " = " << get(*i);
393  return sBuff.str();
394  }
395 
396  template < typename GUM_SCALAR >
399 
400  if (this->domainSize() <= __bufferSize) {
402  } else {
403  __eraseBuffer();
404  }
405 
406  __allVariables.clear();
407 
408  while (!__allVarsInst.empty()) {
410  }
411 
412  for ( // HashTableIteratorSafe<const MultiDimContainer<GUM_SCALAR>*,
413  // Instantiation*>
414  auto iter = __multiDims.beginSafe(); iter != __multiDims.endSafe();
415  ++iter) {
416  for (auto var : iter.key()->variablesSequence()) {
417  __addVariable(var);
418  }
419  }
420 
421  __changed = true;
422  }
423 
424  template < typename GUM_SCALAR >
425  INLINE GUM_SCALAR&
427  GUM_ERROR(OperationNotAllowed, "a MultiDimBucket is a read only MultiDim");
428  }
429 
430  template < typename GUM_SCALAR >
431  INLINE void
433  try {
434  __allVariables.insert(var);
435  __allVarsInst.add(*var);
436  } catch (DuplicateElement&) {
437  // Nothing to do then!
438  }
439  }
440 
441  template < typename GUM_SCALAR >
443  bool found = false;
444 
446  Instantiation* > iter = __multiDims.beginSafe();
447  iter != __multiDims.endSafe();
448  ++iter) {
449  if (iter.key()->contains(*var)) {
450  found = true;
451  break;
452  }
453  }
454 
455  // No one use it, we can safely remove it
456  if (!found) {
457  __allVariables.erase(var);
458  __allVarsInst.erase(*var);
459  }
460  }
461 
462  template < typename GUM_SCALAR >
464  if (__bucket) {
466 
467  for (BiIter iter = __instantiations.beginSafe();
468  iter != __instantiations.endSafe();
469  ++iter) {
470  delete iter.second();
471  }
472 
473  __instantiations.clear();
474  delete __bucket;
475  __bucket = 0;
476  }
477 
478  // Creating the table.
480 
481  for (auto var : this->variablesSequence()) {
482  __bucket->add(*var);
483  }
484 
485  if (!this->_slaves().empty()) {
487  this->_slaves().cbeginSafe();
488  iter != this->_slaves().cendSafe();
489  ++iter) {
490  __instantiations.insert(*iter, new Instantiation(*__bucket));
491  }
492  }
493 
494  __changed = true;
495  }
496 
497  template < typename GUM_SCALAR >
499  if (__bucket) {
501 
502  for (BiIter iter = __instantiations.beginSafe();
503  iter != __instantiations.endSafe();
504  ++iter) {
505  delete iter.second();
506  }
507 
508  __instantiations.clear();
509  delete __bucket;
510  __bucket = 0;
511  }
512  }
513 
514  template < typename GUM_SCALAR >
516  const Instantiation& value) const {
517  try {
518  GUM_SCALAR sum = (GUM_SCALAR)0;
519  GUM_SCALAR current;
520  __allVarsInst.setVals(value);
521 
522  for (__allVarsInst.setFirstOut(value); !__allVarsInst.end();
523  __allVarsInst.incOut(value)) {
524  current = (GUM_SCALAR)1;
525 
527  Instantiation* > iter =
528  __multiDims.beginSafe();
529  iter != __multiDims.endSafe();
530  ++iter) {
531  (iter.val())->setVals(__allVarsInst);
532  current *= iter.key()->get(*(iter.val()));
533  }
534 
535  sum += current;
536  }
537 
538  return sum;
539  } catch (NotFound& e) {
540  std::cerr << std::endl << e.errorContent() << std::endl;
541  // This happens if the bucket is empty.
542  GUM_ERROR(SizeError, "This MultiDimBucket is empty.");
543  }
544  }
545 
546  template < typename GUM_SCALAR >
549  return new MultiDimBucket< GUM_SCALAR >;
550  }
551 
552  template < typename GUM_SCALAR >
553  INLINE const MultiDimArray< GUM_SCALAR >&
555  if (__bucket) {
556  return *__bucket;
557  } else {
558  GUM_ERROR(OperationNotAllowed, "bucket not used.");
559  }
560  }
561 
562  template < typename GUM_SCALAR >
564  const DiscreteVariable* y) {
567 
568  for (Iter iter = __instantiations.beginSafe();
569  iter != __instantiations.endSafe();
570  ++iter) {
571  iter.first()->replace(*x, *y);
572  iter.second()->replace(*x, *y);
573  }
574 
575  if (__bucket) __bucket->replace(*x, *y);
576 
577  __allVariables.erase(x);
578  __allVariables.insert(y);
579  __allVarsInst.replace(*x, *y);
580  }
581 
582  template < typename GUM_SCALAR >
585  return __multiDims;
586  }
587 
588 } /* namespace gum */
virtual bool unregisterSlave(Instantiation &i) override
Unregister i as a slave of this MultiDimAdressable.
virtual void setDecNotification(const Instantiation &i) override
Listen to increment in each recorded Instantiation.
Size __bufferSize
The number of element allowed in __bucket.
Instantiation __allVarsInst
Instantiation over all variable in this.
MultiDimArray< GUM_SCALAR > * __bucket
The result table of this bucket.
HashTable< const MultiDimContainer< GUM_SCALAR > *, Instantiation *> __multiDims
The set of MultiDimContainer in this bucket.
virtual void setChangeNotification(const Instantiation &i) override
Listen to an assignment of a value in a Instantiation.
std::string __name
The class name.
virtual Size realSize() const override
Returns the real number of parameters used for this table.
virtual void erase(const DiscreteVariable &v) override
Removes a var from the variables of the multidimensional matrix.
Safe iterators for bijectionIterator.
Definition: bijection.h:1409
bool isBucketEmpty() const
Returns true if this bucket is empty.
const List< Instantiation *> & _slaves() const
Returns a constant reference over the list of slaved instantiations.
virtual const std::string toString() const
Returns a representation of this MultiDimContainer.
A multidim implementation for buckets.
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...
GUM_SCALAR __computeValue(const Instantiation &value) const
Compute the value of the final table of this bucket given i.
Base class for discrete random variable.
bool contains(const MultiDimContainer< GUM_SCALAR > &impl) const
Returns true if the MultiDimContainer is in this bucket.
Safe Iterators for hashtables.
Definition: hashTable.h:2217
virtual bool unregisterSlave(Instantiation &slave) override
Unregister i as a slave of this MultiDimAdressable.
gum is the global namespace for all aGrUM entities
Definition: agrum.h:25
Abstract base class for all multi dimensionnal containers.
virtual bool empty() const override
Returns true if no var is in *this.
virtual MultiDimContainer< GUM_SCALAR > * newFactory() const override
Default constructor.
virtual GUM_SCALAR get(const Instantiation &i) const override
Returns the value pointed by i.
Abstract base class for all multi dimensionnal read only structure.
Instantiation & setVals(const Instantiation &i)
Assign the values from i in the Instantiation.
const Sequence< const DiscreteVariable *> & variablesSequence() const final
Returns the sequence of DiscreteVariable of this instantiation.
The class for generic Hash Tables.
Definition: hashTable.h:676
virtual ~MultiDimBucket()
Destructor.
void __addVariable(const DiscreteVariable *var)
Add a variable to __allVariables, and do nothing if var is already in the set.
Representation of a setA Set is a structure that contains arbitrary elements.
Definition: set.h:162
void __initializeBuffer()
Initialize the internal buffer.
void __eraseBuffer()
Clean the buffer and switch it&#39;s instantiation to this bucket.
void erase(const MultiDimContainer< GUM_SCALAR > &impl)
Remove a MultiDimContainer from this bucket.
void incOut(const Instantiation &i)
Operator increment for the variables not in i.
virtual void changeNotification(const Instantiation &i, const DiscreteVariable *const var, Idx oldval, Idx newval) override
Listen to changes in a given Instantiation.
virtual void setLastNotification(const Instantiation &i) override
Listen to setLast in a given Instantiation.
virtual void _replace(const DiscreteVariable *x, const DiscreteVariable *y) override
Replace variable x by y.
void inc()
Operator increment.
const MultiDimArray< GUM_SCALAR > & bucket() const
Returns the MultiDimArray used by this MultiDimBucket.
void __eraseVariable(const DiscreteVariable *var)
Erase a variable from __allVariables if no other multidimensional table uses it in this bucket...
Size bucketSize() const
Returns the number of MultiDimContainer in in this bukcet.
MultiDimBucket(Size bufferSize=INT_MAX)
Default constructor.
virtual GUM_SCALAR & _get(const Instantiation &i) const override
void compute(bool force=false) const
This method computes the final table of this bucket.
virtual void setIncNotification(const Instantiation &i) override
Listen to increment in a given Instantiation.
Multidimensional matrix stored as an array in memory.
Definition: multiDimArray.h:51
Bijection< Instantiation *, Instantiation *> __instantiations
Bijection between instantiations registered on this and their equivalent on __bucket.
bool bucketChanged() const
Returns true if the bucket need re-computation since the last computation.
virtual bool empty() const final
Returns true if the instantiation is empty.
virtual void add(const DiscreteVariable &v) override
Adds a new var to the variables of the multidimensional matrix.
bool __changed
Flag used to know if changes has occurred in the bucket since last computation.
virtual const Sequence< const DiscreteVariable *> & variablesSequence() const override
Returns a const ref to the sequence of DiscreteVariable*.
virtual void setFirstNotification(const Instantiation &i) override
Listen to setFirst in a given Instantiation.
Abstract base class for all multi dimensionnal addressable.
Class for assigning/browsing values to tuples of discrete variables.
Definition: instantiation.h:80
virtual void _commitMultipleChanges() override
Synchronize content after MultipleChanges.
virtual Size domainSize() const override
Returns the product of the variables domain size.
Set< const DiscreteVariable *> __allVariables
The set of all variables of the multidims in this bucket.
Size bufferSize() const
Returns the amount of memory allowed for this bucket.
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.
Headers of the MultiDimBucket class.
const T2 & second() const
Returns the second element of the current association.
void replace(const DiscreteVariable &x, const DiscreteVariable &y)
Replace variables in this multidim.
virtual void _commitMultipleChanges()
Synchronize content after MultipleChanges.
Safe const iterators for Lists.
Definition: list.h:2027
virtual bool registerSlave(Instantiation &i) override
Register i as a slave of this MultiDimAdressable.
<agrum/multidim/multiDimImplementation.h>
virtual const Sequence< const DiscreteVariable *> & variablesSequence() const =0
Returns a const ref to the sequence of DiscreteVariable*.
Size Idx
Type for indexes.
Definition: types.h:50
void add(const DiscreteVariable &v) final
Adds a new variable in the Instantiation.
void erase(const DiscreteVariable &v) final
Removes a variable from the Instantiation.
std::size_t Size
In aGrUM, hashed values are unsigned long int.
Definition: types.h:45
void setBufferSize(Size amount)
Changes the amount of memory allowed for this bucket.
const Set< const DiscreteVariable *> & allVariables() const
Returns the sequence of all the variables contained in the bucket.
virtual bool contains(const DiscreteVariable &v) const override
Returns true if var is in *this.
const HashTable< const MultiDimContainer< GUM_SCALAR > *, Instantiation *> & multidims() const
Returns the MultiDimContainer and their respective Instantiation.
const std::string & name() const override
Returns the real name of the multiDim implementation.
const std::string errorContent() const
Returns the message content.
Definition: exceptions.h:132
virtual MultiDimAdressable & getMasterRef() override
In order to insure the dereference for decorators, we need to virtualize the access to master pointer...
void add(const MultiDimContainer< GUM_SCALAR > &impl)
Add a MultiDimContainer in the bucket.
virtual void _replace(const DiscreteVariable *x, const DiscreteVariable *y) override
Replace variable x by y.
const T1 & first() const
Returns the first element of the current association.
virtual bool registerSlave(Instantiation &slave) override
Register i as a slave of this MultiDimAdressable.
#define GUM_ERROR(type, msg)
Definition: exceptions.h:52
bool end() const
Returns true if the Instantiation reached the end.
void setFirstOut(const Instantiation &i)
Assign the first values in the Instantiation for the variables not in i.