aGrUM 3.0.0
a C++ library for (probabilistic) graphical models
instantiation_inl.h
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#pragma once
42
43
50
52#include <agrum/base/multidim/instantiation.h> // to ease IDE parser
53
54namespace gum {
55 // indicates whether a given variable belongs to the Instantiation
56 INLINE bool Instantiation::contains(const DiscreteVariable& v) const { return _vars_.exists(&v); }
57
58 INLINE bool Instantiation::contains(std::string_view name) const {
59 for (const auto& v: _vars_) {
60 if (v->name() == name) return true;
61 }
62 return false;
63 }
64
65 // indicates whether a given variable belongs to the Instantiation
66 INLINE bool Instantiation::contains(const DiscreteVariable* v) const { return _vars_.exists(v); }
67
68 // modifies internally the value of a given variable of the sequence
69 INLINE void Instantiation::_chgVal_(Idx varPos, Idx newVal) {
70 Idx oldVal = _vals_[varPos];
71 _vals_[varPos] = newVal;
72
73 _masterChangeNotification_(varPos, newVal, oldVal);
74 }
75
76 // modifies the value of a given variable of the sequence (external function)
78 // check that the variable does belong to the instantiation and that the
79 // new value is possible.
80 auto pPos = _vars_.tryPos(&v);
81 if (!pPos) {
82 std::string name = "instantiation does not contain this DiscreteVariable: ";
83 GUM_ERROR(NotFound, name + v.name())
84 }
85
86 Idx varPos = *pPos;
87
88 if (newVal >= v.domainSize()) { GUM_ERROR(OutOfBounds, "") }
89
90 // if we were in overflow, indicate that we are not anymore
91 _overflow_ = false;
92
93 _chgVal_(varPos, newVal);
94
95 return *this;
96 }
97
98 // modifies the value of a given variable of the sequence (external function)
99 INLINE Instantiation& Instantiation::chgVal(Idx varPos, Idx newVal) {
100 // check that the variable does belong to the instantiation and that the new
101 // value is possible.
102 if (_vals_.size() <= varPos) { GUM_ERROR(NotFound, "") }
103
104 if (newVal >= _vars_[varPos]->domainSize()) { GUM_ERROR(OutOfBounds, "") }
105
106 // if we were in overflow, indicate that we are not anymore
107 _overflow_ = false;
108
109 _chgVal_(varPos, newVal);
110
111 return *this;
112 }
113
114 INLINE Instantiation& Instantiation::chgVal(std::string_view var, Idx newVal) {
115 return chgVal(variable(var), newVal);
116 }
117
118 INLINE Instantiation& Instantiation::chgVal(std::string_view var, std::string_view newVal) {
119 const auto& vv = variable(var);
120 Idx pos = vv.index(newVal);
121 return chgVal(vv, pos);
122 }
123
124 // adds a new var to the sequence of vars
125
126 // removes a variable from the sequence of vars
128 // if _master_ : not allowed
129 if (_master_) { GUM_ERROR(OperationNotAllowed, "in slave Instantiation") }
130
131 // check that the variable does actually belong to the Instantiation
132 if (!_vars_.exists(&v)) { GUM_ERROR(NotFound, "Var does not exist in this instantiation") }
133
134 // actually delete the dimension
135 _erase_(v);
136 }
137
138 INLINE void Instantiation::erase(std::string_view name) { erase(variable(name)); }
139
140 // removes everything
141 INLINE void Instantiation::clear() {
142 if (_master_) { GUM_ERROR(OperationNotAllowed, "in slave Instantiation") }
143
144 _vars_.clear();
145 _vals_.clear();
146 }
147
148 // @brief returns the product of the size of the domains of the variables
149 // belonging to the matrix
151 Size s = 1;
152
153 for (const auto var: _vars_)
154 s *= var->domainSize();
155
156 return s;
157 }
158
159 // returns the index of a var
160 INLINE Idx Instantiation::pos(const DiscreteVariable& k) const { return _vars_.pos(&k); }
161
162 // returns the number of vars in the sequence
163 INLINE Idx Instantiation::nbrDim() const { return _vars_.size(); }
164
165 // returns the current value of a given variable
166 INLINE Idx Instantiation::val(Idx i) const {
167 if (i >= _vals_.size()) {
168 GUM_ERROR(NotFound, i << " is out of bound index for the instantiation.")
169 }
170
171 return _vals_[i];
172 }
173
174 // returns the current value of a given variable
175 INLINE Idx Instantiation::val(const DiscreteVariable& var) const {
176 return _vals_[_vars_.pos(&var)];
177 }
178
179 // returns the current value of a given variable
180 INLINE Idx Instantiation::val(std::string_view name) const { return val(variable(name)); }
181
182 // returns the current value of a given variable
184 return _vals_[_vars_.pos(pvar)];
185 }
186
187 // returns the variable at position i in the tuple
188 INLINE const DiscreteVariable& Instantiation::variable(Idx i) const { return *(_vars_.atPos(i)); }
189
190 // returns the variable with name in the tuple
191 INLINE const DiscreteVariable& Instantiation::variable(std::string_view name) const {
192 for (const auto& v: _vars_) {
193 if (v->name() == name) return *v;
194 }
195
196 GUM_ERROR(NotFound, "'" << name << "' can not be found in the instantiation.")
197 }
198
199 // indicates whether the current value of the tuple is correct or not
200 INLINE bool Instantiation::inOverflow() const { return _overflow_; }
201
202 // end() just is a synonym for inOverflow()
203 INLINE bool Instantiation::end() const { return inOverflow(); }
204
205 // rend() just is a synonym for inOverflow()
206 INLINE bool Instantiation::rend() const { return inOverflow(); }
207
208 // indicates that the current value is correct even if it should be in
209 // overflow
210 INLINE void Instantiation::unsetOverflow() { _overflow_ = false; }
211
212 // alias for unsetOverflow
213 INLINE void Instantiation::unsetEnd() { _overflow_ = false; }
214
215 // operator ++
216
217 // operator --
218
219 // operator ++
221 inc();
222 return *this;
223 }
224
225 // operator --
227 dec();
228 return *this;
229 }
230
231 // operator +=
233 for (Idx i = 0; i < depl; i++)
234 inc();
235
236 return *this;
237 }
238
239 // operator -=
241 for (Idx i = 0; i < depl; i++)
242 dec();
243
244 return *this;
245 }
246
247 // assign the (0,0,...) first value to the tuple of the Instantiation.
249 _overflow_ = false;
250 Size s = nbrDim();
251
252 for (Idx p = 0; p < s; ++p)
253 _vals_[p] = 0;
254
256 }
257
258 // put the (D1-1,D2-1,...) last value in the Instantiation
260 _overflow_ = false;
261 Size s = nbrDim();
262
263 for (Idx p = 0; p < s; ++p)
264 _vals_[p] = _vars_[p]->domainSize() - 1;
265
267 }
268
269 // operator ++ limited only to the variables in i
270
271 // operator -- limited only to the variables in i
272
273 // reorder vars in *this
275
276 // put the (0,0,...) first value in the Instantiation for the variables in i
278 _overflow_ = false;
279 Idx s = nbrDim();
280
281 for (Size p = 0; p < s; ++p)
282 if (i.contains(_vars_[p])) _chgVal_(p, 0);
283 }
284
285 // change values with those in i
287 _overflow_ = false;
288 Idx s = i.nbrDim();
289
290 for (Size p = 0; p < s; ++p) {
291 if (auto pPos = _vars_.tryPos(&i.variable(p))) _chgVal_(*pPos, i.val(p));
292 }
293
294 return *this;
295 }
296
297 // put the (D1-1,D2-1,...) lastvalue in the Instantiation for variables in i
299 _overflow_ = false;
300 Idx s = nbrDim();
301
302 for (Size p = 0; p < s; ++p)
303 if (i.contains(_vars_[p])) _chgVal_(p, _vars_[p]->domainSize() - 1);
304 }
305
306 // operator ++ for the variables not in i
307
308 // operator -- for the variables not in i
309
310 // put the (0,0,...) first val in the Instantiation for the variables not in
311 // i
313 _overflow_ = false;
314 Idx s = nbrDim();
315
316 for (Size p = 0; p < s; ++p)
317 if (!i.contains(_vars_[p])) _chgVal_(p, 0);
318 }
319
320 // put the (D1-1,D2-1,...) lastvalue in the Instantiation for vars not in i
322 _overflow_ = false;
323 Idx s = nbrDim();
324
325 for (Size p = 0; p < s; ++p)
326 if (!i.contains(_vars_[p])) _chgVal_(p, _vars_[p]->domainSize() - 1);
327 }
328
329 // operator ++ for vars which are not v.
330
331 // operator -- for vars which are not v.
332
333 // assign the (0,0,...) first value to variables which are not v.
335 _overflow_ = false;
336 Idx s = nbrDim();
337
338 for (Size p = 0; p < s; ++p) {
339 if (_vars_[p] == &v) {
340 Idx oldval = _vals_[p];
341 setFirst();
342 _chgVal_(p, oldval);
343 return;
344 }
345 }
346
347 setFirst();
348 }
349
350 // put the (D1-1,D2-1,...) lastvalue in the Instantiation for vars != v
352 _overflow_ = false;
353 Idx s = nbrDim();
354
355 for (Size p = 0; p < s; ++p) {
356 if (_vars_[p] == &v) {
357 Idx oldval = _vals_[p];
358 setLast();
359 _chgVal_(p, oldval);
360 return;
361 }
362 }
363
364 setLast();
365 }
366
367 // operator ++ for variable v only
369 // get the position of the variable
370 Idx cpt = _vars_.pos(&v);
371 // if we are in overflow, do nothing
372
373 if (_overflow_) return;
374
375 Idx p = _vals_[cpt];
376
377 if (p + 1 == v.domainSize()) {
378 _chgVal_(cpt, 0);
379 _overflow_ = true;
380 } else {
381 _chgVal_(cpt, p + 1);
382 }
383 }
384
385 // operator -- for variable v only
387 // get the position of the variable
388 Idx cpt = _vars_.pos(&v);
389 // if we are in overflow, do nothing
390
391 if (_overflow_) return;
392
393 Idx p = _vals_[cpt];
394
395 if (p == 0) {
396 _chgVal_(cpt, v.domainSize() - 1);
397 _overflow_ = true;
398 } else {
399 _chgVal_(cpt, p - 1);
400 }
401 }
402
403 // assign the first value in the Instantiation for var v.
405 _overflow_ = false;
406 _chgVal_(_vars_.pos(&v), 0);
407 }
408
409 // assign the last value to var v.
411 _overflow_ = false;
412 _chgVal_(_vars_.pos(&v), v.domainSize() - 1);
413 }
414
415 // indicates whether the Instantiation has a master MultiDimAdressable
416 INLINE bool Instantiation::isSlave() const { return (_master_ != nullptr); }
417
418 // indicates wether the MultiDimAdressable* m is the master
419 INLINE bool Instantiation::isMaster(const MultiDimAdressable* m) const { return (_master_ == m); }
420
421 // indicates wether the MultiDimAdressable* m is the master
422 INLINE bool Instantiation::isMaster(const MultiDimAdressable& m) const { return isMaster(&m); }
423
424 // returns the sequence of DiscreteVariable
428
429 // replace 2 vars in the Instantiation
430 INLINE void Instantiation::_swap_(Idx i, Idx j) {
431 if (i == j) return;
432
433 _vars_.swap(i, j);
434
435 Idx v;
436 v = _vals_[i];
437 _vals_[i] = _vals_[j];
438 _vals_[j] = v;
439 }
440
441 // reordering
442 INLINE
443
445 if (_master_ != nullptr) {
446 GUM_ERROR(OperationNotAllowed, "Reordering impossible in slave instantiation")
447 }
448
449 _reorder_(original);
450 }
451
452 INLINE
453
455 Idx max = original.size();
456 Idx position = 0;
457 for (Idx i = 0; i < max; ++i) {
458 const DiscreteVariable* pv = original.atPos(i);
459
460 if (contains(pv)) {
461 auto p = pos(*pv);
462 GUM_ASSERT(p >= position); // this var should not be
463 // already placed.
464 _swap_(position, p);
465 position++;
466 }
467 }
468 }
469
470 // add new dim by master
472 if (m != _master_) { GUM_ERROR(OperationNotAllowed, "only master can do this") }
473
474 _add_(v);
475 }
476
477 // adds a new var to the sequence of vars
479 _vars_.insert(&v);
480 _vals_.push_back(0);
481 _overflow_ = false;
482 }
483
484 // removes a variable from the sequence of vars
486 // get the position of the variable
487 Idx pos = _vars_.pos(&v);
488 _vars_.erase(&v);
489 _vals_.erase(_vals_.begin() + pos);
490 }
491
492 // is this empty ?
493 INLINE bool Instantiation::empty() const { return _vals_.empty(); }
494
495 // Replace x by y.
497 _vars_.setAtPos(_vars_.pos(x), y);
498 }
499
503 Size h = Size(0);
504 for (const DiscreteVariable* k:
505 key.variablesSequence()) // k are unique only by address (not by name)
507
508 return h;
509 }
510
514 return castToSize(key) & this->hash_mask_;
515 }
516
517 INLINE bool Instantiation::operator==(const Instantiation& other) const {
518 if (inOverflow() && other.inOverflow()) return true;
519 if (inOverflow() != other.inOverflow()) return false;
520 if (other.nbrDim() != nbrDim()) return false;
521 for (const auto& k: variablesSequence()) {
522 if (!other.contains(k)) return false;
523 if (val(*k) != other.val(*k)) return false;
524 }
525 return true;
526 }
527} /* namespace gum */
Base class for discrete random variable.
virtual Size domainSize() const =0
Size operator()(const Instantiation &key) const final
Computes the hashed value of a key.
static Size castToSize(const Instantiation &key)
Returns the value of a key as a Size.
This class should be useless as only its specializations should be used.
Definition hashFunc.h:492
Class for assigning/browsing values to tuples of discrete variables.
const Sequence< const DiscreteVariable * > & variablesSequence() const final
Returns the sequence of DiscreteVariable of this instantiation.
void setLastOut(const Instantiation &i)
Assign the last values in the Instantiation for the variables not in i.
Instantiation & chgVal(const DiscreteVariable &v, Idx newval)
Assign newval to variable v in the Instantiation.
bool end() const
Returns true if the Instantiation reached the end.
void inc()
Operator increment.
void clear()
Erase all variables from an Instantiation.
Instantiation & operator--()
Alias of Instantiation::dec().
Sequence< const DiscreteVariable * > _vars_
The tuple of variables to be instantiated.
void incVar(const DiscreteVariable &v)
Operator increment for variable v only.
bool isMaster(const MultiDimAdressable *m) const
Indicates whether m is the master of this instantiation.
void _masterFirstNotification_() const
void setFirstNotVar(const DiscreteVariable &v)
Assign the first values to variables different of v.
void setFirstIn(const Instantiation &i)
Assign the first values in the Instantiation for the variables in i.
void decVar(const DiscreteVariable &v)
Operator decrement for variable v only.
void dec()
Operator decrement.
Instantiation & setVals(const Instantiation &i)
Assign the values from i in the Instantiation.
Instantiation & operator-=(Size depl)
Calls depl times Instantiation::dec().
std::vector< Idx > _vals_
The current instantiation: the value of the tuple.
void setLastIn(const Instantiation &i)
Assign the last values in the Instantiation for the variables in i.
bool empty() const final
Returns true if the instantiation is empty.
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.
Idx valFromPtr(const DiscreteVariable *pvar) const
Returns the current value of a given variable.
void setFirstVar(const DiscreteVariable &v)
Assign the first value in the Instantiation for var v.
bool rend() const
Returns true if the Instantiation reached the rend.
MultiDimAdressable * _master_
The master, if any, contains precisely the set of variables to be instantiated.
void erase(const DiscreteVariable &v) final
Removes a variable from the Instantiation.
bool isSlave() const
Indicates whether the Instantiation has a master.
void addWithMaster(const MultiDimAdressable *m, const DiscreteVariable &v)
Call Instantiation:: add(const DiscreteVariable&) by master.
void setLastNotVar(const DiscreteVariable &v)
Assign the last values to variables different of v.
void _erase_(const DiscreteVariable &v)
Removes a variable from the sequence of vars.
void reorder(const Sequence< const DiscreteVariable * > &v)
Reorder vars of this instantiation giving the order in v.
Instantiation & operator+=(Size depl)
Calls depl times Instantiation::inc().
void _masterLastNotification_() const
void _swap_(Idx i, Idx j)
Swap two variables in the Instantiation.
bool inOverflow() const
Indicates whether the current value of the tuple is correct or not.
void _add_(const DiscreteVariable &v)
Adds a new var to the sequence of vars.
Idx val(Idx i) const
Returns the current value of the variable at position i.
void setFirst()
Assign the first values to the tuple of the Instantiation.
void _masterChangeNotification_(Idx varPos, Idx newVal, Idx oldVal) const
void setFirstOut(const Instantiation &i)
Assign the first values in the Instantiation for the variables not in i.
void _chgVal_(Idx varPos, Idx newVal)
Modifies internally the value of a given variable of the sequence.
void unsetEnd()
Alias for unsetOverflow().
const DiscreteVariable & variable(Idx i) const final
Returns the variable at position i in the tuple.
Idx nbrDim() const final
Returns the number of variables in the Instantiation.
Instantiation & operator++()
Alias of Instantiation::inc().
bool operator==(const Instantiation &other) const
operator==
void setLastVar(const DiscreteVariable &v)
Assign the last value in the Instantiation for var v.
void unsetOverflow()
Removes the flag overflow.
void replace_(const DiscreteVariable *x, const DiscreteVariable *y) final
Replace x by y.
void setLast()
Assign the last values in the Instantiation.
Abstract base class for all multi dimensionnal addressable.
Exception : the element we looked for cannot be found.
Exception : operation not allowed.
Exception : out of bound.
const Key & atPos(Idx i) const
Returns the object at the pos i.
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.
Headers for the abstract base class for all multi dimensionnal containers.
gum is the global namespace for all aGrUM entities
Definition agrum.h:46