-
Notifications
You must be signed in to change notification settings - Fork 5
/
abstractsimpleweightedgraph.jl
125 lines (93 loc) · 3.68 KB
/
abstractsimpleweightedgraph.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
"""
AbstractSimpleWeightedGraph
An abstract type representing a simple graph structure with edge weights.
The only requirement for concrete subtypes is that they should implement a method `Graphs.weights(g)` which returns the weighted adjacency matrix.
"""
abstract type AbstractSimpleWeightedGraph{T<:Integer,U<:Real} <: AbstractGraph{T} end
function Base.show(io::IO, g::AbstractSimpleWeightedGraph{T,U}) where {T} where {U}
dir = is_directed(g) ? "directed" : "undirected"
return print(io, "{$(nv(g)), $(ne(g))} $dir simple $T graph with $U weights")
end
## Interface
Base.eltype(::AbstractSimpleWeightedGraph{T,U}) where {T} where {U} = T
Base.zero(::T) where {T<:AbstractSimpleWeightedGraph} = T()
Base.copy(g::T) where {T<:AbstractSimpleWeightedGraph} = T(copy(weights(g)))
"""
weighttype(g)
Return the subtype of `Real` used to represent edge weights.
"""
weighttype(::AbstractSimpleWeightedGraph{T,U}) where {T} where {U} = U
"""
get_weight(g, u, v)
Retrieve the weight of edge `(u, v)`.
"""
get_weight(g::AbstractSimpleWeightedGraph, u::Integer, v::Integer) = weights(g)[u, v]
## Vertices
Graphs.nv(g::AbstractSimpleWeightedGraph{T,U}) where {T} where {U} = T(size(weights(g), 1))
Graphs.vertices(g::AbstractSimpleWeightedGraph{T,U}) where {T} where {U} = one(T):nv(g)
Graphs.has_vertex(g::AbstractSimpleWeightedGraph, v::Integer) = v in vertices(g)
# TODO: manipulate SparseMatrixCSC directly
Graphs.add_vertex!(g::AbstractSimpleWeightedGraph) = add_vertices!(g, 1)
function Graphs.add_vertices!(g::AbstractSimpleWeightedGraph, n::Integer)
T = eltype(g)
U = weighttype(g)
(nv(g) + one(T) <= nv(g)) && return false # test for overflow
emptycols = spzeros(U, nv(g) + n, n)
g.weights = hcat(g.weights, emptycols[1:nv(g), :])
g.weights = vcat(g.weights, emptycols')
return true
end
## Edges
# Handle single-argument edge constructors such as pairs and tuples
"""
Graphs.has_edge(g, e)
Check the existence of the edge `e` in the graph, where `e` is any object that can be converted into `edgetype(g)`.
"""
function Graphs.has_edge(g::AbstractSimpleWeightedGraph{T,U}, e) where {T,U}
return has_edge(g, edgetype(g)(e))
end
"""
Graphs.add_edge!(g, e)
Add the edge `e` to the graph, where `e` is any object that can be converted into `edgetype(g)`.
"""
function Graphs.add_edge!(g::AbstractSimpleWeightedGraph{T,U}, e) where {T,U}
return add_edge!(g, edgetype(g)(e))
end
# Handle two-argument edge constructors like src,dst
"""
Graphs.has_edge(g, u, v)
Check the existence of the edge `(u, v)` in the graph.
"""
function Graphs.has_edge(g::AbstractSimpleWeightedGraph{T,U}, u, v) where {T,U}
return has_edge(g, edgetype(g)(u, v, 0))
end
"""
Graphs.add_edge!(g, u, v)
Add the edge `(u, v)` to the graph with a default weight of 1.
"""
function Graphs.add_edge!(g::AbstractSimpleWeightedGraph{T,U}, u, v) where {T,U}
return add_edge!(g, edgetype(g)(T(u), T(v), one(U)))
end
"""
Graphs.rem_edge!(g, u, v)
Remove the edge `(u, v)` from the graph.
"""
function Graphs.rem_edge!(
g::AbstractSimpleWeightedGraph{T,U}, u::Integer, v::Integer
) where {T,U}
return rem_edge!(g, edgetype(g)(T(u), T(v), one(U)))
end
# Handle three-argument constructors
"""
Graphs.add_edge!(g, u, v, w)
Add the edge `(u, v)` to the graph with a weight of `w`.
"""
function Graphs.add_edge!(g::AbstractSimpleWeightedGraph{T,U}, u, v, w) where {T,U}
return add_edge!(g, edgetype(g)(T(u), T(v), U(w)))
end
## Miscellaneous
function Base.issubset(g::T, h::T) where {T<:AbstractSimpleWeightedGraph}
(gmin, gmax) = extrema(vertices(g))
(hmin, hmax) = extrema(vertices(h))
return (hmin <= gmin <= gmax <= hmax) && issubset(edges(g), edges(h))
end