@@ -220,31 +220,14 @@ function degree_increasing(; degtype, direction)
220220 return increasing
221221end
222222
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
223+ function pop_next_candidate! (db:: AbstractDegreeBuckets ; degree_range:: OrdinalRange )
224+ (; degrees) = db
225+ # degree_range is used to avoid going through the empty parts of 0:dmax
226+ candidate_degree = - 1
227+ for d in degree_range
228+ if nonempty_bucket (db, d)
229+ candidate_degree = d
230+ break
248231 end
249232 end
250233 if db isa DegreeBucketsColPack
@@ -255,21 +238,22 @@ function pop_next_candidate!(db::AbstractDegreeBuckets; direction::Symbol)
255238 (; bucket_storage, bucket_high) = db
256239 high = bucket_high[candidate_degree + 1 ]
257240 candidate = bucket_storage[high]
258- bucket_storage[high] = - 1
259241 bucket_high[candidate_degree + 1 ] -= 1
260242 end
261- mark_ordered! (db, candidate)
262- return candidate
243+ # mark as ordered
244+ degrees[candidate] = - 1
245+ # returning candidate degree is useful to update degree_range
246+ return candidate, candidate_degree
263247end
264248
265249function update_bucket! (
266- db:: DegreeBucketsSMC , v:: Integer ; degtype:: Symbol , direction:: Symbol
250+ db:: DegreeBucketsSMC , v:: Integer , d :: Integer ; degtype:: Symbol , direction:: Symbol
267251)
268252 (; 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 ]
253+ p = positions[v]
271254 # select previous or next bucket for the move
272255 if degree_increasing (; degtype, direction)
256+ high = bucket_high[d + 1 ]
273257 # move the vertex w located at the end of the current bucket to v's position
274258 w = bucket_storage[high]
275259 bucket_storage[p] = w
@@ -279,14 +263,15 @@ function update_bucket!(
279263 bucket_high[d + 1 ] -= 1
280264 # move v to the beginning of the next bucket (!= ColPack)
281265 d_new = d + 1
282- low_new, high_new = bucket_low[d_new + 1 ], bucket_high [d_new + 1 ]
266+ low_new = bucket_low[d_new + 1 ]
283267 bucket_storage[low_new - 1 ] = v
284268 # grow next bucket to the left
285269 bucket_low[d_new + 1 ] -= 1
286270 # update v's stats
287271 degrees[v] = d_new
288272 positions[v] = low_new - 1
289273 else
274+ low = bucket_low[d + 1 ]
290275 # move the vertex w located at the start of the current bucket to v's position (!= ColPack)
291276 w = bucket_storage[low]
292277 bucket_storage[p] = w
@@ -296,7 +281,7 @@ function update_bucket!(
296281 bucket_low[d + 1 ] += 1
297282 # move v to the end of the previous bucket
298283 d_new = d - 1
299- low_new, high_new = bucket_low[d_new + 1 ], bucket_high[d_new + 1 ]
284+ high_new = bucket_high[d_new + 1 ]
300285 bucket_storage[high_new + 1 ] = v
301286 # grow previous bucket to the right
302287 bucket_high[d_new + 1 ] += 1
@@ -308,22 +293,22 @@ function update_bucket!(
308293end
309294
310295function update_bucket! (
311- db:: DegreeBucketsColPack , v:: Integer ; degtype:: Symbol , direction:: Symbol
296+ db:: DegreeBucketsColPack , v:: Integer , d :: Integer ; degtype:: Symbol , direction:: Symbol
312297)
313298 (; degrees, buckets, positions) = db
314- d, p = degrees[v], positions[v]
299+ p = positions[v]
315300 bucket = buckets[d + 1 ]
316301 # select previous or next bucket for the move
317302 d_new = degree_increasing (; degtype, direction) ? d + 1 : d - 1
318303 bucket_new = buckets[d_new + 1 ]
319304 # put v at the end of its bucket by swapping
320305 w = bucket[end ]
321306 bucket[p] = w
322- positions[w] = p
323307 bucket[end ] = v
308+ positions[w] = p
324309 positions[v] = length (bucket)
325310 # move v from the old bucket to the new one
326- @assert pop! (bucket) == v
311+ pop! (bucket)
327312 push! (bucket_new, v)
328313 degrees[v] = d_new
329314 positions[v] = length (bucket_new)
@@ -333,26 +318,35 @@ end
333318function vertices (
334319 g:: AdjacencyGraph{T} , :: DynamicDegreeBasedOrder{degtype,direction,reproduce_colpack}
335320) 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 )
321+ degrees = T[degree (g, v) for v in vertices (g)]
322+ dmax = maximum (degrees )
338323 if degree_increasing (; degtype, direction)
339324 fill! (degrees, zero (T))
340325 end
341326 db = if reproduce_colpack
342- DegreeBucketsColPack (T, degrees, max_degrees )
327+ DegreeBucketsColPack (T, degrees, dmax )
343328 else
344- DegreeBucketsSMC (T, degrees, max_degrees )
329+ DegreeBucketsSMC (T, degrees, dmax )
345330 end
346331 nv = nb_vertices (g)
347332 π = Vector {T} (undef, nv)
348- index_π = (direction == :low2high ) ? (1 : nv) : (nv: - 1 : 1 )
333+ index_π = (direction == :low2high ) ? (1 : nv) : reverse (1 : nv)
334+ degree_range = (direction == :low2high ) ? reverse (0 : dmax) : (0 : dmax)
349335 for index in index_π
350- u = pop_next_candidate! (db; direction)
336+ u, du = pop_next_candidate! (db; degree_range)
337+
351338 π[index] = u
352339 for v in neighbors (g, u)
353340 ! has_diagonal (g) || (u == v && continue )
354- already_ordered (db, v) && continue
355- update_bucket! (db, v; degtype, direction)
341+ dv = degrees[v]
342+ dv == - 1 && continue
343+ update_bucket! (db, v, dv; degtype, direction)
344+ end
345+ # no need to look much further than du next time
346+ degree_range = if direction == :low2high
347+ reverse (0 : min (du + 1 , dmax))
348+ else
349+ max (du - 1 , 0 ): dmax
356350 end
357351 end
358352 return π
@@ -366,42 +360,50 @@ function vertices(
366360 other_side = 3 - side
367361 # compute dist-2 degrees in an optimized way
368362 n = nb_vertices (g, Val (side))
369- degrees_dist2 = degrees = zeros (T, n)
363+ degrees = zeros (T, n)
370364 visited = zeros (T, n)
371365 for v in vertices (g, Val (side))
372366 for w1 in neighbors (g, Val (side), v)
373367 for w2 in neighbors (g, Val (other_side), w1)
374368 if w2 != v && visited[w2] != v
375- degrees_dist2 [v] += 1
369+ degrees [v] += 1
376370 visited[w2] = v
377371 end
378372 end
379373 end
380374 end
381- maxd2 = maximum (degrees_dist2 )
375+ dmax = maximum (degrees )
382376 if degree_increasing (; degtype, direction)
383377 fill! (degrees, zero (T))
384378 end
385379 db = if reproduce_colpack
386- DegreeBucketsColPack (T, degrees, maxd2 )
380+ DegreeBucketsColPack (T, degrees, dmax )
387381 else
388- DegreeBucketsSMC (T, degrees, maxd2 )
382+ DegreeBucketsSMC (T, degrees, dmax )
389383 end
390384 π = Vector {T} (undef, n)
391385 index_π = (direction == :low2high ) ? (1 : n) : (n: - 1 : 1 )
386+ degree_range = (direction == :low2high ) ? reverse (0 : dmax) : (0 : dmax)
392387 for index in index_π
393- u = pop_next_candidate! (db; direction )
388+ u, du = pop_next_candidate! (db; degree_range )
394389 π[index] = u
395390 for w in neighbors (g, Val (side), u)
396391 for v in neighbors (g, Val (other_side), w)
397392 if v != u && visited[v] != - u
398393 # Use -u such that we don't need to fill "visited" with 0 after the computation of the dist-2 degrees
399394 visited[v] = - u
400- already_ordered (db, v) && continue
401- update_bucket! (db, v; degtype, direction)
395+ dv = degrees[v]
396+ dv == - 1 && continue
397+ update_bucket! (db, v, dv; degtype, direction)
402398 end
403399 end
404400 end
401+ # no need to look much further than du next time
402+ degree_range = if direction == :low2high
403+ reverse (0 : min (du + 1 , dmax))
404+ else
405+ max (du - 1 , 0 ): dmax
406+ end
405407 end
406408 return π
407409end
0 commit comments