aGrUM
0.20.3
a C++ library for (probabilistic) graphical models
DFSTree_tpl.h
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 Inline implementation of the DFSTree class.
25
*
26
* @author Lionel TORTI and Pierre-Henri WUILLEMIN(@LIP6)
27
*/
28
29
#
include
<
agrum
/
PRM
/
gspan
/
DFSTree
.
h
>
30
#
include
<
agrum
/
PRM
/
gspan
/
edgeGrowth
.
h
>
31
32
namespace
gum
{
33
namespace
prm
{
34
namespace
gspan
{
35
template
<
typename
GUM_SCALAR
>
36
DFSTree
<
GUM_SCALAR
>::~
DFSTree
() {
37
GUM_DESTRUCTOR
(
DFSTree
);
38
39
for
(
const
auto
&
elt
:
_data_
) {
40
delete
elt
.
first
;
41
delete
elt
.
second
;
42
}
43
44
delete
_strategy_
;
45
}
46
47
template
<
typename
GUM_SCALAR
>
48
void
DFSTree
<
GUM_SCALAR
>::
addRoot
(
LabelData
&
label
) {
49
HashTable
<
Pattern
*,
std
::
pair
<
Idx
,
Idx
> >
roots
;
50
HashTable
<
Pattern
*,
Sequence
<
EdgeData
<
GUM_SCALAR
>* >* >
roots_edges
;
51
52
for
(
const
auto
&
edge
:
_graph_
->
edges
(&
label
)) {
53
bool
u_first
= (
edge
->
l_u
->
id
<
edge
->
l_v
->
id
);
54
Idx
u_idx
= (
u_first
) ?
edge
->
l_u
->
id
:
edge
->
l_v
->
id
;
55
Idx
v_idx
= (!
u_first
) ?
edge
->
l_u
->
id
:
edge
->
l_v
->
id
;
56
57
bool
found
=
false
;
58
59
for
(
const
auto
&
elt
:
roots
)
60
if
((
elt
.
second
.
first
==
u_idx
) && (
elt
.
second
.
second
==
v_idx
)) {
61
roots_edges
[
elt
.
first
]->
insert
(
edge
);
62
found
=
true
;
63
break
;
64
}
65
66
/// Then we create a new pattern
67
if
(!
found
) {
68
Pattern
*
p
=
new
Pattern
();
69
roots
.
insert
(
p
,
std
::
make_pair
(
u_idx
,
v_idx
));
70
roots_edges
.
insert
(
p
,
new
Sequence
<
EdgeData
<
GUM_SCALAR
>* >());
71
roots_edges
[
p
]->
insert
(
edge
);
72
DFSTree
<
GUM_SCALAR
>::
PatternData
*
data
=
new
DFSTree
<
GUM_SCALAR
>::
PatternData
(
p
);
73
NodeId
u
=
p
->
addNodeWithLabel
((
u_first
) ? *
edge
->
l_u
: *
edge
->
l_v
);
74
NodeId
v
=
p
->
addNodeWithLabel
((!
u_first
) ? *
edge
->
l_u
: *
edge
->
l_v
);
75
p
->
addArc
(
u
,
v
,
label
);
76
_node_map_
.
insert
(
DiGraph
::
addNode
(),
p
);
77
_data_
.
insert
(
p
,
data
);
78
_roots_
.
push_back
(
_node_map_
.
first
(
p
));
79
}
80
}
81
82
// This is used to compute the max independent set of p->max_indep_set
83
for
(
const
auto
&
elt
:
roots_edges
) {
84
_initialiaze_root_
(
elt
.
first
, *
elt
.
second
);
85
strategy
().
accept_root
(
elt
.
first
);
86
delete
elt
.
second
;
87
}
88
}
89
90
template
<
typename
GUM_SCALAR
>
91
void
92
DFSTree
<
GUM_SCALAR
>::
_initialiaze_root_
(
Pattern
*
p
,
93
Sequence
<
EdgeData
<
GUM_SCALAR
>* >&
edge_seq
) {
94
DFSTree
<
GUM_SCALAR
>::
PatternData
*
data
=
_data_
[
p
];
95
std
::
vector
<
NodeId
>
degree_list
;
96
97
for
(
auto
iter
=
edge_seq
.
begin
();
iter
!=
edge_seq
.
end
(); ++
iter
) {
98
const
auto
&
edge
= *
iter
;
99
Sequence
<
PRMInstance
<
GUM_SCALAR
>* >*
seq
100
=
new
Sequence
<
PRMInstance
<
GUM_SCALAR
>* >();
101
102
// Creating the multiset of instances matching p
103
bool
u_first
= (
edge
->
l_u
->
id
<
edge
->
l_v
->
id
);
104
seq
->
insert
((
u_first
) ?
edge
->
u
:
edge
->
v
);
105
seq
->
insert
((!
u_first
) ?
edge
->
u
:
edge
->
v
);
106
107
NodeId
an_id
=
data
->
iso_graph
.
addNode
();
108
data
->
iso_map
.
insert
(
an_id
,
seq
);
109
degree_list
.
push_back
(
an_id
);
110
111
// Adding edges between two isomorphisms of p sharing at least one
112
// instance
113
for
(
const
auto
&
elt
:
data
->
iso_map
)
114
if
(
elt
.
first
!=
an_id
)
115
for
(
auto
iter
=
elt
.
second
->
begin
();
iter
!=
elt
.
second
->
end
(); ++
iter
)
116
if
(
seq
->
exists
(*
iter
)) {
117
data
->
iso_graph
.
addEdge
(
an_id
,
elt
.
first
);
118
break
;
119
}
120
}
121
122
// Computing p->max_indep_set using a greedy algorithm
123
DFSTree
<
GUM_SCALAR
>::
NeighborDegreeSort
my_operator
(
data
->
iso_graph
);
124
std
::
sort
(
degree_list
.
begin
(),
degree_list
.
end
(),
my_operator
);
125
Set
<
NodeId
>
removed
;
126
127
for
(
const
auto
node
:
degree_list
) {
128
if
(!
removed
.
exists
(
node
)) {
129
removed
.
insert
(
node
);
130
131
for
(
const
auto
neighbor
:
data
->
iso_graph
.
neighbours
(
node
))
132
removed
.
insert
(
neighbor
);
133
134
data
->
max_indep_set
.
insert
(
node
);
135
}
136
}
137
}
138
139
template
<
typename
GUM_SCALAR
>
140
bool
DFSTree
<
GUM_SCALAR
>::
_is_new_seq_
(
141
Sequence
<
PRMInstance
<
GUM_SCALAR
>* >&
seq
,
142
NodeProperty
<
Sequence
<
PRMInstance
<
GUM_SCALAR
>* >* >&
iso_map
) {
143
for
(
const
auto
&
elt
:
iso_map
) {
144
bool
found
=
false
;
145
146
for
(
const
auto
&
inst
:
seq
)
147
if
(!(
elt
.
second
->
exists
(
inst
))) {
148
found
=
true
;
149
break
;
150
}
151
152
if
(!
found
) {
return
false
; }
153
}
154
155
return
true
;
156
}
157
158
template
<
typename
GUM_SCALAR
>
159
void
DFSTree
<
GUM_SCALAR
>::
_addChild_
(
Pattern
&
p
,
160
Pattern
*
child
,
161
EdgeGrowth
<
GUM_SCALAR
>&
edge_growth
) {
162
// Adding child to the tree
163
NodeId
node
=
DiGraph
::
addNode
();
164
_node_map_
.
insert
(
node
,
child
);
165
// Adding child in p's children list
166
std
::
list
<
NodeId
>&
children
=
_data_
[&
p
]->
children
;
167
168
if
(
children
.
empty
()) {
169
children
.
push_back
(
node
);
170
}
else
{
171
size_t
size
=
children
.
size
();
172
173
for
(
std
::
list
<
NodeId
>::
iterator
iter
=
children
.
begin
();
iter
!=
children
.
end
();
174
++
iter
) {
175
if
(
child
->
code
() <
pattern
(*
iter
).
code
()) {
176
children
.
insert
(
iter
,
node
);
177
break
;
178
}
179
}
180
181
if
(
size
==
children
.
size
()) {
children
.
push_back
(
node
); }
182
}
183
}
184
185
template
<
typename
GUM_SCALAR
>
186
void
DFSTree
<
GUM_SCALAR
>::
_checkGrowth_
(
Pattern
&
p
,
187
Pattern
*
child
,
188
EdgeGrowth
<
GUM_SCALAR
>&
edge_growth
) {
189
NodeId
v
=
edge_growth
.
v
;
190
191
// First we check if the edge is legal
192
if
(
v
== 0) {
v
=
child
->
addNodeWithLabel
(*(
edge_growth
.
l_v
)); }
193
194
child
->
addArc
(
edge_growth
.
u
,
v
, *(
edge_growth
.
edge
));
195
// Neighborhood restriction is checked by the Pattern class
196
EdgeCode
&
edge
=
child
->
edgeCode
(
edge_growth
.
u
,
v
);
197
198
// Then we check if the edge we added is valid
199
if
(
edge
< *(
child
->
code
().
codes
.
front
())) {
200
GUM_ERROR
(
OperationNotAllowed
,
201
"added edge code is lesser than the first "
202
"one in the pattern's DFSCode"
);
203
}
204
205
if
(
edge
.
isBackward
()) {
206
typedef
std
::
vector
<
EdgeCode
* >::
iterator
EdgeIter
;
207
208
for
(
EdgeIter
iter
=
child
->
code
().
codes
.
begin
(); (
iter
+ 1) !=
child
->
code
().
codes
.
end
();
209
++
iter
) {
210
if
((((**
iter
).
i
==
v
) || ((**
iter
).
j
==
v
)) &&
edge
< (**
iter
)) {
211
GUM_ERROR
(
OperationNotAllowed
,
212
"added backward edge is lesser than an existing edge on v"
);
213
}
214
}
215
}
216
217
// Finally we check if child is minimal.
218
if
(!
child
->
isMinimal
()) {
219
GUM_ERROR
(
OperationNotAllowed
,
"the DFSCode for this growth is not minimal"
)
220
}
221
}
222
223
template
<
typename
GUM_SCALAR
>
224
Pattern
&
DFSTree
<
GUM_SCALAR
>::
growPattern
(
Pattern
&
p
,
225
EdgeGrowth
<
GUM_SCALAR
>&
edge_growth
,
226
Size
min_freq
) {
227
Pattern
*
child
=
new
Pattern
(
p
);
228
229
try
{
230
_checkGrowth_
(
p
,
child
,
edge_growth
);
231
}
catch
(
OperationNotAllowed
&) {
232
delete
child
;
233
throw
;
234
}
235
236
// Now we need to build the pattern data about child
237
DFSTree
<
GUM_SCALAR
>::
PatternData
*
data
=
new
DFSTree
<
GUM_SCALAR
>::
PatternData
(
child
);
238
std
::
vector
<
NodeId
>
degree_list
;
239
NodeProperty
<
Sequence
<
PRMInstance
<
GUM_SCALAR
>* >* >&
p_iso_map
=
_data_
[&
p
]->
iso_map
;
240
typename
NodeProperty
<
std
::
pair
<
PRMInstance
<
GUM_SCALAR
>*,
241
PRMInstance
<
GUM_SCALAR
>* > >::
iterator_safe
match
;
242
// Using p information to build child's isomorphism graph
243
NodeId
id
= 0;
244
245
for
(
const
auto
&
elt
:
p_iso_map
) {
246
auto
match
=
edge_growth
.
matches
.
begin
();
247
248
for
(;
match
!=
edge_growth
.
matches
.
end
(); ++
match
) {
249
// Adding the isomorphism in the iso_graph and building the iso_map.
250
if
(
child
->
code
().
codes
.
back
()->
isForward
()) {
251
if
(
elt
.
second
->
exists
(
match
.
val
().
first
)
252
&& !(
elt
.
second
->
exists
(
match
.
val
().
second
))) {
253
// Let's see if the new match is already matched
254
Sequence
<
PRMInstance
<
GUM_SCALAR
>* >*
new_seq
255
=
new
Sequence
<
PRMInstance
<
GUM_SCALAR
>* >(*
elt
.
second
);
256
new_seq
->
insert
(
match
.
val
().
second
);
257
258
if
(
_is_new_seq_
(*
new_seq
,
data
->
iso_map
)) {
259
id
=
data
->
iso_graph
.
addNode
();
260
data
->
iso_map
.
insert
(
id
,
new_seq
);
261
}
else
{
262
delete
new_seq
;
263
}
264
265
break
;
266
}
267
}
else
{
268
if
(
elt
.
second
->
exists
(
match
.
val
().
first
) &&
elt
.
second
->
exists
(
match
.
val
().
second
)) {
269
Sequence
<
PRMInstance
<
GUM_SCALAR
>* >*
new_seq
270
=
new
Sequence
<
PRMInstance
<
GUM_SCALAR
>* >(*
elt
.
second
);
271
272
if
(
_is_new_seq_
(*
new_seq
,
data
->
iso_map
)) {
273
id
=
data
->
iso_graph
.
addNode
();
274
data
->
iso_map
.
insert
(
id
,
new_seq
);
275
}
else
{
276
delete
new_seq
;
277
}
278
279
break
;
280
}
281
}
282
}
283
284
if
(
match
!=
edge_growth
.
matches
.
end
()) {
285
// Adding edges in the iso_graph
286
for
(
const
auto
node
:
data
->
iso_graph
.
nodes
())
287
if
(
node
!=
id
)
288
for
(
const
auto
m
: *
data
->
iso_map
[
id
])
289
if
(
data
->
iso_map
[
node
]->
exists
(
m
)) {
290
data
->
iso_graph
.
addEdge
(
node
,
id
);
291
break
;
292
}
293
294
degree_list
.
push_back
(
id
);
295
edge_growth
.
matches
.
erase
(
match
.
key
());
296
}
297
}
298
299
if
(
data
->
iso_graph
.
size
() <
min_freq
) {
300
delete
data
;
301
delete
child
;
302
GUM_ERROR
(
OperationNotAllowed
,
"child is not frequent enough"
)
303
}
304
305
// Now we can compute the maximal independent set of child
306
DFSTree
<
GUM_SCALAR
>::
NeighborDegreeSort
my_operator
(
data
->
iso_graph
);
307
std
::
sort
(
degree_list
.
begin
(),
degree_list
.
end
(),
my_operator
);
308
Set
<
NodeId
>
removed
;
309
310
for
(
const
auto
node
:
degree_list
) {
311
if
(!
removed
.
exists
(
node
)) {
312
removed
.
insert
(
node
);
313
314
for
(
const
auto
neighbor
:
data
->
iso_graph
.
neighbours
(
node
))
315
removed
.
insert
(
neighbor
);
316
317
data
->
max_indep_set
.
insert
(
node
);
318
}
319
}
320
321
_data_
.
insert
(
child
,
data
);
322
323
if
(!
_strategy_
->
accept_growth
(&
p
,
child
,
edge_growth
)) {
324
_data_
.
erase
(
child
);
325
delete
data
;
326
delete
child
;
327
GUM_ERROR
(
OperationNotAllowed
,
"child is not frequent enough"
)
328
}
329
330
_addChild_
(
p
,
child
,
edge_growth
);
331
return
*
child
;
332
}
333
334
template
<
typename
GUM_SCALAR
>
335
bool
DFSTree
<
GUM_SCALAR
>::
_test_equality_
(
336
HashTable
<
PRMClassElement
<
GUM_SCALAR
>*,
Size
>&
x
,
337
HashTable
<
PRMClassElement
<
GUM_SCALAR
>*,
Size
>&
y
) {
338
try
{
339
for
(
const
auto
&
elt
:
x
)
340
if
(
y
[
elt
.
first
] !=
elt
.
second
)
return
false
;
341
}
catch
(
NotFound
&) {
return
false
; }
342
343
return
true
;
344
}
345
346
// PatternData
347
template
<
typename
GUM_SCALAR
>
348
DFSTree
<
GUM_SCALAR
>::
PatternData
::
PatternData
(
const
PatternData
&
from
) :
349
pattern
(
from
.
pattern
),
children
(
from
.
children
),
iso_graph
(
from
.
iso_graph
),
350
max_indep_set
(
from
.
max_indep_set
),
cost
(
from
.
cost
),
gain
(
from
.
gain
) {
351
GUM_CONS_CPY
(
DFSTree
<
GUM_SCALAR
>::
PatternData
);
352
353
for
(
const
auto
&
elt
:
from
.
iso_map
)
354
iso_map
.
insert
(
elt
.
first
,
new
Sequence
<
PRMInstance
<
GUM_SCALAR
>* >(*
elt
.
second
));
355
}
356
357
template
<
typename
GUM_SCALAR
>
358
DFSTree
<
GUM_SCALAR
>::
PatternData
::~
PatternData
() {
359
GUM_DESTRUCTOR
(
DFSTree
<
GUM_SCALAR
>::
PatternData
);
360
361
for
(
const
auto
&
elt
:
iso_map
)
362
delete
elt
.
second
;
363
}
364
365
template
<
typename
GUM_SCALAR
>
366
INLINE
DFSTree
<
GUM_SCALAR
>::
DFSTree
(
const
InterfaceGraph
<
GUM_SCALAR
>&
graph
,
367
gspan
::
SearchStrategy
<
GUM_SCALAR
>*
strategy
) :
368
_graph_
(&
graph
),
369
_strategy_
(
strategy
) {
370
GUM_CONSTRUCTOR
(
DFSTree
);
371
372
if
(!
_strategy_
)
_strategy_
=
new
FrequenceSearch
<
GUM_SCALAR
>(2);
373
374
_strategy_
->
setTree
(
this
);
375
}
376
377
template
<
typename
GUM_SCALAR
>
378
INLINE
std
::
list
<
NodeId
>&
DFSTree
<
GUM_SCALAR
>::
roots
() {
379
return
_roots_
;
380
}
381
382
template
<
typename
GUM_SCALAR
>
383
INLINE
const
std
::
list
<
NodeId
>&
DFSTree
<
GUM_SCALAR
>::
roots
()
const
{
384
return
_roots_
;
385
}
386
387
template
<
typename
GUM_SCALAR
>
388
INLINE
Pattern
&
DFSTree
<
GUM_SCALAR
>::
parent
(
const
Pattern
&
p
) {
389
try
{
390
return
*(
_node_map_
.
second
(
391
*(
DiGraph
::
parents
(
_node_map_
.
first
(
const_cast
<
Pattern
* >(&
p
))).
begin
())));
392
}
catch
(
NotFound
&) {
393
if
(
_node_map_
.
existsSecond
(
const_cast
<
Pattern
* >(&
p
))) {
394
GUM_ERROR
(
NotFound
,
"the given pattern is a root node"
)
395
}
else
{
396
GUM_ERROR
(
NotFound
,
"pattern not found in this DFSTree"
)
397
}
398
}
399
}
400
401
template
<
typename
GUM_SCALAR
>
402
INLINE
const
Pattern
&
DFSTree
<
GUM_SCALAR
>::
parent
(
const
Pattern
&
p
)
const
{
403
try
{
404
return
*(
_node_map_
.
second
(
405
*(
DiGraph
::
parents
(
_node_map_
.
first
(
const_cast
<
Pattern
* >(&
p
))).
begin
())));
406
}
catch
(
NotFound
&) {
407
if
(
_node_map_
.
existsSecond
(
const_cast
<
Pattern
* >(&
p
))) {
408
GUM_ERROR
(
NotFound
,
"the given pattern is a root node"
)
409
}
else
{
410
GUM_ERROR
(
NotFound
,
"pattern not found in this DFSTree"
)
411
}
412
}
413
}
414
415
template
<
typename
GUM_SCALAR
>
416
INLINE
std
::
list
<
NodeId
>&
DFSTree
<
GUM_SCALAR
>::
children
(
const
Pattern
&
p
) {
417
try
{
418
return
_data_
[
const_cast
<
Pattern
* >(&
p
)]->
children
;
419
}
catch
(
NotFound
&) {
GUM_ERROR
(
NotFound
,
"pattern not found in this DFSTree"
) }
420
}
421
422
template
<
typename
GUM_SCALAR
>
423
INLINE
const
std
::
list
<
NodeId
>&
DFSTree
<
GUM_SCALAR
>::
children
(
const
Pattern
&
p
)
const
{
424
try
{
425
return
_data_
[
const_cast
<
Pattern
* >(&
p
)]->
children
;
426
}
catch
(
NotFound
&) {
GUM_ERROR
(
NotFound
,
"pattern not found in this DFSTree"
) }
427
}
428
429
template
<
typename
GUM_SCALAR
>
430
INLINE
Pattern
&
DFSTree
<
GUM_SCALAR
>::
pattern
(
NodeId
id
) {
431
try
{
432
return
*(
_node_map_
.
second
(
id
));
433
}
catch
(
NotFound
&) {
GUM_ERROR
(
NotFound
,
"no pattern matching the given id"
) }
434
}
435
436
template
<
typename
GUM_SCALAR
>
437
INLINE
const
Pattern
&
DFSTree
<
GUM_SCALAR
>::
pattern
(
NodeId
id
)
const
{
438
try
{
439
return
*(
_node_map_
.
second
(
id
));
440
}
catch
(
NotFound
&) {
GUM_ERROR
(
NotFound
,
"no pattern matching the given id"
) }
441
}
442
443
template
<
typename
GUM_SCALAR
>
444
INLINE
UndiGraph
&
DFSTree
<
GUM_SCALAR
>::
iso_graph
(
const
Pattern
&
p
) {
445
try
{
446
return
_data_
[
const_cast
<
Pattern
* >(&
p
)]->
iso_graph
;
447
}
catch
(
NotFound
&) {
GUM_ERROR
(
NotFound
,
"pattern not found in this DFSTree"
) }
448
}
449
450
template
<
typename
GUM_SCALAR
>
451
INLINE
Sequence
<
PRMInstance
<
GUM_SCALAR
>* >&
452
DFSTree
<
GUM_SCALAR
>::
iso_map
(
const
Pattern
&
p
,
NodeId
node
) {
453
try
{
454
return
*(
_data_
[
const_cast
<
Pattern
* >(&
p
)]->
iso_map
[
node
]);
455
}
catch
(
NotFound
&) {
456
if
(
_data_
.
exists
(
const_cast
<
Pattern
* >(&
p
))) {
457
GUM_ERROR
(
NotFound
,
"node not found in Pattern's isomorphism graph"
)
458
}
else
{
459
GUM_ERROR
(
NotFound
,
"pattern not found in this DFSTree"
)
460
}
461
}
462
}
463
464
template
<
typename
GUM_SCALAR
>
465
INLINE
Set
<
NodeId
>&
DFSTree
<
GUM_SCALAR
>::
max_indep_set
(
const
Pattern
&
p
) {
466
try
{
467
return
_data_
[
const_cast
<
Pattern
* >(&
p
)]->
max_indep_set
;
468
}
catch
(
NotFound
&) {
GUM_ERROR
(
NotFound
,
"pattern not found in this DFSTree"
) }
469
}
470
471
template
<
typename
GUM_SCALAR
>
472
INLINE
const
InterfaceGraph
<
GUM_SCALAR
>&
DFSTree
<
GUM_SCALAR
>::
graph
()
const
{
473
return
*
_graph_
;
474
}
475
476
template
<
typename
GUM_SCALAR
>
477
INLINE
std
::
ostream
&
operator
<<(
std
::
ostream
&
out
,
const
EdgeGrowth
<
GUM_SCALAR
>&
edge
) {
478
out
<<
edge
.
u
<<
", "
<< *(
edge
.
edge
) <<
", "
<< *(
edge
.
l_v
) <<
", "
<<
edge
.
v
;
479
return
out
;
480
}
481
482
template
<
typename
GUM_SCALAR
>
483
INLINE
double
DFSTree
<
GUM_SCALAR
>::
frequency
(
const
Pattern
&
p
)
const
{
484
return
(
double
)
_data_
[
const_cast
<
Pattern
* >(&
p
)]->
max_indep_set
.
size
();
485
}
486
487
template
<
typename
GUM_SCALAR
>
488
INLINE
typename
DFSTree
<
GUM_SCALAR
>::
PatternData
&
489
DFSTree
<
GUM_SCALAR
>::
data
(
const
Pattern
&
p
) {
490
return
*(
_data_
[
const_cast
<
Pattern
* >(&
p
)]);
491
}
492
493
template
<
typename
GUM_SCALAR
>
494
INLINE
const
typename
DFSTree
<
GUM_SCALAR
>::
PatternData
&
495
DFSTree
<
GUM_SCALAR
>::
data
(
const
Pattern
&
p
)
const
{
496
return
*(
_data_
[
const_cast
<
Pattern
* >(&
p
)]);
497
}
498
499
template
<
typename
GUM_SCALAR
>
500
INLINE
SearchStrategy
<
GUM_SCALAR
>&
DFSTree
<
GUM_SCALAR
>::
strategy
() {
501
return
*
_strategy_
;
502
}
503
504
template
<
typename
GUM_SCALAR
>
505
INLINE
const
SearchStrategy
<
GUM_SCALAR
>&
DFSTree
<
GUM_SCALAR
>::
strategy
()
const
{
506
return
*
_strategy_
;
507
}
508
509
// NeighborDegreeSort
510
511
template
<
typename
GUM_SCALAR
>
512
INLINE
DFSTree
<
GUM_SCALAR
>::
NeighborDegreeSort
::
NeighborDegreeSort
(
UndiGraph
&
graph
) :
513
g
(
graph
) {
514
GUM_CONSTRUCTOR
(
DFSTree
<
GUM_SCALAR
>::
NeighborDegreeSort
);
515
}
516
517
template
<
typename
GUM_SCALAR
>
518
INLINE
DFSTree
<
GUM_SCALAR
>::
NeighborDegreeSort
::
NeighborDegreeSort
(
519
const
NeighborDegreeSort
&
source
) :
520
g
(
source
.
g
) {
521
GUM_CONS_CPY
(
DFSTree
<
GUM_SCALAR
>::
NeighborDegreeSort
);
522
}
523
524
template
<
typename
GUM_SCALAR
>
525
INLINE
DFSTree
<
GUM_SCALAR
>::
NeighborDegreeSort
::~
NeighborDegreeSort
() {
526
GUM_DESTRUCTOR
(
DFSTree
<
GUM_SCALAR
>::
NeighborDegreeSort
);
527
}
528
529
template
<
typename
GUM_SCALAR
>
530
INLINE
bool
DFSTree
<
GUM_SCALAR
>::
NeighborDegreeSort
::
operator
()(
NodeId
i
,
NodeId
j
) {
531
return
g
.
neighbours
(
i
).
size
() <
g
.
neighbours
(
j
).
size
();
532
}
533
534
// PatternData
535
536
template
<
typename
GUM_SCALAR
>
537
INLINE
DFSTree
<
GUM_SCALAR
>::
PatternData
::
PatternData
(
Pattern
*
p
) :
538
pattern
(
p
),
cost
(0),
gain
(0) {
539
GUM_CONSTRUCTOR
(
DFSTree
<
GUM_SCALAR
>::
PatternData
);
540
}
541
542
}
/* namespace gspan */
543
}
/* namespace prm */
544
}
/* 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