Commit dc5689b5 authored by Bentriou Mahmoud's avatar Bentriou Mahmoud
Browse files

Finally I managed to improve the performance of function access of LHA.

The solution is to use FunctionWrappers.jl which provides a high
interface for C function pointers.

All tests passed.
parent 99ece473
# Creation of the automaton types # Creation of the automaton types
@everywhere @eval abstract type EdgeAutomatonF <: Edge end #@everywhere @eval abstract type EdgeAutomatonF <: Edge end
@everywhere struct EdgeAutomatonF <: Edge
transitions::TransitionSet
check_constraints::CheckConstraintsFunction
update_state!::UpdateStateFunction
end
@everywhere @eval $(MarkovProcesses.generate_code_lha_type_def(:AutomatonF, :EdgeAutomatonF)) @everywhere @eval $(MarkovProcesses.generate_code_lha_type_def(:AutomatonF, :EdgeAutomatonF))
function create_automaton_F(m::ContinuousTimeModel, x1::Float64, x2::Float64, t1::Float64, t2::Float64, sym_obs::VariableModel) function create_automaton_F(m::ContinuousTimeModel, x1::Float64, x2::Float64, t1::Float64, t2::Float64, sym_obs::VariableModel)
...@@ -46,78 +51,85 @@ function create_automaton_F(m::ContinuousTimeModel, x1::Float64, x2::Float64, t1 ...@@ -46,78 +51,85 @@ function create_automaton_F(m::ContinuousTimeModel, x1::Float64, x2::Float64, t1
basename_func = "$(model_name)_$(id)" basename_func = "$(model_name)_$(id)"
edge_name(from_loc::Location, to_loc::Location, edge_number::Int) = edge_name(from_loc::Location, to_loc::Location, edge_number::Int) =
Symbol("Edge_$(lha_name)_$(basename_func)_$(from_loc)$(to_loc)_$(edge_number)") Symbol("Edge_$(lha_name)_$(basename_func)_$(from_loc)$(to_loc)_$(edge_number)")
function check_constraints(from_loc::Location, to_loc::Location, edge_number::Int)
return Symbol("check_constraints_$(edge_type)_$(from_loc)$(to_loc)_$(edge_number)_$(model_name)_$(id)")
end
function update_state!(from_loc::Location, to_loc::Location, edge_number::Int)
return Symbol("update_state_$(edge_type)_$(from_loc)$(to_loc)_$(edge_number)_$(model_name)_$(id)!")
end
## check_constraints & update_state! ## check_constraints & update_state!
@everywhere @eval begin meta_funcs = quote
istrue(val::Float64) = convert(Bool, val) @everywhere istrue(val::Float64) = convert(Bool, val)
## Check constraints and update state functions ## Check constraints and update state functions
# l0 loc : we construct the edges of the form l0 => (..) # l0 loc : we construct the edges of the form l0 => (..)
# "cc" as check_constraints and "us" as update_state # "cc" as check_constraints and "us" as update_state
# l0 => l1 # l0 => l1
struct $(edge_name(:l0, :l1, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end #struct $(edge_name(:l0, :l1, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
$(check_constraints)(edge::$(edge_name(:l0, :l1, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = true @everywhere $(check_constraints(:l0, :l1, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = true
$(update_state!)(edge::$(edge_name(:l0, :l1, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = @everywhere $(update_state!(:l0, :l1, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
(S_values[$(to_idx(:n))] = x[$(idx_obs_var)]; (S_values[$(to_idx(:n))] = x[$(idx_obs_var)];
S_values[$(to_idx(:d))] = Inf; S_values[$(to_idx(:d))] = Inf;
S_values[$(to_idx(:isabs))] = $(m.isabsorbing)(p,x); S_values[$(to_idx(:isabs))] = $(m.isabsorbing)(p,x);
:l1) :l1)
# l1 loc # l1 loc
# l1 => l2 # l1 => l2
struct $(edge_name(:l1, :l2, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end #struct $(edge_name(:l1, :l2, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
$(check_constraints)(edge::$(edge_name(:l1, :l2, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = @everywhere $(check_constraints(:l1, :l2, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
S_time >= $t1 && S_time >= $t1 &&
S_values[$(to_idx(:d))] == 0 S_values[$(to_idx(:d))] == 0
$(update_state!)(edge::$(edge_name(:l1, :l2, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = @everywhere $(update_state!(:l1, :l2, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
(:l2) (:l2)
struct $(edge_name(:l1, :l2, 2)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end #struct $(edge_name(:l1, :l2, 2)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
$(check_constraints)(edge::$(edge_name(:l1, :l2, 2)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = @everywhere $(check_constraints(:l1, :l2, 2))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
(S_time >= $t2) && (S_time >= $t2) &&
(S_values[$(to_idx(:n))] < $x1 || S_values[$(to_idx(:n))] > $x2) (S_values[$(to_idx(:n))] < $x1 || S_values[$(to_idx(:n))] > $x2)
$(update_state!)(edge::$(edge_name(:l1, :l2, 2)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = @everywhere $(update_state!(:l1, :l2, 2))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
(:l2;) (:l2;)
#setindex!(S_values, min(abs(S_values[$(to_idx(:n))] - $x1), abs(S_values[$(to_idx(:n))] - $x2)), $(to_idx(:d)))) #setindex!(S_values, min(abs(S_values[$(to_idx(:n))] - $x1), abs(S_values[$(to_idx(:n))] - $x2)), $(to_idx(:d))))
# l1 => l3 # l1 => l3
struct $(edge_name(:l1, :l3, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end #struct $(edge_name(:l1, :l3, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
$(check_constraints)(edge::$(edge_name(:l1, :l3, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = @everywhere $(check_constraints(:l1, :l3, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
(S_time <= $t1) && (S_time <= $t1) &&
(S_values[$(to_idx(:n))] < $x1 || S_values[$(to_idx(:n))] > $x2) (S_values[$(to_idx(:n))] < $x1 || S_values[$(to_idx(:n))] > $x2)
$(update_state!)(edge::$(edge_name(:l1, :l3, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = @everywhere $(update_state!(:l1, :l3, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
(S_values[$(to_idx(:d))] = min(sqrt((S_time - $t1)^2 + (S_values[$(to_idx(:n))] - $x2)^2), (S_values[$(to_idx(:d))] = min(sqrt((S_time - $t1)^2 + (S_values[$(to_idx(:n))] - $x2)^2),
sqrt((S_time - $t1)^2 + (S_values[$(to_idx(:n))] - $x1)^2)); sqrt((S_time - $t1)^2 + (S_values[$(to_idx(:n))] - $x1)^2));
:l3) :l3)
struct $(edge_name(:l1, :l3, 2)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end #struct $(edge_name(:l1, :l3, 2)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
$(check_constraints)(edge::$(edge_name(:l1, :l3, 2)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = @everywhere $(check_constraints(:l1, :l3, 2))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
($x1 <= S_values[$(to_idx(:n))] <= $x2) ($x1 <= S_values[$(to_idx(:n))] <= $x2)
$(update_state!)(edge::$(edge_name(:l1, :l3, 2)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = @everywhere $(update_state!(:l1, :l3, 2))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
(S_values[$(to_idx(:d))] = 0; (S_values[$(to_idx(:d))] = 0;
:l3) :l3)
struct $(edge_name(:l1, :l3, 3)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end #struct $(edge_name(:l1, :l3, 3)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
$(check_constraints)(edge::$(edge_name(:l1, :l3, 3)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = @everywhere $(check_constraints(:l1, :l3, 3))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
(S_time >= $t1) && (S_time >= $t1) &&
(S_values[$(to_idx(:n))] < $x1 || S_values[$(to_idx(:n))] > $x2) (S_values[$(to_idx(:n))] < $x1 || S_values[$(to_idx(:n))] > $x2)
$(update_state!)(edge::$(edge_name(:l1, :l3, 3)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = @everywhere $(update_state!(:l1, :l3, 3))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
(val_min = min(S_values[$(to_idx(:d))], (val_min = min(S_values[$(to_idx(:d))],
min(abs(S_values[$(to_idx(:n))] - $x1), abs(S_values[$(to_idx(:n))] - $x2))); min(abs(S_values[$(to_idx(:n))] - $x1), abs(S_values[$(to_idx(:n))] - $x2)));
S_values[$(to_idx(:d))] = val_min; S_values[$(to_idx(:d))] = val_min;
:l3) :l3)
# l3 loc # l3 loc
# l3 => l1 # l3 => l1
struct $(edge_name(:l3, :l1, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end #struct $(edge_name(:l3, :l1, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
$(check_constraints)(edge::$(edge_name(:l3, :l1, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = true @everywhere $(check_constraints(:l3, :l1, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = true
$(update_state!)(edge::$(edge_name(:l3, :l1, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = @everywhere $(update_state!(:l3, :l1, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
(S_values[$(to_idx(:n))] = x[$(idx_obs_var)]; (S_values[$(to_idx(:n))] = x[$(idx_obs_var)];
S_values[$(to_idx(:isabs))] = $(m.isabsorbing)(p,x); S_values[$(to_idx(:isabs))] = $(m.isabsorbing)(p,x);
:l1) :l1)
# l3 => l2 # l3 => l2
struct $(edge_name(:l3, :l2, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end #struct $(edge_name(:l3, :l2, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
$(check_constraints)(edge::$(edge_name(:l3, :l2, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = @everywhere $(check_constraints(:l3, :l2, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
(S_time >= $t2 || istrue(S_values[$(to_idx(:isabs))])) (S_time >= $t2 || istrue(S_values[$(to_idx(:isabs))]))
$(update_state!)(edge::$(edge_name(:l3, :l2, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = @everywhere $(update_state!(:l3, :l2, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
(:l2) (:l2)
end end
eval(meta_funcs)
@eval begin @eval begin
map_edges = Dict{Location, Dict{Location, Vector{$(edge_type)}}}() map_edges = Dict{Location, Dict{Location, Vector{$(edge_type)}}}()
...@@ -127,46 +139,50 @@ function create_automaton_F(m::ContinuousTimeModel, x1::Float64, x2::Float64, t1 ...@@ -127,46 +139,50 @@ function create_automaton_F(m::ContinuousTimeModel, x1::Float64, x2::Float64, t1
# l0 loc # l0 loc
# l0 => l1 # l0 => l1
edge1 = $(edge_name(:l0, :l1, 1))(nothing) edge1 = EdgeAutomatonF(nothing, $(check_constraints(:l0, :l1, 1)), $(update_state!(:l0, :l1, 1)))
map_edges[:l0][:l1] = [edge1] map_edges[:l0][:l1] = [edge1]
# l1 loc # l1 loc
# l1 => l2 # l1 => l2
edge1 = $(edge_name(:l1, :l2, 1))(nothing) edge1 = EdgeAutomatonF(nothing, $(check_constraints(:l1, :l2, 1)), $(update_state!(:l1, :l2, 1)))
edge2 = $(edge_name(:l1, :l2, 2))(nothing) edge2 = EdgeAutomatonF(nothing, $(check_constraints(:l1, :l2, 2)), $(update_state!(:l1, :l2, 2)))
map_edges[:l1][:l2] = [edge1, edge2] map_edges[:l1][:l2] = [edge1, edge2]
#edge3 = $(edge_name(:l1, :l2, 3))(nothing) #edge3 = EdgeAutomatonF(nothing, $(check_constraints(:l1, :l2, 3)), $(update_state!(:l1, :l2, 3)))
#edge4 = $(edge_name(:l1, :l2, 4))(nothing) #edge4 = EdgeAutomatonF(nothing, $(check_constraints(:l1, :l2, 4)), $(update_state!(:l1, :l2, 4)))
#map_edges[:l1][:l2] = [edge1, edge2, edge3, edge4] #map_edges[:l1][:l2] = [edge1, edge2, edge3, edge4]
# l1 => l3 # l1 => l3
edge1 = $(edge_name(:l1, :l3, 1))(nothing) edge1 = EdgeAutomatonF(nothing, $(check_constraints(:l1, :l3, 1)), $(update_state!(:l1, :l3, 1)))
edge2 = $(edge_name(:l1, :l3, 2))(nothing) edge2 = EdgeAutomatonF(nothing, $(check_constraints(:l1, :l3, 2)), $(update_state!(:l1, :l3, 2)))
edge3 = $(edge_name(:l1, :l3, 3))(nothing) edge3 = EdgeAutomatonF(nothing, $(check_constraints(:l1, :l3, 3)), $(update_state!(:l1, :l3, 3)))
map_edges[:l1][:l3] = [edge1, edge2, edge3] map_edges[:l1][:l3] = [edge1, edge2, edge3]
# l3 loc # l3 loc
# l3 => l1 # l3 => l1
edge1 = $(edge_name(:l3, :l1, 1))([:ALL]) edge1 = EdgeAutomatonF([:ALL], $(check_constraints(:l3, :l1, 1)), $(update_state!(:l3, :l1, 1)))
map_edges[:l3][:l1] = [edge1] map_edges[:l3][:l1] = [edge1]
# l3 => l2 # l3 => l2
edge1 = $(edge_name(:l3, :l2, 1))(nothing) edge1 = EdgeAutomatonF(nothing, $(check_constraints(:l3, :l2, 1)), $(update_state!(:l3, :l2, 1)))
map_edges[:l3][:l2] = [edge1] map_edges[:l3][:l2] = [edge1]
end end
## Constants ## Constants
constants = Dict{Symbol,Float64}(:x1 => x1, :x2 => x2, :t1 => t1, :t2 => t2) constants = Dict{Symbol,Float64}(:x1 => x1, :x2 => x2, :t1 => t1, :t2 => t2)
map_edges_transitions = Dict{Symbol, Dict{Symbol,Vector{TransitionSet}}}()
map_edges_check_constraints = Dict{Symbol, Dict{Symbol,Vector{CheckConstraintsFunction}}}()
map_edges_update_state = Dict{Symbol, Dict{Symbol,Vector{UpdateStateFunction}}}()
# Updating types and simulation methods # Updating types and simulation methods
@everywhere @eval $(MarkovProcesses.generate_code_synchronized_model_type_def(model_name, lha_name)) @everywhere @eval $(MarkovProcesses.generate_code_synchronized_model_type_def(model_name, lha_name))
@everywhere @eval $(MarkovProcesses.generate_code_next_state(lha_name, edge_type, check_constraints, update_state!)) @everywhere @eval $(MarkovProcesses.generate_code_next_state(lha_name, edge_type))
@everywhere @eval $(MarkovProcesses.generate_code_synchronized_simulation(model_name, lha_name, edge_type, m.f!, m.isabsorbing)) @everywhere @eval $(MarkovProcesses.generate_code_synchronized_simulation(model_name, lha_name, edge_type, m.f!, m.isabsorbing))
A = AutomatonF(m.transitions, locations, Λ_F, locations_init, locations_final, A = AutomatonF(m.transitions, locations, Λ_F, locations_init, locations_final,
map_var_automaton_idx, flow, map_edges, constants, m.map_var_idx) map_var_automaton_idx, flow, map_edges,
map_edges_transitions, map_edges_check_constraints, map_edges_update_state,
constants, m.map_var_idx)
return A return A
end end
export create_automaton_F
This diff is collapsed.
This diff is collapsed.
# Creation of the automaton types # Creation of the automaton types
@everywhere @eval abstract type EdgeEuclideanDistanceAutomaton <: Edge end #@everywhere @eval abstract type EdgeEuclideanDistanceAutomaton <: Edge end
@everywhere struct EdgeEuclideanDistanceAutomaton <: Edge
transitions::TransitionSet
check_constraints::CheckConstraintsFunction
update_state!::UpdateStateFunction
end
@everywhere @eval $(MarkovProcesses.generate_code_lha_type_def(:EuclideanDistanceAutomaton, :EdgeEuclideanDistanceAutomaton)) @everywhere @eval $(MarkovProcesses.generate_code_lha_type_def(:EuclideanDistanceAutomaton, :EdgeEuclideanDistanceAutomaton))
function create_euclidean_distance_automaton(m::ContinuousTimeModel, timeline::AbstractVector{Float64}, observations::AbstractVector{Float64}, sym_obs::VariableModel) function create_euclidean_distance_automaton(m::ContinuousTimeModel, timeline::AbstractVector{Float64}, observations::AbstractVector{Float64}, sym_obs::VariableModel)
...@@ -43,14 +48,20 @@ function create_euclidean_distance_automaton(m::ContinuousTimeModel, timeline::A ...@@ -43,14 +48,20 @@ function create_euclidean_distance_automaton(m::ContinuousTimeModel, timeline::A
basename_func = "$(model_name)_$(id)" basename_func = "$(model_name)_$(id)"
edge_name(from_loc::Location, to_loc::Location, edge_number::Int) = edge_name(from_loc::Location, to_loc::Location, edge_number::Int) =
Symbol("Edge_$(lha_name)_$(basename_func)_$(from_loc)$(to_loc)_$(edge_number)") Symbol("Edge_$(lha_name)_$(basename_func)_$(from_loc)$(to_loc)_$(edge_number)")
function check_constraints(from_loc::Location, to_loc::Location, edge_number::Int)
return Symbol("check_constraints_$(edge_type)_$(from_loc)$(to_loc)_$(edge_number)_$(model_name)_$(id)")
end
function update_state!(from_loc::Location, to_loc::Location, edge_number::Int)
return Symbol("update_state_$(edge_type)_$(from_loc)$(to_loc)_$(edge_number)_$(model_name)_$(id)!")
end
## check_constraints & update_state! ## check_constraints & update_state!
@everywhere @eval begin meta_funcs = quote
# l0 loc # l0 loc
# l0 => l1 # l0 => l1
struct $(edge_name(:l0, :l1, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end #struct $(edge_name(:l0, :l1, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
$(check_constraints)(edge::$(edge_name(:l0, :l1, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = true @everywhere $(check_constraints(:l0, :l1, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = true
$(update_state!)(edge::$(edge_name(:l0, :l1, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = @everywhere $(update_state!(:l0, :l1, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
(S_values[$(to_idx(:n))] = x[$(idx_obs_var)]; (S_values[$(to_idx(:n))] = x[$(idx_obs_var)];
S_values[$(to_idx(:d))] = 0.0; S_values[$(to_idx(:d))] = 0.0;
S_values[$(to_idx(:idx))] = 1.0; S_values[$(to_idx(:idx))] = 1.0;
...@@ -59,32 +70,33 @@ function create_euclidean_distance_automaton(m::ContinuousTimeModel, timeline::A ...@@ -59,32 +70,33 @@ function create_euclidean_distance_automaton(m::ContinuousTimeModel, timeline::A
# l1 loc # l1 loc
# l1 => l1 # l1 => l1
# Defined below # Defined below
struct $(edge_name(:l1, :l1, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end #struct $(edge_name(:l1, :l1, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
$(check_constraints)(edge::$(edge_name(:l1, :l1, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = @everywhere $(check_constraints(:l1, :l1, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
(tml = $(Tuple(timeline)); (tml = $(Tuple(timeline));
tml_idx = tml[convert(Int, S_values[$(to_idx(:idx))])]; tml_idx = tml[convert(Int, S_values[$(to_idx(:idx))])];
S_values[$(to_idx(:t))] >= tml_idx) S_values[$(to_idx(:t))] >= tml_idx)
$(update_state!)(edge::$(edge_name(:l1, :l1, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = @everywhere $(update_state!(:l1, :l1, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
(y_obs = $(Tuple(observations)); (y_obs = $(Tuple(observations));
y_obs_idx = y_obs[convert(Int, S_values[$(to_idx(:idx))])]; y_obs_idx = y_obs[convert(Int, S_values[$(to_idx(:idx))])];
S_values[$(to_idx(:d))] = S_values[$(to_idx(:d))]+(S_values[$(to_idx(:n))]-y_obs_idx)^2; S_values[$(to_idx(:d))] = S_values[$(to_idx(:d))]+(S_values[$(to_idx(:n))]-y_obs_idx)^2;
S_values[$(to_idx(:idx))] = S_values[$(to_idx(:idx))]+1.0; S_values[$(to_idx(:idx))] = S_values[$(to_idx(:idx))]+1.0;
:l1) :l1)
struct $(edge_name(:l1, :l1, 2)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end #struct $(edge_name(:l1, :l1, 2)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
$(check_constraints)(edge::$(edge_name(:l1, :l1, 2)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = true @everywhere $(check_constraints(:l1, :l1, 2))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = true
$(update_state!)(edge::$(edge_name(:l1, :l1, 2)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = @everywhere $(update_state!(:l1, :l1, 2))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
(S_values[$(to_idx(:n))] = x[$(idx_obs_var)]; (S_values[$(to_idx(:n))] = x[$(idx_obs_var)];
:l1) :l1)
# l1 => l2 # l1 => l2
struct $(edge_name(:l1, :l2, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end #struct $(edge_name(:l1, :l2, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
$(check_constraints)(edge::$(edge_name(:l1, :l2, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = @everywhere $(check_constraints(:l1, :l2, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
S_values[$(to_idx(:idx))] >= ($nbr_observations + 1) S_values[$(to_idx(:idx))] >= ($nbr_observations + 1)
$(update_state!)(edge::$(edge_name(:l1, :l2, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = @everywhere $(update_state!(:l1, :l2, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
(S_values[$(to_idx(:d))] = sqrt(S_values[$(to_idx(:d))]); (S_values[$(to_idx(:d))] = sqrt(S_values[$(to_idx(:d))]);
:l2) :l2)
end end
eval(meta_funcs)
@eval begin @eval begin
map_edges = Dict{Location,Dict{Location,Vector{$(edge_type)}}}() map_edges = Dict{Location,Dict{Location,Vector{$(edge_type)}}}()
...@@ -95,20 +107,24 @@ function create_euclidean_distance_automaton(m::ContinuousTimeModel, timeline::A ...@@ -95,20 +107,24 @@ function create_euclidean_distance_automaton(m::ContinuousTimeModel, timeline::A
## Edges ## Edges
# l0 loc # l0 loc
# l0 => l1 # l0 => l1
edge1 = $(edge_name(:l0, :l1, 1))(nothing) edge1 = EdgeEuclideanDistanceAutomaton(nothing, $(check_constraints(:l0, :l1, 1)), $(update_state!(:l0, :l1, 1)))
map_edges[:l0][:l1] = [edge1] map_edges[:l0][:l1] = [edge1]
# l1 loc # l1 loc
# l1 => l1 # l1 => l1
edge1 = $(edge_name(:l1, :l1, 1))(nothing) edge1 = EdgeEuclideanDistanceAutomaton(nothing, $(check_constraints(:l1, :l1, 1)), $(update_state!(:l1, :l1, 1)))
edge2 = $(edge_name(:l1, :l1, 2))([:ALL]) edge2 = EdgeEuclideanDistanceAutomaton([:ALL], $(check_constraints(:l1, :l1, 2)), $(update_state!(:l1, :l1, 2)))
map_edges[:l1][:l1] = [edge1, edge2] map_edges[:l1][:l1] = [edge1, edge2]
# l1 => l2 # l1 => l2
edge1 = $(edge_name(:l1, :l2, 1))(nothing) edge1 = EdgeEuclideanDistanceAutomaton(nothing, $(check_constraints(:l1, :l2, 1)), $(update_state!(:l1, :l2, 1)))
map_edges[:l1][:l2] = [edge1] map_edges[:l1][:l2] = [edge1]
end end
map_edges_transitions = Dict{Symbol, Dict{Symbol,Vector{TransitionSet}}}()
map_edges_check_constraints = Dict{Symbol, Dict{Symbol,Vector{CheckConstraintsFunction}}}()
map_edges_update_state = Dict{Symbol, Dict{Symbol,Vector{UpdateStateFunction}}}()
## Constants ## Constants
constants = Dict{Symbol,Float64}(:nbr_obs => nbr_observations) constants = Dict{Symbol,Float64}(:nbr_obs => nbr_observations)
for i = 1:nbr_observations for i = 1:nbr_observations
...@@ -118,11 +134,13 @@ function create_euclidean_distance_automaton(m::ContinuousTimeModel, timeline::A ...@@ -118,11 +134,13 @@ function create_euclidean_distance_automaton(m::ContinuousTimeModel, timeline::A
# Updating types and simulation methods # Updating types and simulation methods
@everywhere @eval $(MarkovProcesses.generate_code_synchronized_model_type_def(model_name, lha_name)) @everywhere @eval $(MarkovProcesses.generate_code_synchronized_model_type_def(model_name, lha_name))
@everywhere @eval $(MarkovProcesses.generate_code_next_state(lha_name, edge_type, check_constraints, update_state!)) @everywhere @eval $(MarkovProcesses.generate_code_next_state(lha_name, edge_type))
@everywhere @eval $(MarkovProcesses.generate_code_synchronized_simulation(model_name, lha_name, edge_type, m.f!, m.isabsorbing)) @everywhere @eval $(MarkovProcesses.generate_code_synchronized_simulation(model_name, lha_name, edge_type, m.f!, m.isabsorbing))
A = EuclideanDistanceAutomaton(m.transitions, locations, Λ_F, locations_init, locations_final, A = EuclideanDistanceAutomaton(m.transitions, locations, Λ_F, locations_init, locations_final,
map_var_automaton_idx, flow, map_edges, constants, m.map_var_idx) map_var_automaton_idx, flow,
map_edges, map_edges_transitions, map_edges_check_constraints, map_edges_update_state,
constants, m.map_var_idx)
return A return A
end end
......
# Creation of the automaton types # Creation of the automaton types
@everywhere @eval abstract type EdgeEuclideanDistanceAutomaton2 <: Edge end #@everywhere @eval abstract type EdgeEuclideanDistanceAutomaton2 <: Edge end
@everywhere struct EdgeEuclideanDistanceAutomaton2 <: Edge
transitions::TransitionSet
check_constraints::CheckConstraintsFunction
update_state!::UpdateStateFunction
end
@everywhere @eval $(MarkovProcesses.generate_code_lha_type_def(:EuclideanDistanceAutomaton2,:EdgeEuclideanDistanceAutomaton2)) @everywhere @eval $(MarkovProcesses.generate_code_lha_type_def(:EuclideanDistanceAutomaton2,:EdgeEuclideanDistanceAutomaton2))
function create_euclidean_distance_automaton_2(m::ContinuousTimeModel, timeline::AbstractVector{Float64}, observations::AbstractVector{Float64}, sym_obs::VariableModel) function create_euclidean_distance_automaton_2(m::ContinuousTimeModel, timeline::AbstractVector{Float64}, observations::AbstractVector{Float64}, sym_obs::VariableModel)
...@@ -48,99 +53,104 @@ function create_euclidean_distance_automaton_2(m::ContinuousTimeModel, timeline: ...@@ -48,99 +53,104 @@ function create_euclidean_distance_automaton_2(m::ContinuousTimeModel, timeline:
basename_func = "$(model_name)_$(id)" basename_func = "$(model_name)_$(id)"
edge_name(from_loc::Location, to_loc::Location, edge_number::Int) = edge_name(from_loc::Location, to_loc::Location, edge_number::Int) =
Symbol("Edge_$(lha_name)_$(basename_func)_$(from_loc)$(to_loc)_$(edge_number)") Symbol("Edge_$(lha_name)_$(basename_func)_$(from_loc)$(to_loc)_$(edge_number)")
function check_constraints(from_loc::Location, to_loc::Location, edge_number::Int)
return Symbol("check_constraints_$(edge_type)_$(from_loc)$(to_loc)_$(edge_number)_$(model_name)_$(id)")
end
function update_state!(from_loc::Location, to_loc::Location, edge_number::Int)
return Symbol("update_state_$(edge_type)_$(from_loc)$(to_loc)_$(edge_number)_$(model_name)_$(id)!")
end
loc_nbr_obs = Symbol("l$(nbr_observations)") loc_nbr_obs = Symbol("l$(nbr_observations)")
@everywhere @eval begin meta_funcs = quote
# l0 loc # l0 loc
# l0 => l1 # l0 => l1
@everywhere struct $(edge_name(:l0, :l1, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end #struct $(edge_name(:l0, :l1, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
$(check_constraints)(edge::$(edge_name(:l0, :l1, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = true @everywhere $(check_constraints(:l0, :l1, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = true
@everywhere $(update_state!)(edge::$(edge_name(:l0, :l1, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = @everywhere $(update_state!(:l0, :l1, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
(S_values[$(to_idx(:n))] = x[$(idx_obs_var)]; (S_values[$(to_idx(:n))] = x[$(idx_obs_var)];
S_values[$(to_idx(:d))] = 0.0; S_values[$(to_idx(:d))] = 0.0;
:l1) :l1)
# lnbr_obs => lfinal # lnbr_obs => lfinal
@everywhere struct $(edge_name(loc_nbr_obs, :lfinal, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end #struct $(edge_name(loc_nbr_obs, :lfinal, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
$(check_constraints)(edge::$(edge_name(loc_nbr_obs, :lfinal, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = @everywhere $(check_constraints(loc_nbr_obs, :lfinal, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
S_values[$(to_idx(:t))] >= $(timeline[nbr_observations]) S_values[$(to_idx(:t))] >= $(timeline[nbr_observations])
@everywhere $(update_state!)(edge::$(edge_name(loc_nbr_obs, :lfinal, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = @everywhere $(update_state!(loc_nbr_obs, :lfinal, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
(S_values[$(to_idx(:d))] = S_values[$(to_idx(:d))]+(S_values[$(to_idx(:n))]-$(observations[nbr_observations]))^2; (S_values[$(to_idx(:d))] = S_values[$(to_idx(:d))]+(S_values[$(to_idx(:n))]-$(observations[nbr_observations]))^2;
S_values[$(to_idx(:d))] = sqrt(S_values[$(to_idx(:d))]); S_values[$(to_idx(:d))] = sqrt(S_values[$(to_idx(:d))]);
:lfinal) :lfinal)
# lnbr_obs => lnbr_obs # lnbr_obs => lnbr_obs
@everywhere struct $(edge_name(loc_nbr_obs, loc_nbr_obs, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end #struct $(edge_name(loc_nbr_obs, loc_nbr_obs, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
$(check_constraints)(edge::$(edge_name(loc_nbr_obs, loc_nbr_obs, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = true @everywhere $(check_constraints(loc_nbr_obs, loc_nbr_obs, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = true
@everywhere $(update_state!)(edge::$(edge_name(loc_nbr_obs, loc_nbr_obs, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = @everywhere $(update_state!(loc_nbr_obs, loc_nbr_obs, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
(S_values[$(to_idx(:n))] = x[$(idx_obs_var)]; (S_values[$(to_idx(:n))] = x[$(idx_obs_var)];
$(Meta.quot(loc_nbr_obs))) $(Meta.quot(loc_nbr_obs)))
end end
eval(meta_funcs)
@eval begin @eval begin
map_edges = Dict{Location,Dict{Location,Vector{$(edge_type)}}}() map_edges = Dict{Location,Dict{Location,Vector{$(edge_type)}}}()
for loc in $(locations) for loc in $(locations)
map_edges[loc] = Dict{Location,Vector{$(edge_type)}}() map_edges[loc] = Dict{Location,Vector{$(edge_type)}}()
end end