Skip to content

Commit c7471c3

Browse files
yuehhuasbromberger
authored andcommitted
Fix adjacency & Laplacian matrices for weighted graph (#48)
* Fix adjacency & Laplacian matrices for weighted graph * Correct the laplacian_matrix, add degree_matrix, add package dependencies Test passed Fix * Ignore Manifest.toml * Add dependency Add dependencies Add LinearAlgebra Add Test * Test degree_matrix * Refine error and test on error * Add tests
1 parent 379adf6 commit c7471c3

File tree

7 files changed

+81
-10
lines changed

7 files changed

+81
-10
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
*.jl.cov
22
*.jl.*.cov
33
*.jl.mem
4+
Manifest.toml

Project.toml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
name = "SimpleWeightedGraphs"
2+
uuid = "47aef6b3-ad0c-573a-a1e2-d07658019622"
3+
version = "1.1.0"
4+
5+
[deps]
6+
LightGraphs = "093fc24a-ae57-5d10-9952-331d41423f4d"
7+
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
8+
Markdown = "d6f4376e-aef5-505a-96c1-9c027394607a"
9+
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
10+
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

src/SimpleWeightedGraphs.jl

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ import LightGraphs:
1515
has_vertex, has_edge, inneighbors, outneighbors,
1616
indegree, outdegree, degree, has_self_loops, num_self_loops,
1717

18-
add_vertices!, adjacency_matrix, weights, connected_components, cartesian_product,
18+
add_vertices!, adjacency_matrix, laplacian_matrix, weights,
19+
connected_components, cartesian_product,
1920

2021
AbstractGraphFormat, loadgraph, loadgraphs, savegraph,
2122
pagerank, induced_subgraph
@@ -33,7 +34,8 @@ export
3334
get_weight,
3435
WGraph,
3536
WDiGraph,
36-
SWGFormat
37+
SWGFormat,
38+
degree_matrix
3739

3840
include("simpleweightededge.jl")
3941

src/overrides.jl

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,35 @@ function add_vertices!(g::AbstractSimpleWeightedGraph, n::Integer)
1010
return true
1111
end
1212

13-
function adjacency_matrix(g::AbstractSimpleWeightedGraph, T::DataType=Int; dir::Symbol=:out)
13+
function degree_matrix(g::AbstractSimpleWeightedGraph, T::DataType=weighttype(g); dir::Symbol=:out)
14+
if is_directed(g)
15+
if dir == :out
16+
d = vec(sum(g.weights, dims=1))
17+
elseif dir == :in
18+
d = vec(sum(g.weights, dims=2))
19+
elseif dir == :both
20+
d = vec(sum(g.weights, dims=1)) + vec(sum(g.weights, dims=2))
21+
else
22+
throw(DomainError(dir, "invalid argument, only accept :in, :out and :both"))
23+
end
24+
else
25+
d = vec(sum(g.weights, dims=1))
26+
end
27+
return SparseMatrixCSC(T.(diagm(0=>d)))
28+
end
29+
30+
function adjacency_matrix(g::AbstractSimpleWeightedGraph, T::DataType=weighttype(g); dir::Symbol=:out)
1431
if dir == :out
15-
return SparseMatrixCSC(T.(LinearAlgebra.fillstored!(copy(g.weights), 1))')
32+
return SparseMatrixCSC(T.(copy(g.weights))')
1633
else
17-
return T.(LinearAlgebra.fillstored!(copy(g.weights), 1))
34+
return T.(copy(g.weights))
1835
end
1936
end
2037

38+
function laplacian_matrix(g::AbstractSimpleWeightedGraph, T::DataType=weighttype(g); dir::Symbol=:out)
39+
degree_matrix(g, T; dir=dir) - adjacency_matrix(g, T; dir=dir)
40+
end
41+
2142
function pagerank(g::SimpleWeightedDiGraph, α=0.85, n=100::Integer, ϵ=1.0e-6)
2243
A = weights(g)
2344
S = vec(sum(A, dims=1))
@@ -123,4 +144,3 @@ function induced_subgraph(g::T, vlist::AbstractVector{U}) where T <: AbstractSim
123144
newg.weights = new_weights
124145
return newg, Vector{E}(vlist)
125146
end
126-

test/overrides.jl

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,66 @@
11
@testset "Overrides" begin
22
g3 = SimpleWeightedGraph(PathGraph(5))
3+
g3_d = [1. 0. 0. 0. 0.;
4+
0. 2. 0. 0. 0.;
5+
0. 0. 2. 0. 0.;
6+
0. 0. 0. 2. 0.;
7+
0. 0. 0. 0. 1.]
8+
g3_l = [1. -1. 0. 0. 0.;
9+
-1. 2. -1. 0. 0.;
10+
0. -1. 2. -1. 0.;
11+
0. 0. -1. 2. -1.;
12+
0. 0. 0. -1. 1.]
313
g5 = SimpleWeightedDiGraph(4)
14+
g5_din = [0. 0. 0. 0.;
15+
0. 2. 0. 0.;
16+
0. 0. 3. 0.;
17+
0. 0. 0. 5.]
18+
g5_dout = [3. 0. 0. 0.;
19+
0. 2. 0. 0.;
20+
0. 0. 5. 0.;
21+
0. 0. 0. 0.]
22+
g5_dboth = [3. 0. 0. 0.;
23+
0. 4. 0. 0.;
24+
0. 0. 8. 0.;
25+
0. 0. 0. 5.]
26+
g5_l = [3. -2. -1. 0.;
27+
0. 2. -2. 0.;
28+
0. 0. 5. -5.;
29+
0. 0. 0. 0.]
430

531
for g in testgraphs(g3)
632
@test @inferred(adjacency_matrix(g, Bool)) == adjacency_matrix(g, Bool; dir=:out)
733
@test @inferred(adjacency_matrix(g))[3, 2] == 1
34+
@test degree_matrix(g, Float64, dir=:out) == g3_d
35+
@test degree_matrix(g, Float64, dir=:out) == degree_matrix(g, Float64, dir=:in)
836
@test adjacency_matrix(g)[2, 4] == 0
937
@test adjacency_matrix(g; dir=:out) == adjacency_matrix(g; dir=:in)'
38+
@test issymmetric(laplacian_matrix(g))
39+
@test laplacian_matrix(g, Float64) g3_l
1040
@test g[1:3] == SimpleWeightedGraph{eltype(g), weighttype(g)}(PathGraph(3))
1141
gx = copy(g)
1242
add_edge!(gx, 2, 3, 99)
1343
gi = gx[2:4]
1444
@test weights(gi)[1, 2] == 99
15-
45+
1646
h = @inferred(cartesian_product(g, g))
1747
@test nv(h) == 25
1848
@test ne(h) == 40
1949
gz = g3[1:4]
2050
add_edge!(gz, 3, 4, 87)
21-
@test weights(cartesian_product(g3,gz))[11,12]==weights(gz)[3,4]
51+
@test weights(cartesian_product(g3,gz))[11,12]==weights(gz)[3,4]
2252
end
2353

2454
add_edge!(g5, 1, 2, 2); add_edge!(g5, 2, 3, 2); add_edge!(g5, 1, 3, 1); add_edge!(g5, 3, 4, 5)
2555
for g in testdigraphs(g5)
26-
@test @inferred(adjacency_matrix(g, Bool)) == adjacency_matrix(g, Bool; dir=:out)
56+
@test degree_matrix(g, Float64, dir=:out) == g5_dout
57+
@test degree_matrix(g, Float64, dir=:in) == g5_din
58+
@test degree_matrix(g, Float64, dir=:both) == g5_dboth
59+
@test_throws DomainError degree_matrix(g, dir=:other)
60+
@test @inferred(adjacency_matrix(g, Int64)) == adjacency_matrix(g, Int64; dir=:out)
2761
@test adjacency_matrix(g; dir=:out) == adjacency_matrix(g; dir=:in)'
62+
@test !issymmetric(laplacian_matrix(g))
63+
@test laplacian_matrix(g, Float64) g5_l
2864
@test @inferred(pagerank(g))[3] 0.2266 atol=0.001
2965
@test length(@inferred(pagerank(g))) == nv(g)
3066
@test_throws ErrorException pagerank(g, 2)
@@ -35,4 +71,3 @@
3571
@test weights(g[2:3])[1, 2] == 2
3672
end
3773
end
38-

test/runtests.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using LightGraphs
22
using SimpleWeightedGraphs
3+
using LinearAlgebra
34
using Test
45

56
testdir = dirname(@__FILE__)

test/simpleweightededge.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,14 @@ import SimpleWeightedGraphs.SimpleWeightedEdge
2020

2121
@test src(ep1) == src(ep2) == src(ep3) == src(ep) == s
2222
@test dst(ep1) == dst(ep2) == dst(ep3) == dst(ep) == s + one(T)
23+
@test weight(ep1) == one(T)
2324

2425
@test eltype(t) == typeof(s)
2526
@test SimpleWeightedEdge(t) == e3
2627
@test SimpleWeightedEdge(t1) == SimpleWeightedEdge(t2)
2728
@test SimpleWeightedEdge(t1) == SimpleWeightedEdge{UInt8, Float64}(t1) == SimpleWeightedEdge{Int16, Float64}(t1)
2829
@test SimpleWeightedEdge{Int64, Float64}(ep1) == e3
30+
@test Tuple(ep1) == t2
2931

3032
@test reverse(ep1) == re
3133
@test sprint(show, ep1) == "Edge 1 => 2 with weight 1"

0 commit comments

Comments
 (0)