Skip to content

Commit bcca5b8

Browse files
authored
Speed up LargestFirst order (#241)
* Speed up LF order * Optimize visited filling * Fix
1 parent 5572dab commit bcca5b8

3 files changed

Lines changed: 35 additions & 22 deletions

File tree

src/graph.jl

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -270,13 +270,9 @@ end
270270
degree(g::AdjacencyGraph{T,false}, v::Integer) where {T} = g.S.colptr[v + 1] - g.S.colptr[v]
271271

272272
function degree(g::AdjacencyGraph{T,true}, v::Integer) where {T}
273-
d = 0
274-
for u in neighbors(g, v)
275-
if u != v
276-
d += 1
277-
end
278-
end
279-
return d
273+
neigh = neighbors(g, v)
274+
has_selfloop = insorted(v, neigh)
275+
return g.S.colptr[v + 1] - g.S.colptr[v] - has_selfloop
280276
end
281277

282278
nb_edges(g::AdjacencyGraph{T,false}) where {T} = nnz(g.S) ÷ 2

src/order.jl

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -80,17 +80,17 @@ Instance of [`AbstractOrder`](@ref) which sorts vertices using their degree in t
8080
struct LargestFirst <: AbstractOrder end
8181

8282
function vertices(g::AdjacencyGraph, ::LargestFirst)
83-
criterion(v) = degree(g, v)
83+
degrees = map(Base.Fix1(degree, g), vertices(g))
84+
criterion(v) = degrees[v]
8485
return sort(vertices(g); by=criterion, rev=true)
8586
end
8687

8788
function vertices(bg::BipartiteGraph{T}, ::Val{side}, ::LargestFirst) where {T,side}
8889
other_side = 3 - side
8990
n = nb_vertices(bg, Val(side))
90-
visited = falses(n) # necessary for distance-2 neighborhoods
91+
visited = fill(false, n) # necessary for distance-2 neighborhoods
9192
degrees_dist2 = zeros(T, n)
9293
for v in vertices(bg, Val(side))
93-
fill!(visited, false)
9494
for u in neighbors(bg, Val(side), v)
9595
for w in neighbors(bg, Val(other_side), u)
9696
if w != v && !visited[w]
@@ -99,6 +99,11 @@ function vertices(bg::BipartiteGraph{T}, ::Val{side}, ::LargestFirst) where {T,s
9999
end
100100
end
101101
end
102+
for u in neighbors(bg, Val(side), v)
103+
for w in neighbors(bg, Val(other_side), u)
104+
visited[w] = false # reset only the toggled ones to false
105+
end
106+
end
102107
end
103108
criterion(v) = degrees_dist2[v]
104109
return sort(vertices(bg, Val(side)); by=criterion, rev=true)
@@ -330,13 +335,14 @@ end
330335
function vertices(
331336
g::AdjacencyGraph{T}, order::DynamicDegreeBasedOrder{degtype,direction}
332337
) where {T<:Integer,degtype,direction}
338+
true_degrees = degrees = T[degree(g, v) for v in vertices(g)]
333339
if degree_increasing(; degtype, direction)
334340
degrees = zeros(T, nb_vertices(g))
335341
else
336-
degrees = T[degree(g, v) for v in vertices(g)]
342+
degrees = true_degrees
337343
end
338344
db = DegreeBuckets(
339-
T, degrees, maximum_degree(g); reproduce_colpack=order.reproduce_colpack
345+
T, degrees, maximum(true_degrees); reproduce_colpack=order.reproduce_colpack
340346
)
341347
π = T[]
342348
sizehint!(π, nb_vertices(g))
@@ -359,15 +365,21 @@ function vertices(
359365
# compute dist-2 degrees in an optimized way
360366
n = nb_vertices(g, Val(side))
361367
degrees_dist2 = zeros(T, n)
362-
dist2_neighbor = falses(n)
368+
visited = fill(false, n)
363369
for v in vertices(g, Val(side))
364-
fill!(dist2_neighbor, false)
365370
for w1 in neighbors(g, Val(side), v)
366371
for w2 in neighbors(g, Val(other_side), w1)
367-
dist2_neighbor[w2] = true
372+
if w2 != v && !visited[w2]
373+
degrees_dist2[v] += 1
374+
visited[w2] = true
375+
end
376+
end
377+
end
378+
for w1 in neighbors(g, Val(side), v)
379+
for w2 in neighbors(g, Val(other_side), w1)
380+
visited[w2] = false
368381
end
369382
end
370-
degrees_dist2[v] = sum(dist2_neighbor)
371383
end
372384
if degree_increasing(; degtype, direction)
373385
degrees = zeros(T, n)
@@ -378,7 +390,7 @@ function vertices(
378390
db = DegreeBuckets(T, degrees, maxd2; reproduce_colpack=order.reproduce_colpack)
379391
π = T[]
380392
sizehint!(π, n)
381-
visited = falses(n)
393+
fill!(visited, false)
382394
for _ in 1:nb_vertices(g, Val(side))
383395
u = pop_next_candidate!(db; direction)
384396
direction == :low2high ? push!(π, u) : pushfirst!(π, u)
@@ -393,7 +405,11 @@ function vertices(
393405
update_bucket!(db, v; degtype, direction)
394406
end
395407
end
396-
fill!(visited, false)
408+
for w in neighbors(g, Val(side), u)
409+
for v in neighbors(g, Val(other_side), w)
410+
visited[v] = false # reset only the toggled ones to false
411+
end
412+
end
397413
end
398414
return π
399415
end

test/order.jl

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,13 @@ end;
6363
@testset "LargestFirst" begin
6464
for has_diagonal in (false, true)
6565
A = sparse([
66-
0 1 0
67-
1 0 1
68-
0 1 0
66+
0 1 0 0
67+
1 0 1 1
68+
0 1 0 1
69+
0 1 1 0
6970
])
7071
ag = AdjacencyGraph(A; has_diagonal)
71-
@test vertices(ag, LargestFirst()) == [2, 1, 3]
72+
@test vertices(ag, LargestFirst()) == [2, 3, 4, 1]
7273
end
7374

7475
A = sparse([

0 commit comments

Comments
 (0)