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..76491d39 100644 --- a/src/order.jl +++ b/src/order.jl @@ -80,17 +80,17 @@ 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 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] @@ -99,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) @@ -330,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)) @@ -359,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 w2 != v && !visited[w2] + 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) @@ -378,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) @@ -393,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 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([