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