blegat / HybridSystems.jl

Hybrid Systems definitions in Julia
Other
28 stars 5 forks source link

out_transitions for location with no transitions #29

Closed schillic closed 5 years ago

schillic commented 5 years ago

Here is a small example of an automaton where the second location has no outgoing transition.

using HybridSystems

automaton = LightAutomaton(2)
add_transition!(automaton, 1, 1, 1)
add_transition!(automaton, 1, 2, 2)
m1 = "mode1"
m2 = "mode2"
modes = [m1, m2]
resetmaps = ["transition1", "transition2"]
switchings = [AutonomousSwitching() for _ in 1:2]
H = HybridSystem(automaton, modes, resetmaps, switchings)

println("outgoing transitions of location 1:")
out_transitions(H, 1)
println("outgoing transitions of location 2:")
out_transitions(H, 2)

This script breaks in the last line with the following message:

ERROR: LoadError: AssertionError: 1 <= r <= nstates(A)

After adding println("q = $q, r = $r") to this line I get this output:

q = 1, r = 1
q = 1, r = 2
outgoing transitions of location 1:
q = 1, r = 1
outgoing transitions of location 2:
q = 2, r = 0
ERROR: LoadError: AssertionError: 1 <= r <= nstates(A)

It seems that the graph method here returns 0 if there is no outgoing edge, which is apparently not expected by the other function.

schillic commented 5 years ago

The problem is caused by MappedArrays: They call zero(eltype(A)) for array A if it is empty. In the case here, A::Vector(Int), so zero(eltype(A)) == 0. Then the edge_object function crashes because a location with index 0 does not exist. I am working on a fix, but I only see an unpleasent way how to make it type stable using MappedArrays.

blegat commented 5 years ago

We can give the type to MappedArrays so that it does not need to infer it (last time I checked it was not possible, I am glad they added it):

julia> mappedarray(x -> sqrt(-1 + x), 1:0)
ERROR: DomainError with -1.0:
sqrt will only return a complex result if called with a complex argument. Try sqrt(Complex(x)).
Stacktrace:
 [1] sqrt at ./math.jl:492 [inlined]
 [2] sqrt at ./math.jl:518 [inlined]
 [3] #15 at ./REPL[17]:1 [inlined]
 [4] mappedarray(::getfield(Main, Symbol("##15#16")), ::UnitRange{Int64}) at /home/blegat/.julia/packages/MappedArrays/kV0sK/src/MappedArrays.jl:61
 [5] top-level scope at none:0

julia> mappedarray(Float64, x -> sqrt(-1 + x), 1:0)
0-element mappedarray(Float64, getfield(Main, Symbol("##17#18"))(), ::UnitRange{Int64}) with eltype Float64

Wouldn't it resolve the issue ?

schillic commented 5 years ago

Perfect! Should I update my PR or do you want to send a fix?

blegat commented 5 years ago

You can update the PR, I am on my phone at the moment

schillic commented 5 years ago

