diff --git a/automata/automaton_F.jl b/automata/automaton_F.jl
index b18b37ee29a677286be48d99faf34f2242a72646..016c38357e4a9b7c178500d8161ca5f5003f5a46 100644
--- a/automata/automaton_F.jl
+++ b/automata/automaton_F.jl
@@ -1,76 +1,4 @@
 
-@everywhere istrue(val::Float64) = convert(Bool, val)
-
-# Invariant predicates functions
-@everywhere true_inv_predicate(x::Vector{Int}) = true 
-
-# 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 cc_aut_F_l0l1_1(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = true
-# us_aut_F_l0l1_1! inside create_automaton_F
-
-# l1 loc
-# l1 => l2
-@everywhere cc_aut_F_l1l2_1(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-getfield(S, :time) >= constants[:t1] &&
-(constants[:x1] <= S[:n] <= constants[:x2])
-@everywhere us_aut_F_l1l2_1!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(S.loc = :l2;
- S[:d] = 0)
-
-@everywhere cc_aut_F_l1l2_4(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-getfield(S, :time) >= constants[:t1] &&
-S[:d] == 0 
-@everywhere us_aut_F_l1l2_4!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(S.loc = :l2)
-
-@everywhere cc_aut_F_l1l2_2(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(getfield(S, :time) >= constants[:t2]) && 
-(S[:n] < constants[:x1] || S[:n] > constants[:x2])
-@everywhere us_aut_F_l1l2_2!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(S.loc = :l2;
- S[:d] = min(abs(S[:n] - constants[:x1]), abs(S[:n] - constants[:x2])))
-
-@everywhere cc_aut_F_l1l2_3(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-istrue(S[:isabs]) && getfield(S, :time) <= constants[:t2]
-@everywhere us_aut_F_l1l2_3!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(S.loc = :l2)
-
-# l1 => l3
-@everywhere cc_aut_F_l1l3_1(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(constants[:x1] <= S[:n] <= constants[:x2])
-@everywhere us_aut_F_l1l3_1!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(S.loc = :l3;
- S[:d] = 0;)
-
-@everywhere cc_aut_F_l1l3_2(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(S[:n] < constants[:x1] || S[:n] > constants[:x2]) && 
-(getfield(S, :time) <= constants[:t1])
-@everywhere us_aut_F_l1l3_2!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(S.loc = :l3;
- S[:d] = min(sqrt((getfield(S, :time) - constants[:t1])^2 + (S[:n] - constants[:x2])^2), 
-             sqrt((getfield(S, :time) - constants[:t1])^2 + (S[:n] - constants[:x1])^2)))
-
-@everywhere cc_aut_F_l1l3_3(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(S[:n] < constants[:x1] || S[:n] > constants[:x2]) && 
-(constants[:t1] <= getfield(S, :time) <= constants[:t2])
-@everywhere us_aut_F_l1l3_3!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(S.loc = :l3;
- S[:d] = min(S[:d], min(abs(S[:n] - constants[:x1]), abs(S[:n] - constants[:x2]))))
-
-# l3 loc
-# l3 => l1
-@everywhere cc_aut_F_l3l1_1(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = true
-
-# l3 => l2
-@everywhere cc_aut_F_l3l2_1(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(getfield(S, :time) >= constants[:t2])
-@everywhere us_aut_F_l3l2_1!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(S.loc = :l2)
-
 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."
@@ -81,6 +9,7 @@ function create_automaton_F(m::ContinuousTimeModel, x1::Float64, x2::Float64, t1
     locations = [:l0, :l1, :l2, :l3]
 
     ## Invariant predicates
+    @everywhere true_inv_predicate(x::Vector{Int}) = true 
     Λ_F = Dict(:l0 => getfield(Main, :true_inv_predicate), :l1 => getfield(Main, :true_inv_predicate),
                :l2 => getfield(Main, :true_inv_predicate), :l3 => getfield(Main, :true_inv_predicate))
     
@@ -106,53 +35,124 @@ function create_automaton_F(m::ContinuousTimeModel, x1::Float64, x2::Float64, t1
         map_edges[loc] = Dict{Location, Vector{Edge}}()
     end
     
-    sym_isabs_func = Symbol(m.isabsorbing)
     idx_obs_var = getfield(m, :map_var_idx)[sym_obs]
-    nbr_rand = rand(1:1000)
+    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)
+
+        ## 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::StateLHA, x::Vector{Int}, p::Vector{Float64}) = true
+        @everywhere $(func_name(:us, :l0, :l1, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (S.loc = :l1; 
+         getfield(S, :values)[$(idx_var_n)] = x[$(idx_obs_var)];
+         setindex!(getfield(S, :values), Inf, $(idx_var_d)); 
+         setindex!(getfield(S, :values), getfield(Main, $(Meta.quot(sym_isabs_func)))(p, x), $(idx_var_isabs)))
+
+        # l1 loc
+        # l1 => l2
+        @everywhere $(func_name(:cc, :l1, :l2, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        getfield(S, :time) >= $t1 &&
+        ($x1 <= getfield(S, :values)[$(idx_var_n)] <= $x2)
+        @everywhere $(func_name(:us, :l1, :l2, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (S.loc = :l2;
+         setindex!(getfield(S, :values), 0, $(idx_var_d)))
+
+        @everywhere $(func_name(:cc, :l1, :l2, 4))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        getfield(S, :time) >= $t1 &&
+        getfield(S, :values)[$(idx_var_d)] == 0 
+        @everywhere $(func_name(:us, :l1, :l2, 4))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (S.loc = :l2)
+
+        @everywhere $(func_name(:cc, :l1, :l2, 2))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (getfield(S, :time) >= $t2) && 
+        (getfield(S, :values)[$(idx_var_n)] < $x1 || getfield(S, :values)[$(idx_var_n)] > $x2)
+        @everywhere $(func_name(:us, :l1, :l2, 2))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (S.loc = :l2;
+         setindex!(getfield(S, :values), min(abs(getfield(S, :values)[$(idx_var_n)] - $x1), abs(getfield(S, :values)[$(idx_var_n)] - $x2)), $(idx_var_d)))
+
+        @everywhere $(func_name(:cc, :l1, :l2, 3))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        istrue(getfield(S, :values)[$(idx_var_isabs)]) && getfield(S, :time) <= $t2
+        @everywhere $(func_name(:us, :l1, :l2, 3))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (S.loc = :l2)
+
+        # l1 => l3
+        @everywhere $(func_name(:cc, :l1, :l3, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        ($x1 <= getfield(S, :values)[$(idx_var_n)] <= $x2)
+        @everywhere $(func_name(:us, :l1, :l3, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (S.loc = :l3;
+         setindex!(getfield(S, :values), 0, $(idx_var_d)))
+
+        @everywhere $(func_name(:cc, :l1, :l3, 2))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (getfield(S, :values)[$(idx_var_n)] < $x1 || getfield(S, :values)[$(idx_var_n)] > $x2) && 
+        (getfield(S, :time) <= $t1)
+        @everywhere $(func_name(:us, :l1, :l3, 2))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (S.loc = :l3;
+         setindex!(getfield(S, :values), min(sqrt((getfield(S, :time) - $t1)^2 + (getfield(S, :values)[$(idx_var_n)] - $x2)^2), 
+                                             sqrt((getfield(S, :time) - $t1)^2 + (getfield(S, :values)[$(idx_var_n)] - $x1)^2)), $(idx_var_d)))
+
+        @everywhere $(func_name(:cc, :l1, :l3, 3))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (getfield(S, :values)[$(idx_var_n)] < $x1 || getfield(S, :values)[$(idx_var_n)] > $x2) && 
+        ($t1 <= getfield(S, :time) <= $t2)
+        @everywhere $(func_name(:us, :l1, :l3, 3))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (S.loc = :l3;
+         val_min = min(getfield(S, :values)[$(idx_var_d)], 
+                       min(abs(getfield(S, :values)[$(idx_var_n)] - $x1), abs(getfield(S, :values)[$(idx_var_n)] - $x2)));
+         setindex!(getfield(S, :values), val_min, $(idx_var_d)))
+
+        # l3 loc
+        # l3 => l1
+        @everywhere $(func_name(:cc, :l3, :l1, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = true
+        @everywhere $(func_name(:us, :l3, :l1, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (S.loc = :l1;
+         getfield(S, :values)[$(idx_var_n)] = x[$(idx_obs_var)];
+         setindex!(getfield(S, :values), getfield(Main, $(Meta.quot(sym_isabs_func)))(p, x), $(idx_var_isabs)))
+
+        # l3 => l2
+        @everywhere $(func_name(:cc, :l3, :l2, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (getfield(S, :time) >= $t2)
+        @everywhere $(func_name(:us, :l3, :l2, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (S.loc = :l2)
+    end
+    eval(meta_elementary_functions)
 
     # l0 loc
     # l0 => l1
-    sym_func_us_l0l1_1 = Symbol("us_aut_F_$(basename_func)_l0l1_1!")
-    str_us_l0l1_1 = "
-    @everywhere $(sym_func_us_l0l1_1)(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = \n
-    (S.loc = :l1; \n
-     S[:n] = x[$(idx_obs_var)];\n
-     S[:d] = Inf; \n
-     S[:isabs] = getfield(Main, $(Meta.quot(sym_isabs_func)))(p, x))"
-    eval(Meta.parse(str_us_l0l1_1))
-    edge1 = Edge([nothing], getfield(Main, :cc_aut_F_l0l1_1), getfield(Main, sym_func_us_l0l1_1))
+    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, :cc_aut_F_l1l2_1), getfield(Main, :us_aut_F_l1l2_1!))
-    edge2 = Edge([nothing], getfield(Main, :cc_aut_F_l1l2_2), getfield(Main, :us_aut_F_l1l2_2!))
-    edge3 = Edge([nothing], getfield(Main, :cc_aut_F_l1l2_3), getfield(Main, :us_aut_F_l1l2_3!))
-    edge4 = Edge([nothing], getfield(Main, :cc_aut_F_l1l2_4), getfield(Main, :us_aut_F_l1l2_4!))
+    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)))
+    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, :cc_aut_F_l1l3_1), getfield(Main, :us_aut_F_l1l3_1!))
-    edge2 = Edge([nothing], getfield(Main, :cc_aut_F_l1l3_2), getfield(Main, :us_aut_F_l1l3_2!))
-    edge3 = Edge([nothing], getfield(Main, :cc_aut_F_l1l3_3), getfield(Main, :us_aut_F_l1l3_3!))
+    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
-    sym_func_us_l3l1_1 = Symbol("us_aut_F_$(basename_func)_l0l1_1!")
-    str_us_l3l1_1 = 
-    "@everywhere $(sym_func_us_l3l1_1)(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = \n
-    (S.loc = :l1;\n
-    S[:n] = x[$(idx_obs_var)];\n
-    S[:isabs] = getfield(Main, $(Meta.quot(sym_isabs_func)))(p, x))"
-    eval(Meta.parse(str_us_l3l1_1))
-    edge1 = Edge([:ALL], getfield(Main, :cc_aut_F_l3l1_1), getfield(Main, sym_func_us_l3l1_1))
+    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, :cc_aut_F_l3l2_1), getfield(Main, :us_aut_F_l3l2_1!))
+    edge1 = Edge([nothing], getfield(Main, func_name(:cc, :l3, :l2, 1)), getfield(Main, func_name(:us, :l3, :l2, 1)))
     map_edges[:l3][:l2] = [edge1]
 
     ## Constants
diff --git a/automata/automaton_G.jl b/automata/automaton_G.jl
index b07a4796d412caa34dcec7ca3c00cdfc1c350425..01efc47b7fd9f2164ee4e23674ce638b15911c5e 100644
--- a/automata/automaton_G.jl
+++ b/automata/automaton_G.jl
@@ -1,121 +1,4 @@
 
-@everywhere istrue(val::Float64) = convert(Bool, val)
-
-# Invariant predicate functions
-@everywhere true_inv_predicate(x::Vector{Int}) = true 
-
-# l0 loc
-# l0 => l1
-@everywhere cc_aut_G_l0l1_1(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = true
-
-# l1 => l3
-@everywhere cc_aut_G_l1l3_1(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-getfield(S, :time) <= constants[:t1] && 
-S[:n] < constants[:x1] || S[:n] > constants[:x2]
-@everywhere us_aut_G_l1l3_1!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(S.loc = :l3; 
- S[:d] = min(abs(constants[:x1] - S[:n]), abs(constants[:x2] - S[:n])); 
- S[:in] = false)
-
-@everywhere cc_aut_G_l1l3_2(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(getfield(S, :time) <= constants[:t1]) && 
-(constants[:x1] <= S[:n] <= constants[:x2])
-@everywhere us_aut_G_l1l3_2!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(S.loc = :l3; 
- S[:d] = 0; 
- S[:in] = false)
-
-@everywhere cc_aut_G_l1l3_3(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-!istrue(S[:in]) && 
-(constants[:t1] <= getfield(S, :time) <= constants[:t2]) && 
-(constants[:x1] <= S[:n] <= constants[:x2])
-@everywhere us_aut_G_l1l3_3!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(S.loc = :l3; 
- S[:d] = S[:d] * (getfield(S, :time) - constants[:t1]); 
- S[:tprime] = 0.0)
-
-@everywhere cc_aut_G_l1l3_4(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-istrue(S[:in]) && 
-(constants[:t1] <= getfield(S, :time) <= constants[:t2]) && 
-(constants[:x1] <= S[:n] <= constants[:x2])
-@everywhere us_aut_G_l1l3_4!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(S.loc = :l3; 
- S[:tprime] = 0.0)
-
-# l1 => l4
-@everywhere cc_aut_G_l1l4_1(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-!istrue(S[:in]) && 
-(constants[:t1] <= getfield(S, :time) <= constants[:t2]) && 
-(S[:n] < constants[:x1] || S[:n] > constants[:x2])
-@everywhere us_aut_G_l1l4_1!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(S.loc = :l4; 
- S[:d] += S[:d] * (getfield(S, :time) - constants[:t1]))
-
-@everywhere cc_aut_G_l1l4_2(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-istrue(S[:in]) && 
-(constants[:t1] <= getfield(S, :time) <= constants[:t2]) && 
-(S[:n] < constants[:x1] || S[:n] > constants[:x2])
-@everywhere us_aut_G_l1l4_2!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(S.loc = :l4)
-
-
-# l1 => l2
-@everywhere cc_aut_G_l1l2_1(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-istrue(S[:in]) && 
-getfield(S, :time) >= constants[:t2]
-@everywhere us_aut_G_l1l2_1!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(S.loc = :l2)
-
-@everywhere cc_aut_G_l1l2_2(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-!istrue(S[:in]) && 
-getfield(S, :time) >= constants[:t2]
-@everywhere us_aut_G_l1l2_2!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(S.loc = :l2; 
- S[:d] = S[:d] * (constants[:t2] - constants[:t1]))
-
-@everywhere cc_aut_G_l1l2_3(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-istrue(S[:isabs]) && 
-getfield(S, :time) <= constants[:t1]
-@everywhere us_aut_G_l1l2_3!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(S.loc = :l2; 
- S[:d] = (constants[:t2] - constants[:t1]) *
-min(abs(constants[:x1] - S[:n]), abs(constants[:x2] - S[:n])))
-
-@everywhere cc_aut_G_l1l2_4(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-istrue(S[:isabs]) && 
-(constants[:t1] <= getfield(S, :time) <= constants[:t2])
-@everywhere us_aut_G_l1l2_4!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(S.loc = :l2; 
- S[:d] += (constants[:t2] - getfield(S, :time)) * 
-min(abs(constants[:x1] - S[:n]), abs(constants[:x2] - S[:n])))
-
-# l3 => l1
-@everywhere cc_aut_G_l3l1_1(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = true
-
-# l4 => l1
-@everywhere cc_aut_G_l4l1_1(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = true
-
-# l2 => l1
-@everywhere cc_aut_G_l3l2_2(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-istrue(S[:in]) && 
-getfield(S, :time) >= constants[:t2]
-@everywhere us_aut_G_l3l2_2!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(S.loc = :l2;
- S[:d] = S[:d] * (constants[:t2] - constants[:t1]))
-
-@everywhere cc_aut_G_l3l2_1(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-!istrue(S[:in]) && 
-getfield(S, :time) >= constants[:t2]
-@everywhere us_aut_G_l3l2_1!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(S.loc = :l2)
-
-# l4 => l2
-@everywhere cc_aut_G_l4l2_1(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(getfield(S, :time) >= constants[:t2])
-@everywhere us_aut_G_l4l2_1!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(S.loc = :l2; 
- S[:d] +=  S[:tprime] * min(abs(constants[:x1] - S[:n]), abs(constants[:x2] - S[:n])); 
- S[:tprime] = 0.0)
 
 function create_automaton_G(m::ContinuousTimeModel, x1::Float64, x2::Float64, t1::Float64, t2::Float64, sym_obs::VariableModel)
     # Requirements for the automaton
@@ -127,6 +10,7 @@ function create_automaton_G(m::ContinuousTimeModel, x1::Float64, x2::Float64, t1
     locations = [:l0, :l1, :l2, :l3, :l4]
 
     # Invariant predicates
+    @everywhere true_inv_predicate(x::Vector{Int}) = true 
     Λ_F = Dict(:l0 => getfield(Main, :true_inv_predicate), :l1 => getfield(Main, :true_inv_predicate),
                :l2 => getfield(Main, :true_inv_predicate), :l3 => getfield(Main, :true_inv_predicate), 
                :l4 => getfield(Main, :true_inv_predicate))
@@ -152,80 +36,193 @@ function create_automaton_G(m::ContinuousTimeModel, x1::Float64, x2::Float64, t1
         map_edges[loc] = Dict{Location, Vector{Edge}}()
     end
 
-    sym_isabs_func = Symbol(m.isabsorbing)
     idx_obs_var = getfield(m, :map_var_idx)[sym_obs]
-    nbr_rand = rand(1:1000)
+    idx_var_n = map_var_automaton_idx[:n] 
+    idx_var_d = map_var_automaton_idx[:d] 
+    idx_var_isabs = map_var_automaton_idx[:isabs] 
+    idx_var_in = map_var_automaton_idx[:in] 
+    idx_var_tprime = map_var_automaton_idx[:tprime]
+
+    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_G_$(basename_func)_$(from_loc)$(to_loc)_$(edge_number)$(type_func == :us ? "!" : "")")
+    meta_elementary_functions = quote
+        @everywhere istrue(val::Float64) = convert(Bool, val)
+        # l0 loc
+        # l0 => l1
+        @everywhere $(func_name(:cc, :l0, :l1, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = true
+        @everywhere $(func_name(:us, :l0, :l1, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (setfield!(S, :loc, Symbol("l1")); 
+         setindex!(getfield(S, :values), 0, $(idx_var_d));
+         setindex!(getfield(S, :values), x[$(idx_obs_var)], $(idx_var_n));
+         setindex!(getfield(S, :values), true, $(idx_var_in));
+         setindex!(getfield(S, :values), getfield(Main, $(Meta.quot(sym_isabs_func)))(p, x), $(idx_var_isabs)))
+
+        # l1 => l3
+        @everywhere $(func_name(:cc, :l1, :l3, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        getfield(S, :time) <= $t1 && 
+        getfield(S, :values)[$(idx_var_n)] < $x1 || getfield(S, :values)[$(idx_var_n)] > $x2
+        @everywhere $(func_name(:us, :l1, :l3, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (setfield!(S, :loc, Symbol("l3")); 
+         setindex!(getfield(S, :values), min(abs($x1 - getfield(S, :values)[$(idx_var_n)]), abs($x2 - getfield(S, :values)[$(idx_var_n)])), $(idx_var_d));
+         setindex!(getfield(S, :values), false, $(idx_var_in)))
+
+        @everywhere $(func_name(:cc, :l1, :l3, 2))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (getfield(S, :time) <= $t1) && 
+        ($x1 <= getfield(S, :values)[$(idx_var_n)] <= $x2)
+        @everywhere $(func_name(:us, :l1, :l3, 2))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (setfield!(S, :loc, Symbol("l3")); 
+         setindex!(getfield(S, :values), 0, $(idx_var_d));
+         setindex!(getfield(S, :values), false, $(idx_var_in)))
+
+        @everywhere $(func_name(:cc, :l1, :l3, 3))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        !istrue(getfield(S, :values)[$(idx_var_in)]) && 
+        ($t1 <= getfield(S, :time) <= $t2) && 
+        ($x1 <= getfield(S, :values)[$(idx_var_n)] <= $x2)
+        @everywhere $(func_name(:us, :l1, :l3, 3))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (setfield!(S, :loc, Symbol("l3")); 
+         setindex!(getfield(S, :values), getfield(S, :values)[$(idx_var_d)] * (getfield(S, :time) - $t1), $(idx_var_d));
+         setindex!(getfield(S, :values), 0.0, $(idx_var_tprime)))
+
+        @everywhere $(func_name(:cc, :l1, :l3, 4))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        istrue(getfield(S, :values)[$(idx_var_in)]) && 
+        ($t1 <= getfield(S, :time) <= $t2) && 
+        ($x1 <= getfield(S, :values)[$(idx_var_n)] <= $x2)
+        @everywhere $(func_name(:us, :l1, :l3, 4))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (setfield!(S, :loc, Symbol("l3")); 
+         setindex!(getfield(S, :values), 0.0, $(idx_var_tprime)))
+
+        # l1 => l4
+        @everywhere $(func_name(:cc, :l1, :l4, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        !istrue(getfield(S, :values)[$(idx_var_in)]) && 
+        ($t1 <= getfield(S, :time) <= $t2) && 
+        (getfield(S, :values)[$(idx_var_n)] < $x1 || getfield(S, :values)[$(idx_var_n)] > $x2)
+        @everywhere $(func_name(:us, :l1, :l4, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (setfield!(S, :loc, Symbol("l4")); 
+         setindex!(getfield(S, :values), getfield(S, :values)[$(idx_var_d)] + getfield(S, :values)[$(idx_var_d)] * (getfield(S, :time) - $t1), $(idx_var_d)))
+
+        @everywhere $(func_name(:cc, :l1, :l4, 2))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        istrue(getfield(S, :values)[$(idx_var_in)]) && 
+        ($t1 <= getfield(S, :time) <= $t2) && 
+        (getfield(S, :values)[$(idx_var_n)] < $x1 || getfield(S, :values)[$(idx_var_n)] > $x2)
+        @everywhere $(func_name(:us, :l1, :l4, 2))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (setfield!(S, :loc, Symbol("l4")))
+
+
+        # l1 => l2
+        @everywhere $(func_name(:cc, :l1, :l2, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        istrue(getfield(S, :values)[$(idx_var_in)]) && 
+        getfield(S, :time) >= $t2
+        @everywhere $(func_name(:us, :l1, :l2, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (setfield!(S, :loc, Symbol("l2")))
+
+        @everywhere $(func_name(:cc, :l1, :l2, 2))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        !istrue(getfield(S, :values)[$(idx_var_in)]) && 
+        getfield(S, :time) >= $t2
+        @everywhere $(func_name(:us, :l1, :l2, 2))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (setfield!(S, :loc, Symbol("l2")); 
+         setindex!(getfield(S, :values), getfield(S, :values)[$(idx_var_d)] * ($t2 - $t1), $(idx_var_d)))
+
+        @everywhere $(func_name(:cc, :l1, :l2, 3))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        istrue(getfield(S, :values)[$(idx_var_isabs)]) && 
+        getfield(S, :time) <= $t1
+        @everywhere $(func_name(:us, :l1, :l2, 3))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (setfield!(S, :loc, Symbol("l2")); 
+         setindex!(getfield(S, :values), ($t2 - $t1) * min(abs($x1 - getfield(S, :values)[$(idx_var_n)]), abs($x2 - getfield(S, :values)[$(idx_var_n)])), $(idx_var_d)))
+
+        @everywhere $(func_name(:cc, :l1, :l2, 4))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        istrue(getfield(S, :values)[$(idx_var_isabs)]) && 
+        ($t1 <= getfield(S, :time) <= $t2)
+        @everywhere $(func_name(:us, :l1, :l2, 4))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (setfield!(S, :loc, Symbol("l2")); 
+         setindex!(getfield(S, :values), getfield(S, :values)[$(idx_var_d)] + ($t2 - getfield(S, :time)) * min(abs($x1 - getfield(S, :values)[$(idx_var_n)]), abs($x2 - getfield(S, :values)[$(idx_var_n)])), $(idx_var_d)))
+
+        # l3 => l1
+        @everywhere $(func_name(:cc, :l3, :l1, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = true
+        @everywhere $(func_name(:us, :l3, :l1, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (setfield!(S, :loc, Symbol("l1")); 
+         setindex!(getfield(S, :values), x[$(idx_obs_var)], $(idx_var_n));
+         setindex!(getfield(S, :values), getfield(Main, $(Meta.quot(sym_isabs_func)))(p, x), $(idx_var_isabs)))
+
+        # l4 => l1
+        @everywhere $(func_name(:cc, :l4, :l1, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = true
+        @everywhere $(func_name(:us, :l4, :l1, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (setfield!(S, :loc, Symbol("l1")); 
+         setindex!(getfield(S, :values), getfield(S, :values)[$(idx_var_d)] + getfield(S, :values)[$(idx_var_tprime)] * min(abs($x1 - getfield(S, :values)[$(idx_var_n)]), abs($x2 - getfield(S, :values)[$(idx_var_n)])), $(idx_var_d));
+         setindex!(getfield(S, :values), 0.0, $(idx_var_tprime));
+         setindex!(getfield(S, :values), x[$(idx_obs_var)], $(idx_var_n));
+         setindex!(getfield(S, :values), true, $(idx_var_in));
+         setindex!(getfield(S, :values), getfield(Main, $(Meta.quot(sym_isabs_func)))(p, x), $(idx_var_isabs)))
+
+        # l2 => l1
+        @everywhere $(func_name(:cc, :l3, :l2, 2))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        istrue(getfield(S, :values)[$(idx_var_in)]) && 
+        getfield(S, :time) >= $t2
+        @everywhere $(func_name(:us, :l3, :l2, 2))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (setfield!(S, :loc, Symbol("l2"));
+         setindex!(getfield(S, :values), getfield(S, :values)[$(idx_var_d)] * ($t2 - $t1), $(idx_var_d)))
+
+        @everywhere $(func_name(:cc, :l3, :l2, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        !istrue(getfield(S, :values)[$(idx_var_in)]) && 
+        getfield(S, :time) >= $t2
+        @everywhere $(func_name(:us, :l3, :l2, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (setfield!(S, :loc, Symbol("l2")))
+
+        # l4 => l2
+        @everywhere $(func_name(:cc, :l4, :l2, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (getfield(S, :time) >= $t2)
+        @everywhere $(func_name(:us, :l4, :l2, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (setfield!(S, :loc, Symbol("l2")); 
+         setindex!(getfield(S, :values), getfield(S, :values)[$(idx_var_d)] + getfield(S, :values)[$(idx_var_tprime)] * min(abs($x1 - getfield(S, :values)[$(idx_var_n)]), abs($x2 - getfield(S, :values)[$(idx_var_n)])), $(idx_var_d));
+         setindex!(getfield(S, :values), 0.0, $(idx_var_tprime)))
+    end
+    eval(meta_elementary_functions)
 
     # l0 loc
     # l0 => l1
-    sym_func_us_l0l1_1 = Symbol("us_aut_G_$(basename_func)_l0l1_1!")
-    str_us_l0l1_1 = "
-    @everywhere $(sym_func_us_l0l1_1)(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = \n
-    (S.loc = :l1; \n
-    S[:d] = 0; \n
-    S[:n] = x[$(idx_obs_var)]; \n
-    S[:in] = true; \n
-    S[:isabs] = getfield(Main, $(Meta.quot(sym_isabs_func)))(p, x))"
-    eval(Meta.parse(str_us_l0l1_1))
-    edge1 = Edge([nothing], getfield(Main, :cc_aut_G_l0l1_1), getfield(Main, sym_func_us_l0l1_1))
+    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 => l3
-    edge1 = Edge([nothing], getfield(Main, :cc_aut_G_l1l3_1), getfield(Main, :us_aut_G_l1l3_1!))
-    edge2 = Edge([nothing], getfield(Main, :cc_aut_G_l1l3_2), getfield(Main, :us_aut_G_l1l3_2!))
-    edge3 = Edge([nothing], getfield(Main, :cc_aut_G_l1l3_3), getfield(Main, :us_aut_G_l1l3_3!))
-    edge4 = Edge([nothing], getfield(Main, :cc_aut_G_l1l3_4), getfield(Main, :us_aut_G_l1l3_4!))
+    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)))
+    edge4 = Edge([nothing], getfield(Main, func_name(:cc, :l1, :l3, 4)), getfield(Main, func_name(:us, :l1, :l3, 4)))
     map_edges[:l1][:l3] = [edge1, edge2, edge3, edge4]
 
     # l1 => l4
-    edge1 = Edge([nothing], getfield(Main, :cc_aut_G_l1l4_1), getfield(Main, :us_aut_G_l1l4_1!))
-    edge2 = Edge([nothing], getfield(Main, :cc_aut_G_l1l4_2), getfield(Main, :us_aut_G_l1l4_2!))
+    edge1 = Edge([nothing], getfield(Main, func_name(:cc, :l1, :l4, 1)), getfield(Main, func_name(:us, :l1, :l4, 1)))
+    edge2 = Edge([nothing], getfield(Main, func_name(:cc, :l1, :l4, 2)), getfield(Main, func_name(:us, :l1, :l4, 2)))
     map_edges[:l1][:l4] = [edge1, edge2]
    
     # l1 => l2
-    edge1 = Edge([nothing], getfield(Main, :cc_aut_G_l1l2_1), getfield(Main, :us_aut_G_l1l2_1!))
-    edge2 = Edge([nothing], getfield(Main, :cc_aut_G_l1l2_2), getfield(Main, :us_aut_G_l1l2_2!))
-    edge3 = Edge([nothing], getfield(Main, :cc_aut_G_l1l2_3), getfield(Main, :us_aut_G_l1l2_3!))
-    edge4 = Edge([nothing], getfield(Main, :cc_aut_G_l1l2_4), getfield(Main, :us_aut_G_l1l2_4!))
+    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)))
+    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]
 
     # l3 loc
     # l3 => l1
-    sym_func_us_l3l1_1 = Symbol("us_aut_G_$(basename_func)_l3l1_1!")
-    str_us_l3l1_1 = "
-    @everywhere $(sym_func_us_l3l1_1)(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-    (S.loc = :l1; 
-    S[:n] = x[$(idx_obs_var)]; 
-    S[:isabs] = getfield(Main, $(Meta.quot(sym_isabs_func)))(p, x))"
-    eval(Meta.parse(str_us_l3l1_1))
-    edge1 = Edge([:ALL], getfield(Main, :cc_aut_G_l3l1_1), getfield(Main, sym_func_us_l3l1_1))
+    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, :cc_aut_G_l3l2_1), getfield(Main, :us_aut_G_l3l2_1!))
-    edge2 = Edge([nothing], getfield(Main, :cc_aut_G_l3l2_2), getfield(Main, :us_aut_G_l3l2_2!))
+    edge1 = Edge([nothing], getfield(Main, func_name(:cc, :l3, :l2, 1)), getfield(Main, func_name(:us, :l3, :l2, 1)))
+    edge2 = Edge([nothing], getfield(Main, func_name(:cc, :l3, :l2, 2)), getfield(Main, func_name(:us, :l3, :l2, 2)))
     map_edges[:l3][:l2] = [edge1, edge2]
 
     # l4 loc
     # l4 => l1
-    sym_func_us_l4l1_1 = Symbol("us_aut_G_$(basename_func)_l4l1_1!")
-    str_us_l4l1_1 = "
-    @everywhere $(sym_func_us_l4l1_1)(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = \n
-    (S.loc = :l1; \n
-    S[:d] += S[:tprime] * min(abs(constants[:x1] - S[:n]), abs(constants[:x2] - S[:n])); \n
-    S[:tprime] = 0.0; \n
-    S[:n] = x[$(idx_obs_var)]; \n
-    S[:in] = true; \n
-    S[:isabs] = getfield(Main, $(Meta.quot(sym_isabs_func)))(p, x))"
-    eval(Meta.parse(str_us_l4l1_1))
-    edge1 = Edge([:ALL], getfield(Main, :cc_aut_G_l4l1_1), getfield(Main, sym_func_us_l4l1_1))
+    edge1 = Edge([:ALL], getfield(Main, func_name(:cc, :l4, :l1, 1)), getfield(Main, func_name(:us, :l4, :l1, 1)))
     map_edges[:l4][:l1] = [edge1]
 
     # l4 => l2
-    edge1 = Edge([nothing], getfield(Main, :cc_aut_G_l4l2_1), getfield(Main, :us_aut_G_l4l2_1!))
+    edge1 = Edge([nothing], getfield(Main, func_name(:cc, :l4, :l2, 1)), getfield(Main, func_name(:us, :l4, :l2, 1)))
     map_edges[:l4][:l2] = [edge1]
 
     ## Constants
diff --git a/automata/automaton_G_and_F.jl b/automata/automaton_G_and_F.jl
index bd42caf86f795844d685c220aec5f46367fe5259..1bfd93ef3dc5a2bfa7ffa57f3c7f8b9f7fbe51dc 100644
--- a/automata/automaton_G_and_F.jl
+++ b/automata/automaton_G_and_F.jl
@@ -1,191 +1,4 @@
 
-@everywhere istrue(val::Float64) = convert(Bool, val)
-
-## Invariant predicate functions
-
-@everywhere true_inv_predicate(x::Vector{Int}) = true 
-
-## Edges check constraint and update state functions
-
-# l0G loc
-# l0G => l1G
-@everywhere cc_aut_G_l0Gl1G_1(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = true
-
-# l1G loc
-# l1G => l3G
-@everywhere cc_aut_G_l1Gl3G_1(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-getfield(S, :time) <= constants[:t1] && 
-S[:n] < constants[:x1] || S[:n] > constants[:x2]
-@everywhere us_aut_G_l1Gl3G_1!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(S.loc = :l3G; 
- S[:d] = min(abs(constants[:x1] - S[:n]), abs(constants[:x2] - S[:n])); 
- S[:in] = false)
-
-@everywhere cc_aut_G_l1Gl3G_2(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(getfield(S, :time) <= constants[:t1]) && 
-(constants[:x1] <= S[:n] <= constants[:x2])
-@everywhere us_aut_G_l1Gl3G_2!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(S.loc = :l3G; 
- S[:d] = 0; 
- S[:in] = false)
-
-@everywhere cc_aut_G_l1Gl3G_3(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-!istrue(S[:in]) && 
-(constants[:t1] <= getfield(S, :time) <= constants[:t2]) && 
-(constants[:x1] <= S[:n] <= constants[:x2])
-@everywhere us_aut_G_l1Gl3G_3!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(S.loc = :l3G; 
- S[:d] = S[:d] * (getfield(S, :time) - constants[:t1]); 
- S[:tprime] = 0.0)
-
-@everywhere cc_aut_G_l1Gl3G_4(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-istrue(S[:in]) && 
-(constants[:t1] <= getfield(S, :time) <= constants[:t2]) && 
-(constants[:x1] <= S[:n] <= constants[:x2])
-@everywhere us_aut_G_l1Gl3G_4!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(S.loc = :l3G; 
- S[:tprime] = 0.0)
-
-# l1G => l4G
-@everywhere cc_aut_G_l1Gl4G_1(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-!istrue(S[:in]) && 
-(constants[:t1] <= getfield(S, :time) <= constants[:t2]) && 
-(S[:n] < constants[:x1] || S[:n] > constants[:x2])
-@everywhere us_aut_G_l1Gl4G_1!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(S.loc = :l4G; 
- S[:d] += S[:d] * (getfield(S, :time) - constants[:t1]))
-
-@everywhere cc_aut_G_l1Gl4G_2(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-istrue(S[:in]) && 
-(constants[:t1] <= getfield(S, :time) <= constants[:t2]) && 
-(S[:n] < constants[:x1] || S[:n] > constants[:x2])
-@everywhere us_aut_G_l1Gl4G_2!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(S.loc = :l4G)
-
-# l1G => l2G
-@everywhere cc_aut_G_l1Gl2G_3(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-istrue(S[:isabs]) && 
-getfield(S, :time) <= constants[:t1]
-@everywhere us_aut_G_l1Gl2G_3!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(S.loc = :l2G; 
- S[:d] = (constants[:t2] - constants[:t1]) *
- min(abs(constants[:x1] - S[:n]), abs(constants[:x2] - S[:n])))
-
-@everywhere cc_aut_G_l1Gl2G_4(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-istrue(S[:isabs]) && 
-(constants[:t1] <= getfield(S, :time) <= constants[:t2])
-@everywhere us_aut_G_l1Gl2G_4!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(S.loc = :l2G; 
- S[:d] += (constants[:t2] - getfield(S, :time)) * 
- min(abs(constants[:x1] - S[:n]), abs(constants[:x2] - S[:n])))
-
-@everywhere cc_aut_G_l1Gl2G_1(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-istrue(S[:in]) && 
-getfield(S, :time) >= constants[:t2]
-@everywhere us_aut_G_l1Gl2G_1!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(S.loc = :l2G)
-
-@everywhere cc_aut_G_l1Gl2G_2(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-!istrue(S[:in]) && 
-getfield(S, :time) >= constants[:t2]
-@everywhere us_aut_G_l1Gl2G_2!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(S.loc = :l2G; 
- S[:d] = S[:d] * (constants[:t2] - constants[:t1]))
-
-# l3G loc
-# l3G => l1G
-@everywhere cc_aut_G_l3Gl1G_1(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = true
-
-# l3G => l2G
-@everywhere cc_aut_G_l3Gl2G_2(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-istrue(S[:in]) && 
-getfield(S, :time) >= constants[:t2]
-@everywhere us_aut_G_l3Gl2G_2!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(S.loc = :l2G;
- S[:d] = S[:d] * (constants[:t2] - constants[:t1]))
-
-@everywhere cc_aut_G_l3Gl2G_1(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-!istrue(S[:in]) && 
-getfield(S, :time) >= constants[:t2]
-@everywhere us_aut_G_l3Gl2G_1!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(S.loc = :l2G)
-
-# l4G loc
-# l4G => l1G
-@everywhere cc_aut_G_l4Gl1G_1(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = true
-
-# l4G => l2G
-@everywhere cc_aut_G_l4Gl2G_1(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(getfield(S, :time) >= constants[:t2])
-@everywhere us_aut_G_l4Gl2G_1!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(S.loc = :l2G; 
- S[:d] +=  S[:tprime] * min(abs(constants[:x1] - S[:n]), abs(constants[:x2] - S[:n])); 
- S[:tprime] = 0.0)
-
-# Connection between the two automata: l2G => l1F
-@everywhere cc_aut_F_l2Gl1F_1(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = true
-
-# l1F loc : we construct  the edges of the form l1F => (..)
-# l1F => l2F
-@everywhere cc_aut_F_l1Fl2F_1(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-getfield(S, :time) >= constants[:t3] &&
-(constants[:x3] <= S[:n] <= constants[:x4])
-@everywhere us_aut_F_l1Fl2F_1!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(S.loc = :l2F;
- S[:dprime] = 0)
-
-@everywhere cc_aut_F_l1Fl2F_4(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-getfield(S, :time) >= constants[:t3] &&
-S[:dprime] == 0 
-@everywhere us_aut_F_l1Fl2F_4!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(S.loc = :l2F)
-
-@everywhere cc_aut_F_l1Fl2F_2(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(getfield(S, :time) >= constants[:t4]) && 
-(S[:n] < constants[:x3] || S[:n] > constants[:x4])
-@everywhere us_aut_F_l1Fl2F_2!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(S.loc = :l2F;
- S[:dprime] = min(abs(S[:n] - constants[:x3]), abs(S[:n] - constants[:x4]));
- S[:d] += S[:dprime])
-
-@everywhere cc_aut_F_l1Fl2F_3(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-istrue(S[:isabs]) && getfield(S, :time) <= constants[:t4]
-@everywhere us_aut_F_l1Fl2F_3!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(S.loc = :l2F;
- S[:d] += S[:dprime])
-
-# l1F => l3F
-@everywhere cc_aut_F_l1Fl3F_1(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(constants[:x3] <= S[:n] <= constants[:x4])
-@everywhere us_aut_F_l1Fl3F_1!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(S.loc = :l3F;
- S[:dprime] = 0;)
-
-@everywhere cc_aut_F_l1Fl3F_2(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(S[:n] < constants[:x3] || S[:n] > constants[:x4]) && 
-(getfield(S, :time) <= constants[:t3])
-@everywhere us_aut_F_l1Fl3F_2!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(S.loc = :l3F;
- S[:dprime] = min(sqrt((getfield(S, :time) - constants[:t3])^2 + (S[:n] - constants[:x4])^2), 
-                  sqrt((getfield(S, :time) - constants[:t3])^2 + (S[:n] - constants[:x3])^2)))
-
-@everywhere cc_aut_F_l1Fl3F_3(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(S[:n] < constants[:x3] || S[:n] > constants[:x4]) && 
-(constants[:t3] <= getfield(S, :time) <= constants[:t4])
-@everywhere us_aut_F_l1Fl3F_3!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(S.loc = :l3F;
- S[:dprime] = min(S[:dprime], min(abs(S[:n] - constants[:x3]), abs(S[:n] - constants[:x4]))))
-
-# l3F loc
-# l3F => l1F
-@everywhere cc_aut_F_l3Fl1F_1(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = true
-
-# l3F => l2F
-@everywhere cc_aut_F_l3Fl2F_1(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(getfield(S, :time) >= constants[:t4])
-@everywhere us_aut_F_l3Fl2F_1!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(S.loc = :l2F)
-
 function create_automaton_G_and_F(m::ContinuousTimeModel, x1::Float64, x2::Float64, t1::Float64, t2::Float64, sym_obs_G::VariableModel,
                                   x3::Float64, x4::Float64, t3::Float64, t4::Float64, sym_obs_F::VariableModel)
     # Requirements for the automaton
@@ -195,12 +8,13 @@ function create_automaton_G_and_F(m::ContinuousTimeModel, x1::Float64, x2::Float
     @assert (x3 <= x4) "x3 > x3 impossible for G and F automaton."
     @assert (t3 <= t4) "t3 > t4 impossible for G and F automaton."
     @assert (t2 <= t3) "t3 > t2 impossible for G and F automaton."
-    
+
     # Locations
     locations = [:l0G, :l1G, :l2G, :l3G, :l4G,
                  :l1F, :l2F, :l3F]
 
     # Invariant predicates
+    @everywhere true_inv_predicate(x::Vector{Int}) = true 
     Λ_F = Dict(:l0G => getfield(Main, :true_inv_predicate), :l1G => getfield(Main, :true_inv_predicate),
                :l2G => getfield(Main, :true_inv_predicate), :l3G => getfield(Main, :true_inv_predicate), 
                :l4G => getfield(Main, :true_inv_predicate),
@@ -232,123 +46,299 @@ function create_automaton_G_and_F(m::ContinuousTimeModel, x1::Float64, x2::Float
         map_edges[loc] = Dict{Location, Vector{Edge}}()
     end
 
-    sym_isabs_func = Symbol(m.isabsorbing)
     idx_obs_var_F = getfield(m, :map_var_idx)[sym_obs_F]
     idx_obs_var_G = getfield(m, :map_var_idx)[sym_obs_G]
+    idx_var_n = map_var_automaton_idx[:n] 
+    idx_var_d = map_var_automaton_idx[:d] 
+    idx_var_dprime = map_var_automaton_idx[:dprime] 
+    idx_var_isabs = map_var_automaton_idx[:isabs] 
+    idx_var_in = map_var_automaton_idx[:in] 
+    idx_var_tprime = map_var_automaton_idx[:tprime]
+    
     nbr_rand = rand(1:1000)
     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)
+        ## Edges check constraint and update state functions
+
+        # l0G loc
+        # l0G => l1G
+        @everywhere $(func_name(:cc, :l0G, :l1G, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = true
+        @everywhere $(func_name(:us, :l0G, :l1G, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (setfield!(S, :loc, Symbol("l1G")); 
+         setindex!(getfield(S, :values), 0, $(idx_var_d));
+         setindex!(getfield(S, :values), x[$(idx_obs_var_G)], $(idx_var_n)); 
+         setindex!(getfield(S, :values), true, $(idx_var_in));
+         setindex!(getfield(S, :values), getfield(Main, $(Meta.quot(sym_isabs_func)))(p, x), $(idx_var_isabs)))
+
+        # l1G loc
+        # l1G => l3G
+        @everywhere $(func_name(:cc, :l1G, :l3G, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        getfield(S, :time) <= $t1 && 
+        getfield(S, :values)[$(idx_var_n)] < $x1 || getfield(S, :values)[$(idx_var_n)] > $x2
+        @everywhere $(func_name(:us, :l1G, :l3G, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (setfield!(S, :loc, Symbol("l3G")); 
+         setindex!(getfield(S, :values), min(abs($x1 - getfield(S, :values)[$(idx_var_n)]), abs($x2 - getfield(S, :values)[$(idx_var_n)])), $(idx_var_d)); 
+         setindex!(getfield(S, :values), false, $(idx_var_in)))
+
+        @everywhere $(func_name(:cc, :l1G, :l3G, 2))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (getfield(S, :time) <= $t1) && 
+        ($x1 <= getfield(S, :values)[$(idx_var_n)] <= $x2)
+        @everywhere $(func_name(:us, :l1G, :l3G, 2))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (setfield!(S, :loc, Symbol("l3G")); 
+         setindex!(getfield(S, :values), 0, $(idx_var_d));
+         setindex!(getfield(S, :values), false, $(idx_var_in)))
+
+        @everywhere $(func_name(:cc, :l1G, :l3G, 3))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        !istrue(getfield(S, :values)[$(idx_var_in)]) && 
+        ($t1 <= getfield(S, :time) <= $t2) && 
+        ($x1 <= getfield(S, :values)[$(idx_var_n)] <= $x2)
+        @everywhere $(func_name(:us, :l1G, :l3G, 3))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (setfield!(S, :loc, Symbol("l3G")); 
+         setindex!(getfield(S, :values), getfield(S, :values)[$(idx_var_d)] * (getfield(S, :time) - $t1), $(idx_var_d)); 
+         setindex!(getfield(S, :values), 0.0, $(idx_var_tprime)))
+
+        @everywhere $(func_name(:cc, :l1G, :l3G, 4))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        istrue(getfield(S, :values)[$(idx_var_in)]) && 
+        ($t1 <= getfield(S, :time) <= $t2) && 
+        ($x1 <= getfield(S, :values)[$(idx_var_n)] <= $x2)
+        @everywhere $(func_name(:us, :l1G, :l3G, 4))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (setfield!(S, :loc, Symbol("l3G")); 
+         setindex!(getfield(S, :values), 0.0, $(idx_var_tprime)))
+
+        # l1G => l4G
+        @everywhere $(func_name(:cc, :l1G, :l4G, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        !istrue(getfield(S, :values)[$(idx_var_in)]) && 
+        ($t1 <= getfield(S, :time) <= $t2) && 
+        (getfield(S, :values)[$(idx_var_n)] < $x1 || getfield(S, :values)[$(idx_var_n)] > $x2)
+        @everywhere $(func_name(:us, :l1G, :l4G, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (setfield!(S, :loc, Symbol("l4G")); 
+         setindex!(getfield(S, :values), getfield(S, :values)[$(idx_var_d)] + getfield(S, :values)[$(idx_var_d)] * (getfield(S, :time) - $t1), $(idx_var_d)))
+
+        @everywhere $(func_name(:cc, :l1G, :l4G, 2))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        istrue(getfield(S, :values)[$(idx_var_in)]) && 
+        ($t1 <= getfield(S, :time) <= $t2) && 
+        (getfield(S, :values)[$(idx_var_n)] < $x1 || getfield(S, :values)[$(idx_var_n)] > $x2)
+        @everywhere $(func_name(:us, :l1G, :l4G, 2))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (setfield!(S, :loc, Symbol("l4G")))
+
+        # l1G => l2G
+        @everywhere $(func_name(:cc, :l1G, :l2G, 3))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        istrue(getfield(S, :values)[$(idx_var_isabs)]) && 
+        getfield(S, :time) <= $t1
+        @everywhere $(func_name(:us, :l1G, :l2G, 3))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (setfield!(S, :loc, Symbol("l2G")); 
+         setindex!(getfield(S, :values), ($t2 - $t1) * min(abs($x1 - getfield(S, :values)[$(idx_var_n)]), abs($x2 - getfield(S, :values)[$(idx_var_n)])), $(idx_var_d)))
+
+        @everywhere $(func_name(:cc, :l1G, :l2G, 4))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        istrue(getfield(S, :values)[$(idx_var_isabs)]) && 
+        ($t1 <= getfield(S, :time) <= $t2)
+        @everywhere $(func_name(:us, :l1G, :l2G, 4))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (setfield!(S, :loc, Symbol("l2G")); 
+         setindex!(getfield(S, :values), getfield(S, :values)[$(idx_var_d)] + ($t2 - getfield(S, :time)) * min(abs($x1 - getfield(S, :values)[$(idx_var_n)]), abs($x2 - getfield(S, :values)[$(idx_var_n)])), $(idx_var_d)))
+
+        @everywhere $(func_name(:cc, :l1G, :l2G, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        istrue(getfield(S, :values)[$(idx_var_in)]) && 
+        getfield(S, :time) >= $t2
+        @everywhere $(func_name(:us, :l1G, :l2G, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (setfield!(S, :loc, Symbol("l2G")))
+
+        @everywhere $(func_name(:cc, :l1G, :l2G, 2))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        !istrue(getfield(S, :values)[$(idx_var_in)]) && 
+        getfield(S, :time) >= $t2
+        @everywhere $(func_name(:us, :l1G, :l2G, 2))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (setfield!(S, :loc, Symbol("l2G")); 
+         setindex!(getfield(S, :values), getfield(S, :values)[$(idx_var_d)] * ($t2 - $t1), $(idx_var_d)))
+
+        # l3G loc
+        # l3G => l1G
+        @everywhere $(func_name(:cc, :l3G, :l1G, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = true
+        @everywhere $(func_name(:us, :l3G, :l1G, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (setfield!(S, :loc, Symbol("l1G")); 
+         setindex!(getfield(S, :values), x[$(idx_obs_var_G)], $(idx_var_n)); 
+         setindex!(getfield(S, :values), getfield(Main, $(Meta.quot(sym_isabs_func)))(p, x), $(idx_var_isabs)))
+
+        # l3G => l2G
+        @everywhere $(func_name(:cc, :l3G, :l2G, 2))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        istrue(getfield(S, :values)[$(idx_var_in)]) && 
+        getfield(S, :time) >= $t2
+        @everywhere $(func_name(:us, :l3G, :l2G, 2))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (setfield!(S, :loc, Symbol("l2G"));
+         setindex!(getfield(S, :values), getfield(S, :values)[$(idx_var_d)] * ($t2 - $t1), $(idx_var_d)))
+
+        @everywhere $(func_name(:cc, :l3G, :l2G, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        !istrue(getfield(S, :values)[$(idx_var_in)]) && 
+        getfield(S, :time) >= $t2
+        @everywhere $(func_name(:us, :l3G, :l2G, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (setfield!(S, :loc, Symbol("l2G")))
+
+        # l4G loc
+        # l4G => l1G
+        @everywhere $(func_name(:cc, :l4G, :l1G, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = true
+        @everywhere $(func_name(:us, :l4G, :l1G, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (setfield!(S, :loc, Symbol("l1G")); 
+         setindex!(getfield(S, :values), getfield(S, :values)[$(idx_var_d)] + getfield(S, :values)[$(idx_var_tprime)] * min(abs($x1 - getfield(S, :values)[$(idx_var_n)]), abs($x2 - getfield(S, :values)[$(idx_var_n)])), $(idx_var_d)); 
+         setindex!(getfield(S, :values), 0.0, $(idx_var_tprime));
+         setindex!(getfield(S, :values), x[$(idx_obs_var_G)], $(idx_var_n)); 
+         setindex!(getfield(S, :values), true, $(idx_var_in));
+         setindex!(getfield(S, :values), getfield(Main, $(Meta.quot(sym_isabs_func)))(p, x), $(idx_var_isabs)))
+
+        # l4G => l2G
+        @everywhere $(func_name(:cc, :l4G, :l2G, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (getfield(S, :time) >= $t2)
+        @everywhere $(func_name(:us, :l4G, :l2G, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (setfield!(S, :loc, Symbol("l2G")); 
+         setindex!(getfield(S, :values), getfield(S, :values)[$(idx_var_d)] +  getfield(S, :values)[$(idx_var_tprime)] * min(abs($x1 - getfield(S, :values)[$(idx_var_n)]), abs($x2 - getfield(S, :values)[$(idx_var_n)])), $(idx_var_d)); 
+         setindex!(getfield(S, :values), 0.0, $(idx_var_tprime)))
+
+        # Connection between the two automata: l2G => l1F
+        @everywhere $(func_name(:cc, :l2G, :l1F, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = true
+        @everywhere $(func_name(:us, :l2G, :l1F, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (setfield!(S, :loc, Symbol("l1F")); 
+         setindex!(getfield(S, :values), x[$(idx_obs_var_F)], $(idx_var_n));
+         setindex!(getfield(S, :values), Inf, $(idx_var_dprime));
+         setindex!(getfield(S, :values), getfield(Main, $(Meta.quot(sym_isabs_func)))(p, x), $(idx_var_isabs)))
+
+        # l1F loc : we construct  the edges of the form l1F => (..)
+        # l1F => l2F
+        @everywhere $(func_name(:cc, :l1F, :l2F, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        getfield(S, :time) >= $t3 &&
+        ($x3 <= getfield(S, :values)[$(idx_var_n)] <= $x4)
+        @everywhere $(func_name(:us, :l1F, :l2F, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (setfield!(S, :loc, Symbol("l2F"));
+         setindex!(getfield(S, :values), 0, $(idx_var_dprime)))
+
+        @everywhere $(func_name(:cc, :l1F, :l2F, 4))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        getfield(S, :time) >= $t3 &&
+        getfield(S, :values)[$(idx_var_dprime)] == 0 
+        @everywhere $(func_name(:us, :l1F, :l2F, 4))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (setfield!(S, :loc, Symbol("l2F")))
+
+        @everywhere $(func_name(:cc, :l1F, :l2F, 2))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (getfield(S, :time) >= $t4) && 
+        (getfield(S, :values)[$(idx_var_n)] < $x3 || getfield(S, :values)[$(idx_var_n)] > $x4)
+        @everywhere $(func_name(:us, :l1F, :l2F, 2))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (setfield!(S, :loc, Symbol("l2F"));
+         setindex!(getfield(S, :values), min(abs(getfield(S, :values)[$(idx_var_n)] - $x3), abs(getfield(S, :values)[$(idx_var_n)] - $x4)), $(idx_var_dprime));
+         setindex!(getfield(S, :values), getfield(S, :values)[$(idx_var_d)] + getfield(S, :values)[$(idx_var_dprime)], $(idx_var_d)))
+
+        @everywhere $(func_name(:cc, :l1F, :l2F, 3))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        istrue(getfield(S, :values)[$(idx_var_isabs)]) && getfield(S, :time) <= $t4
+        @everywhere $(func_name(:us, :l1F, :l2F, 3))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (setfield!(S, :loc, Symbol("l2F"));
+         setindex!(getfield(S, :values), getfield(S, :values)[$(idx_var_d)] + getfield(S, :values)[$(idx_var_dprime)], $(idx_var_d)))
+
+        # l1F => l3F
+        @everywhere $(func_name(:cc, :l1F, :l3F, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        ($x3 <= getfield(S, :values)[$(idx_var_n)] <= $x4)
+        @everywhere $(func_name(:us, :l1F, :l3F, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (setfield!(S, :loc, Symbol("l3F"));
+         setindex!(getfield(S, :values), 0, $(idx_var_dprime));)
+
+        @everywhere $(func_name(:cc, :l1F, :l3F, 2))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (getfield(S, :values)[$(idx_var_n)] < $x3 || getfield(S, :values)[$(idx_var_n)] > $x4) && 
+        (getfield(S, :time) <= $t3)
+        @everywhere $(func_name(:us, :l1F, :l3F, 2))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (setfield!(S, :loc, Symbol("l3F"));
+         setindex!(getfield(S, :values), min(sqrt((getfield(S, :time) - $t3)^2 + (getfield(S, :values)[$(idx_var_n)] - $x4)^2), 
+                                             sqrt((getfield(S, :time) - $t3)^2 + (getfield(S, :values)[$(idx_var_n)] - $x3)^2)), $(idx_var_dprime)))
+
+        @everywhere $(func_name(:cc, :l1F, :l3F, 3))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (getfield(S, :values)[$(idx_var_n)] < $x3 || getfield(S, :values)[$(idx_var_n)] > $x4) && 
+        ($t3 <= getfield(S, :time) <= $t4)
+        @everywhere $(func_name(:us, :l1F, :l3F, 3))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (setfield!(S, :loc, Symbol("l3F"));
+         setindex!(getfield(S, :values), min(getfield(S, :values)[$(idx_var_dprime)], min(abs(getfield(S, :values)[$(idx_var_n)] - $x3), abs(getfield(S, :values)[$(idx_var_n)] - $x4))), $(idx_var_dprime)))
+
+        # l3F loc
+        # l3F => l1F
+        @everywhere $(func_name(:cc, :l3F, :l1F, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = true
+        @everywhere $(func_name(:us, :l3F, :l1F, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (setfield!(S, :loc, Symbol("l1F"));
+         setindex!(getfield(S, :values), x[$(idx_obs_var_F)], $(idx_var_n));
+         setindex!(getfield(S, :values), getfield(Main, $(Meta.quot(sym_isabs_func)))(p, x), $(idx_var_isabs)))
+
+        # l3F => l2F
+        @everywhere $(func_name(:cc, :l3F, :l2F, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (getfield(S, :time) >= $t4)
+        @everywhere $(func_name(:us, :l3F, :l2F, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (setfield!(S, :loc, Symbol("l2F")))
+    end
+    eval(meta_elementary_functions)
+
     # l0G loc
     # l0G => l1G
-    sym_func_us_l0Gl1G_1 = Symbol("us_aut_G_$(basename_func)_l0Gl1G_1!")
-    str_us_l0Gl1G_1 = "
-    @everywhere $(sym_func_us_l0Gl1G_1)(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = \n
-    (S.loc = :l1G; \n
-     S[:d] = 0; \n
-     S[:n] = x[$(idx_obs_var_G)]; \n
-     S[:in] = true; \n
-     S[:isabs] = getfield(Main, $(Meta.quot(sym_isabs_func)))(p, x))"
-    eval(Meta.parse(str_us_l0Gl1G_1))
-    edge1 = Edge([nothing], getfield(Main, :cc_aut_G_l0Gl1G_1), getfield(Main, sym_func_us_l0Gl1G_1))
+    edge1 = Edge([nothing], getfield(Main, func_name(:cc, :l0G, :l1G, 1)), getfield(Main, func_name(:us, :l0G, :l1G, 1)))
     map_edges[:l0G][:l1G] = [edge1]
 
     # l1G => l3G
-    edge1 = Edge([nothing], getfield(Main, :cc_aut_G_l1Gl3G_1), getfield(Main, :us_aut_G_l1Gl3G_1!))
-    edge2 = Edge([nothing], getfield(Main, :cc_aut_G_l1Gl3G_2), getfield(Main, :us_aut_G_l1Gl3G_2!))
-    edge3 = Edge([nothing], getfield(Main, :cc_aut_G_l1Gl3G_3), getfield(Main, :us_aut_G_l1Gl3G_3!))
-    edge4 = Edge([nothing], getfield(Main, :cc_aut_G_l1Gl3G_4), getfield(Main, :us_aut_G_l1Gl3G_4!))
+    edge1 = Edge([nothing], getfield(Main, func_name(:cc, :l1G, :l3G, 1)), getfield(Main, func_name(:us, :l1G, :l3G, 1)))
+    edge2 = Edge([nothing], getfield(Main, func_name(:cc, :l1G, :l3G, 2)), getfield(Main, func_name(:us, :l1G, :l3G, 2)))
+    edge3 = Edge([nothing], getfield(Main, func_name(:cc, :l1G, :l3G, 3)), getfield(Main, func_name(:us, :l1G, :l3G, 3)))
+    edge4 = Edge([nothing], getfield(Main, func_name(:cc, :l1G, :l3G, 4)), getfield(Main, func_name(:us, :l1G, :l3G, 4)))
     map_edges[:l1G][:l3G] = [edge1, edge2, edge3, edge4]
-    
+
     # l1G => l4G
-    edge1 = Edge([nothing], getfield(Main, :cc_aut_G_l1Gl4G_1), getfield(Main, :us_aut_G_l1Gl4G_1!))
-    edge2 = Edge([nothing], getfield(Main, :cc_aut_G_l1Gl4G_2), getfield(Main, :us_aut_G_l1Gl4G_2!))
+    edge1 = Edge([nothing], getfield(Main, func_name(:cc, :l1G, :l4G, 1)), getfield(Main, func_name(:us, :l1G, :l4G, 1)))
+    edge2 = Edge([nothing], getfield(Main, func_name(:cc, :l1G, :l4G, 2)), getfield(Main, func_name(:us, :l1G, :l4G, 2)))
     map_edges[:l1G][:l4G] = [edge1, edge2]
-    
+
     # l1G => l2G
-    edge1 = Edge([nothing], getfield(Main, :cc_aut_G_l1Gl2G_1), getfield(Main, :us_aut_G_l1Gl2G_1!))
-    edge2 = Edge([nothing], getfield(Main, :cc_aut_G_l1Gl2G_2), getfield(Main, :us_aut_G_l1Gl2G_2!))
-    edge3 = Edge([nothing], getfield(Main, :cc_aut_G_l1Gl2G_3), getfield(Main, :us_aut_G_l1Gl2G_3!))
-    edge4 = Edge([nothing], getfield(Main, :cc_aut_G_l1Gl2G_4), getfield(Main, :us_aut_G_l1Gl2G_4!))
+    edge1 = Edge([nothing], getfield(Main, func_name(:cc, :l1G, :l2G, 1)), getfield(Main, func_name(:us, :l1G, :l2G, 1)))
+    edge2 = Edge([nothing], getfield(Main, func_name(:cc, :l1G, :l2G, 2)), getfield(Main, func_name(:us, :l1G, :l2G, 2)))
+    edge3 = Edge([nothing], getfield(Main, func_name(:cc, :l1G, :l2G, 3)), getfield(Main, func_name(:us, :l1G, :l2G, 3)))
+    edge4 = Edge([nothing], getfield(Main, func_name(:cc, :l1G, :l2G, 4)), getfield(Main, func_name(:us, :l1G, :l2G, 4)))
     map_edges[:l1G][:l2G] = [edge3, edge4, edge1, edge2]
 
     # l3G loc
     # l3G => l1G
-    sym_func_us_l3Gl1G_1 = Symbol("us_aut_G_$(basename_func)_l3Gl1G_1!")
-    str_us_l3Gl1G_1 = "
-    @everywhere $(sym_func_us_l3Gl1G_1)(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = \n
-    (S.loc = :l1G; \n
-     S[:n] = x[$(idx_obs_var_G)]; \n
-     S[:isabs] = getfield(Main, $(Meta.quot(sym_isabs_func)))(p, x))"
-    eval(Meta.parse(str_us_l3Gl1G_1))
-    edge1 = Edge([:ALL], getfield(Main, :cc_aut_G_l3Gl1G_1), getfield(Main, sym_func_us_l3Gl1G_1))
+    edge1 = Edge([:ALL], getfield(Main, func_name(:cc, :l3G, :l1G, 1)), getfield(Main, func_name(:us, :l3G, :l1G, 1)))
     map_edges[:l3G][:l1G] = [edge1]
-    
+
     # l3G => l2G
-    edge1 = Edge([nothing], getfield(Main, :cc_aut_G_l3Gl2G_1), getfield(Main, :us_aut_G_l3Gl2G_1!))
-    edge2 = Edge([nothing], getfield(Main, :cc_aut_G_l3Gl2G_2), getfield(Main, :us_aut_G_l3Gl2G_2!))
+    edge1 = Edge([nothing], getfield(Main, func_name(:cc, :l3G, :l2G, 1)), getfield(Main, func_name(:us, :l3G, :l2G, 1)))
+    edge2 = Edge([nothing], getfield(Main, func_name(:cc, :l3G, :l2G, 2)), getfield(Main, func_name(:us, :l3G, :l2G, 2)))
     map_edges[:l3G][:l2G] = [edge1, edge2]
 
     # l4 loc
     # l4G => l1G
-    sym_func_us_l4Gl1G_1 = Symbol("us_aut_G_$(basename_func)_l4Gl1G_1!")
-    str_us_l4Gl1G_1 = "
-    @everywhere $(sym_func_us_l4Gl1G_1)(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = \n
-    (S.loc = :l1G; \n
-     S[:d] += S[:tprime] * min(abs(constants[:x1] - S[:n]), abs(constants[:x2] - S[:n])); \n
-     S[:tprime] = 0.0; \n
-     S[:n] = x[$(idx_obs_var_G)]; \n
-     S[:in] = true; \n
-     S[:isabs] = getfield(Main, $(Meta.quot(sym_isabs_func)))(p, x))"
-    eval(Meta.parse(str_us_l4Gl1G_1))
-    edge1 = Edge([:ALL], getfield(Main, :cc_aut_G_l4Gl1G_1), getfield(Main, sym_func_us_l4Gl1G_1))
+    edge1 = Edge([:ALL], getfield(Main, func_name(:cc, :l4G, :l1G, 1)), getfield(Main, func_name(:us, :l4G, :l1G, 1)))
     map_edges[:l4G][:l1G] = [edge1]
 
     # l4G => l2G
-    edge1 = Edge([nothing], getfield(Main, :cc_aut_G_l4Gl2G_1), getfield(Main, :us_aut_G_l4Gl2G_1!))
+    edge1 = Edge([nothing], getfield(Main, func_name(:cc, :l4G, :l2G, 1)), getfield(Main, func_name(:us, :l4G, :l2G, 1)))
     map_edges[:l4G][:l2G] = [edge1]
 
     # l2G loc
     # l2G => l1F : Transition from autF to autG
-    sym_func_us_l2Gl1F_1 = Symbol("us_aut_G_$(basename_func)_l2Gl1F_1!")
-    str_us_l2Gl1F_1 = "
-    @everywhere $(sym_func_us_l2Gl1F_1)(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = \n
-    (S.loc = :l1F; \n
-     S[:n] = x[$(idx_obs_var_F)];\n
-     S[:dprime] = Inf; \n
-     S[:isabs] = getfield(Main, $(Meta.quot(sym_isabs_func)))(p, x))"
-    eval(Meta.parse(str_us_l2Gl1F_1))
-    edge1 = Edge([nothing], getfield(Main, :cc_aut_F_l2Gl1F_1), getfield(Main, sym_func_us_l2Gl1F_1))
+    edge1 = Edge([nothing], getfield(Main, func_name(:cc, :l2G, :l1F, 1)), getfield(Main, func_name(:us, :l2G, :l1F, 1)))
     map_edges[:l2G][:l1F] = [edge1]
 
     # l1F loc
     # l1F => l3F
-    edge1 = Edge([nothing], getfield(Main, :cc_aut_F_l1Fl2F_1), getfield(Main, :us_aut_F_l1Fl2F_1!))
-    edge2 = Edge([nothing], getfield(Main, :cc_aut_F_l1Fl2F_2), getfield(Main, :us_aut_F_l1Fl2F_2!))
-    edge3 = Edge([nothing], getfield(Main, :cc_aut_F_l1Fl2F_3), getfield(Main, :us_aut_F_l1Fl2F_3!))
-    edge4 = Edge([nothing], getfield(Main, :cc_aut_F_l1Fl2F_4), getfield(Main, :us_aut_F_l1Fl2F_4!))
+    edge1 = Edge([nothing], getfield(Main, func_name(:cc, :l1F, :l2F, 1)), getfield(Main, func_name(:us, :l1F, :l2F, 1)))
+    edge2 = Edge([nothing], getfield(Main, func_name(:cc, :l1F, :l2F, 2)), getfield(Main, func_name(:us, :l1F, :l2F, 2)))
+    edge3 = Edge([nothing], getfield(Main, func_name(:cc, :l1F, :l2F, 3)), getfield(Main, func_name(:us, :l1F, :l2F, 3)))
+    edge4 = Edge([nothing], getfield(Main, func_name(:cc, :l1F, :l2F, 4)), getfield(Main, func_name(:us, :l1F, :l2F, 4)))
     map_edges[:l1F][:l2F] = [edge1, edge4, edge3, edge2]
 
     # l1F => l3F
-    edge1 = Edge([nothing], getfield(Main, :cc_aut_F_l1Fl3F_1), getfield(Main, :us_aut_F_l1Fl3F_1!))
-    edge2 = Edge([nothing], getfield(Main, :cc_aut_F_l1Fl3F_2), getfield(Main, :us_aut_F_l1Fl3F_2!))
-    edge3 = Edge([nothing], getfield(Main, :cc_aut_F_l1Fl3F_3), getfield(Main, :us_aut_F_l1Fl3F_3!))
+    edge1 = Edge([nothing], getfield(Main, func_name(:cc, :l1F, :l3F, 1)), getfield(Main, func_name(:us, :l1F, :l3F, 1)))
+    edge2 = Edge([nothing], getfield(Main, func_name(:cc, :l1F, :l3F, 2)), getfield(Main, func_name(:us, :l1F, :l3F, 2)))
+    edge3 = Edge([nothing], getfield(Main, func_name(:cc, :l1F, :l3F, 3)), getfield(Main, func_name(:us, :l1F, :l3F, 3)))
     map_edges[:l1F][:l3F] = [edge1, edge2, edge3]
 
     # l3F loc
     # l3F => l1F
-    sym_func_us_l3Fl1F_1 = Symbol("us_aut_G_$(basename_func)_l3Fl1F_1!")
-    str_us_l3Fl1F_1 = "
-    @everywhere $(sym_func_us_l3Fl1F_1)(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = \n
-    (S.loc = :l1F;\n
-     S[:n] = x[$(idx_obs_var_F)];\n
-     S[:isabs] = getfield(Main, $(Meta.quot(sym_isabs_func)))(p, x))"
-    eval(Meta.parse(str_us_l3Fl1F_1))
-    edge1 = Edge([:ALL], getfield(Main, :cc_aut_F_l3Fl1F_1), getfield(Main, sym_func_us_l3Fl1F_1))
+    edge1 = Edge([:ALL], getfield(Main, func_name(:cc, :l3F, :l1F, 1)), getfield(Main, func_name(:us, :l3F, :l1F, 1)))
     map_edges[:l3F][:l1F] = [edge1]
 
     # l3F => l2F
-    edge1 = Edge([nothing], getfield(Main, :cc_aut_F_l3Fl2F_1), getfield(Main, :us_aut_F_l3Fl2F_1!))    
+    edge1 = Edge([nothing], getfield(Main, func_name(:cc, :l3F, :l2F, 1)), getfield(Main, func_name(:us, :l3F, :l2F, 1)))    
     map_edges[:l3F][:l2F] = [edge1]
 
     ## Constants
diff --git a/automata/euclidean_distance_automaton.jl b/automata/euclidean_distance_automaton.jl
index 7b64a18ed5d749ec2ba65d8fe92a146c2569797b..5fc21aebdab2a6615c16ee4280b2b6175eb7a8ef 100644
--- a/automata/euclidean_distance_automaton.jl
+++ b/automata/euclidean_distance_automaton.jl
@@ -1,25 +1,4 @@
 
-# l0 loc
-# l0 => l1
-@everywhere cc_eucl_dist_aut_l0l1_1(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = true
-
-# l1 loc
-# l1 => l1
-@everywhere cc_eucl_dist_aut_l1l1_1(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-S[:t] >= constants[Symbol("tml_$(S[:idx])")]
-@everywhere us_eucl_dist_aut_l1l1_1!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(S[:d] += (S[:n]  - constants[Symbol("y_$(S[:idx])")])^2;
- S[:idx] += 1.0)
-
-# l1 => l2
-@everywhere cc_eucl_dist_aut_l1l2_1(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-S[:idx] >= constants[:nbr_obs] + 1
-@everywhere us_eucl_dist_aut_l1l2_1!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(S.loc = :l2; 
- S[:d] = sqrt(S[:d]))
-
-@everywhere cc_eucl_dist_aut_l1l1_2(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = true 
-
 function create_euclidean_distance_automaton(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."
@@ -40,16 +19,7 @@ function create_euclidean_distance_automaton(m::ContinuousTimeModel, timeline::A
 
     map_var_automaton_idx = Dict{VariableAutomaton,Int}(:t => 1, :n => 2, 
                                                         :d => 3, :idx => 4)
-    nbr_first_vars = 4
-    for i = 1:nbr_observations
-        map_var_automaton_idx[Symbol("tml_$(convert(Float64, i))")] = nbr_first_vars + i
-    end
-    for i = 1:nbr_observations
-        map_var_automaton_idx[Symbol("y_$(convert(Float64, i))")] = nbr_first_vars + nbr_observations + i
-    end
-    
-    vector_flow = zeros(nbr_first_vars + 2*nbr_observations)
-    vector_flow[1] = 1.0
+    vector_flow = [1.0, 0.0, 0.0, 0.0]
     flow = Dict{Location,Vector{Float64}}(:l0 => vector_flow, 
                                           :l1 => vector_flow, 
                                           :l2 => vector_flow)
@@ -61,36 +31,78 @@ function create_euclidean_distance_automaton(m::ContinuousTimeModel, timeline::A
     end
 
     idx_obs_var = getfield(m, :map_var_idx)[sym_obs]
+    idx_var_t = map_var_automaton_idx[:t] 
+    idx_var_n = map_var_automaton_idx[:n] 
+    idx_var_d = map_var_automaton_idx[:d] 
+    idx_var_idx = map_var_automaton_idx[:idx] 
+    
     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_$(basename_func)_$(from_loc)$(to_loc)_$(edge_number)$(type_func == :us ? "!" : "")")
+    meta_elementary_functions = quote
+        # l0 loc
+        # l0 => l1
+        @everywhere $(func_name(:cc, :l0, :l1, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = true
+        @everywhere $(func_name(:us, :l0, :l1, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (setfield!(S, :loc, Symbol("l1")); 
+         setindex!(getfield(S, :values), x[$(idx_obs_var)], $(idx_var_n));
+         setindex!(getfield(S, :values), 0.0, $(idx_var_d));
+         setindex!(getfield(S, :values), 1.0, $(idx_var_idx)))
+
+        # l1 loc
+        # l1 => l1
+        # Defined below 
+        @everywhere $(func_name(:cc, :l1, :l1, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) =
+        getfield(S, :values)[$(idx_var_t)] >= $(timeline)[convert(Int, getfield(S, :values)[$(idx_var_idx)])]
+        @everywhere $(func_name(:us, :l1, :l1, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) =
+        (setindex!(getfield(S, :values), getfield(S, :values)[$(idx_var_d)] + 
+                                        (getfield(S, :values)[$(idx_var_n)]  - $(observations)[convert(Int, getfield(S, :values)[$(idx_var_idx)])])^2, 
+                                        $(idx_var_d));
+         setindex!(getfield(S, :values), getfield(S, :values)[$(idx_var_idx)] + 1.0, $(idx_var_idx)))
+        
+        @everywhere $(func_name(:cc, :l1, :l1, 2))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = true 
+        @everywhere $(func_name(:us, :l1, :l1, 2))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (setindex!(getfield(S, :values), x[$(idx_obs_var)], $(idx_var_n)))
+        
+        # l1 => l2
+        @everywhere $(func_name(:cc, :l1, :l2, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        getfield(S, :values)[$(idx_var_idx)] >= ($nbr_observations + 1)
+        @everywhere $(func_name(:us, :l1, :l2, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (setfield!(S, :loc, Symbol("l2")); 
+         setindex!(getfield(S, :values), sqrt(getfield(S, :values)[$(idx_var_d)]), $(idx_var_d)))
+    end
+    eval(meta_elementary_functions)
+
     # l0 loc
     # l0 => l1
-    sym_func_us_l0l1_1 = Symbol("us_eucl_dist_$(basename_func)_l0l1_1!")
-    str_us_l0l1_1 = "
-    @everywhere $(sym_func_us_l0l1_1)(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = \n
-        (S.loc = :l1; \n
-         S[:n] = x[$(idx_obs_var)];\n
-         S[:d] = 0.0;\n
-         S[:idx] = 1.0)"
-    eval(Meta.parse(str_us_l0l1_1))
-    edge1 = Edge([nothing], getfield(Main, :cc_eucl_dist_aut_l0l1_1), getfield(Main, sym_func_us_l0l1_1))
+    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 => l1
-    sym_func_us_l1l2_2 = Symbol("us_eucl_dist_$(basename_func)_l1l2_2!")
-    str_us_l1l2_2 = "
-    @everywhere $(sym_func_us_l1l2_2)(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) =\n 
-    (S[:n] = x[$(idx_obs_var)])"
-    eval(Meta.parse(str_us_l1l2_2))
-    edge1 = Edge([nothing], getfield(Main, :cc_eucl_dist_aut_l1l1_1), getfield(Main, :us_eucl_dist_aut_l1l1_1!))
-    edge2 = Edge([:ALL], getfield(Main, :cc_eucl_dist_aut_l1l1_2), getfield(Main, sym_func_us_l1l2_2))
+    #=
+    edge1 = Edge([:ALL], getfield(Main, func_name(:cc, :l1, :l1, 1)), getfield(Main, func_name(:us, :l1, :l2, 1)))
+    map_edges[:l1][:l1] = [edge1]
+    for i = 1:nbr_observations
+        meta_edge_i = quote
+            @everywhere $(func_name(:cc, :l1, :l1, 1+i))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) =
+            S[:t] >= $(timeline[i])
+            @everywhere $(func_name(:us, :l1, :l1, 1+i))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) =
+            (setindex!(getfield(S, :values), S[:d] + (S[:n]  - $(observations[i]))^2, $(idx_var_d));
+             setindex!(getfield(S, :values), S[:idx] + 1.0, $(idx_var_idx)))
+        end
+        eval(meta_edge_i)
+        push!(map_edges[:l1][:l1], Edge([nothing], getfield(Main, func_name(:cc, :l1, :l1, 1+i)), getfield(Main, func_name(:us, :l1, :l1, 1+i))))
+    end
+    =#
+    edge1 = Edge([nothing], getfield(Main, func_name(:cc, :l1, :l1, 1)), getfield(Main, func_name(:us, :l1, :l1, 1)))
+    edge2 = Edge([:ALL], getfield(Main, func_name(:cc, :l1, :l1, 2)), getfield(Main, func_name(:us, :l1, :l1, 2)))
     map_edges[:l1][:l1] = [edge1, edge2]
 
     # l1 => l2
-    edge1 = Edge([nothing], getfield(Main, :cc_eucl_dist_aut_l1l2_1), getfield(Main, :us_eucl_dist_aut_l1l2_1!))
+    edge1 = Edge([nothing], getfield(Main, func_name(:cc, :l1, :l2, 1)), getfield(Main, func_name(:us, :l1, :l2, 1)))
     map_edges[:l1][:l2] = [edge1]
 
     ## Constants
diff --git a/automata/period_automaton.jl b/automata/period_automaton.jl
index 653efe7eba9282b34a2a3355dee6275ce86fcdf3..19581c705d3ce71a319872883e577efe9338efb4 100644
--- a/automata/period_automaton.jl
+++ b/automata/period_automaton.jl
@@ -1,139 +1,4 @@
 
-## Edge functions
-
-# l0 loc 
-# * l0 => l0
-@everywhere cc_aut_per_l0l0_1(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-true
-@everywhere us_aut_per_l0l0_1!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) =
-(nothing)
-
-# * l0 => l0prime
-@everywhere cc_aut_per_l0l0prime_1(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-S[:t] >= constants[:initT]
-@everywhere us_aut_per_l0l0prime_1!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) =
-(S.loc = :l0prime)
-
-# * l0 => low
-@everywhere cc_aut_per_l0low_1(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-S[:t] >= constants[:initT]
-@everywhere us_aut_per_l0low_1!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) =
-(S.loc = :low;
- S[:t] = 0.0;
- S[:top] = 0.0;
- S[:n] = -1)
-
-# l0prime
-# * l0prime => l0prime
-@everywhere cc_aut_per_l0primel0prime_1(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-true
-@everywhere us_aut_per_l0primel0prime_1!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) =
-(nothing)
-
-# * l0prime => low
-@everywhere cc_aut_per_l0primelow_1(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-true
-@everywhere us_aut_per_l0primelow_1!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) =
-(S.loc = :low;
- S[:t] = 0.0;
- S[:top] = 0.0;
- S[:n] = -1)
-
-# low 
-# * low => low
-@everywhere cc_aut_per_lowlow_1(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-S[:n] < constants[:N]
-@everywhere us_aut_per_lowlow_1!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) =
-(nothing)
-
-# * low => mid 
-@everywhere cc_aut_per_lowmid_1(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-S[:n] < constants[:N]
-@everywhere us_aut_per_lowmid_1!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) =
-(S.loc = :mid)
-
-# * low => final
-@everywhere cc_aut_per_lowfinal_1(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-S[:n] == constants[:N]
-@everywhere us_aut_per_lowfinal_1!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) =
-(S.loc = :final)
-
-# mid
-# * mid => mid
-@everywhere cc_aut_per_midmid_1(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-S[:n] < constants[:N]
-@everywhere us_aut_per_midmid_1!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) =
-(nothing)
-
-# * mid => low 
-@everywhere cc_aut_per_midlow_1(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-S[:n] < constants[:N] &&
-S[:top] == 0.0
-@everywhere us_aut_per_midlow_1!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) =
-(S.loc = :low)
-
-@everywhere cc_aut_per_midlow_2(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-S[:n] == -1.0 &&
-S[:top] == 1.0
-@everywhere us_aut_per_midlow_2!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) =
-(S.loc = :low;
- S[:n] += 1;
- S[:t] = 0.0;
- S[:top] = 0.0)
-
-@everywhere cc_aut_per_midlow_3(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(0 <= S[:n] <= 1) &&
-S[:top] == 1.0
-@everywhere us_aut_per_midlow_3!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) =
-(S.loc = :low;
- S[:n] += 1;
- S[:top] = 0.0;
- S[:mean_tp] = (S[:mean_tp] * (S[:n]-1) + S[:tp]) / S[:n];
- S[:tp] = 0.0)
-
-@everywhere cc_aut_per_midlow_4(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-(2 <= S[:n] < constants[:N]) &&
-S[:top] == 1.0
-@everywhere us_aut_per_midlow_4!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) =
-(S.loc = :low;
- S[:n] += 1;
- S[:top] = 0.0;
- S[:mean_tp] = (S[:mean_tp] * (S[:n]-1) + S[:tp]) / S[:n];
- S[:var_tp] = (S[:var_tp] * (S[:n]-1) + (S[:mean_tp]-S[:tp])^2) / S[:n];
- S[:tp] = 0.0)
-
-# * mid => high
-@everywhere cc_aut_per_midhigh_1(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-S[:n] < constants[:N]
-@everywhere us_aut_per_midhigh_1!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) =
-(S.loc = :high;
- S[:top] = 1.0)
-
-# * mid => final
-@everywhere cc_aut_per_midfinal_1(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-S[:n] == constants[:N]
-@everywhere us_aut_per_midfinal_1!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) =
-(S.loc = :final)
-
-# high 
-# * high => high
-@everywhere cc_aut_per_highhigh_1(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-S[:n] < constants[:N]
-@everywhere us_aut_per_highhigh_1!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) =
-(nothing)
-
-# * high => mid
-@everywhere cc_aut_per_highmid_1(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-S[:n] < constants[:N]
-@everywhere us_aut_per_highmid_1!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) =
-(S.loc = :mid)
-
-# * high => final
-@everywhere cc_aut_per_highfinal_1(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) = 
-S[:n] == constants[:N]
-@everywhere us_aut_per_highfinal_1!(S::StateLHA, constants::Dict{Symbol,Float64}, x::Vector{Int}, p::Vector{Float64}) =
-(S.loc = :final)
-
 function create_period_automaton(m::ContinuousTimeModel, L::Float64, H::Float64, N::Int, sym_obs::VariableModel;
                                  initT::Float64 = 0.0)
     # Requirements for the automaton
@@ -159,13 +24,6 @@ function create_period_automaton(m::ContinuousTimeModel, L::Float64, H::Float64,
     @everywhere not_low_predicate(x::Vector{Int}) = !low_predicate(x)
     @everywhere mid_predicate(x::Vector{Int}) = $L < x[$(Meta.quot(idx_sym_obs))] < $H
     @everywhere high_predicate(x::Vector{Int}) = x[$(Meta.quot(idx_sym_obs))] >= $H
-    #=
-    eval(Meta.parse("@everywhere true_predicate(x::Vector{Int}) = true"))
-    eval(Meta.parse("@everywhere low_predicate(x::Vector{Int}) = x[$(Meta.quot(idx_sym_obs))] <= $L"))
-    eval(Meta.parse("@everywhere not_low_predicate(x::Vector{Int}) = !low_predicate(x)"))
-    eval(Meta.parse("@everywhere mid_predicate(x::Vector{Int}) = L < x[$(Meta.quot(idx_sym_obs))] < $H"))
-    eval(Meta.parse("@everywhere high_predicate(x::Vector{Int}) = x[$(Meta.quot(idx_sym_obs))] >= $H"))
-    =#
 
     Λ_F = Dict(:l0 => getfield(Main, :true_predicate), :l0prime => getfield(Main, :not_low_predicate),
                :low => getfield(Main, :low_predicate), :mid => getfield(Main, :mid_predicate), 
@@ -184,70 +42,219 @@ function create_period_automaton(m::ContinuousTimeModel, L::Float64, H::Float64,
                                           :low => [1.0,0.0,0.0,1.0,0.0,0.0],
                                           :mid => [1.0,0.0,0.0,1.0,0.0,0.0],
                                           :high => [1.0,0.0,0.0,1.0,0.0,0.0],
-                                          :final => [1.0,0.0,0.0,0.0,0.0,0.0])
-    
+                                          :final => [1.0,0.0,0.0,0.0,0.0,0.0]) 
     ## 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]
+    idx_var_t = map_var_automaton_idx[:t] 
+    idx_var_tp = map_var_automaton_idx[:tp] 
+    idx_var_mean_tp = map_var_automaton_idx[:mean_tp] 
+    idx_var_var_tp = map_var_automaton_idx[:var_tp] 
+    idx_var_n = map_var_automaton_idx[:n] 
+    idx_var_top = map_var_automaton_idx[:top]
+    
+    nbr_rand = rand(1:100000)
+    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)_aut_per_$(basename_func)_$(from_loc)$(to_loc)_$(edge_number)$(type_func == :us ? "!" : "")")
+    meta_elementary_functions = quote
+        ## Edge functions
+
+        # l0 loc 
+        # * l0 => l0
+        @everywhere $(func_name(:cc, :l0, :l0, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        true
+        @everywhere $(func_name(:us, :l0, :l0, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) =
+        (nothing)
+
+        # * l0 => l0prime
+        @everywhere $(func_name(:cc, :l0, :l0prime, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        S[:t] >= $initT
+        @everywhere $(func_name(:us, :l0, :l0prime, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) =
+        (setfield!(S, :loc, Symbol("l0prime")))
+
+        # * l0 => low
+        @everywhere $(func_name(:cc, :l0, :low, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        S[:t] >= $initT
+        @everywhere $(func_name(:us, :l0, :low, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) =
+        (setfield!(S, :loc, Symbol("low"));
+         setindex!(getfield(S, :values), 0.0, $(idx_var_t));
+         setindex!(getfield(S, :values), 0.0, $(idx_var_top));
+         setindex!(getfield(S, :values), -1, $(idx_var_n)))
+
+        # l0prime
+        # * l0prime => l0prime
+        @everywhere $(func_name(:cc, :l0prime, :l0prime, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        true
+        @everywhere $(func_name(:us, :l0prime, :l0prime, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) =
+        (nothing)
+
+        # * l0prime => low
+        @everywhere $(func_name(:cc, :l0prime, :low, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        true
+        @everywhere $(func_name(:us, :l0prime, :low, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) =
+        (setfield!(S, :loc, Symbol("low"));
+         setindex!(getfield(S, :values), 0.0, $(idx_var_t));
+         setindex!(getfield(S, :values), 0.0, $(idx_var_top));
+         setindex!(getfield(S, :values), -1, $(idx_var_n)))
+
+        # low 
+        # * low => low
+        @everywhere $(func_name(:cc, :low, :low, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        S[:n] < $N
+        @everywhere $(func_name(:us, :low, :low, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) =
+        (nothing)
+
+        # * low => mid 
+        @everywhere $(func_name(:cc, :low, :mid, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        S[:n] < $N
+        @everywhere $(func_name(:us, :low, :mid, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) =
+        (setfield!(S, :loc, Symbol("mid")))
+
+        # * low => final
+        @everywhere $(func_name(:cc, :low, :final, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        S[:n] == $N
+        @everywhere $(func_name(:us, :low, :final, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) =
+        (setfield!(S, :loc, Symbol("final")))
+
+        # mid
+        # * mid => mid
+        @everywhere $(func_name(:cc, :mid, :mid, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        S[:n] < $N
+        @everywhere $(func_name(:us, :mid, :mid, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) =
+        (nothing)
+
+        # * mid => low 
+        @everywhere $(func_name(:cc, :mid, :low, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        S[:n] < $N &&
+        S[:top] == 0.0
+        @everywhere $(func_name(:us, :mid, :low, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) =
+        (setfield!(S, :loc, Symbol("low")))
+
+        @everywhere $(func_name(:cc, :mid, :low, 2))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        S[:n] == -1.0 &&
+        S[:top] == 1.0
+        @everywhere $(func_name(:us, :mid, :low, 2))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) =
+        (setfield!(S, :loc, Symbol("low"));
+         setindex!(getfield(S, :values), S[:n] + 1, $(idx_var_n));
+         setindex!(getfield(S, :values), 0.0, $(idx_var_t));
+         setindex!(getfield(S, :values), 0.0, $(idx_var_top)))
+
+        @everywhere $(func_name(:cc, :mid, :low, 3))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (0 <= S[:n] <= 1) &&
+        S[:top] == 1.0
+        @everywhere $(func_name(:us, :mid, :low, 3))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) =
+        (setfield!(S, :loc, Symbol("low"));
+         setindex!(getfield(S, :values), S[:n] + 1, $(idx_var_n));
+         setindex!(getfield(S, :values), 0.0, $(idx_var_top));
+         setindex!(getfield(S, :values), (S[:mean_tp] * (S[:n]-1) + S[:tp]) / S[:n], $(idx_var_mean_tp));
+         setindex!(getfield(S, :values), 0.0, $(idx_var_tp)))
+
+        @everywhere $(func_name(:cc, :mid, :low, 4))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        (2 <= S[:n] < $N) &&
+        S[:top] == 1.0
+        @everywhere $(func_name(:us, :mid, :low, 4))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) =
+        (setfield!(S, :loc, Symbol("low"));
+         setindex!(getfield(S, :values), S[:n] + 1, $(idx_var_n));
+         setindex!(getfield(S, :values), 0.0, $(idx_var_top));
+         setindex!(getfield(S, :values), (S[:mean_tp] * (S[:n]-1) + S[:tp]) / S[:n], $(idx_var_mean_tp));
+         setindex!(getfield(S, :values), (S[:var_tp] * (S[:n]-1) + (S[:mean_tp]-S[:tp])^2) / S[:n], $(idx_var_var_tp)))
+
+        # * mid => high
+        @everywhere $(func_name(:cc, :mid, :high, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        S[:n] < $N
+        @everywhere $(func_name(:us, :mid, :high, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) =
+        (setfield!(S, :loc, Symbol("high"));
+         setindex!(getfield(S, :values), 1.0, $(idx_var_top)))
+
+        # * mid => final
+        @everywhere $(func_name(:cc, :mid, :final, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        S[:n] == $N
+        @everywhere $(func_name(:us, :mid, :final, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) =
+        (setfield!(S, :loc, Symbol("final")))
+
+        # high 
+        # * high => high
+        @everywhere $(func_name(:cc, :high, :high, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        S[:n] < $N
+        @everywhere $(func_name(:us, :high, :high, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) =
+        (nothing)
+
+        # * high => mid
+        @everywhere $(func_name(:cc, :high, :mid, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        S[:n] < $N
+        @everywhere $(func_name(:us, :high, :mid, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) =
+        (setfield!(S, :loc, Symbol("mid")))
+
+        # * high => final
+        @everywhere $(func_name(:cc, :high, :final, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) = 
+        S[:n] == $N
+        @everywhere $(func_name(:us, :high, :final, 1))(S::StateLHA, x::Vector{Int}, p::Vector{Float64}) =
+        (setfield!(S, :loc, Symbol("final")))
+    end
+    eval(meta_elementary_functions)
 
     # l0 loc 
     # * l0 => l0
-    edge_1 = Edge([:ALL], getfield(Main, :cc_aut_per_l0l0_1), getfield(Main, :us_aut_per_l0l0_1!))
+    edge_1 = Edge([:ALL], getfield(Main, func_name(:cc, :l0, :l0, 1)), getfield(Main, func_name(:us, :l0, :l0, 1)))
     map_edges[:l0][:l0] = [edge_1]
     # * l0 => l0prime
-    edge_1 = Edge([nothing], getfield(Main, :cc_aut_per_l0l0prime_1), getfield(Main, :us_aut_per_l0l0prime_1!))
+    edge_1 = Edge([nothing], getfield(Main, func_name(:cc, :l0, :l0prime, 1)), getfield(Main, func_name(:us, :l0, :l0prime, 1)))
     map_edges[:l0][:l0prime] = [edge_1]
     # * l0 => low
-    edge_1 = Edge([nothing], getfield(Main, :cc_aut_per_l0low_1), getfield(Main, :us_aut_per_l0low_1!))
+    edge_1 = Edge([nothing], getfield(Main, func_name(:cc, :l0, :low, 1)), getfield(Main, func_name(:us, :l0, :low, 1)))
     map_edges[:l0][:low] = [edge_1]
 
     # l0prime
     # * l0prime => l0prime
-    edge_1 = Edge([:ALL], getfield(Main, :cc_aut_per_l0primel0prime_1), getfield(Main, :us_aut_per_l0primel0prime_1!))
+    edge_1 = Edge([:ALL], getfield(Main, func_name(:cc, :l0prime, :l0prime, 1)), getfield(Main, func_name(:us, :l0prime, :l0prime, 1)))
     map_edges[:l0prime][:l0prime] = [edge_1]
     # * l0prime => low
-    edge_1 = Edge([nothing], getfield(Main, :cc_aut_per_l0primelow_1), getfield(Main, :us_aut_per_l0primelow_1!))
+    edge_1 = Edge([nothing], getfield(Main, func_name(:cc, :l0prime, :low, 1)), getfield(Main, func_name(:us, :l0prime, :low, 1)))
     map_edges[:l0prime][:low] = [edge_1]
 
     # low 
     # * low => low
-    edge_1 = Edge([:ALL], getfield(Main, :cc_aut_per_lowlow_1), getfield(Main, :us_aut_per_lowlow_1!))
+    edge_1 = Edge([:ALL], getfield(Main, func_name(:cc, :low, :low, 1)), getfield(Main, func_name(:us, :low, :low, 1)))
     map_edges[:low][:low] = [edge_1]
     # * low => mid 
-    edge_1 = Edge([:ALL], getfield(Main, :cc_aut_per_lowmid_1), getfield(Main, :us_aut_per_lowmid_1!))
+    edge_1 = Edge([:ALL], getfield(Main, func_name(:cc, :low, :mid, 1)), getfield(Main, func_name(:us, :low, :mid, 1)))
     map_edges[:low][:mid] = [edge_1]
     # * low => final
-    edge_1 = Edge([nothing], getfield(Main, :cc_aut_per_lowfinal_1), getfield(Main, :us_aut_per_lowfinal_1!))
+    edge_1 = Edge([nothing], getfield(Main, func_name(:cc, :low, :final, 1)), getfield(Main, func_name(:us, :low, :final, 1)))
     map_edges[:low][:final] = [edge_1]
 
     # mid
     # * mid => mid
-    edge_1 = Edge([:ALL], getfield(Main, :cc_aut_per_midmid_1), getfield(Main, :us_aut_per_midmid_1!))
+    edge_1 = Edge([:ALL], getfield(Main, func_name(:cc, :mid, :mid, 1)), getfield(Main, func_name(:us, :mid, :mid, 1)))
     map_edges[:mid][:mid] = [edge_1]
     # * mid => low 
-    edge_1 = Edge([:ALL], getfield(Main, :cc_aut_per_midlow_1), getfield(Main, :us_aut_per_midlow_1!))
-    edge_2 = Edge([:ALL], getfield(Main, :cc_aut_per_midlow_2), getfield(Main, :us_aut_per_midlow_2!))
-    edge_3 = Edge([:ALL], getfield(Main, :cc_aut_per_midlow_3), getfield(Main, :us_aut_per_midlow_3!))
-    edge_4 = Edge([:ALL], getfield(Main, :cc_aut_per_midlow_4), getfield(Main, :us_aut_per_midlow_4!))
+    edge_1 = Edge([:ALL], getfield(Main, func_name(:cc, :mid, :low, 1)), getfield(Main, func_name(:us, :mid, :low, 1)))
+    edge_2 = Edge([:ALL], getfield(Main, func_name(:cc, :mid, :low, 2)), getfield(Main, func_name(:us, :mid, :low, 2)))
+    edge_3 = Edge([:ALL], getfield(Main, func_name(:cc, :mid, :low, 3)), getfield(Main, func_name(:us, :mid, :low, 3)))
+    edge_4 = Edge([:ALL], getfield(Main, func_name(:cc, :mid, :low, 4)), getfield(Main, func_name(:us, :mid, :low, 4)))
     map_edges[:mid][:low] = [edge_1, edge_2, edge_3, edge_4]
     # * mid => high
-    edge_1 = Edge([:ALL], getfield(Main, :cc_aut_per_midhigh_1), getfield(Main, :us_aut_per_midhigh_1!))
+    edge_1 = Edge([:ALL], getfield(Main, func_name(:cc, :mid, :high, 1)), getfield(Main, func_name(:us, :mid, :high, 1)))
     map_edges[:mid][:high] = [edge_1]
     # * mid => final
-    edge_1 = Edge([nothing], getfield(Main, :cc_aut_per_midfinal_1), getfield(Main, :us_aut_per_midfinal_1!))
+    edge_1 = Edge([nothing], getfield(Main, func_name(:cc, :mid, :final, 1)), getfield(Main, func_name(:us, :mid, :final, 1)))
     map_edges[:mid][:final] = [edge_1]
 
     # high 
     # * high => high
-    edge_1 = Edge([:ALL], getfield(Main, :cc_aut_per_highhigh_1), getfield(Main, :us_aut_per_highhigh_1!))
+    edge_1 = Edge([:ALL], getfield(Main, func_name(:cc, :high, :high, 1)), getfield(Main, func_name(:us, :high, :high, 1)))
     map_edges[:high][:high] = [edge_1]
     # * high => mid
-    edge_1 = Edge([:ALL], getfield(Main, :cc_aut_per_highmid_1), getfield(Main, :us_aut_per_highmid_1!))
+    edge_1 = Edge([:ALL], getfield(Main, func_name(:cc, :high, :mid, 1)), getfield(Main, func_name(:us, :high, :mid, 1)))
     map_edges[:high][:mid] = [edge_1]
     # * high => final
-    edge_1 = Edge([nothing], getfield(Main, :cc_aut_per_highfinal_1), getfield(Main, :us_aut_per_highfinal_1!))
+    edge_1 = Edge([nothing], getfield(Main, func_name(:cc, :high, :final, 1)), getfield(Main, func_name(:us, :high, :final, 1)))
     map_edges[:high][:final] = [edge_1] 
 
     ## Constants
diff --git a/core/MarkovProcesses.jl b/core/MarkovProcesses.jl
index 3485e7562ed87e7c7740d547e366542cb662591b..f0fdc940ae930813c54bbe2a9fd65a01d4337fbb 100644
--- a/core/MarkovProcesses.jl
+++ b/core/MarkovProcesses.jl
@@ -17,7 +17,7 @@ export VariableModel, ParameterModel, Transition
 export LHA, StateLHA, Edge, Location, VariableAutomaton
 
 # Trajectory related methods
-export +, -, δ, dist_lp
+export +, -, δ, dist_lp, euclidean_distance
 export get_obs_var, length_states, length_obs_var
 export get_state_from_time, get_var_from_time, vectorize
 export isbounded, times, transitions
diff --git a/core/lha.jl b/core/lha.jl
index 6b9a0832264fc505375f380c8fa79816715302f3..a9d35de1e9ed37bbd6976af49cdd3c95b1df4a50 100644
--- a/core/lha.jl
+++ b/core/lha.jl
@@ -104,19 +104,19 @@ end
 function _find_edge_candidates!(edge_candidates::Vector{Edge},
                                 edges_from_current_loc::Dict{Location,Vector{Edge}},
                                 Λ::Dict{Location,Function},
-                                Snplus1::StateLHA, constants::Dict{Symbol,Float64}, 
+                                Snplus1::StateLHA,
                                 x::Vector{Int}, p::Vector{Float64},
                                 only_asynchronous::Bool)
     nbr_candidates = 0
     for target_loc in keys(edges_from_current_loc)
         for edge in edges_from_current_loc[target_loc]
-            if Λ[target_loc](x) && getfield(edge, :check_constraints)(Snplus1, constants, x, p)
-                if edge.transitions[1] == nothing
+            if Λ[target_loc](x) && getfield(edge, :check_constraints)(Snplus1, x, p)
+                if getfield(edge, :transitions)[1] == nothing
                     _push_edge!(edge_candidates, edge, nbr_candidates)
                     nbr_candidates += 1
                     return nbr_candidates
                 end
-                if !only_asynchronous && edge.transitions[1] != nothing
+                if !only_asynchronous && getfield(edge, :transitions)[1] != nothing
                     _push_edge!(edge_candidates, edge, nbr_candidates)
                     nbr_candidates += 1
                 end
@@ -133,13 +133,13 @@ function _get_edge_index(edge_candidates::Vector{Edge}, nbr_candidates::Int,
     for i = 1:nbr_candidates
         edge = edge_candidates[i]
         # Asynchronous edge detection: we fire it
-        if edge.transitions[1] == nothing 
+        if getfield(edge, :transitions)[1] == nothing 
             return (i, bool_event)
         end
         # Synchronous detection
         if !detected_event && tr_nplus1 != nothing
-            if (edge.transitions[1] == :ALL) || 
-               (tr_nplus1 in edge.transitions)
+            if (getfield(edge, :transitions)[1] == :ALL) || 
+                (tr_nplus1 in getfield(edge, :transitions))
                 ind_edge = i
                 bool_event = true
             end
@@ -163,7 +163,6 @@ function next_state!(Snplus1::StateLHA, A::LHA,
         @show Sn 
         @show Snplus1 
     end
-    constants = getfield(A, :constants) 
     # In terms of values not reference, Snplus1 == Sn
     # First, we check the asynchronous transitions
     while first_round || length(edge_candidates) > 0
@@ -172,14 +171,14 @@ function next_state!(Snplus1::StateLHA, A::LHA,
         current_loc = getfield(Snplus1, :loc)
         edges_from_current_loc = getfield(A, :map_edges)[current_loc]
         # Save all edges that satisfies transition predicate (asynchronous ones)
-        nbr_candidates = _find_edge_candidates!(edge_candidates, edges_from_current_loc, getfield(A, :Λ), Snplus1, constants, xn, p, true)
+        nbr_candidates = _find_edge_candidates!(edge_candidates, edges_from_current_loc, getfield(A, :Λ), Sn, xn, p, true) #Snplus1=>Sn
         # Search the one we must chose, here the event is nothing because 
         # we're not processing yet the next event
         ind_edge, detected_event = _get_edge_index(edge_candidates, nbr_candidates, detected_event, nothing)
         # Update the state with the chosen one (if it exists)
         # Should be xn here
         if ind_edge > 0
-            getfield(edge_candidates[ind_edge], :update_state!)(Snplus1, constants, xn, p)
+            getfield(edge_candidates[ind_edge], :update_state!)(Snplus1, xn, p)
         end
         first_round = false
         if verbose
@@ -193,6 +192,7 @@ function next_state!(Snplus1::StateLHA, A::LHA,
             break 
         end
         # For debug
+        #=
         if turns > 100
             println("Number of turns in next_state! is suspicious")
             @show first_round, detected_event
@@ -200,10 +200,11 @@ function next_state!(Snplus1::StateLHA, A::LHA,
             @show tnplus1, tr_nplus1, xnplus1
             @show edge_candidates
             for edge in edge_candidates
-                @show getfield(edge, :check_constraints)(Snplus1, constants, x, p)
+                @show getfield(edge, :check_constraints)(Snplus1, xn, p)
             end
             error("Unpredicted behavior automaton")
         end
+        =#
     end
     if verbose 
         @show Snplus1 
@@ -227,7 +228,7 @@ function next_state!(Snplus1::StateLHA, A::LHA,
         current_loc = getfield(Snplus1, :loc)
         edges_from_current_loc = getfield(A, :map_edges)[current_loc]
         # Save all edges that satisfies transition predicate (synchronous ones)
-        nbr_candidates = _find_edge_candidates!(edge_candidates, edges_from_current_loc, getfield(A, :Λ), Snplus1, constants, xnplus1, p, false)
+        nbr_candidates = _find_edge_candidates!(edge_candidates, edges_from_current_loc, getfield(A, :Λ), Snplus1, xnplus1, p, false)
         # Search the one we must chose
         ind_edge, detected_event = _get_edge_index(edge_candidates, nbr_candidates, detected_event, tr_nplus1)
         # Update the state with the chosen one (if it exists)
@@ -237,7 +238,7 @@ function next_state!(Snplus1::StateLHA, A::LHA,
             @show ind_edge, detected_event, nbr_candidates
         end
         if ind_edge > 0
-            getfield(edge_candidates[ind_edge], :update_state!)(Snplus1, constants, xnplus1, p)
+            getfield(edge_candidates[ind_edge], :update_state!)(Snplus1, xnplus1, p)
         end
         first_round = false
         if verbose
@@ -249,6 +250,7 @@ function next_state!(Snplus1::StateLHA, A::LHA,
             break 
         end
         # For debug
+        #=
         if turns > 100
             println("Number of turns in next_state! is suspicious")
             @show detected_event
@@ -256,10 +258,11 @@ function next_state!(Snplus1::StateLHA, A::LHA,
             @show tnplus1, tr_nplus1, xnplus1
             @show edge_candidates
             for edge in edge_candidates
-                @show getfield(edge, :check_constraints)(Snplus1, constants, x, p)
+                @show getfield(edge, :check_constraints)(Snplus1, x, p)
             end
             error("Unpredicted behavior automaton")
         end
+        =#
     end
     if verbose println("##### End next_state!") end
 end
diff --git a/core/model.jl b/core/model.jl
index c636424edc0f93a9dde2741eda4fcbd13a81ffed..4e2a797dcdcf52a97a8afbd368aaebe47d3b4247 100644
--- a/core/model.jl
+++ b/core/model.jl
@@ -295,7 +295,6 @@ function volatile_simulate(product::SynchronizedModel;
         getfield(m, :f!)(vec_x, l_t, l_tr, xn, tn, p_sim)
         if l_t[1] > time_bound
             tn = l_t[1]
-            i -= 1
             break
         end
         if vec_x == xn
diff --git a/core/trajectory.jl b/core/trajectory.jl
index c875281d863a853c07f48fc97385cddafbda73eb..f2ec60c602ecda285ec157f58193bfa68c886031 100644
--- a/core/trajectory.jl
+++ b/core/trajectory.jl
@@ -1,4 +1,6 @@
 
+## About distances
+
 # Top-level Lp distance function
 """
 `dist_lp(l_σ1, l_σ2; verbose, p, str_stat_list, str_stat_trajectory)`   
@@ -68,6 +70,7 @@ function dist_lp(x_obs::Vector{Int}, t_x::Vector{Float64}, y_obs::Vector{Int}, t
                  verbose::Bool = false, p::Int = 1)
     current_y_obs = y_obs[1]
     current_t_y = t_y[2]
+    nbr_y_obs = length(y_obs)
     idx = 1
     res = 0.0
     for i = 1:(length(x_obs)-1)
@@ -78,7 +81,7 @@ function dist_lp(x_obs::Vector{Int}, t_x::Vector{Float64}, y_obs::Vector{Int}, t
             @show t_x[i+1]
         end
         last_t_y = t_x[i]
-        while current_t_y < t_x[i+1]
+        while current_t_y < t_x[i+1] && idx <= nbr_y_obs
             rect =  abs(current_y_obs - x_obs[i])^p * (current_t_y - last_t_y)
             res += rect
             if verbose
@@ -172,6 +175,13 @@ function vectorize(σ::AbstractTrajectory, sym_var::Symbol,
     return trajectory_points
 end
 
+function euclidean_distance(σ::AbstractTrajectory, sym_obs::Symbol,
+                            tml::AbstractVector{Float64}, observations::AbstractVector{Float64})
+    traj_obs = vectorize(σ, sym_obs, tml)
+    diff_obs = observations - traj_obs
+    return sqrt(dot(diff_obs, diff_obs))
+end
+
 function check_consistency(σ::AbstractTrajectory)
     test_length_var = true
     for i = 1:σ.m.dim_obs_state 
diff --git a/tests/automata/euclidean_distance.jl b/tests/automata/euclidean_distance.jl
new file mode 100644
index 0000000000000000000000000000000000000000..2f0cc1fd592079be162763b200b02543007f47e7
--- /dev/null
+++ b/tests/automata/euclidean_distance.jl
@@ -0,0 +1,42 @@
+
+using MarkovProcesses
+import LinearAlgebra: dot
+import Distributions: Uniform
+
+load_automaton("euclidean_distance_automaton")
+load_model("SIR")
+load_model("ER")
+
+test_all = true
+
+# SIR model
+nbr_sim = 10
+for i = 1:nbr_sim
+    set_param!(SIR, [:ki, :kr], [rand(Uniform(5E-5, 3E-3)), rand(Uniform(5E-3, 0.2))]) 
+    let tml_obs, y_obs, sync_SIR, σ, test
+        tml_obs = rand(Uniform(0.0, 5.0)):1.0:rand(Uniform(50.0, 100.0))
+        y_obs = vectorize(simulate(SIR), :I, tml_obs)
+        sync_SIR = SIR * create_euclidean_distance_automaton(SIR, tml_obs, y_obs, :I)
+        σ = simulate(sync_SIR)
+        test = euclidean_distance(σ, :I, tml_obs, y_obs) == σ.state_lha_end[:d]
+        #@show test, euclidean_distance(σ, tml_obs, y_obs, :I), σ.state_lha_end[:d]
+        global test_all = test_all && test
+    end
+end
+
+# ER model
+for i = 1:nbr_sim
+    let tml_obs, y_obs, sync_SIR, σ, test
+        set_param!(ER, :k3, rand(Uniform(0.0, 100.0))) 
+        tml_obs = rand(Uniform(0.0, 0.2)):1.0:rand(Uniform(0.5,10.0))
+        y_obs = vectorize(simulate(ER), :P, tml_obs)
+        sync_ER = ER * create_euclidean_distance_automaton(ER, tml_obs, y_obs, :P)
+        σ = simulate(sync_ER)
+        test = euclidean_distance(σ, :P, tml_obs, y_obs) == σ.state_lha_end[:d]
+        #@show test, euclidean_distance(σ, tml_obs, y_obs, :P), σ.state_lha_end[:d]
+        global test_all = test_all && test
+    end
+end
+
+return test_all
+
diff --git a/tests/automata/euclidean_distance_single.jl b/tests/automata/euclidean_distance_single.jl
new file mode 100644
index 0000000000000000000000000000000000000000..237ed3de3209c8f01166526f7af317e1e977ea7b
--- /dev/null
+++ b/tests/automata/euclidean_distance_single.jl
@@ -0,0 +1,17 @@
+
+using MarkovProcesses
+import LinearAlgebra: dot
+import Distributions: Uniform
+
+load_automaton("euclidean_distance_automaton")
+load_model("SIR")
+tml_obs = 0:0.5:200
+set_time_bound!(SIR, 200.0)
+y_obs = vectorize(simulate(SIR), :I, tml_obs)
+sync_SIR = SIR * create_euclidean_distance_automaton(SIR, tml_obs, y_obs, :I)
+σ = simulate(sync_SIR)
+test = euclidean_distance(σ, tml_obs, y_obs, :I) == σ.state_lha_end[:d]
+@show test, euclidean_distance(σ, tml_obs, y_obs, :I), σ.state_lha_end[:d]
+
+return test
+
diff --git a/tests/run_automata.jl b/tests/run_automata.jl
index 9046876a1581dc8778ea9eac9b02709e499e4e2f..0d029fd824aa30ef31729410e550174ab2aad006 100644
--- a/tests/run_automata.jl
+++ b/tests/run_automata.jl
@@ -4,6 +4,8 @@ using Test
 @testset "Automata tests" begin
     @test include("automata/absorbing_x0_p.jl")
     @test include("automata/accept_R5.jl")
+    @test include("automata/euclidean_distance.jl")
+    @test include("automata/euclidean_distance_single.jl")
     @test include("automata/read_trajectory_last_state_F.jl")
     @test include("automata/read_trajectory_last_state_G.jl")
     @test include("automata/sync_simulate_last_state_F.jl")