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