aGrUM
0.20.3
a C++ library for (probabilistic) graphical models
graphChangesSelector4DiGraph_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
/** @file
23
* @brief The mecanism to compute the next available graph changes for directed
24
* structure learning search algorithms.
25
*
26
* @author Christophe GONZALES(@AMU) and Pierre-Henri WUILLEMIN(@LIP6)
27
*/
28
#
ifndef
DOXYGEN_SHOULD_SKIP_THIS
29
30
#
include
<
limits
>
31
32
namespace
gum
{
33
34
namespace
learning
{
35
36
/// default constructor
37
template
<
typename
STRUCTURAL_CONSTRAINT,
38
typename
GRAPH_CHANGES_GENERATOR,
39
template
<
typename
>
40
class
ALLOC >
41
INLINE GraphChangesSelector4DiGraph<
STRUCTURAL_CONSTRAINT
,
GRAPH_CHANGES_GENERATOR
,
ALLOC
>::
42
GraphChangesSelector4DiGraph
(
Score
<
ALLOC
>&
score
,
43
STRUCTURAL_CONSTRAINT
&
constraint
,
44
GRAPH_CHANGES_GENERATOR
&
changes_generator
) :
45
_score_
(
score
.
clone
()),
46
_constraint_
(&
constraint
),
_changes_generator_
(&
changes_generator
) {
47
_parents_
.
resize
(32);
48
GUM_CONSTRUCTOR
(
GraphChangesSelector4DiGraph
);
49
}
50
51
/// copy constructor
52
template
<
typename
STRUCTURAL_CONSTRAINT
,
53
typename
GRAPH_CHANGES_GENERATOR
,
54
template
<
typename
>
55
class
ALLOC
>
56
GraphChangesSelector4DiGraph
<
STRUCTURAL_CONSTRAINT
,
GRAPH_CHANGES_GENERATOR
,
ALLOC
>::
57
GraphChangesSelector4DiGraph
(
const
GraphChangesSelector4DiGraph
<
STRUCTURAL_CONSTRAINT
,
58
GRAPH_CHANGES_GENERATOR
,
59
ALLOC
>&
from
) :
60
_score_
(
from
.
_score_
!=
nullptr
?
from
.
_score_
->
clone
() :
nullptr
),
61
_constraint_
(
from
.
_constraint_
),
_changes_generator_
(
from
.
_changes_generator_
),
62
_changes_
(
from
.
_changes_
),
_change_scores_
(
from
.
_change_scores_
),
63
_change_queue_per_node_
(
from
.
_change_queue_per_node_
),
_node_queue_
(
from
.
_node_queue_
),
64
_illegal_changes_
(
from
.
_illegal_changes_
),
65
_node_current_scores_
(
from
.
_node_current_scores_
),
_parents_
(
from
.
_parents_
),
66
_queues_valid_
(
from
.
_queues_valid_
),
_queues_to_update_
(
from
.
_queues_to_update_
) {
67
// for debugging
68
GUM_CONS_CPY
(
GraphChangesSelector4DiGraph
);
69
}
70
71
/// move constructor
72
template
<
typename
STRUCTURAL_CONSTRAINT
,
73
typename
GRAPH_CHANGES_GENERATOR
,
74
template
<
typename
>
75
class
ALLOC
>
76
GraphChangesSelector4DiGraph
<
STRUCTURAL_CONSTRAINT
,
GRAPH_CHANGES_GENERATOR
,
ALLOC
>::
77
GraphChangesSelector4DiGraph
(
78
GraphChangesSelector4DiGraph
<
STRUCTURAL_CONSTRAINT
,
GRAPH_CHANGES_GENERATOR
,
ALLOC
>&&
79
from
) :
80
_score_
(
from
.
_score_
),
81
_constraint_
(
std
::
move
(
from
.
_constraint_
)),
82
_changes_generator_
(
std
::
move
(
from
.
_changes_generator_
)),
83
_changes_
(
std
::
move
(
from
.
_changes_
)),
_change_scores_
(
std
::
move
(
from
.
_change_scores_
)),
84
_change_queue_per_node_
(
std
::
move
(
from
.
_change_queue_per_node_
)),
85
_node_queue_
(
std
::
move
(
from
.
_node_queue_
)),
86
_illegal_changes_
(
std
::
move
(
from
.
_illegal_changes_
)),
87
_node_current_scores_
(
std
::
move
(
from
.
_node_current_scores_
)),
88
_parents_
(
std
::
move
(
from
.
_parents_
)),
_queues_valid_
(
std
::
move
(
from
.
_queues_valid_
)),
89
_queues_to_update_
(
std
::
move
(
from
.
_queues_to_update_
)) {
90
from
.
_score_
=
nullptr
;
91
// for debugging
92
GUM_CONS_MOV
(
GraphChangesSelector4DiGraph
);
93
}
94
95
/// destructor
96
template
<
typename
STRUCTURAL_CONSTRAINT
,
97
typename
GRAPH_CHANGES_GENERATOR
,
98
template
<
typename
>
99
class
ALLOC
>
100
INLINE
GraphChangesSelector4DiGraph
<
101
102
STRUCTURAL_CONSTRAINT
,
103
GRAPH_CHANGES_GENERATOR
,
104
ALLOC
>::~
GraphChangesSelector4DiGraph
() {
105
if
(
_score_
!=
nullptr
) {
106
ALLOC
<
Score
<
ALLOC
> >
allocator
(
_score_
->
getAllocator
());
107
allocator
.
destroy
(
_score_
);
108
allocator
.
deallocate
(
_score_
, 1);
109
}
110
GUM_DESTRUCTOR
(
GraphChangesSelector4DiGraph
);
111
}
112
113
/// copy operator
114
template
<
typename
STRUCTURAL_CONSTRAINT
,
115
typename
GRAPH_CHANGES_GENERATOR
,
116
template
<
typename
>
117
class
ALLOC
>
118
GraphChangesSelector4DiGraph
<
STRUCTURAL_CONSTRAINT
,
GRAPH_CHANGES_GENERATOR
,
ALLOC
>&
119
GraphChangesSelector4DiGraph
<
STRUCTURAL_CONSTRAINT
,
GRAPH_CHANGES_GENERATOR
,
ALLOC
>::
120
operator
=(
const
GraphChangesSelector4DiGraph
<
STRUCTURAL_CONSTRAINT
,
121
GRAPH_CHANGES_GENERATOR
,
122
ALLOC
>&
from
) {
123
if
(
this
!= &
from
) {
124
// remove the old score
125
if
(
_score_
!=
nullptr
) {
126
ALLOC
<
Score
<
ALLOC
> >
allocator
(
_score_
->
getAllocator
());
127
allocator
.
destroy
(
_score_
);
128
allocator
.
deallocate
(
_score_
, 1);
129
_score_
=
nullptr
;
130
}
131
132
if
(
from
.
_score_
!=
nullptr
)
_score_
=
from
.
_score_
->
clone
();
133
_constraint_
=
from
.
_constraint_
;
134
_changes_generator_
=
from
.
_changes_generator_
;
135
_changes_
=
from
.
_changes_
;
136
_change_scores_
=
from
.
_change_scores_
;
137
_change_queue_per_node_
=
from
.
_change_queue_per_node_
;
138
_node_queue_
=
from
.
_node_queue_
;
139
_illegal_changes_
=
from
.
_illegal_changes_
;
140
_node_current_scores_
=
from
.
_node_current_scores_
;
141
_parents_
=
from
.
_parents_
;
142
_queues_valid_
=
from
.
_queues_valid_
;
143
_queues_to_update_
=
from
.
_queues_to_update_
;
144
}
145
146
return
*
this
;
147
}
148
149
/// move operator
150
template
<
typename
STRUCTURAL_CONSTRAINT
,
151
typename
GRAPH_CHANGES_GENERATOR
,
152
template
<
typename
>
153
class
ALLOC
>
154
GraphChangesSelector4DiGraph
<
STRUCTURAL_CONSTRAINT
,
GRAPH_CHANGES_GENERATOR
,
ALLOC
>&
155
GraphChangesSelector4DiGraph
<
STRUCTURAL_CONSTRAINT
,
GRAPH_CHANGES_GENERATOR
,
ALLOC
>::
156
operator
=(
157
GraphChangesSelector4DiGraph
<
STRUCTURAL_CONSTRAINT
,
GRAPH_CHANGES_GENERATOR
,
ALLOC
>&&
158
from
) {
159
if
(
this
!= &
from
) {
160
_score_
=
from
.
_score_
;
161
from
.
_score_
=
nullptr
;
162
163
_constraint_
=
std
::
move
(
from
.
_constraint_
);
164
_changes_generator_
=
std
::
move
(
from
.
_changes_generator_
);
165
_changes_
=
std
::
move
(
from
.
_changes_
);
166
_change_scores_
=
std
::
move
(
from
.
_change_scores_
);
167
_change_queue_per_node_
=
std
::
move
(
from
.
_change_queue_per_node_
);
168
_node_queue_
=
std
::
move
(
from
.
_node_queue_
);
169
_illegal_changes_
=
std
::
move
(
from
.
_illegal_changes_
);
170
_node_current_scores_
=
std
::
move
(
from
.
_node_current_scores_
);
171
_parents_
=
std
::
move
(
from
.
_parents_
);
172
_queues_valid_
=
std
::
move
(
from
.
_queues_valid_
);
173
_queues_to_update_
=
std
::
move
(
from
.
_queues_to_update_
);
174
}
175
176
return
*
this
;
177
}
178
179
180
/// indicates whether a given change is valid or not
181
template
<
typename
STRUCTURAL_CONSTRAINT
,
182
typename
GRAPH_CHANGES_GENERATOR
,
183
template
<
typename
>
184
class
ALLOC
>
185
INLINE
bool
186
GraphChangesSelector4DiGraph
<
STRUCTURAL_CONSTRAINT
,
GRAPH_CHANGES_GENERATOR
,
ALLOC
>::
187
isChangeValid
(
const
GraphChange
&
change
)
const
{
188
return
_constraint_
->
checkModification
(
change
);
189
}
190
191
192
/// indicates whether a given change is valid or not
193
template
<
typename
STRUCTURAL_CONSTRAINT
,
194
typename
GRAPH_CHANGES_GENERATOR
,
195
template
<
typename
>
196
class
ALLOC
>
197
INLINE
bool
198
GraphChangesSelector4DiGraph
<
STRUCTURAL_CONSTRAINT
,
GRAPH_CHANGES_GENERATOR
,
ALLOC
>::
199
_isChangeValid_
(
const
std
::
size_t
index
)
const
{
200
return
isChangeValid
(
_changes_
[
index
]);
201
}
202
203
204
/// sets the graph from which scores are computed
205
template
<
typename
STRUCTURAL_CONSTRAINT
,
206
typename
GRAPH_CHANGES_GENERATOR
,
207
template
<
typename
>
208
class
ALLOC
>
209
void
GraphChangesSelector4DiGraph
<
STRUCTURAL_CONSTRAINT
,
GRAPH_CHANGES_GENERATOR
,
ALLOC
>::
210
setGraph
(
DiGraph
&
graph
) {
211
// fill the DAG with all the missing nodes
212
const
DatabaseTable
<
ALLOC
>&
database
=
_score_
->
database
();
213
const
auto
&
nodeId2Columns
=
_score_
->
nodeId2Columns
();
214
215
if
(
nodeId2Columns
.
empty
()) {
216
const
NodeId
nb_nodes
=
NodeId
(
database
.
nbVariables
());
217
for
(
NodeId
i
=
NodeId
(0);
i
<
nb_nodes
; ++
i
) {
218
if
(!
graph
.
existsNode
(
i
)) {
graph
.
addNodeWithId
(
i
); }
219
}
220
}
else
{
221
for
(
auto
iter
=
nodeId2Columns
.
cbegin
();
iter
!=
nodeId2Columns
.
cend
(); ++
iter
) {
222
const
NodeId
id
=
iter
.
first
();
223
if
(!
graph
.
existsNode
(
id
)) {
graph
.
addNodeWithId
(
id
); }
224
}
225
}
226
227
228
// remove the node that do belong neither to the database
229
// nor to nodeId2Columns
230
if
(
nodeId2Columns
.
empty
()) {
231
const
NodeId
nb_nodes
=
NodeId
(
database
.
nbVariables
());
232
for
(
auto
node
:
graph
) {
233
if
(
node
>=
nb_nodes
) {
graph
.
eraseNode
(
node
); }
234
}
235
}
else
{
236
for
(
auto
node
:
graph
) {
237
if
(!
nodeId2Columns
.
existsFirst
(
node
)) {
graph
.
eraseNode
(
node
); }
238
}
239
}
240
241
242
// _constraint_ is the constraint used by the selector to restrict the set
243
// of applicable changes. However, the generator may have a different set
244
// of constraints (e.g., a constraintSliceOrder needs be tested only by the
245
// generator because the changes returned by the generator will always
246
// statisfy this constraint, hence the selector needs not test this
247
// constraint). Therefore, if the selector and generator have different
248
// constraints, both should use method setGraph() to initialize
249
// themselves.
250
_constraint_
->
setGraph
(
graph
);
251
if
(
reinterpret_cast
<
STRUCTURAL_CONSTRAINT
* >(&(
_changes_generator_
->
constraint
()))
252
!=
_constraint_
) {
253
_changes_generator_
->
constraint
().
setGraph
(
graph
);
254
}
255
256
_changes_generator_
->
setGraph
(
graph
);
257
258
259
// save the set of parents of each node (this will speed-up the
260
// computations of the scores)
261
const
std
::
size_t
nb_nodes
=
graph
.
size
();
262
{
263
const
std
::
vector
<
NodeId
,
ALLOC
<
NodeId
> >
empty_pars
;
264
_parents_
.
clear
();
265
_parents_
.
resize
(
nb_nodes
);
266
for
(
const
auto
node
:
graph
) {
267
auto
&
node_parents
=
_parents_
.
insert
(
node
,
empty_pars
).
second
;
268
const
NodeSet
&
dag_parents
=
graph
.
parents
(
node
);
269
if
(!
dag_parents
.
empty
()) {
270
node_parents
.
resize
(
dag_parents
.
size
());
271
std
::
size_t
j
=
std
::
size_t
(0);
272
for
(
const
auto
par
:
dag_parents
) {
273
node_parents
[
j
] =
par
;
274
++
j
;
275
}
276
}
277
}
278
}
279
280
// assign a score to each node given its parents in the current graph
281
_node_current_scores_
.
clear
();
282
_node_current_scores_
.
resize
(
nb_nodes
);
283
for
(
const
auto
node
:
graph
) {
284
_node_current_scores_
.
insert
(
node
,
_score_
->
score
(
node
,
_parents_
[
node
]));
285
}
286
287
// compute all the possible changes
288
_changes_
.
clear
();
289
_changes_
.
resize
(
nb_nodes
);
290
for
(
const
auto
&
change
: *
_changes_generator_
) {
291
_changes_
<<
change
;
292
}
293
_changes_generator_
->
notifyGetCompleted
();
294
295
// determine the changes that are illegal and prepare the computation of
296
// the scores of all the legal changes
297
_illegal_changes_
.
clear
();
298
299
// set the _change_scores_ and _change_queue_per_node_ for legal changes
300
_change_scores_
.
clear
();
301
_change_scores_
.
resize
(
_changes_
.
size
(),
302
std
::
pair
<
double
,
double
>(
std
::
numeric_limits
<
double
>::
min
(),
303
std
::
numeric_limits
<
double
>::
min
()));
304
_change_queue_per_node_
.
clear
();
305
_change_queue_per_node_
.
resize
(
nb_nodes
);
306
{
307
const
PriorityQueue
<
std
::
size_t
,
double
,
std
::
greater
<
double
> >
empty_prio
;
308
for
(
const
auto
node
:
graph
) {
309
_change_queue_per_node_
.
insert
(
node
,
empty_prio
);
310
}
311
}
312
313
for
(
std
::
size_t
i
=
std
::
size_t
(0);
i
<
_changes_
.
size
(); ++
i
) {
314
if
(!
_isChangeValid_
(
i
)) {
315
_illegal_changes_
.
insert
(
i
);
316
}
else
{
317
const
GraphChange
&
change
=
_changes_
[
i
];
318
319
switch
(
change
.
type
()) {
320
case
GraphChangeType
::
ARC_ADDITION
: {
321
auto
&
parents
=
_parents_
[
change
.
node2
()];
322
parents
.
push_back
(
change
.
node1
());
323
const
double
delta
324
=
_score_
->
score
(
change
.
node2
(),
parents
) -
_node_current_scores_
[
change
.
node2
()];
325
parents
.
pop_back
();
326
327
_change_scores_
[
i
].
second
=
delta
;
328
_change_queue_per_node_
[
change
.
node2
()].
insert
(
i
,
delta
);
329
}
break
;
330
331
case
GraphChangeType
::
ARC_DELETION
: {
332
auto
&
parents
=
_parents_
[
change
.
node2
()];
333
for
(
auto
&
par
:
parents
) {
334
if
(
par
==
change
.
node1
()) {
335
par
= *(
parents
.
rbegin
());
336
parents
.
pop_back
();
337
break
;
338
}
339
}
340
const
double
delta
341
=
_score_
->
score
(
change
.
node2
(),
parents
) -
_node_current_scores_
[
change
.
node2
()];
342
parents
.
push_back
(
change
.
node1
());
343
344
_change_scores_
[
i
].
second
=
delta
;
345
_change_queue_per_node_
[
change
.
node2
()].
insert
(
i
,
delta
);
346
}
break
;
347
348
case
GraphChangeType
::
ARC_REVERSAL
: {
349
// remove arc ( node1 -> node2 )
350
auto
&
parents2
=
_parents_
[
change
.
node2
()];
351
for
(
auto
&
par
:
parents2
) {
352
if
(
par
==
change
.
node1
()) {
353
par
= *(
parents2
.
rbegin
());
354
parents2
.
pop_back
();
355
break
;
356
}
357
}
358
359
const
double
delta2
360
=
_score_
->
score
(
change
.
node2
(),
parents2
) -
_node_current_scores_
[
change
.
node2
()];
361
parents2
.
push_back
(
change
.
node1
());
362
363
// add arc ( node2 -> node1 )
364
auto
&
parents1
=
_parents_
[
change
.
node1
()];
365
parents1
.
push_back
(
change
.
node2
());
366
const
double
delta1
367
=
_score_
->
score
(
change
.
node1
(),
parents1
) -
_node_current_scores_
[
change
.
node1
()];
368
parents1
.
pop_back
();
369
370
_change_scores_
[
i
].
first
=
delta1
;
371
_change_scores_
[
i
].
second
=
delta2
;
372
373
const
double
delta
=
delta1
+
delta2
;
374
_change_queue_per_node_
[
change
.
node1
()].
insert
(
i
,
delta
);
375
_change_queue_per_node_
[
change
.
node2
()].
insert
(
i
,
delta
);
376
377
}
break
;
378
379
default
: {
380
GUM_ERROR
(
NotImplementedYet
,
381
"Method setGraph of GraphChangesSelector4DiGraph "
382
<<
"does not handle yet graph change of type "
<<
change
.
type
());
383
}
384
}
385
}
386
}
387
388
// update the global queue
389
_node_queue_
.
clear
();
390
for
(
const
auto
node
:
graph
) {
391
_node_queue_
.
insert
(
node
,
392
_change_queue_per_node_
[
node
].
empty
()
393
?
std
::
numeric_limits
<
double
>::
min
()
394
:
_change_queue_per_node_
[
node
].
topPriority
());
395
}
396
_queues_valid_
=
true
;
397
_queues_to_update_
.
clear
();
398
}
399
400
401
/// put a change into the illegal set
402
template
<
typename
STRUCTURAL_CONSTRAINT
,
403
typename
GRAPH_CHANGES_GENERATOR
,
404
template
<
typename
>
405
class
ALLOC
>
406
void
GraphChangesSelector4DiGraph
<
STRUCTURAL_CONSTRAINT
,
GRAPH_CHANGES_GENERATOR
,
ALLOC
>::
407
_invalidateChange_
(
const
std
::
size_t
change_index
) {
408
const
GraphChange
&
change
=
_changes_
[
change_index
];
409
if
(
change
.
type
() ==
GraphChangeType
::
ARC_REVERSAL
) {
410
// remove the tail change from its priority queue
411
PriorityQueue
<
std
::
size_t
,
double
,
std
::
greater
<
double
> >&
queue1
412
=
_change_queue_per_node_
[
change
.
node1
()];
413
queue1
.
erase
(
change_index
);
414
415
// recompute the top priority for the changes of the head
416
const
double
new_priority
417
=
queue1
.
empty
() ?
std
::
numeric_limits
<
double
>::
min
() :
queue1
.
topPriority
();
418
_node_queue_
.
setPriority
(
change
.
node1
(),
new_priority
);
419
}
420
421
// remove the head change from its priority queue
422
PriorityQueue
<
std
::
size_t
,
double
,
std
::
greater
<
double
> >&
queue2
423
=
_change_queue_per_node_
[
change
.
node2
()];
424
queue2
.
erase
(
change_index
);
425
426
// recompute the top priority for the changes of the head
427
const
double
new_priority
428
=
queue2
.
empty
() ?
std
::
numeric_limits
<
double
>::
min
() :
queue2
.
topPriority
();
429
_node_queue_
.
setPriority
(
change
.
node2
(),
new_priority
);
430
431
// put the change into the illegal set
432
_illegal_changes_
.
insert
(
change_index
);
433
}
434
435
436
/// indicates whether the selector still contain graph changes
437
template
<
typename
STRUCTURAL_CONSTRAINT
,
438
typename
GRAPH_CHANGES_GENERATOR
,
439
template
<
typename
>
440
class
ALLOC
>
441
bool
GraphChangesSelector4DiGraph
<
STRUCTURAL_CONSTRAINT
,
GRAPH_CHANGES_GENERATOR
,
ALLOC
>::
442
empty
() {
443
// put into the illegal change set all the top elements of the different
444
// queues that are not valid anymore
445
if
(!
_queues_valid_
) {
446
for
(
auto
&
queue_pair
:
_change_queue_per_node_
) {
447
auto
&
queue
=
queue_pair
.
second
;
448
while
(!
queue
.
empty
() && !
_isChangeValid_
(
queue
.
top
())) {
449
_invalidateChange_
(
queue
.
top
());
450
}
451
}
452
_queues_valid_
=
true
;
453
}
454
455
return
_node_queue_
.
topPriority
() ==
std
::
numeric_limits
<
double
>::
min
();
456
}
457
458
459
/// indicates whether the selector still contain graph changes
460
/// in the ith queue
461
template
<
typename
STRUCTURAL_CONSTRAINT
,
462
typename
GRAPH_CHANGES_GENERATOR
,
463
template
<
typename
>
464
class
ALLOC
>
465
bool
466
GraphChangesSelector4DiGraph
<
STRUCTURAL_CONSTRAINT
,
GRAPH_CHANGES_GENERATOR
,
ALLOC
>::
empty
(
467
const
NodeId
node
) {
468
// put into the illegal change set all the top elements of the different
469
// queues that are not valid anymore
470
if
(!
_queues_valid_
) {
471
for
(
auto
&
queue_pair
:
_change_queue_per_node_
) {
472
auto
&
queue
=
queue_pair
.
second
;
473
while
(!
queue
.
empty
() && !
_isChangeValid_
(
queue
.
top
())) {
474
_invalidateChange_
(
queue
.
top
());
475
}
476
}
477
_queues_valid_
=
true
;
478
}
479
480
return
_change_queue_per_node_
[
node
].
empty
();
481
}
482
483
484
/// returns the best graph change to examine
485
template
<
typename
STRUCTURAL_CONSTRAINT
,
486
typename
GRAPH_CHANGES_GENERATOR
,
487
template
<
typename
>
488
class
ALLOC
>
489
INLINE
const
GraphChange
&
GraphChangesSelector4DiGraph
<
STRUCTURAL_CONSTRAINT
,
490
GRAPH_CHANGES_GENERATOR
,
491
ALLOC
>::
bestChange
() {
492
if
(!
empty
())
493
return
_changes_
[
_change_queue_per_node_
[
_node_queue_
.
top
()].
top
()];
494
else
495
GUM_ERROR
(
NotFound
,
"there exists no graph change applicable"
)
496
}
497
498
499
/// returns the best graph change to examine in the ith queue
500
template
<
typename
STRUCTURAL_CONSTRAINT
,
501
typename
GRAPH_CHANGES_GENERATOR
,
502
template
<
typename
>
503
class
ALLOC
>
504
INLINE
const
GraphChange
&
GraphChangesSelector4DiGraph
<
STRUCTURAL_CONSTRAINT
,
505
GRAPH_CHANGES_GENERATOR
,
506
ALLOC
>::
bestChange
(
const
NodeId
node
) {
507
if
(!
empty
(
node
))
508
return
_changes_
[
_change_queue_per_node_
[
node
].
top
()];
509
else
510
GUM_ERROR
(
NotFound
,
"there exists no graph change applicable"
)
511
}
512
513
514
/// return the score of the best graph change
515
template
<
typename
STRUCTURAL_CONSTRAINT
,
516
typename
GRAPH_CHANGES_GENERATOR
,
517
template
<
typename
>
518
class
ALLOC
>
519
INLINE
double
GraphChangesSelector4DiGraph
<
STRUCTURAL_CONSTRAINT
,
520
GRAPH_CHANGES_GENERATOR
,
521
ALLOC
>::
bestScore
() {
522
if
(!
empty
())
523
return
_change_queue_per_node_
[
_node_queue_
.
top
()].
topPriority
();
524
else
525
GUM_ERROR
(
NotFound
,
"there exists no graph change applicable"
)
526
}
527
528
529
/// return the score of the best graph change in the ith queue
530
template
<
typename
STRUCTURAL_CONSTRAINT
,
531
typename
GRAPH_CHANGES_GENERATOR
,
532
template
<
typename
>
533
class
ALLOC
>
534
INLINE
double
GraphChangesSelector4DiGraph
<
STRUCTURAL_CONSTRAINT
,
535
GRAPH_CHANGES_GENERATOR
,
536
ALLOC
>::
bestScore
(
const
NodeId
node
) {
537
if
(!
empty
(
node
))
538
return
_change_queue_per_node_
[
node
].
topPriority
();
539
else
540
GUM_ERROR
(
NotFound
,
"there exists no graph change applicable"
)
541
}
542
543
544
/// remove the now legal changes from the illegal set
545
template
<
typename
STRUCTURAL_CONSTRAINT
,
546
typename
GRAPH_CHANGES_GENERATOR
,
547
template
<
typename
>
548
class
ALLOC
>
549
void
GraphChangesSelector4DiGraph
<
STRUCTURAL_CONSTRAINT
,
GRAPH_CHANGES_GENERATOR
,
ALLOC
>::
550
_illegal2LegalChanges_
(
Set
<
std
::
size_t
>&
changes_to_recompute
) {
551
for
(
auto
iter
=
_illegal_changes_
.
beginSafe
();
iter
!=
_illegal_changes_
.
endSafe
(); ++
iter
) {
552
if
(
_isChangeValid_
(*
iter
)) {
553
const
GraphChange
&
change
=
_changes_
[*
iter
];
554
if
(
change
.
type
() ==
GraphChangeType
::
ARC_REVERSAL
) {
555
_change_queue_per_node_
[
change
.
node1
()].
insert
(*
iter
,
556
std
::
numeric_limits
<
double
>::
min
());
557
}
558
_change_queue_per_node_
[
change
.
node2
()].
insert
(*
iter
,
559
std
::
numeric_limits
<
double
>::
min
());
560
561
changes_to_recompute
.
insert
(*
iter
);
562
_illegal_changes_
.
erase
(
iter
);
563
}
564
}
565
}
566
567
568
/// finds the changes that are affected by a given node modification
569
template
<
typename
STRUCTURAL_CONSTRAINT
,
570
typename
GRAPH_CHANGES_GENERATOR
,
571
template
<
typename
>
572
class
ALLOC
>
573
void
GraphChangesSelector4DiGraph
<
STRUCTURAL_CONSTRAINT
,
GRAPH_CHANGES_GENERATOR
,
ALLOC
>::
574
_findLegalChangesNeedingUpdate_
(
Set
<
std
::
size_t
>&
changes_to_recompute
,
575
const
NodeId
target_node
) {
576
const
HashTable
<
std
::
size_t
,
Size
>&
changes
577
=
_change_queue_per_node_
[
target_node
].
allValues
();
578
for
(
auto
iter
=
changes
.
cbeginSafe
();
iter
!=
changes
.
cendSafe
(); ++
iter
) {
579
if
(!
changes_to_recompute
.
exists
(
iter
.
key
())) {
580
if
(
_isChangeValid_
(
iter
.
key
())) {
581
changes_to_recompute
.
insert
(
iter
.
key
());
582
}
else
{
583
_invalidateChange_
(
iter
.
key
());
584
}
585
}
586
}
587
}
588
589
590
/// perform the necessary updates of the scores
591
template
<
typename
STRUCTURAL_CONSTRAINT
,
592
typename
GRAPH_CHANGES_GENERATOR
,
593
template
<
typename
>
594
class
ALLOC
>
595
void
GraphChangesSelector4DiGraph
<
STRUCTURAL_CONSTRAINT
,
GRAPH_CHANGES_GENERATOR
,
ALLOC
>::
596
_updateScores_
(
const
Set
<
std
::
size_t
>&
changes_to_recompute
) {
597
Set
<
NodeId
>
modified_nodes
(
changes_to_recompute
.
size
());
598
599
for
(
const
auto
change_index
:
changes_to_recompute
) {
600
const
GraphChange
&
change
=
_changes_
[
change_index
];
601
602
switch
(
change
.
type
()) {
603
case
GraphChangeType
::
ARC_ADDITION
: {
604
// add the arc
605
auto
&
parents
=
_parents_
[
change
.
node2
()];
606
parents
.
push_back
(
change
.
node1
());
607
const
double
delta
608
=
_score_
->
score
(
change
.
node2
(),
parents
) -
_node_current_scores_
[
change
.
node2
()];
609
parents
.
pop_back
();
610
611
// update the score
612
_change_scores_
[
change_index
].
second
=
delta
;
613
614
// update the head queue
615
_change_queue_per_node_
[
change
.
node2
()].
setPriority
(
change_index
,
delta
);
616
// indicate which queue was modified
617
modified_nodes
.
insert
(
change
.
node2
());
618
}
break
;
619
620
case
GraphChangeType
::
ARC_DELETION
: {
621
// remove the arc
622
auto
&
parents
=
_parents_
[
change
.
node2
()];
623
for
(
auto
&
par
:
parents
) {
624
if
(
par
==
change
.
node1
()) {
625
par
= *(
parents
.
rbegin
());
626
parents
.
pop_back
();
627
break
;
628
}
629
}
630
const
double
delta
631
=
_score_
->
score
(
change
.
node2
(),
parents
) -
_node_current_scores_
[
change
.
node2
()];
632
parents
.
push_back
(
change
.
node1
());
633
634
// update the score
635
_change_scores_
[
change_index
].
second
=
delta
;
636
637
// update the head queue
638
_change_queue_per_node_
[
change
.
node2
()].
setPriority
(
change_index
,
delta
);
639
// indicate which queue was modified
640
modified_nodes
.
insert
(
change
.
node2
());
641
}
break
;
642
643
case
GraphChangeType
::
ARC_REVERSAL
: {
644
// remove arc ( node1 -> node2 )
645
auto
&
parents2
=
_parents_
[
change
.
node2
()];
646
for
(
auto
&
par
:
parents2
) {
647
if
(
par
==
change
.
node1
()) {
648
par
= *(
parents2
.
rbegin
());
649
parents2
.
pop_back
();
650
break
;
651
}
652
}
653
654
const
double
delta2
655
=
_score_
->
score
(
change
.
node2
(),
parents2
) -
_node_current_scores_
[
change
.
node2
()];
656
parents2
.
push_back
(
change
.
node1
());
657
658
// add arc ( node2 -> node1 )
659
auto
&
parents1
=
_parents_
[
change
.
node1
()];
660
parents1
.
push_back
(
change
.
node2
());
661
const
double
delta1
662
=
_score_
->
score
(
change
.
node1
(),
parents1
) -
_node_current_scores_
[
change
.
node1
()];
663
parents1
.
pop_back
();
664
665
// update the scores
666
_change_scores_
[
change_index
].
first
=
delta1
;
667
_change_scores_
[
change_index
].
second
=
delta2
;
668
669
// update the queues
670
const
double
delta
=
delta1
+
delta2
;
671
_change_queue_per_node_
[
change
.
node1
()].
setPriority
(
change_index
,
delta
);
672
_change_queue_per_node_
[
change
.
node2
()].
setPriority
(
change_index
,
delta
);
673
674
// indicate which queues were modified
675
modified_nodes
.
insert
(
change
.
node1
());
676
modified_nodes
.
insert
(
change
.
node2
());
677
}
break
;
678
679
default
: {
680
GUM_ERROR
(
NotImplementedYet
,
681
"Method _updateScores_ of GraphChangesSelector4DiGraph "
682
<<
"does not handle yet graph change of type "
<<
change
.
type
());
683
}
684
}
685
}
686
687
// update the node queue
688
for
(
const
auto
node
:
modified_nodes
) {
689
_node_queue_
.
setPriority
(
node
,
690
_change_queue_per_node_
[
node
].
empty
()
691
?
std
::
numeric_limits
<
double
>::
min
()
692
:
_change_queue_per_node_
[
node
].
topPriority
());
693
}
694
}
695
696
697
/// get from the graph change generator a new set of changes
698
template
<
typename
STRUCTURAL_CONSTRAINT
,
699
typename
GRAPH_CHANGES_GENERATOR
,
700
template
<
typename
>
701
class
ALLOC
>
702
void
GraphChangesSelector4DiGraph
<
STRUCTURAL_CONSTRAINT
,
GRAPH_CHANGES_GENERATOR
,
ALLOC
>::
703
_getNewChanges_
() {
704
// ask the graph change generator for all its available changes
705
for
(
const
auto
&
change
: *
_changes_generator_
) {
706
// check that the change does not already exist
707
if
(!
_changes_
.
exists
(
change
)) {
708
// add the new change. To make the addition simple, we put the new
709
// change into the illegal changes set. Afterwards, the applyChange
710
// function will put the legal changes again into the queues
711
_illegal_changes_
.
insert
(
_changes_
.
size
());
712
_changes_
<<
change
;
713
_change_scores_
.
push_back
(
714
std
::
pair
<
double
,
double
>(
std
::
numeric_limits
<
double
>::
min
(),
715
std
::
numeric_limits
<
double
>::
min
()));
716
}
717
}
718
719
// indicate to the generator that we have finished retrieving its changes
720
_changes_generator_
->
notifyGetCompleted
();
721
}
722
723
724
/// indicate to the selector that its best score has been applied
725
template
<
typename
STRUCTURAL_CONSTRAINT
,
726
typename
GRAPH_CHANGES_GENERATOR
,
727
template
<
typename
>
728
class
ALLOC
>
729
void
GraphChangesSelector4DiGraph
<
STRUCTURAL_CONSTRAINT
,
GRAPH_CHANGES_GENERATOR
,
ALLOC
>::
730
applyChange
(
const
GraphChange
&
change
) {
731
// first, we get the index of the change
732
const
std
::
size_t
change_index
=
_changes_
.
pos
(
change
);
733
734
// perform the change
735
Set
<
std
::
size_t
>
changes_to_recompute
;
736
switch
(
change
.
type
()) {
737
case
GraphChangeType
::
ARC_ADDITION
: {
738
// update the current score
739
_node_current_scores_
[
change
.
node2
()] +=
_change_scores_
[
change_index
].
second
;
740
_parents_
[
change
.
node2
()].
push_back
(
change
.
node1
());
741
742
// inform the constraint that the graph has been modified
743
_constraint_
->
modifyGraph
(
static_cast
<
const
ArcAddition
& >(
change
));
744
if
(
reinterpret_cast
<
STRUCTURAL_CONSTRAINT
* >(&(
_changes_generator_
->
constraint
()))
745
!=
_constraint_
) {
746
_changes_generator_
->
constraint
().
modifyGraph
(
747
static_cast
<
const
ArcAddition
& >(
change
));
748
}
749
750
// get new possible changes from the graph change generator
751
// warning: put the next 3 lines before calling _illegal2LegalChanges_
752
_changes_generator_
->
modifyGraph
(
static_cast
<
const
ArcAddition
& >(
change
));
753
_getNewChanges_
();
754
755
// check whether some illegal changes can be put into the valid queues
756
_illegal2LegalChanges_
(
changes_to_recompute
);
757
_invalidateChange_
(
change_index
);
758
_findLegalChangesNeedingUpdate_
(
changes_to_recompute
,
change
.
node2
());
759
_updateScores_
(
changes_to_recompute
);
760
}
break
;
761
762
case
GraphChangeType
::
ARC_DELETION
: {
763
// update the current score
764
_node_current_scores_
[
change
.
node2
()] +=
_change_scores_
[
change_index
].
second
;
765
auto
&
parents
=
_parents_
[
change
.
node2
()];
766
for
(
auto
&
par
:
parents
) {
767
if
(
par
==
change
.
node1
()) {
768
par
= *(
parents
.
rbegin
());
769
parents
.
pop_back
();
770
break
;
771
}
772
}
773
774
// inform the constraint that the graph has been modified
775
_constraint_
->
modifyGraph
(
static_cast
<
const
ArcDeletion
& >(
change
));
776
if
(
reinterpret_cast
<
STRUCTURAL_CONSTRAINT
* >(&(
_changes_generator_
->
constraint
()))
777
!=
_constraint_
) {
778
_changes_generator_
->
constraint
().
modifyGraph
(
779
static_cast
<
const
ArcDeletion
& >(
change
));
780
}
781
782
// get new possible changes from the graph change generator
783
// warning: put the next 3 lines before calling _illegal2LegalChanges_
784
_changes_generator_
->
modifyGraph
(
static_cast
<
const
ArcDeletion
& >(
change
));
785
_getNewChanges_
();
786
787
// check whether some illegal changes can be put into the valid queues
788
_illegal2LegalChanges_
(
changes_to_recompute
);
789
_invalidateChange_
(
change_index
);
790
_findLegalChangesNeedingUpdate_
(
changes_to_recompute
,
change
.
node2
());
791
_updateScores_
(
changes_to_recompute
);
792
}
break
;
793
794
case
GraphChangeType
::
ARC_REVERSAL
: {
795
// update the current score
796
_node_current_scores_
[
change
.
node1
()] +=
_change_scores_
[
change_index
].
first
;
797
_node_current_scores_
[
change
.
node2
()] +=
_change_scores_
[
change_index
].
second
;
798
_parents_
[
change
.
node1
()].
push_back
(
change
.
node2
());
799
auto
&
parents
=
_parents_
[
change
.
node2
()];
800
for
(
auto
&
par
:
parents
) {
801
if
(
par
==
change
.
node1
()) {
802
par
= *(
parents
.
rbegin
());
803
parents
.
pop_back
();
804
break
;
805
}
806
}
807
808
// inform the constraint that the graph has been modified
809
_constraint_
->
modifyGraph
(
static_cast
<
const
ArcReversal
& >(
change
));
810
if
(
reinterpret_cast
<
STRUCTURAL_CONSTRAINT
* >(&(
_changes_generator_
->
constraint
()))
811
!=
_constraint_
) {
812
_changes_generator_
->
constraint
().
modifyGraph
(
813
static_cast
<
const
ArcReversal
& >(
change
));
814
}
815
816
// get new possible changes from the graph change generator
817
// warning: put the next 3 lines before calling _illegal2LegalChanges_
818
_changes_generator_
->
modifyGraph
(
static_cast
<
const
ArcReversal
& >(
change
));
819
_getNewChanges_
();
820
821
// check whether some illegal changes can be put into the valid queues
822
_illegal2LegalChanges_
(
changes_to_recompute
);
823
_invalidateChange_
(
change_index
);
824
_findLegalChangesNeedingUpdate_
(
changes_to_recompute
,
change
.
node1
());
825
_findLegalChangesNeedingUpdate_
(
changes_to_recompute
,
change
.
node2
());
826
_updateScores_
(
changes_to_recompute
);
827
}
break
;
828
829
default
:
830
GUM_ERROR
(
NotImplementedYet
,
831
"Method applyChange of GraphChangesSelector4DiGraph "
832
<<
"does not handle yet graph change of type "
<<
change
.
type
());
833
}
834
835
_queues_valid_
=
false
;
836
}
837
838
839
/// applies several changes at a time
840
template
<
typename
STRUCTURAL_CONSTRAINT
,
841
typename
GRAPH_CHANGES_GENERATOR
,
842
template
<
typename
>
843
class
ALLOC
>
844
void
GraphChangesSelector4DiGraph
<
STRUCTURAL_CONSTRAINT
,
GRAPH_CHANGES_GENERATOR
,
ALLOC
>::
845
applyChangeWithoutScoreUpdate
(
const
GraphChange
&
change
) {
846
// first, we get the index of the change
847
const
std
::
size_t
change_index
=
_changes_
.
pos
(
change
);
848
849
// perform the change
850
switch
(
change
.
type
()) {
851
case
GraphChangeType
::
ARC_ADDITION
: {
852
// update the current score
853
_node_current_scores_
[
change
.
node2
()] +=
_change_scores_
[
change_index
].
second
;
854
_parents_
[
change
.
node2
()].
push_back
(
change
.
node1
());
855
856
// inform the constraint that the graph has been modified
857
_constraint_
->
modifyGraph
(
static_cast
<
const
ArcAddition
& >(
change
));
858
if
(
reinterpret_cast
<
STRUCTURAL_CONSTRAINT
* >(&(
_changes_generator_
->
constraint
()))
859
!=
_constraint_
) {
860
_changes_generator_
->
constraint
().
modifyGraph
(
861
static_cast
<
const
ArcAddition
& >(
change
));
862
}
863
864
// get new possible changes from the graph change generator
865
// warning: put the next 3 lines before calling _illegal2LegalChanges_
866
_changes_generator_
->
modifyGraph
(
static_cast
<
const
ArcAddition
& >(
change
));
867
_getNewChanges_
();
868
869
// indicate that we have just applied the change
870
_invalidateChange_
(
change_index
);
871
872
// indicate that the queue to which the change belongs needs be
873
// updated
874
_queues_to_update_
.
insert
(
change
.
node2
());
875
}
break
;
876
877
case
GraphChangeType
::
ARC_DELETION
: {
878
// update the current score
879
_node_current_scores_
[
change
.
node2
()] +=
_change_scores_
[
change_index
].
second
;
880
auto
&
parents
=
_parents_
[
change
.
node2
()];
881
for
(
auto
&
par
:
parents
) {
882
if
(
par
==
change
.
node1
()) {
883
par
= *(
parents
.
rbegin
());
884
parents
.
pop_back
();
885
break
;
886
}
887
}
888
889
// inform the constraint that the graph has been modified
890
_constraint_
->
modifyGraph
(
static_cast
<
const
ArcDeletion
& >(
change
));
891
if
(
reinterpret_cast
<
STRUCTURAL_CONSTRAINT
* >(&(
_changes_generator_
->
constraint
()))
892
!=
_constraint_
) {
893
_changes_generator_
->
constraint
().
modifyGraph
(
894
static_cast
<
const
ArcDeletion
& >(
change
));
895
}
896
897
// get new possible changes from the graph change generator
898
// warning: put the next 3 lines before calling _illegal2LegalChanges_
899
_changes_generator_
->
modifyGraph
(
static_cast
<
const
ArcDeletion
& >(
change
));
900
_getNewChanges_
();
901
902
// indicate that we have just applied the change
903
_invalidateChange_
(
change_index
);
904
905
// indicate that the queue to which the change belongs needs be
906
// updated
907
_queues_to_update_
.
insert
(
change
.
node2
());
908
}
break
;
909
910
case
GraphChangeType
::
ARC_REVERSAL
: {
911
// update the current score
912
_node_current_scores_
[
change
.
node1
()] +=
_change_scores_
[
change_index
].
first
;
913
_node_current_scores_
[
change
.
node2
()] +=
_change_scores_
[
change_index
].
second
;
914
_parents_
[
change
.
node1
()].
push_back
(
change
.
node2
());
915
auto
&
parents
=
_parents_
[
change
.
node2
()];
916
for
(
auto
&
par
:
parents
) {
917
if
(
par
==
change
.
node1
()) {
918
par
= *(
parents
.
rbegin
());
919
parents
.
pop_back
();
920
break
;
921
}
922
}
923
924
// inform the constraint that the graph has been modified
925
_constraint_
->
modifyGraph
(
static_cast
<
const
ArcReversal
& >(
change
));
926
if
(
reinterpret_cast
<
STRUCTURAL_CONSTRAINT
* >(&(
_changes_generator_
->
constraint
()))
927
!=
_constraint_
) {
928
_changes_generator_
->
constraint
().
modifyGraph
(
929
static_cast
<
const
ArcReversal
& >(
change
));
930
}
931
932
// get new possible changes from the graph change generator
933
// warning: put the next 3 lines before calling _illegal2LegalChanges_
934
_changes_generator_
->
modifyGraph
(
static_cast
<
const
ArcReversal
& >(
change
));
935
_getNewChanges_
();
936
937
// indicate that we have just applied the change
938
_invalidateChange_
(
change_index
);
939
940
// indicate that the queue to which the change belongs needs be
941
// updated
942
_queues_to_update_
.
insert
(
change
.
node1
());
943
_queues_to_update_
.
insert
(
change
.
node2
());
944
}
break
;
945
946
default
:
947
GUM_ERROR
(
NotImplementedYet
,
948
"Method applyChangeWithoutScoreUpdate of "
949
<<
"GraphChangesSelector4DiGraph "
950
<<
"does not handle yet graph change of type "
<<
change
.
type
());
951
}
952
}
953
954
955
/// applies several changes at a time
956
template
<
typename
STRUCTURAL_CONSTRAINT
,
957
typename
GRAPH_CHANGES_GENERATOR
,
958
template
<
typename
>
959
class
ALLOC
>
960
void
GraphChangesSelector4DiGraph
<
STRUCTURAL_CONSTRAINT
,
GRAPH_CHANGES_GENERATOR
,
ALLOC
>::
961
updateScoresAfterAppliedChanges
() {
962
// determine which changes in the illegal set are now legal
963
Set
<
std
::
size_t
>
new_legal_changes
;
964
for
(
auto
iter
=
_illegal_changes_
.
beginSafe
();
iter
!=
_illegal_changes_
.
endSafe
(); ++
iter
) {
965
if
(
_isChangeValid_
(*
iter
)) {
966
new_legal_changes
.
insert
(*
iter
);
967
_illegal_changes_
.
erase
(
iter
);
968
}
969
}
970
971
// update the scores that need be updated
972
Set
<
std
::
size_t
>
changes_to_recompute
;
973
for
(
const
auto
&
node
:
_queues_to_update_
) {
974
_findLegalChangesNeedingUpdate_
(
changes_to_recompute
,
node
);
975
}
976
_queues_to_update_
.
clear
();
977
978
// put the previously illegal changes that are now legal into their queues
979
for
(
const
auto
change_index
:
new_legal_changes
) {
980
const
GraphChange
&
change
=
_changes_
[
change_index
];
981
if
(
change
.
type
() ==
GraphChangeType
::
ARC_REVERSAL
) {
982
_change_queue_per_node_
[
change
.
node1
()].
insert
(
change_index
,
983
std
::
numeric_limits
<
double
>::
min
());
984
}
985
_change_queue_per_node_
[
change
.
node2
()].
insert
(
change_index
,
986
std
::
numeric_limits
<
double
>::
min
());
987
988
changes_to_recompute
.
insert
(
change_index
);
989
}
990
991
// compute the scores that we need
992
_updateScores_
(
changes_to_recompute
);
993
994
_queues_valid_
=
false
;
995
}
996
997
998
/// returns the set of queues sorted by decreasing top priority
999
template
<
typename
STRUCTURAL_CONSTRAINT
,
1000
typename
GRAPH_CHANGES_GENERATOR
,
1001
template
<
typename
>
1002
class
ALLOC
>
1003
std
::
vector
<
std
::
pair
<
NodeId
,
double
> >
1004
GraphChangesSelector4DiGraph
<
STRUCTURAL_CONSTRAINT
,
GRAPH_CHANGES_GENERATOR
,
ALLOC
>::
1005
nodesSortedByBestScore
()
const
{
1006
std
::
vector
<
std
::
pair
<
NodeId
,
double
> >
result
(
_node_queue_
.
size
());
1007
for
(
std
::
size_t
i
=
std
::
size_t
(0);
i
<
_node_queue_
.
size
(); ++
i
) {
1008
result
[
i
].
first
=
_node_queue_
[
i
];
1009
result
[
i
].
second
=
_node_queue_
.
priorityByPos
(
i
);
1010
}
1011
1012
std
::
sort
(
result
.
begin
(),
1013
result
.
end
(),
1014
[](
const
std
::
pair
<
NodeId
,
double
>&
a
,
1015
const
std
::
pair
<
NodeId
,
double
>&
b
) ->
bool
{
return
a
.
second
>
b
.
second
; });
1016
1017
return
result
;
1018
}
1019
1020
1021
/// returns the set of queues sorted by decreasing top priority
1022
template
<
typename
STRUCTURAL_CONSTRAINT
,
1023
typename
GRAPH_CHANGES_GENERATOR
,
1024
template
<
typename
>
1025
class
ALLOC
>
1026
std
::
vector
<
std
::
pair
<
NodeId
,
double
> >
1027
GraphChangesSelector4DiGraph
<
STRUCTURAL_CONSTRAINT
,
GRAPH_CHANGES_GENERATOR
,
ALLOC
>::
1028
nodesUnsortedWithScore
()
const
{
1029
std
::
vector
<
std
::
pair
<
NodeId
,
double
> >
result
(
_node_queue_
.
size
());
1030
for
(
std
::
size_t
i
=
std
::
size_t
(0);
i
<
_node_queue_
.
size
(); ++
i
) {
1031
result
[
i
].
first
=
_node_queue_
[
i
];
1032
result
[
i
].
second
=
_node_queue_
.
priorityByPos
(
i
);
1033
}
1034
1035
return
result
;
1036
}
1037
1038
1039
/// returns the generator used by the selector
1040
template
<
typename
STRUCTURAL_CONSTRAINT
,
1041
typename
GRAPH_CHANGES_GENERATOR
,
1042
template
<
typename
>
1043
class
ALLOC
>
1044
INLINE
typename
GraphChangesSelector4DiGraph
<
STRUCTURAL_CONSTRAINT
,
1045
GRAPH_CHANGES_GENERATOR
,
1046
ALLOC
>::
GeneratorType
&
1047
GraphChangesSelector4DiGraph
<
STRUCTURAL_CONSTRAINT
,
GRAPH_CHANGES_GENERATOR
,
ALLOC
>::
1048
graphChangeGenerator
()
const
noexcept
{
1049
return
*
_changes_generator_
;
1050
}
1051
1052
1053
}
/* namespace learning */
1054
1055
}
/* namespace gum */
1056
1057
#
endif
/* DOXYGEN_SHOULD_SKIP_THIS */
gum::Set::emplace
INLINE void emplace(Args &&... args)
Definition:
set_tpl.h:643
gum::learning::genericBNLearner::Database::Database
Database(const std::string &filename, const BayesNet< GUM_SCALAR > &bn, const std::vector< std::string > &missing_symbols)
Definition:
genericBNLearner_tpl.h:31