aGrUM 2.3.2
a C++ library for (probabilistic) graphical models
tensor_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
48
49#include <algorithm>
50
51#include <agrum/agrum.h>
52
54
56
57namespace gum {
58 // Default constructor: creates an empty null dimensional matrix
59 // choose a MultiDimArray<> as decorated implementation
60 template < typename GUM_SCALAR >
62 MultiDimDecorator< GUM_SCALAR >(new MultiDimArray< GUM_SCALAR >(), GUM_SCALAR(1)) {
63 GUM_CONSTRUCTOR(Tensor)
64 }
65
66 // Default constructor: creates an empty null dimensional matrix
67 // choose a MultiDimArray<> as decorated implementation
68 template < typename GUM_SCALAR >
69 INLINE Tensor< GUM_SCALAR >::Tensor(const std::vector< const DiscreteVariable* >& vars) :
70 Tensor() {
71 for (const auto& var: vars) {
72 this->add(*var);
73 }
74 }
75
76 // constructor using aContent as content
77 template < typename GUM_SCALAR >
79 MultiDimDecorator< GUM_SCALAR >(aContent, GUM_SCALAR(1)) {
80 // for debugging purposes
81 GUM_CONSTRUCTOR(Tensor)
82 }
83
84 // copy constructor
85 template < typename GUM_SCALAR >
86 INLINE Tensor< GUM_SCALAR >::Tensor(const Tensor< GUM_SCALAR >& src) :
87 Tensor< GUM_SCALAR >(
88 static_cast< MultiDimImplementation< GUM_SCALAR >* >(src.content()->newFactory()),
89 *(src.content())) {
90 this->empty_value_ = src.empty_value_;
91 // GUM_CONS_CPY not here because in called Tensor
92 // GUM_CONS_CPY( Tensor );
93 }
94
96 template < typename GUM_SCALAR >
97 INLINE Tensor< GUM_SCALAR >::Tensor(Tensor< GUM_SCALAR >&& from) :
98 MultiDimDecorator< GUM_SCALAR >(std::forward< MultiDimDecorator< GUM_SCALAR > >(from)) {
99 GUM_CONS_MOV(Tensor)
100 }
101
102 // complex copy constructor : we choose the implementation
103 template < typename GUM_SCALAR >
106 MultiDimDecorator< GUM_SCALAR >(aContent) {
107 // for debugging purposes
108 GUM_CONSTRUCTOR(Tensor)
109
110 if (!src.empty()) {
111 this->beginMultipleChanges();
112
113 for (Idx i = 0; i < src.variablesSequence().size(); i++) {
114 this->add(*(src.variablesSequence()[i]));
115 }
116
117 this->endMultipleChanges();
118 this->content()->copyFrom(*src.content());
119 }
120 }
121
122 // operator= (copy)
123 template < typename GUM_SCALAR >
124 Tensor< GUM_SCALAR >& Tensor< GUM_SCALAR >::operator=(const Tensor< GUM_SCALAR >& src) {
125 GUM_OP_CPY(Tensor)
126 if (&src == this) return *this;
128 return *this;
129 }
130
131 // operator= (move)
132 template < typename GUM_SCALAR >
133 Tensor< GUM_SCALAR >& Tensor< GUM_SCALAR >::operator=(Tensor< GUM_SCALAR >&& src) {
134 GUM_OP_MOV(Tensor)
135 if (&src == this) return *this;
137 std::forward< MultiDimDecorator< GUM_SCALAR > >(src));
138 return *this;
139 }
140
141 // destructor
142
143 template < typename GUM_SCALAR >
145 // for debugging purposes
146 GUM_DESTRUCTOR(Tensor)
147 }
148
149 template < typename GUM_SCALAR >
150 INLINE Tensor< GUM_SCALAR >* Tensor< GUM_SCALAR >::newFactory() const {
151 return new Tensor< GUM_SCALAR >(
152 static_cast< MultiDimImplementation< GUM_SCALAR >* >(this->content()->newFactory()));
153 }
154
155 // sum of all elements in this
156 template < typename GUM_SCALAR >
157 INLINE GUM_SCALAR Tensor< GUM_SCALAR >::sum() const {
158 if (static_cast< MultiDimContainer< GUM_SCALAR >* >(this->content_)->empty()) {
159 return this->empty_value_;
160 }
161 return gum::projectSum(*this->content());
162 }
163
164 // product of all elements in this
165 template < typename GUM_SCALAR >
166 INLINE GUM_SCALAR Tensor< GUM_SCALAR >::product() const {
167 if (static_cast< MultiDimContainer< GUM_SCALAR >* >(this->content_)->empty()) {
168 return this->empty_value_;
169 }
170 return gum::projectProduct(*this->content());
171 }
172
173 // max of all elements in this
174 template < typename GUM_SCALAR >
175 INLINE GUM_SCALAR Tensor< GUM_SCALAR >::max() const {
176 if (static_cast< MultiDimContainer< GUM_SCALAR >* >(this->content_)->empty()) {
177 return this->empty_value_;
178 }
179 return gum::projectMax(*this->content());
180 }
181
182 // min of all elements in this
183 template < typename GUM_SCALAR >
184 INLINE GUM_SCALAR Tensor< GUM_SCALAR >::min() const {
185 if (static_cast< MultiDimContainer< GUM_SCALAR >* >(this->content_)->empty()) {
186 return this->empty_value_;
187 }
188 return gum::projectMin(*this->content());
189 }
190
191 // max of all non-one elements in this
192 // warning can return 1 if no other value than 1 ...
193 template < typename GUM_SCALAR >
195 GUM_SCALAR res;
196
197 if (static_cast< MultiDimContainer< GUM_SCALAR >* >(this->content_)->empty()) {
198 res = this->empty_value_;
199 } else {
200 res = this->reduce(
201 [](GUM_SCALAR z, GUM_SCALAR p) {
202 return (p == static_cast< GUM_SCALAR >(1)) ? z
203 : (z == static_cast< GUM_SCALAR >(1)) ? p
204 : (p > z ? p : z);
205 },
206 static_cast< GUM_SCALAR >(1));
207 }
208
209 return res;
210 }
211
212 // min of all non-zero elements in this
213 // warning can return 0 if no other value than 0 ...
214 template < typename GUM_SCALAR >
215 INLINE GUM_SCALAR Tensor< GUM_SCALAR >::minNonZero() const {
216 GUM_SCALAR res;
217
218 if (static_cast< MultiDimContainer< GUM_SCALAR >* >(this->content_)->empty()) {
219 res = this->empty_value_;
220 } else {
221 res = this->reduce(
222 [](GUM_SCALAR z, GUM_SCALAR p) {
223 return (p == static_cast< GUM_SCALAR >(0)) ? z
224 : (z == static_cast< GUM_SCALAR >(0)) ? p
225 : (p < z ? p : z);
226 },
227 static_cast< GUM_SCALAR >(0));
228 }
229 return res;
230 }
231
232 template < typename GUM_SCALAR >
234 std::function< GUM_SCALAR(const gum::Instantiation&) > f) const {
235 if (static_cast< MultiDimContainer< GUM_SCALAR >* >(this->content_)->empty()) {
236 return static_cast< GUM_SCALAR >(0);
237 }
238
239 GUM_SCALAR res = 0;
240 auto i = Instantiation(*this);
241 for (i.setFirst(); !i.end(); i.inc()) {
242 const GUM_SCALAR v_f = f(i);
243 if (v_f != GUM_SCALAR(0.0)) res += this->get(i) * v_f;
244 }
245 return res;
246 }
247
248 // entropy of this
249 template < typename GUM_SCALAR >
250 INLINE GUM_SCALAR Tensor< GUM_SCALAR >::entropy() const {
251 return -this->expectedValue([this](const gum::Instantiation& i) -> GUM_SCALAR {
252 return GUM_SCALAR(GUM_LOG2_OR_0(this->get(i)));
253 });
254 }
255
256 template < typename GUM_SCALAR >
257 INLINE const Tensor< GUM_SCALAR >&
258 Tensor< GUM_SCALAR >::fillWith(const std::vector< GUM_SCALAR >& data) const {
259 this->populate(data);
260 return *this;
261 }
262
263 template < typename GUM_SCALAR >
264 INLINE const Tensor< GUM_SCALAR >& Tensor< GUM_SCALAR >::fillWith(const GUM_SCALAR& val) const {
265 this->fill(val);
266 return *this;
267 }
268
269 template < typename GUM_SCALAR >
270 INLINE const Tensor< GUM_SCALAR >&
271 Tensor< GUM_SCALAR >::fillWith(const Tensor< GUM_SCALAR >& src) const {
272 if (src.domainSize() != this->domainSize()) {
273 GUM_ERROR(InvalidArgument, "Tensor to copy has not the same domainSize.")
274 }
275 gum::Set< std::string > son; // set of names
276 for (const auto& v: src.variablesSequence()) {
277 son.insert(v->name());
278 }
279 for (const auto& v: this->variablesSequence()) {
280 if (!son.contains(v->name())) {
282 "Variable <" << v->name() << "> not present in src (" << son << ").")
283 }
284 // we check size, labels and order of labels in the same time
285 if (v->toString() != src.variable(v->name()).toString()) {
286 GUM_ERROR(InvalidArgument, "Variables <" << v->name() << "> are not identical.")
287 }
288 }
289
290 Instantiation Isrc(src);
291 Instantiation Idst(*this);
292 for (Isrc.setFirst(); !Isrc.end(); ++Isrc) {
293 for (Idx i = 0; i < this->nbrDim(); i++) {
294 Idst.chgVal(Isrc.variable(i).name(), Isrc.val(i));
295 }
296 this->set(Idst, src.get(Isrc));
297 }
298
299 return *this;
300 }
301
302 template < typename GUM_SCALAR >
303 INLINE const Tensor< GUM_SCALAR >&
304 Tensor< GUM_SCALAR >::fillWith(const Tensor< GUM_SCALAR >& src,
305 const std::vector< std::string >& mapSrc) const {
306 if (src.nbrDim() != this->nbrDim()) {
307 GUM_ERROR(InvalidArgument, "Tensor to copy has not the same size.")
308 }
309 if (src.nbrDim() != mapSrc.size()) {
310 GUM_ERROR(InvalidArgument, "Tensor and vector have not the same size.")
311 }
312 Instantiation Isrc;
313 for (Idx i = 0; i < src.nbrDim(); i++) {
314 if (src.variable(mapSrc[i]).domainSize() != this->variable(i).domainSize()) {
316 "Variables " << mapSrc[i] << " (in the argument) and " << this->variable(i).name()
317 << " have not the same dimension.")
318 } else {
319 Isrc.add(src.variable(mapSrc[i]));
320 }
321 }
322 Instantiation Idst(*this);
323 for (Isrc.setFirst(); !Isrc.end(); ++Isrc, ++Idst) {
324 this->set(Idst, src.get(Isrc));
325 }
326
327 return *this;
328 }
329
330 template < typename GUM_SCALAR >
331 INLINE const Tensor< GUM_SCALAR >& Tensor< GUM_SCALAR >::sq() const {
332 this->apply([](GUM_SCALAR x) { return x * x; });
333 return *this;
334 }
335
336 template < typename GUM_SCALAR >
337 INLINE const Tensor< GUM_SCALAR >& Tensor< GUM_SCALAR >::log2() const {
338 this->apply([](GUM_SCALAR x) { return std::log2(x); });
339 return *this;
340 }
341
342 template < typename GUM_SCALAR >
343 INLINE const Tensor< GUM_SCALAR >& Tensor< GUM_SCALAR >::sgn() const {
344 this->apply([](GUM_SCALAR x) { return (GUM_SCALAR(0) < x) - (x < GUM_SCALAR(0)); });
345 return *this;
346 }
347
348 template < typename GUM_SCALAR >
349 INLINE GUM_SCALAR Tensor< GUM_SCALAR >::KL(const Tensor< GUM_SCALAR >& p) const {
350 if (this->nbrDim() != p.nbrDim())
351 GUM_ERROR(InvalidArgument, "BNdistance between tensors with different numbers of dimensions")
352 for (const auto var: p.variablesSequence()) {
353 if (!this->contains(*var))
354 GUM_ERROR(InvalidArgument, "A variable in the argument does not belong to the tensor.")
355 }
356 for (const auto var: this->variablesSequence()) {
357 if (!p.contains(*var))
358 GUM_ERROR(InvalidArgument, "A variable does not belong to the argument.")
359 }
360
361 Instantiation inst(*this);
362 auto res = static_cast< GUM_SCALAR >(0);
363 for (inst.setFirst(); !inst.end(); inst.inc()) {
364 GUM_SCALAR x = this->get(inst);
365 GUM_SCALAR y = p.get(inst);
366 if (static_cast< GUM_SCALAR >(0) == x) // 0*log(0/y)=0
367 continue;
368
369 if (static_cast< GUM_SCALAR >(0) == y)
370 // we know that x!=0;
371 GUM_ERROR(FatalError, "The argument has a 0 at " << inst << " while the tensor has not.")
372
373 res += x * std::log2(x / y);
374 }
375 return res;
376 }
377
378 template < typename GUM_SCALAR >
379 INLINE const Tensor< GUM_SCALAR >& Tensor< GUM_SCALAR >::abs() const {
380 this->apply([](GUM_SCALAR x) {
381 if (x >= 0) return x;
382 else return -x;
383 });
384 return *this;
385 }
386
387 // normalisation of this
388 // do nothing is sum is 0
389 template < typename GUM_SCALAR >
390 INLINE const Tensor< GUM_SCALAR >& Tensor< GUM_SCALAR >::normalize() const {
391 if (static_cast< MultiDimContainer< GUM_SCALAR >* >(this->content_)->empty()) {
392 if (this->empty_value_ != static_cast< GUM_SCALAR >(0))
393 this->empty_value_ = static_cast< GUM_SCALAR >(1.0);
394 } else {
395 GUM_SCALAR s = sum();
396
397 if (s != (GUM_SCALAR)0) {
398 this->apply([s](GUM_SCALAR x) { return x / s; });
399 }
400 }
401 return *this;
402 }
403
404 template < typename GUM_SCALAR >
405 INLINE const Tensor< GUM_SCALAR >& Tensor< GUM_SCALAR >::normalizeAsCPT(const Idx& varId) const {
406 if (static_cast< MultiDimContainer< GUM_SCALAR >* >(this->content_)->empty()) {
407 if (this->empty_value_ != static_cast< GUM_SCALAR >(0)) {
408 this->empty_value_ = static_cast< GUM_SCALAR >(1.0);
409 } else {
410 GUM_ERROR(FatalError, "Normalization for a tensor that sum to 0 in " << *this)
411 }
412 } else {
413 if (varId >= this->nbrDim()) {
414 GUM_ERROR(FatalError, varId << " is not a position for " << *this)
415 }
416 Instantiation inst(*this);
417 const auto& v = this->variable(varId);
418
419 for (inst.setFirst(); !inst.end(); inst.incNotVar(v)) {
420 auto s = (GUM_SCALAR)0.0;
421 for (inst.setFirstVar(v); !inst.end(); inst.incVar(v))
422 s += this->get(inst);
423 if (s == (GUM_SCALAR)0.0) {
424 GUM_ERROR(FatalError, "Normalization for a tensor that sum to 0 in " << *this)
425 }
426 if (s != (GUM_SCALAR)1.0) {
427 for (inst.setFirstVar(v); !inst.end(); inst.incVar(v))
428 this->set(inst, this->get(inst) / s);
429 }
430 inst.setFirstVar(v); // to remove inst.end()
431 }
432 }
433 return *this;
434 }
435
436 template < typename GUM_SCALAR >
437 INLINE const Tensor< GUM_SCALAR >& Tensor< GUM_SCALAR >::scale(GUM_SCALAR v) const {
438 this->apply([v](GUM_SCALAR x) { return x * v; });
439 return *this;
440 }
441
442 template < typename GUM_SCALAR >
443 INLINE const Tensor< GUM_SCALAR >& Tensor< GUM_SCALAR >::translate(GUM_SCALAR v) const {
444 this->apply([v](GUM_SCALAR x) { return x + v; });
445 return *this;
446 }
447
448 template < typename GUM_SCALAR >
449 INLINE const Tensor< GUM_SCALAR >& Tensor< GUM_SCALAR >::inverse() const {
450 this->apply([](GUM_SCALAR x) { return 1 / x; });
451 return *this;
452 }
453
454 template < typename GUM_SCALAR >
455 INLINE Tensor< GUM_SCALAR > Tensor< GUM_SCALAR >::sumOut(const gum::VariableSet& del_vars) const {
456 if (static_cast< MultiDimContainer< GUM_SCALAR >* >(this->content_)->empty()) {
457 return Tensor< GUM_SCALAR >().fillWith(this->empty_value_);
458 }
459
460 // if we remove all the variables, create an empty tensor
461 // TODO: remove this test when operations will be able to handle empty tensors
462 if (this->variablesSequence().size() <= del_vars.size()) {
463 bool equal = true;
464 for (const auto var: this->variablesSequence()) {
465 if (!del_vars.exists(var)) {
466 equal = false;
467 break;
468 }
469 }
470 if (equal) { return Tensor< GUM_SCALAR >().fillWith(this->sum()); }
471 }
472
473 return Tensor< GUM_SCALAR >(gum::projectSum(*this->content(), del_vars));
474 }
475
476 template < typename GUM_SCALAR >
477 INLINE Tensor< GUM_SCALAR >
479 if (static_cast< MultiDimContainer< GUM_SCALAR >* >(this->content_)->empty()) {
480 return Tensor< GUM_SCALAR >().fillWith(this->empty_value_);
481 }
482
483 // if we remove all the variables, create an empty tensor
484 // TODO: remove this test when operations will be able to handle empty tensors
485 if (this->variablesSequence().size() <= del_vars.size()) {
486 bool equal = true;
487 for (const auto var: this->variablesSequence()) {
488 if (!del_vars.exists(var)) {
489 equal = false;
490 break;
491 }
492 }
493 if (equal) { return Tensor< GUM_SCALAR >().fillWith(this->product()); }
494 }
495
496 return Tensor< GUM_SCALAR >(gum::projectProduct(*this->content(), del_vars));
497 }
498
499 template < typename GUM_SCALAR >
500 INLINE Tensor< GUM_SCALAR > Tensor< GUM_SCALAR >::minOut(const gum::VariableSet& del_vars) const {
501 if (static_cast< MultiDimContainer< GUM_SCALAR >* >(this->content_)->empty()) {
502 return Tensor< GUM_SCALAR >().fillWith(this->empty_value_);
503 }
504
505 // if we remove all the variables, create an empty tensor
506 // TODO: remove this test when operations will be able to handle empty tensors
507 if (this->variablesSequence().size() <= del_vars.size()) {
508 bool equal = true;
509 for (const auto var: this->variablesSequence()) {
510 if (!del_vars.exists(var)) {
511 equal = false;
512 break;
513 }
514 }
515 if (equal) { return Tensor< GUM_SCALAR >().fillWith(this->min()); }
516 }
517
518 return Tensor< GUM_SCALAR >(gum::projectMin(*this->content(), del_vars));
519 }
520
521 template < typename GUM_SCALAR >
522 INLINE Tensor< GUM_SCALAR > Tensor< GUM_SCALAR >::maxOut(const gum::VariableSet& del_vars) const {
523 if (static_cast< MultiDimContainer< GUM_SCALAR >* >(this->content_)->empty()) {
524 return Tensor< GUM_SCALAR >().fillWith(this->empty_value_);
525 }
526
527 // if we remove all the variables, create an empty tensor
528 // TODO: remove this test when operations will be able to handle empty tensors
529 if (this->variablesSequence().size() <= del_vars.size()) {
530 bool equal = true;
531 for (const auto var: this->variablesSequence()) {
532 if (!del_vars.exists(var)) {
533 equal = false;
534 break;
535 }
536 }
537 if (equal) { return Tensor< GUM_SCALAR >().fillWith(this->max()); }
538 }
539
540 return Tensor< GUM_SCALAR >(gum::projectMax(*this->content(), del_vars));
541 }
542
543 template < typename GUM_SCALAR >
544 INLINE Tensor< GUM_SCALAR > Tensor< GUM_SCALAR >::sumIn(const gum::VariableSet& kept_vars) const {
545 if (static_cast< MultiDimContainer< GUM_SCALAR >* >(this->content_)->empty()) {
546 return Tensor< GUM_SCALAR >().fillWith(this->empty_value_);
547 }
548
549 // if kept_var is empty, create an empty tensor
550 // TODO: remove this test when operations will be able to handle empty tensors
551 if (kept_vars.empty()) { return Tensor< GUM_SCALAR >().fillWith(this->sum()); }
552
553 return Tensor< GUM_SCALAR >(gum::projectSum(*this->content(), complementVars_(kept_vars)));
554 }
555
556 template < typename GUM_SCALAR >
557 INLINE Tensor< GUM_SCALAR >
559 if (static_cast< MultiDimContainer< GUM_SCALAR >* >(this->content_)->empty()) {
560 return Tensor< GUM_SCALAR >().fillWith(this->empty_value_);
561 }
562
563 // if kept_var is empty, create an empty tensor
564 // TODO: remove this test when operations will be able to handle empty tensors
565 if (kept_vars.empty()) { return Tensor< GUM_SCALAR >().fillWith(this->product()); }
566
567 return Tensor< GUM_SCALAR >(gum::projectProduct(*this->content(), complementVars_(kept_vars)));
568 }
569
570 template < typename GUM_SCALAR >
571 INLINE Tensor< GUM_SCALAR > Tensor< GUM_SCALAR >::minIn(const gum::VariableSet& kept_vars) const {
572 if (static_cast< MultiDimContainer< GUM_SCALAR >* >(this->content_)->empty()) {
573 return Tensor< GUM_SCALAR >().fillWith(this->empty_value_);
574 }
575
576 // if kept_var is empty, create an empty tensor
577 // TODO: remove this test when operations will be able to handle empty tensors
578 if (kept_vars.empty()) { return Tensor< GUM_SCALAR >().fillWith(this->min()); }
579
580 return Tensor< GUM_SCALAR >(gum::projectMin(*this->content(), complementVars_(kept_vars)));
581 }
582
583 template < typename GUM_SCALAR >
584 INLINE Tensor< GUM_SCALAR > Tensor< GUM_SCALAR >::maxIn(const gum::VariableSet& kept_vars) const {
585 if (static_cast< MultiDimContainer< GUM_SCALAR >* >(this->content_)->empty()) {
586 return Tensor< GUM_SCALAR >().fillWith(this->empty_value_);
587 }
588
589 // if kept_var is empty, create an empty tensor
590 // TODO: remove this test when operations will be able to handle empty tensors
591 if (kept_vars.empty()) { return Tensor< GUM_SCALAR >().fillWith(this->max()); }
592
593 return Tensor< GUM_SCALAR >(gum::projectMax(*this->content(), complementVars_(kept_vars)));
594 }
595
596 template < typename GUM_SCALAR >
597 INLINE Tensor< GUM_SCALAR > Tensor< GUM_SCALAR >::isNonZeroMap() const {
598 auto p = Tensor< GUM_SCALAR >(*this);
599 p.apply([](GUM_SCALAR x) {
600 if (x != static_cast< GUM_SCALAR >(0)) return static_cast< GUM_SCALAR >(1);
601 else return static_cast< GUM_SCALAR >(0);
602 });
603 return p;
604 }
605
606 template < typename GUM_SCALAR >
608 gum::VariableSet cplt;
609
610 for (const auto x: this->variablesSequence())
611 if (!vars.contains(x)) cplt.insert(x);
612
613 return cplt;
614 }
615
616 template < typename GUM_SCALAR >
617 Tensor< GUM_SCALAR >
618 Tensor< GUM_SCALAR >::reorganize(const std::vector< const DiscreteVariable* >& vars) const {
619 if (vars.size() != this->nbrDim())
621 "The argument contains " << vars.size() << " variables instead of "
622 << this->nbrDim() << ".")
623 for (const auto var: vars) {
624 if (!this->contains(*var))
625 GUM_ERROR(InvalidArgument, "A variable in the argument does not belong to the tensor.")
626 }
627
628 Tensor< GUM_SCALAR > p;
629 p.beginMultipleChanges();
630 for (const auto var: vars)
631 p.add(*var);
632 p.endMultipleChanges();
633 p.copyFrom(*this, nullptr); // copy *this in p using the same order
634
635 return p;
636 }
637
638 template < typename GUM_SCALAR >
639 Tensor< GUM_SCALAR >
640 Tensor< GUM_SCALAR >::reorganize(const std::vector< std::string >& vars) const {
641 std::vector< const DiscreteVariable* > res;
642
644 for (gum::Idx i = 0; i < this->nbrDim(); i++)
645 namesToVars.insert(this->variable(i).name(), &(this->variable(i)));
646
647 for (const auto& name: vars) {
648 if (!namesToVars.exists(name)) {
649 GUM_ERROR(gum::InvalidArgument,
650 "'" << name << "' is a not a name of a variable in this tensor")
651 }
652 res.push_back(namesToVars[name]);
653 }
654 return reorganize(res);
655 }
656
657 template < typename GUM_SCALAR >
658 Tensor< GUM_SCALAR > Tensor< GUM_SCALAR >::putFirst(const DiscreteVariable* var) const {
659 if (!this->contains(*var)) {
660 GUM_ERROR(InvalidArgument, "The variable to put first does not belong to the tensor")
661 }
662 if (&(this->variable(0)) == var) return Tensor< GUM_SCALAR >(*this);
663
664 std::vector< const DiscreteVariable* > vars;
665 vars.push_back(var);
666 for (Idx i = 0; i < this->nbrDim(); i++)
667 if (&(this->variable(i)) != var) vars.push_back(&(this->variable(i)));
668
669 return this->reorganize(vars);
670 }
671
672 template < typename GUM_SCALAR >
673 Tensor< GUM_SCALAR > Tensor< GUM_SCALAR >::putFirst(const std::string& varname) const {
674 const DiscreteVariable* var = nullptr;
675
676 for (gum::Idx i = 0; i < this->nbrDim(); i++)
677 if (this->variable(i).name() == varname) {
678 var = &(this->variable(i));
679 break;
680 }
681 if (var == nullptr)
683 "The variable '" << varname << "' to put first does not belong to the tensor")
684 return this->putFirst(var);
685 }
686
687 template < typename GUM_SCALAR >
688 Tensor< GUM_SCALAR > Tensor< GUM_SCALAR >::extract(const Instantiation& inst) const {
689 Tensor< GUM_SCALAR > p;
690 p.extractFrom(*this, inst);
691
692 return p;
693 }
694
695 template < typename GUM_SCALAR >
697 if (this->nbrDim() != 1) {
698 GUM_ERROR(FatalError, "To draw from a tensor, the dimension must be 1")
699 }
700
701 auto r = static_cast< GUM_SCALAR >(randomProba());
702 Instantiation Ip(*this);
703 for (Ip.setFirst(); !Ip.end(); Ip.inc()) {
704 r -= this->get(Ip);
705 if (r <= 0) return Ip.val(0);
706 }
707 return this->variable(0).domainSize() - 1;
708 }
709
710 template < typename GUM_SCALAR >
711 std::ostream& operator<<(std::ostream& out, const Tensor< GUM_SCALAR >& array) {
712 out << array.toString();
713 return out;
714 }
715
716 // argmax of all elements in this
717 template < typename GUM_SCALAR >
719 Instantiation I(*this);
721
722 // if (static_cast< MultiDimContainer< GUM_SCALAR >* >(this->content_)->empty()) { return
723 // res; }
724 for (I.setFirst(); !I.end(); ++I) {
725 if (this->get(I) == v) res.insert(Instantiation(I, false));
726 }
727 return res;
728 }
729
730 // argmax of all elements in this
731 template < typename GUM_SCALAR >
732 INLINE std::pair< Set< Instantiation >, GUM_SCALAR > Tensor< GUM_SCALAR >::argmax() const {
733 auto m = max();
734 return std::pair(findAll(m), m);
735 }
736
737 // argmin of all elements in this
738 template < typename GUM_SCALAR >
739 INLINE std::pair< Set< Instantiation >, GUM_SCALAR > Tensor< GUM_SCALAR >::argmin() const {
740 auto m = min();
741 return std::pair(findAll(m), m);
742 }
743
744 template < typename GUM_SCALAR >
745 const Tensor< GUM_SCALAR >& Tensor< GUM_SCALAR >::random() const {
746 if (this->domainSize() == 0) return *this;
747
748 std::vector< GUM_SCALAR > v;
749 v.reserve(this->domainSize());
750 for (Size i = 0; i < this->domainSize(); ++i) {
751 auto r = (GUM_SCALAR)randomProba();
752 v.push_back(r);
753 }
754 this->fillWith(v);
755 return *this;
756 }
757
758 template < typename GUM_SCALAR >
759 INLINE const Tensor< GUM_SCALAR >& Tensor< GUM_SCALAR >::randomDistribution() const {
760 if (this->domainSize() == 0) {
761 this->fillWith((GUM_SCALAR)1.0);
762 } else {
764 }
765
766 return *this;
767 }
768
769 template < typename GUM_SCALAR >
770 INLINE const Tensor< GUM_SCALAR >& Tensor< GUM_SCALAR >::randomCPT() const {
771 if (this->domainSize() == 0) {
772 this->fillWith((GUM_SCALAR)1.0);
773 } else {
774 gum::Instantiation I(*this);
775 const auto& v = this->variable(0);
776 for (I.setFirstNotVar(v); !I.end(); I.incNotVar(v)) {
777 const auto& distrib = gum::randomDistribution< GUM_SCALAR >(v.domainSize());
778 for (I.setFirstVar(v); !I.end(); I.incVar(v)) {
779 this->set(I, distrib[I.val(0)]);
780 }
781 I.unsetEnd();
782 }
783 }
784 return *this;
785 }
786
787 template < typename GUM_SCALAR >
788 const Tensor< GUM_SCALAR >& Tensor< GUM_SCALAR >::noising(GUM_SCALAR alpha) const {
789 if ((alpha < GUM_SCALAR(0.0)) || (alpha > GUM_SCALAR(1.0))) {
790 GUM_ERROR(InvalidArgument, "alpha must be in [0,1]")
791 }
792 Tensor< GUM_SCALAR > noise(*this);
793 return fillWith(scale(1 - alpha) + noise.randomCPT().scale(alpha)).normalizeAsCPT();
794 }
795
796 template < typename GUM_SCALAR >
797 Tensor< GUM_SCALAR > Tensor< GUM_SCALAR >::new_abs() const {
798 return Tensor< GUM_SCALAR >(*this).abs();
799 }
800
801 template < typename GUM_SCALAR >
802 Tensor< GUM_SCALAR > Tensor< GUM_SCALAR >::new_sq() const {
803 return Tensor< GUM_SCALAR >(*this).sq();
804 }
805
806 template < typename GUM_SCALAR >
807 Tensor< GUM_SCALAR > Tensor< GUM_SCALAR >::new_log2() const {
808 return Tensor< GUM_SCALAR >(*this).log2();
809 }
810
811 template < typename GUM_SCALAR >
812 Tensor< GUM_SCALAR > Tensor< GUM_SCALAR >::new_sgn() const {
813 return Tensor< GUM_SCALAR >(*this).sgn();
814 }
815
816 template < typename GUM_SCALAR >
817 Tensor< GUM_SCALAR >& Tensor< GUM_SCALAR >::operator<<(const DiscreteVariable& v) {
818 this->add(v);
819 return *this;
820 }
821
823 template < typename GUM_SCALAR >
824 Tensor< GUM_SCALAR > Tensor< GUM_SCALAR >::operator+(const Tensor< GUM_SCALAR >& p2) const {
825 if (p2.empty()) return Tensor< GUM_SCALAR >(*this).translate(p2.empty_value_);
826 if (this->empty()) return Tensor< GUM_SCALAR >(p2).translate(this->empty_value_);
827
828 return Tensor< GUM_SCALAR >(*this->content() + *p2.content());
829 }
830
832 template < typename GUM_SCALAR >
833 Tensor< GUM_SCALAR > Tensor< GUM_SCALAR >::operator+(const GUM_SCALAR& v) const {
834 return Tensor< GUM_SCALAR >(*this).translate(v);
835 }
836
838 template < typename GUM_SCALAR >
840 if (this->nbrDim() != 1) return false;
841 if (this->sum() <= 0.0) return false;
842 return (this->min() >= 0.0) && (this->max() <= 1.0);
843 }
844
845 // max function between two evidence
846 template < typename GUM_SCALAR >
847 Tensor< GUM_SCALAR > Tensor< GUM_SCALAR >::operator|(const Tensor< GUM_SCALAR >& p2) const {
848 if (!isEvidence() || !p2.isEvidence())
849 GUM_ERROR(InvalidArgument, "The tensors are not evidences.")
850 if (this->variable(0) != p2.variable(0))
851 GUM_ERROR(InvalidArgument, "The evidence are not on the same variable.")
852 Tensor< GUM_SCALAR > res(*this);
853 gum::Instantiation I(res);
854 for (I.setFirst(); !I.end(); ++I) {
855 res.set(I, std::max(res.get(I), p2.get(I)));
856 }
857 return res;
858 }
859
860 // min function between two evidence
861 template < typename GUM_SCALAR >
862 Tensor< GUM_SCALAR > Tensor< GUM_SCALAR >::operator&(const Tensor< GUM_SCALAR >& p2) const {
863 if (!isEvidence() || !p2.isEvidence())
864 GUM_ERROR(InvalidArgument, "The tensors are not evidences.")
865 if (this->variable(0) != p2.variable(0))
866 GUM_ERROR(InvalidArgument, "The evidence are not on the same variable.")
867 Tensor< GUM_SCALAR > res(*this);
868 gum::Instantiation I(res);
869 for (I.setFirst(); !I.end(); ++I) {
870 res.set(I, std::min(res.get(I), p2.get(I)));
871 }
872 return res;
873 }
874
875 // complement function between two evidence
876 template < typename GUM_SCALAR >
877 Tensor< GUM_SCALAR > Tensor< GUM_SCALAR >::operator~() const {
878 if (!isEvidence()) GUM_ERROR(InvalidArgument, "The tensor is not an evidence.")
879
880 Tensor< GUM_SCALAR > res(*this);
881 gum::Instantiation I(res);
882 for (I.setFirst(); !I.end(); ++I) {
883 res.set(I, 1 - res.get(I));
884 }
885 return res;
886 }
887
889 template < typename GUM_SCALAR >
890 Tensor< GUM_SCALAR > Tensor< GUM_SCALAR >::operator-(const Tensor< GUM_SCALAR >& p2) const {
891 if (p2.empty()) return Tensor< GUM_SCALAR >(*this).translate(-p2.empty_value_);
892 if (this->empty()) {
893 auto p = Tensor< GUM_SCALAR >(p2);
894 p.apply([this](GUM_SCALAR x) { return this->empty_value_ - x; });
895 return p;
896 }
897 return Tensor< GUM_SCALAR >(*this->content() - *p2.content());
898 }
899
901 template < typename GUM_SCALAR >
902 Tensor< GUM_SCALAR > Tensor< GUM_SCALAR >::operator-(const GUM_SCALAR& v) const {
903 return Tensor< GUM_SCALAR >(*this).translate(-v);
904 }
905
907 template < typename GUM_SCALAR >
908 Tensor< GUM_SCALAR > Tensor< GUM_SCALAR >::operator*(const Tensor< GUM_SCALAR >& p2) const {
909 if (p2.empty()) return Tensor< GUM_SCALAR >(*this).scale(p2.empty_value_);
910 if (this->empty()) return Tensor< GUM_SCALAR >(p2).scale(this->empty_value_);
911
912 return Tensor< GUM_SCALAR >(*this->content() * *p2.content());
913 }
914
916 template < typename GUM_SCALAR >
917 Tensor< GUM_SCALAR > Tensor< GUM_SCALAR >::operator*(const GUM_SCALAR& v) const {
918 return Tensor< GUM_SCALAR >(*this).scale(v);
919 }
920
922 template < typename GUM_SCALAR >
923 Tensor< GUM_SCALAR > Tensor< GUM_SCALAR >::operator/(const Tensor< GUM_SCALAR >& p2) const {
924 if (p2.empty()) return Tensor< GUM_SCALAR >(*this).scale(1 / p2.empty_value_);
925 if (this->empty()) {
926 auto p = Tensor< GUM_SCALAR >(p2);
927 p.apply([this](GUM_SCALAR x) { return this->empty_value_ / x; });
928 return p;
929 }
930 return Tensor< GUM_SCALAR >(*this->content() / *p2.content());
931 }
932
934 template < typename GUM_SCALAR >
935 Tensor< GUM_SCALAR > Tensor< GUM_SCALAR >::operator/(const GUM_SCALAR& v) const {
936 return Tensor< GUM_SCALAR >(*this).scale(1 / v);
937 }
938
939 template < typename GUM_SCALAR >
940 Tensor< GUM_SCALAR >& Tensor< GUM_SCALAR >::operator+=(const Tensor< GUM_SCALAR >& r) {
941 *this = *this + r;
942 return *this;
943 }
944
945 template < typename GUM_SCALAR >
946 Tensor< GUM_SCALAR >& Tensor< GUM_SCALAR >::operator+=(const GUM_SCALAR& v) {
947 this->translate(v);
948 return *this;
949 }
950
951 template < typename GUM_SCALAR >
952 Tensor< GUM_SCALAR >& Tensor< GUM_SCALAR >::operator*=(const Tensor< GUM_SCALAR >& r) {
953 *this = *this * r;
954 return *this;
955 }
956
957 template < typename GUM_SCALAR >
958 Tensor< GUM_SCALAR >& Tensor< GUM_SCALAR >::operator*=(const GUM_SCALAR& v) {
959 this->scale(v);
960 return *this;
961 }
962
963 template < typename GUM_SCALAR >
964 Tensor< GUM_SCALAR >& Tensor< GUM_SCALAR >::operator-=(const Tensor< GUM_SCALAR >& r) {
965 *this = *this - r;
966 return *this;
967 }
968
969 template < typename GUM_SCALAR >
970 Tensor< GUM_SCALAR >& Tensor< GUM_SCALAR >::operator-=(const GUM_SCALAR& v) {
971 this->translate(-v);
972 return *this;
973 }
974
975 template < typename GUM_SCALAR >
976 Tensor< GUM_SCALAR >& Tensor< GUM_SCALAR >::operator/=(const Tensor< GUM_SCALAR >& r) {
977 *this = *this / r;
978 return *this;
979 }
980
981 template < typename GUM_SCALAR >
982 Tensor< GUM_SCALAR >& Tensor< GUM_SCALAR >::operator/=(const GUM_SCALAR& v) {
983 this->scale(1 / v);
984 return *this;
985 }
986
987 template < typename GUM_SCALAR >
988 bool Tensor< GUM_SCALAR >::operator==(const Tensor< GUM_SCALAR >& r) const {
989 if (this->empty()) {
990 if (r.empty()) return this->empty_value_ == r.empty_value_;
991 else return false;
992 } else {
993 if (r.empty()) return false;
994 else return (*this->content_) == (*r.content_);
995 }
996 }
997
998 template < typename GUM_SCALAR >
999 std::string Tensor< GUM_SCALAR >::toString() const {
1000 auto table = this->content();
1001 std::stringstream ss;
1002
1003 if (table->nbrDim() == 0) {
1004 Instantiation I(this);
1005 ss << "[" << this->get(I) << "]";
1006 return ss.str();
1007 }
1008 const Size colwidth = 6;
1009 const Size numberwidth = 9;
1010 const Size nbrLigMax = 6;
1011
1012 ss << std::left << std::fixed << std::endl;
1013 ss.precision(numberwidth - 5);
1014
1015 const auto& var = table->variable(0);
1016
1017 const Size nbparents = table->nbrDim() - 1;
1018 const Size nbcol = var.domainSize();
1019 const std::string maskparent(colwidth, '-');
1020 const std::string masknumber(numberwidth, '-');
1021
1022 if (nbparents > 0)
1023 ss << std::setw(nbparents * (colwidth + 1) - 1) << " "
1024 << "||";
1025 ss << " " << std::setw(nbcol * (numberwidth + 1) - 3)
1026 << var.name().substr(0, nbcol * (numberwidth + 1) - 3) << "|";
1027 ss << std::endl;
1028
1029 if (nbparents > 0) {
1030 for (Idx i = 1; i <= nbparents; i++)
1031 ss << std::setw(colwidth) << table->variable(i).name().substr(0, colwidth) << "|";
1032 ss << "|";
1033 }
1034 for (Idx i = 0; i < nbcol; i++)
1035 ss << std::setw(numberwidth) << var.label(i).substr(0, numberwidth) << "|";
1036 ss << std::endl;
1037
1038
1039 if (nbparents > 0) {
1040 for (Idx i = 1; i <= nbparents; i++)
1041 ss << maskparent << "|";
1042 ss << "|";
1043 }
1044 for (Idx i = 0; i < nbcol; i++)
1045 ss << masknumber << "|";
1046 ss << std::endl;
1047 Instantiation I(*table);
1048
1049 const auto drawligne = [&]() {
1050 if (nbparents > 0) {
1051 for (Idx i = 1; i <= nbparents; i++)
1052 ss << std::setw(colwidth) << table->variable(i).label(I.val(i)).substr(0, colwidth)
1053 << "|";
1054 ss << "|";
1055 }
1056 for (I.setFirstVar(var); !I.end(); I.incVar(var))
1057 ss << " " << std::setw(numberwidth - 1) << table->get(I) << "|";
1058 I.setFirstVar(var);
1059 ss << std::endl;
1060 };
1061
1062 if (const Size nbrLig = table->domainSize() / var.domainSize(); nbrLig < nbrLigMax * 2 + 1) {
1063 for (I.setFirst(); !I.end(); I.incNotVar(var))
1064 drawligne();
1065 } else {
1066 Size cpt = 0;
1067 for (I.setFirst(); !I.end(); I.incNotVar(var)) {
1068 cpt++;
1069 if (cpt > nbrLigMax) break;
1070 drawligne();
1071 }
1072 ss << "[..." << nbrLig - nbrLigMax * 2 << " more line(s) ...]" << std::endl;
1073 I.setLast();
1074 for (Idx revi = 1; revi < nbrLigMax; revi++)
1075 I.decNotVar(var);
1076 for (I.setFirstVar(var); !I.end(); I.incNotVar(var)) {
1077 drawligne();
1078 }
1079 }
1080
1081 return ss.str();
1082 }
1083
1084 template < typename GUM_SCALAR >
1085 Tensor< GUM_SCALAR > Tensor< GUM_SCALAR >::evEq(const DiscreteVariable& v, double val) {
1086 const auto i = v.closestIndex(val);
1087
1089 p.add(v);
1090 p.fillWith(0);
1091 Instantiation I(p);
1092 I.chgVal(0, i);
1093 p.set(I, 1);
1094 return p;
1095 }
1096
1097 template < typename GUM_SCALAR >
1098 Tensor< GUM_SCALAR >
1099 Tensor< GUM_SCALAR >::evIn(const DiscreteVariable& v, double val1, double val2) {
1100 if (val2 < val1) {
1102 "val2 (" << val2 << ") must be greater than val1 (" << val1 << ").")
1103 }
1104 const auto i1 = v.closestIndex(val1);
1105 const auto i2 = v.closestIndex(val2);
1106
1108 p.add(v);
1109 p.fillWith(0);
1110 Instantiation I(p);
1111 for (Idx i = i1; i <= i2; i++) {
1112 I.chgVal(0, i);
1113 p.set(I, 1);
1114 }
1115 return p;
1116 }
1117
1118 template < typename GUM_SCALAR >
1119 Tensor< GUM_SCALAR > Tensor< GUM_SCALAR >::evGt(const DiscreteVariable& v, double val) {
1120 const auto i = v.closestIndex(val);
1121 if (i == v.domainSize() - 1) { return evEq(v, val); }
1122
1124 p.add(v);
1125 p.fillWith(0);
1126 Instantiation I(p);
1127 for (Idx i2 = i + 1; i2 < v.domainSize(); i2++) {
1128 I.chgVal(0, i2);
1129 p.set(I, 1);
1130 }
1131 return p;
1132 }
1133
1134 template < typename GUM_SCALAR >
1135 Tensor< GUM_SCALAR > Tensor< GUM_SCALAR >::evLt(const DiscreteVariable& v, double val) {
1136 const auto i = v.closestIndex(val);
1137 if (i == 0) { return evEq(v, val); }
1138
1140 p.add(v);
1141 p.fillWith(0);
1142 Instantiation I(p);
1143 for (Idx i2 = 0; i2 < i; i2++) {
1144 I.chgVal(0, i2);
1145 p.set(I, 1);
1146 }
1147 return p;
1148 }
1149
1150 template < typename GUM_SCALAR >
1152 return this->content()->realSize() * sizeof(GUM_SCALAR);
1153 }
1154
1155 template < typename GUM_SCALAR >
1157 Idx value) {
1158 Tensor< GUM_SCALAR > pot;
1159
1160 pot.beginMultipleChanges();
1161 pot << var;
1162 pot.endMultipleChanges(GUM_SCALAR(0.0));
1163
1164 Instantiation I(pot);
1165 I.chgVal(var, value);
1166 pot.set(I, GUM_SCALAR(1.0));
1167
1168 return pot;
1169 }
1170
1171 template < typename GUM_SCALAR >
1173 const std::string& value) {
1174 return Tensor< GUM_SCALAR >::deterministicTensor(var, var.index(value));
1175 }
1176
1177 template < typename GUM_SCALAR >
1179 Tensor< GUM_SCALAR > pot;
1180
1181 pot.beginMultipleChanges();
1182 pot << var;
1183 pot.endMultipleChanges(GUM_SCALAR(1.0));
1184
1185 pot.normalize();
1186
1187 return pot;
1188 }
1189} /* namespace gum */
Base class for discrete random variable.
virtual Idx index(const std::string &label) const =0
virtual Idx closestIndex(double val) const =0
for numerical variables, returns the closest index for the value
virtual Size domainSize() const =0
Exception : fatal (unknown ?) error.
The class for generic Hash Tables.
Definition hashTable.h:637
bool exists(const Key &key) const
Checks whether there exists an element with a given key in the hashtable.
value_type & insert(const Key &key, const Val &val)
Adds a new element (actually a copy of this element) into the hash table.
Class for assigning/browsing values to tuples of discrete variables.
void decNotVar(const DiscreteVariable &v)
Operator decrement for vars which are not v.
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 incVar(const DiscreteVariable &v)
Operator increment for variable v only.
void setFirstNotVar(const DiscreteVariable &v)
Assign the first values to variables different of v.
void add(const DiscreteVariable &v) final
Adds a new variable in the Instantiation.
void incNotVar(const DiscreteVariable &v)
Operator increment for vars which are not v.
void setFirstVar(const DiscreteVariable &v)
Assign the first value in the Instantiation for var v.
void inc()
Operator increment.
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 unsetEnd()
Alias for unsetOverflow().
const DiscreteVariable & variable(Idx i) const final
Returns the variable at position i in the tuple.
void setLast()
Assign the last values in the Instantiation.
Exception: at least one argument passed to a function is not what was expected.
Multidimensional matrix stored as an array in memory.
Abstract base class for all multi dimensionnal containers.
virtual const MultiDimImplementation< GUM_SCALAR > * content() const =0
Returns the implementation for this object (may be *this).
virtual const Sequence< const DiscreteVariable * > & variablesSequence() const final
Returns a const ref to the sequence of DiscreteVariable*.
GUM_SCALAR empty_value_
value of the MultiDimDecorator if no dimension.
MultiDimDecorator< GUM_SCALAR > & operator=(const MultiDimDecorator &from) noexcept
copy operator
virtual GUM_SCALAR reduce(std::function< GUM_SCALAR(GUM_SCALAR, GUM_SCALAR) > f, GUM_SCALAR base) const final
compute lfold for this container
virtual bool empty() const final
Returns true if no var is in *this.
virtual Idx nbrDim() const final
Returns the number of vars in the multidimensional container.
MultiDimDecorator(MultiDimImplementation< GUM_SCALAR > *aContent=nullptr, GUM_SCALAR empty_value=(GUM_SCALAR) 0)
Class constructor.
virtual void endMultipleChanges() final
Default implementation of MultiDimContainer::set().
virtual GUM_SCALAR get(const Instantiation &i) const final
Default implementation of MultiDimContainer::get().
virtual void populate(const std::vector< GUM_SCALAR > &v) const final
Automatically fills this MultiDimContainer with the values in v.
MultiDimImplementation< GUM_SCALAR > * content_
The true container.
virtual void add(const DiscreteVariable &v) final
Adds a new var to the variables of the multidimensional matrix.
virtual bool contains(const DiscreteVariable &var) const final
Returns true if var is in *this.
virtual void apply(std::function< GUM_SCALAR(GUM_SCALAR) > f) const final
Apply a function on every element of the container.
virtual void beginMultipleChanges() final
Default implementation of MultiDimContainer::set().
virtual void fill(const GUM_SCALAR &d) const final
Default implementation of MultiDimContainer::set().
virtual Size domainSize() const final
Returns the product of the variables domain size.
virtual const MultiDimImplementation< GUM_SCALAR > * content() const final
Returns the implementation for this object (may be *this).
virtual const DiscreteVariable & variable(Idx) const final
Returns a const ref to the ith var.
virtual void set(const Instantiation &i, const GUM_SCALAR &value) const final
Default implementation of MultiDimContainer::set().
<agrum/base/multidim/multiDimImplementation.h>
virtual const Sequence< const DiscreteVariable * > & variablesSequence() const =0
Returns a const ref to the sequence of DiscreteVariable*.
virtual bool empty() const =0
Returns true if no var is in *this.
Size size() const noexcept
Returns the number of elements in the set.
Definition set_tpl.h:636
bool exists(const Key &k) const
Indicates whether a given elements belong to the set.
Definition set_tpl.h:533
bool contains(const Key &k) const
Indicates whether a given elements belong to the set.
Definition set_tpl.h:497
void insert(const Key &k)
Inserts a new element into the set.
Definition set_tpl.h:539
bool empty() const noexcept
Indicates whether the set is the empty set.
Definition set_tpl.h:642
aGrUM's Tensor is a multi-dimensional array with tensor operators.
Definition tensor.h:85
Tensor< GUM_SCALAR > & operator-=(const Tensor< GUM_SCALAR > &r)
the function to be used to add two Tensors
Definition tensor_tpl.h:964
Tensor< GUM_SCALAR > & operator/=(const Tensor< GUM_SCALAR > &r)
the function to be used to add two Tensors
Definition tensor_tpl.h:976
const Tensor< GUM_SCALAR > & fillWith(const Tensor< GUM_SCALAR > &src) const
copy a Tensor data using name of variables and labels (not necessarily the same variables in the same...
Definition tensor_tpl.h:271
const Tensor< GUM_SCALAR > & normalizeAsCPT(const Idx &varId=0) const
normalisation of this as a CPT for the variable varId
Definition tensor_tpl.h:405
Idx draw() const
get a value at random from a 1-D distribution
Definition tensor_tpl.h:696
Tensor< GUM_SCALAR > operator|(const Tensor< GUM_SCALAR > &p2) const
the function to be used to add two Tensors
Definition tensor_tpl.h:847
GUM_SCALAR minNonZero() const
min of all non zero elements in the Tensor
Definition tensor_tpl.h:215
std::pair< Set< Instantiation >, GUM_SCALAR > argmin() const
Pair of the set of instantiation corresponding to the min and this min in the Tensor.
Definition tensor_tpl.h:739
Tensor< GUM_SCALAR > extract(const Instantiation &inst) const
create a new Tensor extracted from *this given a partial instantiation
Definition tensor_tpl.h:688
const Tensor< GUM_SCALAR > & random() const
generate a random Tensor with each parameter in [0,1]
Definition tensor_tpl.h:745
Tensor< GUM_SCALAR > new_sq() const
Create a new tensor and apply $x^2$ on every element of the container.
Definition tensor_tpl.h:802
Tensor< GUM_SCALAR > putFirst(const DiscreteVariable *var) const
create a new Tensor with a certain variable in first
Definition tensor_tpl.h:658
Tensor< GUM_SCALAR > prodIn(const gum::VariableSet &kept_vars) const
Projection using multiplication as operation (and implementation-optimized operations).
Definition tensor_tpl.h:558
Tensor< GUM_SCALAR > maxOut(const gum::VariableSet &del_vars) const
Projection using max as operation (and implementation-optimized operations).
Definition tensor_tpl.h:522
gum::VariableSet complementVars_(const gum::VariableSet &del_vars) const
Definition tensor_tpl.h:607
Tensor< GUM_SCALAR > * newFactory() const final
Default implementation of MultiDimContainer::set().
Definition tensor_tpl.h:150
static Tensor< GUM_SCALAR > evEq(const DiscreteVariable &v, double val)
numerical evidence generator
Tensor< GUM_SCALAR > sumOut(const gum::VariableSet &del_vars) const
Projection using sum as operation (and implementation-optimized operations).
Definition tensor_tpl.h:455
Tensor< GUM_SCALAR > reorganize(const std::vector< const DiscreteVariable * > &vars) const
create a new Tensor with another order
Definition tensor_tpl.h:618
Tensor< GUM_SCALAR > operator&(const Tensor< GUM_SCALAR > &p2) const
the function to be used to add two Tensors
Definition tensor_tpl.h:862
Size memoryFootprint() const
compute the (approximated) footprint in memory of the tensor
Tensor< GUM_SCALAR > new_sgn() const
Create a new tensor and apply sgn(x)$ on every element of the container.
Definition tensor_tpl.h:812
GUM_SCALAR maxNonOne() const
max of all non one elements in the Tensor
Definition tensor_tpl.h:194
bool operator==(const Tensor< GUM_SCALAR > &r) const
the function to be used to add two Tensors
Definition tensor_tpl.h:988
static Tensor< GUM_SCALAR > deterministicTensor(const DiscreteVariable &var, Idx value)
Tensor< GUM_SCALAR > new_log2() const
Create a new tensor and apply $log_2(x)$ on every element of the container.
Definition tensor_tpl.h:807
static Tensor< GUM_SCALAR > uniformTensor(const DiscreteVariable &var)
const Tensor< GUM_SCALAR > & scale(GUM_SCALAR v) const
multiply (each value of) *this by v
Definition tensor_tpl.h:437
GUM_SCALAR entropy() const
entropy of the Tensor
Definition tensor_tpl.h:250
Tensor< GUM_SCALAR > minOut(const gum::VariableSet &del_vars) const
Projection using min as operation (and implementation-optimized operations).
Definition tensor_tpl.h:500
GUM_SCALAR KL(const Tensor< GUM_SCALAR > &p) const
compute KL divergence between this and p Checks the compatibility and then compute KL divergence
Definition tensor_tpl.h:349
static Tensor< GUM_SCALAR > evGt(const DiscreteVariable &v, double val)
numerical evidence generator
~Tensor() final
Destructor.
Definition tensor_tpl.h:144
Tensor< GUM_SCALAR > sumIn(const gum::VariableSet &kept_vars) const
Projection using sum as operation (and implementation-optimized operations).
Definition tensor_tpl.h:544
Set< Instantiation > findAll(GUM_SCALAR v) const
set of instantiation corresponding to the parameter v in the Tensor
Definition tensor_tpl.h:718
static Tensor< GUM_SCALAR > evIn(const DiscreteVariable &v, double val1, double val2)
numerical evidence generator
const Tensor< GUM_SCALAR > & sq() const
apply $x^2$ on every element of the container
Definition tensor_tpl.h:331
const Tensor< GUM_SCALAR > & normalize() const
normalisation of this do nothing if sum is 0
Definition tensor_tpl.h:390
std::pair< Set< Instantiation >, GUM_SCALAR > argmax() const
Pair of the set of instantiation corresponding to the max and this max in the Tensor.
Definition tensor_tpl.h:732
const Tensor< GUM_SCALAR > & translate(GUM_SCALAR v) const
add v to (each value of) *this
Definition tensor_tpl.h:443
const Tensor< GUM_SCALAR > & noising(GUM_SCALAR alpha) const
add a noise in a CPT by mixing (1-alpha)this+alpha.randomCPT()
Definition tensor_tpl.h:788
const Tensor< GUM_SCALAR > & sgn() const
apply sgn(x)$ on every element of the container
Definition tensor_tpl.h:343
bool isEvidence() const
is an evidence ? (marginal-like but has not to sum to 1)
Definition tensor_tpl.h:839
Tensor< GUM_SCALAR > & operator=(const Tensor< GUM_SCALAR > &src)
Default constructor.
Definition tensor_tpl.h:124
const Tensor< GUM_SCALAR > & randomDistribution() const
generate a random Distribution in the Tensor
Definition tensor_tpl.h:759
GUM_SCALAR sum() const
sum of all elements in the Tensor
Definition tensor_tpl.h:157
const Tensor< GUM_SCALAR > & randomCPT() const
generate a random CPT in the Tensor
Definition tensor_tpl.h:770
Tensor< GUM_SCALAR > operator/(const Tensor< GUM_SCALAR > &p2) const
the function to be used to divide two Tensors
Definition tensor_tpl.h:923
Tensor< GUM_SCALAR > minIn(const gum::VariableSet &kept_vars) const
Projection using min as operation (and implementation-optimized operations).
Definition tensor_tpl.h:571
Tensor()
Default constructor.
Definition tensor_tpl.h:61
GUM_SCALAR max() const
max of all elements in the Tensor
Definition tensor_tpl.h:175
GUM_SCALAR expectedValue(std::function< GUM_SCALAR(const gum::Instantiation &) >) const
ExpectedValue computes the expectation of f over *this.
Definition tensor_tpl.h:233
Tensor< GUM_SCALAR > new_abs() const
Create a new tensor and apply abs on every element of the container.
Definition tensor_tpl.h:797
Tensor< GUM_SCALAR > maxIn(const gum::VariableSet &kept_vars) const
Projection using max as operation (and implementation-optimized operations).
Definition tensor_tpl.h:584
GUM_SCALAR product() const
product of all elements in the Tensor
Definition tensor_tpl.h:166
Tensor< GUM_SCALAR > & operator<<(const DiscreteVariable &v)
the function to be used to add two Tensors
Definition tensor_tpl.h:817
const Tensor< GUM_SCALAR > & abs() const
Apply abs on every element of the container.
Definition tensor_tpl.h:379
const Tensor< GUM_SCALAR > & log2() const
apply $log_2(x)$ on every element of the container
Definition tensor_tpl.h:337
Tensor< GUM_SCALAR > operator*(const Tensor< GUM_SCALAR > &p2) const
the function to be used to multiply two Tensors
Definition tensor_tpl.h:908
Tensor< GUM_SCALAR > prodOut(const gum::VariableSet &del_vars) const
Projection using multiplication as operation (and implementation-optimized operations).
Definition tensor_tpl.h:478
Tensor< GUM_SCALAR > operator-(const Tensor< GUM_SCALAR > &p2) const
the function to be used to subtract two Tensors
Definition tensor_tpl.h:890
Tensor< GUM_SCALAR > & operator*=(const Tensor< GUM_SCALAR > &r)
the function to be used to add two Tensors
Definition tensor_tpl.h:952
Tensor< GUM_SCALAR > isNonZeroMap() const
create a boolean-like tensor using the predicate isNonZero
Definition tensor_tpl.h:597
std::string toString() const final
the function to be used to add two Tensors
Definition tensor_tpl.h:999
GUM_SCALAR min() const
min of all elements in the Tensor
Definition tensor_tpl.h:184
static Tensor< GUM_SCALAR > evLt(const DiscreteVariable &v, double val)
numerical evidence generator
Tensor< GUM_SCALAR > & operator+=(const Tensor< GUM_SCALAR > &r)
the function to be used to add two Tensors
Definition tensor_tpl.h:940
Tensor< GUM_SCALAR > operator+(const Tensor< GUM_SCALAR > &p2) const
the function to be used to add two Tensors
Definition tensor_tpl.h:824
const Tensor< GUM_SCALAR > & inverse() const
the function to inverse (each value of) *this
Definition tensor_tpl.h:449
Tensor< GUM_SCALAR > operator~() const
the function to be used to add two Tensors
Definition tensor_tpl.h:877
const std::string & name() const
returns the name of the variable
#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
double randomProba()
Returns a random double between 0 and 1 included (i.e.
std::vector< GUM_SCALAR > randomDistribution(Size n)
Return a random discrete distribution.
Useful macros for maths.
#define GUM_LOG2_OR_0(x)
Definition math_utils.h:70
gum is the global namespace for all aGrUM entities
Definition agrum.h:46
GUM_SCALAR projectProduct(const MultiDimImplementation< GUM_SCALAR > &table, Instantiation *instantiation=0)
the function to be used to project a MultiDimImplementation using a Product
Set< const DiscreteVariable * > VariableSet
GUM_SCALAR projectMin(const MultiDimImplementation< GUM_SCALAR > &table, Instantiation *instantiation=0)
the function to be used to project a MultiDimImplementation using a Min
GUM_SCALAR projectMax(const MultiDimImplementation< GUM_SCALAR > &table, Instantiation *instantiation=0)
the function to be used to project a MultiDimImplementation using a Max
std::ostream & operator<<(std::ostream &stream, const AVLTree< Val, Cmp > &tree)
display the content of a tree
Definition AVLTree.h:913
GUM_SCALAR projectSum(const MultiDimImplementation< GUM_SCALAR > &table, Instantiation *instantiation=0)
the function to be used to project a MultiDimImplementation using a sum
STL namespace.
Header of the Tensor class.