aGrUM  0.20.3
a C++ library for (probabilistic) graphical models
instantiation_inl.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 Inline implemenation of gum::Instantiation.
25  *
26  * @author Pierre-Henri WUILLEMIN(@LIP6) & Christophe GONZALES(@AMU)
27  */
28 
29 #include <agrum/tools/multidim/implementations/multiDimAdressable.h>
30 
31 namespace gum {
32 
33  // indicates whether a given variable belongs to the Instantiation
34  INLINE bool Instantiation::contains(const DiscreteVariable& v) const { return _vars_.exists(&v); }
35 
36  INLINE bool Instantiation::contains(const std::string& name) const {
37  return contains(variable(name));
38  }
39 
40  // indicates whether a given variable belongs to the Instantiation
41  INLINE bool Instantiation::contains(const DiscreteVariable* v) const { return _vars_.exists(v); }
42 
43  // modifies internally the value of a given variable of the sequence
46  _vals_[varPos] = newVal;
47 
49  }
50 
51  // modifies the value of a given variable of the sequence (external function)
52  INLINE Instantiation& Instantiation::chgVal(const DiscreteVariable& v, Idx newVal) {
53  try {
54  // check that the variable does belong to the instantiation and that the
55  // new
56  // value is possible.
57  Idx varPos = _vars_.pos(&v); // throws NotFound if v doesn't belong to this
58 
59  if (newVal >= v.domainSize()) { GUM_ERROR(OutOfBounds, "") }
60 
61  // if we were in overflow, indicate that we are not anymore
62  _overflow_ = false;
63 
65 
66  return *this;
67  } catch (NotFound&) {
68  std::string name = "instantiation does not contain this DiscreteVariable: ";
70  }
71  }
72 
74  try {
75  // check that the variable does belong to the instantiation and that the
76  // new
77  // value is possible.
78  Idx varPos = _vars_.pos(v); // throws NotFound if v doesn't belong to this
79 
80  if (newVal >= v->domainSize()) { GUM_ERROR(OutOfBounds, "") }
81 
82  // if we were in overflow, indicate that we are not anymore
83  _overflow_ = false;
84 
86 
87  return *this;
88  } catch (NotFound&) {
89  std::string name = "instantiation does not contain this DiscreteVariable: ";
91  }
92  }
93 
94  // modifies the value of a given variable of the sequence (external function)
96  // check that the variable does belong to the instantiation and that the new
97  // value is possible.
98  if (_vals_.size() <= varPos) { GUM_ERROR(NotFound, "") }
99 
100  if (newVal >= _vars_[varPos]->domainSize()) { GUM_ERROR(OutOfBounds, "") }
101 
102  // if we were in overflow, indicate that we are not anymore
103  _overflow_ = false;
104 
106 
107  return *this;
108  }
109 
111  return chgVal(variable(var), newVal);
112  }
113 
115  const auto& vv = variable(var);
116  Idx pos = vv.index(newVal);
117  return chgVal(vv, pos);
118  }
119 
120  // adds a new var to the sequence of vars
122  // if _master_ : not allowed
123  if (_master_) { GUM_ERROR(OperationNotAllowed, "in slave Instantiation") }
124 
125  // check if the variable already belongs to the tuple of variables
126  // of the Instantiation
127  if (_vars_.exists(&v)) {
128  GUM_ERROR(DuplicateElement, "Var <" << v.name() << "> already exists in this instantiation")
129  }
130 
131  for (const auto& vv: _vars_) {
132  if (vv->name() == v.name()) {
134  "Var with name <" << v.name() << "> already exists in this instantiation");
135  }
136  }
137 
138  // actually add the new dimension
139  _add_(v);
140  }
141 
142  // removes a variable from the sequence of vars
144  // if _master_ : not allowed
145  if (_master_) { GUM_ERROR(OperationNotAllowed, "in slave Instantiation") }
146 
147  // check that the variable does actually belong to the Instantiation
148  if (!_vars_.exists(&v)) { GUM_ERROR(NotFound, "Var does not exist in this instantiation") }
149 
150  // actually delete the dimension
151  _erase_(v);
152  }
153 
155 
156  // removes everything
158  if (_master_) { GUM_ERROR(OperationNotAllowed, "in slave Instantiation") }
159 
160  _vars_.clear();
161  _vals_.clear();
162  }
163 
164  // @brief returns the product of the size of the domains of the variables
165  // belonging to the matrix
167  Size s = 1;
168 
169  for (const auto var: _vars_)
170  s *= var->domainSize();
171 
172  return s;
173  }
174 
175  // returns the index of a var
176  INLINE Idx Instantiation::pos(const DiscreteVariable& k) const { return _vars_.pos(&k); }
177 
178  // returns the number of vars in the sequence
179  INLINE Idx Instantiation::nbrDim() const { return _vars_.size(); }
180 
181  // returns the current value of a given variable
183  if (i >= _vals_.size()) {
184  GUM_ERROR(NotFound, i << " is out of bound index for the instantiation.")
185  }
186 
187  return _vals_[i];
188  }
189 
190  // returns the current value of a given variable
192  return _vals_[_vars_.pos(&var)];
193  }
194  // returns the current value of a given variable
195  INLINE Idx Instantiation::val(const std::string& name) const { return val(variable(name)); }
196 
197 
198  // returns the current value of a given variable
200  return _vals_[_vars_.pos(pvar)];
201  }
202 
203  // returns the variable at position i in the tuple
204  INLINE const DiscreteVariable& Instantiation::variable(Idx i) const { return *(_vars_.atPos(i)); }
205  // returns the variable with name in the tuple
207  for (const auto& v: _vars_) {
208  if (v->name() == name) return *v;
209  }
210 
211  GUM_ERROR(NotFound, "'" << name << "' can not be found in the instantiation.")
212  }
213 
214  // indicates whether the current value of the tuple is correct or not
215  INLINE bool Instantiation::inOverflow() const { return _overflow_; }
216 
217  // end() just is a synonym for inOverflow()
218  INLINE bool Instantiation::end() const { return inOverflow(); }
219 
220  // rend() just is a synonym for inOverflow()
221  INLINE bool Instantiation::rend() const { return inOverflow(); }
222 
223  // indicates that the current value is correct even if it should be in
224  // overflow
226 
227  // alias for unsetOverflow
229 
230  // operator ++
232  Size p = nbrDim();
233  if (p == 0) { _overflow_ = true; }
234 
235  if (_overflow_) return;
236  p -= 1;
237  Idx cpt = 0;
238  // if we are in overflow, do nothing
239 
240  // perform the increment
241  while (true) {
242  Idx v = _vals_[cpt];
243 
244  if (v + 1 == _vars_[cpt]->domainSize()) {
245  _vals_[cpt] = 0;
246 
247  if (cpt == p) {
248  _overflow_ = true;
250  return;
251  } else
252  ++cpt;
253  } else {
254  ++_vals_[cpt];
255  break;
256  }
257  }
258 
260  }
261 
262  // operator --
264  Size p = nbrDim();
265  if (p == 0) { _overflow_ = true; }
266 
267  if (_overflow_) return;
268  p -= 1;
269  Idx cpt = 0;
270  // if we are in overflow, do nothing
271 
272  // perform the increment
273  while (true) {
274  Idx v = _vals_[cpt];
275 
276  if (v == 0) {
277  _vals_[cpt] = _vars_[cpt]->domainSize() - 1;
278 
279  if (cpt == p) {
280  _overflow_ = true;
281 
283 
284  return;
285  } else
286  ++cpt;
287  } else {
288  --_vals_[cpt];
289  break;
290  }
291  }
292 
294  }
295 
296  // operator ++
298  inc();
299  return *this;
300  }
301 
302  // operator --
304  dec();
305  return *this;
306  }
307 
308  // operator +=
310  for (Idx i = 0; i < depl; i++)
311  inc();
312 
313  return *this;
314  }
315 
316  // operator -=
318  for (Idx i = 0; i < depl; i++)
319  dec();
320 
321  return *this;
322  }
323 
324  // assign the (0,0,...) first value to the tuple of the Instantiation.
326  _overflow_ = false;
327  Size s = nbrDim();
328 
329  for (Idx p = 0; p < s; ++p)
330  _vals_[p] = 0;
331 
333  }
334 
335  // put the (D1-1,D2-1,...) last value in the Instantiation
337  _overflow_ = false;
338  Size s = nbrDim();
339 
340  for (Idx p = 0; p < s; ++p)
341  _vals_[p] = _vars_[p]->domainSize() - 1;
342 
344  }
345 
346  // operator ++ limited only to the variables in i
348  // if i is empty, overflow and do nothing
349  if (i.nbrDim() == 0) {
350  _overflow_ = true;
351  return;
352  }
353 
354  // if we are in overflow, do nothing
355  if (_overflow_) return;
356 
357  Size p = i.nbrDim() - 1;
358 
359  Idx i_cpt = 0;
360 
361  while (true) {
362  // verify that _vars_[cpt] belongs to i before incrementing its value
363  const DiscreteVariable& v = i.variable(i_cpt);
364 
365  if (!contains(v)) {
366  if (i_cpt == p) {
367  _overflow_ = true;
368  return;
369  } else
370  ++i_cpt;
371  } else {
372  Idx cpt = pos(v);
373  Idx iv = _vals_[cpt];
374 
375  if (iv + 1 == _vars_[cpt]->domainSize()) {
376  _chgVal_(cpt, 0);
377 
378  if (i_cpt == p) {
379  _overflow_ = true;
380  return;
381  } else
382  ++i_cpt;
383  } else {
384  _chgVal_(cpt, iv + 1);
385  return;
386  }
387  }
388  }
389  }
390 
391  // operator -- limited only to the variables in i
393  Size p = i.nbrDim() - 1;
394  Idx i_cpt = 0;
395  // if we are in overflow, do nothing
396 
397  if (_overflow_) return;
398 
399  while (true) {
400  // verify that _vars_[cpt] belongs to i before incrementing its value
401  const DiscreteVariable& v = i.variable(i_cpt);
402 
403  if (!contains(v)) {
404  if (i_cpt == p) {
405  _overflow_ = true;
406  return;
407  } else
408  ++i_cpt;
409  } else {
410  Idx cpt = pos(v);
411  Idx iv = _vals_[cpt];
412 
413  if (iv == 0) {
414  _chgVal_(cpt, _vars_[cpt]->domainSize() - 1);
415 
416  if (i_cpt == p) {
417  _overflow_ = true;
418  return;
419  } else
420  ++i_cpt;
421  } else {
422  _chgVal_(cpt, iv - 1);
423  return;
424  }
425  }
426  }
427  }
428 
429  // reorder vars in *this
431 
432  // put the (0,0,...) first value in the Instantiation for the variables in i
434  _overflow_ = false;
435  Idx s = nbrDim();
436 
437  for (Size p = 0; p < s; ++p)
438  if (i.contains(_vars_[p])) _chgVal_(p, 0);
439  }
440 
441  // change values with those in i
443  _overflow_ = false;
444  Idx s = i.nbrDim();
445 
446  for (Size p = 0; p < s; ++p)
447  if (contains(i.variable(p))) _chgVal_(pos(i.variable(p)), i.val(p));
448 
449  return *this;
450  }
451 
452  // put the (D1-1,D2-1,...) lastvalue in the Instantiation for variables in i
454  _overflow_ = false;
455  Idx s = nbrDim();
456 
457  for (Size p = 0; p < s; ++p)
458  if (i.contains(_vars_[p])) _chgVal_(p, _vars_[p]->domainSize() - 1);
459  }
460 
461  // operator ++ for the variables not in i
463  Size p = nbrDim() - 1;
464  Idx cpt = 0;
465  // if we are in overflow, do nothing
466 
467  if (_overflow_) return;
468 
469  while (true) {
470  if (i.contains(_vars_[cpt])) {
471  if (cpt == p) {
472  _overflow_ = true;
473  return;
474  } else
475  ++cpt;
476  } else {
477  Idx v = _vals_[cpt];
478 
479  if (v + 1 == _vars_[cpt]->domainSize()) {
480  _chgVal_(cpt, 0);
481 
482  if (cpt == p) {
483  _overflow_ = true;
484  return;
485  } else
486  ++cpt;
487  } else {
488  _chgVal_(cpt, v + 1);
489  return;
490  }
491  }
492  }
493  }
494 
495  // operator -- for the variables not in i
497  Size p = nbrDim() - 1;
498  Idx cpt = 0;
499  // if we are in overflow, do nothing
500 
501  if (_overflow_) return;
502 
503  while (true) {
504  if (i.contains(_vars_[cpt])) {
505  if (cpt == p) {
506  _overflow_ = true;
507  return;
508  } else
509  ++cpt;
510  } else {
511  Idx v = _vals_[cpt];
512 
513  if (v == 0) {
514  _chgVal_(cpt, _vars_[cpt]->domainSize() - 1);
515 
516  if (cpt == p) {
517  _overflow_ = true;
518  return;
519  } else
520  ++cpt;
521  } else {
522  _chgVal_(cpt, v - 1);
523  return;
524  }
525  }
526  }
527  }
528 
529  // put the (0,0,...) first val in the Instantiation for the variables not in
530  // i
532  _overflow_ = false;
533  Idx s = nbrDim();
534 
535  for (Size p = 0; p < s; ++p)
536  if (!i.contains(_vars_[p])) _chgVal_(p, 0);
537  }
538 
539  // put the (D1-1,D2-1,...) lastvalue in the Instantiation for vars not in i
541  _overflow_ = false;
542  Idx s = nbrDim();
543 
544  for (Size p = 0; p < s; ++p)
545  if (!i.contains(_vars_[p])) _chgVal_(p, _vars_[p]->domainSize() - 1);
546  }
547 
548  // operator ++ for vars which are not v.
550  Size p = nbrDim() - 1;
551  Idx cpt = 0;
552  // if we are in overflow, do nothing
553 
554  if (_overflow_) return;
555 
556  while (true) {
557  if (_vars_[cpt] == &v) {
558  if (cpt == p) {
559  _overflow_ = true;
560  return;
561  } else
562  ++cpt;
563  } else {
564  Idx iv = _vals_[cpt];
565 
566  if (iv + 1 == _vars_[cpt]->domainSize()) {
567  _chgVal_(cpt, 0);
568 
569  if (cpt == p) {
570  _overflow_ = true;
571  return;
572  } else
573  ++cpt;
574  } else {
575  _chgVal_(cpt, iv + 1);
576  return;
577  }
578  }
579  }
580  }
581 
582  // operator -- for vars which are not v.
584  Size p = nbrDim() - 1;
585  Idx cpt = 0;
586  // if we are in overflow, do nothing
587 
588  if (_overflow_) return;
589 
590  while (true) {
591  if (_vars_[cpt] == &v) {
592  if (cpt == p) {
593  _overflow_ = true;
594  return;
595  } else
596  ++cpt;
597  } else {
598  Idx iv = _vals_[cpt];
599 
600  if (iv == 0) {
601  _chgVal_(cpt, _vars_[cpt]->domainSize() - 1);
602 
603  if (cpt == p) {
604  _overflow_ = true;
605  return;
606  } else
607  ++cpt;
608  } else {
609  _chgVal_(cpt, iv - 1);
610  return;
611  }
612  }
613  }
614  }
615 
616  // assign the (0,0,...) first value to variables which are not v.
618  _overflow_ = false;
619  Idx s = nbrDim();
620 
621  for (Size p = 0; p < s; ++p) {
622  if (_vars_[p] == &v) {
623  Idx oldval = _vals_[p];
624  setFirst();
625  _chgVal_(p, oldval);
626  return;
627  }
628  }
629 
630  setFirst();
631  }
632 
633  // put the (D1-1,D2-1,...) lastvalue in the Instantiation for vars != v
635  _overflow_ = false;
636  Idx s = nbrDim();
637 
638  for (Size p = 0; p < s; ++p) {
639  if (_vars_[p] == &v) {
640  Idx oldval = _vals_[p];
641  setLast();
642  _chgVal_(p, oldval);
643  return;
644  }
645  }
646 
647  setLast();
648  }
649 
650  // operator ++ for variable v only
652  // get the position of the variable
653  Idx cpt = _vars_.pos(&v);
654  // if we are in overflow, do nothing
655 
656  if (_overflow_) return;
657 
658  Idx p = _vals_[cpt];
659 
660  if (p + 1 == v.domainSize()) {
661  _chgVal_(cpt, 0);
662  _overflow_ = true;
663  } else {
664  _chgVal_(cpt, p + 1);
665  }
666  }
667 
668  // operator -- for variable v only
670  // get the position of the variable
671  Idx cpt = _vars_.pos(&v);
672  // if we are in overflow, do nothing
673 
674  if (_overflow_) return;
675 
676  Idx p = _vals_[cpt];
677 
678  if (p == 0) {
679  _chgVal_(cpt, v.domainSize() - 1);
680  _overflow_ = true;
681  } else {
682  _chgVal_(cpt, p - 1);
683  }
684  }
685 
686  // assign the first value in the Instantiation for var v.
688  _overflow_ = false;
689  _chgVal_(_vars_.pos(&v), 0);
690  }
691 
692  // assign the last value to var v.
694  _overflow_ = false;
695  _chgVal_(_vars_.pos(&v), v.domainSize() - 1);
696  }
697 
698  // indicates whether the Instantiation has a master MultiDimAdressable
699  INLINE bool Instantiation::isSlave() const { return (_master_ != nullptr); }
700 
701  // indicates wether the MultiDimAdressable* m is the master
702  INLINE bool Instantiation::isMaster(const MultiDimAdressable* m) const { return (_master_ == m); }
703 
704  // indicates wether the MultiDimAdressable* m is the master
705  INLINE bool Instantiation::isMaster(const MultiDimAdressable& m) const { return isMaster(&m); }
706 
707  // returns the sequence of DiscreteVariable
709  return _vars_;
710  }
711 
712 
713  // replace 2 vars in the Instantiation
715  if (i == j) return;
716 
717  _vars_.swap(i, j);
718 
719  Idx v;
720  v = _vals_[i];
721  _vals_[i] = _vals_[j];
722  _vals_[j] = v;
723  }
724 
725  // reordering
726  INLINE
728  if (_master_ != nullptr) {
729  GUM_ERROR(OperationNotAllowed, "Reordering impossible in slave instantiation")
730  }
731 
733  }
734 
735  INLINE
737  Idx max = original.size();
738  Idx position = 0;
739  for (Idx i = 0; i < max; ++i) {
740  const DiscreteVariable* pv = original.atPos(i);
741 
742  if (contains(pv)) {
743  auto p = pos(*pv);
744  GUM_ASSERT(p >= position); // this var should not be
745  // already placed.
746  _swap_(position, p);
747  position++;
748  }
749  }
750  }
751 
752 
753  // add new dim by master
755  if (m != _master_) { GUM_ERROR(OperationNotAllowed, "only master can do this") }
756 
757  _add_(v);
758  }
759 
760 
761  // adds a new var to the sequence of vars
763  _vars_.insert(&v);
764  _vals_.push_back(0);
765  _overflow_ = false;
766  }
767 
768  // removes a variable from the sequence of vars
770  // get the position of the variable
771  Idx pos = _vars_.pos(&v);
772  _vars_.erase(&v);
773  _vals_.erase(_vals_.begin() + pos);
774  }
775 
776  // is this empty ?
777  INLINE bool Instantiation::empty() const { return _vals_.empty(); }
778 
779  // Replace x by y.
782  }
783 
784  /// returns a hashed key for hash tables the keys of which are represented
785  /// by vectors of Idx
787  Size h = Size(0);
788  for (const DiscreteVariable* k:
789  key.variablesSequence()) // k are unique only by address (not by name)
790  h += HashFunc< const DiscreteVariable* >::castToSize(k) * Size(key.val(*k));
791 
792  return h;
793  }
794 
795  /// returns a hashed key for hash tables the keys of which are represented
796  /// by vectors of Idx
798  return castToSize(key) & this->hash_mask_;
799  }
800 
802  if (inOverflow() && other.inOverflow()) return true;
803  if (other.nbrDim() != nbrDim()) return false;
804  for (const auto& k: variablesSequence()) {
805  if (!other.contains(k)) return false;
806  if (val(*k) != other.val(*k)) return false;
807  }
808  return true;
809  }
810 } /* namespace gum */
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:643