|
| 1 | +""" |
| 2 | + SimpleWeightedGraphs |
| 3 | +
|
| 4 | +A package for graphs with edge weights and no self-loops, stored as sparse adjacency matrices. |
| 5 | +""" |
1 | 6 | module SimpleWeightedGraphs |
2 | 7 |
|
3 | | -using Graphs |
4 | 8 | using LinearAlgebra |
5 | 9 | using Markdown |
6 | | -using SparseArrays |
7 | | - |
8 | | -import Base: |
9 | | - convert, eltype, show, ==, Pair, Tuple, copy, length, issubset, zero |
10 | | - |
11 | | -import Graphs: |
12 | | - _NI, AbstractGraph, AbstractEdge, AbstractEdgeIter, |
13 | | - src, dst, edgetype, nv, ne, vertices, edges, is_directed, |
14 | | - add_vertex!, add_edge!, rem_vertex!, rem_edge!, |
15 | | - has_vertex, has_edge, inneighbors, outneighbors, |
16 | | - indegree, outdegree, degree, has_self_loops, num_self_loops, |
17 | | - |
18 | | - add_vertices!, adjacency_matrix, laplacian_matrix, weights, |
19 | | - connected_components, cartesian_product, |
20 | | - |
21 | | - AbstractGraphFormat, loadgraph, loadgraphs, savegraph, |
22 | | - pagerank, induced_subgraph |
23 | | - |
24 | | -export |
25 | | - AbstractSimpleWeightedGraph, |
26 | | - AbstractSimpleWeightedEdge, |
27 | | - SimpleWeightedEdge, |
28 | | - SimpleWeightedGraph, |
29 | | - SimpleWeightedGraphEdge, |
30 | | - SimpleWeightedDiGraph, |
31 | | - SimpleWeightedDiGraphEdge, |
32 | | - weight, |
33 | | - weighttype, |
34 | | - get_weight, |
35 | | - WGraph, |
36 | | - WDiGraph, |
37 | | - SWGFormat, |
38 | | - degree_matrix |
39 | | - |
| 10 | +using SparseArrays: SparseMatrixCSC, sparse, spzeros, nnz, findnz, spdiagm, nzrange |
| 11 | + |
| 12 | +using Graphs: Graphs |
| 13 | +using Graphs: AbstractGraph, AbstractEdge, AbstractEdgeIter, AbstractGraphFormat |
| 14 | +using Graphs: SimpleGraph, SimpleDiGraph |
| 15 | +using Graphs: src, dst |
| 16 | +using Graphs: edgetype, is_directed, nv, ne, vertices, edges |
| 17 | +using Graphs: add_vertex!, add_vertices!, add_edge!, rem_vertex!, rem_edge! |
| 18 | +using Graphs: has_vertex, has_edge, inneighbors, outneighbors |
| 19 | +using Graphs: indegree, outdegree, degree, has_self_loops, num_self_loops |
| 20 | +using Graphs: adjacency_matrix, laplacian_matrix, weights |
| 21 | +using Graphs: connected_components, cartesian_product, induced_subgraph, pagerank |
| 22 | +using Graphs: loadgraph, loadgraphs, savegraph |
| 23 | +using Graphs: _NI |
| 24 | + |
| 25 | +export AbstractSimpleWeightedGraph, AbstractSimpleWeightedEdge |
| 26 | +export SimpleWeightedGraph, SimpleWeightedDiGraph |
| 27 | +export SimpleWeightedEdge, SimpleWeightedGraphEdge, SimpleWeightedDiGraphEdge |
| 28 | +export WGraph, WDiGraph, SWGFormat |
| 29 | +export weight, weighttype, get_weight, degree_matrix |
| 30 | + |
| 31 | +include("utils.jl") |
40 | 32 | include("simpleweightededge.jl") |
41 | | - |
42 | | -""" |
43 | | - AbstractSimpleWeightedGraph |
44 | | -
|
45 | | -An abstract type representing a simple graph structure. |
46 | | -AbstractSimpleWeightedGraphs must have the following elements: |
47 | | -- weightmx::AbstractSparseMatrix{Real} |
48 | | -""" |
49 | | -abstract type AbstractSimpleWeightedGraph{T<:Integer,U<:Real} <: AbstractGraph{T} end |
50 | | - |
51 | | -function show(io::IO, g::AbstractSimpleWeightedGraph{T, U}) where T where U |
52 | | - dir = is_directed(g) ? "directed" : "undirected" |
53 | | - print(io, "{$(nv(g)), $(ne(g))} $dir simple $T graph with $U weights") |
54 | | -end |
55 | | - |
56 | | -# conversion to SparseMatrixCSC |
57 | | -convert(::Type{SparseMatrixCSC{T, U}}, g::AbstractSimpleWeightedGraph) where T<:Real where U<:Integer = SparseMatrixCSC{T, U}(g.weights) |
58 | | - |
59 | | - |
60 | | -### INTERFACE |
61 | | - |
62 | | -nv(g::AbstractSimpleWeightedGraph{T, U}) where T where U = T(size(weights(g), 1)) |
63 | | -vertices(g::AbstractSimpleWeightedGraph{T, U}) where T where U = one(T):nv(g) |
64 | | -eltype(x::AbstractSimpleWeightedGraph{T, U}) where T where U = T |
65 | | -weighttype(x::AbstractSimpleWeightedGraph{T, U}) where T where U = U |
66 | | - |
67 | | -# handles single-argument edge constructors such as pairs and tuples |
68 | | -has_edge(g::AbstractSimpleWeightedGraph{T, U}, x) where T where U = has_edge(g, edgetype(g)(x)) |
69 | | -add_edge!(g::AbstractSimpleWeightedGraph{T, U}, x) where T where U = add_edge!(g, edgetype(g)(x)) |
70 | | - |
71 | | -# handles two-argument edge constructors like src,dst |
72 | | -has_edge(g::AbstractSimpleWeightedGraph, x, y) = has_edge(g, edgetype(g)(x, y, 0)) |
73 | | -add_edge!(g::AbstractSimpleWeightedGraph, x, y) = add_edge!(g, edgetype(g)(x, y, 1)) |
74 | | -add_edge!(g::AbstractSimpleWeightedGraph, x, y, z) = add_edge!(g, edgetype(g)(x, y, z)) |
75 | | - |
76 | | -function issubset(g::T, h::T) where T<:AbstractSimpleWeightedGraph |
77 | | - (gmin, gmax) = extrema(vertices(g)) |
78 | | - (hmin, hmax) = extrema(vertices(h)) |
79 | | - return (hmin <= gmin <= gmax <= hmax) && issubset(edges(g), edges(h)) |
80 | | -end |
81 | | - |
82 | | -has_vertex(g::AbstractSimpleWeightedGraph, v::Integer) = v in vertices(g) |
83 | | - |
84 | | -function rem_edge!(g::AbstractSimpleWeightedGraph{T, U}, u::Integer, v::Integer) where {T, U} |
85 | | - rem_edge!(g, edgetype(g)(T(u), T(v), one(U))) |
86 | | -end |
87 | | - |
88 | | -get_weight(g::AbstractSimpleWeightedGraph, u::Integer, v::Integer) = weights(g)[v, u] |
89 | | - |
90 | | -zero(g::T) where T<:AbstractSimpleWeightedGraph = T() |
91 | | - |
92 | | -# TODO: manipulte SparseMatrixCSC directly |
93 | | -add_vertex!(g::AbstractSimpleWeightedGraph) = add_vertices!(g, 1) |
94 | | - |
95 | | -copy(g::T) where T <: AbstractSimpleWeightedGraph = T(copy(weights(g))) |
96 | | - |
97 | | - |
98 | | -const SimpleWeightedGraphEdge = SimpleWeightedEdge |
99 | | -const SimpleWeightedDiGraphEdge = SimpleWeightedEdge |
| 33 | +include("abstractsimpleweightedgraph.jl") |
100 | 34 | include("simpleweighteddigraph.jl") |
101 | 35 | include("simpleweightedgraph.jl") |
| 36 | +include("conversion.jl") |
102 | 37 | include("overrides.jl") |
103 | 38 | include("persistence.jl") |
104 | 39 |
|
105 | | -const WGraph = SimpleWeightedGraph |
106 | | -const WDiGraph = SimpleWeightedDiGraph |
107 | | - |
108 | | - |
109 | | -# return the index in nzval of mat[i, j] |
110 | | -# we assume bounds are already checked |
111 | | -# see https://github.com/JuliaSparse/SparseArrays.jl/blob/fa547689947fadd6c2f3d09ddfcb5f26536f18c8/src/sparsematrix.jl#L2492 for implementation |
112 | | -@inbounds function _get_nz_index!(mat::SparseMatrixCSC, i::Integer, j::Integer) |
113 | | - # r1 and r2 are start and end of the column |
114 | | - r1 = Int(mat.colptr[j]) |
115 | | - r2 = Int(mat.colptr[j+1]-1) |
116 | | - (r1 > r2) && return 0 # column is empty so we have a non structural zero |
117 | | - # search if i correspond to a stored value |
118 | | - indx = searchsortedfirst(mat.rowval, i, r1, r2, Base.Forward) |
119 | | - ((indx > r2) || (mat.rowval[indx] != i)) && return 0 |
120 | | - return indx |
121 | | -end |
122 | | - |
123 | | -SimpleWeightedDiGraph(g::SimpleWeightedGraph) = SimpleWeightedDiGraph(copy(g.weights)) |
124 | | -function SimpleWeightedDiGraph{T, U}(g::SimpleWeightedGraph) where {T<:Integer, U<:Real} |
125 | | - return SimpleWeightedDiGraph(SparseMatrixCSC{U, T}(copy(g.weights))) |
126 | 40 | end |
127 | | - |
128 | | -SimpleWeightedGraph(g::SimpleWeightedDiGraph) = SimpleWeightedGraph(g.weights .+ g.weights') |
129 | | - |
130 | | -function SimpleWeightedGraph{T, U}(g::SimpleWeightedDiGraph) where {T<:Integer, U<:Real} |
131 | | - return SimpleWeightedGraph(SparseMatrixCSC{U, T}(g.weights .+ g.weights')) |
132 | | -end |
133 | | - |
134 | | -end # module |
0 commit comments