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