aGrUM
0.20.2
a C++ library for (probabilistic) graphical models
potential_tpl.h
Go to the documentation of this file.
1
/**
2
*
3
* Copyright 2005-2020 Pierre-Henri WUILLEMIN(@LIP6) et Christophe GONZALES(@AMU)
4
* (@AMU) info_at_agrum_dot_org
5
*
6
* This library is free software: you can redistribute it and/or modify
7
* it under the terms of the GNU Lesser General Public License as published by
8
* the Free Software Foundation, either version 3 of the License, or
9
* (at your option) any later version.
10
*
11
* This library is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU Lesser General Public License for more details.
15
*
16
* You should have received a copy of the GNU Lesser General Public License
17
* along with this library. If not, see <http://www.gnu.org/licenses/>.
18
*
19
*/
20
21
22
/**
23
* @file
24
* @brief Implementation of the Potential class.
25
* @author Pierre-Henri WUILLEMIN(@LIP6) & Christophe GONZALES(@AMU)
26
*/
27
28
#
include
<
agrum
/
agrum
.
h
>
29
#
include
<
agrum
/
tools
/
core
/
math
/
math_utils
.
h
>
30
#
include
<
agrum
/
tools
/
multidim
/
potential
.
h
>
31
32
namespace
gum
{
33
34
// Default constructor: creates an empty null dimensional matrix
35
// choose a MultiDimArray<> as decorated implementation
36
template
<
typename
GUM_SCALAR >
37
INLINE Potential<
GUM_SCALAR
>::
Potential
() :
38
MultiDimDecorator
<
GUM_SCALAR
>(
new
MultiDimArray
<
GUM_SCALAR
>(),
39
GUM_SCALAR
(1)) {
40
GUM_CONSTRUCTOR
(
Potential
);
41
}
42
43
// constructor using aContent as content
44
template
<
typename
GUM_SCALAR
>
45
INLINE
Potential
<
GUM_SCALAR
>::
Potential
(
46
MultiDimImplementation
<
GUM_SCALAR
>*
aContent
) :
47
MultiDimDecorator
<
GUM_SCALAR
>(
aContent
,
GUM_SCALAR
(1)) {
48
// for debugging purposes
49
GUM_CONSTRUCTOR
(
Potential
);
50
}
51
// copy constructor
52
template
<
typename
GUM_SCALAR
>
53
INLINE
Potential
<
GUM_SCALAR
>::
Potential
(
const
Potential
<
GUM_SCALAR
>&
src
) :
54
Potential
<
GUM_SCALAR
>(
static_cast
<
MultiDimImplementation
<
GUM_SCALAR
>* >(
55
src
.
content
()->
newFactory
()),
56
*(
src
.
content
())) {
57
this
->
empty_value_
=
src
.
empty_value_
;
58
// GUM_CONS_CPY not here because in called Potential
59
// GUM_CONS_CPY( Potential );
60
}
61
62
/// move constructor
63
template
<
typename
GUM_SCALAR
>
64
INLINE
Potential
<
GUM_SCALAR
>::
Potential
(
Potential
<
GUM_SCALAR
>&&
from
) :
65
MultiDimDecorator
<
GUM_SCALAR
>(
66
std
::
forward
<
MultiDimDecorator
<
GUM_SCALAR
> >(
from
)) {
67
GUM_CONS_MOV
(
Potential
);
68
}
69
70
// complex copy constructor : we choose the implementation
71
template
<
typename
GUM_SCALAR
>
72
Potential
<
GUM_SCALAR
>::
Potential
(
73
MultiDimImplementation
<
GUM_SCALAR
>*
aContent
,
74
const
MultiDimContainer
<
GUM_SCALAR
>&
src
) :
75
MultiDimDecorator
<
GUM_SCALAR
>(
aContent
) {
76
// for debugging purposes
77
GUM_CONSTRUCTOR
(
Potential
);
78
79
if
(!
src
.
empty
()) {
80
this
->
beginMultipleChanges
();
81
82
for
(
Idx
i
= 0;
i
<
src
.
variablesSequence
().
size
();
i
++) {
83
this
->
add
(*(
src
.
variablesSequence
()[
i
]));
84
}
85
86
this
->
endMultipleChanges
();
87
this
->
content
()->
copyFrom
(*
src
.
content
());
88
}
89
}
90
91
// operator = copy
92
template
<
typename
GUM_SCALAR
>
93
Potential
<
GUM_SCALAR
>&
94
Potential
<
GUM_SCALAR
>::
operator
=(
const
Potential
<
GUM_SCALAR
>&
src
) {
95
GUM_OP_CPY
(
Potential
);
96
if
(&
src
==
this
)
return
*
this
;
97
MultiDimDecorator
<
GUM_SCALAR
>::
operator
=(
src
);
98
return
*
this
;
99
}
100
101
// operator = move
102
template
<
typename
GUM_SCALAR
>
103
Potential
<
GUM_SCALAR
>&
104
Potential
<
GUM_SCALAR
>::
operator
=(
Potential
<
GUM_SCALAR
>&&
src
) {
105
GUM_OP_MOV
(
Potential
);
106
if
(&
src
==
this
)
return
*
this
;
107
MultiDimDecorator
<
GUM_SCALAR
>::
operator
=(
108
std
::
forward
<
MultiDimDecorator
<
GUM_SCALAR
> >(
src
));
109
return
*
this
;
110
}
111
112
// destructor
113
114
template
<
typename
GUM_SCALAR
>
115
Potential
<
GUM_SCALAR
>::~
Potential
() {
116
// for debugging purposes
117
GUM_DESTRUCTOR
(
Potential
);
118
}
119
120
template
<
typename
GUM_SCALAR
>
121
INLINE
Potential
<
GUM_SCALAR
>*
Potential
<
GUM_SCALAR
>::
newFactory
()
const
{
122
return
new
Potential
<
GUM_SCALAR
>(
123
static_cast
<
MultiDimImplementation
<
GUM_SCALAR
>* >(
124
this
->
content
()->
newFactory
()));
125
}
126
127
// sum of all elements in this
128
template
<
typename
GUM_SCALAR
>
129
INLINE
GUM_SCALAR
Potential
<
GUM_SCALAR
>::
sum
()
const
{
130
if
(
static_cast
<
MultiDimContainer
<
GUM_SCALAR
>* >(
this
->
content_
)->
empty
()) {
131
return
this
->
empty_value_
;
132
}
133
return
gum
::
projectSum
(*
this
->
content
());
134
}
135
// product of all elements in this
136
template
<
typename
GUM_SCALAR
>
137
INLINE
GUM_SCALAR
Potential
<
GUM_SCALAR
>::
product
()
const
{
138
if
(
static_cast
<
MultiDimContainer
<
GUM_SCALAR
>* >(
this
->
content_
)->
empty
()) {
139
return
this
->
empty_value_
;
140
}
141
return
gum
::
projectProduct
(*
this
->
content
());
142
}
143
// max of all elements in this
144
template
<
typename
GUM_SCALAR
>
145
INLINE
GUM_SCALAR
Potential
<
GUM_SCALAR
>::
max
()
const
{
146
if
(
static_cast
<
MultiDimContainer
<
GUM_SCALAR
>* >(
this
->
content_
)->
empty
()) {
147
return
this
->
empty_value_
;
148
}
149
return
gum
::
projectMax
(*
this
->
content
());
150
}
151
// min of all elements in this
152
template
<
typename
GUM_SCALAR
>
153
INLINE
GUM_SCALAR
Potential
<
GUM_SCALAR
>::
min
()
const
{
154
if
(
static_cast
<
MultiDimContainer
<
GUM_SCALAR
>* >(
this
->
content_
)->
empty
()) {
155
return
this
->
empty_value_
;
156
}
157
return
gum
::
projectMin
(*
this
->
content
());
158
}
159
160
// max of all non one elements in this
161
// warning can return 1 if no other value than 1 ...
162
template
<
typename
GUM_SCALAR
>
163
GUM_SCALAR
Potential
<
GUM_SCALAR
>::
maxNonOne
()
const
{
164
GUM_SCALAR
res
;
165
166
if
(
static_cast
<
MultiDimContainer
<
GUM_SCALAR
>* >(
this
->
content_
)->
empty
()) {
167
res
=
this
->
empty_value_
;
168
}
else
{
169
res
=
this
->
reduce
(
170
[](
GUM_SCALAR
z
,
GUM_SCALAR
p
) {
171
return
(
p
==
static_cast
<
GUM_SCALAR
>(1)) ?
z
172
: (
z
==
static_cast
<
GUM_SCALAR
>(1)) ?
p
173
: (
p
>
z
?
p
:
z
);
174
},
175
static_cast
<
GUM_SCALAR
>(1));
176
}
177
178
return
res
;
179
}
180
181
// min of all non zero elements in this
182
// warning can return 0 if no other value than 0 ...
183
template
<
typename
GUM_SCALAR
>
184
INLINE
GUM_SCALAR
Potential
<
GUM_SCALAR
>::
minNonZero
()
const
{
185
GUM_SCALAR
res
;
186
187
if
(
static_cast
<
MultiDimContainer
<
GUM_SCALAR
>* >(
this
->
content_
)->
empty
()) {
188
res
=
this
->
empty_value_
;
189
}
else
{
190
res
=
this
->
reduce
(
191
[](
GUM_SCALAR
z
,
GUM_SCALAR
p
) {
192
return
(
p
==
static_cast
<
GUM_SCALAR
>(0)) ?
z
193
: (
z
==
static_cast
<
GUM_SCALAR
>(0)) ?
p
194
: (
p
<
z
?
p
:
z
);
195
},
196
static_cast
<
GUM_SCALAR
>(0));
197
}
198
return
res
;
199
}
200
201
// entropy of this
202
template
<
typename
GUM_SCALAR
>
203
INLINE
GUM_SCALAR
Potential
<
GUM_SCALAR
>::
entropy
()
const
{
204
if
(
static_cast
<
MultiDimContainer
<
GUM_SCALAR
>* >(
this
->
content_
)->
empty
()) {
205
return
static_cast
<
GUM_SCALAR
>(0);
206
}
207
208
return
this
->
reduce
(
209
[](
GUM_SCALAR
z
,
GUM_SCALAR
p
) {
210
return
(
p
== 0.0) ?
z
: (
z
-
p
*
std
::
log2
(
p
));
211
},
212
0.0);
213
}
214
215
template
<
typename
GUM_SCALAR
>
216
INLINE
const
Potential
<
GUM_SCALAR
>&
Potential
<
GUM_SCALAR
>::
fillWith
(
217
const
std
::
vector
<
GUM_SCALAR
>&
data
)
const
{
218
this
->
populate
(
data
);
219
return
*
this
;
220
}
221
222
template
<
typename
GUM_SCALAR
>
223
INLINE
const
Potential
<
GUM_SCALAR
>&
224
Potential
<
GUM_SCALAR
>::
fillWith
(
const
GUM_SCALAR
&
val
)
const
{
225
this
->
fill
(
val
);
226
return
*
this
;
227
}
228
229
template
<
typename
GUM_SCALAR
>
230
INLINE
const
Potential
<
GUM_SCALAR
>&
231
Potential
<
GUM_SCALAR
>::
fillWith
(
const
Potential
<
GUM_SCALAR
>&
src
)
const
{
232
if
(
src
.
domainSize
() !=
this
->
domainSize
()) {
233
GUM_ERROR
(
InvalidArgument
,
"Potential to copy has not the same dimension."
);
234
}
235
gum
::
Set
<
std
::
string
>
son
;
// set of names
236
for
(
const
auto
&
v
:
src
.
variablesSequence
()) {
237
son
.
insert
(
v
->
name
());
238
}
239
for
(
const
auto
&
v
:
this
->
variablesSequence
()) {
240
if
(!
son
.
contains
(
v
->
name
())) {
241
GUM_ERROR
(
InvalidArgument
,
242
"Variable <"
<<
v
->
name
() <<
"> not present in src ("
<<
son
243
<<
")."
);
244
}
245
// we check size, labels and order of labels in the same time
246
if
(
v
->
toString
() !=
src
.
variable
(
v
->
name
()).
toString
()) {
247
GUM_ERROR
(
InvalidArgument
,
248
"Variables <"
<<
v
->
name
() <<
"> are not identical."
);
249
}
250
}
251
252
Instantiation
Isrc
(
src
);
253
Instantiation
Idst
(*
this
);
254
for
(
Isrc
.
setFirst
(); !
Isrc
.
end
(); ++
Isrc
) {
255
for
(
Idx
i
= 0;
i
<
this
->
nbrDim
();
i
++) {
256
Idst
.
chgVal
(
Isrc
.
variable
(
i
).
name
(),
Isrc
.
val
(
i
));
257
}
258
this
->
set
(
Idst
,
src
.
get
(
Isrc
));
259
}
260
261
return
*
this
;
262
}
263
264
template
<
typename
GUM_SCALAR
>
265
INLINE
const
Potential
<
GUM_SCALAR
>&
Potential
<
GUM_SCALAR
>::
fillWith
(
266
const
Potential
<
GUM_SCALAR
>&
src
,
267
const
std
::
vector
<
std
::
string
>&
mapSrc
)
const
{
268
if
(
src
.
nbrDim
() !=
this
->
nbrDim
()) {
269
GUM_ERROR
(
InvalidArgument
,
"Potential to copy has not the same dimension."
);
270
}
271
if
(
src
.
nbrDim
() !=
mapSrc
.
size
()) {
272
GUM_ERROR
(
InvalidArgument
,
273
"Potential and vector have not the same dimension."
);
274
}
275
Instantiation
Isrc
;
276
for
(
Idx
i
= 0;
i
<
src
.
nbrDim
();
i
++) {
277
if
(
src
.
variable
(
mapSrc
[
i
]).
domainSize
() !=
this
->
variable
(
i
).
domainSize
()) {
278
GUM_ERROR
(
InvalidArgument
,
279
"Variables "
<<
mapSrc
[
i
] <<
" (in the argument) and "
280
<<
this
->
variable
(
i
).
name
()
281
<<
" have not the same dimension."
);
282
}
else
{
283
Isrc
.
add
(
src
.
variable
(
mapSrc
[
i
]));
284
}
285
}
286
Instantiation
Idst
(*
this
);
287
for
(
Isrc
.
setFirst
(); !
Isrc
.
end
(); ++
Isrc
, ++
Idst
) {
288
this
->
set
(
Idst
,
src
.
get
(
Isrc
));
289
}
290
291
return
*
this
;
292
}
293
294
template
<
typename
GUM_SCALAR
>
295
INLINE
const
Potential
<
GUM_SCALAR
>&
Potential
<
GUM_SCALAR
>::
sq
()
const
{
296
this
->
apply
([](
GUM_SCALAR
x
) {
return
x
*
x
; });
297
return
*
this
;
298
}
299
300
template
<
typename
GUM_SCALAR
>
301
INLINE
const
Potential
<
GUM_SCALAR
>&
Potential
<
GUM_SCALAR
>::
log2
()
const
{
302
this
->
apply
([](
GUM_SCALAR
x
) {
return
std
::
log2
(
x
); });
303
return
*
this
;
304
}
305
306
template
<
typename
GUM_SCALAR
>
307
INLINE
GUM_SCALAR
308
Potential
<
GUM_SCALAR
>::
KL
(
const
Potential
<
GUM_SCALAR
>&
p
)
const
{
309
if
(
this
->
nbrDim
() !=
p
.
nbrDim
())
310
GUM_ERROR
(
311
InvalidArgument
,
312
"BNdistance between potentials with different numbers of dimensions"
);
313
for
(
const
auto
var
:
p
.
variablesSequence
()) {
314
if
(!
this
->
contains
(*
var
))
315
GUM_ERROR
(
InvalidArgument
,
316
"A variable in the argument does not belong to the potential."
);
317
}
318
for
(
const
auto
var
:
this
->
variablesSequence
()) {
319
if
(!
p
.
contains
(*
var
))
320
GUM_ERROR
(
InvalidArgument
,
"A variable does not belong to the argument."
);
321
}
322
323
Instantiation
inst
(*
this
);
324
GUM_SCALAR
res
=
static_cast
<
GUM_SCALAR
>(0);
325
for
(
inst
.
setFirst
(); !
inst
.
end
();
inst
.
inc
()) {
326
GUM_SCALAR
x
=
this
->
get
(
inst
);
327
GUM_SCALAR
y
=
p
.
get
(
inst
);
328
if
(
static_cast
<
GUM_SCALAR
>(0) ==
x
)
// 0*log(0/y)=0
329
continue
;
330
331
if
(
static_cast
<
GUM_SCALAR
>(0) ==
y
)
332
// we know that x!=0;
333
GUM_ERROR
(
FatalError
,
334
"The argument has a 0 at "
<<
inst
335
<<
" while the potential has not."
)
336
337
res
+=
x
*
std
::
log2
(
x
/
y
);
338
}
339
return
res
;
340
}
341
342
template
<
typename
GUM_SCALAR
>
343
INLINE
const
Potential
<
GUM_SCALAR
>&
Potential
<
GUM_SCALAR
>::
abs
()
const
{
344
this
->
apply
([](
GUM_SCALAR
x
) {
345
if
(
x
>= 0)
346
return
x
;
347
else
348
return
-
x
;
349
});
350
return
*
this
;
351
}
352
353
// normalisation of this
354
// do nothing is sum is 0
355
template
<
typename
GUM_SCALAR
>
356
INLINE
const
Potential
<
GUM_SCALAR
>&
357
Potential
<
GUM_SCALAR
>::
normalize
()
const
{
358
if
(
static_cast
<
MultiDimContainer
<
GUM_SCALAR
>* >(
this
->
content_
)->
empty
()) {
359
if
(
this
->
empty_value_
!=
static_cast
<
GUM_SCALAR
>(0))
360
this
->
empty_value_
=
static_cast
<
GUM_SCALAR
>(1.0);
361
}
else
{
362
GUM_SCALAR
s
=
sum
();
363
364
if
(
s
!= (
GUM_SCALAR
)0) {
365
this
->
apply
([
s
](
GUM_SCALAR
x
) {
return
x
/
s
; });
366
}
367
}
368
return
*
this
;
369
}
370
371
template
<
typename
GUM_SCALAR
>
372
INLINE
const
Potential
<
GUM_SCALAR
>&
373
Potential
<
GUM_SCALAR
>::
normalizeAsCPT
(
const
Idx
&
varId
)
const
{
374
if
(
static_cast
<
MultiDimContainer
<
GUM_SCALAR
>* >(
this
->
content_
)->
empty
()) {
375
if
(
this
->
empty_value_
!=
static_cast
<
GUM_SCALAR
>(0)) {
376
this
->
empty_value_
=
static_cast
<
GUM_SCALAR
>(1.0);
377
}
else
{
378
GUM_ERROR
(
FatalError
,
379
"Normalization for a potential that sum to 0 in "
<< *
this
);
380
}
381
}
else
{
382
if
(
varId
>=
this
->
nbrDim
()) {
383
GUM_ERROR
(
FatalError
,
varId
<<
" is not a position for "
<< *
this
);
384
}
385
Instantiation
inst
(*
this
);
386
const
auto
&
v
=
this
->
variable
(
varId
);
387
388
for
(
inst
.
setFirst
(); !
inst
.
end
();
inst
.
incNotVar
(
v
)) {
389
GUM_SCALAR
s
= (
GUM_SCALAR
)0.0;
390
for
(
inst
.
setFirstVar
(
v
); !
inst
.
end
();
inst
.
incVar
(
v
))
391
s
+=
this
->
get
(
inst
);
392
if
(
s
== (
GUM_SCALAR
)0.0) {
393
GUM_ERROR
(
FatalError
,
394
"Normalization for a potential that sum to 0 in "
<< *
this
);
395
}
396
if
(
s
!= (
GUM_SCALAR
)1.0) {
397
for
(
inst
.
setFirstVar
(
v
); !
inst
.
end
();
inst
.
incVar
(
v
))
398
this
->
set
(
inst
,
this
->
get
(
inst
) /
s
);
399
}
400
inst
.
setFirstVar
(
v
);
// to remove inst.end()
401
}
402
}
403
return
*
this
;
404
}
405
406
template
<
typename
GUM_SCALAR
>
407
INLINE
const
Potential
<
GUM_SCALAR
>&
408
Potential
<
GUM_SCALAR
>::
scale
(
GUM_SCALAR
v
)
const
{
409
this
->
apply
([
v
](
GUM_SCALAR
x
) {
return
x
*
v
; });
410
return
*
this
;
411
}
412
413
template
<
typename
GUM_SCALAR
>
414
INLINE
const
Potential
<
GUM_SCALAR
>&
415
Potential
<
GUM_SCALAR
>::
translate
(
GUM_SCALAR
v
)
const
{
416
this
->
apply
([
v
](
GUM_SCALAR
x
) {
return
x
+
v
; });
417
return
*
this
;
418
}
419
420
template
<
typename
GUM_SCALAR
>
421
INLINE
const
Potential
<
GUM_SCALAR
>&
Potential
<
GUM_SCALAR
>::
inverse
()
const
{
422
this
->
apply
([](
GUM_SCALAR
x
) {
return
1 /
x
; });
423
return
*
this
;
424
}
425
426
template
<
typename
GUM_SCALAR
>
427
INLINE
Potential
<
GUM_SCALAR
>
Potential
<
GUM_SCALAR
>::
margSumOut
(
428
const
Set
<
const
DiscreteVariable
* >&
del_vars
)
const
{
429
if
(
static_cast
<
MultiDimContainer
<
GUM_SCALAR
>* >(
this
->
content_
)->
empty
()) {
430
return
Potential
<
GUM_SCALAR
>().
fillWith
(
this
->
empty_value_
);
431
}
432
return
Potential
<
GUM_SCALAR
>(
gum
::
projectSum
(*
this
->
content
(),
del_vars
));
433
}
434
435
template
<
typename
GUM_SCALAR
>
436
INLINE
Potential
<
GUM_SCALAR
>
Potential
<
GUM_SCALAR
>::
margProdOut
(
437
const
Set
<
const
DiscreteVariable
* >&
del_vars
)
const
{
438
if
(
static_cast
<
MultiDimContainer
<
GUM_SCALAR
>* >(
this
->
content_
)->
empty
()) {
439
return
Potential
<
GUM_SCALAR
>().
fillWith
(
this
->
empty_value_
);
440
}
441
return
Potential
<
GUM_SCALAR
>(
442
gum
::
projectProduct
(*
this
->
content
(),
del_vars
));
443
}
444
445
template
<
typename
GUM_SCALAR
>
446
INLINE
Potential
<
GUM_SCALAR
>
Potential
<
GUM_SCALAR
>::
margMinOut
(
447
const
Set
<
const
DiscreteVariable
* >&
del_vars
)
const
{
448
if
(
static_cast
<
MultiDimContainer
<
GUM_SCALAR
>* >(
this
->
content_
)->
empty
()) {
449
return
Potential
<
GUM_SCALAR
>().
fillWith
(
this
->
empty_value_
);
450
}
451
return
Potential
<
GUM_SCALAR
>(
gum
::
projectMin
(*
this
->
content
(),
del_vars
));
452
}
453
454
template
<
typename
GUM_SCALAR
>
455
INLINE
Potential
<
GUM_SCALAR
>
Potential
<
GUM_SCALAR
>::
margMaxOut
(
456
const
Set
<
const
DiscreteVariable
* >&
del_vars
)
const
{
457
if
(
static_cast
<
MultiDimContainer
<
GUM_SCALAR
>* >(
this
->
content_
)->
empty
()) {
458
return
Potential
<
GUM_SCALAR
>().
fillWith
(
this
->
empty_value_
);
459
}
460
return
Potential
<
GUM_SCALAR
>(
gum
::
projectMax
(*
this
->
content
(),
del_vars
));
461
}
462
template
<
typename
GUM_SCALAR
>
463
INLINE
Potential
<
GUM_SCALAR
>
Potential
<
GUM_SCALAR
>::
margSumIn
(
464
const
Set
<
const
DiscreteVariable
* >&
kept_vars
)
const
{
465
if
(
static_cast
<
MultiDimContainer
<
GUM_SCALAR
>* >(
this
->
content_
)->
empty
()) {
466
return
Potential
<
GUM_SCALAR
>().
fillWith
(
this
->
empty_value_
);
467
}
468
return
Potential
<
GUM_SCALAR
>(
469
gum
::
projectSum
(*
this
->
content
(),
complementVars_
(
kept_vars
)));
470
}
471
472
template
<
typename
GUM_SCALAR
>
473
INLINE
Potential
<
GUM_SCALAR
>
Potential
<
GUM_SCALAR
>::
margProdIn
(
474
const
Set
<
const
DiscreteVariable
* >&
kept_vars
)
const
{
475
if
(
static_cast
<
MultiDimContainer
<
GUM_SCALAR
>* >(
this
->
content_
)->
empty
()) {
476
return
Potential
<
GUM_SCALAR
>().
fillWith
(
this
->
empty_value_
);
477
}
478
return
Potential
<
GUM_SCALAR
>(
479
gum
::
projectProduct
(*
this
->
content
(),
complementVars_
(
kept_vars
)));
480
}
481
482
template
<
typename
GUM_SCALAR
>
483
INLINE
Potential
<
GUM_SCALAR
>
Potential
<
GUM_SCALAR
>::
margMinIn
(
484
const
Set
<
const
DiscreteVariable
* >&
kept_vars
)
const
{
485
if
(
static_cast
<
MultiDimContainer
<
GUM_SCALAR
>* >(
this
->
content_
)->
empty
()) {
486
return
Potential
<
GUM_SCALAR
>().
fillWith
(
this
->
empty_value_
);
487
}
488
return
Potential
<
GUM_SCALAR
>(
489
gum
::
projectMin
(*
this
->
content
(),
complementVars_
(
kept_vars
)));
490
}
491
492
template
<
typename
GUM_SCALAR
>
493
INLINE
Potential
<
GUM_SCALAR
>
Potential
<
GUM_SCALAR
>::
margMaxIn
(
494
const
Set
<
const
DiscreteVariable
* >&
kept_vars
)
const
{
495
if
(
static_cast
<
MultiDimContainer
<
GUM_SCALAR
>* >(
this
->
content_
)->
empty
()) {
496
return
Potential
<
GUM_SCALAR
>().
fillWith
(
this
->
empty_value_
);
497
}
498
return
Potential
<
GUM_SCALAR
>(
499
gum
::
projectMax
(*
this
->
content
(),
complementVars_
(
kept_vars
)));
500
}
501
502
template
<
typename
GUM_SCALAR
>
503
INLINE
Potential
<
GUM_SCALAR
>
Potential
<
GUM_SCALAR
>::
isNonZeroMap
()
const
{
504
auto
p
=
Potential
<
GUM_SCALAR
>(*
this
);
505
p
.
apply
([](
GUM_SCALAR
x
) {
506
if
(
x
!=
static_cast
<
GUM_SCALAR
>(0))
507
return
static_cast
<
GUM_SCALAR
>(1);
508
else
509
return
static_cast
<
GUM_SCALAR
>(0);
510
});
511
return
p
;
512
}
513
514
template
<
typename
GUM_SCALAR
>
515
Set
<
const
DiscreteVariable
* >
Potential
<
GUM_SCALAR
>::
complementVars_
(
516
const
Set
<
const
DiscreteVariable
* >&
vars
)
const
{
517
Set
<
const
DiscreteVariable
* >
cplt
;
518
519
for
(
const
auto
x
:
this
->
variablesSequence
())
520
if
(!
vars
.
contains
(
x
))
cplt
.
insert
(
x
);
521
522
return
cplt
;
523
}
524
525
template
<
typename
GUM_SCALAR
>
526
Potential
<
GUM_SCALAR
>
Potential
<
GUM_SCALAR
>::
reorganize
(
527
const
std
::
vector
<
const
DiscreteVariable
* >&
vars
)
const
{
528
if
(
vars
.
size
() !=
this
->
nbrDim
())
529
GUM_ERROR
(
InvalidArgument
,
530
"The vector contains "
<<
vars
.
size
() <<
" variables instead of "
531
<<
this
->
nbrDim
() <<
"."
);
532
for
(
const
auto
var
:
vars
) {
533
if
(!
this
->
contains
(*
var
))
534
GUM_ERROR
(
InvalidArgument
,
535
"A variable in the vector does not belong to the potential."
);
536
}
537
538
Potential
<
GUM_SCALAR
>
p
;
539
p
.
beginMultipleChanges
();
540
for
(
const
auto
var
:
vars
)
541
p
.
add
(*
var
);
542
p
.
endMultipleChanges
();
543
p
.
copyFrom
(*
this
,
nullptr
);
// copy *this in p using the same order
544
545
return
p
;
546
}
547
548
template
<
typename
GUM_SCALAR
>
549
Potential
<
GUM_SCALAR
>
Potential
<
GUM_SCALAR
>::
reorganize
(
550
const
std
::
vector
<
std
::
string
>&
vars
)
const
{
551
std
::
vector
<
const
DiscreteVariable
* >
res
;
552
553
gum
::
HashTable
<
std
::
string
,
const
gum
::
DiscreteVariable
* >
namesToVars
;
554
for
(
gum
::
Idx
i
= 0;
i
<
this
->
nbrDim
();
i
++)
555
namesToVars
.
insert
(
this
->
variable
(
i
).
name
(), &(
this
->
variable
(
i
)));
556
557
for
(
const
auto
&
name
:
vars
) {
558
if
(!
namesToVars
.
exists
(
name
)) {
559
GUM_ERROR
(
gum
::
InvalidArgument
,
560
"'"
<<
name
561
<<
"' is a not a name of a variable in this potential"
);
562
}
563
res
.
push_back
(
namesToVars
[
name
]);
564
}
565
return
reorganize
(
res
);
566
}
567
568
template
<
typename
GUM_SCALAR
>
569
Potential
<
GUM_SCALAR
>
570
Potential
<
GUM_SCALAR
>::
putFirst
(
const
DiscreteVariable
*
var
)
const
{
571
if
(!
this
->
contains
(*
var
)) {
572
GUM_ERROR
(
InvalidArgument
,
573
"The variable to put first does not belong to the potential"
);
574
}
575
if
(&(
this
->
variable
(0)) ==
var
)
return
Potential
<
GUM_SCALAR
>(*
this
);
576
577
std
::
vector
<
const
DiscreteVariable
* >
vars
;
578
vars
.
push_back
(
var
);
579
for
(
Idx
i
= 0;
i
<
this
->
nbrDim
();
i
++)
580
if
(&(
this
->
variable
(
i
)) !=
var
)
vars
.
push_back
(&(
this
->
variable
(
i
)));
581
582
return
this
->
reorganize
(
vars
);
583
}
584
585
template
<
typename
GUM_SCALAR
>
586
Potential
<
GUM_SCALAR
>
587
Potential
<
GUM_SCALAR
>::
putFirst
(
const
std
::
string
&
varname
)
const
{
588
const
DiscreteVariable
*
var
=
nullptr
;
589
590
for
(
gum
::
Idx
i
= 0;
i
<
this
->
nbrDim
();
i
++)
591
if
(
this
->
variable
(
i
).
name
() ==
varname
) {
592
var
= &(
this
->
variable
(
i
));
593
break
;
594
}
595
if
(
var
==
nullptr
)
596
GUM_ERROR
(
InvalidArgument
,
597
"The variable '"
598
<<
varname
599
<<
"' to put first does not belong to the potential"
);
600
return
this
->
putFirst
(
var
);
601
}
602
603
template
<
typename
GUM_SCALAR
>
604
Potential
<
GUM_SCALAR
>
605
Potential
<
GUM_SCALAR
>::
extract
(
const
Instantiation
&
inst
)
const
{
606
Potential
<
GUM_SCALAR
>
p
;
607
p
.
extractFrom
(*
this
,
inst
);
608
609
return
p
;
610
}
611
612
template
<
typename
GUM_SCALAR
>
613
Idx
Potential
<
GUM_SCALAR
>::
draw
()
const
{
614
if
(
this
->
nbrDim
() != 1) {
615
GUM_ERROR
(
FatalError
,
"To draw from a potential, the dimension must be 1"
)
616
}
617
618
GUM_SCALAR
r
=
static_cast
<
GUM_SCALAR
>(
randomProba
());
619
Instantiation
Ip
(*
this
);
620
for
(
Ip
.
setFirst
(); !
Ip
.
end
();
Ip
.
inc
()) {
621
r
-=
this
->
get
(
Ip
);
622
if
(
r
<= 0)
return
Ip
.
val
(0);
623
}
624
return
this
->
variable
(0).
domainSize
() - 1;
625
}
626
627
template
<
typename
GUM_SCALAR
>
628
std
::
ostream
&
operator
<<(
std
::
ostream
&
out
,
629
const
Potential
<
GUM_SCALAR
>&
array
) {
630
out
<<
array
.
toString
();
631
return
out
;
632
}
633
634
// argmax of all elements in this
635
template
<
typename
GUM_SCALAR
>
636
Set
<
Instantiation
>
Potential
<
GUM_SCALAR
>::
findAll
(
GUM_SCALAR
v
)
const
{
637
Instantiation
I
(*
this
);
638
Set
<
Instantiation
>
res
;
639
640
if
(
static_cast
<
MultiDimContainer
<
GUM_SCALAR
>* >(
this
->
content_
)->
empty
()) {
641
return
res
;
642
}
643
for
(
I
.
setFirst
(); !
I
.
end
(); ++
I
) {
644
if
(
this
->
get
(
I
) ==
v
)
res
.
insert
(
I
);
645
}
646
return
res
;
647
}
648
// argmax of all elements in this
649
template
<
typename
GUM_SCALAR
>
650
INLINE
Set
<
Instantiation
>
Potential
<
GUM_SCALAR
>::
argmax
()
const
{
651
return
findAll
(
max
());
652
}
653
// argmin of all elements in this
654
template
<
typename
GUM_SCALAR
>
655
INLINE
Set
<
Instantiation
>
Potential
<
GUM_SCALAR
>::
argmin
()
const
{
656
return
findAll
(
min
());
657
}
658
659
template
<
typename
GUM_SCALAR
>
660
const
Potential
<
GUM_SCALAR
>&
Potential
<
GUM_SCALAR
>::
random
()
const
{
661
if
(
this
->
domainSize
() == 0)
return
*
this
;
662
663
std
::
vector
<
GUM_SCALAR
>
v
;
664
GUM_SCALAR
sum
;
665
v
.
reserve
(
this
->
domainSize
());
666
sum
= 0.0;
667
for
(
Size
i
= 0;
i
<
this
->
domainSize
(); ++
i
) {
668
auto
r
= (
GUM_SCALAR
)
randomProba
();
669
v
.
push_back
(
r
);
670
sum
+=
r
;
671
}
672
if
(
sum
== 0.0)
673
v
[
gum
::
randomValue
(
this
->
domainSize
())] = 1.0;
// a 1 somewhere
674
675
this
->
fillWith
(
v
);
676
return
*
this
;
677
}
678
679
template
<
typename
GUM_SCALAR
>
680
INLINE
const
Potential
<
GUM_SCALAR
>&
681
Potential
<
GUM_SCALAR
>::
randomDistribution
()
const
{
682
return
this
->
random
().
normalize
();
683
}
684
685
template
<
typename
GUM_SCALAR
>
686
INLINE
const
Potential
<
GUM_SCALAR
>&
687
Potential
<
GUM_SCALAR
>::
randomCPT
()
const
{
688
return
this
->
random
().
normalizeAsCPT
();
689
}
690
691
template
<
typename
GUM_SCALAR
>
692
const
Potential
<
GUM_SCALAR
>&
693
Potential
<
GUM_SCALAR
>::
noising
(
GUM_SCALAR
alpha
)
const
{
694
if
((
alpha
<
GUM_SCALAR
(0.0)) || (
alpha
>
GUM_SCALAR
(1.0))) {
695
GUM_ERROR
(
InvalidArgument
,
"alpha must be in [0,1]"
);
696
}
697
Potential
<
GUM_SCALAR
>
noise
(*
this
);
698
return
fillWith
(
scale
(1 -
alpha
) +
noise
.
randomCPT
().
scale
(
alpha
))
699
.
normalizeAsCPT
();
700
}
701
702
template
<
typename
GUM_SCALAR
>
703
const
Potential
<
GUM_SCALAR
>
Potential
<
GUM_SCALAR
>::
new_abs
()
const
{
704
return
Potential
<
GUM_SCALAR
>(*
this
).
abs
();
705
}
706
707
template
<
typename
GUM_SCALAR
>
708
const
Potential
<
GUM_SCALAR
>
Potential
<
GUM_SCALAR
>::
new_sq
()
const
{
709
return
Potential
<
GUM_SCALAR
>(*
this
).
sq
();
710
}
711
712
template
<
typename
GUM_SCALAR
>
713
const
Potential
<
GUM_SCALAR
>
Potential
<
GUM_SCALAR
>::
new_log2
()
const
{
714
return
Potential
<
GUM_SCALAR
>(*
this
).
log2
();
715
}
716
717
}
/* namespace gum */
gum::Set::emplace
INLINE void emplace(Args &&... args)
Definition:
set_tpl.h:669