edsger 0.1.1__pp39-pypy39_pp73-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 +8409 -0
- edsger/commons.pxd +25 -0
- edsger/commons.pypy39-pp73-darwin.so +0 -0
- edsger/commons.pyx +34 -0
- edsger/dijkstra.c +35865 -0
- edsger/dijkstra.pypy39-pp73-darwin.so +0 -0
- edsger/dijkstra.pyx +504 -0
- edsger/networks.py +414 -0
- edsger/path.py +786 -0
- edsger/path_tracking.c +30258 -0
- edsger/path_tracking.pypy39-pp73-darwin.so +0 -0
- edsger/path_tracking.pyx +93 -0
- edsger/pq_4ary_dec_0b.c +35886 -0
- edsger/pq_4ary_dec_0b.pxd +33 -0
- edsger/pq_4ary_dec_0b.pypy39-pp73-darwin.so +0 -0
- edsger/pq_4ary_dec_0b.pyx +692 -0
- edsger/spiess_florian.c +34537 -0
- edsger/spiess_florian.pypy39-pp73-darwin.so +0 -0
- edsger/spiess_florian.pyx +368 -0
- edsger/star.c +33913 -0
- edsger/star.pypy39-pp73-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,368 @@
|
|
1
|
+
"""
|
2
|
+
An implementation of Spiess and Florian's hyperpath generating algorithm.
|
3
|
+
|
4
|
+
reference: Spiess, H. and Florian, M. (1989). Optimal strategies: A new
|
5
|
+
assignment model for transit networks. Transportation Research Part B 23(2),
|
6
|
+
83-102.
|
7
|
+
|
8
|
+
cpdef function:
|
9
|
+
|
10
|
+
- compute_SF_in
|
11
|
+
Compute Spiess & Florian optimal strategy (all-to-one).
|
12
|
+
|
13
|
+
cdef functions:
|
14
|
+
|
15
|
+
- _SF_in_first_pass_full
|
16
|
+
- _SF_in_second_pass
|
17
|
+
|
18
|
+
"""
|
19
|
+
|
20
|
+
import numpy as np
|
21
|
+
cimport numpy as cnp
|
22
|
+
|
23
|
+
from edsger.commons import DTYPE_PY, DTYPE_INF_PY
|
24
|
+
from edsger.commons cimport (
|
25
|
+
DTYPE_INF, UNLABELED, SCANNED, DTYPE_t, ElementState)
|
26
|
+
cimport edsger.pq_4ary_dec_0b as pq # priority queue
|
27
|
+
|
28
|
+
|
29
|
+
cpdef void compute_SF_in(
|
30
|
+
cnp.uint32_t[::1] csc_indptr,
|
31
|
+
cnp.uint32_t[::1] csc_edge_idx,
|
32
|
+
DTYPE_t[::1] c_a_vec,
|
33
|
+
DTYPE_t[::1] f_a_vec,
|
34
|
+
cnp.uint32_t[::1] tail_indices,
|
35
|
+
cnp.uint32_t[::1] head_indices,
|
36
|
+
cnp.uint32_t[::1] demand_indices,
|
37
|
+
DTYPE_t[::1] demand_values,
|
38
|
+
DTYPE_t[::1] v_a_vec,
|
39
|
+
DTYPE_t[::1] u_i_vec,
|
40
|
+
int vertex_count,
|
41
|
+
int dest_vert_index,
|
42
|
+
):
|
43
|
+
"""Compute Spiess & Florian optimal strategy (all-to-one).
|
44
|
+
"""
|
45
|
+
|
46
|
+
cdef:
|
47
|
+
int edge_count = tail_indices.shape[0]
|
48
|
+
|
49
|
+
# initialization
|
50
|
+
u_i_vec[<size_t>dest_vert_index] = 0.0
|
51
|
+
|
52
|
+
# vertex properties
|
53
|
+
# vertex frequency (inverse of the maximum delay)
|
54
|
+
f_i_vec = np.zeros(vertex_count, dtype=DTYPE_PY)
|
55
|
+
u_j_c_a_vec = DTYPE_INF_PY * np.ones(edge_count, dtype=DTYPE_PY)
|
56
|
+
v_i_vec = np.zeros(vertex_count, dtype=DTYPE_PY) # vertex volume
|
57
|
+
|
58
|
+
# edge properties
|
59
|
+
h_a_vec = np.zeros(edge_count, dtype=bool) # edge belonging to hyperpath
|
60
|
+
|
61
|
+
# first pass #
|
62
|
+
# ---------- #
|
63
|
+
|
64
|
+
_SF_in_first_pass_full(
|
65
|
+
csc_indptr,
|
66
|
+
csc_edge_idx,
|
67
|
+
c_a_vec,
|
68
|
+
f_a_vec,
|
69
|
+
tail_indices,
|
70
|
+
u_i_vec,
|
71
|
+
f_i_vec,
|
72
|
+
u_j_c_a_vec,
|
73
|
+
h_a_vec,
|
74
|
+
dest_vert_index
|
75
|
+
)
|
76
|
+
|
77
|
+
# second pass #
|
78
|
+
# ----------- #
|
79
|
+
|
80
|
+
cdef:
|
81
|
+
DTYPE_t u_r, _v_a_new, _v_i, u_i
|
82
|
+
size_t i, h_a_count
|
83
|
+
cnp.uint32_t vert_idx
|
84
|
+
|
85
|
+
v_i_vec = np.zeros(vertex_count, dtype=DTYPE_PY) # vertex volume
|
86
|
+
|
87
|
+
u_r = DTYPE_INF_PY
|
88
|
+
for i, vert_idx in enumerate(demand_indices):
|
89
|
+
|
90
|
+
v_i_vec[<size_t>vert_idx] = demand_values[i]
|
91
|
+
u_i = u_i_vec[<size_t>vert_idx]
|
92
|
+
|
93
|
+
if u_i < u_r:
|
94
|
+
|
95
|
+
u_r = u_i
|
96
|
+
|
97
|
+
# if the destination can be reached from any of the origins
|
98
|
+
if u_r < DTYPE_INF_PY:
|
99
|
+
|
100
|
+
# make sure f_i values are not zero
|
101
|
+
f_i_vec = np.where(
|
102
|
+
f_i_vec < MIN_FREQ_PY, MIN_FREQ_PY, f_i_vec
|
103
|
+
)
|
104
|
+
|
105
|
+
# sort the links with descreasing order of u_j + c_a
|
106
|
+
h_a_count = h_a_vec.sum()
|
107
|
+
masked_a = np.ma.array(-u_j_c_a_vec, mask=~h_a_vec)
|
108
|
+
edge_indices = np.argsort(masked_a).astype(np.uint32)
|
109
|
+
|
110
|
+
_SF_in_second_pass(
|
111
|
+
edge_indices,
|
112
|
+
tail_indices,
|
113
|
+
head_indices,
|
114
|
+
v_i_vec,
|
115
|
+
v_a_vec,
|
116
|
+
f_i_vec,
|
117
|
+
f_a_vec,
|
118
|
+
h_a_count
|
119
|
+
)
|
120
|
+
|
121
|
+
|
122
|
+
cdef void _SF_in_first_pass_full(
|
123
|
+
cnp.uint32_t[::1] csc_indptr,
|
124
|
+
cnp.uint32_t[::1] csc_edge_idx,
|
125
|
+
DTYPE_t[::1] c_a_vec,
|
126
|
+
DTYPE_t[::1] f_a_vec,
|
127
|
+
cnp.uint32_t[::1] tail_indices,
|
128
|
+
DTYPE_t[::1] u_i_vec,
|
129
|
+
DTYPE_t[::1] f_i_vec,
|
130
|
+
DTYPE_t[::1] u_j_c_a_vec,
|
131
|
+
cnp.uint8_t[::1] h_a_vec,
|
132
|
+
int dest_vert_index,
|
133
|
+
) nogil:
|
134
|
+
"""SF in first pass.
|
135
|
+
|
136
|
+
Note : all vertices are visited.
|
137
|
+
"""
|
138
|
+
|
139
|
+
cdef:
|
140
|
+
int edge_count = tail_indices.shape[0]
|
141
|
+
pq.PriorityQueue pqueue
|
142
|
+
ElementState edge_state
|
143
|
+
size_t i, edge_idx, tail_vert_idx
|
144
|
+
DTYPE_t u_j_c_a, u_i, f_i, beta, u_i_new, f_a
|
145
|
+
|
146
|
+
# initialization of the heap elements
|
147
|
+
# all nodes have INFINITY key and UNLABELED state
|
148
|
+
pq.init_pqueue(&pqueue, <size_t>edge_count, <size_t>edge_count)
|
149
|
+
|
150
|
+
# only the incoming edges of the target vertex are inserted into the
|
151
|
+
# priority queue
|
152
|
+
for i in range(<size_t>csc_indptr[<size_t>dest_vert_index],
|
153
|
+
<size_t>csc_indptr[<size_t>(dest_vert_index + 1)]):
|
154
|
+
edge_idx = csc_edge_idx[i]
|
155
|
+
pq.insert(&pqueue, edge_idx, c_a_vec[edge_idx])
|
156
|
+
u_j_c_a_vec[edge_idx] = c_a_vec[edge_idx]
|
157
|
+
|
158
|
+
# first pass
|
159
|
+
while pqueue.size > 0:
|
160
|
+
|
161
|
+
edge_idx = pq.extract_min(&pqueue)
|
162
|
+
u_j_c_a = pqueue.Elements[edge_idx].key
|
163
|
+
tail_vert_idx = <size_t>tail_indices[edge_idx]
|
164
|
+
u_i = u_i_vec[tail_vert_idx]
|
165
|
+
|
166
|
+
if u_i >= u_j_c_a:
|
167
|
+
|
168
|
+
f_i = f_i_vec[tail_vert_idx]
|
169
|
+
|
170
|
+
# compute the beta coefficient
|
171
|
+
if (u_i < DTYPE_INF) | (f_i > 0.0):
|
172
|
+
|
173
|
+
beta = f_i * u_i
|
174
|
+
|
175
|
+
else:
|
176
|
+
|
177
|
+
beta = 1.0
|
178
|
+
|
179
|
+
# update u_i
|
180
|
+
f_a = f_a_vec[edge_idx]
|
181
|
+
u_i_new = (beta + f_a * u_j_c_a) / (f_i + f_a)
|
182
|
+
u_i_vec[tail_vert_idx] = u_i_new
|
183
|
+
|
184
|
+
# update f_i
|
185
|
+
f_i_vec[tail_vert_idx] = f_i + f_a
|
186
|
+
|
187
|
+
# add the edge to hyperpath
|
188
|
+
h_a_vec[edge_idx] = 1
|
189
|
+
|
190
|
+
else:
|
191
|
+
|
192
|
+
u_i_new = u_i
|
193
|
+
|
194
|
+
# loop on incoming edges
|
195
|
+
for i in range(<size_t>csc_indptr[tail_vert_idx],
|
196
|
+
<size_t>csc_indptr[tail_vert_idx + 1]):
|
197
|
+
|
198
|
+
edge_idx = csc_edge_idx[i]
|
199
|
+
edge_state = pqueue.Elements[edge_idx].state
|
200
|
+
|
201
|
+
if edge_state != SCANNED:
|
202
|
+
|
203
|
+
# u_j of current edge = u_i of outgoing edge
|
204
|
+
u_j_c_a = u_i_new + c_a_vec[edge_idx]
|
205
|
+
|
206
|
+
if edge_state == UNLABELED:
|
207
|
+
|
208
|
+
pq.insert(&pqueue, edge_idx, u_j_c_a)
|
209
|
+
u_j_c_a_vec[edge_idx] = u_j_c_a
|
210
|
+
|
211
|
+
elif (pqueue.Elements[edge_idx].key > u_j_c_a):
|
212
|
+
|
213
|
+
pq.decrease_key(&pqueue, edge_idx, u_j_c_a)
|
214
|
+
u_j_c_a_vec[edge_idx] = u_j_c_a
|
215
|
+
|
216
|
+
pq.free_pqueue(&pqueue)
|
217
|
+
|
218
|
+
|
219
|
+
cdef void _SF_in_second_pass(
|
220
|
+
cnp.uint32_t[::1] edge_indices,
|
221
|
+
cnp.uint32_t[::1] tail_indices,
|
222
|
+
cnp.uint32_t[::1] head_indices,
|
223
|
+
DTYPE_t[::1] v_i_vec,
|
224
|
+
DTYPE_t[::1] v_a_vec,
|
225
|
+
DTYPE_t[::1] f_i_vec,
|
226
|
+
DTYPE_t[::1] f_a_vec,
|
227
|
+
size_t h_a_count
|
228
|
+
) nogil:
|
229
|
+
"""SF in second_pass.
|
230
|
+
"""
|
231
|
+
|
232
|
+
cdef:
|
233
|
+
size_t i, edge_idx, vert_idx
|
234
|
+
DTYPE_t v_i, f_i, f_a, v_a_new
|
235
|
+
|
236
|
+
for i in range(h_a_count):
|
237
|
+
|
238
|
+
edge_idx = <size_t>edge_indices[i]
|
239
|
+
vert_idx = <size_t>tail_indices[edge_idx]
|
240
|
+
|
241
|
+
v_i = v_i_vec[vert_idx]
|
242
|
+
f_i = f_i_vec[vert_idx]
|
243
|
+
f_a = f_a_vec[edge_idx]
|
244
|
+
|
245
|
+
# update v_a
|
246
|
+
v_a_new = v_i * f_a / f_i
|
247
|
+
v_a_vec[edge_idx] = v_a_new
|
248
|
+
v_i_vec[<size_t>head_indices[edge_idx]] += v_a_new
|
249
|
+
|
250
|
+
|
251
|
+
# ============================================================================ #
|
252
|
+
# tests #
|
253
|
+
# ============================================================================ #
|
254
|
+
|
255
|
+
|
256
|
+
from edsger.commons import MIN_FREQ_PY, INF_FREQ_PY
|
257
|
+
|
258
|
+
cpdef compute_SF_in_01():
|
259
|
+
"""
|
260
|
+
Single edge network.
|
261
|
+
|
262
|
+
This network has 1 edge and 2 vertices.
|
263
|
+
"""
|
264
|
+
|
265
|
+
volume = 1.0
|
266
|
+
|
267
|
+
f_a = MIN_FREQ_PY
|
268
|
+
|
269
|
+
csc_indptr = np.array([0, 0, 1], dtype=np.uint32)
|
270
|
+
csc_edge_idx = np.array([0], dtype=np.uint32)
|
271
|
+
c_a_vec = np.array([1.0], dtype=DTYPE_PY)
|
272
|
+
f_a_vec = np.array([f_a], dtype=DTYPE_PY)
|
273
|
+
v_a_vec = np.array([0.0], dtype=DTYPE_PY)
|
274
|
+
tail_indices = np.array([0], dtype=np.uint32)
|
275
|
+
head_indices = np.array([1], dtype=np.uint32)
|
276
|
+
demand_indices = np.array([0], dtype=np.uint32)
|
277
|
+
demand_values = np.array([volume], dtype=DTYPE_PY)
|
278
|
+
vertex_count = 2
|
279
|
+
u_i_vec = DTYPE_INF_PY * np.ones(vertex_count, dtype=DTYPE_PY)
|
280
|
+
dest_vert_index = 1
|
281
|
+
|
282
|
+
compute_SF_in(
|
283
|
+
csc_indptr,
|
284
|
+
csc_edge_idx,
|
285
|
+
c_a_vec,
|
286
|
+
f_a_vec,
|
287
|
+
tail_indices,
|
288
|
+
head_indices,
|
289
|
+
demand_indices,
|
290
|
+
demand_values,
|
291
|
+
v_a_vec,
|
292
|
+
u_i_vec,
|
293
|
+
vertex_count,
|
294
|
+
dest_vert_index,
|
295
|
+
)
|
296
|
+
|
297
|
+
assert v_a_vec[0] == volume
|
298
|
+
assert v_a_vec.shape[0] == 1
|
299
|
+
|
300
|
+
f_a = INF_FREQ_PY
|
301
|
+
f_a_vec = np.array([f_a], dtype=DTYPE_PY)
|
302
|
+
u_i_vec = DTYPE_INF_PY * np.ones(vertex_count, dtype=DTYPE_PY)
|
303
|
+
|
304
|
+
compute_SF_in(
|
305
|
+
csc_indptr,
|
306
|
+
csc_edge_idx,
|
307
|
+
c_a_vec,
|
308
|
+
f_a_vec,
|
309
|
+
tail_indices,
|
310
|
+
head_indices,
|
311
|
+
demand_indices,
|
312
|
+
demand_values,
|
313
|
+
v_a_vec,
|
314
|
+
u_i_vec,
|
315
|
+
vertex_count,
|
316
|
+
dest_vert_index,
|
317
|
+
)
|
318
|
+
|
319
|
+
assert v_a_vec[0] == volume
|
320
|
+
assert v_a_vec.shape[0] == 1
|
321
|
+
|
322
|
+
|
323
|
+
cpdef compute_SF_in_02():
|
324
|
+
"""
|
325
|
+
Two edges network.
|
326
|
+
|
327
|
+
This network has 2 edges and 2 vertices.
|
328
|
+
"""
|
329
|
+
|
330
|
+
volume = 1.0
|
331
|
+
|
332
|
+
csc_indptr = np.array([0, 0, 2], dtype=np.uint32)
|
333
|
+
csc_edge_idx = np.array([0, 1], dtype=np.uint32)
|
334
|
+
c_a_vec = np.array([1.0, 1.0], dtype=DTYPE_PY)
|
335
|
+
f_a_vec = np.array([2.0, 1.0], dtype=DTYPE_PY)
|
336
|
+
v_a_vec = np.array([0.0, 0.0], dtype=DTYPE_PY)
|
337
|
+
tail_indices = np.array([0, 0], dtype=np.uint32)
|
338
|
+
head_indices = np.array([1, 1], dtype=np.uint32)
|
339
|
+
demand_indices = np.array([0], dtype=np.uint32)
|
340
|
+
demand_values = np.array([volume], dtype=DTYPE_PY)
|
341
|
+
vertex_count = 2
|
342
|
+
u_i_vec = DTYPE_INF_PY * np.ones(vertex_count, dtype=DTYPE_PY)
|
343
|
+
dest_vert_index = 1
|
344
|
+
|
345
|
+
compute_SF_in(
|
346
|
+
csc_indptr,
|
347
|
+
csc_edge_idx,
|
348
|
+
c_a_vec,
|
349
|
+
f_a_vec,
|
350
|
+
tail_indices,
|
351
|
+
head_indices,
|
352
|
+
demand_indices,
|
353
|
+
demand_values,
|
354
|
+
v_a_vec,
|
355
|
+
u_i_vec,
|
356
|
+
vertex_count,
|
357
|
+
dest_vert_index,
|
358
|
+
)
|
359
|
+
|
360
|
+
assert v_a_vec[0] == 2. / 3.
|
361
|
+
assert v_a_vec[1] == 1. / 3.
|
362
|
+
assert v_a_vec.shape[0] == 2
|
363
|
+
|
364
|
+
|
365
|
+
# author : Francois Pacull
|
366
|
+
# copyright : Architecture & Performance
|
367
|
+
# email: francois.pacull@architecture-performance.fr
|
368
|
+
# license : MIT
|