aGrUM  0.20.3
a C++ library for (probabilistic) graphical models
multiDimBucket.h
Go to the documentation of this file.
1 /**
2  *
3  * Copyright (c) 2005-2021 by Pierre-Henri WUILLEMIN(@LIP6) & Christophe GONZALES(@AMU)
4  * info_at_agrum_dot_org
5  *
6  * This library is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this library. If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 
22 /**
23  * @file
24  * @brief Headers of the MultiDimBucket class.
25  *
26  * @author Pierre-Henri WUILLEMIN(@LIP6) & Christophe GONZALES(@AMU)
27  * @author Lionel TORTI
28  */
29 
30 #ifndef GUM_MULTIDIM_BUCKET_H
31 #define GUM_MULTIDIM_BUCKET_H
32 
33 #include <climits>
34 #include <sstream>
35 
36 #include <agrum/tools/core/bijection.h>
37 #include <agrum/tools/core/hashTable.h>
38 #include <agrum/tools/core/sequence.h>
39 #include <agrum/tools/core/set.h>
40 
41 #include <agrum/tools/multidim/implementations/multiDimArray.h>
42 #include <agrum/tools/multidim/implementations/multiDimReadOnly.h>
43 
44 namespace gum {
45 
46  /**
47  * @class MultiDimBucket
48  * @headerfile multiDimBucket.h <agrum/tools/multidim/multiDimBucket.h>
49  * @ingroup multidim_group
50  *
51  * @brief A multidim implementation for buckets.
52  *
53  * This class behaves in two different ways, depending on the value of memory
54  * allowed and the size of the resulting multidimensional table. If the table
55  * is above the allowed amount of memory then value are computed when
56  * demanded, having a cache for each registered instantiation to not compute
57  * several times in a row the same value.
58  *
59  * If the memory allowed is enough to contain the bucket's table, then the
60  * resulting table is computed when a value is demanded for the first time.
61  *
62  * Since a MultiDimArray is used as a buffer, an instantiation real master
63  * will be the internal buffer of a MultiDimBucket. This is why you should
64  * always call the Instantiation::isMaster() method with the reference
65  * retuned by MultiDimBucket::getMasterRef().
66  *
67  * TODO handle slave switch between buffer and hashtable.
68  *
69  * @tparam GUM_SCALAR The type of scalars stored in this multidimensional
70  * table.
71  */
72 
73  template < typename GUM_SCALAR >
74  class MultiDimBucket: public MultiDimReadOnly< GUM_SCALAR > {
75  public:
76  // ========================================================================
77  /// @name Constructor & destructor.
78  // ========================================================================
79  /// @{
80 
81  /**
82  * @brief Default constructor.
83  *
84  * The default amount of memory available for a bucket is 2^16 (65536)
85  * elements in the table.
86  *
87  * @param bufferSize The amount of memory allowed for this bucket.
88  */
89  explicit MultiDimBucket(Size bufferSize = INT_MAX);
90 
91  /**
92  * @brief Copy constructor.
93  * @param source The MultiDimBucket to copy.
94  */
95  MultiDimBucket(const MultiDimBucket< GUM_SCALAR >& source);
96 
97  /**
98  * @brief Destructor.
99  */
100  virtual ~MultiDimBucket();
101 
102  /// @}
103  // ========================================================================
104  /// @name Bucket methods
105  // ========================================================================
106  /// @{
107 
108  /**
109  * @brief Add a MultiDimContainer in the bucket.
110  * @param impl The MultiDimContainer to copy.
111  * @throw DuplicateElement Raised if impl is already in the bucket.
112  */
113  void add(const MultiDimContainer< GUM_SCALAR >& impl);
114 
115  /**
116  * @brief Add a MultiDimContainer in the bucket.
117  * @param impl The MultiDimContainer to add.
118  * @throw DuplicateElement Raised if impl is already in the bucket.
119  */
120  void add(const MultiDimContainer< GUM_SCALAR >* impl);
121 
122  /**
123  * @brief Remove a MultiDimContainer from this bucket.
124  * @param impl The MultiDimContainer to remove.
125  */
126  void erase(const MultiDimContainer< GUM_SCALAR >& impl);
127 
128  /**
129  * @brief Remove a MultiDimContainer from this bucket.
130  * @param impl The MultiDimContainer to remove.
131  */
132  void erase(const MultiDimContainer< GUM_SCALAR >* impl);
133 
134  /**
135  * @brief Returns true if the MultiDimContainer is in this bucket.
136  * @param impl The impl to test for existence.
137  * @return Returns true if the MultiDimContainer is in this bucket.
138  */
139  bool contains(const MultiDimContainer< GUM_SCALAR >& impl) const;
140 
141  /**
142  * @brief Returns the sequence of all the variables contained in the
143  * bucket.
144  * @return Returns the sequence of all the variables contained in the
145  * bucket.
146  */
147  const Set< const DiscreteVariable* >& allVariables() const;
148 
149  /**
150  * @brief Returns the number of MultiDimContainer in in this bukcet.
151  * @return Returns the number of MultiDimContainer in in this bukcet.
152  */
153  Size bucketSize() const;
154 
155  /**
156  * @brief Returns true if this bucket is empty.
157  * @return Returns true if this bucket is empty.
158  */
159  bool isBucketEmpty() const;
160 
161  /**
162  * @brief Returns true if the bucket need re-computation since the last
163  * computation.
164  * @return Returns true if the bucket need re-computation since the last
165  * computation.
166  */
167  bool bucketChanged() const;
168 
169  /**
170  * @brief Returns the MultiDimArray used by this MultiDimBucket.
171  * @return Returns the MultiDimArray used by this MultiDimBucket.
172  * @throw OperationNotAllowed Raised if the bucket has not been built.
173  */
174  const MultiDimArray< GUM_SCALAR >& bucket() const;
175 
176  /**
177  * @brief Returns the amount of memory allowed for this bucket.
178  * @return Returns the amount of memory allowed for this bucket.
179  */
180  Size bufferSize() const;
181 
182  /**
183  * @brief Changes the amount of memory allowed for this bucket.
184  *
185  * If the new amount is not enough for the current size of this bucket,
186  * then internal buffer is deleted. In the other case, the internal buffer
187  * is created but not computed.
188  *
189  * @param amount The amount of memory allowed for this bucket.
190  */
191  void setBufferSize(Size amount);
192 
193  /**
194  * @brief This method computes the final table of this bucket.
195  *
196  * A flag is used to prevent unnecessary computation if the table has
197  * already been computed.
198  *
199  * If the size of the final table is above the amount of authorized memory,
200  * an OperationNotAllowed is raised.
201  *
202  * Remember that this method is constant because the content of a
203  * multidimensional table is mutable.
204  *
205  * @param force If true (default set at false) then the final table is
206  * re-computed.
207  *
208  * @throw OperationNotAllowed Raised if the size of the final table is
209  * above the authorized amount of memory.
210  * @throw SizeError Raised if the bucket is empty.
211  */
212  void compute(bool force = false) const;
213 
214  /// @}
215  // ========================================================================
216  /// @name Inherited methods
217  // ========================================================================
218  /// @{
219 
220  virtual MultiDimContainer< GUM_SCALAR >* newFactory() const override;
221 
222  const std::string& name() const override;
223 
224  virtual void add(const DiscreteVariable& v) override;
225 
226  virtual void erase(const DiscreteVariable& v) override;
227 
228  virtual Size realSize() const override;
229 
230  bool contains(const DiscreteVariable& v) const override;
231 
232  virtual GUM_SCALAR get(const Instantiation& i) const override;
233 
234  virtual void changeNotification(const Instantiation& i,
235  const DiscreteVariable* const var,
236  Idx oldval,
237  Idx newval) override;
238 
239  virtual void setFirstNotification(const Instantiation& i) override;
240 
241  virtual void setLastNotification(const Instantiation& i) override;
242 
243  virtual void setIncNotification(const Instantiation& i) override;
244 
245  virtual void setDecNotification(const Instantiation& i) override;
246 
247  virtual void setChangeNotification(const Instantiation& i) override;
248 
249  virtual bool registerSlave(Instantiation& i) override;
250 
251  virtual bool unregisterSlave(Instantiation& i) override;
252 
253  virtual MultiDimAdressable& getMasterRef() override;
254 
255  virtual const MultiDimAdressable& getMasterRef() const override;
256 
257  virtual std::string toString(const Instantiation* i) const override;
258 
259  /// @}
260 
261  /**
262  * @brief Returns the MultiDimContainer and their respective Instantiation.
263  * @return Returns the MultiDimContainer and their respective Instantiation.
264  */
265  const HashTable< const MultiDimContainer< GUM_SCALAR >*, Instantiation* >& multidims() const;
266 
267  protected:
268  virtual void commitMultipleChanges_() override;
269 
270  /**
271  * @warning This will raise en exception, you should directly use the get()
272  * and operator[]() methods.
273  */
274  virtual GUM_SCALAR& get_(const Instantiation& i) const override;
275 
276  virtual void replace_(const DiscreteVariable* x, const DiscreteVariable* y) override;
277 
278  private:
279  /// The number of element allowed in _bucket_.
280  Size _bufferSize_;
281 
282  /// Bijection between instantiations registered on this and
283  /// their equivalent on _bucket_
284  Bijection< Instantiation*, Instantiation* > _instantiations_;
285 
286  /// The result table of this bucket.
287  MultiDimArray< GUM_SCALAR >* _bucket_;
288 
289  /// The set of MultiDimContainer in this bucket.
290  mutable HashTable< const MultiDimContainer< GUM_SCALAR >*, Instantiation* > _multiDims_;
291 
292  /// The set of all variables of the multidims in this bucket.
293  Set< const DiscreteVariable* > _allVariables_;
294 
295  /// Instantiation over all variable in this
296  mutable Instantiation _allVarsInst_;
297 
298  /**
299  * @brief Add a variable to _allVariables_, and do nothing if var is already
300  * in
301  * the set.
302  * @param var The DiscreteVariable to add.
303  */
304  void _addVariable_(const DiscreteVariable* var);
305 
306  /**
307  * @brief Erase a variable from _allVariables_ if no other multidimensional
308  * table
309  * uses it in this bucket.
310  * @param var The DiscreteVariable to remove.
311  */
312  void _eraseVariable_(const DiscreteVariable* var);
313 
314  /**
315  * @brief Initialize the internal buffer.
316  *
317  * This method delete _bucket_ after saving it's slave instantiations.
318  */
319  void _initializeBuffer_();
320 
321  /**
322  * @brief Clean the buffer and switch it's instantiation to this bucket.
323  */
324  void _eraseBuffer_();
325 
326  /**
327  * @brief Compute the value of the final table of this bucket given i.
328  *
329  * If i variables are a subset of this bucket, then the missing values are
330  * supposed to be at 0.
331  *
332  * @param value The value to compute.
333  * @throw SizeError Raised if the bucket is empty.
334  */
335  GUM_SCALAR _computeValue_(const Instantiation& value) const;
336 
337  /// Flag used to know if changes has occurred in the bucket since last
338  /// computation.
339  mutable bool _changed_;
340 
341  /// This table is used to keep the last value computed for an instantiation
342  /// when the value are computed on the fly.
343  mutable HashTable< const Instantiation*, GUM_SCALAR > _slavesValue_;
344 
345  /// The class name.
346  std::string _name_;
347  };
348 
349 
350 #ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
351  extern template class MultiDimBucket< double >;
352 #endif
353 
354 
355 } /* namespace gum */
356 
357 #include <agrum/tools/multidim/implementations/multiDimBucket_tpl.h>
358 
359 #endif /* GUM_MULTIDIM_BUCKET_H */