@@ -203,9 +203,6 @@ function DegreeBucketsSMC(::Type{T}, degrees::Vector{T}, dmax::Integer) where {T
203
203
return DegreeBucketsSMC (degrees, bucket_storage, bucket_low, bucket_high, positions)
204
204
end
205
205
206
- maxdeg (db:: DegreeBucketsColPack ) = length (db. buckets) - 1
207
- maxdeg (db:: DegreeBucketsSMC ) = length (db. bucket_low) - 1
208
-
209
206
function nonempty_bucket (db:: DegreeBucketsSMC , d:: Integer )
210
207
return db. bucket_high[d + 1 ] >= db. bucket_low[d + 1 ]
211
208
end
@@ -220,31 +217,14 @@ function degree_increasing(; degtype, direction)
220
217
return increasing
221
218
end
222
219
223
- function mark_ordered! (db:: AbstractDegreeBuckets{T} , v:: Integer ) where {T}
224
- db. degrees[v] = - 1
225
- db. positions[v] = typemin (T)
226
- return nothing
227
- end
228
-
229
- already_ordered (db:: AbstractDegreeBuckets , v:: Integer ) = db. degrees[v] == - 1
230
-
231
- function pop_next_candidate! (db:: AbstractDegreeBuckets ; direction:: Symbol )
232
- dmax = maxdeg (db)
233
- if direction == :low2high
234
- candidate_degree = dmax + 1
235
- for d in dmax: - 1 : 0
236
- if nonempty_bucket (db, d)
237
- candidate_degree = d
238
- break
239
- end
240
- end
241
- else
242
- candidate_degree = - 1
243
- for d in 0 : dmax
244
- if nonempty_bucket (db, d)
245
- candidate_degree = d
246
- break
247
- end
220
+ function pop_next_candidate! (db:: AbstractDegreeBuckets ; degree_range:: OrdinalRange )
221
+ (; degrees) = db
222
+ # degree_range is used to avoid going through the empty parts of 0:dmax
223
+ candidate_degree = - 1
224
+ for d in degree_range
225
+ if nonempty_bucket (db, d)
226
+ candidate_degree = d
227
+ break
248
228
end
249
229
end
250
230
if db isa DegreeBucketsColPack
@@ -255,21 +235,22 @@ function pop_next_candidate!(db::AbstractDegreeBuckets; direction::Symbol)
255
235
(; bucket_storage, bucket_high) = db
256
236
high = bucket_high[candidate_degree + 1 ]
257
237
candidate = bucket_storage[high]
258
- bucket_storage[high] = - 1
259
238
bucket_high[candidate_degree + 1 ] -= 1
260
239
end
261
- mark_ordered! (db, candidate)
262
- return candidate
240
+ # mark as ordered
241
+ degrees[candidate] = - 1
242
+ # returning candidate degree is useful to update degree_range
243
+ return candidate, candidate_degree
263
244
end
264
245
265
246
function update_bucket! (
266
- db:: DegreeBucketsSMC , v:: Integer ; degtype:: Symbol , direction:: Symbol
247
+ db:: DegreeBucketsSMC , v:: Integer , d :: Integer ; degtype:: Symbol , direction:: Symbol
267
248
)
268
249
(; degrees, bucket_storage, bucket_low, bucket_high, positions) = db
269
- d, p = degrees[v], positions[v]
270
- low, high = bucket_low[d + 1 ], bucket_high[d + 1 ]
250
+ p = positions[v]
271
251
# select previous or next bucket for the move
272
252
if degree_increasing (; degtype, direction)
253
+ high = bucket_high[d + 1 ]
273
254
# move the vertex w located at the end of the current bucket to v's position
274
255
w = bucket_storage[high]
275
256
bucket_storage[p] = w
@@ -279,14 +260,15 @@ function update_bucket!(
279
260
bucket_high[d + 1 ] -= 1
280
261
# move v to the beginning of the next bucket (!= ColPack)
281
262
d_new = d + 1
282
- low_new, high_new = bucket_low[d_new + 1 ], bucket_high [d_new + 1 ]
263
+ low_new = bucket_low[d_new + 1 ]
283
264
bucket_storage[low_new - 1 ] = v
284
265
# grow next bucket to the left
285
266
bucket_low[d_new + 1 ] -= 1
286
267
# update v's stats
287
268
degrees[v] = d_new
288
269
positions[v] = low_new - 1
289
270
else
271
+ low = bucket_low[d + 1 ]
290
272
# move the vertex w located at the start of the current bucket to v's position (!= ColPack)
291
273
w = bucket_storage[low]
292
274
bucket_storage[p] = w
@@ -296,7 +278,7 @@ function update_bucket!(
296
278
bucket_low[d + 1 ] += 1
297
279
# move v to the end of the previous bucket
298
280
d_new = d - 1
299
- low_new, high_new = bucket_low[d_new + 1 ], bucket_high[d_new + 1 ]
281
+ high_new = bucket_high[d_new + 1 ]
300
282
bucket_storage[high_new + 1 ] = v
301
283
# grow previous bucket to the right
302
284
bucket_high[d_new + 1 ] += 1
@@ -308,22 +290,22 @@ function update_bucket!(
308
290
end
309
291
310
292
function update_bucket! (
311
- db:: DegreeBucketsColPack , v:: Integer ; degtype:: Symbol , direction:: Symbol
293
+ db:: DegreeBucketsColPack , v:: Integer , d :: Integer ; degtype:: Symbol , direction:: Symbol
312
294
)
313
295
(; degrees, buckets, positions) = db
314
- d, p = degrees[v], positions[v]
296
+ p = positions[v]
315
297
bucket = buckets[d + 1 ]
316
298
# select previous or next bucket for the move
317
299
d_new = degree_increasing (; degtype, direction) ? d + 1 : d - 1
318
300
bucket_new = buckets[d_new + 1 ]
319
301
# put v at the end of its bucket by swapping
320
302
w = bucket[end ]
321
303
bucket[p] = w
322
- positions[w] = p
323
304
bucket[end ] = v
305
+ positions[w] = p
324
306
positions[v] = length (bucket)
325
307
# move v from the old bucket to the new one
326
- @assert pop! (bucket) == v
308
+ pop! (bucket)
327
309
push! (bucket_new, v)
328
310
degrees[v] = d_new
329
311
positions[v] = length (bucket_new)
@@ -333,26 +315,35 @@ end
333
315
function vertices (
334
316
g:: AdjacencyGraph{T} , :: DynamicDegreeBasedOrder{degtype,direction,reproduce_colpack}
335
317
) where {T<: Integer ,degtype,direction,reproduce_colpack}
336
- true_degrees = degrees = T[degree (g, v) for v in vertices (g)]
337
- max_degrees = maximum (true_degrees )
318
+ degrees = T[degree (g, v) for v in vertices (g)]
319
+ dmax = maximum (degrees )
338
320
if degree_increasing (; degtype, direction)
339
321
fill! (degrees, zero (T))
340
322
end
341
323
db = if reproduce_colpack
342
- DegreeBucketsColPack (T, degrees, max_degrees )
324
+ DegreeBucketsColPack (T, degrees, dmax )
343
325
else
344
- DegreeBucketsSMC (T, degrees, max_degrees )
326
+ DegreeBucketsSMC (T, degrees, dmax )
345
327
end
346
328
nv = nb_vertices (g)
347
329
π = Vector {T} (undef, nv)
348
- index_π = (direction == :low2high ) ? (1 : nv) : (nv: - 1 : 1 )
330
+ index_π = (direction == :low2high ) ? (1 : nv) : reverse (1 : nv)
331
+ degree_range = (direction == :low2high ) ? reverse (0 : dmax) : (0 : dmax)
349
332
for index in index_π
350
- u = pop_next_candidate! (db; direction)
333
+ u, du = pop_next_candidate! (db; degree_range)
334
+
351
335
π[index] = u
352
336
for v in neighbors (g, u)
353
337
! has_diagonal (g) || (u == v && continue )
354
- already_ordered (db, v) && continue
355
- update_bucket! (db, v; degtype, direction)
338
+ dv = degrees[v]
339
+ dv == - 1 && continue
340
+ update_bucket! (db, v, dv; degtype, direction)
341
+ end
342
+ # no need to look much further than du next time
343
+ degree_range = if direction == :low2high
344
+ reverse (0 : min (du + 1 , dmax))
345
+ else
346
+ max (du - 1 , 0 ): dmax
356
347
end
357
348
end
358
349
return π
@@ -366,42 +357,50 @@ function vertices(
366
357
other_side = 3 - side
367
358
# compute dist-2 degrees in an optimized way
368
359
n = nb_vertices (g, Val (side))
369
- degrees_dist2 = degrees = zeros (T, n)
360
+ degrees = zeros (T, n)
370
361
visited = zeros (T, n)
371
362
for v in vertices (g, Val (side))
372
363
for w1 in neighbors (g, Val (side), v)
373
364
for w2 in neighbors (g, Val (other_side), w1)
374
365
if w2 != v && visited[w2] != v
375
- degrees_dist2 [v] += 1
366
+ degrees [v] += 1
376
367
visited[w2] = v
377
368
end
378
369
end
379
370
end
380
371
end
381
- maxd2 = maximum (degrees_dist2 )
372
+ dmax = maximum (degrees )
382
373
if degree_increasing (; degtype, direction)
383
374
fill! (degrees, zero (T))
384
375
end
385
376
db = if reproduce_colpack
386
- DegreeBucketsColPack (T, degrees, maxd2 )
377
+ DegreeBucketsColPack (T, degrees, dmax )
387
378
else
388
- DegreeBucketsSMC (T, degrees, maxd2 )
379
+ DegreeBucketsSMC (T, degrees, dmax )
389
380
end
390
381
π = Vector {T} (undef, n)
391
382
index_π = (direction == :low2high ) ? (1 : n) : (n: - 1 : 1 )
383
+ degree_range = (direction == :low2high ) ? reverse (0 : dmax) : (0 : dmax)
392
384
for index in index_π
393
- u = pop_next_candidate! (db; direction )
385
+ u, du = pop_next_candidate! (db; degree_range )
394
386
π[index] = u
395
387
for w in neighbors (g, Val (side), u)
396
388
for v in neighbors (g, Val (other_side), w)
397
389
if v != u && visited[v] != - u
398
390
# Use -u such that we don't need to fill "visited" with 0 after the computation of the dist-2 degrees
399
391
visited[v] = - u
400
- already_ordered (db, v) && continue
401
- update_bucket! (db, v; degtype, direction)
392
+ dv = degrees[v]
393
+ dv == - 1 && continue
394
+ update_bucket! (db, v, dv; degtype, direction)
402
395
end
403
396
end
404
397
end
398
+ # no need to look much further than du next time
399
+ degree_range = if direction == :low2high
400
+ reverse (0 : min (du + 1 , dmax))
401
+ else
402
+ max (du - 1 , 0 ): dmax
403
+ end
405
404
end
406
405
return π
407
406
end
0 commit comments