aGrUM  0.20.2
a C++ library for (probabilistic) graphical models
multiDimBucket.h
Go to the documentation of this file.
1 /**
2  *
3  * Copyright 2005-2020 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* >&
266  multidims() const;
267 
268  protected:
269  virtual void commitMultipleChanges_() override;
270 
271  /**
272  * @warning This will raise en exception, you should directly use the get()
273  * and operator[]() methods.
274  */
275  virtual GUM_SCALAR& get_(const Instantiation& i) const override;
276 
277  virtual void replace_(const DiscreteVariable* x,
278  const DiscreteVariable* y) override;
279 
280  private:
281  /// The number of element allowed in bucket__.
282  Size bufferSize__;
283 
284  /// Bijection between instantiations registered on this and
285  /// their equivalent on bucket__
286  Bijection< Instantiation*, Instantiation* > instantiations__;
287 
288  /// The result table of this bucket.
289  MultiDimArray< GUM_SCALAR >* bucket__;
290 
291  /// The set of MultiDimContainer in this bucket.
292  mutable HashTable< const MultiDimContainer< GUM_SCALAR >*, Instantiation* >
293  multiDims__;
294 
295  /// The set of all variables of the multidims in this bucket.
296  Set< const DiscreteVariable* > allVariables__;
297 
298  /// Instantiation over all variable in this
299  mutable Instantiation allVarsInst__;
300 
301  /**
302  * @brief Add a variable to allVariables__, and do nothing if var is already
303  * in
304  * the set.
305  * @param var The DiscreteVariable to add.
306  */
307  void addVariable__(const DiscreteVariable* var);
308 
309  /**
310  * @brief Erase a variable from allVariables__ if no other multidimensional
311  * table
312  * uses it in this bucket.
313  * @param var The DiscreteVariable to remove.
314  */
315  void eraseVariable__(const DiscreteVariable* var);
316 
317  /**
318  * @brief Initialize the internal buffer.
319  *
320  * This method delete bucket__ after saving it's slave instantiations.
321  */
322  void initializeBuffer__();
323 
324  /**
325  * @brief Clean the buffer and switch it's instantiation to this bucket.
326  */
327  void eraseBuffer__();
328 
329  /**
330  * @brief Compute the value of the final table of this bucket given i.
331  *
332  * If i variables are a subset of this bucket, then the missing values are
333  * supposed to be at 0.
334  *
335  * @param value The value to compute.
336  * @throw SizeError Raised if the bucket is empty.
337  */
338  GUM_SCALAR computeValue__(const Instantiation& value) const;
339 
340  /// Flag used to know if changes has occurred in the bucket since last
341  /// computation.
342  mutable bool changed__;
343 
344  /// This table is used to keep the last value computed for an instantiation
345  /// when the value are computed on the fly.
346  mutable HashTable< const Instantiation*, GUM_SCALAR > slavesValue__;
347 
348  /// The class name.
349  std::string name__;
350  };
351 
352 
353 #ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
354  extern template class MultiDimBucket< double >;
355 #endif
356 
357 
358 } /* namespace gum */
359 
360 #include <agrum/tools/multidim/implementations/multiDimBucket_tpl.h>
361 
362 #endif /* GUM_MULTIDIM_BUCKET_H */