aGrUM  0.20.2
a C++ library for (probabilistic) graphical models
idCondSet_tpl.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 Template implementation of idSets
24  *
25  * @author Christophe GONZALES(@AMU) and Pierre-Henri WUILLEMIN(@LIP6)
26  */
27 
28 #ifndef DOXYGEN_SHOULD_SKIP_THIS
29 
30 
31 namespace gum {
32 
33  namespace learning {
34 
35 
36  /// default constructor
37  template < template < typename > class ALLOC >
38  INLINE IdCondSetIterator< ALLOC >::IdCondSetIterator() {
40  }
41 
42 
43  /// Constructor for a begin
44  template < template < typename > class ALLOC >
46  const IdCondSet< ALLOC >& idset) :
47  seq__(&(idset.ids())) {
49  }
50 
51 
52  /// Copy constructor.
53  template < template < typename > class ALLOC >
55  const IdCondSetIterator< ALLOC >& from) :
56  seq__(from.seq__),
59  }
60 
61 
62  /// move constructor
63  template < template < typename > class ALLOC >
66  seq__(from.seq__),
69  }
70 
71 
72  /// destructor
73  template < template < typename > class ALLOC >
76  }
77 
78 
79  /// places the index to the end of the sequence
80  template < template < typename > class ALLOC >
82  if (seq__ != nullptr)
83  index__ = seq__->size();
84  else
85  index__ = std::size_t(0);
86  }
87 
88 
89  /// copy operator
90  template < template < typename > class ALLOC >
92  const IdCondSetIterator< ALLOC >& from) {
93  seq__ = from.seq__;
95  return *this;
96  }
97 
98 
99  /// move operator
100  template < template < typename > class ALLOC >
103  seq__ = from.seq__;
104  index__ = from.index__;
105  return *this;
106  }
107 
108 
109  /// Gives access to the content of the iterator.
110  template < template < typename > class ALLOC >
112  return seq__->operator[](index__);
113  }
114 
115 
116  /// Checks whether two iterators point toward different elements.
117  template < template < typename > class ALLOC >
119  const IdCondSetIterator< ALLOC >& from) const {
120  return (index__ != from.index__) || (seq__ != from.seq__);
121  }
122 
123 
124  /// Checks whether two iterators point toward the same elements.
125  template < template < typename > class ALLOC >
127  const IdCondSetIterator< ALLOC >& from) const {
128  return !operator!=(from);
129  }
130 
131 
132  /// Makes the iterator point to the next element in the IdCondSet
133  template < template < typename > class ALLOC >
135  ++index__;
136  return *this;
137  }
138 
139 
140  /// Makes the iterator point to i elements further in the IdCondSet
141  template < template < typename > class ALLOC >
143  IdCondSetIterator< ALLOC >::operator+=(const std::size_t i) {
144  index__ += i;
145  return *this;
146  }
147 
148 
149  /// Returns a new iterator pointing to i further elements in the IdCondSet
150  template < template < typename > class ALLOC >
152  IdCondSetIterator< ALLOC >::operator+(const std::size_t i) {
153  IdCondSetIterator< ALLOC > res(*this);
154  res += i;
155  return res;
156  }
157 
158 
159  /// Returns the position of the iterator in the IdCondSet
160  template < template < typename > class ALLOC >
161  std::size_t IdCondSetIterator< ALLOC >::pos() const {
162  if (seq__ == nullptr)
164  "The IdCondSet is empty, so its iterators have no position");
165  if (index__ >= seq__->size())
167  "the IdCondSet iterator has no position because it reached "
168  "the set's end.");
169  return index__;
170  }
171 
172 
173  /// ==========================================================================
174  /// ==========================================================================
175 
176 
177  /// returns the allocator used by the translator
178  template < template < typename > class ALLOC >
179  INLINE typename IdCondSet< ALLOC >::allocator_type
180  IdCondSet< ALLOC >::getAllocator() const {
181  return *this;
182  }
183 
184 
185  /// default constructor
186  template < template < typename > class ALLOC >
188  const typename IdCondSet< ALLOC >::allocator_type& alloc) :
189  ALLOC< NodeId >(alloc),
190  end_safe__(*this) {
192  }
193 
194 
195  /// default constructor with no variable on the left side
196  template < template < typename > class ALLOC >
198  const std::vector< NodeId, ALLOC< NodeId > >& ids,
199  const bool rhs_ids,
200  const bool ordered_ids,
201  const typename IdCondSet< ALLOC >::allocator_type& alloc) :
202  ALLOC< NodeId >(alloc),
203  end_safe__(*this) {
204  ids__.resize(ids.size());
205 
206  // if the rhs_ids should be considered as unordered, we sort them by
207  // increasing order so that we can compare easily two different rhs_ids
208  if (!ordered_ids) {
209  std::vector< NodeId, ALLOC< NodeId > > vect(ids);
210  std::sort(vect.begin(), vect.end());
211  for (const auto id: vect)
212  ids__ << id;
213  } else {
214  for (const auto id: ids)
215  ids__ << id;
216  }
217 
218  if (!rhs_ids) nb_lhs_ids__ = ids__.size();
219 
220  // update the end iterator
222 
224  }
225 
226 
227  /// default constructor with one variable on the left side
228  template < template < typename > class ALLOC >
230  NodeId var1,
231  const std::vector< NodeId, ALLOC< NodeId > >& rhs_ids,
232  const bool ordered_rhs_ids,
233  const typename IdCondSet< ALLOC >::allocator_type& alloc) :
234  ALLOC< NodeId >(alloc),
235  nb_lhs_ids__(std::size_t(1)), end_safe__(*this) {
236  ids__.resize(rhs_ids.size() + std::size_t(1));
237  ids__ << var1;
238 
239  // if the rhs_ids should be considered as unordered, we sort them by
240  // increasing order so that we can compare easily two different rhs_ids
241  if (!ordered_rhs_ids) {
243  std::sort(vect.begin(), vect.end());
244  for (const auto id: vect)
245  ids__ << id;
246  } else {
247  for (const auto id: rhs_ids)
248  ids__ << id;
249  }
250 
251  // update the end iterator
253 
255  }
256 
257 
258  /// default constructor with two variables on the left side
259  template < template < typename > class ALLOC >
261  NodeId var1,
262  NodeId var2,
263  const std::vector< NodeId, ALLOC< NodeId > >& rhs_ids,
264  const bool ordered_lhs_vars,
265  const bool ordered_rhs_ids,
266  const typename IdCondSet< ALLOC >::allocator_type& alloc) :
267  ALLOC< NodeId >(alloc),
268  nb_lhs_ids__(std::size_t(2)), end_safe__(*this) {
269  ids__.resize(rhs_ids.size() + std::size_t(2));
270 
271  // if the variables on the left side are unordered, sort them by
272  // increasing order
273  if (!ordered_lhs_vars && (var1 > var2)) std::swap(var1, var2);
274  ids__ << var1;
275  ids__ << var2;
276 
277  // if the rhs_ids should be considered as unordered, we sort them by
278  // increasing order so that we can compare easily two different rhs_ids
279  if (!ordered_rhs_ids) {
281  std::sort(vect.begin(), vect.end());
282  for (const auto id: vect)
283  ids__ << id;
284  } else {
285  for (const auto id: rhs_ids)
286  ids__ << id;
287  }
288 
289  // update the end iterator
291 
293  }
294 
295 
296  /// default constructor with three variables on the left side
297  template < template < typename > class ALLOC >
299  NodeId var1,
300  NodeId var2,
301  NodeId var3,
302  const std::vector< NodeId, ALLOC< NodeId > >& rhs_ids,
303  const bool ordered_lhs_vars,
304  const bool ordered_rhs_ids,
305  const typename IdCondSet< ALLOC >::allocator_type& alloc) :
306  ALLOC< NodeId >(alloc),
307  nb_lhs_ids__(std::size_t(3)), end_safe__(*this) {
308  ids__.resize(rhs_ids.size() + std::size_t(3));
309 
310  // if the variables on the left side are unordered, sort them by
311  // increasing order
312  if (!ordered_lhs_vars) {
313  if (var1 > var2) std::swap(var1, var2);
314  if (var1 > var3) std::swap(var1, var3);
315  if (var2 > var3) std::swap(var2, var3);
316  }
317  ids__ << var1;
318  ids__ << var2;
319  ids__ << var3;
320 
321  // if the rhs_ids should be considered as unordered, we sort them by
322  // increasing order so that we can compare easily two different rhs_ids
323  if (!ordered_rhs_ids) {
325  std::sort(vect.begin(), vect.end());
326  for (const auto id: vect)
327  ids__ << id;
328  } else {
329  for (const auto id: rhs_ids)
330  ids__ << id;
331  }
332 
333  // update the end iterator
335 
337  }
338 
339 
340  /// copy constructor with a given allocator
341  template < template < typename > class ALLOC >
343  const IdCondSet< ALLOC >& from,
344  const typename IdCondSet< ALLOC >::allocator_type& alloc) :
345  ALLOC< NodeId >(alloc),
349  }
350 
351 
352  /// copy constructor
353  template < template < typename > class ALLOC >
356 
357 
358  /// move constructor with a given allocator
359  template < template < typename > class ALLOC >
361  IdCondSet< ALLOC >&& from,
362  const typename IdCondSet< ALLOC >::allocator_type& alloc) :
363  ALLOC< NodeId >(alloc),
365  end_safe__(*this) {
368  }
369 
370 
371  /// move constructor
372  template < template < typename > class ALLOC >
375 
376 
377  /// virtual copy constructor with a given allocator
378  template < template < typename > class ALLOC >
380  const typename IdCondSet< ALLOC >::allocator_type& alloc) const {
383  try {
384  allocator.construct(new_set, *this, alloc);
385  } catch (...) {
387  throw;
388  }
389 
390  return new_set;
391  }
392 
393 
394  /// virtual copy constructor
395  template < template < typename > class ALLOC >
396  IdCondSet< ALLOC >* IdCondSet< ALLOC >::clone() const {
397  return clone(this->getAllocator());
398  }
399 
400 
401  /// destructor
402  template < template < typename > class ALLOC >
405  }
406 
407 
408  /// copy operator
409  template < template < typename > class ALLOC >
411  IdCondSet< ALLOC >::operator=(const IdCondSet< ALLOC >& from) {
412  if (this != &from) {
413  ids__ = from.ids__;
416  }
417  return *this;
418  }
419 
420 
421  /// move operator
422  template < template < typename > class ALLOC >
425  if (this != &from) {
426  ids__ = std::move(from.ids__);
429  }
430  return *this;
431  }
432 
433 
434  /// returns the id stored at a given index
435  template < template < typename > class ALLOC >
436  INLINE NodeId IdCondSet< ALLOC >::operator[](const std::size_t index) const {
437  return ids__.atPos(index);
438  }
439 
440 
441  /// returns true if both sets are equal
442  template < template < typename > class ALLOC >
443  INLINE bool
444  IdCondSet< ALLOC >::operator==(const IdCondSet< ALLOC >& from) const {
445  if (nb_lhs_ids__ != from.nb_lhs_ids__) return false;
446 
447  const std::size_t size = ids__.size();
448 
449  if (size != from.ids__.size()) return false;
450 
451  for (std::size_t i = std::size_t(0); i < size; ++i) {
452  if (ids__[i] != from.ids__[i]) return false;
453  }
454 
455  return true;
456  }
457 
458 
459  /// returns true if the sets differ
460  template < template < typename > class ALLOC >
461  INLINE bool
462  IdCondSet< ALLOC >::operator!=(const IdCondSet< ALLOC >& from) const {
463  return !operator==(from);
464  }
465 
466 
467  /// Returns a safe begin iterator.
468  template < template < typename > class ALLOC >
469  INLINE typename IdCondSet< ALLOC >::iterator_safe
470  IdCondSet< ALLOC >::beginSafe() const {
471  return IdCondSetIterator< ALLOC >(*this);
472  }
473 
474 
475  /// Returns the safe end iterator.
476  template < template < typename > class ALLOC >
477  INLINE const typename IdCondSet< ALLOC >::iterator_safe&
478  IdCondSet< ALLOC >::endSafe() const {
479  return end_safe__;
480  }
481 
482 
483  /// Returns an unsafe begin iterator.
484  template < template < typename > class ALLOC >
485  INLINE typename IdCondSet< ALLOC >::iterator
486  IdCondSet< ALLOC >::begin() const {
487  return IdCondSetIterator< ALLOC >(*this);
488  }
489 
490 
491  /// Returns the unsafe end iterator.
492  template < template < typename > class ALLOC >
493  INLINE const typename IdCondSet< ALLOC >::iterator&
494  IdCondSet< ALLOC >::end() const {
495  return end_safe__;
496  }
497 
498 
499  /// returns the set of ids contained in the object
500  template < template < typename > class ALLOC >
501  INLINE const Sequence< NodeId, ALLOC< NodeId > >&
502  IdCondSet< ALLOC >::ids() const {
503  return ids__;
504  }
505 
506 
507  /// returns the idSet at the right hand side of the conditioning bar
508  template < template < typename > class ALLOC >
510  IdCondSet< ALLOC > set(this->getAllocator());
511  const std::size_t size = ids__.size();
512  for (std::size_t i = nb_lhs_ids__; i < size; ++i)
513  set.ids__ << ids__[i];
515  return set;
516  }
517 
518 
519  /// erase a node in the idset
520  template < template < typename > class ALLOC >
521  void IdCondSet< ALLOC >::erase(const NodeId id) {
522  // search for id in Sequence ids__
523  const std::size_t size = ids__.size();
524  std::size_t pos = std::size_t(0);
525  for (; pos < size; ++pos) {
526  if (ids__[pos] == id) break;
527  }
528 
529  // if we found the id, remove it
530  if (pos < size) {
532  if (pos < nb_lhs_ids__) --nb_lhs_ids__;
534  }
535  }
536 
537 
538  /// returns the content of the set as a string
539  template < template < typename > class ALLOC >
540  std::string IdCondSet< ALLOC >::toString() const {
542 
543  str << '{';
544  bool deja = false;
545 
546  for (std::size_t i = std::size_t(0); i < nb_lhs_ids__; ++i) {
547  if (deja)
548  str << " , ";
549  else
550  deja = true;
551  str << ids__[i];
552  }
553 
554  deja = false;
555  for (auto iter = ids__.begin() + nb_lhs_ids__; iter != ids__.end(); ++iter) {
556  if (deja)
557  str << " , ";
558  else {
559  deja = true;
560  str << " | ";
561  }
562  str << *iter;
563  }
564 
565  str << '}';
566 
567  return str.str();
568  }
569 
570 
571  /// returns the number of left hand side ids
572  template < template < typename > class ALLOC >
573  INLINE std::size_t IdCondSet< ALLOC >::nbLHSIds() const {
574  return nb_lhs_ids__;
575  }
576 
577 
578  /// returns the number of right hand side ids
579  template < template < typename > class ALLOC >
580  INLINE std::size_t IdCondSet< ALLOC >::nbRHSIds() const {
581  return ids__.size() - nb_lhs_ids__;
582  }
583 
584 
585  /// indicates whether the IdCondSet contains the IdCondSet passed in argument
586  template < template < typename > class ALLOC >
587  bool IdCondSet< ALLOC >::contains(const IdCondSet< ALLOC >& set) const {
588  if (set.ids__.size() > ids__.size()) return false;
589  for (const auto node: set.ids__) {
590  if (!ids__.exists(node)) return false;
591  }
592  return true;
593  }
594 
595 
596  /// removes all the nodes from the IdCondSet
597  template < template < typename > class ALLOC >
598  INLINE void IdCondSet< ALLOC >::clear() {
599  ids__.clear();
600  nb_lhs_ids__ = std::size_t(0);
602  }
603 
604 
605  /// returns the number of variables (both left and right hand side)
606  template < template < typename > class ALLOC >
607  INLINE std::size_t IdCondSet< ALLOC >::size() const {
608  return ids__.size();
609  }
610 
611 
612  /// returns the position of a given node in the IdCondSet
613  template < template < typename > class ALLOC >
614  INLINE std::size_t IdCondSet< ALLOC >::pos(const NodeId id) const {
615  return ids__.pos(id);
616  }
617 
618 
619  /// indicates whether a given id is contained in the IdCondSet
620  template < template < typename > class ALLOC >
621  INLINE bool IdCondSet< ALLOC >::exists(const NodeId id) const {
622  return ids__.exists(id);
623  }
624 
625 
626  /// indicates whether the idset contains a non-empty conditioning set
627  template < template < typename > class ALLOC >
628  INLINE bool IdCondSet< ALLOC >::hasConditioningSet() const {
629  return nb_lhs_ids__ != ids__.size();
630  }
631 
632 
633  /// indicates whether the IdCondSet contains some nodes or not
634  template < template < typename > class ALLOC >
635  INLINE bool IdCondSet< ALLOC >::empty() const {
636  return ids__.empty();
637  }
638 
639 
640  // the display operator
641  template < template < typename > class ALLOC >
643  const IdCondSet< ALLOC >& idset) {
644  return stream << idset.toString();
645  }
646 
647  } /* namespace learning */
648 
649 
650  // Returns the value of a key as a Size.
651  template < template < typename > class ALLOC >
652  Size HashFunc< learning::IdCondSet< ALLOC > >::castToSize(
653  const learning::IdCondSet< ALLOC >& key) {
654  Size h = Size(key.nbLHSIds());
655  const Sequence< NodeId, ALLOC< NodeId > >& vect = key.ids();
656  const std::size_t size = vect.size();
657 
658  std::size_t i = std::size_t(0);
659  while (i < size) {
660  const Size id = Size(vect[i]);
661  ++i;
662  h += Size(i) * id;
663  }
664 
665  return h;
666  }
667 
668 
669  // the hash function for idSets
670  template < template < typename > class ALLOC >
671  INLINE Size HashFunc< learning::IdCondSet< ALLOC > >::operator()(
672  const learning::IdCondSet< ALLOC >& key) const {
673  return (castToSize(key) * HashFuncConst::gold) & this->hash_mask_;
674  }
675 
676 } /* namespace gum */
677 
678 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:669
Database(const std::string &filename, const BayesNet< GUM_SCALAR > &bn, const std::vector< std::string > &missing_symbols)