aGrUM
0.20.3
a C++ library for (probabilistic) graphical models
mixedGraph.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 Base classes for undirected graphs
24
*
25
* @author Pierre-Henri WUILLEMIN(@LIP6) & Christophe GONZALES(@AMU)
26
*
27
*/
28
#
include
<
agrum
/
tools
/
graphs
/
mixedGraph
.
h
>
29
30
#
ifdef
GUM_NO_INLINE
31
#
include
<
agrum
/
tools
/
graphs
/
mixedGraph_inl
.
h
>
32
#
endif
// GUM_NOINLINE
33
34
namespace
gum
{
35
36
MixedGraph
::
MixedGraph
(
Size
nodes_size
,
37
bool
nodes_resize_policy
,
38
Size
arcs_size
,
39
bool
arcs_resize_policy
,
40
Size
edges_size
,
41
bool
edges_resize_policy
) :
42
// Note that we need to initialize the NodeGraphPart by ourselves
43
// because
44
// it is a virtual inherited class (see C++ FAQ Lite #25.12 for details)
45
NodeGraphPart
(
nodes_size
,
nodes_resize_policy
),
46
UndiGraph
(
edges_size
,
edges_resize_policy
),
47
DiGraph
(
arcs_size
,
arcs_resize_policy
) {
// for debugging purposes
48
GUM_CONSTRUCTOR
(
MixedGraph
);
49
}
50
51
MixedGraph
::
MixedGraph
(
const
UndiGraph
&
g
) :
NodeGraphPart
(
g
),
UndiGraph
(
g
),
DiGraph
() {
52
GUM_CONSTRUCTOR
(
MixedGraph
);
53
}
54
55
MixedGraph
::
MixedGraph
(
const
DiGraph
&
g
) :
NodeGraphPart
(
g
),
UndiGraph
(),
DiGraph
(
g
) {
56
GUM_CONSTRUCTOR
(
MixedGraph
);
57
}
58
59
MixedGraph
::
MixedGraph
(
const
MixedGraph
&
g
) :
60
NodeGraphPart
(
g
),
UndiGraph
(
g
),
DiGraph
(
g
) {
// for debugging purposes
61
GUM_CONS_CPY
(
MixedGraph
);
62
}
63
64
MixedGraph
::~
MixedGraph
() {
// for debugging purposes
65
GUM_DESTRUCTOR
(
MixedGraph
);
66
}
67
68
std
::
string
MixedGraph
::
toString
()
const
{
69
std
::
string
s
=
NodeGraphPart
::
toString
();
70
s
+=
" , "
;
71
s
+=
ArcGraphPart
::
toString
();
72
s
+=
" , "
;
73
s
+=
EdgeGraphPart
::
toString
();
74
return
s
;
75
}
76
77
std
::
vector
<
NodeId
>
MixedGraph
::
mixedOrientedPath
(
NodeId
n1
,
NodeId
n2
)
const
{
78
std
::
vector
<
NodeId
>
v
;
79
// not recursive version => use a FIFO for simulating the recursion
80
List
<
NodeId
>
node_fifo
;
81
node_fifo
.
pushBack
(
n2
);
82
83
// mark[node] = successor if visited, else mark[node] does not exist
84
NodeProperty
<
NodeId
>
mark
;
85
mark
.
insert
(
n2
,
n2
);
86
87
NodeId
current
;
88
while
(!
node_fifo
.
empty
()) {
89
current
=
node_fifo
.
front
();
90
node_fifo
.
popFront
();
91
92
// check the neighbours
93
for
(
const
auto
new_one
:
neighbours
(
current
)) {
94
if
(
mark
.
exists
(
new_one
))
// if the node has already been visited
95
continue
;
// do not check it again
96
97
mark
.
insert
(
new_one
,
current
);
98
99
if
(
new_one
==
n1
) {
100
for
(
current
=
n1
;
current
!=
n2
;
current
=
mark
[
current
])
101
v
.
push_back
(
current
);
102
v
.
push_back
(
n2
);
103
return
v
;
104
}
105
106
node_fifo
.
pushBack
(
new_one
);
107
}
108
109
// check the parents
110
for
(
const
auto
new_one
:
parents
(
current
)) {
111
if
(
mark
.
exists
(
new_one
))
// if this node is already marked, do not
112
continue
;
// check it again
113
114
mark
.
insert
(
new_one
,
current
);
115
116
if
(
new_one
==
n1
) {
117
for
(
current
=
n1
;
current
!=
n2
;
current
=
mark
[
current
])
118
v
.
push_back
(
current
);
119
v
.
push_back
(
n2
);
120
return
v
;
121
}
122
123
node_fifo
.
pushBack
(
new_one
);
124
}
125
}
126
127
return
v
;
128
}
129
130
std
::
vector
<
NodeId
>
MixedGraph
::
mixedUnorientedPath
(
NodeId
n1
,
NodeId
n2
)
const
{
131
std
::
vector
<
NodeId
>
v
;
132
// not recursive version => use a FIFO for simulating the recursion
133
List
<
NodeId
>
node_fifo
;
134
node_fifo
.
pushBack
(
n2
);
135
136
// mark[node] = successor if visited, else mark[node] does not exist
137
NodeProperty
<
NodeId
>
mark
;
138
mark
.
insert
(
n2
,
n2
);
139
140
NodeId
current
;
141
142
while
(!
node_fifo
.
empty
()) {
143
current
=
node_fifo
.
front
();
144
node_fifo
.
popFront
();
145
146
// check the neighbours
147
for
(
const
auto
new_one
:
neighbours
(
current
)) {
148
if
(
mark
.
exists
(
new_one
))
// if the node has already been visited
149
continue
;
// do not check it again
150
151
mark
.
insert
(
new_one
,
current
);
152
153
if
(
new_one
==
n1
) {
154
for
(
current
=
n1
;
current
!=
n2
;
current
=
mark
[
current
])
155
v
.
push_back
(
current
);
156
v
.
push_back
(
n2
);
157
return
v
;
158
}
159
160
node_fifo
.
pushBack
(
new_one
);
161
}
162
163
// check the parents
164
for
(
const
auto
new_one
:
parents
(
current
)) {
165
if
(
mark
.
exists
(
new_one
))
// the node has already been visited
166
continue
;
167
168
mark
.
insert
(
new_one
,
current
);
169
if
(
new_one
==
n1
) {
170
for
(
current
=
n1
;
current
!=
n2
;
current
=
mark
[
current
])
171
v
.
push_back
(
current
);
172
v
.
push_back
(
n2
);
173
return
v
;
174
}
175
node_fifo
.
pushBack
(
new_one
);
176
}
177
178
// check the children
179
for
(
const
auto
new_one
:
children
(
current
)) {
180
if
(
mark
.
exists
(
new_one
))
// the node has already been visited
181
continue
;
182
183
mark
.
insert
(
new_one
,
current
);
184
185
if
(
new_one
==
n1
) {
186
for
(
current
=
n1
;
current
!=
n2
;
current
=
mark
[
current
])
187
v
.
push_back
(
current
);
188
v
.
push_back
(
n2
);
189
return
v
;
190
}
191
192
node_fifo
.
pushBack
(
new_one
);
193
}
194
}
195
196
return
v
;
197
}
198
199
std
::
string
MixedGraph
::
toDot
()
const
{
200
std
::
stringstream
output
;
201
std
::
stringstream
nodeStream
;
202
std
::
stringstream
edgeStream
;
203
List
<
NodeId
>
treatedNodes
;
204
output
<<
"digraph \""
205
<<
"no_name\" {"
<<
std
::
endl
;
206
nodeStream
<<
"node [shape = ellipse];"
<<
std
::
endl
;
207
std
::
string
tab
=
" "
;
208
209
for
(
const
auto
node
:
nodes
()) {
210
nodeStream
<<
tab
<<
node
<<
";"
;
211
212
for
(
const
auto
nei
:
neighbours
(
node
))
213
if
(!
treatedNodes
.
exists
(
nei
))
214
edgeStream
<<
tab
<<
node
<<
" -> "
<<
nei
<<
" [dir=none];"
<<
std
::
endl
;
215
216
for
(
const
auto
chi
:
children
(
node
))
217
edgeStream
<<
tab
<<
node
<<
" -> "
<<
chi
<<
";"
<<
std
::
endl
;
218
219
treatedNodes
.
insert
(
node
);
220
}
221
222
output
<<
nodeStream
.
str
() <<
std
::
endl
<<
edgeStream
.
str
() <<
std
::
endl
<<
"}"
<<
std
::
endl
;
223
224
return
output
.
str
();
225
}
226
227
NodeSet
MixedGraph
::
adjacents
(
const
NodeId
id
)
const
{
228
return
neighbours
(
id
) +
parents
(
id
) +
children
(
id
);
229
}
230
231
/// for friendly displaying the content of directed graphs
232
std
::
ostream
&
operator
<<(
std
::
ostream
&
stream
,
const
MixedGraph
&
g
) {
233
stream << g.toString();
234
return
stream;
235
}
236
237
238
}
/* namespace gum */
gum::Set::emplace
INLINE void emplace(Args &&... args)
Definition:
set_tpl.h:643
gum::operator<<
std::ostream & operator<<(std::ostream &aStream, const Instantiation &i)
Print information of the instantiation in the stream.
Definition:
instantiation.cpp:247