aGrUM
0.20.2
a C++ library for (probabilistic) graphical models
IBayesNet_tpl.h
Go to the documentation of this file.
1
/**
2
*
3
* Copyright 2005-2020 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 bns/bayesNet.h classes.
25
*
26
* @author Pierre-Henri WUILLEMIN(@LIP6) and Lionel TORTI
27
*/
28
29
#
include
<
limits
>
30
#
include
<
cmath
>
31
32
#
include
<
agrum
/
BN
/
IBayesNet
.
h
>
33
34
#
include
<
agrum
/
tools
/
multidim
/
aggregators
/
and
.
h
>
35
#
include
<
agrum
/
tools
/
multidim
/
aggregators
/
or
.
h
>
36
37
#
include
<
agrum
/
tools
/
multidim
/
ICIModels
/
multiDimNoisyAND
.
h
>
38
#
include
<
agrum
/
tools
/
multidim
/
ICIModels
/
multiDimNoisyORCompound
.
h
>
39
#
include
<
agrum
/
tools
/
multidim
/
ICIModels
/
multiDimNoisyORNet
.
h
>
40
41
#
include
<
agrum
/
BN
/
generator
/
simpleCPTGenerator
.
h
>
42
#
include
<
agrum
/
tools
/
multidim
/
potential
.
h
>
43
44
namespace
gum
{
45
46
// IBayesNet
47
48
template
<
typename
GUM_SCALAR >
49
INLINE IBayesNet<
GUM_SCALAR
>::
IBayesNet
() :
DAGmodel
() {
50
GUM_CONSTRUCTOR
(
IBayesNet
);
51
}
52
53
template
<
typename
GUM_SCALAR
>
54
INLINE
IBayesNet
<
GUM_SCALAR
>::
IBayesNet
(
std
::
string
name
) :
DAGmodel
() {
55
GUM_CONSTRUCTOR
(
IBayesNet
);
56
this
->
setProperty
(
"name"
,
name
);
57
}
58
59
template
<
typename
GUM_SCALAR
>
60
IBayesNet
<
GUM_SCALAR
>::
IBayesNet
(
const
IBayesNet
<
GUM_SCALAR
>&
source
) :
61
DAGmodel
(
source
) {
62
GUM_CONS_CPY
(
IBayesNet
);
63
}
64
65
template
<
typename
GUM_SCALAR
>
66
IBayesNet
<
GUM_SCALAR
>&
67
IBayesNet
<
GUM_SCALAR
>::
operator
=(
const
IBayesNet
<
GUM_SCALAR
>&
source
) {
68
if
(
this
!= &
source
) {
DAGmodel
::
operator
=(
source
); }
69
70
return
*
this
;
71
}
72
73
template
<
typename
GUM_SCALAR
>
74
IBayesNet
<
GUM_SCALAR
>::~
IBayesNet
() {
75
GUM_DESTRUCTOR
(
IBayesNet
);
76
}
77
78
template
<
typename
GUM_SCALAR
>
79
Size
IBayesNet
<
GUM_SCALAR
>::
dim
()
const
{
80
Size
dim
= 0;
81
82
for
(
auto
node
:
nodes
()) {
83
Size
q
= 1;
84
85
for
(
auto
parent
:
parents
(
node
))
86
q
*=
variable
(
parent
).
domainSize
();
87
88
dim
+= (
variable
(
node
).
domainSize
() - 1) *
q
;
89
}
90
91
return
dim
;
92
}
93
94
template
<
typename
GUM_SCALAR
>
95
Size
IBayesNet
<
GUM_SCALAR
>::
maxVarDomainSize
()
const
{
96
Size
res
= 0;
97
for
(
auto
node
:
nodes
()) {
98
auto
v
=
variable
(
node
).
domainSize
();
99
if
(
v
>
res
) {
res
=
v
; }
100
}
101
return
res
;
102
}
103
104
template
<
typename
GUM_SCALAR
>
105
GUM_SCALAR
IBayesNet
<
GUM_SCALAR
>::
minParam
()
const
{
106
GUM_SCALAR
res
= 1.0;
107
for
(
auto
node
:
nodes
()) {
108
auto
v
=
cpt
(
node
).
min
();
109
if
(
v
<
res
) {
res
=
v
; }
110
}
111
return
res
;
112
}
113
114
template
<
typename
GUM_SCALAR
>
115
GUM_SCALAR
IBayesNet
<
GUM_SCALAR
>::
maxParam
()
const
{
116
GUM_SCALAR
res
= 1.0;
117
for
(
auto
node
:
nodes
()) {
118
auto
v
=
cpt
(
node
).
max
();
119
if
(
v
>
res
) {
res
=
v
; }
120
}
121
return
res
;
122
}
123
124
template
<
typename
GUM_SCALAR
>
125
GUM_SCALAR
IBayesNet
<
GUM_SCALAR
>::
minNonZeroParam
()
const
{
126
GUM_SCALAR
res
= 1.0;
127
for
(
auto
node
:
nodes
()) {
128
auto
v
=
cpt
(
node
).
minNonZero
();
129
if
(
v
<
res
) {
res
=
v
; }
130
}
131
return
res
;
132
}
133
134
template
<
typename
GUM_SCALAR
>
135
GUM_SCALAR
IBayesNet
<
GUM_SCALAR
>::
maxNonOneParam
()
const
{
136
GUM_SCALAR
res
= 0.0;
137
for
(
auto
node
:
nodes
()) {
138
auto
v
=
cpt
(
node
).
maxNonOne
();
139
if
(
v
>
res
) {
res
=
v
; }
140
}
141
return
res
;
142
}
143
144
template
<
typename
GUM_SCALAR
>
145
INLINE
std
::
string
IBayesNet
<
GUM_SCALAR
>::
toString
()
const
{
146
Size
param
= 0;
147
double
dSize
=
log10DomainSize
();
148
149
for
(
auto
node
:
nodes
())
150
param
+=
cpt
(
node
).
content
()->
realSize
();
151
152
std
::
stringstream
s
;
153
s
<<
"BN{nodes: "
<<
size
() <<
", arcs: "
<<
dag
().
sizeArcs
() <<
", "
;
154
155
if
(
dSize
> 6)
156
s
<<
"domainSize: 10^"
<<
dSize
;
157
else
158
s
<<
"domainSize: "
<<
std
::
round
(
std
::
pow
(10.0,
dSize
));
159
160
s
<<
", dim: "
<<
param
<<
"}"
;
161
162
return
s
.
str
();
163
}
164
165
template
<
typename
GUM_SCALAR
>
166
std
::
string
IBayesNet
<
GUM_SCALAR
>::
toDot
()
const
{
167
std
::
stringstream
output
;
168
output
<<
"digraph \""
;
169
170
std
::
string
bn_name
;
171
172
try
{
173
bn_name
=
this
->
property
(
"name"
);
174
}
catch
(
NotFound
&) {
bn_name
=
"no_name"
; }
175
176
output
<<
bn_name
<<
"\" {"
<<
std
::
endl
;
177
output
<<
" graph [bgcolor=transparent,label=\""
<<
bn_name
<<
"\"];"
178
<<
std
::
endl
;
179
output
<<
" node [style=filled fillcolor=\"#ffffaa\"];"
<<
std
::
endl
180
<<
std
::
endl
;
181
182
for
(
auto
node
:
nodes
())
183
output
<<
"\""
<<
variable
(
node
).
name
() <<
"\" [comment=\""
<<
node
<<
":"
184
<<
variable
(
node
).
toStringWithDescription
() <<
"\"];"
<<
std
::
endl
;
185
186
output
<<
std
::
endl
;
187
188
std
::
string
tab
=
" "
;
189
190
for
(
auto
node
:
nodes
()) {
191
if
(
children
(
node
).
size
() > 0) {
192
for
(
auto
child
:
children
(
node
)) {
193
output
<<
tab
<<
"\""
<<
variable
(
node
).
name
() <<
"\" -> "
194
<<
"\""
<<
variable
(
child
).
name
() <<
"\";"
<<
std
::
endl
;
195
}
196
}
else
if
(
parents
(
node
).
size
() == 0) {
197
output
<<
tab
<<
"\""
<<
variable
(
node
).
name
() <<
"\";"
<<
std
::
endl
;
198
}
199
}
200
201
output
<<
"}"
<<
std
::
endl
;
202
203
return
output
.
str
();
204
}
205
206
/// Compute a parameter of the joint probability for the BN (given an
207
/// instantiation
208
/// of the vars)
209
template
<
typename
GUM_SCALAR
>
210
GUM_SCALAR
211
IBayesNet
<
GUM_SCALAR
>::
jointProbability
(
const
Instantiation
&
i
)
const
{
212
auto
value
= (
GUM_SCALAR
)1.0;
213
214
GUM_SCALAR
tmp
;
215
216
for
(
auto
node
:
nodes
()) {
217
if
((
tmp
=
cpt
(
node
)[
i
]) == (
GUM_SCALAR
)0) {
return
(
GUM_SCALAR
)0; }
218
219
value
*=
tmp
;
220
}
221
222
return
value
;
223
}
224
225
/// Compute a parameter of the joint probability for the BN (given an
226
/// instantiation
227
/// of the vars)
228
template
<
typename
GUM_SCALAR
>
229
GUM_SCALAR
230
IBayesNet
<
GUM_SCALAR
>::
log2JointProbability
(
const
Instantiation
&
i
)
const
{
231
auto
value
= (
GUM_SCALAR
)0.0;
232
233
GUM_SCALAR
tmp
;
234
235
for
(
auto
node
:
nodes
()) {
236
if
((
tmp
=
cpt
(
node
)[
i
]) == (
GUM_SCALAR
)0) {
237
return
(
GUM_SCALAR
)(-
std
::
numeric_limits
<
double
>::
infinity
());
238
}
239
240
value
+=
std
::
log2
(
cpt
(
node
)[
i
]);
241
}
242
243
return
value
;
244
}
245
246
template
<
typename
GUM_SCALAR
>
247
bool
IBayesNet
<
GUM_SCALAR
>::
operator
==(
const
IBayesNet
&
from
)
const
{
248
if
(
size
() !=
from
.
size
()) {
return
false
; }
249
250
if
(
sizeArcs
() !=
from
.
sizeArcs
()) {
return
false
; }
251
252
// alignment of variables between the 2 BNs
253
Bijection
<
const
DiscreteVariable
*,
const
DiscreteVariable
* >
alignment
;
254
255
for
(
auto
node
:
nodes
()) {
256
try
{
257
alignment
.
insert
(&
variable
(
node
),
258
&
from
.
variableFromName
(
variable
(
node
).
name
()));
259
}
catch
(
NotFound
&) {
260
// a name is not found in from
261
return
false
;
262
}
263
}
264
265
for
(
auto
node
:
nodes
()) {
266
NodeId
fromnode
=
from
.
idFromName
(
variable
(
node
).
name
());
267
268
if
(
cpt
(
node
).
nbrDim
() !=
from
.
cpt
(
fromnode
).
nbrDim
()) {
return
false
; }
269
270
if
(
cpt
(
node
).
domainSize
() !=
from
.
cpt
(
fromnode
).
domainSize
()) {
271
return
false
;
272
}
273
274
Instantiation
i
(
cpt
(
node
));
275
Instantiation
j
(
from
.
cpt
(
fromnode
));
276
277
for
(
i
.
setFirst
(); !
i
.
end
();
i
.
inc
()) {
278
for
(
Idx
indice
= 0;
indice
<
cpt
(
node
).
nbrDim
(); ++
indice
) {
279
const
DiscreteVariable
*
p
= &(
i
.
variable
(
indice
));
280
j
.
chgVal
(*(
alignment
.
second
(
p
)),
i
.
val
(*
p
));
281
}
282
283
if
(
std
::
pow
(
cpt
(
node
).
get
(
i
) -
from
.
cpt
(
fromnode
).
get
(
j
), (
GUM_SCALAR
)2)
284
> (
GUM_SCALAR
)1e-6) {
285
return
false
;
286
}
287
}
288
}
289
290
return
true
;
291
}
292
293
template
<
typename
GUM_SCALAR
>
294
bool
IBayesNet
<
GUM_SCALAR
>::
operator
!=(
const
IBayesNet
&
from
)
const
{
295
return
!
this
->
operator
==(
from
);
296
}
297
298
// visit the nodes and add some of node from soids in minimal
299
template
<
typename
GUM_SCALAR
>
300
void
IBayesNet
<
GUM_SCALAR
>::
minimalCondSetVisitUp__
(
301
NodeId
node
,
302
const
NodeSet
&
soids
,
303
NodeSet
&
minimal
,
304
NodeSet
&
alreadyVisitedUp
,
305
NodeSet
&
alreadyVisitedDn
)
const
{
306
if
(
alreadyVisitedUp
.
contains
(
node
))
return
;
307
alreadyVisitedUp
<<
node
;
308
309
if
(
soids
.
contains
(
node
)) {
310
minimal
<<
node
;
311
}
else
{
312
for
(
auto
fath
:
dag_
.
parents
(
node
))
313
minimalCondSetVisitUp__
(
fath
,
314
soids
,
315
minimal
,
316
alreadyVisitedUp
,
317
alreadyVisitedDn
);
318
for
(
auto
chil
:
dag_
.
children
(
node
))
319
minimalCondSetVisitDn__
(
chil
,
320
soids
,
321
minimal
,
322
alreadyVisitedUp
,
323
alreadyVisitedDn
);
324
}
325
}
326
327
// visit the nodes and add some of node from soids in minimal
328
template
<
typename
GUM_SCALAR
>
329
void
IBayesNet
<
GUM_SCALAR
>::
minimalCondSetVisitDn__
(
330
NodeId
node
,
331
const
NodeSet
&
soids
,
332
NodeSet
&
minimal
,
333
NodeSet
&
alreadyVisitedUp
,
334
NodeSet
&
alreadyVisitedDn
)
const
{
335
if
(
alreadyVisitedDn
.
contains
(
node
))
return
;
336
alreadyVisitedDn
<<
node
;
337
338
if
(
soids
.
contains
(
node
)) {
339
minimal
<<
node
;
340
for
(
auto
fath
:
dag_
.
parents
(
node
))
341
minimalCondSetVisitUp__
(
fath
,
342
soids
,
343
minimal
,
344
alreadyVisitedUp
,
345
alreadyVisitedDn
);
346
}
else
{
347
for
(
auto
chil
:
dag_
.
children
(
node
))
348
minimalCondSetVisitDn__
(
chil
,
349
soids
,
350
minimal
,
351
alreadyVisitedUp
,
352
alreadyVisitedDn
);
353
}
354
}
355
356
357
template
<
typename
GUM_SCALAR
>
358
NodeSet
IBayesNet
<
GUM_SCALAR
>::
minimalCondSet
(
NodeId
target
,
359
const
NodeSet
&
soids
)
const
{
360
if
(
soids
.
contains
(
target
))
return
NodeSet
({
target
});
361
362
NodeSet
res
;
363
NodeSet
alreadyVisitedUp
;
364
NodeSet
alreadyVisitedDn
;
365
alreadyVisitedDn
<<
target
;
366
alreadyVisitedUp
<<
target
;
367
368
for
(
auto
fath
:
dag_
.
parents
(
target
))
369
minimalCondSetVisitUp__
(
fath
,
370
soids
,
371
res
,
372
alreadyVisitedUp
,
373
alreadyVisitedDn
);
374
for
(
auto
chil
:
dag_
.
children
(
target
))
375
minimalCondSetVisitDn__
(
chil
,
376
soids
,
377
res
,
378
alreadyVisitedUp
,
379
alreadyVisitedDn
);
380
return
res
;
381
}
382
383
template
<
typename
GUM_SCALAR
>
384
NodeSet
IBayesNet
<
GUM_SCALAR
>::
minimalCondSet
(
const
NodeSet
&
targets
,
385
const
NodeSet
&
soids
)
const
{
386
NodeSet
res
;
387
for
(
auto
node
:
targets
) {
388
res
+=
minimalCondSet
(
node
,
soids
);
389
}
390
return
res
;
391
}
392
393
template
<
typename
GUM_SCALAR
>
394
INLINE
std
::
ostream
&
operator
<<(
std
::
ostream
&
output
,
395
const
IBayesNet
<
GUM_SCALAR
>&
bn
) {
396
output
<<
bn
.
toString
();
397
return
output
;
398
}
399
400
}
/* namespace gum */
gum::Set::emplace
INLINE void emplace(Args &&... args)
Definition:
set_tpl.h:669