aGrUM
0.20.3
a C++ library for (probabilistic) graphical models
arcGraphPart.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 classes for directed edge sets
24
*
25
* @author Pierre-Henri WUILLEMIN(@LIP6) & Christophe GONZALES(@AMU)
26
*
27
*/
28
#
include
<
agrum
/
tools
/
graphs
/
parts
/
arcGraphPart
.
h
>
29
30
#
ifdef
GUM_NO_INLINE
31
#
include
<
agrum
/
tools
/
graphs
/
parts
/
arcGraphPart_inl
.
h
>
32
#
endif
// GUM_NOINLINE
33
#
include
"agrum/tools/graphs/graphElements.h"
34
35
namespace
gum
{
36
37
///////////////////// ArcGraphPart
38
ArcGraphPart
::
ArcGraphPart
(
Size
arcs_size
,
bool
arcs_resize_policy
) :
39
_arcs_
(
arcs_size
,
arcs_resize_policy
) {
40
GUM_CONSTRUCTOR
(
ArcGraphPart
);
41
}
42
43
ArcGraphPart
::
ArcGraphPart
(
const
ArcGraphPart
&
s
) :
_arcs_
(
s
.
_arcs_
) {
44
GUM_CONS_CPY
(
ArcGraphPart
);
45
46
// copy the sets of parents
47
const
NodeProperty
<
NodeSet
* >&
pars
=
s
.
_parents_
;
48
_parents_
.
resize
(
pars
.
capacity
());
49
50
for
(
const
auto
&
elt
:
pars
) {
51
NodeSet
*
newpar
=
new
NodeSet
(*
elt
.
second
);
52
_parents_
.
insert
(
elt
.
first
,
newpar
);
53
}
54
55
// copy the sets of children
56
const
NodeProperty
<
NodeSet
* >&
children
=
s
.
_children_
;
57
_children_
.
resize
(
children
.
capacity
());
58
59
for
(
const
auto
&
elt
:
children
) {
60
NodeSet
*
newchildren
=
new
NodeSet
(*
elt
.
second
);
61
_children_
.
insert
(
elt
.
first
,
newchildren
);
62
}
63
64
// send signals to indicate that there are new arcs
65
if
(
onArcAdded
.
hasListener
()) {
66
for
(
const
auto
&
arc
:
_arcs_
) {
67
GUM_EMIT2
(
onArcAdded
,
arc
.
tail
(),
arc
.
head
());
68
}
69
}
70
}
71
72
ArcGraphPart
::~
ArcGraphPart
() {
73
GUM_DESTRUCTOR
(
ArcGraphPart
);
74
// be sure to deallocate all the parents and children sets
75
clearArcs
();
76
}
77
78
void
ArcGraphPart
::
clearArcs
() {
79
for
(
const
auto
&
elt
:
_parents_
)
80
delete
elt
.
second
;
81
82
_parents_
.
clear
();
83
84
for
(
const
auto
&
elt
:
_children_
)
85
delete
elt
.
second
;
86
87
_children_
.
clear
();
88
89
// we need this copy only if at least one onArcDeleted listener exists
90
if
(
onArcDeleted
.
hasListener
()) {
91
ArcSet
tmp
=
_arcs_
;
92
_arcs_
.
clear
();
93
94
for
(
const
auto
&
arc
:
tmp
)
95
GUM_EMIT2
(
onArcDeleted
,
arc
.
tail
(),
arc
.
head
());
96
}
else
{
97
_arcs_
.
clear
();
98
}
99
}
100
101
ArcGraphPart
&
ArcGraphPart
::
operator
=(
const
ArcGraphPart
&
s
) {
102
// avoid self assignment
103
if
(
this
!= &
s
) {
104
// copy the arcs
105
clearArcs
();
106
_arcs_
=
s
.
_arcs_
;
107
108
// copy the sets of parents
109
_parents_
.
resize
(
s
.
_parents_
.
capacity
());
110
111
for
(
const
auto
&
elt
:
s
.
_parents_
) {
112
NodeSet
*
newpar
=
new
NodeSet
(*
elt
.
second
);
113
_parents_
.
insert
(
elt
.
first
,
newpar
);
114
}
115
116
// copy the sets of children
117
_children_
.
resize
(
s
.
_children_
.
capacity
());
118
119
for
(
const
auto
&
elt
:
s
.
_children_
) {
120
NodeSet
*
newchildren
=
new
NodeSet
(*
elt
.
second
);
121
_children_
.
insert
(
elt
.
first
,
newchildren
);
122
}
123
124
if
(
onArcAdded
.
hasListener
()) {
125
for
(
const
auto
&
arc
:
_arcs_
) {
126
GUM_EMIT2
(
onArcAdded
,
arc
.
tail
(),
arc
.
head
());
127
}
128
}
129
}
130
131
return
*
this
;
132
}
133
134
std
::
string
ArcGraphPart
::
toString
()
const
{
135
std
::
stringstream
s
;
136
bool
first
=
true
;
137
s
<<
"{"
;
138
139
for
(
const
auto
&
arc
:
_arcs_
) {
140
if
(
first
) {
141
first
=
false
;
142
}
else
{
143
s
<<
","
;
144
}
145
146
s
<<
arc
;
147
}
148
149
s
<<
"}"
;
150
151
return
s
.
str
();
152
}
153
154
NodeSet
ArcGraphPart
::
descendants
(
NodeId
id
)
const
{
155
NodeSet
res
;
156
NodeSet
tmp
;
157
for
(
auto
next
:
children
(
id
))
158
tmp
.
insert
(
next
);
159
160
while
(!
tmp
.
empty
()) {
161
auto
current
= *(
tmp
.
begin
());
162
tmp
.
erase
(
current
);
163
res
.
insert
(
current
);
164
for
(
auto
next
:
children
(
current
)) {
165
if
(!
tmp
.
contains
(
next
) && !
res
.
contains
(
next
)) {
tmp
.
insert
(
next
); }
166
}
167
}
168
return
res
;
169
}
170
171
172
NodeSet
ArcGraphPart
::
ancestors
(
NodeId
id
)
const
{
173
NodeSet
res
;
174
NodeSet
tmp
;
175
for
(
auto
next
:
parents
(
id
))
176
tmp
.
insert
(
next
);
177
178
while
(!
tmp
.
empty
()) {
179
auto
current
= *(
tmp
.
begin
());
180
tmp
.
erase
(
current
);
181
res
.
insert
(
current
);
182
for
(
auto
next
:
parents
(
current
)) {
183
if
(!
tmp
.
contains
(
next
) && !
res
.
contains
(
next
)) {
tmp
.
insert
(
next
); }
184
}
185
}
186
return
res
;
187
}
188
189
190
std
::
vector
<
NodeId
>
ArcGraphPart
::
directedPath
(
NodeId
n1
,
NodeId
n2
)
const
{
191
// not recursive version => use a FIFO for simulating the recursion
192
List
<
NodeId
>
nodeFIFO
;
193
nodeFIFO
.
pushBack
(
n2
);
194
195
// mark[node] = successor if visited, else mark[node] does not exist
196
NodeProperty
<
NodeId
>
mark
;
197
mark
.
insert
(
n2
,
n2
);
198
199
NodeId
current
;
200
201
while
(!
nodeFIFO
.
empty
()) {
202
current
=
nodeFIFO
.
front
();
203
nodeFIFO
.
popFront
();
204
205
// check the parents
206
207
for
(
const
auto
new_one
:
parents
(
current
)) {
208
if
(
mark
.
exists
(
new_one
))
// if this node is already marked, do not
209
continue
;
// check it again
210
211
mark
.
insert
(
new_one
,
current
);
212
213
if
(
new_one
==
n1
) {
214
std
::
vector
<
NodeId
>
v
;
215
216
for
(
current
=
n1
;
current
!=
n2
;
current
=
mark
[
current
])
217
v
.
push_back
(
current
);
218
219
v
.
push_back
(
n2
);
220
221
return
v
;
222
}
223
224
nodeFIFO
.
pushBack
(
new_one
);
225
}
226
}
227
228
GUM_ERROR
(
NotFound
,
"no path found"
)
229
}
230
231
std
::
vector
<
NodeId
>
ArcGraphPart
::
directedUnorientedPath
(
NodeId
n1
,
NodeId
n2
)
const
{
232
// not recursive version => use a FIFO for simulating the recursion
233
List
<
NodeId
>
nodeFIFO
;
234
nodeFIFO
.
pushBack
(
n2
);
235
236
// mark[node] = successor if visited, else mark[node] does not exist
237
NodeProperty
<
NodeId
>
mark
;
238
mark
.
insert
(
n2
,
n2
);
239
240
NodeId
current
;
241
242
while
(!
nodeFIFO
.
empty
()) {
243
current
=
nodeFIFO
.
front
();
244
nodeFIFO
.
popFront
();
245
246
// check the parents
247
for
(
const
auto
new_one
:
parents
(
current
)) {
248
if
(
mark
.
exists
(
new_one
))
// the node has already been visited
249
continue
;
250
251
mark
.
insert
(
new_one
,
current
);
252
253
if
(
new_one
==
n1
) {
254
std
::
vector
<
NodeId
>
v
;
255
256
for
(
current
=
n1
;
current
!=
n2
;
current
=
mark
[
current
])
257
v
.
push_back
(
current
);
258
259
v
.
push_back
(
n2
);
260
261
return
v
;
262
}
263
264
nodeFIFO
.
pushBack
(
new_one
);
265
}
266
267
// check the children
268
for
(
const
auto
new_one
:
children
(
current
)) {
269
if
(
mark
.
exists
(
new_one
))
// the node has already been visited
270
continue
;
271
272
mark
.
insert
(
new_one
,
current
);
273
274
if
(
new_one
==
n1
) {
275
std
::
vector
<
NodeId
>
v
;
276
277
for
(
current
=
n1
;
current
!=
n2
;
current
=
mark
[
current
])
278
v
.
push_back
(
current
);
279
280
v
.
push_back
(
n2
);
281
282
return
v
;
283
}
284
285
nodeFIFO
.
pushBack
(
new_one
);
286
}
287
}
288
289
GUM_ERROR
(
NotFound
,
"no path found"
)
290
}
291
292
std
::
ostream
&
operator
<<(
std
::
ostream
&
stream
,
const
ArcGraphPart
&
set
) {
293
stream << set.toString();
294
return
stream;
295
}
296
297
}
/* 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