Skip to content
This repository has been archived by the owner on Oct 8, 2021. It is now read-only.

Commit

Permalink
Merge pull request #34 from JuliaGraphs/sbromberger/fix-33
Browse files Browse the repository at this point in the history
fixes #33
  • Loading branch information
sbromberger authored Mar 25, 2018
2 parents 6fb3813 + 85f69d6 commit d706aa9
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 72 deletions.
56 changes: 29 additions & 27 deletions src/MetaGraphs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ has_vertex(g::AbstractMetaGraph, x...) = has_vertex(g.graph, x...)
inneighbors(g::AbstractMetaGraph, v::Integer) = inneighbors(g.graph, v)
outneighbors(g::AbstractMetaGraph, v::Integer) = fadj(g.graph, v)

issubset(g::T, h::T) where T<:AbstractMetaGraph = issubset(g.graph, h.graph)
issubset(g::T, h::T) where T <: AbstractMetaGraph = issubset(g.graph, h.graph)

"""
add_edge!(g, u, v, s, val)
Expand Down Expand Up @@ -113,7 +113,7 @@ end
return true if the vertex has been added, false otherwise.
"""
add_vertex!(g::AbstractMetaGraph) = add_vertex!(g.graph)
function add_vertex!(g::AbstractMetaGraph,d::Dict)
function add_vertex!(g::AbstractMetaGraph, d::Dict)
add_vertex!(g) || return false
set_props!(g, nv(g), d)
return true
Expand All @@ -140,28 +140,30 @@ function rem_vertex!(g::AbstractMetaGraph, v::Integer)
for n in inneighbors(g, lastv)
clear_props!(g, n, lastv)
end

for n in outneighbors(g, v)
clear_props!(g, v, n)
end

for n in inneighbors(g, v)
clear_props!(g, n, v)
if v != lastv # ignore if we're removing the last vertex.
for n in outneighbors(g, v)
clear_props!(g, v, n)
end
for n in inneighbors(g, v)
clear_props!(g, n, v)
end
end
clear_props!(g, lastv)
retval = rem_vertex!(g.graph, v)
retval && set_props!(g, v, lastvprops)
for n in outneighbors(g, v)
set_props!(g, v, n, lasteoutprops[n])
end

for n in inneighbors(g, v)
set_props!(g, n, v, lasteinprops[n])
if v != lastv # ignore if we're removing the last vertex.
for n in outneighbors(g, v)
set_props!(g, v, n, lasteoutprops[n])
end

for n in inneighbors(g, v)
set_props!(g, n, v, lasteinprops[n])
end
end
return retval
end

struct MetaWeights{T<:Integer,U<:Real} <: AbstractMatrix{U}
struct MetaWeights{T <: Integer,U <: Real} <: AbstractMatrix{U}
n::T
weightfield::Symbol
defaultweight::U
Expand Down Expand Up @@ -192,7 +194,7 @@ end

function getindex(g::AbstractMetaGraph, indx::Integer, prop::Symbol)
haskey(g.metaindex, prop) || error("':$prop' is not an index")
return props(g,indx)[prop]
return props(g, indx)[prop]
end

size(d::MetaWeights) = (d.n, d.n)
Expand Down Expand Up @@ -286,10 +288,10 @@ Will return false if vertex or edge does not exist, true otherwise
set_prop!(g::AbstractMetaGraph, prop::Symbol, val) = set_props!(g, Dict(prop => val))
set_prop!(g::AbstractMetaGraph, v::Integer, prop::Symbol, val) =
if in(prop, g.indices)
error("':$prop' is an indexing property, use `set_indexing_prop!()` instead")
else
set_props!(g, v, Dict(prop => val))
end
error("':$prop' is an indexing property, use `set_indexing_prop!()` instead")
else
set_props!(g, v, Dict(prop => val))
end
set_prop!(g::AbstractMetaGraph, e::SimpleEdge, prop::Symbol, val) = set_props!(g, e, Dict(prop => val))

