aGrUM
0.20.3
a C++ library for (probabilistic) graphical models
BayesNet_tpl.h
Go to the documentation of this file.
1
/**
2
*
3
* Copyright (c) 2005-2021 by Pierre-Henri WUILLEMIN(@LIP6) & Christophe GONZALES(@AMU)
4
* 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 Template implementation of BN/BayesNet.h class.
25
*
26
* @author Pierre-Henri WUILLEMIN(@LIP6) and Lionel TORTI
27
*/
28
29
#
include
<
limits
>
30
#
include
<
set
>
31
32
#
include
<
agrum
/
BN
/
BayesNet
.
h
>
33
34
#
include
<
agrum
/
tools
/
variables
/
rangeVariable
.
h
>
35
#
include
<
agrum
/
tools
/
variables
/
labelizedVariable
.
h
>
36
#
include
<
agrum
/
tools
/
variables
/
discretizedVariable
.
h
>
37
38
#
include
<
agrum
/
tools
/
multidim
/
aggregators
/
amplitude
.
h
>
39
#
include
<
agrum
/
tools
/
multidim
/
aggregators
/
and
.
h
>
40
#
include
<
agrum
/
tools
/
multidim
/
aggregators
/
count
.
h
>
41
#
include
<
agrum
/
tools
/
multidim
/
aggregators
/
exists
.
h
>
42
#
include
<
agrum
/
tools
/
multidim
/
aggregators
/
forall
.
h
>
43
#
include
<
agrum
/
tools
/
multidim
/
aggregators
/
max
.
h
>
44
#
include
<
agrum
/
tools
/
multidim
/
aggregators
/
median
.
h
>
45
#
include
<
agrum
/
tools
/
multidim
/
aggregators
/
min
.
h
>
46
#
include
<
agrum
/
tools
/
multidim
/
aggregators
/
or
.
h
>
47
#
include
<
agrum
/
tools
/
multidim
/
aggregators
/
sum
.
h
>
48
49
#
include
<
agrum
/
tools
/
multidim
/
ICIModels
/
multiDimNoisyAND
.
h
>
50
#
include
<
agrum
/
tools
/
multidim
/
ICIModels
/
multiDimNoisyORCompound
.
h
>
51
#
include
<
agrum
/
tools
/
multidim
/
ICIModels
/
multiDimNoisyORNet
.
h
>
52
53
#
include
<
agrum
/
tools
/
multidim
/
ICIModels
/
multiDimLogit
.
h
>
54
55
#
include
<
agrum
/
BN
/
generator
/
simpleCPTGenerator
.
h
>
56
#
include
<
agrum
/
tools
/
core
/
utils_string
.
h
>
57
58
namespace
gum
{
59
template
<
typename
GUM_SCALAR
>
60
NodeId
61
build_node
(
gum
::
BayesNet
<
GUM_SCALAR
>&
bn
,
std
::
string
node
,
gum
::
Size
default_domain_size
) {
62
std
::
string
name
=
node
;
63
auto
ds
=
default_domain_size
;
64
long
range_min
= 0;
65
long
range_max
=
long
(
ds
) - 1;
66
std
::
vector
<
std
::
string
>
labels
;
67
std
::
vector
<
GUM_SCALAR
>
ticks
;
68
69
if
(*(
node
.
rbegin
()) ==
']'
) {
70
auto
posBrack
=
node
.
find
(
'['
);
71
if
(
posBrack
!=
std
::
string
::
npos
) {
72
name
=
node
.
substr
(0,
posBrack
);
73
const
auto
&
s_args
=
node
.
substr
(
posBrack
+ 1,
node
.
size
() -
posBrack
- 2);
74
const
auto
&
args
=
split
(
s_args
,
","
);
75
if
(
args
.
size
() == 0) {
// n[]
76
GUM_ERROR
(
InvalidArgument
,
"Empty range for variable "
<<
node
)
77
}
else
if
(
args
.
size
() == 1) {
// n[4]
78
ds
=
static_cast
<
Size
>(
std
::
stoi
(
args
[0]));
79
range_min
= 0;
80
range_max
=
long
(
ds
) - 1;
81
}
else
if
(
args
.
size
() == 2) {
// n[5,10]
82
range_min
=
std
::
stol
(
args
[0]);
83
range_max
=
std
::
stol
(
args
[1]);
84
if
(1 +
range_max
-
range_min
< 2) {
85
GUM_ERROR
(
InvalidArgument
,
"Invalid range for variable "
<<
node
)
86
}
87
ds
=
static_cast
<
Size
>(1 +
range_max
-
range_min
);
88
}
else
{
// n[3.14,5,10,12]
89
for
(
const
auto
&
tick
:
args
) {
90
ticks
.
push_back
(
static_cast
<
GUM_SCALAR
>(
std
::
atof
(
tick
.
c_str
())));
91
}
92
ds
=
static_cast
<
Size
>(
args
.
size
() - 1);
93
}
94
}
95
}
else
if
(*(
node
.
rbegin
()) ==
'}'
) {
// node like "n{one|two|three}"
96
auto
posBrack
=
node
.
find
(
'{'
);
97
if
(
posBrack
!=
std
::
string
::
npos
) {
98
name
=
node
.
substr
(0,
posBrack
);
99
labels
=
split
(
node
.
substr
(
posBrack
+ 1,
node
.
size
() -
posBrack
- 2),
"|"
);
100
if
(
labels
.
size
() < 2) {
GUM_ERROR
(
InvalidArgument
,
"Not enough labels in node "
<<
node
) }
101
if
(!
hasUniqueElts
(
labels
)) {
102
GUM_ERROR
(
InvalidArgument
,
"Duplicate labels in node "
<<
node
)
103
}
104
ds
=
static_cast
<
Size
>(
labels
.
size
());
105
}
106
}
107
108
if
(
ds
== 0) {
109
GUM_ERROR
(
InvalidArgument
,
"No value for variable "
<<
name
<<
"."
)
110
}
else
if
(
ds
== 1) {
111
GUM_ERROR
(
InvalidArgument
,
112
"Only one value for variable "
<<
name
<<
" (2 at least are needed)."
)
113
}
114
115
// now we add the node in the BN
116
NodeId
idVar
;
117
try
{
118
idVar
=
bn
.
idFromName
(
name
);
119
}
catch
(
gum
::
NotFound
&) {
120
if
(!
labels
.
empty
()) {
121
idVar
=
bn
.
add
(
LabelizedVariable
(
name
,
name
,
labels
));
122
}
else
if
(!
ticks
.
empty
()) {
123
idVar
=
bn
.
add
(
DiscretizedVariable
<
GUM_SCALAR
>(
name
,
name
,
ticks
));
124
}
else
{
125
idVar
=
bn
.
add
(
RangeVariable
(
name
,
name
,
range_min
,
range_max
));
126
}
127
}
128
129
return
idVar
;
130
}
131
132
template
<
typename
GUM_SCALAR >
133
BayesNet< GUM_SCALAR > BayesNet<
GUM_SCALAR
>::
fastPrototype
(
const
std
::
string
&
dotlike
,
134
Size
domainSize
) {
135
gum
::
BayesNet
<
GUM_SCALAR
>
bn
;
136
137
138
for
(
const
auto
&
chaine
:
split
(
dotlike
,
";"
)) {
139
NodeId
lastId
= 0;
140
bool
notfirst
=
false
;
141
for
(
const
auto
&
souschaine
:
split
(
chaine
,
"->"
)) {
142
bool
forward
=
true
;
143
for
(
const
auto
&
node
:
split
(
souschaine
,
"<-"
)) {
144
auto
idVar
=
build_node
(
bn
,
node
,
domainSize
);
145
if
(
notfirst
) {
146
if
(
forward
) {
147
bn
.
addArc
(
lastId
,
idVar
);
148
forward
=
false
;
149
}
else
{
150
bn
.
addArc
(
idVar
,
lastId
);
151
}
152
}
else
{
153
notfirst
=
true
;
154
forward
=
false
;
155
}
156
lastId
=
idVar
;
157
}
158
}
159
}
160
bn
.
generateCPTs
();
161
bn
.
setProperty
(
"name"
,
"fastPrototype"
);
162
return
bn
;
163
}
164
165
template
<
typename
GUM_SCALAR
>
166
INLINE
BayesNet
<
GUM_SCALAR
>::
BayesNet
() :
IBayesNet
<
GUM_SCALAR
>() {
167
GUM_CONSTRUCTOR
(
BayesNet
);
168
}
169
170
template
<
typename
GUM_SCALAR
>
171
INLINE
BayesNet
<
GUM_SCALAR
>::
BayesNet
(
std
::
string
name
) :
IBayesNet
<
GUM_SCALAR
>(
name
) {
172
GUM_CONSTRUCTOR
(
BayesNet
);
173
}
174
175
template
<
typename
GUM_SCALAR
>
176
BayesNet
<
GUM_SCALAR
>::
BayesNet
(
const
BayesNet
<
GUM_SCALAR
>&
source
) :
177
IBayesNet
<
GUM_SCALAR
>(
source
),
_varMap_
(
source
.
_varMap_
) {
178
GUM_CONS_CPY
(
BayesNet
);
179
180
_copyPotentials_
(
source
);
181
}
182
183
template
<
typename
GUM_SCALAR
>
184
BayesNet
<
GUM_SCALAR
>&
BayesNet
<
GUM_SCALAR
>::
operator
=(
const
BayesNet
<
GUM_SCALAR
>&
source
) {
185
if
(
this
!= &
source
) {
186
IBayesNet
<
GUM_SCALAR
>::
operator
=(
source
);
187
_varMap_
=
source
.
_varMap_
;
188
189
_clearPotentials_
();
190
_copyPotentials_
(
source
);
191
}
192
193
return
*
this
;
194
}
195
196
template
<
typename
GUM_SCALAR
>
197
BayesNet
<
GUM_SCALAR
>::~
BayesNet
() {
198
GUM_DESTRUCTOR
(
BayesNet
);
199
for
(
const
auto
p
:
_probaMap_
) {
200
delete
p
.
second
;
201
}
202
}
203
204
template
<
typename
GUM_SCALAR
>
205
INLINE
const
DiscreteVariable
&
BayesNet
<
GUM_SCALAR
>::
variable
(
NodeId
id
)
const
{
206
return
_varMap_
.
get
(
id
);
207
}
208
209
template
<
typename
GUM_SCALAR
>
210
INLINE
void
BayesNet
<
GUM_SCALAR
>::
changeVariableName
(
NodeId
id
,
const
std
::
string
&
new_name
) {
211
_varMap_
.
changeName
(
id
,
new_name
);
212
}
213
214
template
<
typename
GUM_SCALAR
>
215
INLINE
void
BayesNet
<
GUM_SCALAR
>::
changeVariableLabel
(
NodeId
id
,
216
const
std
::
string
&
old_label
,
217
const
std
::
string
&
new_label
) {
218
if
(
variable
(
id
).
varType
() !=
VarType
::
Labelized
)
219
GUM_ERROR
(
NotFound
,
"Variable "
<<
id
<<
" is not a LabelizedVariable."
)
220
221
LabelizedVariable
*
var
222
=
dynamic_cast
<
LabelizedVariable
* >(
const_cast
<
DiscreteVariable
* >(&
variable
(
id
)));
223
224
var
->
changeLabel
(
var
->
posLabel
(
old_label
),
new_label
);
225
}
226
227
228
template
<
typename
GUM_SCALAR
>
229
INLINE
NodeId
BayesNet
<
GUM_SCALAR
>::
nodeId
(
const
DiscreteVariable
&
var
)
const
{
230
return
_varMap_
.
get
(
var
);
231
}
232
233
template
<
typename
GUM_SCALAR
>
234
INLINE
NodeId
BayesNet
<
GUM_SCALAR
>::
add
(
const
DiscreteVariable
&
var
) {
235
auto
ptr
=
new
MultiDimArray
<
GUM_SCALAR
>();
236
try
{
237
return
add
(
var
,
ptr
);
238
}
catch
(
Exception
&) {
239
delete
ptr
;
240
throw
;
241
}
242
}
243
244
template
<
typename
GUM_SCALAR
>
245
INLINE
NodeId
BayesNet
<
GUM_SCALAR
>::
add
(
const
std
::
string
&
name
,
unsigned
int
nbrmod
) {
246
if
(
nbrmod
< 2) {
247
GUM_ERROR
(
OperationNotAllowed
,
248
"Variable "
<<
name
<<
"needs more than "
<<
nbrmod
<<
" modalities"
)
249
}
250
251
RangeVariable
v
(
name
,
name
, 0,
nbrmod
- 1);
252
return
add
(
v
);
253
}
254
255
template
<
typename
GUM_SCALAR
>
256
INLINE
NodeId
BayesNet
<
GUM_SCALAR
>::
add
(
const
DiscreteVariable
&
var
,
257
MultiDimImplementation
<
GUM_SCALAR
>*
aContent
) {
258
NodeId
proposedId
=
dag
().
nextNodeId
();
259
260
return
add
(
var
,
aContent
,
proposedId
);
261
}
262
263
template
<
typename
GUM_SCALAR
>
264
INLINE
NodeId
BayesNet
<
GUM_SCALAR
>::
add
(
const
DiscreteVariable
&
var
,
NodeId
id
) {
265
auto
ptr
=
new
MultiDimArray
<
GUM_SCALAR
>();
266
267
try
{
268
return
add
(
var
,
ptr
,
id
);
269
270
}
catch
(
Exception
&) {
271
delete
ptr
;
272
throw
;
273
}
274
}
275
276
template
<
typename
GUM_SCALAR
>
277
NodeId
BayesNet
<
GUM_SCALAR
>::
add
(
const
DiscreteVariable
&
var
,
278
MultiDimImplementation
<
GUM_SCALAR
>*
aContent
,
279
NodeId
id
) {
280
_varMap_
.
insert
(
id
,
var
);
281
this
->
dag_
.
addNodeWithId
(
id
);
282
283
auto
cpt
=
new
Potential
<
GUM_SCALAR
>(
aContent
);
284
(*
cpt
) <<
variable
(
id
);
285
_probaMap_
.
insert
(
id
,
cpt
);
286
return
id
;
287
}
288
289
template
<
typename
GUM_SCALAR
>
290
INLINE
NodeId
BayesNet
<
GUM_SCALAR
>::
idFromName
(
const
std
::
string
&
name
)
const
{
291
return
_varMap_
.
idFromName
(
name
);
292
}
293
294
template
<
typename
GUM_SCALAR
>
295
INLINE
const
DiscreteVariable
&
296
BayesNet
<
GUM_SCALAR
>::
variableFromName
(
const
std
::
string
&
name
)
const
{
297
return
_varMap_
.
variableFromName
(
name
);
298
}
299
300
template
<
typename
GUM_SCALAR
>
301
INLINE
const
Potential
<
GUM_SCALAR
>&
BayesNet
<
GUM_SCALAR
>::
cpt
(
NodeId
varId
)
const
{
302
return
*(
_probaMap_
[
varId
]);
303
}
304
305
template
<
typename
GUM_SCALAR
>
306
INLINE
const
VariableNodeMap
&
BayesNet
<
GUM_SCALAR
>::
variableNodeMap
()
const
{
307
return
_varMap_
;
308
}
309
310
template
<
typename
GUM_SCALAR
>
311
INLINE
void
BayesNet
<
GUM_SCALAR
>::
erase
(
const
DiscreteVariable
&
var
) {
312
erase
(
_varMap_
.
get
(
var
));
313
}
314
315
template
<
typename
GUM_SCALAR
>
316
void
BayesNet
<
GUM_SCALAR
>::
erase
(
NodeId
varId
) {
317
if
(
_varMap_
.
exists
(
varId
)) {
318
// Reduce the variable child's CPT
319
const
NodeSet
&
children
=
this
->
children
(
varId
);
320
321
for
(
const
auto
c
:
children
) {
322
_probaMap_
[
c
]->
erase
(
variable
(
varId
));
323
}
324
325
delete
_probaMap_
[
varId
];
326
327
_probaMap_
.
erase
(
varId
);
328
_varMap_
.
erase
(
varId
);
329
this
->
dag_
.
eraseNode
(
varId
);
330
}
331
}
332
333
template
<
typename
GUM_SCALAR
>
334
void
BayesNet
<
GUM_SCALAR
>::
clear
() {
335
if
(!
this
->
empty
()) {
336
auto
l
=
this
->
nodes
();
337
for
(
const
auto
no
:
l
) {
338
this
->
erase
(
no
);
339
}
340
}
341
}
342
343
template
<
typename
GUM_SCALAR
>
344
INLINE
void
BayesNet
<
GUM_SCALAR
>::
addArc
(
NodeId
tail
,
NodeId
head
) {
345
if
(
this
->
dag_
.
existsArc
(
tail
,
head
)) {
346
GUM_ERROR
(
DuplicateElement
,
"The arc ("
<<
tail
<<
","
<<
head
<<
") already exists."
)
347
}
348
349
this
->
dag_
.
addArc
(
tail
,
head
);
350
// Add parent in the child's CPT
351
(*(
_probaMap_
[
head
])) <<
variable
(
tail
);
352
}
353
354
template
<
typename
GUM_SCALAR
>
355
INLINE
void
BayesNet
<
GUM_SCALAR
>::
addArc
(
const
std
::
string
&
tail
,
const
std
::
string
&
head
) {
356
try
{
357
addArc
(
this
->
idFromName
(
tail
),
this
->
idFromName
(
head
));
358
}
catch
(
DuplicateElement
) {
359
GUM_ERROR
(
DuplicateElement
,
"The arc "
<<
tail
<<
"->"
<<
head
<<
" already exists."
)
360
}
361
}
362
363
template
<
typename
GUM_SCALAR
>
364
INLINE
void
BayesNet
<
GUM_SCALAR
>::
eraseArc
(
const
Arc
&
arc
) {
365
if
(
_varMap_
.
exists
(
arc
.
tail
()) &&
_varMap_
.
exists
(
arc
.
head
())) {
366
NodeId
head
=
arc
.
head
(),
tail
=
arc
.
tail
();
367
this
->
dag_
.
eraseArc
(
arc
);
368
// Remove parent from child's CPT
369
(*(
_probaMap_
[
head
])) >>
variable
(
tail
);
370
}
371
}
372
373
template
<
typename
GUM_SCALAR
>
374
INLINE
void
BayesNet
<
GUM_SCALAR
>::
eraseArc
(
NodeId
tail
,
NodeId
head
) {
375
eraseArc
(
Arc
(
tail
,
head
));
376
}
377
378
template
<
typename
GUM_SCALAR
>
379
void
BayesNet
<
GUM_SCALAR
>::
reverseArc
(
const
Arc
&
arc
) {
380
// check that the arc exists
381
if
(!
_varMap_
.
exists
(
arc
.
tail
()) || !
_varMap_
.
exists
(
arc
.
head
()) || !
dag
().
existsArc
(
arc
)) {
382
GUM_ERROR
(
InvalidArc
,
"a non-existing arc cannot be reversed"
)
383
}
384
385
NodeId
tail
=
arc
.
tail
(),
head
=
arc
.
head
();
386
387
// check that the reversal does not induce a cycle
388
try
{
389
DAG
d
=
dag
();
390
d
.
eraseArc
(
arc
);
391
d
.
addArc
(
head
,
tail
);
392
}
catch
(
Exception
&) {
393
GUM_ERROR
(
InvalidArc
,
"this arc reversal would induce a directed cycle"
)
394
}
395
396
// with the same notations as Shachter (1986), "evaluating influence
397
// diagrams", p.878, we shall first compute the product of probabilities:
398
// pi_j^old (x_j | x_c^old(j) ) * pi_i^old (x_i | x_c^old(i) )
399
Potential
<
GUM_SCALAR
>
prod
{
cpt
(
tail
) *
cpt
(
head
)};
400
401
// modify the topology of the graph: add to tail all the parents of head
402
// and add to head all the parents of tail
403
beginTopologyTransformation
();
404
NodeSet
new_parents
;
405
for
(
const
auto
node
:
this
->
parents
(
tail
))
406
new_parents
.
insert
(
node
);
407
for
(
const
auto
node
:
this
->
parents
(
head
))
408
new_parents
.
insert
(
node
);
409
// remove arc (head, tail)
410
eraseArc
(
arc
);
411
412
// add the necessary arcs to the tail
413
for
(
const
auto
p
:
new_parents
) {
414
if
((
p
!=
tail
) && !
dag
().
existsArc
(
p
,
tail
)) {
addArc
(
p
,
tail
); }
415
}
416
417
addArc
(
head
,
tail
);
418
// add the necessary arcs to the head
419
new_parents
.
erase
(
tail
);
420
421
for
(
const
auto
p
:
new_parents
) {
422
if
((
p
!=
head
) && !
dag
().
existsArc
(
p
,
head
)) {
addArc
(
p
,
head
); }
423
}
424
425
endTopologyTransformation
();
426
427
// update the conditional distributions of head and tail
428
Set
<
const
DiscreteVariable
* >
del_vars
;
429
del_vars
<< &(
variable
(
tail
));
430
Potential
<
GUM_SCALAR
>
new_cpt_head
=
prod
.
margSumOut
(
del_vars
).
putFirst
(&
variable
(
head
));
431
432
auto
&
cpt_head
=
const_cast
<
Potential
<
GUM_SCALAR
>& >(
cpt
(
head
));
433
cpt_head
=
std
::
move
(
new_cpt_head
);
434
435
Potential
<
GUM_SCALAR
>
new_cpt_tail
{(
prod
/
cpt_head
).
putFirst
(&
variable
(
tail
))};
436
auto
&
cpt_tail
=
const_cast
<
Potential
<
GUM_SCALAR
>& >(
cpt
(
tail
));
437
cpt_tail
=
std
::
move
(
new_cpt_tail
);
438
}
439
440
template
<
typename
GUM_SCALAR
>
441
INLINE
void
BayesNet
<
GUM_SCALAR
>::
reverseArc
(
NodeId
tail
,
NodeId
head
) {
442
reverseArc
(
Arc
(
tail
,
head
));
443
}
444
445
446
//==============================================
447
// Aggregators
448
//=============================================
449
template
<
typename
GUM_SCALAR
>
450
INLINE
NodeId
BayesNet
<
GUM_SCALAR
>::
addAMPLITUDE
(
const
DiscreteVariable
&
var
) {
451
return
add
(
var
,
new
aggregator
::
Amplitude
<
GUM_SCALAR
>());
452
}
453
454
template
<
typename
GUM_SCALAR
>
455
INLINE
NodeId
BayesNet
<
GUM_SCALAR
>::
addAND
(
const
DiscreteVariable
&
var
) {
456
if
(
var
.
domainSize
() > 2)
GUM_ERROR
(
SizeError
,
"an AND has to be boolean"
)
457
458
return
add
(
var
,
new
aggregator
::
And
<
GUM_SCALAR
>());
459
}
460
461
template
<
typename
GUM_SCALAR
>
462
INLINE
NodeId
BayesNet
<
GUM_SCALAR
>::
addCOUNT
(
const
DiscreteVariable
&
var
,
Idx
value
) {
463
return
add
(
var
,
new
aggregator
::
Count
<
GUM_SCALAR
>(
value
));
464
}
465
466
template
<
typename
GUM_SCALAR
>
467
INLINE
NodeId
BayesNet
<
GUM_SCALAR
>::
addEXISTS
(
const
DiscreteVariable
&
var
,
Idx
value
) {
468
if
(
var
.
domainSize
() > 2)
GUM_ERROR
(
SizeError
,
"an EXISTS has to be boolean"
)
469
470
return
add
(
var
,
new
aggregator
::
Exists
<
GUM_SCALAR
>(
value
));
471
}
472
473
template
<
typename
GUM_SCALAR
>
474
INLINE
NodeId
BayesNet
<
GUM_SCALAR
>::
addFORALL
(
const
DiscreteVariable
&
var
,
Idx
value
) {
475
if
(
var
.
domainSize
() > 2)
GUM_ERROR
(
SizeError
,
"an EXISTS has to be boolean"
)
476
477
return
add
(
var
,
new
aggregator
::
Forall
<
GUM_SCALAR
>(
value
));
478
}
479
480
template
<
typename
GUM_SCALAR
>
481
INLINE
NodeId
BayesNet
<
GUM_SCALAR
>::
addMAX
(
const
DiscreteVariable
&
var
) {
482
return
add
(
var
,
new
aggregator
::
Max
<
GUM_SCALAR
>());
483
}
484
485
template
<
typename
GUM_SCALAR
>
486
INLINE
NodeId
BayesNet
<
GUM_SCALAR
>::
addMEDIAN
(
const
DiscreteVariable
&
var
) {
487
return
add
(
var
,
new
aggregator
::
Median
<
GUM_SCALAR
>());
488
}
489
490
template
<
typename
GUM_SCALAR
>
491
INLINE
NodeId
BayesNet
<
GUM_SCALAR
>::
addMIN
(
const
DiscreteVariable
&
var
) {
492
return
add
(
var
,
new
aggregator
::
Min
<
GUM_SCALAR
>());
493
}
494
495
template
<
typename
GUM_SCALAR
>
496
INLINE
NodeId
BayesNet
<
GUM_SCALAR
>::
addOR
(
const
DiscreteVariable
&
var
) {
497
if
(
var
.
domainSize
() > 2)
GUM_ERROR
(
SizeError
,
"an OR has to be boolean"
)
498
499
return
add
(
var
,
new
aggregator
::
Or
<
GUM_SCALAR
>());
500
}
501
502
template
<
typename
GUM_SCALAR
>
503
INLINE
NodeId
BayesNet
<
GUM_SCALAR
>::
addSUM
(
const
DiscreteVariable
&
var
) {
504
return
add
(
var
,
new
aggregator
::
Sum
<
GUM_SCALAR
>());
505
}
506
507
//================================
508
// ICIModels
509
//================================
510
template
<
typename
GUM_SCALAR
>
511
INLINE
NodeId
BayesNet
<
GUM_SCALAR
>::
addNoisyOR
(
const
DiscreteVariable
&
var
,
512
GUM_SCALAR
external_weight
) {
513
return
addNoisyORCompound
(
var
,
external_weight
);
514
}
515
516
template
<
typename
GUM_SCALAR
>
517
INLINE
NodeId
BayesNet
<
GUM_SCALAR
>::
addNoisyORCompound
(
const
DiscreteVariable
&
var
,
518
GUM_SCALAR
external_weight
) {
519
return
add
(
var
,
new
MultiDimNoisyORCompound
<
GUM_SCALAR
>(
external_weight
));
520
}
521
522
template
<
typename
GUM_SCALAR
>
523
INLINE
NodeId
BayesNet
<
GUM_SCALAR
>::
addNoisyORNet
(
const
DiscreteVariable
&
var
,
524
GUM_SCALAR
external_weight
) {
525
return
add
(
var
,
new
MultiDimNoisyORNet
<
GUM_SCALAR
>(
external_weight
));
526
}
527
528
template
<
typename
GUM_SCALAR
>
529
INLINE
NodeId
BayesNet
<
GUM_SCALAR
>::
addNoisyAND
(
const
DiscreteVariable
&
var
,
530
GUM_SCALAR
external_weight
) {
531
return
add
(
var
,
new
MultiDimNoisyAND
<
GUM_SCALAR
>(
external_weight
));
532
}
533
534
template
<
typename
GUM_SCALAR
>
535
INLINE
NodeId
BayesNet
<
GUM_SCALAR
>::
addLogit
(
const
DiscreteVariable
&
var
,
536
GUM_SCALAR
external_weight
) {
537
return
add
(
var
,
new
MultiDimLogit
<
GUM_SCALAR
>(
external_weight
));
538
}
539
540
template
<
typename
GUM_SCALAR
>
541
INLINE
NodeId
BayesNet
<
GUM_SCALAR
>::
addNoisyOR
(
const
DiscreteVariable
&
var
,
542
GUM_SCALAR
external_weight
,
543
NodeId
id
) {
544
return
addNoisyORCompound
(
var
,
external_weight
,
id
);
545
}
546
547
template
<
typename
GUM_SCALAR
>
548
INLINE
NodeId
BayesNet
<
GUM_SCALAR
>::
addNoisyAND
(
const
DiscreteVariable
&
var
,
549
GUM_SCALAR
external_weight
,
550
NodeId
id
) {
551
return
add
(
var
,
new
MultiDimNoisyAND
<
GUM_SCALAR
>(
external_weight
),
id
);
552
}
553
554
template
<
typename
GUM_SCALAR
>
555
INLINE
NodeId
BayesNet
<
GUM_SCALAR
>::
addLogit
(
const
DiscreteVariable
&
var
,
556
GUM_SCALAR
external_weight
,
557
NodeId
id
) {
558
return
add
(
var
,
new
MultiDimLogit
<
GUM_SCALAR
>(
external_weight
),
id
);
559
}
560
561
template
<
typename
GUM_SCALAR
>
562
INLINE
NodeId
BayesNet
<
GUM_SCALAR
>::
addNoisyORCompound
(
const
DiscreteVariable
&
var
,
563
GUM_SCALAR
external_weight
,
564
NodeId
id
) {
565
return
add
(
var
,
new
MultiDimNoisyORCompound
<
GUM_SCALAR
>(
external_weight
),
id
);
566
}
567
568
template
<
typename
GUM_SCALAR
>
569
INLINE
NodeId
BayesNet
<
GUM_SCALAR
>::
addNoisyORNet
(
const
DiscreteVariable
&
var
,
570
GUM_SCALAR
external_weight
,
571
NodeId
id
) {
572
return
add
(
var
,
new
MultiDimNoisyORNet
<
GUM_SCALAR
>(
external_weight
),
id
);
573
}
574
575
template
<
typename
GUM_SCALAR
>
576
void
BayesNet
<
GUM_SCALAR
>::
addWeightedArc
(
NodeId
tail
,
NodeId
head
,
GUM_SCALAR
causalWeight
) {
577
auto
*
CImodel
=
dynamic_cast
<
const
MultiDimICIModel
<
GUM_SCALAR
>* >(
cpt
(
head
).
content
());
578
579
if
(
CImodel
!= 0) {
580
// or is OK
581
addArc
(
tail
,
head
);
582
583
CImodel
->
causalWeight
(
variable
(
tail
),
causalWeight
);
584
}
else
{
585
GUM_ERROR
(
InvalidArc
,
586
"Head variable ("
<<
variable
(
head
).
name
() <<
") is not a CIModel variable !"
)
587
}
588
}
589
590
template
<
typename
GUM_SCALAR
>
591
INLINE
std
::
ostream
&
operator
<<(
std
::
ostream
&
output
,
const
BayesNet
<
GUM_SCALAR
>&
bn
) {
592
output
<<
bn
.
toString
();
593
return
output
;
594
}
595
596
/// begin Multiple Change for all CPTs
597
template
<
typename
GUM_SCALAR
>
598
void
BayesNet
<
GUM_SCALAR
>::
beginTopologyTransformation
() {
599
for
(
const
auto
node
:
nodes
())
600
_probaMap_
[
node
]->
beginMultipleChanges
();
601
}
602
603
/// end Multiple Change for all CPTs
604
template
<
typename
GUM_SCALAR
>
605
void
BayesNet
<
GUM_SCALAR
>::
endTopologyTransformation
() {
606
for
(
const
auto
node
:
nodes
())
607
_probaMap_
[
node
]->
endMultipleChanges
();
608
}
609
610
/// clear all potentials
611
template
<
typename
GUM_SCALAR
>
612
void
BayesNet
<
GUM_SCALAR
>::
_clearPotentials_
() {
613
// Removing previous potentials
614
for
(
const
auto
&
elt
:
_probaMap_
) {
615
delete
elt
.
second
;
616
}
617
618
_probaMap_
.
clear
();
619
}
620
621
/// copy of potentials from a BN to another, using names of vars as ref.
622
template
<
typename
GUM_SCALAR
>
623
void
BayesNet
<
GUM_SCALAR
>::
_copyPotentials_
(
const
BayesNet
<
GUM_SCALAR
>&
source
) {
624
// Copying potentials
625
626
for
(
const
auto
src
:
source
.
_probaMap_
) {
627
// First we build the node's CPT
628
Potential
<
GUM_SCALAR
>*
copy_array
=
new
Potential
<
GUM_SCALAR
>();
629
copy_array
->
beginMultipleChanges
();
630
for
(
gum
::
Idx
i
= 0;
i
<
src
.
second
->
nbrDim
();
i
++) {
631
(*
copy_array
) <<
variableFromName
(
src
.
second
->
variable
(
i
).
name
());
632
}
633
copy_array
->
endMultipleChanges
();
634
copy_array
->
copyFrom
(*(
src
.
second
));
635
636
// We add the CPT to the CPT hashmap
637
_probaMap_
.
insert
(
src
.
first
,
copy_array
);
638
}
639
}
640
641
template
<
typename
GUM_SCALAR
>
642
INLINE
void
BayesNet
<
GUM_SCALAR
>::
generateCPTs
()
const
{
643
for
(
const
auto
node
:
nodes
())
644
generateCPT
(
node
);
645
}
646
647
template
<
typename
GUM_SCALAR
>
648
INLINE
void
BayesNet
<
GUM_SCALAR
>::
generateCPT
(
NodeId
node
)
const
{
649
SimpleCPTGenerator
<
GUM_SCALAR
>
generator
;
650
651
generator
.
generateCPT
(
cpt
(
node
).
pos
(
variable
(
node
)),
cpt
(
node
));
652
}
653
654
template
<
typename
GUM_SCALAR
>
655
void
BayesNet
<
GUM_SCALAR
>::
changePotential
(
NodeId
id
,
Potential
<
GUM_SCALAR
>*
newPot
) {
656
if
(
cpt
(
id
).
nbrDim
() !=
newPot
->
nbrDim
()) {
657
GUM_ERROR
(
OperationNotAllowed
,
658
"cannot exchange potentials with different "
659
"dimensions for variable with id "
660
<<
id
)
661
}
662
663
for
(
Idx
i
= 0;
i
<
cpt
(
id
).
nbrDim
();
i
++) {
664
if
(&
cpt
(
id
).
variable
(
i
) != &(
newPot
->
variable
(
i
))) {
665
GUM_ERROR
(
OperationNotAllowed
,
666
"cannot exchange potentials because, for variable with id "
667
<<
id
<<
", dimension "
<<
i
<<
" differs. "
)
668
}
669
}
670
671
_unsafeChangePotential_
(
id
,
newPot
);
672
}
673
674
template
<
typename
GUM_SCALAR
>
675
void
BayesNet
<
GUM_SCALAR
>::
_unsafeChangePotential_
(
NodeId
id
,
Potential
<
GUM_SCALAR
>*
newPot
) {
676
delete
_probaMap_
[
id
];
677
_probaMap_
[
id
] =
newPot
;
678
}
679
680
template
<
typename
GUM_SCALAR
>
681
void
BayesNet
<
GUM_SCALAR
>::
changePotential
(
const
std
::
string
&
name
,
682
Potential
<
GUM_SCALAR
>*
newPot
) {
683
changePotential
(
idFromName
(
name
),
newPot
);
684
}
685
686
}
/* namespace gum */
gum::Set::emplace
INLINE void emplace(Args &&... args)
Definition:
set_tpl.h:643
gum::build_node
NodeId build_node(gum::BayesNet< GUM_SCALAR > &bn, std::string node, gum::Size default_domain_size)
Definition:
BayesNet_tpl.h:61