From d6df31aed9503a9174548e2389aa7c1deeea2fc8 Mon Sep 17 00:00:00 2001 From: Guillaume Dalle <22795598+gdalle@users.noreply.github.com> Date: Tue, 8 Apr 2025 08:35:13 +0200 Subject: [PATCH 1/3] Speed up LF order --- src/graph.jl | 10 +++------- src/order.jl | 3 ++- test/order.jl | 9 +++++---- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/graph.jl b/src/graph.jl index 948ac32e..23331789 100644 --- a/src/graph.jl +++ b/src/graph.jl @@ -270,13 +270,9 @@ end degree(g::AdjacencyGraph{T,false}, v::Integer) where {T} = g.S.colptr[v + 1] - g.S.colptr[v] function degree(g::AdjacencyGraph{T,true}, v::Integer) where {T} - d = 0 - for u in neighbors(g, v) - if u != v - d += 1 - end - end - return d + neigh = neighbors(g, v) + has_selfloop = insorted(v, neigh) + return g.S.colptr[v + 1] - g.S.colptr[v] - has_selfloop end nb_edges(g::AdjacencyGraph{T,false}) where {T} = nnz(g.S) ÷ 2 diff --git a/src/order.jl b/src/order.jl index 9cefc1b2..98d7ffca 100644 --- a/src/order.jl +++ b/src/order.jl @@ -80,7 +80,8 @@ Instance of [`AbstractOrder`](@ref) which sorts vertices using their degree in t struct LargestFirst <: AbstractOrder end function vertices(g::AdjacencyGraph, ::LargestFirst) - criterion(v) = degree(g, v) + degrees = map(Base.Fix1(degree, g), vertices(g)) + criterion(v) = degrees[v] return sort(vertices(g); by=criterion, rev=true) end diff --git a/test/order.jl b/test/order.jl index 594d3be8..16b8fde2 100644 --- a/test/order.jl +++ b/test/order.jl @@ -63,12 +63,13 @@ end; @testset "LargestFirst" begin for has_diagonal in (false, true) A = sparse([ - 0 1 0 - 1 0 1 - 0 1 0 + 0 1 0 0 + 1 0 1 1 + 0 1 0 1 + 0 1 1 0 ]) ag = AdjacencyGraph(A; has_diagonal) - @test vertices(ag, LargestFirst()) == [2, 1, 3] + @test vertices(ag, LargestFirst()) == [2, 3, 4, 1] end A = sparse([ From 7ead437c32920f434a8bfe0783039f09aa7f1ae8 Mon Sep 17 00:00:00 2001 From: Guillaume Dalle <22795598+gdalle@users.noreply.github.com> Date: Tue, 8 Apr 2025 08:53:41 +0200 Subject: [PATCH 2/3] Optimize visited filling --- src/order.jl | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/src/order.jl b/src/order.jl index 98d7ffca..223e539b 100644 --- a/src/order.jl +++ b/src/order.jl @@ -88,10 +88,9 @@ end function vertices(bg::BipartiteGraph{T}, ::Val{side}, ::LargestFirst) where {T,side} other_side = 3 - side n = nb_vertices(bg, Val(side)) - visited = falses(n) # necessary for distance-2 neighborhoods + visited = fill(false, n) # necessary for distance-2 neighborhoods degrees_dist2 = zeros(T, n) for v in vertices(bg, Val(side)) - fill!(visited, false) for u in neighbors(bg, Val(side), v) for w in neighbors(bg, Val(other_side), u) if w != v && !visited[w] @@ -100,6 +99,11 @@ function vertices(bg::BipartiteGraph{T}, ::Val{side}, ::LargestFirst) where {T,s end end end + for u in neighbors(bg, Val(side), v) + for w in neighbors(bg, Val(other_side), u) + visited[w] = false # reset only the toggled ones to false + end + end end criterion(v) = degrees_dist2[v] return sort(vertices(bg, Val(side)); by=criterion, rev=true) @@ -331,13 +335,14 @@ end function vertices( g::AdjacencyGraph{T}, order::DynamicDegreeBasedOrder{degtype,direction} ) where {T<:Integer,degtype,direction} + true_degrees = degrees = T[degree(g, v) for v in vertices(g)] if degree_increasing(; degtype, direction) degrees = zeros(T, nb_vertices(g)) else - degrees = T[degree(g, v) for v in vertices(g)] + degrees = true_degrees end db = DegreeBuckets( - T, degrees, maximum_degree(g); reproduce_colpack=order.reproduce_colpack + T, degrees, maximum(true_degrees); reproduce_colpack=order.reproduce_colpack ) π = T[] sizehint!(π, nb_vertices(g)) @@ -360,15 +365,21 @@ function vertices( # compute dist-2 degrees in an optimized way n = nb_vertices(g, Val(side)) degrees_dist2 = zeros(T, n) - dist2_neighbor = falses(n) + visited = fill(false, n) for v in vertices(g, Val(side)) - fill!(dist2_neighbor, false) for w1 in neighbors(g, Val(side), v) for w2 in neighbors(g, Val(other_side), w1) - dist2_neighbor[w2] = true + if w != v && !visited[w] + degrees_dist2[v] += 1 + visited[w2] = true + end + end + end + for w1 in neighbors(g, Val(side), v) + for w2 in neighbors(g, Val(other_side), w1) + visited[w2] = false end end - degrees_dist2[v] = sum(dist2_neighbor) end if degree_increasing(; degtype, direction) degrees = zeros(T, n) @@ -379,7 +390,7 @@ function vertices( db = DegreeBuckets(T, degrees, maxd2; reproduce_colpack=order.reproduce_colpack) π = T[] sizehint!(π, n) - visited = falses(n) + fill!(visited, false) for _ in 1:nb_vertices(g, Val(side)) u = pop_next_candidate!(db; direction) direction == :low2high ? push!(π, u) : pushfirst!(π, u) @@ -394,7 +405,11 @@ function vertices( update_bucket!(db, v; degtype, direction) end end - fill!(visited, false) + for w in neighbors(g, Val(side), u) + for v in neighbors(g, Val(other_side), w) + visited[v] = false # reset only the toggled ones to false + end + end end return π end From e332ee823f0bd934cff83c1c28b3a9635f37c85e Mon Sep 17 00:00:00 2001 From: Guillaume Dalle <22795598+gdalle@users.noreply.github.com> Date: Tue, 8 Apr 2025 09:40:12 +0200 Subject: [PATCH 3/3] Fix --- src/order.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/order.jl b/src/order.jl index 223e539b..76491d39 100644 --- a/src/order.jl +++ b/src/order.jl @@ -369,7 +369,7 @@ function vertices( for v in vertices(g, Val(side)) for w1 in neighbors(g, Val(side), v) for w2 in neighbors(g, Val(other_side), w1) - if w != v && !visited[w] + if w2 != v && !visited[w2] degrees_dist2[v] += 1 visited[w2] = true end