edsger 0.1.1__cp312-cp312-win32.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.
@@ -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
Binary file
edsger/star.pyx ADDED
@@ -0,0 +1,356 @@
1
+ """
2
+ Forward and reverse star representations of networks.
3
+
4
+
5
+ cpdef functions:
6
+
7
+ - convert_graph_to_csr_uint32
8
+ Convert an edge dataframe in COO format into CSR format, with uint32
9
+ data.
10
+ - convert_graph_to_csc_uint32
11
+ Convert an edge dataframe in COO format into CSC format, with uint32
12
+ data.
13
+ - convert_graph_to_csr_float64
14
+ Convert an edge dataframe in COO format into CSR format, with float64
15
+ data.
16
+ - convert_graph_to_csc_float64
17
+ Convert an edge dataframe in COO format into CSC format, with float64
18
+ data.
19
+
20
+
21
+ cdef functions:
22
+
23
+ - _coo_to_csr_uint32
24
+ - _coo_to_csc_uint32
25
+ - _coo_to_csr_float64
26
+ - _coo_to_csc_float64
27
+ """
28
+
29
+ import numpy as np
30
+ cimport numpy as cnp
31
+
32
+
33
+ cpdef convert_graph_to_csr_uint32(edges, tail, head, data, vertex_count):
34
+ """
35
+ Convert an edge dataframe in COO format into CSR format, with uint32
36
+ data.
37
+
38
+ Parameters
39
+ ----------
40
+ edges : pandas.core.frame.DataFrame
41
+ The edges dataframe.
42
+ tail : str
43
+ The column name in the edges dataframe for the tail vertex index.
44
+ head : str
45
+ The column name in the edges dataframe for the head vertex index.
46
+ data : str
47
+ The column name in the edges dataframe for the int edge attribute.
48
+ vertex_count : int
49
+ The vertex count in the given network edges.
50
+
51
+ Returns
52
+ -------
53
+ tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray]
54
+ """
55
+
56
+ fs_indptr = np.zeros(
57
+ vertex_count + 1, dtype=np.uint32
58
+ ) # make sure it is filled with zeros
59
+ edge_count = len(edges)
60
+ fs_indices = np.empty(edge_count, dtype=np.uint32)
61
+ fs_data = np.empty(edge_count, dtype=np.uint32)
62
+
63
+ _coo_to_csr_uint32(
64
+ edges[tail].values.astype(np.uint32),
65
+ edges[head].values.astype(np.uint32),
66
+ edges[data].values.astype(np.uint32),
67
+ fs_indptr,
68
+ fs_indices,
69
+ fs_data,
70
+ )
71
+
72
+ return fs_indptr, fs_indices, fs_data
73
+
74
+
75
+ cpdef convert_graph_to_csc_uint32(edges, tail, head, data, vertex_count):
76
+ """
77
+ Convert an edge dataframe in COO format into CSC format, with uint32
78
+ data.
79
+
80
+ Parameters
81
+ ----------
82
+ edges : pandas.core.frame.DataFrame
83
+ The edges dataframe.
84
+ tail : str
85
+ The column name in the edges dataframe for the tail vertex index.
86
+ head : str
87
+ The column name in the edges dataframe for the head vertex index.
88
+ data : str
89
+ The column name in the edges dataframe for the int edge attribute.
90
+ vertex_count : int
91
+ The vertex count in the given network edges.
92
+
93
+ Returns
94
+ -------
95
+ tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray]
96
+ """
97
+
98
+ rs_indptr = np.zeros(
99
+ vertex_count + 1, dtype=np.uint32
100
+ ) # make sure it is filled with zeros
101
+ edge_count = len(edges)
102
+ rs_indices = np.empty(edge_count, dtype=np.uint32)
103
+ rs_data = np.empty(edge_count, dtype=np.uint32)
104
+
105
+ _coo_to_csc_uint32(
106
+ edges[tail].values.astype(np.uint32),
107
+ edges[head].values.astype(np.uint32),
108
+ edges[data].values.astype(np.uint32),
109
+ rs_indptr,
110
+ rs_indices,
111
+ rs_data,
112
+ )
113
+
114
+ return rs_indptr, rs_indices, rs_data
115
+
116
+
117
+ cpdef convert_graph_to_csr_float64(edges, tail, head, data, vertex_count):
118
+ """
119
+ Convert an edge dataframe in COO format into CSR format, with float64
120
+ data.
121
+
122
+ Parameters
123
+ ----------
124
+ edges : pandas.core.frame.DataFrame
125
+ The edges dataframe.
126
+ tail : str
127
+ The column name in the edges dataframe for the tail vertex index.
128
+ head : str
129
+ The column name in the edges dataframe for the head vertex index.
130
+ data : str
131
+ The column name in the edges dataframe for the real edge attribute.
132
+ vertex_count : int
133
+ The vertex count in the given network edges.
134
+
135
+ Returns
136
+ -------
137
+ tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray]
138
+ """
139
+
140
+ fs_indptr = np.zeros(
141
+ vertex_count + 1, dtype=np.uint32
142
+ ) # make sure it is filled with zeros
143
+ edge_count = len(edges)
144
+ fs_indices = np.empty(edge_count, dtype=np.uint32)
145
+ fs_data = np.empty(edge_count, dtype=np.float64)
146
+
147
+ _coo_to_csr_float64(
148
+ edges[tail].values.astype(np.uint32),
149
+ edges[head].values.astype(np.uint32),
150
+ edges[data].values.astype(np.float64),
151
+ fs_indptr,
152
+ fs_indices,
153
+ fs_data,
154
+ )
155
+
156
+ return fs_indptr, fs_indices, fs_data
157
+
158
+
159
+ cpdef convert_graph_to_csc_float64(edges, tail, head, data, vertex_count):
160
+ """
161
+ Convert an edge dataframe in COO format into CSC format, with float64
162
+ data.
163
+
164
+ Parameters
165
+ ----------
166
+ edges : pandas.core.frame.DataFrame
167
+ The edges dataframe.
168
+ tail : str
169
+ The column name in the edges dataframe for the tail vertex index.
170
+ head : str
171
+ The column name in the edges dataframe for the head vertex index.
172
+ data : str
173
+ The column name in the edges dataframe for the real edge attribute.
174
+ vertex_count : int
175
+ The vertex count in the given network edges.
176
+
177
+ Returns
178
+ -------
179
+ tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray]
180
+ """
181
+
182
+ rs_indptr = np.zeros(
183
+ vertex_count + 1, dtype=np.uint32
184
+ ) # make sure it is filled with zeros
185
+ edge_count = len(edges)
186
+ rs_indices = np.empty(edge_count, dtype=np.uint32)
187
+ rs_data = np.empty(edge_count, dtype=np.float64)
188
+
189
+ _coo_to_csc_float64(
190
+ edges[tail].values.astype(np.uint32),
191
+ edges[head].values.astype(np.uint32),
192
+ edges[data].values.astype(np.float64),
193
+ rs_indptr,
194
+ rs_indices,
195
+ rs_data,
196
+ )
197
+
198
+ return rs_indptr, rs_indices, rs_data
199
+
200
+
201
+ cdef void _coo_to_csr_uint32(
202
+ cnp.uint32_t [::1] Ai,
203
+ cnp.uint32_t [::1] Aj,
204
+ cnp.uint32_t [::1] Ax,
205
+ cnp.uint32_t [::1] Bp,
206
+ cnp.uint32_t [::1] Bj,
207
+ cnp.uint32_t [::1] Bx) nogil noexcept:
208
+
209
+ cdef:
210
+ size_t i, row, dest
211
+ size_t n_vert = <size_t>(Bp.shape[0] - 1)
212
+ size_t n_edge = <size_t>Bj.shape[0]
213
+ cnp.uint32_t temp, cumsum, last
214
+
215
+ for i in range(n_edge):
216
+ Bp[<size_t>Ai[i]] += 1
217
+
218
+ cumsum = 0
219
+ for i in range(n_vert):
220
+ temp = Bp[i]
221
+ Bp[i] = cumsum
222
+ cumsum += temp
223
+ Bp[n_vert] = <cnp.uint32_t>n_edge
224
+
225
+ for i in range(n_edge):
226
+ row = <size_t>Ai[i]
227
+ dest = <size_t>Bp[row]
228
+ Bj[dest] = Aj[i]
229
+ Bx[dest] = Ax[i]
230
+ Bp[row] += 1
231
+
232
+ last = 0
233
+ for i in range(n_vert + 1):
234
+ temp = Bp[i]
235
+ Bp[i] = last
236
+ last = temp
237
+
238
+
239
+ cdef void _coo_to_csc_uint32(
240
+ cnp.uint32_t [::1] Ai,
241
+ cnp.uint32_t [::1] Aj,
242
+ cnp.uint32_t [::1] Ax,
243
+ cnp.uint32_t [::1] Bp,
244
+ cnp.uint32_t [::1] Bi,
245
+ cnp.uint32_t [::1] Bx) nogil:
246
+
247
+ cdef:
248
+ size_t i, col, dest
249
+ size_t n_vert = <size_t>(Bp.shape[0] - 1)
250
+ size_t n_edge = <size_t>Bi.shape[0]
251
+ cnp.uint32_t temp, cumsum, last
252
+
253
+ for i in range(n_edge):
254
+ Bp[<size_t>Aj[i]] += 1
255
+
256
+ cumsum = 0
257
+ for i in range(n_vert):
258
+ temp = Bp[i]
259
+ Bp[i] = cumsum
260
+ cumsum += temp
261
+ Bp[<size_t>n_vert] = <cnp.uint32_t>n_edge
262
+
263
+ for i in range(n_edge):
264
+ col = <size_t>Aj[i]
265
+ dest = <size_t>Bp[col]
266
+ Bi[dest] = Ai[i]
267
+ Bx[dest] = Ax[i]
268
+ Bp[col] += 1
269
+
270
+ last = 0
271
+ for i in range(n_vert + 1):
272
+ temp = Bp[i]
273
+ Bp[i] = last
274
+ last = temp
275
+
276
+
277
+ cpdef void _coo_to_csr_float64(
278
+ cnp.uint32_t [::1] Ai,
279
+ cnp.uint32_t [::1] Aj,
280
+ cnp.float64_t [::1] Ax,
281
+ cnp.uint32_t [::1] Bp,
282
+ cnp.uint32_t [::1] Bj,
283
+ cnp.float64_t [::1] Bx) nogil noexcept:
284
+
285
+ cdef:
286
+ size_t i, row, dest
287
+ size_t n_vert = <size_t>(Bp.shape[0] - 1)
288
+ size_t n_edge = <size_t>Bj.shape[0]
289
+ cnp.uint32_t temp, cumsum, last
290
+
291
+ for i in range(n_edge):
292
+ Bp[<size_t>Ai[i]] += 1
293
+
294
+ cumsum = 0
295
+ for i in range(n_vert):
296
+ temp = Bp[i]
297
+ Bp[i] = cumsum
298
+ cumsum += temp
299
+ Bp[n_vert] = <cnp.uint32_t>n_edge
300
+
301
+ for i in range(n_edge):
302
+ row = <size_t>Ai[i]
303
+ dest = <size_t>Bp[row]
304
+ Bj[dest] = Aj[i]
305
+ Bx[dest] = Ax[i]
306
+ Bp[row] += 1
307
+
308
+ last = 0
309
+ for i in range(n_vert + 1):
310
+ temp = Bp[i]
311
+ Bp[i] = last
312
+ last = temp
313
+
314
+
315
+ cpdef void _coo_to_csc_float64(
316
+ cnp.uint32_t [::1] Ai,
317
+ cnp.uint32_t [::1] Aj,
318
+ cnp.float64_t [::1] Ax,
319
+ cnp.uint32_t [::1] Bp,
320
+ cnp.uint32_t [::1] Bi,
321
+ cnp.float64_t [::1] Bx) nogil noexcept:
322
+
323
+ cdef:
324
+ size_t i, col, dest
325
+ size_t n_vert = <size_t>(Bp.shape[0] - 1)
326
+ size_t n_edge = <size_t>Bi.shape[0]
327
+ cnp.uint32_t temp, cumsum, last
328
+
329
+ for i in range(n_edge):
330
+ Bp[<size_t>Aj[i]] += 1
331
+
332
+ cumsum = 0
333
+ for i in range(n_vert):
334
+ temp = Bp[i]
335
+ Bp[i] = cumsum
336
+ cumsum += temp
337
+ Bp[<size_t>n_vert] = <cnp.uint32_t>n_edge
338
+
339
+ for i in range(n_edge):
340
+ col = <size_t>Aj[i]
341
+ dest = <size_t>Bp[col]
342
+ Bi[dest] = Ai[i]
343
+ Bx[dest] = Ax[i]
344
+ Bp[col] += 1
345
+
346
+ last = 0
347
+ for i in range(n_vert + 1):
348
+ temp = Bp[i]
349
+ Bp[i] = last
350
+ last = temp
351
+
352
+
353
+ # author : Francois Pacull
354
+ # copyright : Architecture & Performance
355
+ # email: francois.pacull@architecture-performance.fr
356
+ # license : MIT