Skip to content

Commit 5415516

Browse files
KeishiSgdalle
andauthored
Modify non_backtracking_matrix function's Return Type (#328)
* 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]>
1 parent be21c3a commit 5415516

File tree

3 files changed

+71
-4
lines changed

3 files changed

+71
-4
lines changed

src/linalg/nonbacktracking.jl

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,25 @@ function non_backtracking_matrix(g::AbstractGraph)
2626
end
2727
end
2828

29-
B = zeros(Float64, m, m)
30-
29+
nz = if is_directed(g)
30+
sum(indegree(g, v) * outdegree(g, v) for v in vertices(g))
31+
else
32+
sum(degree(g, v) * (degree(g, v) - 1) for v in vertices(g))
33+
end
34+
rowidx = sizehint!(Vector{Int}(), nz)
35+
colidx = sizehint!(Vector{Int}(), nz)
3136
for (e, u) in edgeidmap
3237
i, j = src(e), dst(e)
3338
for k in inneighbors(g, i)
3439
k == j && continue
3540
v = edgeidmap[Edge(k, i)]
36-
B[v, u] = 1
41+
42+
push!(rowidx, v)
43+
push!(colidx, u)
3744
end
3845
end
3946

47+
B = sparse(rowidx, colidx, ones(Int, length(rowidx)), m, m)
4048
return B, edgeidmap
4149
end
4250

test/linalg/nonbacktracking.jl

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
using SparseArrays
2+
3+
@testset "nonbacktracking" begin
4+
# Case: simple undirected
5+
ug = path_graph(5)
6+
B, edgemap = non_backtracking_matrix(ug)
7+
# | 1->2 | 2->3 | 3->4 | 4->5 | 2->1 | 3->2 | 4->3 | 5->4
8+
# -------------------------------------------------------------
9+
# 1->2 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0
10+
# 2->3 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0
11+
# 3->4 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0
12+
# 4->5 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0
13+
# 2->1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0
14+
# 3->2 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0
15+
# 4->3 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0
16+
# 5->4 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0
17+
B_ = [
18+
0 1 0 0 0 0 0 0
19+
0 0 1 0 0 0 0 0
20+
0 0 0 1 0 0 0 0
21+
0 0 0 0 0 0 0 0
22+
0 0 0 0 0 0 0 0
23+
0 0 0 0 1 0 0 0
24+
0 0 0 0 0 1 0 0
25+
0 0 0 0 0 0 1 0
26+
]
27+
egs = Edge.([(1, 2), (2, 3), (3, 4), (4, 5), (2, 1), (3, 2), (4, 3), (5, 4)])
28+
@test typeof(B) <: SparseMatrixCSC
29+
@test B == B_
30+
31+
# Case: simple directed
32+
dg = SimpleDiGraph(5)
33+
add_edge!(dg, 1, 2)
34+
add_edge!(dg, 2, 3)
35+
add_edge!(dg, 1, 3)
36+
add_edge!(dg, 3, 4)
37+
add_edge!(dg, 3, 5)
38+
add_edge!(dg, 4, 3)
39+
B, edgemap = non_backtracking_matrix(dg)
40+
# | 1->2 | 1->3 | 2->3 | 3->4 | 3->5 | 4->3
41+
# -----------------------------------------------
42+
# 1->2 | 0 | 0 | 1 | 0 | 0 | 0
43+
# 1->3 | 0 | 0 | 0 | 1 | 1 | 0
44+
# 2->3 | 0 | 0 | 0 | 1 | 1 | 0
45+
# 3->4 | 0 | 0 | 0 | 0 | 0 | 0
46+
# 3->5 | 0 | 0 | 0 | 0 | 0 | 0
47+
# 4->3 | 0 | 0 | 0 | 0 | 1 | 0
48+
B_ = [
49+
0 0 1 0 0 0
50+
0 0 0 1 1 0
51+
0 0 0 1 1 0
52+
0 0 0 0 0 0
53+
0 0 0 0 0 0
54+
0 0 0 0 1 0
55+
]
56+
egs = Edge.([(1, 2), (1, 3), (2, 3), (3, 4), (3, 5), (4, 3)])
57+
@test typeof(B) <: SparseMatrixCSC
58+
@test B == B_
59+
end

test/linalg/runtests.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ using SparseArrays
44
using LinearAlgebra
55
const linalgtestdir = dirname(@__FILE__)
66

7-
tests = ["graphmatrices", "spectral"]
7+
tests = ["graphmatrices", "spectral", "nonbacktracking"]
88

99
@testset "Graphs.LinAlg" begin
1010
for t in tests

0 commit comments

Comments
 (0)