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