aGrUM 3.1.1
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-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
51#include <algorithm>
52
53#include <agrum/agrum.h>
54
56
57namespace gum {
58
59 template < typename GUM_ELEMENT >
64
65 // Default constructor
66 template < typename GUM_ELEMENT >
70
71 // Copy constructor
72 template < typename GUM_ELEMENT >
77
78 template < typename GUM_ELEMENT >
84
85 template < typename GUM_ELEMENT >
88 GUM_OP_MOV(MultiDimContainer);
89 MultiDimAdressable::operator=(std::forward< MultiDimAdressable >(from));
90 return *this;
91 }
92
93 // destructor
94
95 template < typename GUM_ELEMENT >
99
100 // an [] operator using a Instantiation as argument
101
102 template < typename GUM_ELEMENT >
104 return get(i);
105 }
106
107 // an [] operator using a Instantiation as argument
108
109 template < typename GUM_ELEMENT >
111 const GUM_ELEMENT& value) const {
112 get_(i) = value;
113 }
114
115 // an [] operator using a Instantiation as argument
116
117 template < typename GUM_ELEMENT >
119 return get_(i);
120 }
121
122 // display the content of an array
124 template < typename GUM_ELEMENT >
126 // we create a new instantiation and iterate over it to display the whole
127 // content of the array
128 if (this->nbrDim() == 0) { return "[]"; }
129
130 std::stringstream ss;
131 Instantiation inst(const_cast< MultiDimContainer* >(this));
132
133 bool first = true;
134
135 for (inst.setFirst(); !inst.end(); ++inst) {
136 if (!first) { ss << " /"; }
137 first = false;
138
139 ss << inst << " :: " << get(inst);
140 }
141
142 return ss.str();
144
145 // Test if this tensor is equal to p.
146
147 template < typename GUM_ELEMENT >
149 const MultiDimContainer< GUM_ELEMENT >& p) const {
150 if ((nbrDim() == p.nbrDim()) && (domainSize() == p.domainSize())) {
151 if (nbrDim() == 0) return true;
152
153 for (auto iter = variablesSequence().beginSafe(); iter != variablesSequence().endSafe();
154 ++iter) {
155 if (!p.variablesSequence().exists(*iter)) { return false; }
156 }
157 } else {
158 return false;
159 }
161 Instantiation i(*this);
163 for (i.setFirst(); !i.end(); ++i) {
164 if (cmp(get(i), p.get(i))) { return false; }
165 }
166
167 return true;
168 }
169
170 // automation fill with vector.
171 template < typename GUM_ELEMENT >
172 void MultiDimContainer< GUM_ELEMENT >::populate(const std::vector< GUM_ELEMENT >& v) const {
173 if (domainSize() != v.size()) {
174 GUM_ERROR(SizeError, "Sizes do not match : " << domainSize() << "!=" << v.size())
175 }
176
177 Size cpt = 0;
178
179 Instantiation i(*this);
180
181 for (i.setFirst(); !i.end(); ++i, ++cpt)
182 set(i, v[cpt]);
183 }
185 template < typename GUM_ELEMENT >
186 void MultiDimContainer< GUM_ELEMENT >::populate(std::initializer_list< GUM_ELEMENT > l) const {
187 if (domainSize() != l.size()) {
188 GUM_ERROR(SizeError, "Sizes do not match : " << domainSize() << "!=" << l.size())
189 }
190
191 Instantiation i(*this);
192 // insert all the elements
193 for (const auto& elt: l) {
194 set(i, elt);
195 ++i;
196 }
197 }
198
199 template < typename GUM_ELEMENT >
200 void MultiDimContainer< GUM_ELEMENT >::apply(std::function< GUM_ELEMENT(GUM_ELEMENT) > f) const {
201 Instantiation i(*this);
202 for (i.setFirst(); !i.end(); ++i) {
203 set(i, f(get(i)));
204 }
205 }
206
207 template < typename GUM_ELEMENT >
209 std::function< GUM_ELEMENT(GUM_ELEMENT, GUM_ELEMENT) > f,
210 GUM_ELEMENT base) const {
211 GUM_ELEMENT tmp = base;
212 Instantiation i(*this);
213 for (i.setFirst(); !i.end(); ++i) {
214 tmp = f(tmp, get(i));
215 }
216 return tmp;
217 }
218
219 template < typename GUM_ELEMENT >
221 Instantiation* p_i) const {
222 if (src.domainSize() != domainSize()) {
224 "Domain sizes do not fit : " << src.domainSize() << "!=" << domainSize());
225 }
226
227 if (p_i == nullptr) { // if null, we just follow the same order
228 Instantiation i(src);
229 for (i.setFirst(); !i.end(); ++i) {
230 set(i, src[i]);
231 }
232 } else {
233 Instantiation i_dest(*this);
234 Instantiation i_src(src);
235 for (i_dest.setFirst(), i_src.setFirst(); !i_dest.end(); i_dest.incIn(*p_i), ++i_src) {
236 set(i_dest, src[i_src]);
237 }
238 }
239 }
240
241 template < typename GUM_ELEMENT >
243 const Instantiation& imask) {
244 this->beginMultipleChanges();
245
246 Size nbr = this->nbrDim();
247 for (Idx i = 0; i < nbr; i++) {
248 this->erase(this->variable(0));
249 }
251 for (Idx i = 0; i < src.nbrDim(); i++) {
252 if (!imask.contains(src.variable(i))) this->add(src.variable(i));
253 }
254
255 this->endMultipleChanges();
256
257 if (this->nbrDim() == 0) { GUM_ERROR(FatalError, "Empty tensor") }
258
259 Instantiation inst(src);
260 inst.setVals(imask);
261 for (inst.setFirstOut(imask); !inst.end(); inst.incOut(imask))
262 set(inst, src[inst]);
263 }
264
265 template < typename GUM_ELEMENT >
267 const MultiDimContainer< GUM_ELEMENT >& src) const {
268 if (src.domainSize() != domainSize()) {
270 "Domain sizes do not fit : " << src.domainSize() << "!=" << domainSize());
271 }
272
273 Instantiation i_dest(*this);
274 Instantiation i_src(src);
275
276 for (i_dest.setFirst(), i_src.setFirst(); !i_dest.end(); ++i_dest, ++i_src) {
277 set(i_dest, src[i_src]);
278 }
279 }
281 // copy
282
283 template < typename GUM_ELEMENT >
285 this->beginMultipleChanges();
286
287 Size nbr = this->nbrDim();
288
289 for (Idx i = 0; i < nbr; i++) {
290 this->erase(this->variable(0));
291 }
292
293 for (Idx i = 0; i < src.nbrDim(); i++) {
294 this->add(src.variable(i));
295 }
296
297 this->endMultipleChanges();
298 this->copyFrom(src);
299 }
300
301 template < typename GUM_ELEMENT >
306 template < typename GUM_ELEMENT >
308 return static_cast< const MultiDimAdressable& >(*content());
309 }
310
311 // display the content of an array
312
313 template < typename GUM_ELEMENT >
314 std::ostream& operator<<(std::ostream& out, const MultiDimContainer< GUM_ELEMENT >& array) {
315 out << array.toString();
316 return out;
317 }
318
319} /* 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.
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.
MultiDimAdressable()
Default constructor.
MultiDimAdressable & operator=(const MultiDimAdressable &from)
Default constructor.
Abstract base class for all multi dimensionnal containers.
bool operator==(const MultiDimContainer< GUM_ELEMENT > &p) const
Test if this MultiDimContainer is equal to p.
MultiDimContainer & operator=(const MultiDimContainer< GUM_ELEMENT > &src)
Default constructor.
virtual void beginMultipleChanges()=0
Call this method before doing important changes in this MultiDimContainer.
virtual void set(const Instantiation &i, const GUM_ELEMENT &value) const
Changes the value pointed by i.
virtual void copy(const MultiDimContainer< GUM_ELEMENT > &src)
Removes all variables in this MultiDimContainer and copy the content of src, variables included.
virtual void copyFrom(const MultiDimContainer< GUM_ELEMENT > &src) const
Basic copy of a MultiDimContainer.
virtual void populate(const std::vector< GUM_ELEMENT > &v) const
Automatically fills this MultiDimContainer with the values in v.
virtual GUM_ELEMENT get(const Instantiation &i) const
Returns the value pointed by i.
virtual GUM_ELEMENT reduce(std::function< GUM_ELEMENT(GUM_ELEMENT, GUM_ELEMENT) > f, GUM_ELEMENT base) const
compute lfold for this container
virtual const MultiDimImplementation< GUM_ELEMENT > * content() const =0
Returns the implementation for this object (may be *this).
MultiDimContainer()
Default constructor.
virtual void endMultipleChanges()=0
Call this method after doing important changes in this MultiDimContainer.
GUM_ELEMENT operator[](const Instantiation &i) const
An [] operator using a Instantiation as argument.
virtual void extractFrom(const MultiDimContainer< GUM_ELEMENT > &src, const Instantiation &mask)
Basic extraction of a MultiDimContainer.
virtual void apply(std::function< GUM_ELEMENT(GUM_ELEMENT) > f) const
Apply a function on every element of the container.
virtual std::string toString() const
Returns a representation of this MultiDimContainer.
MultiDimAdressable & getMasterRef() override
In order to insure the dereference for decorators, we need to virtualize the access to master pointer...
virtual GUM_ELEMENT & get_(const Instantiation &i) const =0
Return a data, given a Instantiation.
~MultiDimContainer() override
Destructor.
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
Returns the number of vars in the multidimensional container.
virtual const DiscreteVariable & variable(Idx i) const =0
Returns a const ref to the ith var.
virtual void erase(const DiscreteVariable &v)=0
Removes a var from the variables of the multidimensional matrix.
Exception : operation not allowed.
Exception : problem with size.
#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
Headers of the MultiDimContainer class.
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
STL namespace.
Indicate whether two elements are (almost) different or not.
Definition utils_misc.h:164