aGrUM 2.3.2
a C++ library for (probabilistic) graphical models
multiDimContainer_tpl.h
Go to the documentation of this file.
1/****************************************************************************
2 * This file is part of the aGrUM/pyAgrum library. *
3 * *
4 * Copyright (c) 2005-2025 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-2025 *
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#pragma once
41
42
49
50#include <algorithm>
51
52#include <agrum/agrum.h>
53
54namespace gum {
55
56 template < typename GUM_SCALAR >
57 INLINE
62
63 // Default constructor
64 template < typename GUM_SCALAR >
68
69 // Copy constructor
70 template < typename GUM_SCALAR >
75
76 template < typename GUM_SCALAR >
82
83 template < typename GUM_SCALAR >
86 GUM_OP_MOV(MultiDimContainer);
87 MultiDimAdressable::operator=(std::forward< MultiDimAdressable >(from));
88 return *this;
89 }
90
91 // destructor
92
93 template < typename GUM_SCALAR >
97
98 // an [] operator using a Instantiation as argument
99
100 template < typename GUM_SCALAR >
102 return get(i);
103 }
104
105 // an [] operator using a Instantiation as argument
106
107 template < typename GUM_SCALAR >
109 const GUM_SCALAR& value) const {
110 get_(i) = value;
111 }
112
113 // an [] operator using a Instantiation as argument
114
115 template < typename GUM_SCALAR >
116 INLINE GUM_SCALAR MultiDimContainer< GUM_SCALAR >::get(const Instantiation& i) const {
117 return get_(i);
118 }
119
120 // display the content of an array
121
122 template < typename GUM_SCALAR >
124 // we create a new instantiation and iterate over it to display the whole
125 // content of the array
126 if (this->nbrDim() == 0) { return "[]"; }
127
128 std::stringstream ss;
129 Instantiation inst(const_cast< MultiDimContainer* >(this));
130
131 bool first = true;
132
133 for (inst.setFirst(); !inst.end(); ++inst) {
134 if (!first) { ss << " /"; }
135 first = false;
136
137 ss << inst << " :: " << get(inst);
138 }
139
140 return ss.str();
141 }
142
143 // Test if this tensor is equal to p.
144
145 template < typename GUM_SCALAR >
147 if ((nbrDim() == p.nbrDim()) && (domainSize() == p.domainSize())) {
148 if (nbrDim() == 0) return true;
149
150 for (auto iter = variablesSequence().beginSafe(); iter != variablesSequence().endSafe();
151 ++iter) {
152 if (!p.variablesSequence().exists(*iter)) { return false; }
153 }
154 } else {
155 return false;
156 }
157
158 Instantiation i(*this);
160 for (i.setFirst(); !i.end(); ++i) {
161 if (cmp(get(i), p.get(i))) { return false; }
162 }
163
164 return true;
165 }
166
167 // Test if this tensor is different of p.
168
169 template < typename GUM_SCALAR >
170 INLINE bool
172 return !operator==(p);
173 }
174
175 // automation fill with vector.
176 template < typename GUM_SCALAR >
177 void MultiDimContainer< GUM_SCALAR >::populate(const std::vector< GUM_SCALAR >& v) const {
178 if (domainSize() != v.size()) {
179 GUM_ERROR(SizeError, "Sizes do not match : " << domainSize() << "!=" << v.size())
180 }
181
182 Size cpt = 0;
183
185
186 for (i.setFirst(); !i.end(); ++i, ++cpt)
187 set(i, v[cpt]);
188 }
189
190 template < typename GUM_SCALAR >
191 void MultiDimContainer< GUM_SCALAR >::populate(std::initializer_list< GUM_SCALAR > l) const {
192 if (domainSize() != l.size()) {
193 GUM_ERROR(SizeError, "Sizes do not match : " << domainSize() << "!=" << l.size())
194 }
195
196 Instantiation i(*this);
197 // insert all the elements
198 for (const auto& elt: l) {
199 set(i, elt);
200 ++i;
201 }
202 }
203
204 template < typename GUM_SCALAR >
205 void MultiDimContainer< GUM_SCALAR >::apply(std::function< GUM_SCALAR(GUM_SCALAR) > f) const {
206 Instantiation i(*this);
207 for (i.setFirst(); !i.end(); ++i) {
208 set(i, f(get(i)));
209 }
211
212 template < typename GUM_SCALAR >
213 GUM_SCALAR
214 MultiDimContainer< GUM_SCALAR >::reduce(std::function< GUM_SCALAR(GUM_SCALAR, GUM_SCALAR) > f,
215 GUM_SCALAR base) const {
216 GUM_SCALAR tmp = base;
217 Instantiation i(*this);
218 for (i.setFirst(); !i.end(); ++i) {
219 tmp = f(tmp, get(i));
220 }
221 return tmp;
222 }
223
224 template < typename GUM_SCALAR >
226 Instantiation* p_i) const {
227 if (src.domainSize() != domainSize()) {
229 "Domain sizes do not fit : " << src.domainSize() << "!=" << domainSize());
231
232 if (p_i == nullptr) { // if null, we just follow the same order
233 Instantiation i(src);
234 for (i.setFirst(); !i.end(); ++i) {
235 set(i, src[i]);
236 }
237 } else {
238 Instantiation i_dest(*this);
239 Instantiation i_src(src);
240 for (i_dest.setFirst(), i_src.setFirst(); !i_dest.end(); i_dest.incIn(*p_i), ++i_src) {
241 set(i_dest, src[i_src]);
242 }
243 }
244 }
245
246 template < typename GUM_SCALAR >
248 const Instantiation& imask) {
249 this->beginMultipleChanges();
251 Size nbr = this->nbrDim();
252 for (Idx i = 0; i < nbr; i++) {
253 this->erase(this->variable(0));
254 }
255
256 for (Idx i = 0; i < src.nbrDim(); i++) {
257 if (!imask.contains(src.variable(i))) this->add(src.variable(i));
258 }
259
260 this->endMultipleChanges();
261
262 if (this->nbrDim() == 0) { GUM_ERROR(FatalError, "Empty tensor") }
263
264 Instantiation inst(src);
265 inst.setVals(imask);
266 for (inst.setFirstOut(imask); !inst.end(); inst.incOut(imask))
267 set(inst, src[inst]);
268 }
269
270 template < typename GUM_SCALAR >
272 if (src.domainSize() != domainSize()) {
274 "Domain sizes do not fit : " << src.domainSize() << "!=" << domainSize());
275 }
276
277 Instantiation i_dest(*this);
278 Instantiation i_src(src);
279
280 for (i_dest.setFirst(), i_src.setFirst(); !i_dest.end(); ++i_dest, ++i_src) {
281 set(i_dest, src[i_src]);
282 }
283 }
284
285 // copy
286
287 template < typename GUM_SCALAR >
289 this->beginMultipleChanges();
290
291 Size nbr = this->nbrDim();
292
293 for (Idx i = 0; i < nbr; i++) {
294 this->erase(this->variable(0));
295 }
296
297 for (Idx i = 0; i < src.nbrDim(); i++) {
298 this->add(src.variable(i));
299 }
300
301 this->endMultipleChanges();
302 this->copyFrom(src);
303 }
305 template < typename GUM_SCALAR >
309
310 template < typename GUM_SCALAR >
312 return static_cast< const MultiDimAdressable& >(*content());
314
315 // display the content of an array
316
317 template < typename GUM_SCALAR >
318 std::ostream& operator<<(std::ostream& out, const MultiDimContainer< GUM_SCALAR >& array) {
319 out << array.toString();
320 return out;
321 }
322
323} /* namespace gum */
Exception : fatal (unknown ?) error.
Class for assigning/browsing values to tuples of discrete variables.
bool end() const
Returns true if the Instantiation reached the end.
void incOut(const Instantiation &i)
Operator increment for the variables not in i.
Instantiation & setVals(const Instantiation &i)
Assign the values from i in the Instantiation.
bool contains(const DiscreteVariable &v) const final
Indicates whether a given variable belongs to the Instantiation.
void setFirst()
Assign the first values to the tuple of the Instantiation.
void setFirstOut(const Instantiation &i)
Assign the first values in the Instantiation for the variables not in i.
MultiDimAdressable()
Default constructor.
MultiDimAdressable & operator=(const MultiDimAdressable &from)
Default constructor.
Abstract base class for all multi dimensionnal containers.
virtual void copy(const MultiDimContainer< GUM_SCALAR > &src)
Removes all variables in this MultiDimContainer and copy the content of src, variables included.
virtual void extractFrom(const MultiDimContainer< GUM_SCALAR > &src, const Instantiation &mask)
Basic extraction of a MultiDimContainer.
MultiDimContainer & operator=(const MultiDimContainer< GUM_SCALAR > &src)
Default constructor.
virtual const MultiDimImplementation< GUM_SCALAR > * content() const =0
Returns the implementation for this object (may be *this).
virtual ~MultiDimContainer()
Destructor.
virtual MultiDimAdressable & getMasterRef()
In order to insure the dereference for decorators, we need to virtualize the access to master pointer...
bool operator!=(const MultiDimContainer< GUM_SCALAR > &p) const
Test if this MultiDimContainer is different of p.
virtual void beginMultipleChanges()=0
Call this method before doing important changes in this MultiDimContainer.
virtual GUM_SCALAR & get_(const Instantiation &i) const =0
Return a data, given a Instantiation.
virtual void set(const Instantiation &i, const GUM_SCALAR &value) const
Changes the value pointed by i.
MultiDimContainer()
Default constructor.
virtual GUM_SCALAR reduce(std::function< GUM_SCALAR(GUM_SCALAR, GUM_SCALAR) > f, GUM_SCALAR base) const
compute lfold for this container
virtual GUM_SCALAR get(const Instantiation &i) const
Returns the value pointed by i.
virtual void populate(const std::vector< GUM_SCALAR > &v) const
Automatically fills this MultiDimContainer with the values in v.
GUM_SCALAR operator[](const Instantiation &i) const
An [] operator using a Instantiation as argument.
virtual void copyFrom(const MultiDimContainer< GUM_SCALAR > &src) const
Basic copy of a MultiDimContainer.
virtual void apply(std::function< GUM_SCALAR(GUM_SCALAR) > f) const
Apply a function on every element of the container.
virtual std::string toString() const
Returns a representation of this MultiDimContainer.
bool operator==(const MultiDimContainer< GUM_SCALAR > &p) const
Test if this MultiDimContainer is equal to p.
virtual const Sequence< const DiscreteVariable * > & variablesSequence() const =0
Returns a const ref to the sequence of DiscreteVariable*.
virtual Size domainSize() const =0
Returns the product of the variables domain size.
virtual void add(const DiscreteVariable &v)=0
virtual Idx nbrDim() const=0
virtual const DiscreteVariable & variable(Idx i) const=0
virtual void erase(const DiscreteVariable &v)=0
Exception : operation not allowed.
Exception : problem with size.
#define GUM_ERROR(type, msg)
Definition exceptions.h:72
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
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
Definition AVLTree.h:913
bool operator==(const HashTableIteratorSafe< Key, Val > &from) const noexcept
Checks whether two iterators are pointing toward equal elements.
STL namespace.
Indicate whether two elements are (almost) different or not.
Definition utils_misc.h:171