Skip to content

Commit

Permalink
Modify non_backtracking_matrix function's Return Type (#328)
Browse files Browse the repository at this point in the history
* modified to use a sparse matrix in non_backtracking_matrix

* modified to reserve a capacity of size 'nz' & used 'append!' instead of 'push!'

* added tests for non_backtracking_matrix

* modified to achieve zero allocation

* reverted

* Apply suggestions from code review

---------

Co-authored-by: Guillaume Dalle <[email protected]>
  • Loading branch information
KeishiS and gdalle authored May 4, 2024
1 parent be21c3a commit 5415516
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 4 deletions.
14 changes: 11 additions & 3 deletions src/linalg/nonbacktracking.jl
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,25 @@ function non_backtracking_matrix(g::AbstractGraph)
end
end

B = zeros(Float64, m, m)

nz = if is_directed(g)
sum(indegree(g, v) * outdegree(g, v) for v in vertices(g))
else
sum(degree(g, v) * (degree(g, v) - 1) for v in vertices(g))
end
rowidx = sizehint!(Vector{Int}(), nz)
colidx = sizehint!(Vector{Int}(), nz)
for (e, u) in edgeidmap
i, j = src(e), dst(e)
for k in inneighbors(g, i)
k == j && continue
v = edgeidmap[Edge(k, i)]
B[v, u] = 1

push!(rowidx, v)
push!(colidx, u)
end
end

B = sparse(rowidx, colidx, ones(Int, length(rowidx)), m, m)
return B, edgeidmap
end

Expand Down
59 changes: 59 additions & 0 deletions test/linalg/nonbacktracking.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
using SparseArrays

@testset "nonbacktracking" begin
# Case: simple undirected
ug = path_graph(5)
B, edgemap = non_backtracking_matrix(ug)
# | 1->2 | 2->3 | 3->4 | 4->5 | 2->1 | 3->2 | 4->3 | 5->4
# -------------------------------------------------------------
# 1->2 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0
# 2->3 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0
# 3->4 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0
# 4->5 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0
# 2->1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0
# 3->2 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0
# 4->3 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0
# 5->4 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0
B_ = [
0 1 0 0 0 0 0 0
0 0 1 0 0 0 0 0
0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0
0 0 0 0 0 1 0 0
0 0 0 0 0 0 1 0
]
egs = Edge.([(1, 2), (2, 3), (3, 4), (4, 5), (2, 1), (3, 2), (4, 3), (5, 4)])
@test typeof(B) <: SparseMatrixCSC
@test B == B_

# Case: simple directed
dg = SimpleDiGraph(5)
add_edge!(dg, 1, 2)
add_edge!(dg, 2, 3)
add_edge!(dg, 1, 3)
add_edge!(dg, 3, 4)
add_edge!(dg, 3, 5)
add_edge!(dg, 4, 3)
B, edgemap = non_backtracking_matrix(dg)
# | 1->2 | 1->3 | 2->3 | 3->4 | 3->5 | 4->3
# -----------------------------------------------
# 1->2 | 0 | 0 | 1 | 0 | 0 | 0
# 1->3 | 0 | 0 | 0 | 1 | 1 | 0
# 2->3 | 0 | 0 | 0 | 1 | 1 | 0
# 3->4 | 0 | 0 | 0 | 0 | 0 | 0
# 3->5 | 0 | 0 | 0 | 0 | 0 | 0
# 4->3 | 0 | 0 | 0 | 0 | 1 | 0
B_ = [
0 0 1 0 0 0
0 0 0 1 1 0
0 0 0 1 1 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 1 0
]
egs = Edge.([(1, 2), (1, 3), (2, 3), (3, 4), (3, 5), (4, 3)])
@test typeof(B) <: SparseMatrixCSC
@test B == B_
end
2 changes: 1 addition & 1 deletion test/linalg/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ using SparseArrays
using LinearAlgebra
const linalgtestdir = dirname(@__FILE__)

tests = ["graphmatrices", "spectral"]
tests = ["graphmatrices", "spectral", "nonbacktracking"]

@testset "Graphs.LinAlg" begin
for t in tests
Expand Down

0 comments on commit 5415516

Please sign in to comment.