aGrUM
0.20.2
a C++ library for (probabilistic) graphical models
multiPriorityQueue_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 Template implementations of multi priority queues.
25
*
26
* @author Christophe GONZALES(@AMU) and Pierre-Henri WUILLEMIN(@LIP6)
27
*/
28
29
// to help IDE parser
30
#
include
<
agrum
/
tools
/
core
/
multiPriorityQueue
.
h
>
31
32
namespace
gum
{
33
34
// basic constructor
35
template
<
typename
Val,
typename
Priority,
typename
Cmp,
typename
Alloc >
36
MultiPriorityQueue< Val, Priority, Cmp, Alloc >::MultiPriorityQueue(
37
Cmp compare,
38
Size capacity) :
39
indices__(capacity >> 1,
true
,
false
),
40
cmp__(compare) {
41
heap__.reserve(capacity);
42
43
// for debugging purposes
44
GUM_CONSTRUCTOR(MultiPriorityQueue);
45
}
46
47
// initializer list constructor
48
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
49
MultiPriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
MultiPriorityQueue
(
50
std
::
initializer_list
<
std
::
pair
<
Val
,
Priority
> >
list
) :
51
indices__
(
Size
(
list
.
size
()) / 2,
true
,
false
) {
52
// fill the queue
53
heap__
.
reserve
(
list
.
size
());
54
for
(
const
auto
&
elt
:
list
) {
55
insert
(
elt
.
first
,
elt
.
second
);
56
}
57
58
// for debugging purposes
59
GUM_CONSTRUCTOR
(
MultiPriorityQueue
);
60
}
61
62
// copy constructor
63
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
64
MultiPriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
MultiPriorityQueue
(
65
const
MultiPriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>&
from
) :
66
heap__
(
from
.
heap__
),
67
indices__
(
from
.
indices__
),
nb_elements__
(
from
.
nb_elements__
),
68
cmp__
(
from
.
cmp__
) {
69
// for debugging purposes
70
GUM_CONS_CPY
(
MultiPriorityQueue
);
71
72
// fill the heap structure
73
for
(
const
auto
&
val_and_index
:
indices__
) {
74
const
Val
*
val
= &(
val_and_index
.
first
);
75
const
std
::
vector
<
Size
>&
vect
=
val_and_index
.
second
;
76
for
(
auto
index
:
vect
) {
77
heap__
[
index
].
second
=
val
;
78
}
79
}
80
}
81
82
// generalized copy constructor
83
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
84
template
<
typename
OtherAlloc
>
85
MultiPriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
MultiPriorityQueue
(
86
const
MultiPriorityQueue
<
Val
,
Priority
,
Cmp
,
OtherAlloc
>&
from
) :
87
indices__
(
from
.
indices__
),
88
nb_elements__
(
from
.
nb_elements__
),
cmp__
(
from
.
cmp__
) {
89
// for debugging purposes
90
GUM_CONS_CPY
(
MultiPriorityQueue
);
91
92
// fill the heap structure
93
if
(
nb_elements__
) {
94
heap__
.
reserve
(
from
.
heap__
.
size
());
95
for
(
const
auto
&
elt
:
from
.
heap__
) {
96
heap__
.
push_back
(
elt
);
97
}
98
for
(
const
auto
&
val_and_index
:
indices__
) {
99
const
Val
*
val
= &(
val_and_index
.
first
);
100
const
std
::
vector
<
Size
>&
vect
=
val_and_index
.
second
;
101
for
(
auto
index
:
vect
) {
102
heap__
[
index
].
second
=
val
;
103
}
104
}
105
}
106
}
107
108
// move constructor
109
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
110
MultiPriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
MultiPriorityQueue
(
111
MultiPriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>&&
from
) :
112
heap__
(
std
::
move
(
from
.
heap__
)),
113
indices__
(
std
::
move
(
from
.
indices__
)),
114
nb_elements__
(
std
::
move
(
from
.
nb_elements__
)),
cmp__
(
std
::
move
(
from
.
cmp__
)) {
115
// for debugging purposes
116
GUM_CONS_MOV
(
MultiPriorityQueue
);
117
}
118
119
// destructor
120
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
121
MultiPriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::~
MultiPriorityQueue
() {
122
// for debugging purposes
123
GUM_DESTRUCTOR
(
MultiPriorityQueue
);
124
}
125
126
// copy operator
127
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
128
MultiPriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>&
129
MultiPriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
operator
=(
130
const
MultiPriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>&
from
) {
131
// for debugging purposes
132
GUM_OP_CPY
(
MultiPriorityQueue
);
133
134
try
{
135
// set the comprison function
136
cmp__
=
from
.
cmp__
;
137
138
// copy the indices and the heap
139
indices__
=
from
.
indices__
;
140
heap__
=
from
.
heap__
;
141
nb_elements__
=
from
.
nb_elements__
;
142
143
// restore the link between indices__ and heap__
144
for
(
const
auto
&
val_and_index
:
indices__
) {
145
const
Val
*
val
= &(
val_and_index
.
first
);
146
const
std
::
vector
<
Size
>&
vect
=
val_and_index
.
second
;
147
for
(
auto
index
:
vect
) {
148
heap__
[
index
].
second
=
val
;
149
}
150
}
151
}
catch
(...) {
152
heap__
.
clear
();
153
indices__
.
clear
();
154
nb_elements__
= 0;
155
156
throw
;
157
}
158
159
return
*
this
;
160
}
161
162
// generalized copy operator
163
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
164
template
<
typename
OtherAlloc
>
165
MultiPriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>&
166
MultiPriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
operator
=(
167
const
MultiPriorityQueue
<
Val
,
Priority
,
Cmp
,
OtherAlloc
>&
from
) {
168
// for debugging purposes
169
GUM_OP_CPY
(
MultiPriorityQueue
);
170
171
try
{
172
// set the comprison function
173
cmp__
=
from
.
cmp__
;
174
175
// copy the indices and the heap
176
indices__
=
from
.
indices__
;
177
nb_elements__
=
from
.
nb_elements__
;
178
179
// restore the link between indices__ and heap__
180
heap__
.
clear
();
181
heap__
.
reserve
(
from
.
heap__
.
size
());
182
for
(
const
auto
&
elt
:
from
.
heap__
) {
183
heap__
.
push_back
(
elt
);
184
}
185
for
(
const
auto
&
val_and_index
:
indices__
) {
186
const
Val
*
val
= &(
val_and_index
.
first
);
187
const
std
::
vector
<
Size
>&
vect
=
val_and_index
.
second
;
188
for
(
auto
index
:
vect
) {
189
heap__
[
index
].
second
=
val
;
190
}
191
}
192
}
catch
(...) {
193
heap__
.
clear
();
194
indices__
.
clear
();
195
nb_elements__
= 0;
196
197
throw
;
198
}
199
200
return
*
this
;
201
}
202
203
// move operator
204
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
205
MultiPriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>&
206
MultiPriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
operator
=(
207
MultiPriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>&&
from
) {
208
// avoid self assignment
209
if
(
this
!= &
from
) {
210
// for debugging purposes
211
GUM_OP_MOV
(
MultiPriorityQueue
);
212
213
cmp__
=
std
::
move
(
from
.
cmp__
);
214
indices__
=
std
::
move
(
from
.
indices__
);
215
heap__
=
std
::
move
(
from
.
heap__
);
216
nb_elements__
=
std
::
move
(
from
.
nb_elements__
);
217
}
218
219
return
*
this
;
220
}
221
222
// returns the element at the top of the priority queue
223
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
224
INLINE
const
Val
&
MultiPriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
top
()
const
{
225
if
(!
nb_elements__
) {
GUM_ERROR
(
NotFound
,
"empty priority queue"
); }
226
227
return
*(
heap__
[0].
second
);
228
}
229
230
// returns the priority of the top element
231
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
232
INLINE
const
Priority
&
233
MultiPriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
topPriority
()
const
{
234
if
(!
nb_elements__
) {
GUM_ERROR
(
NotFound
,
"empty priority queue"
); }
235
236
return
heap__
[0].
first
;
237
}
238
239
// returns the number of elements in the priority queue
240
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
241
INLINE
Size
242
MultiPriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
size
()
const
noexcept
{
243
return
nb_elements__
;
244
}
245
246
// return the size of the array storing the priority queue
247
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
248
INLINE
Size
249
MultiPriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
capacity
()
const
noexcept
{
250
return
Size
(
heap__
.
capacity
());
251
}
252
253
// changes the size of the array storing the priority queue
254
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
255
INLINE
void
256
MultiPriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
resize
(
Size
new_size
) {
257
if
(
new_size
<
nb_elements__
)
return
;
258
259
heap__
.
reserve
(
new_size
);
260
indices__
.
resize
(
new_size
/ 2);
261
}
262
263
// removes all the elements from the queue
264
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
265
void
MultiPriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
clear
() {
266
nb_elements__
= 0;
267
heap__
.
clear
();
268
indices__
.
clear
();
269
}
270
271
// removes the element at index elt from the priority queue
272
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
273
void
MultiPriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
eraseByPos
(
Size
index
) {
274
if
(
index
>=
nb_elements__
)
return
;
275
276
// remove the element from the hashtable
277
const
Val
&
del_val
= *(
heap__
[
index
].
second
);
278
std
::
vector
<
Size
>&
vect_index
=
indices__
[
del_val
];
279
if
(
vect_index
.
size
() == 1)
280
indices__
.
erase
(
del_val
);
281
else
{
282
for
(
auto
&
v_index
:
vect_index
) {
283
if
(
v_index
==
index
) {
284
v_index
=
vect_index
.
back
();
285
vect_index
.
pop_back
();
286
break
;
287
}
288
}
289
}
290
291
// put the last element at the "index" location
292
std
::
pair
<
Priority
,
const
Val
* >
last
=
std
::
move
(
heap__
.
back
());
293
heap__
.
pop_back
();
294
--
nb_elements__
;
295
296
if
(!
nb_elements__
|| (
index
==
nb_elements__
))
return
;
297
298
// restore the heap property
299
Size
i
=
index
;
300
301
for
(
Size
j
= (
index
<< 1) + 1;
j
<
nb_elements__
;
i
=
j
,
j
= (
j
<< 1) + 1) {
302
// let j be the max child
303
if
((
j
+ 1 <
nb_elements__
) &&
cmp__
(
heap__
[
j
+ 1].
first
,
heap__
[
j
].
first
))
304
++
j
;
305
306
// if "last" is lower than heap[j], "last" must be stored at index i
307
if
(
cmp__
(
last
.
first
,
heap__
[
j
].
first
))
break
;
308
309
// else pull up the jth node
310
heap__
[
i
] =
std
::
move
(
heap__
[
j
]);
311
std
::
vector
<
Size
>&
vect_index
=
indices__
[*(
heap__
[
i
].
second
)];
312
for
(
auto
&
v_index
:
vect_index
) {
313
if
(
v_index
==
j
) {
314
v_index
=
i
;
315
break
;
316
}
317
}
318
}
319
320
// put "last" back into the heap
321
heap__
[
i
] =
std
::
move
(
last
);
322
std
::
vector
<
Size
>&
last_indices
=
indices__
[*(
heap__
[
i
].
second
)];
323
for
(
auto
&
v_index
:
last_indices
) {
324
if
(
v_index
==
nb_elements__
) {
325
v_index
=
i
;
326
break
;
327
}
328
}
329
}
330
331
// removes a given element from the priority queue (but does not return it)
332
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
333
INLINE
void
334
MultiPriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
erase
(
const
Val
&
val
) {
335
try
{
336
eraseByPos
(
indices__
[
val
][0]);
337
}
catch
(
NotFound
&) {}
338
}
339
340
// removes the top of the priority queue (but does not return it)
341
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
342
INLINE
void
MultiPriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
eraseTop
() {
343
eraseByPos
(0);
344
}
345
346
// removes the top element from the priority queue and return it
347
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
348
INLINE
Val
MultiPriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
pop
() {
349
if
(!
nb_elements__
) {
GUM_ERROR
(
NotFound
,
"empty priority queue"
); }
350
351
Val
v
= *(
heap__
[0].
second
);
352
eraseByPos
(0);
353
354
return
v
;
355
}
356
357
// returns a hashtable the keys of which are the values stored in the queue
358
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
359
INLINE
const
HashTable
<
Val
,
std
::
vector
<
Size
> >&
360
MultiPriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
allValues
()
const
{
361
return
reinterpret_cast
<
const
HashTable
<
Val
,
std
::
vector
<
Size
> >& >(
362
indices__
);
363
}
364
365
// inserts a new (a copy) element in the priority queue
366
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
367
Size
MultiPriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
insert
(
368
const
Val
&
val
,
369
const
Priority
&
priority
) {
370
// create the entry in the indices hashtable
371
const
Val
*
new_val
;
372
std
::
vector
<
Size
>*
new_vect
;
373
if
(!
indices__
.
exists
(
val
)) {
374
auto
&
new_elt
=
indices__
.
insert
(
val
,
std
::
vector
<
Size
>());
375
new_val
= &(
new_elt
.
first
);
376
new_vect
= &(
new_elt
.
second
);
377
}
else
{
378
new_val
= &(
indices__
.
key
(
val
));
379
new_vect
= &(
indices__
[
val
]);
380
}
381
382
try
{
383
new_vect
->
push_back
(0);
384
}
catch
(...) {
385
if
(
new_vect
->
empty
()) {
indices__
.
erase
(
val
); }
386
throw
;
387
}
388
389
try
{
390
heap__
.
push_back
(
std
::
pair
<
Priority
,
const
Val
* >(
priority
,
new_val
));
391
}
catch
(...) {
392
if
(
new_vect
->
size
() == 1) {
indices__
.
erase
(
val
); }
393
throw
;
394
}
395
396
std
::
pair
<
Priority
,
const
Val
* >
new_heap_val
397
=
std
::
move
(
heap__
[
nb_elements__
]);
398
++
nb_elements__
;
399
400
// restore the heap property
401
Size
i
=
nb_elements__
- 1;
402
403
for
(
Size
j
= (
i
- 1) >> 1;
i
&&
cmp__
(
new_heap_val
.
first
,
heap__
[
j
].
first
);
404
i
=
j
,
j
= (
j
- 1) >> 1) {
405
heap__
[
i
] =
std
::
move
(
heap__
[
j
]);
406
std
::
vector
<
Size
>&
vect_index
=
indices__
[*(
heap__
[
i
].
second
)];
407
for
(
auto
&
index
:
vect_index
) {
408
if
(
index
==
j
) {
409
index
=
i
;
410
break
;
411
}
412
}
413
}
414
415
// put the new bucket into the heap
416
heap__
[
i
].
first
=
std
::
move
(
new_heap_val
.
first
);
417
heap__
[
i
].
second
=
new_val
;
418
new_vect
->
back
() =
i
;
419
420
return
i
;
421
}
422
423
// inserts a new (a copy) element in the priority queue
424
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
425
Size
426
MultiPriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
insert
(
Val
&&
val
,
427
Priority
&&
priority
) {
428
// create the entry in the indices hashtable
429
const
Val
*
new_val
;
430
std
::
vector
<
Size
>*
new_vect
;
431
if
(!
indices__
.
exists
(
val
)) {
432
auto
&
new_elt
=
indices__
.
insert
(
std
::
move
(
val
),
std
::
vector
<
Size
>());
433
new_val
= &(
new_elt
.
first
);
434
new_vect
= &(
new_elt
.
second
);
435
}
else
{
436
new_val
= &(
indices__
.
key
(
val
));
437
new_vect
= &(
indices__
[
val
]);
438
}
439
440
try
{
441
new_vect
->
push_back
(0);
442
}
catch
(...) {
443
if
(
new_vect
->
empty
()) {
indices__
.
erase
(*
new_val
); }
444
throw
;
445
}
446
447
try
{
448
heap__
.
push_back
(
449
std
::
pair
<
Priority
,
const
Val
* >(
std
::
move
(
priority
),
new_val
));
450
}
catch
(...) {
451
if
(
new_vect
->
size
() == 1) {
indices__
.
erase
(*
new_val
); }
452
throw
;
453
}
454
455
std
::
pair
<
Priority
,
const
Val
* >
new_heap_val
456
=
std
::
move
(
heap__
[
nb_elements__
]);
457
++
nb_elements__
;
458
459
// restore the heap property
460
Size
i
=
nb_elements__
- 1;
461
462
for
(
Size
j
= (
i
- 1) >> 1;
i
&&
cmp__
(
new_heap_val
.
first
,
heap__
[
j
].
first
);
463
i
=
j
,
j
= (
j
- 1) >> 1) {
464
heap__
[
i
] =
std
::
move
(
heap__
[
j
]);
465
std
::
vector
<
Size
>&
vect_index
=
indices__
[*(
heap__
[
i
].
second
)];
466
for
(
auto
&
index
:
vect_index
) {
467
if
(
index
==
j
) {
468
index
=
i
;
469
break
;
470
}
471
}
472
}
473
474
// put the new bucket into the heap
475
heap__
[
i
].
first
=
std
::
move
(
new_heap_val
.
first
);
476
heap__
[
i
].
second
=
new_val
;
477
new_vect
->
back
() =
i
;
478
479
return
i
;
480
}
481
482
// emplace a new element into the priority queue
483
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
484
template
<
typename
...
Args
>
485
INLINE
Size
486
MultiPriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
emplace
(
Args
&&...
args
) {
487
std
::
pair
<
Val
,
Priority
>
new_elt
488
=
std
::
make_pair
<
Val
,
Priority
>(
std
::
forward
<
Args
>(
args
)...);
489
return
insert
(
std
::
move
(
new_elt
.
first
),
std
::
move
(
new_elt
.
second
));
490
}
491
492
// indicates whether the priority queue is empty
493
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
494
INLINE
bool
495
MultiPriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
empty
()
const
noexcept
{
496
return
(
nb_elements__
== 0);
497
}
498
499
// indicates whether the priority queue contains a given value
500
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
501
INLINE
bool
MultiPriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
contains
(
502
const
Val
&
val
)
const
{
503
return
indices__
.
exists
(
val
);
504
}
505
506
// returns the element at position "index" in the priority queue
507
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
508
INLINE
const
Val
&
MultiPriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
operator
[](
509
Size
index
)
const
{
510
if
(
index
>=
nb_elements__
) {
511
GUM_ERROR
(
NotFound
,
"not enough elements in the MultiPriorityQueue"
);
512
}
513
514
return
*(
heap__
[
index
].
second
);
515
}
516
517
// displays the content of the queue
518
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
519
std
::
string
MultiPriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
toString
()
const
{
520
bool
deja
=
false
;
521
std
::
stringstream
stream
;
522
stream
<<
"["
;
523
524
for
(
Size
i
= 0;
i
!=
nb_elements__
; ++
i
,
deja
=
true
) {
525
if
(
deja
)
stream
<<
" , "
;
526
527
stream
<<
"("
<<
heap__
[
i
].
first
<<
" , "
<< *(
heap__
[
i
].
second
) <<
")"
;
528
}
529
530
stream
<<
"]"
;
531
532
return
stream
.
str
();
533
}
534
535
// changes the size of the internal structure storing the priority queue
536
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
537
Size
MultiPriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
setPriorityByPos
(
538
Size
index
,
539
const
Priority
&
new_priority
) {
540
// check whether the element the priority of which should be changed exists
541
if
(
index
>=
nb_elements__
) {
542
GUM_ERROR
(
NotFound
,
"not enough elements in the MultiPriorityQueue"
);
543
}
544
545
// get the element itself
546
const
Val
*
val
=
heap__
[
index
].
second
;
547
548
// restore the heap property
549
Size
i
=
index
;
550
551
// move val upward if needed
552
for
(
Size
j
= (
i
- 1) >> 1;
i
&&
cmp__
(
new_priority
,
heap__
[
j
].
first
);
553
i
=
j
,
j
= (
j
- 1) >> 1) {
554
heap__
[
i
] =
std
::
move
(
heap__
[
j
]);
555
std
::
vector
<
Size
>&
vect_index
=
indices__
[*(
heap__
[
i
].
second
)];
556
for
(
auto
&
idx
:
vect_index
) {
557
if
(
idx
==
j
) {
558
idx
=
i
;
559
break
;
560
}
561
}
562
}
563
564
// move val downward if needed
565
for
(
Size
j
= (
i
<< 1) + 1;
j
<
nb_elements__
;
i
=
j
,
j
= (
j
<< 1) + 1) {
566
// let j be the max child
567
if
((
j
+ 1 <
nb_elements__
) &&
cmp__
(
heap__
[
j
+ 1].
first
,
heap__
[
j
].
first
))
568
++
j
;
569
570
// if "val" is lower than heap[j], "val" must be stored at index i
571
if
(
cmp__
(
new_priority
,
heap__
[
j
].
first
))
break
;
572
573
// else pull up the jth node
574
heap__
[
i
] =
std
::
move
(
heap__
[
j
]);
575
std
::
vector
<
Size
>&
vect_index
=
indices__
[*(
heap__
[
i
].
second
)];
576
for
(
auto
&
idx
:
vect_index
) {
577
if
(
idx
==
j
) {
578
idx
=
i
;
579
break
;
580
}
581
}
582
}
583
584
// update the index of val
585
heap__
[
i
].
first
=
new_priority
;
586
heap__
[
i
].
second
=
val
;
587
std
::
vector
<
Size
>&
vect_index
=
indices__
[*(
heap__
[
i
].
second
)];
588
for
(
auto
&
idx
:
vect_index
) {
589
if
(
idx
==
index
) {
590
idx
=
i
;
591
break
;
592
}
593
}
594
595
return
i
;
596
}
597
598
// changes the size of the internal structure storing the priority queue
599
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
600
Size
MultiPriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
setPriorityByPos
(
601
Size
index
,
602
Priority
&&
new_priority
) {
603
// check whether the element the priority of which should be changed exists
604
if
(
index
>=
nb_elements__
) {
605
GUM_ERROR
(
NotFound
,
"not enough elements in the MultiPriorityQueue"
);
606
}
607
608
// get the element itself
609
const
Val
*
val
=
heap__
[
index
].
second
;
610
611
// restore the heap property
612
Size
i
=
index
;
613
614
// move val upward if needed
615
for
(
Size
j
= (
i
- 1) >> 1;
i
&&
cmp__
(
new_priority
,
heap__
[
j
].
first
);
616
i
=
j
,
j
= (
j
- 1) >> 1) {
617
heap__
[
i
] =
std
::
move
(
heap__
[
j
]);
618
std
::
vector
<
Size
>&
vect_index
=
indices__
[*(
heap__
[
i
].
second
)];
619
for
(
auto
&
idx
:
vect_index
) {
620
if
(
idx
==
j
) {
621
idx
=
i
;
622
break
;
623
}
624
}
625
}
626
627
// move val downward if needed
628
for
(
Size
j
= (
i
<< 1) + 1;
j
<
nb_elements__
;
i
=
j
,
j
= (
j
<< 1) + 1) {
629
// let j be the max child
630
if
((
j
+ 1 <
nb_elements__
) &&
cmp__
(
heap__
[
j
+ 1].
first
,
heap__
[
j
].
first
))
631
++
j
;
632
633
// if "val" is lower than heap[j], "val" must be stored at index i
634
if
(
cmp__
(
new_priority
,
heap__
[
j
].
first
))
break
;
635
636
// else pull up the jth node
637
heap__
[
i
] =
std
::
move
(
heap__
[
j
]);
638
std
::
vector
<
Size
>&
vect_index
=
indices__
[*(
heap__
[
i
].
second
)];
639
for
(
auto
&
idx
:
vect_index
) {
640
if
(
idx
==
j
) {
641
idx
=
i
;
642
break
;
643
}
644
}
645
}
646
647
// update the index of val
648
heap__
[
i
].
first
=
std
::
move
(
new_priority
);
649
heap__
[
i
].
second
=
val
;
650
std
::
vector
<
Size
>&
vect_index
=
indices__
[*(
heap__
[
i
].
second
)];
651
for
(
auto
&
idx
:
vect_index
) {
652
if
(
idx
==
index
) {
653
idx
=
i
;
654
break
;
655
}
656
}
657
658
return
i
;
659
}
660
661
// modifies the priority of each instance of a given element
662
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
663
void
MultiPriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
setPriority
(
664
const
Val
&
elt
,
665
const
Priority
&
new_priority
) {
666
std
::
vector
<
Size
>&
vect_index
=
indices__
[
elt
];
667
668
for
(
auto
index
:
vect_index
) {
669
setPriorityByPos
(
index
,
new_priority
);
670
}
671
}
672
673
// modifies the priority of each instance of a given element
674
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
675
INLINE
const
Priority
&
MultiPriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
priority
(
676
const
Val
&
elt
)
const
{
677
return
heap__
[
indices__
[
elt
][0]].
first
;
678
}
679
680
// A \c << operator for priority queues
681
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
682
INLINE
std
::
ostream
&
683
operator
<<(
std
::
ostream
&
stream
,
684
const
MultiPriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>&
queue
) {
685
stream
<<
queue
.
toString
();
686
return
stream
;
687
}
688
689
}
/* namespace gum */
gum::Set::emplace
INLINE void emplace(Args &&... args)
Definition:
set_tpl.h:669