edsger 0.1.5__cp311-cp311-macosx_11_0_arm64.whl → 0.1.6__cp311-cp311-macosx_11_0_arm64.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/_version.py +1 -1
- edsger/bellman_ford.c +1344 -967
- edsger/bellman_ford.cpython-311-darwin.so +0 -0
- edsger/bellman_ford.pyx +7 -0
- edsger/bfs.c +33575 -0
- edsger/bfs.cpython-311-darwin.so +0 -0
- edsger/bfs.pyx +243 -0
- edsger/commons.c +283 -278
- edsger/commons.cpython-311-darwin.so +0 -0
- edsger/commons.pyx +7 -0
- edsger/dijkstra.c +2417 -1856
- edsger/dijkstra.cpython-311-darwin.so +0 -0
- edsger/dijkstra.pyx +7 -0
- edsger/graph_importer.py +340 -0
- edsger/networks.py +4 -2
- edsger/path.py +676 -129
- edsger/path_tracking.c +407 -301
- edsger/path_tracking.cpython-311-darwin.so +0 -0
- edsger/path_tracking.pyx +7 -0
- edsger/pq_4ary_dec_0b.c +1159 -1015
- edsger/pq_4ary_dec_0b.cpython-311-darwin.so +0 -0
- edsger/pq_4ary_dec_0b.pyx +7 -0
- edsger/spiess_florian.c +1394 -1139
- edsger/spiess_florian.cpython-311-darwin.so +0 -0
- edsger/spiess_florian.pyx +7 -0
- edsger/star.c +1224 -766
- edsger/star.cpython-311-darwin.so +0 -0
- edsger/star.pyx +7 -0
- edsger/utils.py +9 -8
- {edsger-0.1.5.dist-info → edsger-0.1.6.dist-info}/METADATA +124 -2
- edsger-0.1.6.dist-info/RECORD +40 -0
- edsger-0.1.5.dist-info/RECORD +0 -36
- {edsger-0.1.5.dist-info → edsger-0.1.6.dist-info}/WHEEL +0 -0
- {edsger-0.1.5.dist-info → edsger-0.1.6.dist-info}/licenses/AUTHORS.rst +0 -0
- {edsger-0.1.5.dist-info → edsger-0.1.6.dist-info}/licenses/LICENSE +0 -0
- {edsger-0.1.5.dist-info → edsger-0.1.6.dist-info}/top_level.txt +0 -0
Binary file
|
edsger/bfs.pyx
ADDED
@@ -0,0 +1,243 @@
|
|
1
|
+
"""
|
2
|
+
Breadth-First Search (BFS) implementation.
|
3
|
+
|
4
|
+
cpdef functions:
|
5
|
+
|
6
|
+
- bfs_csr
|
7
|
+
Compute BFS tree using CSR format (forward traversal). Returns predecessors.
|
8
|
+
- bfs_csc
|
9
|
+
Compute BFS tree using CSC format (backward traversal). Returns predecessors.
|
10
|
+
"""
|
11
|
+
|
12
|
+
# cython: language_level=3
|
13
|
+
# cython: boundscheck=False
|
14
|
+
# cython: wraparound=False
|
15
|
+
# cython: embedsignature=False
|
16
|
+
# cython: cdivision=True
|
17
|
+
# cython: initializedcheck=False
|
18
|
+
|
19
|
+
cimport numpy as cnp
|
20
|
+
import numpy as np
|
21
|
+
|
22
|
+
cpdef cnp.ndarray bfs_csr(
|
23
|
+
cnp.uint32_t[::1] csr_indptr,
|
24
|
+
cnp.uint32_t[::1] csr_indices,
|
25
|
+
int start_vert_idx,
|
26
|
+
int vertex_count,
|
27
|
+
int sentinel=-9999):
|
28
|
+
"""
|
29
|
+
Compute BFS tree using CSR format (forward traversal from start vertex).
|
30
|
+
|
31
|
+
Parameters
|
32
|
+
----------
|
33
|
+
csr_indptr : cnp.uint32_t[::1]
|
34
|
+
Pointers in the CSR format
|
35
|
+
csr_indices : cnp.uint32_t[::1]
|
36
|
+
Indices in the CSR format
|
37
|
+
start_vert_idx : int
|
38
|
+
Starting vertex index
|
39
|
+
vertex_count : int
|
40
|
+
Total number of vertices
|
41
|
+
sentinel : int, optional
|
42
|
+
Sentinel value for unreachable nodes and start vertex (default: -9999)
|
43
|
+
|
44
|
+
Returns
|
45
|
+
-------
|
46
|
+
predecessors : cnp.ndarray
|
47
|
+
Predecessor array where predecessors[i] contains the predecessor
|
48
|
+
of vertex i in the BFS tree. Unreachable vertices and the start
|
49
|
+
vertex have the sentinel value.
|
50
|
+
"""
|
51
|
+
|
52
|
+
cdef:
|
53
|
+
size_t tail_vert_idx, head_vert_idx, idx
|
54
|
+
size_t queue_head = 0, queue_tail = 0
|
55
|
+
size_t start = <size_t>start_vert_idx
|
56
|
+
cnp.uint32_t[::1] queue
|
57
|
+
cnp.int8_t[::1] visited
|
58
|
+
cnp.int32_t[::1] predecessors
|
59
|
+
|
60
|
+
# Allocate arrays
|
61
|
+
queue = np.empty(vertex_count, dtype=np.uint32)
|
62
|
+
visited = np.zeros(vertex_count, dtype=np.int8)
|
63
|
+
predecessors = np.full(vertex_count, sentinel, dtype=np.int32)
|
64
|
+
|
65
|
+
with nogil:
|
66
|
+
# Initialize: mark start vertex as visited and enqueue it
|
67
|
+
visited[start] = 1
|
68
|
+
queue[queue_tail] = start
|
69
|
+
queue_tail += 1
|
70
|
+
|
71
|
+
# BFS main loop
|
72
|
+
while queue_head < queue_tail:
|
73
|
+
tail_vert_idx = queue[queue_head]
|
74
|
+
queue_head += 1
|
75
|
+
|
76
|
+
# Process all outgoing edges from tail_vert_idx
|
77
|
+
for idx in range(<size_t>csr_indptr[tail_vert_idx],
|
78
|
+
<size_t>csr_indptr[tail_vert_idx + 1]):
|
79
|
+
head_vert_idx = <size_t>csr_indices[idx]
|
80
|
+
|
81
|
+
# If not visited, mark as visited and enqueue
|
82
|
+
if visited[head_vert_idx] == 0:
|
83
|
+
visited[head_vert_idx] = 1
|
84
|
+
predecessors[head_vert_idx] = <int>tail_vert_idx
|
85
|
+
queue[queue_tail] = head_vert_idx
|
86
|
+
queue_tail += 1
|
87
|
+
|
88
|
+
# Convert to numpy array
|
89
|
+
return np.asarray(predecessors)
|
90
|
+
|
91
|
+
|
92
|
+
cpdef cnp.ndarray bfs_csc(
|
93
|
+
cnp.uint32_t[::1] csc_indptr,
|
94
|
+
cnp.uint32_t[::1] csc_indices,
|
95
|
+
int start_vert_idx,
|
96
|
+
int vertex_count,
|
97
|
+
int sentinel=-9999):
|
98
|
+
"""
|
99
|
+
Compute BFS tree using CSC format (backward traversal from start vertex).
|
100
|
+
|
101
|
+
Parameters
|
102
|
+
----------
|
103
|
+
csc_indptr : cnp.uint32_t[::1]
|
104
|
+
Pointers in the CSC format
|
105
|
+
csc_indices : cnp.uint32_t[::1]
|
106
|
+
Indices in the CSC format
|
107
|
+
start_vert_idx : int
|
108
|
+
Starting vertex index
|
109
|
+
vertex_count : int
|
110
|
+
Total number of vertices
|
111
|
+
sentinel : int, optional
|
112
|
+
Sentinel value for unreachable nodes and start vertex (default: -9999)
|
113
|
+
|
114
|
+
Returns
|
115
|
+
-------
|
116
|
+
predecessors : cnp.ndarray
|
117
|
+
Predecessor array where predecessors[i] contains the successor
|
118
|
+
of vertex i in the BFS tree (since we're traversing backward).
|
119
|
+
Unreachable vertices and the start vertex have the sentinel value.
|
120
|
+
"""
|
121
|
+
|
122
|
+
cdef:
|
123
|
+
size_t tail_vert_idx, head_vert_idx, idx
|
124
|
+
size_t queue_head = 0, queue_tail = 0
|
125
|
+
size_t start = <size_t>start_vert_idx
|
126
|
+
cnp.uint32_t[::1] queue
|
127
|
+
cnp.int8_t[::1] visited
|
128
|
+
cnp.int32_t[::1] predecessors
|
129
|
+
|
130
|
+
# Allocate arrays
|
131
|
+
queue = np.empty(vertex_count, dtype=np.uint32)
|
132
|
+
visited = np.zeros(vertex_count, dtype=np.int8)
|
133
|
+
predecessors = np.full(vertex_count, sentinel, dtype=np.int32)
|
134
|
+
|
135
|
+
with nogil:
|
136
|
+
# Initialize: mark start vertex as visited and enqueue it
|
137
|
+
visited[start] = 1
|
138
|
+
queue[queue_tail] = start
|
139
|
+
queue_tail += 1
|
140
|
+
|
141
|
+
# BFS main loop (processing incoming edges using CSC)
|
142
|
+
while queue_head < queue_tail:
|
143
|
+
head_vert_idx = queue[queue_head]
|
144
|
+
queue_head += 1
|
145
|
+
|
146
|
+
# Process all incoming edges to head_vert_idx
|
147
|
+
for idx in range(<size_t>csc_indptr[head_vert_idx],
|
148
|
+
<size_t>csc_indptr[head_vert_idx + 1]):
|
149
|
+
tail_vert_idx = <size_t>csc_indices[idx]
|
150
|
+
|
151
|
+
# If not visited, mark as visited and enqueue
|
152
|
+
if visited[tail_vert_idx] == 0:
|
153
|
+
visited[tail_vert_idx] = 1
|
154
|
+
predecessors[tail_vert_idx] = <int>head_vert_idx
|
155
|
+
queue[queue_tail] = tail_vert_idx
|
156
|
+
queue_tail += 1
|
157
|
+
|
158
|
+
# Convert to numpy array
|
159
|
+
return np.asarray(predecessors)
|
160
|
+
|
161
|
+
|
162
|
+
# ============================================================================ #
|
163
|
+
# tests #
|
164
|
+
# ============================================================================ #
|
165
|
+
|
166
|
+
|
167
|
+
cdef generate_simple_graph_csr():
|
168
|
+
"""
|
169
|
+
Generate a simple directed graph in CSR format.
|
170
|
+
|
171
|
+
Graph structure:
|
172
|
+
0 -> 1 -> 3
|
173
|
+
0 -> 2 -> 3
|
174
|
+
|
175
|
+
4 vertices, 4 edges
|
176
|
+
"""
|
177
|
+
csr_indptr = np.array([0, 2, 3, 4, 4], dtype=np.uint32)
|
178
|
+
csr_indices = np.array([1, 2, 3, 3], dtype=np.uint32)
|
179
|
+
return csr_indptr, csr_indices
|
180
|
+
|
181
|
+
|
182
|
+
cdef generate_simple_graph_csc():
|
183
|
+
"""
|
184
|
+
Generate a simple directed graph in CSC format.
|
185
|
+
|
186
|
+
Graph structure (same as CSR version):
|
187
|
+
0 -> 1 -> 3
|
188
|
+
0 -> 2 -> 3
|
189
|
+
|
190
|
+
4 vertices, 4 edges
|
191
|
+
"""
|
192
|
+
csc_indptr = np.array([0, 0, 1, 2, 4], dtype=np.uint32)
|
193
|
+
csc_indices = np.array([0, 0, 1, 2], dtype=np.uint32)
|
194
|
+
return csc_indptr, csc_indices
|
195
|
+
|
196
|
+
|
197
|
+
cpdef test_bfs_csr_01():
|
198
|
+
"""Test BFS CSR on simple graph from vertex 0."""
|
199
|
+
cdef int UNREACHABLE = -9999
|
200
|
+
csr_indptr, csr_indices = generate_simple_graph_csr()
|
201
|
+
|
202
|
+
predecessors = bfs_csr(csr_indptr, csr_indices, 0, 4)
|
203
|
+
|
204
|
+
# Expected: 0 is start, 1 and 2 have predecessor 0, 3 has predecessor 1 or 2
|
205
|
+
assert predecessors[0] == UNREACHABLE # start vertex
|
206
|
+
assert predecessors[1] == 0
|
207
|
+
assert predecessors[2] == 0
|
208
|
+
assert predecessors[3] in [1, 2] # could be reached from either 1 or 2
|
209
|
+
|
210
|
+
|
211
|
+
cpdef test_bfs_csc_01():
|
212
|
+
"""Test BFS CSC on simple graph to vertex 3."""
|
213
|
+
cdef int UNREACHABLE = -9999
|
214
|
+
csc_indptr, csc_indices = generate_simple_graph_csc()
|
215
|
+
|
216
|
+
predecessors = bfs_csc(csc_indptr, csc_indices, 3, 4)
|
217
|
+
|
218
|
+
# Expected: working backward from 3
|
219
|
+
assert predecessors[3] == UNREACHABLE # start vertex
|
220
|
+
assert predecessors[1] in [3, UNREACHABLE] or predecessors[2] in [3, UNREACHABLE]
|
221
|
+
assert predecessors[0] in [1, 2, UNREACHABLE]
|
222
|
+
|
223
|
+
|
224
|
+
cpdef test_bfs_unreachable():
|
225
|
+
"""Test BFS with unreachable vertices."""
|
226
|
+
cdef int UNREACHABLE = -9999
|
227
|
+
# Graph: 0 -> 1, 2 -> 3 (two disconnected components)
|
228
|
+
csr_indptr = np.array([0, 1, 1, 2, 2], dtype=np.uint32)
|
229
|
+
csr_indices = np.array([1, 3], dtype=np.uint32)
|
230
|
+
|
231
|
+
predecessors = bfs_csr(csr_indptr, csr_indices, 0, 4)
|
232
|
+
|
233
|
+
# From 0, can reach 1 but not 2 or 3
|
234
|
+
assert predecessors[0] == UNREACHABLE # start
|
235
|
+
assert predecessors[1] == 0
|
236
|
+
assert predecessors[2] == UNREACHABLE # unreachable
|
237
|
+
assert predecessors[3] == UNREACHABLE # unreachable
|
238
|
+
|
239
|
+
|
240
|
+
# author : Francois Pacull
|
241
|
+
# copyright : Architecture & Performance
|
242
|
+
# email: francois.pacull@architecture-performance.fr
|
243
|
+
# license : MIT
|