aGrUM
0.20.3
a C++ library for (probabilistic) graphical models
diGraph.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 oriented graphs
24
*
25
* @author Pierre-Henri WUILLEMIN(@LIP6) & Christophe GONZALES(@AMU)
26
*
27
*/
28
#
include
<
agrum
/
tools
/
graphs
/
diGraph
.
h
>
29
30
#
ifdef
GUM_NO_INLINE
31
#
include
<
agrum
/
tools
/
graphs
/
diGraph_inl
.
h
>
32
#
endif
// GUM_NOINLINE
33
34
namespace
gum
{
35
36
DiGraph
::
DiGraph
(
Size
nodes_size
,
37
bool
nodes_resize_policy
,
38
Size
arcs_size
,
39
bool
arcs_resize_policy
) :
40
NodeGraphPart
(
nodes_size
,
nodes_resize_policy
),
41
ArcGraphPart
(
arcs_size
,
arcs_resize_policy
),
_mutableTopologicalOrder_
(
nullptr
) {
42
GUM_CONSTRUCTOR
(
DiGraph
);
43
}
44
45
DiGraph
::
DiGraph
(
const
DiGraph
&
g
) :
46
NodeGraphPart
(
g
),
ArcGraphPart
(
g
),
_mutableTopologicalOrder_
(
nullptr
) {
47
GUM_CONS_CPY
(
DiGraph
);
48
if
(
g
.
_mutableTopologicalOrder_
!=
nullptr
) {
49
_mutableTopologicalOrder_
=
new
Sequence
<
NodeId
>(*(
g
.
_mutableTopologicalOrder_
));
50
}
51
}
52
53
DiGraph
::~
DiGraph
() {
54
GUM_DESTRUCTOR
(
DiGraph
);
55
if
(
_mutableTopologicalOrder_
!=
nullptr
) {
delete
_mutableTopologicalOrder_
; }
56
}
57
58
std
::
string
DiGraph
::
toString
()
const
{
59
std
::
string
s
=
NodeGraphPart
::
toString
();
60
s
+=
" , "
;
61
s
+=
ArcGraphPart
::
toString
();
62
return
s
;
63
}
64
65
std
::
string
DiGraph
::
toDot
()
const
{
66
std
::
stringstream
strBuff
;
67
std
::
string
tab
=
" "
;
68
strBuff
<<
"digraph {"
<<
std
::
endl
;
69
70
for
(
const
auto
node
:
nodes
())
71
strBuff
<<
tab
<<
node
<<
";"
<<
std
::
endl
;
72
73
strBuff
<<
std
::
endl
;
74
75
for
(
const
auto
&
arc
:
arcs
())
76
strBuff
<<
tab
<<
arc
.
tail
() <<
" -> "
<<
arc
.
head
() <<
";"
<<
std
::
endl
;
77
78
strBuff
<<
"}"
<<
std
::
endl
<<
std
::
endl
;
79
return
strBuff
.
str
();
80
}
81
82
/// for friendly displaying the content of directed graphs
83
std
::
ostream
&
operator
<<(
std
::
ostream
&
stream
,
const
DiGraph
&
g
) {
84
stream << g.toString();
85
return
stream;
86
}
87
88
const
Sequence
<
NodeId
>&
DiGraph
::
topologicalOrder
(
bool
clear
)
const
{
89
if
(
clear
|| (
_mutableTopologicalOrder_
==
nullptr
)) {
// we have to call topologicalOrder_
90
if
(
_mutableTopologicalOrder_
==
nullptr
) {
91
_mutableTopologicalOrder_
=
new
Sequence
<
NodeId
>();
92
}
else
{
93
// clear is True
94
_mutableTopologicalOrder_
->
clear
();
95
}
96
97
_topologicalOrder_
();
98
}
99
100
return
*
_mutableTopologicalOrder_
;
101
}
102
103
void
DiGraph
::
_topologicalOrder_
()
const
{
104
auto
dag
= *
this
;
105
auto
roots
=
std
::
vector
<
NodeId
>();
106
107
for
(
const
auto
node
:
dag
.
nodes
()) {
108
if
(
dag
.
parents
(
node
).
empty
()) {
roots
.
push_back
(
node
); }
109
}
110
111
while
(
roots
.
size
()) {
112
if
(
_mutableTopologicalOrder_
->
exists
(
roots
.
back
())) {
113
GUM_ERROR
(
InvalidDirectedCycle
,
"cycles prevent the creation of a topological ordering."
)
114
}
115
_mutableTopologicalOrder_
->
insert
(
roots
.
back
());
116
roots
.
pop_back
();
117
118
while
(
dag
.
children
(
_mutableTopologicalOrder_
->
back
()).
size
()) {
119
auto
back
=
_mutableTopologicalOrder_
->
back
();
120
auto
child
= *(
dag
.
children
(
back
).
begin
());
121
dag
.
eraseArc
(
Arc
(
back
,
child
));
122
123
if
(
dag
.
parents
(
child
).
empty
()) {
roots
.
push_back
(
child
); }
124
}
125
}
126
127
GUM_ASSERT
(
dag
.
sizeArcs
() == (
gum
::
Size
)(0));
128
GUM_ASSERT
(
_mutableTopologicalOrder_
->
size
() ==
dag
.
size
());
129
}
130
131
bool
DiGraph
::
hasDirectedPath
(
const
NodeId
from
,
const
NodeId
to
) {
132
if
(!
exists
(
from
))
return
false
;
133
134
// not recursive version => use a FIFO for simulating the recursion
135
List
<
NodeId
>
nodeFIFO
;
136
nodeFIFO
.
pushBack
(
from
);
137
138
NodeSet
marked
;
139
marked
.
insert
(
from
);
140
141
NodeId
new_one
;
142
143
while
(!
nodeFIFO
.
empty
()) {
144
new_one
=
nodeFIFO
.
front
();
145
// std::cout<<new_one<<std::endl;
146
nodeFIFO
.
popFront
();
147
148
for
(
const
auto
chi
:
children
(
new_one
)) {
149
if
(
chi
==
to
)
return
true
;
150
151
if
(!
marked
.
contains
(
chi
)) {
152
nodeFIFO
.
pushBack
(
chi
);
153
marked
.
insert
(
chi
);
154
}
155
}
156
}
157
158
return
false
;
159
}
160
161
}
/* 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