aGrUM 3.1.1
a C++ library for (probabilistic) graphical models
instantiation.cpp
Go to the documentation of this file.
1/****************************************************************************
2 * This file is part of the aGrUM/pyAgrum library. *
3 * *
4 * Copyright (c) 2005-2026 by *
5 * - Pierre-Henri WUILLEMIN(_at_LIP6) *
6 * - Christophe GONZALES(_at_AMU) *
7 * *
8 * The aGrUM/pyAgrum library is free software; you can redistribute it *
9 * and/or modify it under the terms of either : *
10 * *
11 * - the GNU Lesser General Public License as published by *
12 * the Free Software Foundation, either version 3 of the License, *
13 * or (at your option) any later version, *
14 * - the MIT license (MIT), *
15 * - or both in dual license, as here. *
16 * *
17 * (see https://agrum.gitlab.io/articles/dual-licenses-lgplv3mit.html) *
18 * *
19 * This aGrUM/pyAgrum library is distributed in the hope that it will be *
20 * useful, but WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
21 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES MERCHANTABILITY or FITNESS *
22 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
25 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
26 * OTHER DEALINGS IN THE SOFTWARE. *
27 * *
28 * See LICENCES for more details. *
29 * *
30 * SPDX-FileCopyrightText: Copyright 2005-2026 *
31 * - Pierre-Henri WUILLEMIN(_at_LIP6) *
32 * - Christophe GONZALES(_at_AMU) *
33 * SPDX-License-Identifier: LGPL-3.0-or-later OR MIT *
34 * *
35 * Contact : info_at_agrum_dot_org *
36 * homepage : http://agrum.gitlab.io *
37 * gitlab : https://gitlab.com/agrumery/agrum *
38 * *
39 ****************************************************************************/
40
41
48
51
52#ifdef GUM_NO_INLINE
54#endif /* GUM_NO_INLINE */
55
56namespace gum {
57
58 // Default constructor
60 GUM_CONSTRUCTOR(Instantiation);
61 }
62
63 // destructor
65 GUM_DESTRUCTOR(Instantiation);
66 // unregister the Instantiation from its _master_
67
68 if (_master_) _master_->unregisterSlave(*this);
69 }
70
72 // for speed issues
73 GUM_ASSERT(master != nullptr);
74
76 _vars_.resize(v.size());
77 _vals_.reserve(v.size());
78 // fill the instantiation
79
80 for (const auto var: v)
81 _add_(*var);
82
83 actAsSlave(master->getMasterRef());
84 }
85
86 // constructor for a Instantiation contained into a MultiDimInterface
88 // for debugging purposes
89 GUM_CONSTRUCTOR(Instantiation);
90 _init_(&d);
91 }
92
94 // for debugging purposes
95 GUM_CONSTRUCTOR(Instantiation);
96 _init_(const_cast< MultiDimAdressable* >(&d));
97 }
98
99 // constructor for a Instantiation contained into a MultiDimInterface
101 // for debugging purposes
102 GUM_CONSTRUCTOR(Instantiation);
103
104 if (d) _init_(d);
105 }
106
107 // constructor for a Instantiation contained into a MultiDimInterface this
108 // constructor is needed in order to allow creation of Instantiation(this) in
109 // MultiDimAdressable and below
111 // for debugging purposes
112 GUM_CONSTRUCTOR(Instantiation);
113
114 if (const_d) _init_(const_cast< MultiDimAdressable* >(const_d));
115 }
116
117 // copy constructor
118 Instantiation::Instantiation(const Instantiation& aI, const bool notifyMaster) :
120 // for debugging purposes
121 GUM_CONS_CPY(Instantiation);
122 // copy the content of aI
123 _vars_ = aI._vars_;
124 _vals_ = aI._vals_;
126
127 if (aI._master_ && notifyMaster) actAsSlave(*aI._master_);
128 }
129
130 // operator=
132 if (_master_) {
133 if (!aI.isMaster(_master_)) { // aI as the same master.
134 if (nbrDim() != aI.nbrDim()) { GUM_ERROR(OperationNotAllowed, "in slave Instantiation") }
135
136 for (Idx i = 0; i < nbrDim(); i++) {
137 if ((!contains(aI.variable(i))) || (!aI.contains(variable(i)))) {
138 GUM_ERROR(OperationNotAllowed, "in slave Instantiation")
139 }
140 }
141 }
142
143 setVals(aI);
144 } else {
145 // copy the content of aI
146 _vars_ = aI._vars_;
147 _vals_ = aI._vals_;
149
150 if (aI._master_) actAsSlave(*aI._master_);
151 }
152
153 return *this;
154 }
155
156 // Gives a string version of a Instantiation
157 std::string Instantiation::toString() const {
158 std::string sstr;
159 // check if the value of the instantiation is correct
160
161 if (_overflow_) sstr = "<invalid>";
162
163 sstr += "<";
164
165 bool first = true;
166
167 for (const auto var: _vars_) {
168 if (!first) sstr += "|";
169
170 first = false;
171 sstr += var->name();
172 sstr += ":";
173 sstr += var->label(val(*var));
174 }
175
176 sstr += ">";
177
178 return sstr;
179 }
180
181 // give a Id value for Hamming distance
183 Idx res = 0;
184
185 for (const auto var: _vars_)
186 res += val(*var);
187
188 return res;
189 }
190
193 const Instantiation& external) {
194 for (const auto& elt: map) {
195 const DiscreteVariable& var = *elt.second;
196
197 if (!external.contains(*elt.first)) {
198 GUM_ERROR(NotFound, var.name() << " : missing variable in external instantiation")
199 }
200
201 Idx val = external.val(*elt.first);
202
203 if (!contains(var)) {
204 GUM_ERROR(NotFound, var.name() << " : missing variable in instantiation")
205 }
206
207 chgVal(var, val);
208 }
209 }
210
211 void Instantiation::_masterChangeNotification_(Idx varPos, Idx newVal, Idx oldVal) const {
212 if (_master_) _master_->changeNotification(*this, _vars_[varPos], oldVal, newVal);
213 }
214
216 if (_master_) _master_->setFirstNotification(*this);
217 }
218
220 if (_master_) _master_->setIncNotification(*this);
221 }
222
224 if (_master_) _master_->setLastNotification(*this);
225 }
226
228 if (_master_) _master_->setDecNotification(*this);
229 }
230
231 // deassociate the master MultiDimAdressable, if any
233 if (_master_) {
234 _master_->unregisterSlave(*this);
235 _master_ = nullptr;
236 }
237 return true;
238 }
239
240 // force the variables sequence order to be the same as the master one
242 if (m != _master_) { GUM_ERROR(OperationNotAllowed, "only master can do this") }
243
244 _reorder_(_master_->variablesSequence());
245 }
246
247 // erase new dim by master
249 if (m != _master_) { GUM_ERROR(OperationNotAllowed, "only master can do this") }
250
251 _erase_(v);
252
253 if (_master_) _master_->setChangeNotification(*this);
254 }
255
256 // tries to register the Instantiation to a MultiDimAdressable
258 // if _master_ : not allowed
259 if (_master_ != nullptr) { GUM_ERROR(OperationNotAllowed, "in slave Instantiation") }
260
261 _master_ = &aMD;
262
263 // perform the registration
264 if (aMD.registerSlave(*this)) {
265 return true;
266 } else {
267 _master_ = nullptr;
268 return false;
269 }
270 }
271
272 // an operator for user-friendly displaying the content of a Instantiation
273 std::ostream& operator<<(std::ostream& aStream, const Instantiation& i) {
274 aStream << i.toString();
275 return aStream;
276 }
277
279 // if _master_ : not allowed
280 if (_master_) { GUM_ERROR(OperationNotAllowed, "in slave Instantiation") }
281
282 // check if the variable already belongs to the tuple of variables
283 // of the Instantiation
284 if (_vars_.exists(&v)) {
285 GUM_ERROR(DuplicateElement, "Var <" << v.name() << "> already exists in this instantiation")
286 }
287
288 for (const auto& vv: _vars_) {
289 if (vv->name() == v.name()) {
291 "Var with name <" << v.name() << "> already exists in this instantiation");
292 }
293 }
294
295 // actually add the new dimension
296 _add_(v);
297 }
298
300 Size p = nbrDim();
301 if (p == 0) { _overflow_ = true; }
302
303 if (_overflow_) return;
304 p -= 1;
305 Idx cpt = 0;
306 // if we are in overflow, do nothing
307
308 // perform the increment
309 while (true) {
310 Idx v = _vals_[cpt];
311
312 if (v + 1 == _vars_[cpt]->domainSize()) {
313 _vals_[cpt] = 0;
314
315 if (cpt == p) {
316 _overflow_ = true;
318 return;
319 } else ++cpt;
320 } else {
321 ++_vals_[cpt];
322 break;
323 }
324 }
325
327 }
328
330 Size p = nbrDim();
331 if (p == 0) { _overflow_ = true; }
332
333 if (_overflow_) return;
334 p -= 1;
335 Idx cpt = 0;
336 // if we are in overflow, do nothing
337
338 // perform the increment
339 while (true) {
340 Idx v = _vals_[cpt];
341
342 if (v == 0) {
343 _vals_[cpt] = _vars_[cpt]->domainSize() - 1;
344
345 if (cpt == p) {
346 _overflow_ = true;
347
349
350 return;
351 } else ++cpt;
352 } else {
353 --_vals_[cpt];
354 break;
355 }
356 }
357
359 }
360
362 // if i is empty, overflow and do nothing
363 if (i.nbrDim() == 0) {
364 _overflow_ = true;
365 return;
366 }
367
368 // if we are in overflow, do nothing
369 if (_overflow_) return;
370
371 Size p = i.nbrDim() - 1;
372
373 Idx i_cpt = 0;
374
375 while (true) {
376 // verify that _vars_[cpt] belongs to i before incrementing its value
377 const DiscreteVariable& v = i.variable(i_cpt);
378
379 if (!contains(v)) {
380 if (i_cpt == p) {
381 _overflow_ = true;
382 return;
383 } else ++i_cpt;
384 } else {
385 Idx cpt = pos(v);
386 Idx iv = _vals_[cpt];
387
388 if (iv + 1 == _vars_[cpt]->domainSize()) {
389 _chgVal_(cpt, 0);
390
391 if (i_cpt == p) {
392 _overflow_ = true;
393 return;
394 } else ++i_cpt;
395 } else {
396 _chgVal_(cpt, iv + 1);
397 return;
398 }
399 }
400 }
401 }
402
404 if (i.nbrDim() == 0) {
405 _overflow_ = true;
406 return;
407 }
408 Size p = i.nbrDim() - 1;
409 Idx i_cpt = 0;
410 // if we are in overflow, do nothing
411
412 if (_overflow_) return;
413
414 while (true) {
415 // verify that _vars_[cpt] belongs to i before incrementing its value
416 const DiscreteVariable& v = i.variable(i_cpt);
417
418 if (!contains(v)) {
419 if (i_cpt == p) {
420 _overflow_ = true;
421 return;
422 } else ++i_cpt;
423 } else {
424 Idx cpt = pos(v);
425 Idx iv = _vals_[cpt];
426
427 if (iv == 0) {
428 _chgVal_(cpt, _vars_[cpt]->domainSize() - 1);
429
430 if (i_cpt == p) {
431 _overflow_ = true;
432 return;
433 } else ++i_cpt;
434 } else {
435 _chgVal_(cpt, iv - 1);
436 return;
437 }
438 }
439 }
440 }
441
443 if (nbrDim() == 0) {
444 _overflow_ = true;
445 return;
446 }
447 Size p = nbrDim() - 1;
448 Idx cpt = 0;
449 // if we are in overflow, do nothing
450
451 if (_overflow_) return;
452
453 while (true) {
454 if (i.contains(_vars_[cpt])) {
455 if (cpt == p) {
456 _overflow_ = true;
457 return;
458 } else ++cpt;
459 } else {
460 Idx v = _vals_[cpt];
461
462 if (v + 1 == _vars_[cpt]->domainSize()) {
463 _chgVal_(cpt, 0);
464
465 if (cpt == p) {
466 _overflow_ = true;
467 return;
468 } else ++cpt;
469 } else {
470 _chgVal_(cpt, v + 1);
471 return;
472 }
473 }
474 }
475 }
476
478 if (nbrDim() == 0) {
479 _overflow_ = true;
480 return;
481 }
482 Size p = nbrDim() - 1;
483 Idx cpt = 0;
484 // if we are in overflow, do nothing
485
486 if (_overflow_) return;
487
488 while (true) {
489 if (i.contains(_vars_[cpt])) {
490 if (cpt == p) {
491 _overflow_ = true;
492 return;
493 } else ++cpt;
494 } else {
495 Idx v = _vals_[cpt];
496
497 if (v == 0) {
498 _chgVal_(cpt, _vars_[cpt]->domainSize() - 1);
499
500 if (cpt == p) {
501 _overflow_ = true;
502 return;
503 } else ++cpt;
504 } else {
505 _chgVal_(cpt, v - 1);
506 return;
507 }
508 }
509 }
510 }
511
513 if (nbrDim() == 0) {
514 _overflow_ = true;
515 return;
516 }
517 Size p = nbrDim() - 1;
518 Idx cpt = 0;
519 // if we are in overflow, do nothing
520
521 if (_overflow_) return;
522
523 while (true) {
524 if (_vars_[cpt] == &v) {
525 if (cpt == p) {
526 _overflow_ = true;
527 return;
528 } else ++cpt;
529 } else {
530 Idx iv = _vals_[cpt];
531
532 if (iv + 1 == _vars_[cpt]->domainSize()) {
533 _chgVal_(cpt, 0);
534
535 if (cpt == p) {
536 _overflow_ = true;
537 return;
538 } else ++cpt;
539 } else {
540 _chgVal_(cpt, iv + 1);
541 return;
542 }
543 }
544 }
545 }
546
548 if (nbrDim() == 0) {
549 _overflow_ = true;
550 return;
551 }
552 Size p = nbrDim() - 1;
553 Idx cpt = 0;
554 // if we are in overflow, do nothing
555
556 if (_overflow_) return;
557
558 while (true) {
559 if (_vars_[cpt] == &v) {
560 if (cpt == p) {
561 _overflow_ = true;
562 return;
563 } else ++cpt;
564 } else {
565 Idx iv = _vals_[cpt];
566
567 if (iv == 0) {
568 _chgVal_(cpt, _vars_[cpt]->domainSize() - 1);
569
570 if (cpt == p) {
571 _overflow_ = true;
572 return;
573 } else ++cpt;
574 } else {
575 _chgVal_(cpt, iv - 1);
576 return;
577 }
578 }
579 }
580 }
581} /* namespace gum */
Base class for discrete random variable.
Exception : a similar element already exists.
The class for generic Hash Tables.
Definition hashTable.h:640
Class for assigning/browsing values to tuples of discrete variables.
Instantiation & chgVal(const DiscreteVariable &v, Idx newval)
Assign newval to variable v in the Instantiation.
void inc()
Operator increment.
void incOut(const Instantiation &i)
Operator increment for the variables not in i.
void decIn(const Instantiation &i)
Operator decrement for the variables in i.
void synchronizeWithMaster(const MultiDimAdressable *m)
Force the variables sequence to be the same as the master one.
void _masterIncNotification_() const
Sequence< const DiscreteVariable * > _vars_
The tuple of variables to be instantiated.
bool actAsSlave(MultiDimAdressable &aMD)
Tries to register the Instantiation to a MultiDimAdressable.
bool isMaster(const MultiDimAdressable *m) const
Indicates whether m is the master of this instantiation.
void _masterFirstNotification_() const
~Instantiation() override
Destructor.
void dec()
Operator decrement.
Instantiation & setVals(const Instantiation &i)
Assign the values from i in the Instantiation.
void add(const DiscreteVariable &v) final
Adds a new variable in the Instantiation.
std::vector< Idx > _vals_
The current instantiation: the value of the tuple.
bool _overflow_
Indicates whether the current value of the tuple is valid when we loop sufficiently over values of th...
void _reorder_(const Sequence< const DiscreteVariable * > &v)
Reorder vars of this instantiation giving the order in v.
Idx pos(const DiscreteVariable &v) const final
Returns the position of the variable v.
Size domainSize() const final
Returns the product of the variable's domain size in the Instantiation.
bool contains(const DiscreteVariable &v) const final
Indicates whether a given variable belongs to the Instantiation.
Instantiation()
Default constructor: creates an empty tuple.
void incNotVar(const DiscreteVariable &v)
Operator increment for vars which are not v.
MultiDimAdressable * _master_
The master, if any, contains precisely the set of variables to be instantiated.
void _init_(MultiDimAdressable *master)
Initialize this Instantiation.
Idx hamming() const
Returns the hamming distance of this instantiation.
void _erase_(const DiscreteVariable &v)
Removes a variable from the sequence of vars.
void _masterLastNotification_() const
void _add_(const DiscreteVariable &v)
Adds a new var to the sequence of vars.
void _masterDecNotification_() const
void incIn(const Instantiation &i)
Operator increment for the variables in i.
Idx val(Idx i) const
Returns the current value of the variable at position i.
void setValsFrom(const HashTable< const DiscreteVariable *, const DiscreteVariable * > &map, const Instantiation &external)
Assign the values of external in *this, using map as a bijection between external and this variables.
void _masterChangeNotification_(Idx varPos, Idx newVal, Idx oldVal) const
void _chgVal_(Idx varPos, Idx newVal)
Modifies internally the value of a given variable of the sequence.
void decOut(const Instantiation &i)
Operator decrement for the variables not in i.
std::string toString() const
Give a string version of instantiation.
const DiscreteVariable & variable(Idx i) const final
Returns the variable at position i in the tuple.
void decNotVar(const DiscreteVariable &v)
Operator decrement for vars which are not v.
Idx nbrDim() const final
Returns the number of variables in the Instantiation.
bool forgetMaster()
Deassociate the master MultiDimAdressable, if any.
void eraseWithMaster(const MultiDimAdressable *m, const DiscreteVariable &v)
Call Instantiation:: erase(const DiscreteVariable&) by master.
Instantiation & operator=(const Instantiation &aI)
Copy operator.
Exception: at least one argument passed to a function is not what was expected.
Abstract base class for all multi dimensionnal addressable.
virtual bool registerSlave(Instantiation &i)=0
Register i as a slave of this MultiDimAdressable.
virtual MultiDimAdressable & getMasterRef()=0
In order to insure the dereference for decorators, we need to virtualize the access to master pointer...
Interface for all classes addressing in a multiDim fashion.
virtual const Sequence< const DiscreteVariable * > & variablesSequence() const =0
Returns a const ref to the sequence of DiscreteVariable*.
Exception : the element we looked for cannot be found.
Exception : operation not allowed.
Size size() const noexcept
Returns the size of the sequence.
The generic class for storing (ordered) sequences of objects.
Definition sequence.h:994
const std::string & name() const
returns the name of the variable
#define GUM_ERROR(type, msg)
Definition exceptions.h:76
std::size_t Size
In aGrUM, hashed values are unsigned long int.
Definition types.h:74
Size Idx
Type for indexes.
Definition types.h:79
Header files of gum::Instantiation.
Inline implemenation of gum::Instantiation.
Headers for the abstract base class for all multi dimensionnal containers.
gum is the global namespace for all aGrUM entities
Definition agrum.h:46
std::ostream & operator<<(std::ostream &stream, const AVLTree< Val, Cmp > &tree)
display the content of a tree