set_prop!(g::AbstractMetaGraph{T}, u::Integer, v::Integer, prop::Symbol, val) where T = set_prop!(g, Edge(T(u), T(v)), prop, val)
Expand All @@ -316,10 +318,10 @@ rem_prop!(g::AbstractMetaGraph{T}, u::Integer, v::Integer, prop::Symbol) where T
Provides a default index value for a vertex if no value currently exists. The default is a string: "\$prop\$i" where `prop` is the property name and `i` is the vertex number. If some other vertex already has this name, a randomized string is generated (though the way it is generated is deterministic).
"""
function default_index_value(v::Integer, prop::Symbol, index_values::Set{Any}; exclude=nothing)
function default_index_value(v::Integer, prop::Symbol, index_values::Set{Any}; exclude = nothing)
val = string(prop) * string(v)
if in(val, index_values) || val == exclude
srand(v+hash(prop))
srand(v + hash(prop))
val = randstring()
warn("'$(string(prop))$v' is already in index, setting ':$prop' for vertex $v to $val")
end
Expand All @@ -335,16 +337,16 @@ are already set, each vertex must have unique values. Optionally, set the index
`val` for vertex `v`. Any vertices without values will be set to a default
("(prop)(v)").
"""
function set_indexing_prop!(g::AbstractMetaGraph, prop::Symbol; exclude=nothing)
function set_indexing_prop!(g::AbstractMetaGraph, prop::Symbol; exclude = nothing)
in(prop, g.indices) && return g.indices
index_values = [g.vprops[v][prop] for v in keys(g.vprops) if haskey(g.vprops[v], prop)]
length(index_values) != length(union(index_values)) && error("Cannot make $prop an index, duplicate values detected")
index_values = Set(index_values)

g.metaindex[prop] = Dict{Any, Integer}()
g.metaindex[prop] = Dict{Any,Integer}()
for v in 1:size(g)[1]
if !haskey(g.vprops, v) || !haskey(g.vprops[v], prop)
val = default_index_value(v, prop, index_values, exclude=exclude)
val = default_index_value(v, prop, index_values, exclude = exclude)
set_prop!(g, v, prop, val)
end
g.metaindex[prop][g.vprops[v][prop]] = v
Expand All @@ -354,7 +356,7 @@ function set_indexing_prop!(g::AbstractMetaGraph, prop::Symbol; exclude=nothing)
end

function set_indexing_prop!(g::AbstractMetaGraph, v::Integer, prop::Symbol, val::Any)
!in(prop, g.indices) && set_indexing_prop!(g, prop, exclude=val)
!in(prop, g.indices) && set_indexing_prop!(g, prop, exclude = val)
(haskey(g.metaindex[prop], val) && g.vprops[v][prop] == val) && return g.indices
haskey(g.metaindex[prop], val) && error("':$prop' index already contains $val")

Expand Down
104 changes: 59 additions & 45 deletions test/metagraphs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,18 @@ importall MetaGraphs
dgx = PathDiGraph(4)

mg = MetaGraph()
@test add_vertex!(mg,:color,"red") && get_prop(mg,nv(mg),:color) == "red"
@test add_vertex!(mg,Dict(:color=>"red",:prop2=>"prop2")) && props(mg,nv(mg)) == Dict(:color=>"red",:prop2=>"prop2")
@test add_edge!(mg,1,2,:color,"blue") && get_prop(mg,1,2,:color) == "blue"
@test add_vertex!(mg) && add_edge!(mg,1,3,Dict(:color => "red",:prop2 => "prop2")) && props(mg,1,3) == Dict(:color=>"red",:prop2=>"prop2")
@test add_vertex!(mg, :color, "red") && get_prop(mg, nv(mg), :color) == "red"
@test add_vertex!(mg, Dict(:color => "red", :prop2 => "prop2")) && props(mg, nv(mg)) == Dict(:color => "red", :prop2 => "prop2")
@test add_edge!(mg, 1, 2, :color, "blue") && get_prop(mg, 1, 2, :color) == "blue"
@test add_vertex!(mg) && add_edge!(mg, 1, 3, Dict(:color => "red", :prop2 => "prop2")) && props(mg, 1, 3) == Dict(:color => "red", :prop2 => "prop2")

for g in testgraphs(gx)
mg = MetaGraph(g)
g2 = SimpleGraph(mg)
@test g2 == mg.graph

@test eltype(@inferred(MetaGraph{UInt8, Float16}(mg))) == UInt8
@test weighttype(@inferred(MetaGraph{UInt8, Float16}(mg))) == Float16
@test eltype(@inferred(MetaGraph{UInt8,Float16}(mg))) == UInt8
@test weighttype(@inferred(MetaGraph{UInt8,Float16}(mg))) == Float16

