aGrUM
0.20.2
a C++ library for (probabilistic) graphical models
pattern.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
/**
23
* @file
24
* @brief Implementation of the Pattern class.
25
*
26
* @author Lionel TORTI and Pierre-Henri WUILLEMIN(@LIP6)
27
*/
28
29
#
include
<
agrum
/
PRM
/
gspan
/
pattern
.
h
>
30
31
#
ifdef
GUM_NO_INLINE
32
#
include
<
agrum
/
PRM
/
gspan
/
pattern_inl
.
h
>
33
#
endif
// GUM_NO_INLINE
34
35
namespace
gum
{
36
namespace
prm
{
37
namespace
gspan
{
38
39
Pattern
::
Pattern
(
const
Pattern
&
source
) :
DiGraph
(),
last__
(0) {
40
GUM_CONS_CPY
(
Pattern
);
41
NodeProperty
<
NodeId
>
node_map
;
42
43
for
(
NodeId
node
= 1;
node
<=
source
.
size
(); ++
node
) {
44
node_map
.
insert
(
45
node
,
46
addNodeWithLabel
(
const_cast
<
LabelData
& >(
source
.
label
(
node
))));
47
}
48
49
for
(
const
auto
&
edge
:
source
.
code
().
codes
)
50
addArc
(
node_map
[
edge
->
i
],
51
node_map
[
edge
->
j
],
52
const_cast
<
LabelData
& >(
53
source
.
label
(
node_map
[
edge
->
i
],
node_map
[
edge
->
j
])));
54
}
55
56
bool
Pattern
::
isMinimal
() {
57
for
(
const
auto
node
:
nodes
()) {
58
for
(
const
auto
next
:
parents
(
node
)) {
59
Size
u
=
label
(
node
).
id
;
60
Size
v
=
label
(
next
).
id
;
61
EdgeCode
edge_code
(1, 2,
u
,
label
(
next
,
node
).
id
,
v
);
62
63
if
(
edge_code
< *(
code
().
codes
.
front
())) {
64
return
false
;
65
}
else
if
(
edge_code
== (*
code
().
codes
.
front
())) {
66
if
(
expandCodeIsMinimal__
(
node
,
next
)) {
return
false
; }
67
}
68
}
69
70
for
(
const
auto
next
:
children
(
node
)) {
71
Size
u
=
label
(
node
).
id
;
72
Size
v
=
label
(
next
).
id
;
73
EdgeCode
edge_code
(1, 2,
u
,
label
(
node
,
next
).
id
,
v
);
74
75
if
(
edge_code
< *(
code
().
codes
.
front
())) {
76
return
false
;
77
}
else
if
(
edge_code
== (*
code
().
codes
.
front
())) {
78
if
(
expandCodeIsMinimal__
(
node
,
next
)) {
return
false
; }
79
}
80
}
81
}
82
83
return
true
;
84
}
85
86
std
::
string
Pattern
::
toDot
(
size_t
name
)
const
{
87
std
::
stringstream
sBuff
;
88
sBuff
<<
"digraph "
<<
name
<<
" {\n"
;
89
90
for
(
const
auto
&
arc
:
arcs
()) {
91
sBuff
<<
label
(
arc
.
tail
()).
id
<<
" -> "
;
92
sBuff
<<
label
(
arc
.
head
()).
id
<<
";\n"
;
93
}
94
95
sBuff
<<
"}\n"
;
96
return
sBuff
.
str
();
97
}
98
99
bool
Pattern
::
expandCodeIsMinimal__
(
NodeId
u
,
NodeId
v
) {
100
Bijection
<
NodeId
,
NodeId
>
node_map
;
101
Pattern
p
;
102
node_map
.
insert
(
u
,
p
.
addNodeWithLabel
(
label
(
u
)));
103
node_map
.
insert
(
v
,
p
.
addNodeWithLabel
(
label
(
v
)));
104
105
try
{
106
p
.
addArc
(1, 2,
label
(
u
,
v
));
107
}
catch
(
NotFound
&) {
p
.
addArc
(1, 2,
label
(
v
,
u
)); }
108
109
for
(
const
auto
nei
:
children
(
u
))
110
if
(
nei
!=
v
)
111
if
(
rec__
(
p
,
node_map
,
u
,
nei
))
return
true
;
112
113
for
(
const
auto
nei
:
parents
(
u
))
114
if
(
nei
!=
v
)
115
if
(
rec__
(
p
,
node_map
,
u
,
nei
))
return
true
;
116
117
for
(
const
auto
nei
:
children
(
v
))
118
if
(
nei
!=
u
)
119
if
(
rec__
(
p
,
node_map
,
v
,
nei
))
return
true
;
120
121
for
(
const
auto
nei
:
parents
(
v
))
122
if
(
nei
!=
u
)
123
if
(
rec__
(
p
,
node_map
,
v
,
nei
))
return
true
;
124
125
return
false
;
126
}
127
128
bool
Pattern
::
rec__
(
Pattern
&
p
,
129
Bijection
<
NodeId
,
NodeId
>&
node_map
,
130
NodeId
u
,
131
NodeId
v
) {
132
if
(
node_map
.
existsFirst
(
v
)) {
133
if
(
node_map
.
second
(
u
) <
node_map
.
second
(
v
)) {
134
// Invalid forward edge
135
return
false
;
136
}
else
if
((
p
.
existsArc
(
node_map
.
second
(
u
),
node_map
.
second
(
v
)))
137
|| (
p
.
existsArc
(
node_map
.
second
(
v
),
node_map
.
second
(
u
)))) {
138
// Duplicate arc !
139
return
false
;
140
}
141
}
else
{
142
node_map
.
insert
(
v
,
p
.
addNodeWithLabel
(
label
(
v
)));
143
}
144
145
// Retrieving arc label data
146
LabelData
*
data
= 0;
147
148
try
{
149
data
= &(
label
(
u
,
v
));
150
}
catch
(
NotFound
&) {
data
= &(
label
(
v
,
u
)); }
151
152
// Adding arc
153
try
{
154
p
.
addArc
(
node_map
.
second
(
u
),
node_map
.
second
(
v
), *
data
);
155
}
catch
(
OperationNotAllowed
&) {
156
// Invalid neighbor
157
if
(
node_map
.
second
(
u
) <
node_map
.
second
(
v
)) {
158
p
.
remove
(
node_map
.
second
(
v
));
159
node_map
.
eraseFirst
(
v
);
160
}
161
162
return
false
;
163
}
164
165
// Check if this is minimal or if equal find another growth
166
size_t
depth
=
p
.
code
().
codes
.
size
() - 1;
167
168
if
(*(
p
.
code
().
codes
.
back
()) < *(
code
().
codes
[
depth
])) {
169
return
true
;
170
}
else
if
(*(
p
.
code
().
codes
.
back
()) == *(
code
().
codes
[
depth
])) {
171
std
::
list
<
NodeId
>
r_path
;
172
p
.
rightmostPath
(
r_path
);
173
174
for
(
const
auto
node
:
r_path
) {
175
for
(
const
auto
nei
:
children
(
node_map
.
first
(
node
)))
176
if
(
rec__
(
p
,
node_map
,
node_map
.
first
(
node
),
nei
))
return
true
;
177
178
for
(
const
auto
nei
:
parents
(
node_map
.
first
(
node
)))
179
if
(
rec__
(
p
,
node_map
,
node_map
.
first
(
node
),
nei
))
return
true
;
180
}
181
}
182
183
if
(
p
.
code
().
codes
.
back
()->
isForward
())
node_map
.
eraseFirst
(
v
);
184
185
p
.
pop_back
();
186
return
false
;
187
}
188
189
bool
Pattern
::
not_rec__
(
Pattern
&
p
,
190
Bijection
<
NodeId
,
NodeId
>&
node_map
,
191
NodeId
a_u
,
192
NodeId
a_v
) {
193
std
::
vector
<
std
::
pair
<
NodeId
,
NodeId
> >
stack
;
194
std
::
vector
<
size_t
>
rec_call
;
195
stack
.
push_back
(
std
::
make_pair
(
a_u
,
a_v
));
196
NodeId
u
= 0;
197
NodeId
v
= 0;
198
199
while
(!
stack
.
empty
()) {
200
bool
go
=
true
;
201
u
=
stack
.
back
().
first
;
202
v
=
stack
.
back
().
second
;
203
stack
.
pop_back
();
204
205
if
((
u
== 0) && (
v
== 0)) {
206
p
.
pop_back
();
207
}
else
{
208
if
(
node_map
.
existsFirst
(
v
)) {
209
if
(
node_map
.
second
(
u
) <
node_map
.
second
(
v
)) {
210
// Invalid forward edge
211
go
=
false
;
212
}
else
if
((
p
.
existsArc
(
node_map
.
second
(
u
),
node_map
.
second
(
v
)))
213
|| (
p
.
existsArc
(
node_map
.
second
(
v
),
214
node_map
.
second
(
u
)))) {
215
// Duplicate arc !
216
go
=
false
;
217
}
218
}
else
{
219
node_map
.
insert
(
v
,
p
.
addNodeWithLabel
(
label
(
v
)));
220
}
221
222
if
(
go
) {
223
// Retrieving arc label data
224
LabelData
*
data
= 0;
225
226
try
{
227
data
= &(
label
(
u
,
v
));
228
}
catch
(
NotFound
&) {
data
= &(
label
(
v
,
u
)); }
229
230
// Adding arc
231
try
{
232
p
.
addArc
(
node_map
.
second
(
u
),
node_map
.
second
(
v
), *
data
);
233
}
catch
(
OperationNotAllowed
&) {
234
// Invalid neighbor
235
if
(
node_map
.
second
(
u
) <
node_map
.
second
(
v
)) {
236
p
.
remove
(
node_map
.
second
(
v
));
237
node_map
.
eraseFirst
(
v
);
238
}
239
240
go
=
false
;
241
}
242
243
if
(
go
) {
244
// Check if this is minimal or if equal find another growth
245
size_t
depth
=
p
.
code
().
codes
.
size
() - 1;
246
247
if
(*(
p
.
code
().
codes
.
back
()) < *(
code
().
codes
[
depth
])) {
248
return
true
;
249
}
else
if
(*(
p
.
code
().
codes
.
back
()) == *(
code
().
codes
[
depth
])) {
250
std
::
list
<
NodeId
>
r_path
;
251
p
.
rightmostPath
(
r_path
);
252
stack
.
push_back
(
std
::
make_pair
((
NodeId
)0, (
NodeId
)0));
253
254
for
(
const
auto
node
:
r_path
) {
255
for
(
const
auto
nei
:
children
(
node
)) {
256
stack
.
push_back
(
std
::
make_pair
(
node_map
.
first
(
node
),
nei
));
257
++(
rec_call
.
back
());
258
}
259
260
for
(
const
auto
nei
:
parents
(
node
)) {
261
stack
.
push_back
(
std
::
make_pair
(
node_map
.
first
(
node
),
nei
));
262
++(
rec_call
.
back
());
263
}
264
}
265
}
266
267
if
(
p
.
code
().
codes
.
back
()->
isForward
())
node_map
.
eraseFirst
(
v
);
268
}
269
}
270
}
271
}
272
273
return
false
;
274
}
275
276
}
/* namespace gspan */
277
}
/* namespace prm */
278
}
/* namespace gum */
gum::Set::emplace
INLINE void emplace(Args &&... args)
Definition:
set_tpl.h:669
gum::prm::ParamScopeData::ParamScopeData
ParamScopeData(const std::string &s, const PRMReferenceSlot< GUM_SCALAR > &ref, Idx d)
Definition:
PRMClass_tpl.h:1101
gum::prm::gspan::operator<<
INLINE std::ostream & operator<<(std::ostream &out, const EdgeData< GUM_SCALAR > &data)
Print a EdgeData<GUM_SCALAR> in out.
Definition:
interfaceGraph_tpl.h:393