@@ -203,9 +203,6 @@ function DegreeBucketsSMC(::Type{T}, degrees::Vector{T}, dmax::Integer) where {T
203203 return DegreeBucketsSMC (degrees, bucket_storage, bucket_low, bucket_high, positions)
204204end
205205
206- maxdeg (db:: DegreeBucketsColPack ) = length (db. buckets) - 1
207- maxdeg (db:: DegreeBucketsSMC ) = length (db. bucket_low) - 1
208-
209206function nonempty_bucket (db:: DegreeBucketsSMC , d:: Integer )
210207 return db. bucket_high[d + 1 ] >= db. bucket_low[d + 1 ]
211208end
@@ -220,31 +217,14 @@ function degree_increasing(; degtype, direction)
220217 return increasing
221218end
222219
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
248228 end
249229 end
250230 if db isa DegreeBucketsColPack
@@ -255,21 +235,22 @@ function pop_next_candidate!(db::AbstractDegreeBuckets; direction::Symbol)
255235 (; bucket_storage, bucket_high) = db
256236 high = bucket_high[candidate_degree + 1 ]
257237 candidate = bucket_storage[high]
258- bucket_storage[high] = - 1
259238 bucket_high[candidate_degree + 1 ] -= 1
260239 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
263244end
264245
265246function update_bucket! (
266- db:: DegreeBucketsSMC , v:: Integer ; degtype:: Symbol , direction:: Symbol
247+ db:: DegreeBucketsSMC , v:: Integer , d :: Integer ; degtype:: Symbol , direction:: Symbol
267248)
268249 (; 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]
271251 # select previous or next bucket for the move
272252 if degree_increasing (; degtype, direction)
253+ high = bucket_high[d + 1 ]
273254 # move the vertex w located at the end of the current bucket to v's position
274255 w = bucket_storage[high]
275256 bucket_storage[p] = w
@@ -279,14 +260,15 @@ function update_bucket!(
279260 bucket_high[d + 1 ] -= 1
280261 # move v to the beginning of the next bucket (!= ColPack)
281262 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 ]
283264 bucket_storage[low_new - 1 ] = v
284265 # grow next bucket to the left
285266 bucket_low[d_new + 1 ] -= 1
286267 # update v's stats
287268 degrees[v] = d_new
288269 positions[v] = low_new - 1
289270 else
271+ low = bucket_low[d + 1 ]
290272 # move the vertex w located at the start of the current bucket to v's position (!= ColPack)
291273 w = bucket_storage[low]
292274 bucket_storage[p] = w
@@ -296,7 +278,7 @@ function update_bucket!(
296278 bucket_low[d + 1 ] += 1
297279 # move v to the end of the previous bucket
298280 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 ]
300282 bucket_storage[high_new + 1 ] = v
301283 # grow previous bucket to the right
302284 bucket_high[d_new + 1 ] += 1
@@ -308,22 +290,22 @@ function update_bucket!(
308290end
309291
310292function update_bucket! (
311- db:: DegreeBucketsColPack , v:: Integer ; degtype:: Symbol , direction:: Symbol
293+ db:: DegreeBucketsColPack , v:: Integer , d :: Integer ; degtype:: Symbol , direction:: Symbol
312294)
313295 (; degrees, buckets, positions) = db
314- d, p = degrees[v], positions[v]
296+ p = positions[v]
315297 bucket = buckets[d + 1 ]
316298 # select previous or next bucket for the move
317299 d_new = degree_increasing (; degtype, direction) ? d + 1 : d - 1
318300 bucket_new = buckets[d_new + 1 ]
319301 # put v at the end of its bucket by swapping
320302 w = bucket[end ]
321303 bucket[p] = w
322- positions[w] = p
323304 bucket[end ] = v
305+ positions[w] = p
324306 positions[v] = length (bucket)
325307 # move v from the old bucket to the new one
326- @assert pop! (bucket) == v
308+ pop! (bucket)
327309 push! (bucket_new, v)
328310 degrees[v] = d_new
329311 positions[v] = length (bucket_new)
@@ -333,26 +315,35 @@ end
333315function vertices (
334316 g:: AdjacencyGraph{T} , :: DynamicDegreeBasedOrder{degtype,direction,reproduce_colpack}
335317) 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 )
338320 if degree_increasing (; degtype, direction)
339321 fill! (degrees, zero (T))
340322 end
341323 db = if reproduce_colpack
342- DegreeBucketsColPack (T, degrees, max_degrees )
324+ DegreeBucketsColPack (T, degrees, dmax )
343325 else
344- DegreeBucketsSMC (T, degrees, max_degrees )
326+ DegreeBucketsSMC (T, degrees, dmax )
345327 end
346328 nv = nb_vertices (g)
347329 π = 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)
349332 for index in index_π
350- u = pop_next_candidate! (db; direction)
333+ u, du = pop_next_candidate! (db; degree_range)
334+
351335 π[index] = u
352336 for v in neighbors (g, u)
353337 ! 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
356347 end
357348 end
358349 return π
@@ -366,42 +357,50 @@ function vertices(
366357 other_side = 3 - side
367358 # compute dist-2 degrees in an optimized way
368359 n = nb_vertices (g, Val (side))
369- degrees_dist2 = degrees = zeros (T, n)
360+ degrees = zeros (T, n)
370361 visited = zeros (T, n)
371362 for v in vertices (g, Val (side))
372363 for w1 in neighbors (g, Val (side), v)
373364 for w2 in neighbors (g, Val (other_side), w1)
374365 if w2 != v && visited[w2] != v
375- degrees_dist2 [v] += 1
366+ degrees [v] += 1
376367 visited[w2] = v
377368 end
378369 end
379370 end
380371 end
381- maxd2 = maximum (degrees_dist2 )
372+ dmax = maximum (degrees )
382373 if degree_increasing (; degtype, direction)
383374 fill! (degrees, zero (T))
384375 end
385376 db = if reproduce_colpack
386- DegreeBucketsColPack (T, degrees, maxd2 )
377+ DegreeBucketsColPack (T, degrees, dmax )
387378 else
388- DegreeBucketsSMC (T, degrees, maxd2 )
379+ DegreeBucketsSMC (T, degrees, dmax )
389380 end
390381 π = Vector {T} (undef, n)
391382 index_π = (direction == :low2high ) ? (1 : n) : (n: - 1 : 1 )
383+ degree_range = (direction == :low2high ) ? reverse (0 : dmax) : (0 : dmax)
392384 for index in index_π
393- u = pop_next_candidate! (db; direction )
385+ u, du = pop_next_candidate! (db; degree_range )
394386 π[index] = u
395387 for w in neighbors (g, Val (side), u)
396388 for v in neighbors (g, Val (other_side), w)
397389 if v != u && visited[v] != - u
398390 # Use -u such that we don't need to fill "visited" with 0 after the computation of the dist-2 degrees
399391 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)
402395 end
403396 end
404397 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
405404 end
406405 return π
407406end
0 commit comments