@test @inferred(MetaGraphs.fadj(mg, 2)) == LightGraphs.SimpleGraphs.fadj(g, 2)
@test @inferred(MetaGraphs.badj(mg, 2)) == LightGraphs.SimpleGraphs.badj(g, 2)
Expand All @@ -38,22 +38,22 @@ importall MetaGraphs
@test @inferred(eltype(MetaGraph(g, 2.0))) == eltype(g)
@test @inferred(eltype(MetaGraph(g, :cost))) == eltype(g)
@test @inferred(eltype(MetaGraph(g, :cost, 2.0))) == eltype(g)
@test @inferred(eltype(MetaGraph{UInt8, Float16}(g))) == UInt8
@test @inferred(eltype(MetaGraph{UInt8, Float16}(g, :cost))) == UInt8
@test @inferred(eltype(MetaGraph{UInt8, Float16}(g, 4))) == UInt8
@test @inferred(eltype(MetaGraph{UInt8,Float16}(g))) == UInt8
@test @inferred(eltype(MetaGraph{UInt8,Float16}(g, :cost))) == UInt8
@test @inferred(eltype(MetaGraph{UInt8,Float16}(g, 4))) == UInt8
@test @inferred(ne(mg)) == 3
@test @inferred(nv(mg)) == 4
@test @inferred(!is_directed(mg))

@test @inferred(vertices(mg)) == 1:4
@test Edge(2,3) in edges(mg)
@test @inferred(outneighbors(mg,2)) == inneighbors(mg,2) == neighbors(mg,2)
@test Edge(2, 3) in edges(mg)
@test @inferred(outneighbors(mg, 2)) == inneighbors(mg, 2) == neighbors(mg, 2)
@test @inferred(has_edge(mg, 2, 3))
@test @inferred(has_edge(mg, 3, 2))

mgc = copy(mg)
@test @inferred(add_edge!(mgc, 4=>1)) && mgc == MetaGraph(CycleGraph(4))
@test @inferred(has_edge(mgc, 4=>1)) && has_edge(mgc, 0x04=>0x01)
@test @inferred(add_edge!(mgc, 4 => 1)) && mgc == MetaGraph(CycleGraph(4))
@test @inferred(has_edge(mgc, 4 => 1)) && has_edge(mgc, 0x04 => 0x01)
mgc = copy(mg)
@test @inferred(add_edge!(mgc, (4, 1))) && mgc == MetaGraph(CycleGraph(4))
@test @inferred(has_edge(mgc, (4, 1))) && has_edge(mgc, (0x04, 0x01))
Expand All @@ -69,11 +69,11 @@ importall MetaGraphs
@test @inferred(rem_vertex!(mga, 2)) && ne(mga) == 1
@test @inferred(!rem_vertex!(mga, 10))

@test @inferred(zero(mg)) == MetaGraph{eltype(mg), weighttype(mg)}()
@test @inferred(zero(mg)) == MetaGraph{eltype(mg),weighttype(mg)}()
@test @inferred(eltype(mg)) == eltype(outneighbors(mg, 1)) == eltype(nv(mg))
T = @inferred(eltype(mg))
U = @inferred(weighttype(mg))
@test @inferred(nv(MetaGraph{T, U}(6))) == 6
@test @inferred(nv(MetaGraph{T,U}(6))) == 6

end

Expand All @@ -82,8 +82,8 @@ importall MetaGraphs
g2 = SimpleDiGraph(mg)
@test g2 == mg.graph

@test eltype(@inferred(MetaDiGraph{UInt8, Float16}(mg))) == UInt8
@test weighttype(@inferred(MetaDiGraph{UInt8, Float16}(mg))) == Float16
@test eltype(@inferred(MetaDiGraph{UInt8,Float16}(mg))) == UInt8
@test weighttype(@inferred(MetaDiGraph{UInt8,Float16}(mg))) == Float16

@test @inferred(MetaGraphs.fadj(mg, 2)) == LightGraphs.SimpleGraphs.fadj(g, 2)
@test @inferred(MetaGraphs.badj(mg, 2)) == LightGraphs.SimpleGraphs.badj(g, 2)
Expand All @@ -94,24 +94,24 @@ importall MetaGraphs
@test @inferred(eltype(MetaDiGraph(g, 2.0))) == eltype(g)
@test @inferred(eltype(MetaDiGraph(g, :cost))) == eltype(g)
@test @inferred(eltype(MetaDiGraph(g, :cost, 2.0))) == eltype(g)
@test @inferred(eltype(MetaDiGraph{UInt8, Float16}(g))) == UInt8
@test @inferred(eltype(MetaDiGraph{UInt8, Float16}(g, :cost))) == UInt8
@test @inferred(eltype(MetaDiGraph{UInt8, Float16}(g, 4))) == UInt8
@test @inferred(eltype(MetaDiGraph{UInt8,Float16}(g))) == UInt8
@test @inferred(eltype(MetaDiGraph{UInt8,Float16}(g, :cost))) == UInt8
@test @inferred(eltype(MetaDiGraph{UInt8,Float16}(g, 4))) == UInt8

