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