Skip to content

Commit 0c2771a

Browse files
authored
Remove some useless operations in dynamic orders (#248)
* Remove some useless operations in dynamic orders * Codecov
1 parent c668010 commit 0c2771a

File tree

2 files changed

+57
-56
lines changed

2 files changed

+57
-56
lines changed

src/order.jl

Lines changed: 55 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -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)
204204
end
205205

206-
maxdeg(db::DegreeBucketsColPack) = length(db.buckets) - 1
207-
maxdeg(db::DegreeBucketsSMC) = length(db.bucket_low) - 1
208-
209206
function nonempty_bucket(db::DegreeBucketsSMC, d::Integer)
210207
return db.bucket_high[d + 1] >= db.bucket_low[d + 1]
211208
end
@@ -220,31 +217,14 @@ function degree_increasing(; degtype, direction)
220217
return increasing
221218
end
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
263244
end
264245

265246
function 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!(
308290
end
309291

310292
function 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
333315
function 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 π
407406
end

test/order.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ end;
9797
IncidenceDegree(; reproduce_colpack=true),
9898
DynamicLargestFirst(),
9999
DynamicLargestFirst(; reproduce_colpack=true),
100+
DynamicDegreeBasedOrder{:forward,:high2low}(),
101+
DynamicDegreeBasedOrder{:forward,:high2low}(; reproduce_colpack=true),
100102
]
101103
@testset "AdjacencyGraph" begin
102104
for (n, p) in Iterators.product(20:20:100, 0.0:0.1:0.2)

0 commit comments

Comments
 (0)