aGrUM
0.20.2
a C++ library for (probabilistic) graphical models
MarkovBlanket.cpp
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
/** @file
23
* @brief Source implementation of the class building the Markov Blanket from a
24
* DAGmodel and a node (id or name)
25
*
26
* @author Pierre-Henri WUILLEMIN(@LIP6) & Christophe GONZALES(@AMU)
27
*
28
*/
29
#
include
<
agrum
/
BN
/
algorithms
/
MarkovBlanket
.
h
>
30
31
#
ifdef
GUM_NO_INLINE
32
#
include
<
agrum
/
BN
/
algorithms
/
MarkovBlanket_inl
.
h
>
33
#
endif
// GUM_NOINLINE
34
35
namespace
gum
{
36
MarkovBlanket
::
MarkovBlanket
(
const
DAGmodel
&
m
,
NodeId
id
,
int
level
) :
37
model__
(
m
),
node__
(
id
) {
38
if
(
level
< 1)
39
GUM_ERROR
(
InvalidArgument
,
"Argument level(="
<<
level
<<
") must be >0."
)
40
41
NodeSet
done
;
42
buildMarkovBlanket__
(
node__
);
43
done
.
insert
(
node__
);
44
45
while
(
level
> 1) {
46
level
--;
47
auto
todo
=
mb__
.
nodes
().
asNodeSet
() -
done
;
48
bool
anythingnew
=
false
;
49
for
(
NodeId
n
:
todo
) {
50
done
.
insert
(
n
);
51
if
(
buildMarkovBlanket__
(
n
))
anythingnew
=
true
;
52
}
53
if
(!
anythingnew
)
break
;
54
}
55
56
// we add now some arcs that are between the nodes in mb__ but are not part of
57
// the last ones.
58
// For instance, an arc between a parent and a parent of children
59
for
(
const
auto
node
:
mb__
.
nodes
()) {
60
for
(
const
auto
child
:
model__
.
children
(
node
)) {
61
if
(
mb__
.
existsNode
(
child
) && !
mb__
.
existsArc
(
Arc
(
node
,
child
))) {
62
mb__
.
addArc
(
node
,
child
);
63
specialArcs__
.
insert
(
Arc
(
node
,
child
));
64
}
65
}
66
}
67
}
68
69
MarkovBlanket
::
MarkovBlanket
(
const
DAGmodel
&
m
,
70
const
std
::
string
&
name
,
71
int
level
) :
72
MarkovBlanket
(
m
,
m
.
idFromName
(
name
),
level
) {}
73
74
MarkovBlanket
::~
MarkovBlanket
() {}
75
76
bool
MarkovBlanket
::
buildMarkovBlanket__
(
const
NodeId
node
) {
77
bool
change
=
false
;
78
if
(!
model__
.
nodes
().
exists
(
node
))
79
GUM_ERROR
(
InvalidArgument
,
"Node "
<<
node
<<
" does not exist."
);
80
81
if
(!
mb__
.
nodes
().
exists
(
node
)) {
82
mb__
.
addNodeWithId
(
node
);
83
change
=
true
;
84
}
85
86
for
(
const
auto
&
parent
:
model__
.
parents
(
node
)) {
87
if
(!
mb__
.
nodes
().
exists
(
parent
)) {
88
mb__
.
addNodeWithId
(
parent
);
89
change
=
true
;
90
}
91
mb__
.
addArc
(
parent
,
node
);
92
}
93
94
for
(
const
auto
&
child
:
model__
.
children
(
node
)) {
95
if
(!
mb__
.
nodes
().
exists
(
child
)) {
96
mb__
.
addNodeWithId
(
child
);
97
change
=
true
;
98
}
99
mb__
.
addArc
(
node
,
child
);
100
for
(
const
auto
&
opar
:
model__
.
parents
(
child
)) {
101
if
(
opar
!=
node
) {
102
if
(!
mb__
.
nodes
().
exists
(
opar
)) {
103
mb__
.
addNodeWithId
(
opar
);
104
change
=
true
;
105
}
106
mb__
.
addArc
(
opar
,
child
);
107
}
108
}
109
}
110
111
return
change
;
112
}
113
114
bool
MarkovBlanket
::
hasSameStructure
(
const
DAGmodel
&
other
) {
115
if
(
size
() !=
other
.
size
())
return
false
;
116
117
if
(
sizeArcs
() !=
other
.
sizeArcs
())
return
false
;
118
119
for
(
const
auto
&
nid
:
nodes
()) {
120
try
{
121
other
.
idFromName
(
model__
.
variable
(
nid
).
name
());
122
}
catch
(
NotFound
) {
return
false
; }
123
}
124
125
for
(
const
auto
&
arc
:
arcs
()) {
126
if
(!
other
.
arcs
().
exists
(
127
Arc
(
other
.
idFromName
(
model__
.
variable
(
arc
.
tail
()).
name
()),
128
other
.
idFromName
(
model__
.
variable
(
arc
.
head
()).
name
()))))
129
return
false
;
130
}
131
132
return
true
;
133
}
134
135
std
::
string
MarkovBlanket
::
toDot
()
const
{
136
std
::
stringstream
output
;
137
std
::
stringstream
nodeStream
;
138
std
::
stringstream
arcStream
;
139
List
<
NodeId
>
treatedNodes
;
140
output
<<
"digraph \""
141
<<
"no_name\" {"
<<
std
::
endl
;
142
nodeStream
<<
"node [shape = ellipse];"
<<
std
::
endl
;
143
std
::
string
tab
=
" "
;
144
145
for
(
const
auto
node
:
mb__
.
nodes
()) {
146
nodeStream
<<
tab
<<
node
<<
"[label=\""
<<
model__
.
variable
(
node
).
name
()
147
<<
"\""
;
148
if
(
node
==
node__
) {
nodeStream
<<
", color=red"
; }
149
nodeStream
<<
"];"
<<
std
::
endl
;
150
151
for
(
const
auto
chi
:
mb__
.
children
(
node
)) {
152
arcStream
<<
tab
<<
node
<<
" -> "
<<
chi
;
153
if
(
specialArcs__
.
exists
(
Arc
(
node
,
chi
))) {
arcStream
<<
" [color=grey]"
; }
154
arcStream
<<
";"
<<
std
::
endl
;
155
}
156
}
157
158
output
<<
nodeStream
.
str
() <<
std
::
endl
159
<<
arcStream
.
str
() <<
std
::
endl
160
<<
"}"
<<
std
::
endl
;
161
162
return
output
.
str
();
163
}
164
}
// namespace gum
gum::Set::emplace
INLINE void emplace(Args &&... args)
Definition:
set_tpl.h:669