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