Open evanfields opened 5 years ago
My feeling is that edges
for SimpleWeightedGraphs should ignore 0-weight edges, and that the package should explicitly state that it does not support edges with zero weights.
We could implement the dropzeros!
method for SimpleWeightedGraphs
, so we could remove all zero weight edges after a bunch of edge removals.
May I add that it also means that for some algorithm, like looking for a cycle in a DiGraph, a zero weight and the absence of an edge are completely different.
Today I bumped into an issue that I think is closely related to this one:
julia> using SimpleWeightedGraphs
julia> g = SimpleWeightedGraph(4)
{4, 0} undirected simple Int64 graph with Float64 weights
julia> ne(g)
0
julia> adjacency_matrix(g)
4×4 SparseArrays.SparseMatrixCSC{Int64,Int64} with 0 stored entries
julia> add_edge!(g, 1, 3)
true
julia> g.weights
4×4 SparseArrays.SparseMatrixCSC{Float64,Int64} with 2 stored entries:
[3, 1] = 1.0
[1, 3] = 1.0
julia> ne(g)
1
julia> adjacency_matrix(g)
4×4 SparseArrays.SparseMatrixCSC{Int64,Int64} with 2 stored entries:
[3, 1] = 1
[1, 3] = 1
julia> rem_edge!(g, 1, 3)
true
julia> g.weights
4×4 SparseArrays.SparseMatrixCSC{Float64,Int64} with 2 stored entries:
[3, 1] = 0.0
[1, 3] = 0.0
julia> ne(g)
1
julia> adjacency_matrix(g)
4×4 SparseArrays.SparseMatrixCSC{Int64,Int64} with 2 stored entries:
[3, 1] = 1
After removing the only edge, ne(g)
returns 1 and the adjacency matrix is the same as 1-edge case.
Brief Slack discussion suggests this behavior arises from performance considerations around using sparse matrices; changing a value in a sparse matrix is much faster than changing the sparsity structure. For some use cases, this is totally okay. For example, if edges are "pipes" and edge weights are capacities, then a 0-weight edge and an absent edge are no different.
On the other hand, if edges represent possible movements between locations and edge weights are distances or costs, then a 0-weight edge means something very different than the absence of an edge.