@test @inferred(ne(mg)) == 3
@test @inferred(nv(mg)) == 4
@test @inferred(is_directed(mg))

@test @inferred(vertices(mg)) == 1:4
@test Edge(2,3) in edges(mg)
@test @inferred(outneighbors(mg,2)) == [3]
@test @inferred(inneighbors(mg,2)) == [1]
@test Edge(2, 3) in edges(mg)
@test @inferred(outneighbors(mg, 2)) == [3]
@test @inferred(inneighbors(mg, 2)) == [1]
@test @inferred(has_edge(mg, 2, 3))
@test @inferred(!has_edge(mg, 3, 2))

mgc = copy(mg)
@test @inferred(add_edge!(mgc, 4=>1)) && mgc == MetaDiGraph(CycleDiGraph(4))
@test @inferred(has_edge(mgc, 4=>1)) && has_edge(mgc, 0x04=>0x01)
@test @inferred(add_edge!(mgc, 4 => 1)) && mgc == MetaDiGraph(CycleDiGraph(4))
@test @inferred(has_edge(mgc, 4 => 1)) && has_edge(mgc, 0x04 => 0x01)
mgc = copy(mg)
@test @inferred(add_edge!(mgc, (4, 1))) && mgc == MetaDiGraph(CycleDiGraph(4))
@test @inferred(has_edge(mgc, (4, 1))) && has_edge(mgc, (0x04, 0x01))
Expand All @@ -127,11 +127,11 @@ importall MetaGraphs
@test @inferred(rem_vertex!(mga, 2)) && ne(mga) == 1
@test @inferred(!rem_vertex!(mga, 10))

@test @inferred(zero(mg)) == MetaDiGraph{eltype(mg), weighttype(mg)}()
@test @inferred(zero(mg)) == MetaDiGraph{eltype(mg),weighttype(mg)}()
@test @inferred(eltype(mg)) == eltype(outneighbors(mg, 1)) == eltype(nv(mg))
T = @inferred(eltype(mg))
U = @inferred(weighttype(mg))
@test @inferred(nv(MetaDiGraph{T, U}(6))) == 6
@test @inferred(nv(MetaDiGraph{T,U}(6))) == 6
end

for gbig in [SimpleGraph(0xff), SimpleDiGraph(0xff)]
Expand Down Expand Up @@ -161,13 +161,13 @@ importall MetaGraphs

mg = MetaGraph(CompleteGraph(3), 3.0)
@test enumerate_paths(dijkstra_shortest_paths(mg, 1), 3) == [1, 3]
@test typeof(set_prop!(mg, 1, 2, :weight, 0.2)) == Dict{Symbol, Float64}
@test typeof(set_prop!(mg, 2, 3, :weight, 1)) == Dict{Symbol, Int64}
@test typeof(set_prop!(mg, 1, 2, :weight, 0.2)) == Dict{Symbol,Float64}
@test typeof(set_prop!(mg, 2, 3, :weight, 1)) == Dict{Symbol,Int64}
@test enumerate_paths(dijkstra_shortest_paths(mg, 1), 3) == [1, 2, 3]

@test typeof(set_prop!(mg, 1, :color, "blue")) == Dict{Symbol, String}
@test typeof(set_prop!(mg, 1, :id, 0x5)) == Dict{Symbol, Any}
@test typeof(set_prop!(mg, :name, "test graph")) == Dict{Symbol, Any}
@test typeof(set_prop!(mg, 1, :color, "blue")) == Dict{Symbol,String}
@test typeof(set_prop!(mg, 1, :id, 0x5)) == Dict{Symbol,Any}
@test typeof(set_prop!(mg, :name, "test graph")) == Dict{Symbol,Any}


@test length(props(mg)) == 1
Expand Down Expand Up @@ -198,13 +198,13 @@ importall MetaGraphs
mg = MetaDiGraph(PathDiGraph(3), 3.0)
add_edge!(mg, 1, 3)
@test enumerate_paths(dijkstra_shortest_paths(mg, 1), 3) == [1, 3]
@test typeof(set_prop!(mg, 1, 2, :weight, 0.2)) == Dict{Symbol, Float64}
@test typeof(set_prop!(mg, 2, 3, :weight, 1)) == Dict{Symbol, Int64}
@test typeof(set_prop!(mg, 1, 2, :weight, 0.2)) == Dict{Symbol,Float64}
@test typeof(set_prop!(mg, 2, 3, :weight, 1)) == Dict{Symbol,Int64}
@test enumerate_paths(dijkstra_shortest_paths(mg, 1), 3) == [1, 2, 3]