I failed to do it (see #30).

blegat commented 5 years ago

My example doesn't work, the sqrt function is taken as the inverse function.

julia> mappedarray(Float64, x -> sqrt(-1 + x), 1:2)
2-element mappedarray(Float64, getfield(Main, Symbol("##7#8"))(), ::UnitRange{Int64}) with eltype Float64:
 1.0
 2.0
schillic commented 5 years ago

This is very embarrassing, but my "fix" did not actually fix the example in the inital post :disappointed:

mforets commented 5 years ago

what do you mean that it didn't fix it? i get no error so far:

julia> using HybridSystems

julia> automaton = LightAutomaton(2)
LightAutomaton{LightGraphs.SimpleGraphs.SimpleDiGraph{Int64},LightGraphs.SimpleGraphs.SimpleEdge{Int64}}({2, 0} directed simple Int64 graph, Dict{LightGraphs.SimpleGraphs.SimpleEdge{Int64},Dict{Int64,Int64}}(), 0, 0)

julia> add_transition!(automaton, 1, 1, 1)
HybridSystems.LightTransition{LightGraphs.SimpleGraphs.SimpleEdge{Int64}}(Edge 1 => 1, 1)

julia> add_transition!(automaton, 1, 2, 2)
HybridSystems.LightTransition{LightGraphs.SimpleGraphs.SimpleEdge{Int64}}(Edge 1 => 2, 2)

julia> m1 = "mode1"
"mode1"

julia> m2 = "mode2"
"mode2"

julia> modes = [m1, m2]
2-element Array{String,1}:
 "mode1"
 "mode2"

julia> resetmaps = ["transition1", "transition2"]
2-element Array{String,1}:
 "transition1"
 "transition2"

julia> switchings = [AutonomousSwitching() for _ in 1:2]
2-element Array{AutonomousSwitching,1}:
 AutonomousSwitching()
 AutonomousSwitching()

julia> H = HybridSystem(automaton, modes, resetmaps, switchings)
Hybrid System with automaton LightAutomaton{LightGraphs.SimpleGraphs.SimpleDiGraph{Int64},LightGraphs.SimpleGraphs.SimpleEdge{Int64}}({2, 2} directed simple Int64 graph, Dict(Edge 1 => 2=>Dict(2=>2),Edge 1 => 1=>Dict(1=>1)), 2, 2)

julia> 

julia> out_transitions(H, 1)
HybridSystems.LightTransitionIterator{LightGraphs.SimpleGraphs.SimpleDiGraph{Int64},LightGraphs.SimpleGraphs.SimpleEdge{Int64},MappedArrays.ReadonlyMappedArray{LightGraphs.SimpleGraphs.SimpleEdge{Int64},1,Array{Int64,1},getfield(HybridSystems, Symbol("#f#4")){LightAutomaton{LightGraphs.SimpleGraphs.SimpleDiGraph{Int64},LightGraphs.SimpleGraphs.SimpleEdge{Int64}},Int64}}}(LightAutomaton{LightGraphs.SimpleGraphs.SimpleDiGraph{Int64},LightGraphs.SimpleGraphs.SimpleEdge{Int64}}({2, 2} directed simple Int64 graph, Dict(Edge 1 => 2=>Dict(2=>2),Edge 1 => 1=>Dict(1=>1)), 2, 2), LightGraphs.SimpleGraphs.SimpleEdge{Int64}[Edge 1 => 1, Edge 1 => 2])

julia> 

julia> out_transitions(H, 2)
HybridSystems.LightTransitionIterator{LightGraphs.SimpleGraphs.SimpleDiGraph{Int64},LightGraphs.SimpleGraphs.SimpleEdge{Int64},MappedArrays.ReadonlyMappedArray{LightGraphs.SimpleGraphs.SimpleEdge{Int64},1,Array{Int64,1},getfield(HybridSystems, Symbol("#f#4")){LightAutomaton{LightGraphs.SimpleGraphs.SimpleDiGraph{Int64},LightGraphs.SimpleGraphs.SimpleEdge{Int64}},Int64}}}(LightAutomaton{LightGraphs.SimpleGraphs.SimpleDiGraph{Int64},LightGraphs.SimpleGraphs.SimpleEdge{Int64}}({2, 2} directed simple Int64 graph, Dict(Edge 1 => 2=>Dict(2=>2),Edge 1 => 1=>Dict(1=>1)), 2, 2), LightGraphs.SimpleGraphs.SimpleEdge{Int64}[])

julia> collect(ans)
0-element Array{HybridSystems.LightTransition{LightGraphs.SimpleGraphs.SimpleEdge{Int64}},1}

julia> isempty(ans)
true
schillic commented 5 years ago

Okay, this is even more embarrassing :smile: Apparently I used the release version of HybridSystems. @blegat: Do you mind sending a new release?

blegat commented 5 years ago

Done : https://github.com/JuliaLang/METADATA.jl/pull/22003 :)