aGrUM  0.20.2
a C++ library for (probabilistic) graphical models
idCondSet.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 /** @file
23  * @brief A class used by learning caches to represent uniquely sets of variables
24  *
25  * @author Christophe GONZALES(@AMU) and Pierre-Henri WUILLEMIN(@LIP6)
26  */
27 #ifndef GUM_LEARNING_ID_SET_H
28 #define GUM_LEARNING_ID_SET_H
29 
30 #include <iostream>
31 #include <sstream>
32 #include <string>
33 #include <type_traits>
34 #include <utility>
35 #include <vector>
36 
37 #include <agrum/agrum.h>
38 #include <agrum/tools/core/sequence.h>
39 #include <agrum/tools/graphs/graphElements.h>
40 
41 namespace gum {
42 
43  namespace learning {
44 
45 
46  template < template < typename > class ALLOC >
47  class IdCondSet;
48 
49 
50  /** @class IdCondSetIterator
51  * @brief The iterators for IdSets
52  * @headerfile idCondSet.h <agrum/BN/learning/scores_and_tests/idSet.h>
53  * @ingroup learning_scores
54  */
55  template < template < typename > class ALLOC = std::allocator >
56  class IdCondSetIterator {
57  public:
58  /// types for STL compliance
59  /// @{
60  using iterator_category = std::forward_iterator_tag;
61  using value_type = NodeId;
62  using reference = NodeId&;
63  using const_reference = const NodeId&;
64  using pointer = NodeId*;
65  using const_pointer = const NodeId*;
66  using difference_type = std::ptrdiff_t;
67  /// @}
68 
69 
70  // ##########################################################################
71  /// @name Constructors / Destructors
72  // ##########################################################################
73  /// @{
74 
75  /// default constructor
76  /** @return an iterator pointing toward nothing. */
77  IdCondSetIterator();
78 
79  /// Constructor for a begin
80  /** @param idset The IdCondSet to iterate over. */
81  IdCondSetIterator(const IdCondSet< ALLOC >& idset);
82 
83  /// Copy constructor.
84  IdCondSetIterator(const IdCondSetIterator< ALLOC >& from);
85 
86  /// move constructor
87  IdCondSetIterator(IdCondSetIterator< ALLOC >&& from);
88 
89  /// destructor
90  virtual ~IdCondSetIterator();
91 
92  /// @}
93 
94 
95  // ##########################################################################
96  /// @name Operators
97  // ##########################################################################
98  /// @{
99 
100  /// copy operator
101  IdCondSetIterator< ALLOC >&
102  operator=(const IdCondSetIterator< ALLOC >& from);
103 
104  /// move operator
105  IdCondSetIterator< ALLOC >& operator=(IdCondSetIterator< ALLOC >&& from);
106 
107  /** @brief Gives access to the content of the iterator.
108  * @throw UndefinedIteratorValue Raised if the iterator points to nothing.
109  * @return Returns the content of the iterator.
110  */
111  NodeId operator*() const;
112 
113  /// Checks whether two iterators point toward different elements.
114  bool operator!=(const IdCondSetIterator< ALLOC >& from) const;
115 
116  /// Checks whether two iterators point toward the same elements.
117  bool operator==(const IdCondSetIterator< ALLOC >& from) const;
118 
119  /** @brief Makes the iterator point to the next element in the IdCondSet
120  *
121  * @code
122  * for (iter = idset.begin(); iter != idset.end(); ++iter) {}
123  * @endcode
124  *
125  * The above loop is guaranteed to parse the whole IdCondSet as long as no
126  * element is added to or deleted from the IdCondSet while being in the loop.
127  *
128  * @return Returns this gum::IdCondSetIterator.
129  */
130  IdCondSetIterator< ALLOC >& operator++();
131 
132  /**
133  * @brief Makes the iterator point to i elements further in the IdCondSet
134  * @param i The number of steps to move the iterator.
135  * @return Returns this gum::IdCondSetIterator.
136  */
137  IdCondSetIterator< ALLOC >& operator+=(const std::size_t i);
138 
139  /**
140  * @brief Returns a new iterator pointing to i further elements in the
141  * IdCondSet
142  * @param i The number of steps to move the iterator.
143  * @return Returns a new gum::IdCondSetIterator.
144  */
145  IdCondSetIterator< ALLOC > operator+(const std::size_t i);
146 
147  /// @}
148 
149 
150  // ##########################################################################
151  /// @name Accessors / Modifiers
152  // ##########################################################################
153  /// @{
154 
155  /**
156  * @brief Returns the position of the iterator in the IdCondSet.
157  * @return Returns the position of the iterator in the IdCondSet.
158  * @throw UndefinedIteratorValue Raised on end()
159  */
160  std::size_t pos() const;
161 
162  /// @}
163 
164 
165 #ifndef DOXYGEN_SHOULD_SKIP_THIS
166 
167  private:
168  /// a pointer on the sequence stored in the IdCondSet
169  const Sequence< NodeId, ALLOC< NodeId > >* seq__{nullptr};
170 
171  /// The index in the IdCondSet's sequence where the iterator is pointing.
172  std::size_t index__{std::size_t(0)};
173 
174 
175  /// places the index to the end of the sequence
176  void gotoEnd__();
177 
178  friend class IdCondSet< ALLOC >;
179 
180 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
181  };
182 
183 
184  /** @class IdCondSet
185  * @brief A class for storing a pair of sets of NodeIds, the second one
186  * corresponding to a conditional set.
187  * @headerfile idSet.h <agrum/BN/learning/scores_and_tests/idSet.h>
188  * @ingroup learning_scores
189  *
190  * IdCondSets are used by learning caches to store pairs of sets of nodes,
191  * the second ones represent typically conditional sets.
192  * This is useful for storing in hashtables the scores assigned to sets
193  * of nodes given other nodes. NodeSets are actually not well suited for
194  * this purpose because their implementations makes the computation of their
195  * hash values quite difficult. IdCondSets fix this issue.
196  */
197  template < template < typename > class ALLOC = std::allocator >
198  class IdCondSet: private ALLOC< NodeId > {
199  public:
200  /// type for the allocators passed in arguments of methods
201  using allocator_type = ALLOC< NodeId >;
202 
203  using iterator = IdCondSetIterator< ALLOC >;
204  using const_iterator = IdCondSetIterator< ALLOC >;
205  using iterator_safe = IdCondSetIterator< ALLOC >;
206  using const_iterator_safe = IdCondSetIterator< ALLOC >;
207 
208  // ##########################################################################
209  /// @name Constructors / Destructors
210  // ##########################################################################
211  /// @{
212 
213  /// default constructor
214  IdCondSet(const allocator_type& alloc = allocator_type());
215 
216  /// default constructor with no variable on the left side
217  /** @param ids the set of variables
218  * @param rhs_ids indicate whether the ids are on the right side of the
219  * conditioning bar or not
220  * @param ordered_ids indicates whether the ids in rhs_ids should be
221  * considered as an ordered set or an unordered set
222  * @param alloc the allocator used to store the data in the IdCondSet */
223  IdCondSet(const std::vector< NodeId, ALLOC< NodeId > >& ids,
224  const bool rhs_ids,
225  const bool ordered_ids,
226  const allocator_type& alloc = allocator_type());
227 
228  /// default constructor with one variable on the left side
229  /** @param var1 the variable on the left side of the conditioning bar
230  * @param rhs_ids the set of variables on the right side of the
231  * conditioning bar
232  * @param ordered_rhs_ids indicates whether the ids in rhs_ids should be
233  * considered as an ordered set or an unordered set
234  * @param alloc the allocator used to store the data in the IdCondSet */
235  IdCondSet(NodeId var1,
236  const std::vector< NodeId, ALLOC< NodeId > >& rhs_ids,
237  const bool ordered_rhs_ids = false,
238  const allocator_type& alloc = allocator_type());
239 
240  /// default constructor with two variables on the left side
241  /** @param var1 the 1st variable on the left side of the conditioning bar
242  * @param var2 the 2nd variable on the left side of the conditioning bar
243  * @param rhs_ids the set of variables on the right side of the
244  * conditioning bar
245  * @param ordered_lhs_vars a Boolean indicating whether {var1,var2} should
246  * be considered as an ordered set or not. Typically, in an independence
247  * test, this set is unordered. When set to false,
248  * @param ordered_rhs_ids indicates whether the ids in rhs_ids should be
249  * considered as an ordered set or an unordered set
250  * @param ordered_rhs_ids
251  * @param alloc the allocator used to store the data in the IdCondSet */
252  IdCondSet(NodeId var1,
253  NodeId var2,
254  const std::vector< NodeId, ALLOC< NodeId > >& rhs_ids,
255  const bool ordered_lhs_vars,
256  const bool ordered_rhs_ids = false,
257  const allocator_type& alloc = allocator_type());
258 
259  /// default constructor with three variables on the left side
260  /** @param var1 the 1st variable on the left side of the conditioning bar
261  * @param var2 the 2nd variable on the left side of the conditioning bar
262  * @param var3 the 3rd variable on the left side of the conditioning bar
263  * @param rhs_ids the set of variables on the right side of the
264  * conditioning bar
265  * @param ordered_vars a Boolean indicating whether {var1,var2,var3}
266  * should be considered as an ordered set or not.
267  * @param ordered_rhs_ids indicates whether the ids in rhs_ids should be
268  * considered as an ordered set or an unordered set
269  * @param alloc the allocator used to store the data in the IdCondSet */
270  IdCondSet(NodeId var1,
271  NodeId var2,
272  NodeId var3,
273  const std::vector< NodeId, ALLOC< NodeId > >& rhs_ids,
274  const bool ordered_lhs_vars,
275  const bool ordered_rhs_ids = false,
276  const allocator_type& alloc = allocator_type());
277 
278  /// copy constructor
279  IdCondSet(const IdCondSet< ALLOC >& from);
280 
281  /// copy constructor with a given allocator
282  IdCondSet(const IdCondSet< ALLOC >& from, const allocator_type& alloc);
283 
284  /// move constructor
285  IdCondSet(IdCondSet< ALLOC >&& from);
286 
287  /// move constructor with a given allocator
288  IdCondSet(IdCondSet< ALLOC >&& from, const allocator_type& alloc);
289 
290  /// virtual copy constructor
291  virtual IdCondSet< ALLOC >* clone() const;
292 
293  /// virtual copy constructor with a given allocator
294  virtual IdCondSet< ALLOC >* clone(const allocator_type& alloc) const;
295 
296  /// destructor
297  virtual ~IdCondSet();
298 
299  /// @}
300 
301 
302  // ##########################################################################
303  /// @name Operators
304  // ##########################################################################
305  /// @{
306 
307  /// copy operator
308  IdCondSet< ALLOC >& operator=(const IdCondSet< ALLOC >& from);
309 
310  /// move operator
311  IdCondSet< ALLOC >& operator=(IdCondSet< ALLOC >&& from);
312 
313  /// returns the node id stored at a given index
314  NodeId operator[](const std::size_t index) const;
315 
316  /// returns true if both sets are equal
317  bool operator==(const IdCondSet< ALLOC >& from) const;
318 
319  /// returns true if the sets differ
320  bool operator!=(const IdCondSet< ALLOC >& from) const;
321 
322  /// @}
323 
324 
325  // ##########################################################################
326  /// @name Iterators
327  // ##########################################################################
328  /// @{
329 
330  /**
331  * @brief Returns a safe begin iterator.
332  * @return Returns a safe begin iterator.
333  */
334  iterator_safe beginSafe() const;
335 
336  /**
337  * @brief Returns the safe end iterator.
338  * @return Returns the safe end iterator.
339  */
340  const iterator_safe& endSafe() const;
341 
342  /**
343  * @brief Returns an unsafe begin iterator.
344  * @return Returns an unsafe begin iterator.
345  */
346  iterator begin() const;
347 
348  /**
349  * @brief Returns the unsafe end iterator.
350  * @return Returns the unsafe end iterator.
351  */
352  const iterator& end() const;
353 
354  /// @}
355 
356 
357  // ##########################################################################
358  /// @name Accessors / Modifiers
359  // ##########################################################################
360  /// @{
361 
362  /// returns the set of ids
363  const Sequence< NodeId, ALLOC< NodeId > >& ids() const;
364 
365  /// returns the idSet at the right hand side of the conditioning bar
366  IdCondSet< ALLOC > conditionalIdCondSet() const;
367 
368  /// returns the number of left hand side ids
369  std::size_t nbLHSIds() const;
370 
371  /// returns the number of right hand side ids
372  std::size_t nbRHSIds() const;
373 
374  /// indicates whether the IdCondSet contains the IdCondSet passed in argument
375  bool contains(const IdCondSet< ALLOC >& set) const;
376 
377  /// removes all the nodes from the IdCondSet
378  void clear();
379 
380  /// returns the number of variables (both left and right hand side)
381  std::size_t size() const;
382 
383  /// returns the position of a given node in the IdCondSet
384  /** @throw NotFound Raised if the element does not exist. */
385  std::size_t pos(const NodeId id) const;
386 
387  /// indicates whether a given id is contained in the IdCondSet
388  bool exists(const NodeId id) const;
389 
390  /// erase a node in the idset
391  /** If the element cannot be found, the function does nothing. In
392  * particular, it throws no exception. */
393  void erase(const NodeId id);
394 
395  /// indicates whether the idset contains a non-empty conditioning set
396  bool hasConditioningSet() const;
397 
398  /// indicates whether the IdCondSet contains some nodes or not
399  bool empty() const;
400 
401  /// returns the content of the set as a string
402  std::string toString() const;
403 
404  /// returns the allocator used
405  allocator_type getAllocator() const;
406 
407  /// @}
408 
409 
410 #ifndef DOXYGEN_SHOULD_SKIP_THIS
411 
412  private:
413  /// the ordered set of ids on the right side of the conditioning bar
414  Sequence< NodeId, ALLOC< NodeId > > ids__;
415 
416  /// the number of left ids
417  std::size_t nb_lhs_ids__{std::size_t(0)};
418 
419  /// Stores the end iterator for fast access.
420  IdCondSetIterator< ALLOC > end_safe__;
421 
422 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
423  };
424 
425 
426  /// the display operator
427  template < template < typename > class ALLOC >
428  std::ostream& operator<<(std::ostream& stream,
429  const IdCondSet< ALLOC >& idset);
430 
431  } /* namespace learning */
432 
433 
434  /// the hash function for idSets
435  template < template < typename > class ALLOC >
436  class HashFunc< learning::IdCondSet< ALLOC > >:
437  public HashFuncBase< learning::IdCondSet< ALLOC > > {
438  public:
439  /**
440  * @brief Returns the value of a key as a Size.
441  * @param key The value to return as a Size.
442  * @return Returns the value of a key as a Size.
443  */
444  static Size castToSize(const learning::IdCondSet< ALLOC >& key);
445 
446  /// computes the hashed value of a key
447  virtual Size
448  operator()(const learning::IdCondSet< ALLOC >& key) const override final;
449  };
450 
451 
452 } /* namespace gum */
453 
454 
455 // always include the template implementation
456 #include <agrum/tools/stattests/idCondSet_tpl.h>
457 
458 #endif /* GUM_LEARNING_ID_SET_H */