@test typeof(set_prop!(mg, 1, :color, "blue")) == Dict{Symbol, String}
@test typeof(set_prop!(mg, 1, :id, 0x5)) == Dict{Symbol, Any}
@test typeof(set_prop!(mg, :name, "test graph")) == Dict{Symbol, Any}
@test typeof(set_prop!(mg, 1, :color, "blue")) == Dict{Symbol,String}
@test typeof(set_prop!(mg, 1, :id, 0x5)) == Dict{Symbol,Any}
@test typeof(set_prop!(mg, :name, "test graph")) == Dict{Symbol,Any}


@test length(props(mg)) == 1
Expand Down Expand Up @@ -249,10 +249,10 @@ importall MetaGraphs
@test weightfield!(mg, :weight) == :weight
@test enumerate_paths(dijkstra_shortest_paths(mg, 1), 3) == [1, 2, 3]

@test length(set_props!(mg, 1, 2, Dict(:color=>:blue, :action=>"knows"))) == 3
@test length(set_props!(mg, 1, 2, Dict(:color => :blue, :action => "knows"))) == 3
@test rem_edge!(mg, 1, 2)
@test length(props(mg, 1, 2)) == 0
@test length(set_props!(mg, Dict(:name=>"testgraph", :type=>"undirected"))) == 2
@test length(set_props!(mg, Dict(:name => "testgraph", :type => "undirected"))) == 2

mg = MetaGraph(CompleteGraph(3), 3.0)
set_prop!(mg, 1, :color, "blue")
Expand Down Expand Up @@ -327,6 +327,19 @@ importall MetaGraphs
@test length(mga.eprops) == 1 # should only be edge 3=>2
@test props(mga, 3, 2)[:name] == "3, 4"

# test for #33
mga = MetaGraph(PathGraph(4))
set_prop!(mga, 1, 2, :name, "1, 2")
set_prop!(mga, 2, 3, :name, "2, 3")
set_prop!(mga, 3, 4, :name, "3, 4")
set_prop!(mga, 3, :v, 3)
set_prop!(mga, 4, :v, 4)
@test rem_vertex!(mga, nv(mga))
@test has_prop(mga, 2, 3, :name)
@test !has_prop(mga, 3, 4, :name)
@test !has_prop(mga, 4, :v)
@test has_prop(mga, 3, :v)




Expand All @@ -342,8 +355,8 @@ end
end

for i in 1:100
set_prop!(G, i, :not_unique, "$(i%5)")
set_prop!(dG, i, :not_unique, "$(i%5)")
set_prop!(G, i, :not_unique, "$(i % 5)")
set_prop!(dG, i, :not_unique, "$(i % 5)")
end

@test set_indexing_prop!(G, :name) == Set{Symbol}([:name])
Expand All @@ -358,9 +371,10 @@ end
@test_throws ErrorException set_indexing_prop!(dG, 4, :name, "dgnode_3")
@test_throws ErrorException set_prop!(G, 3, :name, "name3")
@test_throws ErrorException set_prop!(dG, 3, :name, "name3")
@test_throws ErrorException set_props!(G, 5, Dict(:name=>"name", :other_name=>"something"))
@test_throws ErrorException set_props!(dG, 5, Dict(:name=>"name", :other_name=>"something"))
@test_throws ErrorException set_props!(G, 5, Dict(:name => "name", :other_name => "something"))
@test_throws ErrorException set_props!(dG, 5, Dict(:name => "name", :other_name => "something"))

info("Ignore \"'foo1' is already in index\" warnings")
set_indexing_prop!(G, 50, :name, "another name")
set_indexing_prop!(G, 50, :name, "another name")

Expand All @@ -376,8 +390,8 @@ end
@test G[12, :foo] == "foo12"
@test G["bar", :foo] == 42
@test G[42, :foo] == "bar"
@test isa(G[:foo], Dict{Any, Integer})
@test isa(dG[:foo], Dict{Any, Integer})
@test isa(G[:foo], Dict{Any,Integer})
@test isa(dG[:foo], Dict{Any,Integer})


@test dG["foo30", :foo] == 30
Expand Down

0 comments on commit d706aa9

Please sign in to comment.