edsger 0.1.1__cp312-cp312-macosx_10_9_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- edsger/.gitignore +1 -0
- edsger/__init__.py +1 -0
- edsger/_version.py +1 -0
- edsger/commons.c +8391 -0
- edsger/commons.cpython-312-darwin.so +0 -0
- edsger/commons.pxd +25 -0
- edsger/commons.pyx +34 -0
- edsger/dijkstra.c +35848 -0
- edsger/dijkstra.cpython-312-darwin.so +0 -0
- edsger/dijkstra.pyx +504 -0
- edsger/networks.py +414 -0
- edsger/path.py +786 -0
- edsger/path_tracking.c +30241 -0
- edsger/path_tracking.cpython-312-darwin.so +0 -0
- edsger/path_tracking.pyx +93 -0
- edsger/pq_4ary_dec_0b.c +35869 -0
- edsger/pq_4ary_dec_0b.cpython-312-darwin.so +0 -0
- edsger/pq_4ary_dec_0b.pxd +33 -0
- edsger/pq_4ary_dec_0b.pyx +692 -0
- edsger/spiess_florian.c +34520 -0
- edsger/spiess_florian.cpython-312-darwin.so +0 -0
- edsger/spiess_florian.pyx +368 -0
- edsger/star.c +33896 -0
- edsger/star.cpython-312-darwin.so +0 -0
- edsger/star.pyx +356 -0
- edsger/utils.py +63 -0
- edsger-0.1.1.dist-info/METADATA +111 -0
- edsger-0.1.1.dist-info/RECORD +32 -0
- edsger-0.1.1.dist-info/WHEEL +5 -0
- edsger-0.1.1.dist-info/licenses/AUTHORS.rst +5 -0
- edsger-0.1.1.dist-info/licenses/LICENSE +21 -0
- edsger-0.1.1.dist-info/top_level.txt +1 -0
Binary file
|
@@ -0,0 +1,33 @@
|
|
1
|
+
""" Priority queue based on a minimum binary heap. Header file.
|
2
|
+
"""
|
3
|
+
|
4
|
+
cimport numpy as cnp
|
5
|
+
|
6
|
+
from edsger.commons cimport DTYPE_t, ElementState
|
7
|
+
|
8
|
+
|
9
|
+
cdef struct Element:
|
10
|
+
DTYPE_t key
|
11
|
+
ElementState state
|
12
|
+
size_t node_idx
|
13
|
+
|
14
|
+
cdef struct PriorityQueue:
|
15
|
+
size_t length # number of elements in the array
|
16
|
+
size_t size # number of elements in the heap
|
17
|
+
size_t* A # array storing the binary tree
|
18
|
+
Element* Elements # array storing the elements
|
19
|
+
|
20
|
+
cdef void init_pqueue(PriorityQueue*, size_t, size_t) nogil
|
21
|
+
cdef void free_pqueue(PriorityQueue*) nogil
|
22
|
+
cdef void insert(PriorityQueue*, size_t, DTYPE_t) nogil
|
23
|
+
cdef DTYPE_t peek(PriorityQueue*) nogil
|
24
|
+
cdef size_t extract_min(PriorityQueue*) nogil
|
25
|
+
cdef bint is_empty(PriorityQueue*) nogil
|
26
|
+
cdef void decrease_key(PriorityQueue*, size_t, DTYPE_t) nogil
|
27
|
+
cdef cnp.ndarray copy_keys_to_numpy(PriorityQueue*, size_t)
|
28
|
+
|
29
|
+
|
30
|
+
# author : Francois Pacull
|
31
|
+
# copyright : Architecture & Performance
|
32
|
+
# email: francois.pacull@architecture-performance.fr
|
33
|
+
# license : MIT
|
@@ -0,0 +1,692 @@
|
|
1
|
+
"""
|
2
|
+
Priority queue based on a minimum 4-ary heap.
|
3
|
+
|
4
|
+
- dec: priority queue with decrease-key operation.
|
5
|
+
- 0b: indices are zero-based
|
6
|
+
|
7
|
+
cdef functions:
|
8
|
+
|
9
|
+
- init_pqueue
|
10
|
+
Initialize the priority queue.
|
11
|
+
- _initialize_element
|
12
|
+
Initialize a single element.
|
13
|
+
- free_pqueue
|
14
|
+
Free the priority queue.
|
15
|
+
- insert
|
16
|
+
Insert an element into the heap and reorder the heap.
|
17
|
+
- decrease_key
|
18
|
+
Decrease the key of a element in the heap, given its element index.
|
19
|
+
- peek
|
20
|
+
Find heap min key.
|
21
|
+
- is_empty
|
22
|
+
Check if the heap is empty.
|
23
|
+
- extract_min
|
24
|
+
Extract element with min keay from the heap,
|
25
|
+
and return its element index.
|
26
|
+
- copy_keys_to_numpy
|
27
|
+
Copy the keys into a numpy array.
|
28
|
+
- _exchange_nodes
|
29
|
+
Exchange two nodes in the heap.
|
30
|
+
- _min_heapify
|
31
|
+
Re-order sub-tree under a given node (given its node index)
|
32
|
+
until it satisfies the heap property.
|
33
|
+
- _decrease_key_from_node_index
|
34
|
+
Decrease the key of an element in the heap, given its tree index.
|
35
|
+
|
36
|
+
"""
|
37
|
+
|
38
|
+
cimport numpy as cnp
|
39
|
+
from libc.stdlib cimport free, malloc
|
40
|
+
|
41
|
+
from edsger.commons import DTYPE_PY
|
42
|
+
from edsger.commons cimport (
|
43
|
+
DTYPE_INF, LABELED, UNLABELED, SCANNED, DTYPE_t
|
44
|
+
)
|
45
|
+
|
46
|
+
|
47
|
+
cdef void init_pqueue(
|
48
|
+
PriorityQueue* pqueue,
|
49
|
+
size_t heap_length,
|
50
|
+
size_t element_count) nogil noexcept:
|
51
|
+
"""
|
52
|
+
Initialize the priority queue.
|
53
|
+
|
54
|
+
input
|
55
|
+
=====
|
56
|
+
* PriorityQueue* pqueue : priority queue
|
57
|
+
* size_t length : length (maximum size) of the heap
|
58
|
+
* size_t element_count : element count
|
59
|
+
|
60
|
+
assumptions
|
61
|
+
===========
|
62
|
+
* heap_length <= element_count
|
63
|
+
"""
|
64
|
+
cdef size_t i
|
65
|
+
|
66
|
+
pqueue.length = heap_length
|
67
|
+
pqueue.size = 0
|
68
|
+
pqueue.A = <size_t*> malloc(heap_length * sizeof(size_t))
|
69
|
+
pqueue.Elements = <Element*> malloc(element_count * sizeof(Element))
|
70
|
+
|
71
|
+
for i in range(heap_length):
|
72
|
+
pqueue.A[i] = heap_length
|
73
|
+
_initialize_element(pqueue, i)
|
74
|
+
for i in range(heap_length, element_count):
|
75
|
+
_initialize_element(pqueue, i)
|
76
|
+
|
77
|
+
|
78
|
+
cdef void _initialize_element(
|
79
|
+
PriorityQueue* pqueue,
|
80
|
+
size_t element_idx) nogil noexcept:
|
81
|
+
"""
|
82
|
+
Initialize a single element.
|
83
|
+
|
84
|
+
input
|
85
|
+
=====
|
86
|
+
* PriorityQueue* pqueue : priority queue
|
87
|
+
* size_t element_idx : index of the element in the element array
|
88
|
+
"""
|
89
|
+
pqueue.Elements[element_idx].key = DTYPE_INF
|
90
|
+
pqueue.Elements[element_idx].state = UNLABELED
|
91
|
+
pqueue.Elements[element_idx].node_idx = pqueue.length
|
92
|
+
|
93
|
+
|
94
|
+
cdef void free_pqueue(
|
95
|
+
PriorityQueue* pqueue) nogil noexcept:
|
96
|
+
"""
|
97
|
+
Free the priority queue.
|
98
|
+
|
99
|
+
input
|
100
|
+
=====
|
101
|
+
* PriorityQueue* pqueue : priority queue
|
102
|
+
"""
|
103
|
+
free(pqueue.A)
|
104
|
+
free(pqueue.Elements)
|
105
|
+
|
106
|
+
|
107
|
+
cdef void insert(
|
108
|
+
PriorityQueue* pqueue,
|
109
|
+
size_t element_idx,
|
110
|
+
DTYPE_t key) nogil noexcept:
|
111
|
+
"""
|
112
|
+
Insert an element into the heap and reorder the heap.
|
113
|
+
|
114
|
+
input
|
115
|
+
=====
|
116
|
+
* PriorityQueue* pqueue : priority queue
|
117
|
+
* size_t element_idx : index of the element in the element array
|
118
|
+
* DTYPE_t key : key value of the element
|
119
|
+
|
120
|
+
assumptions
|
121
|
+
===========
|
122
|
+
* the element pqueue.Elements[element_idx] is not in the heap
|
123
|
+
* its new key is smaller than DTYPE_INF
|
124
|
+
"""
|
125
|
+
cdef size_t node_idx = pqueue.size
|
126
|
+
|
127
|
+
pqueue.size += 1
|
128
|
+
pqueue.Elements[element_idx].state = LABELED
|
129
|
+
pqueue.Elements[element_idx].node_idx = node_idx
|
130
|
+
pqueue.A[node_idx] = element_idx
|
131
|
+
_decrease_key_from_node_index(pqueue, node_idx, key)
|
132
|
+
|
133
|
+
|
134
|
+
cdef void decrease_key(
|
135
|
+
PriorityQueue* pqueue,
|
136
|
+
size_t element_idx,
|
137
|
+
DTYPE_t key_new) nogil noexcept:
|
138
|
+
"""
|
139
|
+
Decrease the key of a element in the heap, given its element index.
|
140
|
+
|
141
|
+
input
|
142
|
+
=====
|
143
|
+
* PriorityQueue* pqueue : priority queue
|
144
|
+
* size_t element_idx : index of the element in the element array
|
145
|
+
* DTYPE_t key_new : new value of the element key
|
146
|
+
|
147
|
+
assumption
|
148
|
+
==========
|
149
|
+
* pqueue.Elements[idx] is in the heap
|
150
|
+
"""
|
151
|
+
_decrease_key_from_node_index(
|
152
|
+
pqueue,
|
153
|
+
pqueue.Elements[element_idx].node_idx,
|
154
|
+
key_new)
|
155
|
+
|
156
|
+
|
157
|
+
cdef DTYPE_t peek(PriorityQueue* pqueue) nogil noexcept:
|
158
|
+
"""
|
159
|
+
Find heap min key.
|
160
|
+
|
161
|
+
input
|
162
|
+
=====
|
163
|
+
* PriorityQueue* pqueue : priority queue
|
164
|
+
|
165
|
+
output
|
166
|
+
======
|
167
|
+
* DTYPE_t : key value of the min element
|
168
|
+
|
169
|
+
assumption
|
170
|
+
==========
|
171
|
+
* pqueue.size > 0
|
172
|
+
* heap is heapified
|
173
|
+
"""
|
174
|
+
return pqueue.Elements[pqueue.A[0]].key
|
175
|
+
|
176
|
+
|
177
|
+
cdef bint is_empty(PriorityQueue* pqueue) nogil noexcept:
|
178
|
+
"""
|
179
|
+
Check if the heap is empty.
|
180
|
+
|
181
|
+
input
|
182
|
+
=====
|
183
|
+
* PriorityQueue* pqueue : priority queue
|
184
|
+
"""
|
185
|
+
cdef bint isempty = 0
|
186
|
+
|
187
|
+
if pqueue.size == 0:
|
188
|
+
isempty = 1
|
189
|
+
|
190
|
+
return isempty
|
191
|
+
|
192
|
+
|
193
|
+
cdef size_t extract_min(PriorityQueue* pqueue) nogil noexcept:
|
194
|
+
"""
|
195
|
+
Extract element with min keay from the heap,
|
196
|
+
and return its element index.
|
197
|
+
|
198
|
+
input
|
199
|
+
=====
|
200
|
+
* PriorityQueue* pqueue : priority queue
|
201
|
+
|
202
|
+
output
|
203
|
+
======
|
204
|
+
* size_t : element index with min key
|
205
|
+
|
206
|
+
assumption
|
207
|
+
==========
|
208
|
+
* pqueue.size > 0
|
209
|
+
"""
|
210
|
+
cdef:
|
211
|
+
size_t element_idx = pqueue.A[0] # min element index
|
212
|
+
size_t node_idx = pqueue.size - 1 # last leaf node index
|
213
|
+
|
214
|
+
# exchange the root node with the last leaf node
|
215
|
+
_exchange_nodes(pqueue, 0, node_idx)
|
216
|
+
|
217
|
+
# remove this element from the heap
|
218
|
+
pqueue.Elements[element_idx].state = SCANNED
|
219
|
+
pqueue.Elements[element_idx].node_idx = pqueue.length
|
220
|
+
pqueue.A[node_idx] = pqueue.length
|
221
|
+
pqueue.size -= 1
|
222
|
+
|
223
|
+
# reorder the tree Elements from the root node
|
224
|
+
_min_heapify(pqueue, 0)
|
225
|
+
|
226
|
+
return element_idx
|
227
|
+
|
228
|
+
|
229
|
+
cdef cnp.ndarray copy_keys_to_numpy(
|
230
|
+
PriorityQueue* pqueue,
|
231
|
+
size_t vertex_count
|
232
|
+
) noexcept:
|
233
|
+
"""
|
234
|
+
Copy the keys into a numpy array.
|
235
|
+
|
236
|
+
input
|
237
|
+
=====
|
238
|
+
* PriorityQueue* pqueue : priority queue
|
239
|
+
* int vertex_count : vertex count
|
240
|
+
* int num_threads : number of threads for the parallel job
|
241
|
+
|
242
|
+
output
|
243
|
+
======
|
244
|
+
* cnp.ndarray : NumPy array with all the keys
|
245
|
+
"""
|
246
|
+
|
247
|
+
path_lengths = cnp.ndarray(vertex_count, dtype=DTYPE_PY)
|
248
|
+
|
249
|
+
cdef:
|
250
|
+
size_t i # loop counter
|
251
|
+
DTYPE_t[::1] path_lengths_view = path_lengths
|
252
|
+
|
253
|
+
with nogil:
|
254
|
+
|
255
|
+
for i in range(vertex_count):
|
256
|
+
path_lengths_view[i] = pqueue.Elements[i].key
|
257
|
+
|
258
|
+
return path_lengths
|
259
|
+
|
260
|
+
|
261
|
+
cdef void _exchange_nodes(
|
262
|
+
PriorityQueue* pqueue,
|
263
|
+
size_t node_i,
|
264
|
+
size_t node_j) nogil noexcept:
|
265
|
+
"""
|
266
|
+
Exchange two nodes in the heap.
|
267
|
+
|
268
|
+
input
|
269
|
+
=====
|
270
|
+
* PriorityQueue* pqueue : priority queue
|
271
|
+
* size_t node_i: first node index
|
272
|
+
* size_t node_j: second node index
|
273
|
+
"""
|
274
|
+
cdef:
|
275
|
+
size_t element_i = pqueue.A[node_i]
|
276
|
+
size_t element_j = pqueue.A[node_j]
|
277
|
+
|
278
|
+
# exchange element indices in the heap array
|
279
|
+
pqueue.A[node_i] = element_j
|
280
|
+
pqueue.A[node_j] = element_i
|
281
|
+
|
282
|
+
# exchange node indices in the element array
|
283
|
+
pqueue.Elements[element_j].node_idx = node_i
|
284
|
+
pqueue.Elements[element_i].node_idx = node_j
|
285
|
+
|
286
|
+
|
287
|
+
cdef void _min_heapify(
|
288
|
+
PriorityQueue* pqueue,
|
289
|
+
size_t node_idx) nogil noexcept:
|
290
|
+
"""
|
291
|
+
Re-order sub-tree under a given node (given its node index)
|
292
|
+
until it satisfies the heap property.
|
293
|
+
|
294
|
+
input
|
295
|
+
=====
|
296
|
+
* PriorityQueue* pqueue : priority queue
|
297
|
+
* size_t node_idx : node index
|
298
|
+
"""
|
299
|
+
cdef:
|
300
|
+
size_t c1, c2, c3, c4, i = node_idx, s
|
301
|
+
DTYPE_t val_tmp, val_min
|
302
|
+
|
303
|
+
while True:
|
304
|
+
|
305
|
+
c1 = 4 * i + 1
|
306
|
+
c2 = c1 + 1
|
307
|
+
c3 = c2 + 1
|
308
|
+
c4 = c3 + 1
|
309
|
+
|
310
|
+
s = i
|
311
|
+
val_min = pqueue.Elements[pqueue.A[s]].key
|
312
|
+
if (c4 < pqueue.size):
|
313
|
+
val_tmp = pqueue.Elements[pqueue.A[c4]].key
|
314
|
+
if val_tmp < val_min:
|
315
|
+
s = c4
|
316
|
+
val_min = val_tmp
|
317
|
+
val_tmp = pqueue.Elements[pqueue.A[c3]].key
|
318
|
+
if val_tmp < val_min:
|
319
|
+
s = c3
|
320
|
+
val_min = val_tmp
|
321
|
+
val_tmp = pqueue.Elements[pqueue.A[c2]].key
|
322
|
+
if val_tmp < val_min:
|
323
|
+
s = c2
|
324
|
+
val_min = val_tmp
|
325
|
+
val_tmp = pqueue.Elements[pqueue.A[c1]].key
|
326
|
+
if val_tmp < val_min:
|
327
|
+
s = c1
|
328
|
+
else:
|
329
|
+
if (c3 < pqueue.size):
|
330
|
+
val_tmp = pqueue.Elements[pqueue.A[c3]].key
|
331
|
+
if val_tmp < val_min:
|
332
|
+
s = c3
|
333
|
+
val_min = val_tmp
|
334
|
+
val_tmp = pqueue.Elements[pqueue.A[c2]].key
|
335
|
+
if val_tmp < val_min:
|
336
|
+
s = c2
|
337
|
+
val_min = val_tmp
|
338
|
+
val_tmp = pqueue.Elements[pqueue.A[c1]].key
|
339
|
+
if val_tmp < val_min:
|
340
|
+
s = c1
|
341
|
+
else:
|
342
|
+
if (c2 < pqueue.size):
|
343
|
+
val_tmp = pqueue.Elements[pqueue.A[c2]].key
|
344
|
+
if val_tmp < val_min:
|
345
|
+
s = c2
|
346
|
+
val_min = val_tmp
|
347
|
+
val_tmp = pqueue.Elements[pqueue.A[c1]].key
|
348
|
+
if val_tmp < val_min:
|
349
|
+
s = c1
|
350
|
+
else:
|
351
|
+
if (c1 < pqueue.size):
|
352
|
+
val_tmp = pqueue.Elements[pqueue.A[c1]].key
|
353
|
+
if val_tmp < val_min:
|
354
|
+
s = c1
|
355
|
+
|
356
|
+
if s != i:
|
357
|
+
_exchange_nodes(pqueue, i, s)
|
358
|
+
i = s
|
359
|
+
else:
|
360
|
+
break
|
361
|
+
|
362
|
+
|
363
|
+
cdef void _decrease_key_from_node_index(
|
364
|
+
PriorityQueue* pqueue,
|
365
|
+
size_t node_idx,
|
366
|
+
DTYPE_t key_new) nogil noexcept:
|
367
|
+
"""
|
368
|
+
Decrease the key of an element in the heap, given its tree index.
|
369
|
+
|
370
|
+
input
|
371
|
+
=====
|
372
|
+
* PriorityQueue* pqueue : priority queue
|
373
|
+
* size_t node_idx : node index
|
374
|
+
* DTYPE_t key_new : new key value
|
375
|
+
|
376
|
+
assumptions
|
377
|
+
===========
|
378
|
+
* pqueue.Elements[pqueue.A[node_idx]] is in the heap (node_idx < pqueue.size)
|
379
|
+
* key_new < pqueue.Elements[pqueue.A[node_idx]].key
|
380
|
+
"""
|
381
|
+
cdef:
|
382
|
+
size_t i = node_idx, j
|
383
|
+
DTYPE_t key_j
|
384
|
+
|
385
|
+
pqueue.Elements[pqueue.A[i]].key = key_new
|
386
|
+
while i > 0:
|
387
|
+
j = (i - 1) // 4
|
388
|
+
key_j = pqueue.Elements[pqueue.A[j]].key
|
389
|
+
if key_j > key_new:
|
390
|
+
_exchange_nodes(pqueue, i, j)
|
391
|
+
i = j
|
392
|
+
else:
|
393
|
+
break
|
394
|
+
|
395
|
+
|
396
|
+
# ============================================================================ #
|
397
|
+
# tests #
|
398
|
+
# ============================================================================ #
|
399
|
+
|
400
|
+
import numpy as np
|
401
|
+
|
402
|
+
|
403
|
+
cpdef init_01(int length=4):
|
404
|
+
"""
|
405
|
+
Initialize an empty priority queue.
|
406
|
+
"""
|
407
|
+
|
408
|
+
cdef:
|
409
|
+
PriorityQueue pqueue
|
410
|
+
size_t length_val = <size_t>length
|
411
|
+
|
412
|
+
init_pqueue(&pqueue, length_val, length_val)
|
413
|
+
|
414
|
+
assert pqueue.length == length_val
|
415
|
+
assert pqueue.size == 0
|
416
|
+
for i in range(length_val):
|
417
|
+
assert pqueue.A[i] == pqueue.length
|
418
|
+
assert pqueue.Elements[i].key == DTYPE_INF
|
419
|
+
assert pqueue.Elements[i].state == UNLABELED
|
420
|
+
assert pqueue.Elements[i].node_idx == pqueue.length
|
421
|
+
|
422
|
+
free_pqueue(&pqueue)
|
423
|
+
|
424
|
+
|
425
|
+
cpdef insert_01():
|
426
|
+
"""
|
427
|
+
Insert an element into an empty priority queue of length 1.
|
428
|
+
"""
|
429
|
+
|
430
|
+
cdef:
|
431
|
+
PriorityQueue pqueue
|
432
|
+
DTYPE_t key
|
433
|
+
|
434
|
+
init_pqueue(&pqueue, 1, 1)
|
435
|
+
assert pqueue.length == 1
|
436
|
+
key = 1.0
|
437
|
+
insert(&pqueue, 0, key)
|
438
|
+
assert pqueue.size == 1
|
439
|
+
assert pqueue.A[0] == 0
|
440
|
+
assert pqueue.Elements[0].key == key
|
441
|
+
assert pqueue.Elements[0].state == LABELED
|
442
|
+
assert pqueue.Elements[0].node_idx == 0
|
443
|
+
|
444
|
+
free_pqueue(&pqueue)
|
445
|
+
|
446
|
+
|
447
|
+
cpdef insert_02():
|
448
|
+
"""
|
449
|
+
Insert 4 elements into an empty priority queue of length 4.
|
450
|
+
"""
|
451
|
+
|
452
|
+
cdef:
|
453
|
+
PriorityQueue pqueue
|
454
|
+
DTYPE_t key
|
455
|
+
|
456
|
+
init_pqueue(&pqueue, 4, 4)
|
457
|
+
|
458
|
+
elem_idx = 1
|
459
|
+
key = 3.0
|
460
|
+
insert(&pqueue, elem_idx, key)
|
461
|
+
A_ref = [1, 4, 4, 4]
|
462
|
+
for i in range(4):
|
463
|
+
assert pqueue.A[i] == A_ref[i]
|
464
|
+
assert pqueue.Elements[elem_idx].key == key
|
465
|
+
assert pqueue.Elements[elem_idx].state == LABELED
|
466
|
+
assert pqueue.Elements[1].node_idx == 0
|
467
|
+
assert pqueue.size == 1
|
468
|
+
|
469
|
+
elem_idx = 0
|
470
|
+
key = 2.0
|
471
|
+
insert(&pqueue, elem_idx, key)
|
472
|
+
A_ref = [0, 1, 4, 4]
|
473
|
+
for i in range(4):
|
474
|
+
assert pqueue.A[i] == A_ref[i]
|
475
|
+
assert pqueue.Elements[elem_idx].key == key
|
476
|
+
assert pqueue.Elements[elem_idx].state == LABELED
|
477
|
+
assert pqueue.Elements[0].node_idx == 0
|
478
|
+
assert pqueue.Elements[1].node_idx == 1
|
479
|
+
assert pqueue.size == 2
|
480
|
+
|
481
|
+
elem_idx = 3
|
482
|
+
key = 4.0
|
483
|
+
insert(&pqueue, elem_idx, key)
|
484
|
+
A_ref = [0, 1, 3, 4]
|
485
|
+
for i in range(4):
|
486
|
+
assert pqueue.A[i] == A_ref[i]
|
487
|
+
assert pqueue.Elements[elem_idx].key == key
|
488
|
+
assert pqueue.Elements[elem_idx].state == LABELED
|
489
|
+
assert pqueue.Elements[0].node_idx == 0
|
490
|
+
assert pqueue.Elements[1].node_idx == 1
|
491
|
+
assert pqueue.Elements[3].node_idx == 2
|
492
|
+
assert pqueue.size == 3
|
493
|
+
|
494
|
+
elem_idx = 2
|
495
|
+
key = 1.0
|
496
|
+
insert(&pqueue, elem_idx, key)
|
497
|
+
A_ref = [2, 1, 3, 0]
|
498
|
+
for i in range(4):
|
499
|
+
assert pqueue.A[i] == A_ref[i]
|
500
|
+
assert pqueue.Elements[2].key == key
|
501
|
+
assert pqueue.Elements[2].state == LABELED
|
502
|
+
assert pqueue.Elements[0].node_idx == 3
|
503
|
+
assert pqueue.Elements[1].node_idx == 1
|
504
|
+
assert pqueue.Elements[2].node_idx == 0
|
505
|
+
assert pqueue.Elements[3].node_idx == 2
|
506
|
+
assert pqueue.size == 4
|
507
|
+
|
508
|
+
free_pqueue(&pqueue)
|
509
|
+
|
510
|
+
|
511
|
+
cpdef insert_03(int length=4):
|
512
|
+
"""
|
513
|
+
Insert elements with equal key values.
|
514
|
+
"""
|
515
|
+
|
516
|
+
cdef:
|
517
|
+
PriorityQueue pqueue
|
518
|
+
size_t i, length_val = <size_t>length
|
519
|
+
DTYPE_t key = 1.0
|
520
|
+
|
521
|
+
init_pqueue(&pqueue, length_val, length_val)
|
522
|
+
for i in range(length_val):
|
523
|
+
insert(&pqueue, i, key)
|
524
|
+
for i in range(length_val):
|
525
|
+
assert pqueue.A[i] == i
|
526
|
+
|
527
|
+
free_pqueue(&pqueue)
|
528
|
+
|
529
|
+
|
530
|
+
cpdef peek_01():
|
531
|
+
"""
|
532
|
+
Successively insert elements into a priority queue and
|
533
|
+
check the min element of the priority without extracting it.
|
534
|
+
"""
|
535
|
+
|
536
|
+
cdef PriorityQueue pqueue
|
537
|
+
|
538
|
+
init_pqueue(&pqueue, 4, 4)
|
539
|
+
|
540
|
+
insert(&pqueue, 0, 9.0)
|
541
|
+
assert peek(&pqueue) == 9.0
|
542
|
+
insert(&pqueue, 1, 9.0)
|
543
|
+
assert peek(&pqueue) == 9.0
|
544
|
+
insert(&pqueue, 2, 5.0)
|
545
|
+
assert peek(&pqueue) == 5.0
|
546
|
+
insert(&pqueue, 3, 3.0)
|
547
|
+
assert peek(&pqueue) == 3.0
|
548
|
+
|
549
|
+
free_pqueue(&pqueue)
|
550
|
+
|
551
|
+
|
552
|
+
cpdef extract_min_01():
|
553
|
+
"""
|
554
|
+
Insert 4 elements into a priority queue and
|
555
|
+
extract them all.
|
556
|
+
"""
|
557
|
+
|
558
|
+
cdef PriorityQueue pqueue
|
559
|
+
|
560
|
+
init_pqueue(&pqueue, 4, 4)
|
561
|
+
insert(&pqueue, 1, 3.0)
|
562
|
+
insert(&pqueue, 0, 2.0)
|
563
|
+
insert(&pqueue, 3, 4.0)
|
564
|
+
insert(&pqueue, 2, 1.0)
|
565
|
+
idx = extract_min(&pqueue)
|
566
|
+
assert idx == 2
|
567
|
+
assert pqueue.size == 3
|
568
|
+
assert pqueue.Elements[idx].state == SCANNED
|
569
|
+
idx = extract_min(&pqueue)
|
570
|
+
assert idx == 0
|
571
|
+
assert pqueue.size == 2
|
572
|
+
assert pqueue.Elements[idx].state == SCANNED
|
573
|
+
idx = extract_min(&pqueue)
|
574
|
+
assert idx == 1
|
575
|
+
assert pqueue.size == 1
|
576
|
+
assert pqueue.Elements[idx].state == SCANNED
|
577
|
+
idx = extract_min(&pqueue)
|
578
|
+
assert idx == 3
|
579
|
+
assert pqueue.size == 0
|
580
|
+
assert pqueue.Elements[idx].state == SCANNED
|
581
|
+
|
582
|
+
free_pqueue(&pqueue)
|
583
|
+
|
584
|
+
|
585
|
+
cpdef is_empty_01():
|
586
|
+
"""
|
587
|
+
Insert an element and extract it.
|
588
|
+
"""
|
589
|
+
|
590
|
+
cdef PriorityQueue pqueue
|
591
|
+
|
592
|
+
init_pqueue(&pqueue, 2, 2)
|
593
|
+
|
594
|
+
assert is_empty(&pqueue) == 1
|
595
|
+
insert(&pqueue, 1, 3.0)
|
596
|
+
assert is_empty(&pqueue) == 0
|
597
|
+
idx = extract_min(&pqueue)
|
598
|
+
assert is_empty(&pqueue) == 1
|
599
|
+
|
600
|
+
free_pqueue(&pqueue)
|
601
|
+
|
602
|
+
|
603
|
+
cpdef decrease_key_01():
|
604
|
+
"""
|
605
|
+
Insert elements into a priority queue and decrease the largest
|
606
|
+
key value to become the smallest.
|
607
|
+
"""
|
608
|
+
|
609
|
+
cdef PriorityQueue pqueue
|
610
|
+
|
611
|
+
init_pqueue(&pqueue, 4, 4)
|
612
|
+
|
613
|
+
insert(&pqueue, 1, 3.0)
|
614
|
+
insert(&pqueue, 0, 2.0)
|
615
|
+
insert(&pqueue, 3, 4.0)
|
616
|
+
insert(&pqueue, 2, 1.0)
|
617
|
+
|
618
|
+
assert pqueue.size == 4
|
619
|
+
A_ref = [2, 1, 3, 0]
|
620
|
+
n_ref = [3, 1, 0, 2]
|
621
|
+
key_ref = [2.0, 3.0, 1.0, 4.0]
|
622
|
+
for i in range(4):
|
623
|
+
assert pqueue.A[i] == A_ref[i]
|
624
|
+
assert pqueue.Elements[i].node_idx == n_ref[i]
|
625
|
+
assert pqueue.Elements[i].state == LABELED
|
626
|
+
assert pqueue.Elements[i].key == key_ref[i]
|
627
|
+
|
628
|
+
decrease_key(&pqueue, 3, 0.0)
|
629
|
+
|
630
|
+
assert pqueue.size == 4
|
631
|
+
A_ref = [3, 1, 2, 0]
|
632
|
+
n_ref = [3, 1, 2, 0]
|
633
|
+
key_ref = [2.0, 3.0, 1.0, 0.0]
|
634
|
+
for i in range(4):
|
635
|
+
assert pqueue.A[i] == A_ref[i]
|
636
|
+
assert pqueue.Elements[i].node_idx == n_ref[i]
|
637
|
+
assert pqueue.Elements[i].state == LABELED
|
638
|
+
assert pqueue.Elements[i].key == key_ref[i]
|
639
|
+
|
640
|
+
decrease_key(&pqueue, 1, -1.0)
|
641
|
+
|
642
|
+
assert pqueue.size == 4
|
643
|
+
A_ref = [1, 3, 2, 0]
|
644
|
+
n_ref = [3, 0, 2, 1]
|
645
|
+
key_ref = [2.0, -1.0, 1.0, 0.0]
|
646
|
+
for i in range(4):
|
647
|
+
assert pqueue.A[i] == A_ref[i]
|
648
|
+
assert pqueue.Elements[i].node_idx == n_ref[i]
|
649
|
+
assert pqueue.Elements[i].state == LABELED
|
650
|
+
assert pqueue.Elements[i].key == key_ref[i]
|
651
|
+
|
652
|
+
free_pqueue(&pqueue)
|
653
|
+
|
654
|
+
|
655
|
+
cdef void heapsort(DTYPE_t[::1] values_in, DTYPE_t[::1] values_out) nogil:
|
656
|
+
"""
|
657
|
+
Heap sort by inerting all the values into the priority queue,
|
658
|
+
and extracting them.
|
659
|
+
"""
|
660
|
+
|
661
|
+
cdef:
|
662
|
+
size_t i, length_val = <size_t>values_in.shape[0]
|
663
|
+
PriorityQueue pqueue
|
664
|
+
|
665
|
+
init_pqueue(&pqueue, length_val, length_val)
|
666
|
+
for i in range(length_val):
|
667
|
+
insert(&pqueue, i, values_in[i])
|
668
|
+
for i in range(length_val):
|
669
|
+
values_out[i] = pqueue.Elements[extract_min(&pqueue)].key
|
670
|
+
free_pqueue(&pqueue)
|
671
|
+
|
672
|
+
|
673
|
+
cpdef sort_01(int n, random_seed=124):
|
674
|
+
"""
|
675
|
+
Create an array of random number, sort it with the heapsort function
|
676
|
+
and with the numpy default sort function, compare the results.
|
677
|
+
"""
|
678
|
+
|
679
|
+
cdef PriorityQueue pqueue
|
680
|
+
|
681
|
+
rng = np.random.default_rng(random_seed)
|
682
|
+
values_in = rng.random(size=n)
|
683
|
+
values_out = np.empty_like(values_in, dtype=DTYPE_PY)
|
684
|
+
heapsort(values_in, values_out)
|
685
|
+
values_in_sorted = np.sort(values_in)
|
686
|
+
np.testing.assert_array_equal(values_in_sorted, values_out)
|
687
|
+
|
688
|
+
|
689
|
+
# author : Francois Pacull
|
690
|
+
# copyright : Architecture & Performance
|
691
|
+
# email: francois.pacull@architecture-performance.fr
|
692
|
+
# license : MIT
|