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

The new meta paradigm was extended to all automata and models

implemetend in the package.
A lot of files has been modified because some of the internal syntax has
changed. But the top level methods should still work.

Two tests about the plots of synchronized oscillatory simulations have
been added.

All tests passed.
parent dd619a95
# Creation of the automaton types
@everywhere @eval abstract type EdgeAutomatonF <: Edge end
@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)
# Requirements for the automaton
@assert sym_obs in m.g "$(sym_obs) is not observed."
@assert (x1 <= x2) "x1 > x2 impossible for F automaton."
@assert (t1 <= t2) "t1 > t2 impossible for F automaton."
# Automaton types and functions
model_name = Symbol(typeof(m))
lha_name = :AutomatonF
edge_type = :EdgeAutomatonF
check_constraints = Symbol("check_constraints_$(lha_name)")
update_state! = Symbol("update_state_$(lha_name)!")
# Locations
locations = [:l0, :l1, :l2, :l3]
......@@ -17,146 +28,143 @@ function create_automaton_F(m::ContinuousTimeModel, x1::Float64, x2::Float64, t1
locations_init = [:l0]
locations_final = [:l2]
#S.n <=> S.values[A.map_var_automaton_idx[:n]]
#P <=> xn[map_var_model_idx[constants[str_O]] with str_O = :P. On stock str_O dans constants
# P = get_value(S, x, sym_obs)
## Map of automaton variables
map_var_automaton_idx = Dict{VariableAutomaton,Int}(:n => 1, :d => 2, :isabs => 3)
## Flow of variables
flow = Dict{Location,Vector{Float64}}(:l0 => [0.0,0.0,0.0],
:l1 => [0.0,0.0,0.0],
:l2 => [0.0,0.0,0.0],
:l3 => [0.0,0.0,0.0])
vector_flow = [0.0,0.0,0.0]
flow = Dict{Location,Vector{Float64}}(:l0 => vector_flow,
:l1 => vector_flow,
:l2 => vector_flow,
:l3 => vector_flow)
## Edges
map_edges = Dict{Location, Dict{Location, Vector{Edge}}}()
for loc in locations
map_edges[loc] = Dict{Location, Vector{Edge}}()
end
to_idx(var::Symbol) = map_var_automaton_idx[var]
idx_obs_var = getfield(m, :map_var_idx)[sym_obs]
idx_var_n = map_var_automaton_idx[:n]
idx_var_d = map_var_automaton_idx[:d]
idx_var_isabs = map_var_automaton_idx[:isabs]
nbr_rand = rand(1:100000)
basename_func = "$(replace(m.name, ' '=>'_'))_$(nbr_rand)"
basename_func = replace(basename_func, '-'=>'_')
sym_isabs_func = Symbol(m.isabsorbing)
func_name(type_func::Symbol, from_loc::Location, to_loc::Location, edge_number::Int) =
Symbol("$(type_func)_aut_F_$(basename_func)_$(from_loc)$(to_loc)_$(edge_number)$(type_func == :us ? "!" : "")")
meta_elementary_functions = quote
@everywhere istrue(val::Float64) = convert(Bool, val)
id = MarkovProcesses.newid()
basename_func = "$(model_name)_$(id)"
edge_name(from_loc::Location, to_loc::Location, edge_number::Int) =
Symbol("Edge_$(lha_name)_$(basename_func)_$(from_loc)$(to_loc)_$(edge_number)")
## check_constraints & update_state!
@everywhere @eval begin
istrue(val::Float64) = convert(Bool, val)
## Check constraints and update state functions
# l0 loc : we construct the edges of the form l0 => (..)
# "cc" as check_constraints and "us" as update_state
# l0 => l1
@everywhere $(func_name(:cc, :l0, :l1, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = true
@everywhere $(func_name(:us, :l0, :l1, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
(S_values[$(idx_var_n)] = x[$(idx_obs_var)];
setindex!(S_values, Inf, $(idx_var_d));
setindex!(S_values, getfield(Main, $(Meta.quot(sym_isabs_func)))(p, x), $(idx_var_isabs));
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
$(update_state!)(edge::$(edge_name(: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(:d))] = Inf;
S_values[$(to_idx(:isabs))] = $(m.isabsorbing)(p,x);
:l1)
# l1 loc
# l1 => l2
#=
@everywhere $(func_name(:cc, :l1, :l2, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
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}) =
S_time >= $t1 &&
($x1 <= S_values[$(idx_var_n)] <= $x2)
@everywhere $(func_name(:us, :l1, :l2, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
(setindex!(S_values, 0, $(idx_var_d));
:l2) =#
#=
@everywhere $(func_name(:cc, :l1, :l2, 3))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
istrue(S_values[$(idx_var_isabs)]) && S_time <= $t2
@everywhere $(func_name(:us, :l1, :l2, 3))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
(:l2)
=#
@everywhere $(func_name(:cc, :l1, :l2, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
S_time >= $t1 &&
S_values[$(idx_var_d)] == 0
@everywhere $(func_name(:us, :l1, :l2, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
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}) =
(:l2)
@everywhere $(func_name(:cc, :l1, :l2, 2))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
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}) =
(S_time >= $t2) &&
(S_values[$(idx_var_n)] < $x1 || S_values[$(idx_var_n)] > $x2)
@everywhere $(func_name(:us, :l1, :l2, 2))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
(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}) =
(:l2;)
#setindex!(S_values, min(abs(S_values[$(idx_var_n)] - $x1), abs(S_values[$(idx_var_n)] - $x2)), $(idx_var_d)))
#setindex!(S_values, min(abs(S_values[$(to_idx(:n))] - $x1), abs(S_values[$(to_idx(:n))] - $x2)), $(to_idx(:d))))
# l1 => l3
@everywhere $(func_name(:cc, :l1, :l3, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
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}) =
(S_time <= $t1) &&
(S_values[$(idx_var_n)] < $x1 || S_values[$(idx_var_n)] > $x2)
@everywhere $(func_name(:us, :l1, :l3, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
(setindex!(S_values, min(sqrt((S_time - $t1)^2 + (S_values[$(idx_var_n)] - $x2)^2),
sqrt((S_time - $t1)^2 + (S_values[$(idx_var_n)] - $x1)^2)), $(idx_var_d));
:l3)
@everywhere $(func_name(:cc, :l1, :l3, 2))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
($x1 <= S_values[$(idx_var_n)] <= $x2)
@everywhere $(func_name(:us, :l1, :l3, 2))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
(setindex!(S_values, 0, $(idx_var_d));
(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}) =
(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));
:l3)
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}) =
($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}) =
(S_values[$(to_idx(:d))] = 0;
:l3)
@everywhere $(func_name(:cc, :l1, :l3, 3))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
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}) =
(S_time >= $t1) &&
(S_values[$(idx_var_n)] < $x1 || S_values[$(idx_var_n)] > $x2)
@everywhere $(func_name(:us, :l1, :l3, 3))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
(val_min = min(S_values[$(idx_var_d)],
min(abs(S_values[$(idx_var_n)] - $x1), abs(S_values[$(idx_var_n)] - $x2)));
setindex!(S_values, val_min, $(idx_var_d));
:l3)
(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}) =
(val_min = min(S_values[$(to_idx(:d))],
min(abs(S_values[$(to_idx(:n))] - $x1), abs(S_values[$(to_idx(:n))] - $x2)));
S_values[$(to_idx(:d))] = val_min;
:l3)
# l3 loc
# l3 => l1
@everywhere $(func_name(:cc, :l3, :l1, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = true
@everywhere $(func_name(:us, :l3, :l1, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
(S_values[$(idx_var_n)] = x[$(idx_obs_var)];
setindex!(S_values, getfield(Main, $(Meta.quot(sym_isabs_func)))(p, x), $(idx_var_isabs));
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
$(update_state!)(edge::$(edge_name(: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(:isabs))] = $(m.isabsorbing)(p,x);
:l1)
# l3 => l2
@everywhere $(func_name(:cc, :l3, :l2, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
(S_time >= $t2 || istrue(S_values[$(idx_var_isabs)]))
@everywhere $(func_name(:us, :l3, :l2, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
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}) =
(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}) =
(:l2)
end
eval(meta_elementary_functions)
# l0 loc
# l0 => l1
edge1 = Edge(nothing, getfield(Main, func_name(:cc, :l0, :l1, 1)), getfield(Main, func_name(:us, :l0, :l1, 1)))
map_edges[:l0][:l1] = [edge1]
# l1 loc
# l1 => l2
edge1 = Edge(nothing, getfield(Main, func_name(:cc, :l1, :l2, 1)), getfield(Main, func_name(:us, :l1, :l2, 1)))
edge2 = Edge(nothing, getfield(Main, func_name(:cc, :l1, :l2, 2)), getfield(Main, func_name(:us, :l1, :l2, 2)))
map_edges[:l1][:l2] = [edge1, edge2]
#edge3 = Edge(nothing, getfield(Main, func_name(:cc, :l1, :l2, 3)), getfield(Main, func_name(:us, :l1, :l2, 3)))
#edge4 = Edge(nothing, getfield(Main, func_name(:cc, :l1, :l2, 4)), getfield(Main, func_name(:us, :l1, :l2, 4)))
#map_edges[:l1][:l2] = [edge1, edge2, edge3, edge4]
# l1 => l3
edge1 = Edge(nothing, getfield(Main, func_name(:cc, :l1, :l3, 1)), getfield(Main, func_name(:us, :l1, :l3, 1)))
edge2 = Edge(nothing, getfield(Main, func_name(:cc, :l1, :l3, 2)), getfield(Main, func_name(:us, :l1, :l3, 2)))
edge3 = Edge(nothing, getfield(Main, func_name(:cc, :l1, :l3, 3)), getfield(Main, func_name(:us, :l1, :l3, 3)))
map_edges[:l1][:l3] = [edge1, edge2, edge3]
# l3 loc
# l3 => l1
edge1 = Edge([:ALL], getfield(Main, func_name(:cc, :l3, :l1, 1)), getfield(Main, func_name(:us, :l3, :l1, 1)))
map_edges[:l3][:l1] = [edge1]
# l3 => l2
edge1 = Edge(nothing, getfield(Main, func_name(:cc, :l3, :l2, 1)), getfield(Main, func_name(:us, :l3, :l2, 1)))
map_edges[:l3][:l2] = [edge1]
@eval begin
map_edges = Dict{Location, Dict{Location, Vector{$(edge_type)}}}()
for loc in $(locations)
map_edges[loc] = Dict{Location, Vector{$(edge_type)}}()
end
# l0 loc
# l0 => l1
edge1 = $(edge_name(:l0, :l1, 1))(nothing)
map_edges[:l0][:l1] = [edge1]
# l1 loc
# l1 => l2
edge1 = $(edge_name(:l1, :l2, 1))(nothing)
edge2 = $(edge_name(:l1, :l2, 2))(nothing)
map_edges[:l1][:l2] = [edge1, edge2]
#edge3 = $(edge_name(:l1, :l2, 3))(nothing)
#edge4 = $(edge_name(:l1, :l2, 4))(nothing)
#map_edges[:l1][:l2] = [edge1, edge2, edge3, edge4]
# l1 => l3
edge1 = $(edge_name(:l1, :l3, 1))(nothing)
edge2 = $(edge_name(:l1, :l3, 2))(nothing)
edge3 = $(edge_name(:l1, :l3, 3))(nothing)
map_edges[:l1][:l3] = [edge1, edge2, edge3]
# l3 loc
# l3 => l1
edge1 = $(edge_name(:l3, :l1, 1))([:ALL])
map_edges[:l3][:l1] = [edge1]
# l3 => l2
edge1 = $(edge_name(:l3, :l2, 1))(nothing)
map_edges[:l3][:l2] = [edge1]
end
## Constants
constants = Dict{Symbol,Float64}(:x1 => x1, :x2 => x2, :t1 => t1, :t2 => t2)
A = LHA("F property", m.transitions, locations, Λ_F, locations_init, locations_final,
map_var_automaton_idx, flow, map_edges, constants, m.map_var_idx)
# Updating types and simulation methods
@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_synchronized_simulation(model_name, lha_name, edge_type, m.f!, m.isabsorbing))
A = AutomatonF(m.transitions, locations, Λ_F, locations_init, locations_final,
map_var_automaton_idx, flow, map_edges, constants, m.map_var_idx)
return A
end
......
This diff is collapsed.
This diff is collapsed.
# Creation of the automaton types
lha_name = :EuclideanDistanceAutomaton
edge_type = :EdgeEuclideanDistanceAutomaton
@everywhere @eval abstract type $(edge_type) <: Edge end
@everywhere @eval $(MarkovProcesses.generate_code_lha_type_def(lha_name, edge_type))
@everywhere @eval abstract type EdgeEuclideanDistanceAutomaton <: Edge end
@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)
# Requirements for the automaton
......@@ -47,15 +45,15 @@ function create_euclidean_distance_automaton(m::ContinuousTimeModel, timeline::A
Symbol("Edge_$(lha_name)_$(basename_func)_$(from_loc)$(to_loc)_$(edge_number)")
## check_constraints & update_state!
meta_elementary_func = quote
@everywhere @eval begin
# l0 loc
# l0 => l1
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
$(update_state!)(edge::$(edge_name(:l0, :l1, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
(setindex!(S_values, x[$(idx_obs_var)], $(to_idx(:n)));
setindex!(S_values, 0.0, $(to_idx(:d)));
setindex!(S_values, 1.0, $(to_idx(:idx)));
(S_values[$(to_idx(:n))] = x[$(idx_obs_var)];
S_values[$(to_idx(:d))] = 0.0;
S_values[$(to_idx(:idx))] = 1.0;
:l1)
# l1 loc
......@@ -69,15 +67,14 @@ function create_euclidean_distance_automaton(m::ContinuousTimeModel, timeline::A
$(update_state!)(edge::$(edge_name(:l1, :l1, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
(y_obs = $(Tuple(observations));
y_obs_idx = y_obs[convert(Int, S_values[$(to_idx(:idx))])];
setindex!(S_values, S_values[$(to_idx(:d))] + (S_values[$(to_idx(:n))] - y_obs_idx)^2,
$(to_idx(:d)));
setindex!(S_values, S_values[$(to_idx(:idx))] + 1.0, $(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(:idx))] = S_values[$(to_idx(:idx))]+1.0;
:l1)
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
$(update_state!)(edge::$(edge_name(:l1, :l1, 2)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
(setindex!(S_values, x[$(idx_obs_var)], $(to_idx(:n)));
(S_values[$(to_idx(:n))] = x[$(idx_obs_var)];
:l1)
# l1 => l2
......@@ -85,10 +82,9 @@ function create_euclidean_distance_automaton(m::ContinuousTimeModel, timeline::A
$(check_constraints)(edge::$(edge_name(:l1, :l2, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
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}) =
(setindex!(S_values, sqrt(S_values[$(to_idx(:d))]), $(to_idx(:d)));
(S_values[$(to_idx(:d))] = sqrt(S_values[$(to_idx(:d))]);
:l2)
end
@everywhere eval($(meta_elementary_func))
@eval begin
map_edges = Dict{Location,Dict{Location,Vector{$(edge_type)}}}()
......@@ -99,17 +95,17 @@ function create_euclidean_distance_automaton(m::ContinuousTimeModel, timeline::A
## Edges
# l0 loc
# l0 => l1
edge1 = getfield(Main, $(Meta.quot(edge_name(:l0, :l1, 1))))(nothing)
edge1 = $(edge_name(:l0, :l1, 1))(nothing)
map_edges[:l0][:l1] = [edge1]
# l1 loc
# l1 => l1
edge1 = getfield(Main, $(Meta.quot(edge_name(:l1, :l1, 1))))(nothing)
edge2 = getfield(Main, $(Meta.quot(edge_name(:l1, :l1, 2))))([:ALL])
edge1 = $(edge_name(:l1, :l1, 1))(nothing)
edge2 = $(edge_name(:l1, :l1, 2))([:ALL])
map_edges[:l1][:l1] = [edge1, edge2]
# l1 => l2
edge1 = getfield(Main, $(Meta.quot(edge_name(:l1, :l2, 1))))(nothing)
edge1 = $(edge_name(:l1, :l2, 1))(nothing)
map_edges[:l1][:l2] = [edge1]
end
......@@ -120,7 +116,7 @@ function create_euclidean_distance_automaton(m::ContinuousTimeModel, timeline::A
constants[Symbol("y_$(convert(Float64, i))")] = observations[i]
end
# Updating next_state!
# Updating types and simulation methods
@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_synchronized_simulation(model_name, lha_name, edge_type, m.f!, m.isabsorbing))
......
# Creation of the automaton types
@everywhere @eval abstract type EdgeEuclideanDistanceAutomaton2 <: Edge end
@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)
# Requirements for the automaton
@assert sym_obs in m.g "$(sym_obs) is not observed."
@assert length(timeline) == length(observations) "Timeline and observations vectors don't have the same length"
nbr_observations = length(observations)
# Automaton types and functions
model_name = Symbol(typeof(m))
lha_name = :EuclideanDistanceAutomaton2
edge_type = :EdgeEuclideanDistanceAutomaton2
check_constraints = Symbol("check_constraints_$(lha_name)")
update_state! = Symbol("update_state_$(lha_name)!")
# Locations
locations = [:l0, :lfinal]
for i = 1:nbr_observations
......@@ -30,92 +41,106 @@ function create_euclidean_distance_automaton_2(m::ContinuousTimeModel, timeline:
end
## Edges
map_edges = Dict{Location, Dict{Location, Vector{Edge}}}()
for loc in locations
map_edges[loc] = Dict{Location, Vector{Edge}}()
end
idx_obs_var = getfield(m, :map_var_idx)[sym_obs]
to_idx(var::Symbol) = map_var_automaton_idx[var]
nbr_rand = rand(1:1000)
basename_func = "$(replace(m.name, ' '=>'_'))_$(nbr_rand)"
basename_func = replace(basename_func, '-'=>'_')
func_name(type_func::Symbol, from_loc::Location, to_loc::Location, edge_number::Int) =
Symbol("$(type_func)_eucl_dist_aut_2_$(basename_func)_$(from_loc)$(to_loc)_$(edge_number)$(type_func == :us ? "!" : "")")
id = MarkovProcesses.newid()
basename_func = "$(model_name)_$(id)"
edge_name(from_loc::Location, to_loc::Location, edge_number::Int) =
Symbol("Edge_$(lha_name)_$(basename_func)_$(from_loc)$(to_loc)_$(edge_number)")
loc_nbr_obs = Symbol("l$(nbr_observations)")
meta_elementary_functions = quote
@everywhere @eval begin
# l0 loc
# l0 => l1
@everywhere $(func_name(:cc, :l0, :l1, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = true
@everywhere $(func_name(:us, :l0, :l1, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
(setindex!(S_values, x[$(idx_obs_var)], $(to_idx(:n)));
setindex!(S_values, 0.0, $(to_idx(:d)));
@everywhere 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 $(update_state!)(edge::$(edge_name(: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(:d))] = 0.0;
:l1)
# lnbr_obs => lfinal
@everywhere $(func_name(:cc, loc_nbr_obs, :lfinal, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
@everywhere 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}) =
S_values[$(to_idx(:t))] >= $(timeline[nbr_observations])
@everywhere $(func_name(:us, loc_nbr_obs, :lfinal, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
(setindex!(S_values, S_values[$(to_idx(:d))] + (S_values[$(to_idx(:n))]-$(observations[nbr_observations]))^2,
$(to_idx(:d)));
setindex!(S_values, sqrt(S_values[$(to_idx(:d))]), $(to_idx(:d)));
@everywhere $(update_state!)(edge::$(edge_name(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))] = sqrt(S_values[$(to_idx(:d))]);
:lfinal)
# lnbr_obs => lnbr_obs
@everywhere $(func_name(:cc, loc_nbr_obs, loc_nbr_obs, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = true
@everywhere $(func_name(:us, loc_nbr_obs, loc_nbr_obs, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
(setindex!(S_values, x[$(idx_obs_var)], $(to_idx(:n)));
@everywhere 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 $(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}) =
(S_values[$(to_idx(:n))] = x[$(idx_obs_var)];
$(Meta.quot(loc_nbr_obs)))
end
eval(meta_elementary_functions)
# l0 loc
# l0 => l1
edge1 = Edge(nothing, getfield(Main, func_name(:cc, :l0, :l1, 1)), getfield(Main, func_name(:us, :l0, :l1, 1)))
map_edges[:l0][:l1] = [edge1]
# lnbr_obs => lfinal
edge1 = Edge(nothing, getfield(Main, func_name(:cc, loc_nbr_obs, :lfinal, 1)), getfield(Main, func_name(:us, loc_nbr_obs, :lfinal, 1)))
map_edges[loc_nbr_obs][:lfinal] = [edge1]
# lnbr_obs => lnbr_obs
edge1 = Edge([:ALL], getfield(Main, func_name(:cc, loc_nbr_obs, loc_nbr_obs, 1)), getfield(Main, func_name(:us, loc_nbr_obs, loc_nbr_obs, 1)))
map_edges[loc_nbr_obs][loc_nbr_obs] = [edge1]
for i = 1:(nbr_observations-1)
loci = Symbol("l$(i)")
locip1 = Symbol("l$(i+1)")
meta_elementary_functions_loci = quote
# l1 loc
# l1 => l1
# Defined below
@everywhere $(func_name(:cc, loci, locip1, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
@eval begin
map_edges = Dict{Location,Dict{Location,Vector{$(edge_type)}}}()
for loc in $(locations)
map_edges[loc] = Dict{Location,Vector{$(edge_type)}}()
end
# l0 loc
# l0 => l1
edge1 = $(edge_name(:l0, :l1, 1))(nothing)
map_edges[:l0][:l1] = [edge1]
# lnbr_obs => lfinal
edge1 = $(edge_name(loc_nbr_obs, :lfinal, 1))(nothing)
map_edges[$(Meta.quot(loc_nbr_obs))][:lfinal] = [edge1]
# lnbr_obs => lnbr_obs
edge1 = $(edge_name(loc_nbr_obs, loc_nbr_obs, 1))([:ALL])
map_edges[$(Meta.quot(loc_nbr_obs))][$(Meta.quot(loc_nbr_obs))] = [edge1]
end
function generate_code_loci_functions(i::Int, loci::Symbol, locip1::Symbol)
return quote
struct $(edge_name(loci, locip1, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
$(check_constraints)(edge::$(edge_name(loci, locip1, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
S_values[$(to_idx(:t))] >= $(timeline[i])
@everywhere $(func_name(:us, loci, locip1, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
(setindex!(S_values, S_values[$(to_idx(:d))] + (S_values[$(to_idx(:n))]-$(observations[i]))^2,
$(to_idx(:d)));
$(update_state!)(edge::$(edge_name(loci, locip1, 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[i]))^2;
$(Meta.quot(locip1)))
@everywhere $(func_name(:cc, loci, loci, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = true
@everywhere $(func_name(:us, loci, loci, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
(setindex!(S_values, x[$(idx_obs_var)], $(to_idx(:n)));
struct $(edge_name(loci, loci, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
$(check_constraints)(edge::$(edge_name(loci, loci, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = true
$(update_state!)(edge::$(edge_name(loci, loci, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
(S_values[$(to_idx(:n))] = x[$(idx_obs_var)];
$(Meta.quot(loci)))
end
eval(meta_elementary_functions_loci)
# loci => loci+1
edge1 = Edge(nothing, getfield(Main, func_name(:cc, loci, locip1, 1)), getfield(Main, func_name(:us, loci, locip1, 1)))
map_edges[loci][locip1] = [edge1]
# loci => loci
edge1 = Edge([:ALL], getfield(Main, func_name(:cc, loci, loci, 1)), getfield(Main, func_name(:us, loci, loci, 1)))
map_edges[loci][loci] = [edge1]
end
function generate_code_loci_edges(loci::Symbol, locip1::Symbol)
return quote
# loci => loci+1
edge1 = $(edge_name(loci, locip1, 1))(nothing)
map_edges[$(Meta.quot(loci))][$(Meta.quot(locip1))] = [edge1]
# loci => loci