diff --git a/automata/automaton_F.jl b/automata/automaton_F.jl
index 75bb98103efa34205d537c259ede3b85d703b2b8..5fa594b47dd5eb1664b44e8a8ace954bf3329a19 100644
--- a/automata/automaton_F.jl
+++ b/automata/automaton_F.jl
@@ -1,6 +1,11 @@
 
 # Creation of the automaton types
-@everywhere @eval abstract type EdgeAutomatonF <: Edge end
+#@everywhere @eval abstract type EdgeAutomatonF <: Edge end
+@everywhere struct EdgeAutomatonF <: Edge 
+    transitions::TransitionSet 
+    check_constraints::CheckConstraintsFunction
+    update_state!::UpdateStateFunction
+end
 @everywhere @eval $(MarkovProcesses.generate_code_lha_type_def(:AutomatonF, :EdgeAutomatonF))
 
 function create_automaton_F(m::ContinuousTimeModel, x1::Float64, x2::Float64, t1::Float64, t2::Float64, sym_obs::VariableModel)
@@ -46,78 +51,85 @@ function create_automaton_F(m::ContinuousTimeModel, x1::Float64, x2::Float64, t1
     basename_func = "$(model_name)_$(id)"
     edge_name(from_loc::Location, to_loc::Location, edge_number::Int) = 
     Symbol("Edge_$(lha_name)_$(basename_func)_$(from_loc)$(to_loc)_$(edge_number)")
+    function check_constraints(from_loc::Location, to_loc::Location, edge_number::Int)
+        return Symbol("check_constraints_$(edge_type)_$(from_loc)$(to_loc)_$(edge_number)_$(model_name)_$(id)")
+    end
+    function update_state!(from_loc::Location, to_loc::Location, edge_number::Int)
+        return Symbol("update_state_$(edge_type)_$(from_loc)$(to_loc)_$(edge_number)_$(model_name)_$(id)!")
+    end
 
     ## check_constraints & update_state!
-    @everywhere @eval begin
-        istrue(val::Float64) = convert(Bool, val)
+    meta_funcs = 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
-        struct $(edge_name(:l0, :l1, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(edge_name(:l0, :l1, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = true
-        $(update_state!)(edge::$(edge_name(:l0, :l1, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l0, :l1, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
+        @everywhere $(check_constraints(:l0, :l1, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = true
+        @everywhere $(update_state!(:l0, :l1, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_values[$(to_idx(:n))] = x[$(idx_obs_var)];
          S_values[$(to_idx(:d))] = Inf; 
          S_values[$(to_idx(:isabs))] = $(m.isabsorbing)(p,x);
          :l1)
         # l1 loc
         # l1 => l2
-        struct $(edge_name(:l1, :l2, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(edge_name(:l1, :l2, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l1, :l2, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
+        @everywhere $(check_constraints(:l1, :l2, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         S_time >= $t1 &&
         S_values[$(to_idx(:d))] == 0 
-        $(update_state!)(edge::$(edge_name(:l1, :l2, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        @everywhere $(update_state!(:l1, :l2, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (:l2)
 
-        struct $(edge_name(:l1, :l2, 2)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(edge_name(:l1, :l2, 2)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l1, :l2, 2)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
+        @everywhere $(check_constraints(:l1, :l2, 2))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_time >= $t2) && 
         (S_values[$(to_idx(:n))] < $x1 || S_values[$(to_idx(:n))] > $x2)
-        $(update_state!)(edge::$(edge_name(:l1, :l2, 2)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        @everywhere $(update_state!(:l1, :l2, 2))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (:l2;)
         #setindex!(S_values, min(abs(S_values[$(to_idx(:n))] - $x1), abs(S_values[$(to_idx(:n))] - $x2)), $(to_idx(:d))))
 
         # l1 => l3
-        struct $(edge_name(:l1, :l3, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(edge_name(:l1, :l3, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l1, :l3, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
+        @everywhere $(check_constraints(:l1, :l3, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_time <= $t1) &&
         (S_values[$(to_idx(:n))] < $x1 || S_values[$(to_idx(:n))] > $x2)
-        $(update_state!)(edge::$(edge_name(:l1, :l3, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        @everywhere $(update_state!(:l1, :l3, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_values[$(to_idx(:d))] = min(sqrt((S_time - $t1)^2 + (S_values[$(to_idx(:n))] - $x2)^2), 
                                        sqrt((S_time - $t1)^2 + (S_values[$(to_idx(:n))] - $x1)^2));
          :l3)        
-        struct $(edge_name(:l1, :l3, 2)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(edge_name(:l1, :l3, 2)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l1, :l3, 2)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
+        @everywhere $(check_constraints(:l1, :l3, 2))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         ($x1 <= S_values[$(to_idx(:n))] <= $x2)
-        $(update_state!)(edge::$(edge_name(:l1, :l3, 2)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        @everywhere $(update_state!(:l1, :l3, 2))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_values[$(to_idx(:d))] = 0;
          :l3)
-        struct $(edge_name(:l1, :l3, 3)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(edge_name(:l1, :l3, 3)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l1, :l3, 3)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
+        @everywhere $(check_constraints(:l1, :l3, 3))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_time >= $t1) &&
         (S_values[$(to_idx(:n))] < $x1 || S_values[$(to_idx(:n))] > $x2)
-        $(update_state!)(edge::$(edge_name(:l1, :l3, 3)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        @everywhere $(update_state!(:l1, :l3, 3))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (val_min = min(S_values[$(to_idx(:d))], 
                        min(abs(S_values[$(to_idx(:n))] - $x1), abs(S_values[$(to_idx(:n))] - $x2)));
          S_values[$(to_idx(:d))] = val_min;
          :l3)
         # l3 loc
         # l3 => l1
-        struct $(edge_name(:l3, :l1, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(edge_name(:l3, :l1, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = true
-        $(update_state!)(edge::$(edge_name(:l3, :l1, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l3, :l1, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
+        @everywhere $(check_constraints(:l3, :l1, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = true
+        @everywhere $(update_state!(:l3, :l1, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_values[$(to_idx(:n))] = x[$(idx_obs_var)];
          S_values[$(to_idx(:isabs))] = $(m.isabsorbing)(p,x);
          :l1)
         # l3 => l2
-        struct $(edge_name(:l3, :l2, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(edge_name(:l3, :l2, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l3, :l2, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
+        @everywhere $(check_constraints(:l3, :l2, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_time >= $t2 || istrue(S_values[$(to_idx(:isabs))]))
-        $(update_state!)(edge::$(edge_name(:l3, :l2, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        @everywhere $(update_state!(:l3, :l2, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (:l2)
     end
+    eval(meta_funcs)
 
     @eval begin
         map_edges = Dict{Location, Dict{Location, Vector{$(edge_type)}}}()
@@ -127,46 +139,50 @@ function create_automaton_F(m::ContinuousTimeModel, x1::Float64, x2::Float64, t1
 
         # l0 loc
         # l0 => l1
-        edge1 = $(edge_name(:l0, :l1, 1))(nothing)
+        edge1 = EdgeAutomatonF(nothing, $(check_constraints(:l0, :l1, 1)), $(update_state!(:l0, :l1, 1)))
         map_edges[:l0][:l1] = [edge1]
 
         # l1 loc
         # l1 => l2
-        edge1 = $(edge_name(:l1, :l2, 1))(nothing)
-        edge2 = $(edge_name(:l1, :l2, 2))(nothing)
+        edge1 = EdgeAutomatonF(nothing, $(check_constraints(:l1, :l2, 1)), $(update_state!(:l1, :l2, 1)))
+        edge2 = EdgeAutomatonF(nothing, $(check_constraints(:l1, :l2, 2)), $(update_state!(:l1, :l2, 2)))
         map_edges[:l1][:l2] = [edge1, edge2]
-        #edge3 = $(edge_name(:l1, :l2, 3))(nothing)
-        #edge4 = $(edge_name(:l1, :l2, 4))(nothing)
+        #edge3 = EdgeAutomatonF(nothing, $(check_constraints(:l1, :l2, 3)), $(update_state!(:l1, :l2, 3)))
+        #edge4 = EdgeAutomatonF(nothing, $(check_constraints(:l1, :l2, 4)), $(update_state!(:l1, :l2, 4)))
         #map_edges[:l1][:l2] = [edge1, edge2, edge3, edge4]
 
         # l1 => l3
-        edge1 = $(edge_name(:l1, :l3, 1))(nothing)
-        edge2 = $(edge_name(:l1, :l3, 2))(nothing)
-        edge3 = $(edge_name(:l1, :l3, 3))(nothing)
+        edge1 = EdgeAutomatonF(nothing, $(check_constraints(:l1, :l3, 1)), $(update_state!(:l1, :l3, 1)))
+        edge2 = EdgeAutomatonF(nothing, $(check_constraints(:l1, :l3, 2)), $(update_state!(:l1, :l3, 2)))
+        edge3 = EdgeAutomatonF(nothing, $(check_constraints(:l1, :l3, 3)), $(update_state!(:l1, :l3, 3)))
         map_edges[:l1][:l3] = [edge1, edge2, edge3]
 
         # l3 loc
         # l3 => l1
-        edge1 = $(edge_name(:l3, :l1, 1))([:ALL])
+        edge1 = EdgeAutomatonF([:ALL], $(check_constraints(:l3, :l1, 1)), $(update_state!(:l3, :l1, 1)))
         map_edges[:l3][:l1] = [edge1]
 
         # l3 => l2
-        edge1 = $(edge_name(:l3, :l2, 1))(nothing)
+        edge1 = EdgeAutomatonF(nothing, $(check_constraints(:l3, :l2, 1)), $(update_state!(:l3, :l2, 1)))
         map_edges[:l3][:l2] = [edge1]
     end
 
     ## Constants
     constants = Dict{Symbol,Float64}(:x1 => x1,  :x2 => x2, :t1 => t1, :t2 => t2)
 
+    map_edges_transitions = Dict{Symbol, Dict{Symbol,Vector{TransitionSet}}}()
+    map_edges_check_constraints = Dict{Symbol, Dict{Symbol,Vector{CheckConstraintsFunction}}}()
+    map_edges_update_state = Dict{Symbol, Dict{Symbol,Vector{UpdateStateFunction}}}()
+    
     # Updating types and simulation methods
     @everywhere @eval $(MarkovProcesses.generate_code_synchronized_model_type_def(model_name, lha_name))
-    @everywhere @eval $(MarkovProcesses.generate_code_next_state(lha_name, edge_type, check_constraints, update_state!))
+    @everywhere @eval $(MarkovProcesses.generate_code_next_state(lha_name, edge_type))
     @everywhere @eval $(MarkovProcesses.generate_code_synchronized_simulation(model_name, lha_name, edge_type, m.f!, m.isabsorbing))
     
     A = AutomatonF(m.transitions, locations, Λ_F, locations_init, locations_final, 
-                   map_var_automaton_idx, flow, map_edges, constants, m.map_var_idx)
+                   map_var_automaton_idx, flow, map_edges, 
+                   map_edges_transitions, map_edges_check_constraints, map_edges_update_state,
+                   constants, m.map_var_idx)
     return A
 end
 
-export create_automaton_F
-
diff --git a/automata/automaton_G.jl b/automata/automaton_G.jl
index 920e91a3b0a2ed2c3f24ce1df46ca01089eae2e9..35ae1822fb9ee747fb69451af192a9d5791c36e3 100644
--- a/automata/automaton_G.jl
+++ b/automata/automaton_G.jl
@@ -1,6 +1,11 @@
 
 # Creation of the automaton types
-@everywhere @eval abstract type EdgeAutomatonG <: Edge end
+#@everywhere @eval abstract type EdgeAutomatonG <: Edge end
+@everywhere struct EdgeAutomatonG <: Edge 
+    transitions::TransitionSet 
+    check_constraints::CheckConstraintsFunction
+    update_state!::UpdateStateFunction
+end
 @everywhere @eval $(MarkovProcesses.generate_code_lha_type_def(:AutomatonG, :EdgeAutomatonG))
 
 function create_automaton_G(m::ContinuousTimeModel, x1::Float64, x2::Float64, t1::Float64, t2::Float64, sym_obs::VariableModel)
@@ -47,15 +52,21 @@ function create_automaton_G(m::ContinuousTimeModel, x1::Float64, x2::Float64, t1
     basename_func = "$(model_name)_$(id)"
     edge_name(from_loc::Location, to_loc::Location, edge_number::Int) = 
     Symbol("Edge_$(lha_name)_$(basename_func)_$(from_loc)$(to_loc)_$(edge_number)")
+    function check_constraints(from_loc::Location, to_loc::Location, edge_number::Int)
+        return Symbol("check_constraints_$(edge_type)_$(from_loc)$(to_loc)_$(edge_number)_$(model_name)_$(id)")
+    end
+    function update_state!(from_loc::Location, to_loc::Location, edge_number::Int)
+        return Symbol("update_state_$(edge_type)_$(from_loc)$(to_loc)_$(edge_number)_$(model_name)_$(id)!")
+    end
 
     ## check_constraints & update_state!
-    @everywhere @eval begin
-        istrue(val::Float64) = convert(Bool, val)
+    meta_funcs = quote
+        @everywhere istrue(val::Float64) = convert(Bool, val)
         # l0 loc
         # l0 => l1
-        struct $(edge_name(:l0, :l1, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(edge_name(:l0, :l1, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = true
-        $(update_state!)(edge::$(edge_name(:l0, :l1, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l0, :l1, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
+        @everywhere $(check_constraints(:l0, :l1, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = true
+        @everywhere $(update_state!(:l0, :l1, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_values[$(to_idx(:d))] = 0;
          S_values[$(to_idx(:n))] = x[$(idx_obs_var)];
          S_values[$(to_idx(:in))] = true;
@@ -63,107 +74,107 @@ function create_automaton_G(m::ContinuousTimeModel, x1::Float64, x2::Float64, t1
          :l1)
 
         # l1 => l3
-        struct $(edge_name(:l1, :l3, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(edge_name(:l1, :l3, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l1, :l3, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
+        @everywhere $(check_constraints(:l1, :l3, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         S_time <= $t1 && 
         S_values[$(to_idx(:n))] < $x1 || S_values[$(to_idx(:n))] > $x2
-        $(update_state!)(edge::$(edge_name(:l1, :l3, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        @everywhere $(update_state!(:l1, :l3, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_values[$(to_idx(:d))] = min(abs($x1 - S_values[$(to_idx(:n))]), abs($x2 - S_values[$(to_idx(:n))]));
          S_values[$(to_idx(:in))] = false;
          :l3)
 
-        struct $(edge_name(:l1, :l3, 2)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(edge_name(:l1, :l3, 2)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l1, :l3, 2)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
+        @everywhere $(check_constraints(:l1, :l3, 2))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_time <= $t1) && 
         ($x1 <= S_values[$(to_idx(:n))] <= $x2)
-        $(update_state!)(edge::$(edge_name(:l1, :l3, 2)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        @everywhere $(update_state!(:l1, :l3, 2))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_values[$(to_idx(:d))] = 0;
          S_values[$(to_idx(:in))] = false;
          :l3)
 
-        struct $(edge_name(:l1, :l3, 3)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(edge_name(:l1, :l3, 3)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l1, :l3, 3)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
+        @everywhere $(check_constraints(:l1, :l3, 3))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         !istrue(S_values[$(to_idx(:in))]) && 
         ($t1 <= S_time <= $t2) && 
         ($x1 <= S_values[$(to_idx(:n))] <= $x2)
-        $(update_state!)(edge::$(edge_name(:l1, :l3, 3)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        @everywhere $(update_state!(:l1, :l3, 3))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_values[$(to_idx(:d))] = S_values[$(to_idx(:d))] * (S_time - $t1);
          S_values[$(to_idx(:tprime))] = 0.0;
          :l3)
 
-        struct $(edge_name(:l1, :l3, 4)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(edge_name(:l1, :l3, 4)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l1, :l3, 4)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
+        @everywhere $(check_constraints(:l1, :l3, 4))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         istrue(S_values[$(to_idx(:in))]) && 
         ($t1 <= S_time <= $t2) && 
         ($x1 <= S_values[$(to_idx(:n))] <= $x2)
-        $(update_state!)(edge::$(edge_name(:l1, :l3, 4)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        @everywhere $(update_state!(:l1, :l3, 4))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_values[$(to_idx(:tprime))] = 0.0;
          :l3)
 
         # l1 => l4
-        struct $(edge_name(:l1, :l4, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(edge_name(:l1, :l4, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l1, :l4, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
+        @everywhere $(check_constraints(:l1, :l4, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         !istrue(S_values[$(to_idx(:in))]) && 
         ($t1 <= S_time <= $t2) && 
         (S_values[$(to_idx(:n))] < $x1 || S_values[$(to_idx(:n))] > $x2)
-        $(update_state!)(edge::$(edge_name(:l1, :l4, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        @everywhere $(update_state!(:l1, :l4, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_values[$(to_idx(:d))] = S_values[$(to_idx(:d))] + S_values[$(to_idx(:d))] * (S_time - $t1);
          :l4)
 
-        struct $(edge_name(:l1, :l4, 2)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(edge_name(:l1, :l4, 2)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l1, :l4, 2)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
+        @everywhere $(check_constraints(:l1, :l4, 2))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         istrue(S_values[$(to_idx(:in))]) && 
         ($t1 <= S_time <= $t2) && 
         (S_values[$(to_idx(:n))] < $x1 || S_values[$(to_idx(:n))] > $x2)
-        $(update_state!)(edge::$(edge_name(:l1, :l4, 2)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        @everywhere $(update_state!(:l1, :l4, 2))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (:l4)
 
         # l1 => l2
         #=
-        struct $(edge_name(:l1, :l2, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(edge_name(:l1, :l2, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l1, :l2, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
+        @everywhere $(check_constraints(:l1, :l2, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         istrue(S_values[$(to_idx(:in))]) && 
         S_time >= $t2
-        $(update_state!)(edge::$(edge_name(:l1, :l2, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        @everywhere $(update_state!(:l1, :l2, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (:l2)
 
-        struct $(edge_name(:l1, :l2, 2)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(edge_name(:l1, :l2, 2)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l1, :l2, 2)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
+        @everywhere $(check_constraints(:l1, :l2, 2))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         !istrue(S_values[$(to_idx(:in))]) && 
         S_time >= $t2
-        $(update_state!)(edge::$(edge_name(:l1, :l2, 2)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        @everywhere $(update_state!(:l1, :l2, 2))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_values[$(to_idx(:d))] = S_values[$(to_idx(:d))] * ($t2 - $t1);
         :l2)
 
-        struct $(edge_name(:l1, :l2, 3)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(edge_name(:l1, :l2, 3)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l1, :l2, 3)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
+        @everywhere $(check_constraints(:l1, :l2, 3))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         istrue(S_values[$(to_idx(:isabs))]) && 
         S_time <= $t1
-        $(update_state!)(edge::$(edge_name(:l1, :l2, 3)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        @everywhere $(update_state!(:l1, :l2, 3))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_values[$(to_idx(:d))] = ($t2 - $t1) * min(abs($x1 - S_values[$(to_idx(:n))]), abs($x2 - S_values[$(to_idx(:n))]));
         :l2)
 
-        struct $(edge_name(:l1, :l2, 4)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(edge_name(:l1, :l2, 4)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l1, :l2, 4)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
+        @everywhere $(check_constraints(:l1, :l2, 4))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         istrue(S_values[$(to_idx(:isabs))]) && 
         ($t1 <= S_time <= $t2)
-        $(update_state!)(edge::$(edge_name(:l1, :l2, 4)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        @everywhere $(update_state!(:l1, :l2, 4))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_values[$(to_idx(:d))] = S_values[$(to_idx(:d))] + ($t2 - S_time) * min(abs($x1 - S_values[$(to_idx(:n))]), abs($x2 - S_values[$(to_idx(:n))]));
         :l2)
         =#
 
         # l3 => l1
-        struct $(edge_name(:l3, :l1, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(edge_name(:l3, :l1, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = true
-        $(update_state!)(edge::$(edge_name(:l3, :l1, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l3, :l1, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
+        @everywhere $(check_constraints(:l3, :l1, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = true
+        @everywhere $(update_state!(:l3, :l1, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_values[$(to_idx(:n))] = x[$(idx_obs_var)];
          S_values[$(to_idx(:isabs))] = $(m.isabsorbing)(p, x);
          :l1)
 
         # l4 => l1
-        struct $(edge_name(:l4, :l1, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(edge_name(:l4, :l1, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = true
-        $(update_state!)(edge::$(edge_name(:l4, :l1, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l4, :l1, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
+        @everywhere $(check_constraints(:l4, :l1, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = true
+        @everywhere $(update_state!(:l4, :l1, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_values[$(to_idx(:d))] = S_values[$(to_idx(:d))] + S_values[$(to_idx(:tprime))] * min(abs($x1 - S_values[$(to_idx(:n))]), abs($x2 - S_values[$(to_idx(:n))]));
          S_values[$(to_idx(:tprime))] = 0.0;
          S_values[$(to_idx(:n))] = x[$(idx_obs_var)];
@@ -172,39 +183,39 @@ function create_automaton_G(m::ContinuousTimeModel, x1::Float64, x2::Float64, t1
          :l1)
 
         # l3 => l2
-        struct $(edge_name(:l3, :l2, 2)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(edge_name(:l3, :l2, 2)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l3, :l2, 2)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
+        @everywhere $(check_constraints(:l3, :l2, 2))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         istrue(S_values[$(to_idx(:in))]) && 
         (S_time >= $t2 || istrue(S_values[$(to_idx(:isabs))]))
-        $(update_state!)(edge::$(edge_name(:l3, :l2, 2)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        @everywhere $(update_state!(:l3, :l2, 2))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_values[$(to_idx(:d))] = S_values[$(to_idx(:d))] * ($t2 - $t1);
          :l2)
 
-        struct $(edge_name(:l3, :l2, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(edge_name(:l3, :l2, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l3, :l2, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
+        @everywhere $(check_constraints(:l3, :l2, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         !istrue(S_values[$(to_idx(:in))]) && 
         (S_time >= $t2 || istrue(S_values[$(to_idx(:isabs))]))
-        $(update_state!)(edge::$(edge_name(:l3, :l2, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        @everywhere $(update_state!(:l3, :l2, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (:l2)
 
         # l4 => l2
-        struct $(edge_name(:l4, :l2, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(edge_name(:l4, :l2, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l4, :l2, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
+        @everywhere $(check_constraints(:l4, :l2, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (istrue(S_values[$(to_idx(:isabs))]))
-        $(update_state!)(edge::$(edge_name(:l4, :l2, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        @everywhere $(update_state!(:l4, :l2, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_values[$(to_idx(:d))] = S_values[$(to_idx(:d))] + ($t2 - S_time) * min(abs($x1 - S_values[$(to_idx(:n))]), abs($x2 - S_values[$(to_idx(:n))]));
          S_values[$(to_idx(:tprime))] = 0.0;
          :l2)
 
-        struct $(edge_name(:l4, :l2, 2)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(edge_name(:l4, :l2, 2)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l4, :l2, 2)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
+        @everywhere $(check_constraints(:l4, :l2, 2))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_time >= $t2)
-        $(update_state!)(edge::$(edge_name(:l4, :l2, 2)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        @everywhere $(update_state!(:l4, :l2, 2))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_values[$(to_idx(:d))] = S_values[$(to_idx(:d))] + S_values[$(to_idx(:tprime))] * min(abs($x1 - S_values[$(to_idx(:n))]), abs($x2 - S_values[$(to_idx(:n))]));
          S_values[$(to_idx(:tprime))] = 0.0;
          :l2)
-
     end
+    eval(meta_funcs)
 
     @eval begin
         map_edges = Dict{Location, Dict{Location, Vector{$(edge_type)}}}()
@@ -214,62 +225,69 @@ function create_automaton_G(m::ContinuousTimeModel, x1::Float64, x2::Float64, t1
 
         # l0 loc
         # l0 => l1
-        edge1 = $(edge_name(:l0, :l1, 1))(nothing)
+        edge1 = EdgeAutomatonG(nothing, $(check_constraints(:l0, :l1, 1)), $(update_state!(:l0, :l1, 1)))
         map_edges[:l0][:l1] = [edge1]
 
         # l1 loc
         # l1 => l3
-        edge1 = $(edge_name(:l1, :l3, 1))(nothing)
-        edge2 = $(edge_name(:l1, :l3, 2))(nothing)
-        edge3 = $(edge_name(:l1, :l3, 3))(nothing)
-        edge4 = $(edge_name(:l1, :l3, 4))(nothing)
+        edge1 = EdgeAutomatonG(nothing, $(check_constraints(:l1, :l3, 1)), $(update_state!(:l1, :l3, 1)))
+        edge2 = EdgeAutomatonG(nothing, $(check_constraints(:l1, :l3, 2)), $(update_state!(:l1, :l3, 2)))
+        edge3 = EdgeAutomatonG(nothing, $(check_constraints(:l1, :l3, 3)), $(update_state!(:l1, :l3, 3)))
+        edge4 = EdgeAutomatonG(nothing, $(check_constraints(:l1, :l3, 4)), $(update_state!(:l1, :l3, 4)))
         map_edges[:l1][:l3] = [edge1, edge2, edge3, edge4]
 
         # l1 => l4
-        edge1 = $(edge_name(:l1, :l4, 1))(nothing)
-        edge2 = $(edge_name(:l1, :l4, 2))(nothing)
+        edge1 = EdgeAutomatonG(nothing, $(check_constraints(:l1, :l4, 1)), $(update_state!(:l1, :l4, 1)))
+        edge2 = EdgeAutomatonG(nothing, $(check_constraints(:l1, :l4, 2)), $(update_state!(:l1, :l4, 2)))
         map_edges[:l1][:l4] = [edge1, edge2]
 
         # l1 => l2
         #=
-        edge1 = $(edge_name(:l1, :l2, 1))(nothing)
-        edge2 = $(edge_name(:l1, :l2, 2))(nothing)
-        edge3 = $(edge_name(:l1, :l2, 3))(nothing)
-        edge4 = $(edge_name(:l1, :l2, 4))(nothing)
+        edge1 = EdgeAutomatonG(nothing, $(check_constraints(:l1, :l2, 1)), $(update_state!(:l1, :l2, 1)))
+        edge2 = EdgeAutomatonG(nothing, $(check_constraints(:l1, :l2, 2)), $(update_state!(:l1, :l2, 2)))
+        edge3 = EdgeAutomatonG(nothing, $(check_constraints(:l1, :l2, 3)), $(update_state!(:l1, :l2, 3)))
+        edge4 = EdgeAutomatonG(nothing, $(check_constraints(:l1, :l2, 4)), $(update_state!(:l1, :l2, 4)))
         map_edges[:l1][:l2] = [edge1, edge2, edge3, edge4]
         =#
 
         # l3 loc
         # l3 => l1
-        edge1 = $(edge_name(:l3, :l1, 1))([:ALL])
+        edge1 = EdgeAutomatonG([:ALL], $(check_constraints(:l3, :l1, 1)), $(update_state!(:l3, :l1, 1)))
         map_edges[:l3][:l1] = [edge1]
 
         # l3 => l2
-        edge1 = $(edge_name(:l3, :l2, 1))(nothing)
-        edge2 = $(edge_name(:l3, :l2, 2))(nothing)
+        edge1 = EdgeAutomatonG(nothing, $(check_constraints(:l3, :l2, 1)), $(update_state!(:l3, :l2, 1)))
+        edge2 = EdgeAutomatonG(nothing, $(check_constraints(:l3, :l2, 2)), $(update_state!(:l3, :l2, 2)))
         map_edges[:l3][:l2] = [edge1, edge2]
 
         # l4 loc
         # l4 => l1
-        edge1 = $(edge_name(:l4, :l1, 1))([:ALL])
+        edge1 = EdgeAutomatonG([:ALL], $(check_constraints(:l4, :l1, 1)), $(update_state!(:l4, :l1, 1)))
         map_edges[:l4][:l1] = [edge1]
 
         # l4 => l2
-        edge1 = $(edge_name(:l4, :l2, 1))(nothing)
-        edge2 = $(edge_name(:l4, :l2, 2))(nothing)
+        edge1 = EdgeAutomatonG(nothing, $(check_constraints(:l4, :l2, 1)), $(update_state!(:l4, :l2, 1)))
+        edge2 = EdgeAutomatonG(nothing, $(check_constraints(:l4, :l2, 2)), $(update_state!(:l4, :l2, 2)))
         map_edges[:l4][:l2] = [edge1,edge2]
     end
 
+    ## Create data separately
+    map_edges_transitions = Dict{Symbol, Dict{Symbol,Vector{TransitionSet}}}()
+    map_edges_check_constraints = Dict{Symbol, Dict{Symbol,Vector{CheckConstraintsFunction}}}()
+    map_edges_update_state = Dict{Symbol, Dict{Symbol,Vector{UpdateStateFunction}}}()
+    
     ## Constants
     constants = Dict{Symbol,Float64}(:x1 => x1,  :x2 => x2, :t1 => t1, :t2 => t2)
 
     # Updating types and simulation methods
     @everywhere @eval $(MarkovProcesses.generate_code_synchronized_model_type_def(model_name, lha_name))
-    @everywhere @eval $(MarkovProcesses.generate_code_next_state(lha_name, edge_type, check_constraints, update_state!))
+    @everywhere @eval $(MarkovProcesses.generate_code_next_state(lha_name, edge_type))
     @everywhere @eval $(MarkovProcesses.generate_code_synchronized_simulation(model_name, lha_name, edge_type, m.f!, m.isabsorbing))
 
     A = AutomatonG(m.transitions, locations, Λ_F, locations_init, locations_final, 
-                   map_var_automaton_idx, flow, map_edges, constants, m.map_var_idx)
+                   map_var_automaton_idx, flow, map_edges, 
+                   map_edges_transitions, map_edges_check_constraints, map_edges_update_state,
+                   constants, m.map_var_idx)
     return A
 
 end
diff --git a/automata/automaton_G_and_F.jl b/automata/automaton_G_and_F.jl
index ba05cabdd66c062687176f6d69d57c1c12d32697..6b8d6f94ff151866ea6c6039f7f2be2ebf19879a 100644
--- a/automata/automaton_G_and_F.jl
+++ b/automata/automaton_G_and_F.jl
@@ -1,7 +1,11 @@
 
 # Creation of the automaton types
 #@everywhere @eval abstract type EdgeAutomatonGandF <: Edge end
-@everywhere struct EdgeAutomatonGandF{T} <: Edge transitions::Union{Nothing,Vector{Symbol}} end
+@everywhere struct EdgeAutomatonGandF <: Edge 
+    transitions::TransitionSet 
+    check_constraints::CheckConstraintsFunction
+    update_state!::UpdateStateFunction
+end
 @everywhere @eval $(MarkovProcesses.generate_code_lha_type_def(:AutomatonGandF, :EdgeAutomatonGandF))
 
 function create_automaton_G_and_F(m::ContinuousTimeModel, x1::Float64, x2::Float64, t1::Float64, t2::Float64, sym_obs_G::VariableModel,
@@ -27,11 +31,11 @@ function create_automaton_G_and_F(m::ContinuousTimeModel, x1::Float64, x2::Float
 
     # 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),
-               :l1F => getfield(Main, :true_inv_predicate),
-               :l2F => getfield(Main, :true_inv_predicate), :l3F => getfield(Main, :true_inv_predicate))
+    Λ_F = Dict{Symbol,InvariantPredicateFunction}(: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),
+                                                  :l1F => getfield(Main, :true_inv_predicate),
+                                                  :l2F => getfield(Main, :true_inv_predicate), :l3F => getfield(Main, :true_inv_predicate))
 
     ## Init and final loc
     locations_init = [:l0G]
@@ -59,23 +63,26 @@ function create_automaton_G_and_F(m::ContinuousTimeModel, x1::Float64, x2::Float
 
     id = MarkovProcesses.newid()
     #Symbol("Edge_$(lha_name)_$(basename_func)_$(from_loc)$(to_loc)_$(edge_number)")
-    function generate_edge_type(from_loc::Location, to_loc::Location, edge_number::Int)
-        tag_type = Symbol("$(from_loc)$(to_loc)_$(edge_number)_$(model_name)_$(id)")
-        @eval type = EdgeAutomatonGandF{$(Meta.quot(tag_type))}
-        return @eval($type)
+    function edge_name(from_loc::Location, to_loc::Location, edge_number::Int)
+        return Symbol("$(edge_type)_$(from_loc)$(to_loc)_$(edge_number)_$(model_name)_$(id)")
+    end
+    function check_constraints(from_loc::Location, to_loc::Location, edge_number::Int)
+        return Symbol("check_constraints_$(edge_type)_$(from_loc)$(to_loc)_$(edge_number)_$(model_name)_$(id)")
+    end
+    function update_state!(from_loc::Location, to_loc::Location, edge_number::Int)
+        return Symbol("update_state_$(edge_type)_$(from_loc)$(to_loc)_$(edge_number)_$(model_name)_$(id)!")
     end
 
     ## check_constraints & update_state!
-    @everywhere @eval begin
-    #return quote
-        istrue(val::Float64) = convert(Bool, val)
+    meta_funcs = quote
+        @everywhere istrue(val::Float64) = convert(Bool, val)
         ## Edges check constraint and update state functions
 
         # l0G loc
         # l0G => l1G
-        #struct $(generate_edge_type(:l0G, :l1G, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(generate_edge_type(:l0G, :l1G, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = true
-        $(update_state!)(edge::$(generate_edge_type(:l0G, :l1G, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l0G, :l1G, 1)) <: $(edge_type) transitions::TransitionSet end
+        @everywhere $(check_constraints(:l0G, :l1G, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = true
+        @everywhere $(update_state!(:l0G, :l1G, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_values[$(to_idx(:d))] = 0;
          S_values[$(to_idx(:n))] = x[$(idx_obs_var_G)];
          S_values[$(to_idx(:in))] = true;
@@ -84,125 +91,125 @@ function create_automaton_G_and_F(m::ContinuousTimeModel, x1::Float64, x2::Float
 
         # l1G loc
         # l1G => l3G
-        #struct $(generate_edge_type(:l1G, :l3G, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(generate_edge_type(:l1G, :l3G, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l1G, :l3G, 1)) <: $(edge_type) transitions::TransitionSet end
+        @everywhere $(check_constraints(:l1G, :l3G, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         S_time <= $t1 && 
         S_values[$(to_idx(:n))] < $x1 || S_values[$(to_idx(:n))] > $x2
-        $(update_state!)(edge::$(generate_edge_type(:l1G, :l3G, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        @everywhere $(update_state!(:l1G, :l3G, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_values[$(to_idx(:d))] = min(abs($x1 - S_values[$(to_idx(:n))]), abs($x2 - S_values[$(to_idx(:n))]));
          S_values[$(to_idx(:in))] = false;
          :l3G)
 
-        #struct $(generate_edge_type(:l1G, :l3G, 2)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(generate_edge_type(:l1G, :l3G, 2)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l1G, :l3G, 2)) <: $(edge_type) transitions::TransitionSet end
+        @everywhere $(check_constraints(:l1G, :l3G, 2))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_time <= $t1) && 
         ($x1 <= S_values[$(to_idx(:n))] <= $x2)
-        $(update_state!)(edge::$(generate_edge_type(:l1G, :l3G, 2)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        @everywhere $(update_state!(:l1G, :l3G, 2))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_values[$(to_idx(:d))] = 0;
          S_values[$(to_idx(:in))] = false;
          :l3G)
 
-        #struct $(generate_edge_type(:l1G, :l3G, 3)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(generate_edge_type(:l1G, :l3G, 3)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l1G, :l3G, 3)) <: $(edge_type) transitions::TransitionSet end
+        @everywhere $(check_constraints(:l1G, :l3G, 3))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         !istrue(S_values[$(to_idx(:in))]) && 
         ($t1 <= S_time <= $t2) && 
         ($x1 <= S_values[$(to_idx(:n))] <= $x2)
-        $(update_state!)(edge::$(generate_edge_type(:l1G, :l3G, 3)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        @everywhere $(update_state!(:l1G, :l3G, 3))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_values[$(to_idx(:d))] = S_values[$(to_idx(:d))] * (S_time - $t1);
          S_values[$(to_idx(:tprime))] = 0.0;
          :l3G)
 
-        #struct $(generate_edge_type(:l1G, :l3G, 4)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(generate_edge_type(:l1G, :l3G, 4)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l1G, :l3G, 4)) <: $(edge_type) transitions::TransitionSet end
+        @everywhere $(check_constraints(:l1G, :l3G, 4))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         istrue(S_values[$(to_idx(:in))]) && 
         ($t1 <= S_time <= $t2) && 
         ($x1 <= S_values[$(to_idx(:n))] <= $x2)
-        $(update_state!)(edge::$(generate_edge_type(:l1G, :l3G, 4)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        @everywhere $(update_state!(:l1G, :l3G, 4))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_values[$(to_idx(:tprime))] = 0.0;
          :l3G)
 
         # l1G => l4G
-        #struct $(generate_edge_type(:l1G, :l4G, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(generate_edge_type(:l1G, :l4G, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l1G, :l4G, 1)) <: $(edge_type) transitions::TransitionSet end
+        @everywhere $(check_constraints(:l1G, :l4G, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         !istrue(S_values[$(to_idx(:in))]) && 
         ($t1 <= S_time <= $t2) && 
         (S_values[$(to_idx(:n))] < $x1 || S_values[$(to_idx(:n))] > $x2)
-        $(update_state!)(edge::$(generate_edge_type(:l1G, :l4G, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        @everywhere $(update_state!(:l1G, :l4G, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_values[$(to_idx(:d))] = S_values[$(to_idx(:d))] + S_values[$(to_idx(:d))] * (S_time - $t1);
          :l4G)
 
-        #struct $(generate_edge_type(:l1G, :l4G, 2)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(generate_edge_type(:l1G, :l4G, 2)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l1G, :l4G, 2)) <: $(edge_type) transitions::TransitionSet end
+        @everywhere $(check_constraints(:l1G, :l4G, 2))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         istrue(S_values[$(to_idx(:in))]) && 
         ($t1 <= S_time <= $t2) && 
         (S_values[$(to_idx(:n))] < $x1 || S_values[$(to_idx(:n))] > $x2)
-        $(update_state!)(edge::$(generate_edge_type(:l1G, :l4G, 2)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        @everywhere $(update_state!(:l1G, :l4G, 2))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (:l4G)
 
         # l1G => l2G
         #=
-        #struct $(generate_edge_type(:l1G, :l2G, 3)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(generate_edge_type(:l1G, :l2G, 3)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l1G, :l2G, 3)) <: $(edge_type) transitions::TransitionSet end
+        @everywhere $(check_constraints(:l1G, :l2G, 3))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         istrue(S_values[$(to_idx(:isabs))]) && 
         S_time <= $t1
-        $(update_state!)(edge::$(generate_edge_type(:l1G, :l2G, 3)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        @everywhere $(update_state!(:l1G, :l2G, 3))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_values[$(to_idx(:d))] = ($t2 - $t1) * min(abs($x1 - S_values[$(to_idx(:n))]), abs($x2 - S_values[$(to_idx(:n))]));
         :l2G)
 
-        #struct $(generate_edge_type(:l1G, :l2G, 4)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(generate_edge_type(:l1G, :l2G, 4)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l1G, :l2G, 4)) <: $(edge_type) transitions::TransitionSet end
+        @everywhere $(check_constraints(:l1G, :l2G, 4))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         istrue(S_values[$(to_idx(:isabs))]) && 
         ($t1 <= S_time <= $t2)
-        $(update_state!)(edge::$(generate_edge_type(:l1G, :l2G, 4)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        @everywhere $(update_state!(:l1G, :l2G, 4))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_values[$(to_idx(:d))] = S_values[$(to_idx(:d))] + ($t2 - S_time) * min(abs($x1 - S_values[$(to_idx(:n))]), abs($x2 - S_values[$(to_idx(:n))]));
         :l2G)
 
-        #struct $(generate_edge_type(:l1G, :l2G, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(generate_edge_type(:l1G, :l2G, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l1G, :l2G, 1)) <: $(edge_type) transitions::TransitionSet end
+        @everywhere $(check_constraints(:l1G, :l2G, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         istrue(S_values[$(to_idx(:in))]) && 
         S_time >= $t2
-        $(update_state!)(edge::$(generate_edge_type(:l1G, :l2G, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        @everywhere $(update_state!(:l1G, :l2G, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (:l2G)
 
-        #struct $(generate_edge_type(:l1G, :l2G, 2)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(generate_edge_type(:l1G, :l2G, 2)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l1G, :l2G, 2)) <: $(edge_type) transitions::TransitionSet end
+        @everywhere $(check_constraints(:l1G, :l2G, 2))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         !istrue(S_values[$(to_idx(:in))]) && 
         S_time >= $t2
-        $(update_state!)(edge::$(generate_edge_type(:l1G, :l2G, 2)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        @everywhere $(update_state!(:l1G, :l2G, 2))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_values[$(to_idx(:d))] = S_values[$(to_idx(:d))] * ($t2 - $t1);
         :l2G)
         =#
 
         # l3G loc
         # l3G => l1G
-        #struct $(generate_edge_type(:l3G, :l1G, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(generate_edge_type(:l3G, :l1G, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = true
-        $(update_state!)(edge::$(generate_edge_type(:l3G, :l1G, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l3G, :l1G, 1)) <: $(edge_type) transitions::TransitionSet end
+        @everywhere $(check_constraints(:l3G, :l1G, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = true
+        @everywhere $(update_state!(:l3G, :l1G, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_values[$(to_idx(:n))] = x[$(idx_obs_var_G)];
          S_values[$(to_idx(:isabs))] = $(m.isabsorbing)(p, x);
          :l1G)
 
         # l3G => l2G
-        #struct $(generate_edge_type(:l3G, :l2G, 2)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(generate_edge_type(:l3G, :l2G, 2)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l3G, :l2G, 2)) <: $(edge_type) transitions::TransitionSet end
+        @everywhere $(check_constraints(:l3G, :l2G, 2))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         istrue(S_values[$(to_idx(:in))]) && 
         (S_time >= $t2 || istrue(S_values[$(to_idx(:isabs))]))
-        $(update_state!)(edge::$(generate_edge_type(:l3G, :l2G, 2)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        @everywhere $(update_state!(:l3G, :l2G, 2))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_values[$(to_idx(:d))] = S_values[$(to_idx(:d))] * ($t2 - $t1);
          :l2G)
 
-        #struct $(generate_edge_type(:l3G, :l2G, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(generate_edge_type(:l3G, :l2G, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l3G, :l2G, 1)) <: $(edge_type) transitions::TransitionSet end
+        @everywhere $(check_constraints(:l3G, :l2G, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         !istrue(S_values[$(to_idx(:in))]) && 
         (S_time >= $t2 || istrue(S_values[$(to_idx(:isabs))]))
-        $(update_state!)(edge::$(generate_edge_type(:l3G, :l2G, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        @everywhere $(update_state!(:l3G, :l2G, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (:l2G)
 
         # l4G loc
         # l4G => l1G
-        #struct $(generate_edge_type(:l4G, :l1G, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(generate_edge_type(:l4G, :l1G, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = true
-        $(update_state!)(edge::$(generate_edge_type(:l4G, :l1G, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l4G, :l1G, 1)) <: $(edge_type) transitions::TransitionSet end
+        @everywhere $(check_constraints(:l4G, :l1G, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = true
+        @everywhere $(update_state!(:l4G, :l1G, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_values[$(to_idx(:d))] = S_values[$(to_idx(:d))] + S_values[$(to_idx(:tprime))] * min(abs($x1 - S_values[$(to_idx(:n))]), abs($x2 - S_values[$(to_idx(:n))]));
          S_values[$(to_idx(:tprime))] = 0.0;
          S_values[$(to_idx(:n))] = x[$(idx_obs_var_G)];
@@ -211,25 +218,25 @@ function create_automaton_G_and_F(m::ContinuousTimeModel, x1::Float64, x2::Float
          :l1G)
 
         # l4G => l2G
-        #struct $(generate_edge_type(:l4G, :l2G, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(generate_edge_type(:l4G, :l2G, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l4G, :l2G, 1)) <: $(edge_type) transitions::TransitionSet end
+        @everywhere $(check_constraints(:l4G, :l2G, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (istrue(S_values[$(to_idx(:isabs))]))
-        $(update_state!)(edge::$(generate_edge_type(:l4G, :l2G, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        @everywhere $(update_state!(:l4G, :l2G, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_values[$(to_idx(:d))] = S_values[$(to_idx(:d))] +  ($t2 - S_time) * min(abs($x1 - S_values[$(to_idx(:n))]), abs($x2 - S_values[$(to_idx(:n))]));
          :l2G)
 
-        #struct $(generate_edge_type(:l4G, :l2G, 2)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(generate_edge_type(:l4G, :l2G, 2)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l4G, :l2G, 2)) <: $(edge_type) transitions::TransitionSet end
+        @everywhere $(check_constraints(:l4G, :l2G, 2))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_time >= $t2)
-        $(update_state!)(edge::$(generate_edge_type(:l4G, :l2G, 2)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        @everywhere $(update_state!(:l4G, :l2G, 2))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_values[$(to_idx(:d))] = S_values[$(to_idx(:d))] +  S_values[$(to_idx(:tprime))] * min(abs($x1 - S_values[$(to_idx(:n))]), abs($x2 - S_values[$(to_idx(:n))]));
          :l2G)
 
 
         # Connection between the two automata: l2G => l1F
-        #struct $(generate_edge_type(:l2G, :l1F, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(generate_edge_type(:l2G, :l1F, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = true
-        $(update_state!)(edge::$(generate_edge_type(:l2G, :l1F, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l2G, :l1F, 1)) <: $(edge_type) transitions::TransitionSet end
+        @everywhere $(check_constraints(:l2G, :l1F, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = true
+        @everywhere $(update_state!(:l2G, :l1F, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_values[$(to_idx(:n))] = x[$(idx_obs_var_F)];
          S_values[$(to_idx(:dprime))] = Inf;
          S_values[$(to_idx(:isabs))] = $(m.isabsorbing)(p, x);
@@ -237,80 +244,81 @@ function create_automaton_G_and_F(m::ContinuousTimeModel, x1::Float64, x2::Float
 
         # l1F loc : we con#struct  the edges of the form l1F => (..)
         # l1F => l2F
-        #struct $(generate_edge_type(:l1F, :l2F, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(generate_edge_type(:l1F, :l2F, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l1F, :l2F, 1)) <: $(edge_type) transitions::TransitionSet end
+        @everywhere $(check_constraints(:l1F, :l2F, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         S_time >= $t3 &&
         S_values[$(to_idx(:dprime))] == 0 
-        $(update_state!)(edge::$(generate_edge_type(:l1F, :l2F, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        @everywhere $(update_state!(:l1F, :l2F, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (#S_values[$(to_idx(:dprime))] = 0;
          :l2F)
 
-        #struct $(generate_edge_type(:l1F, :l2F, 2)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(generate_edge_type(:l1F, :l2F, 2)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l1F, :l2F, 2)) <: $(edge_type) transitions::TransitionSet end
+        @everywhere $(check_constraints(:l1F, :l2F, 2))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_time >= $t4) && 
         (S_values[$(to_idx(:n))] < $x3 || S_values[$(to_idx(:n))] > $x4)
-        $(update_state!)(edge::$(generate_edge_type(:l1F, :l2F, 2)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        @everywhere $(update_state!(:l1F, :l2F, 2))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (#S_values[$(to_idx(:dprime))] = min(abs(S_values[$(to_idx(:n))] - $x3), abs(S_values[$(to_idx(:n))] - $x4));
          S_values[$(to_idx(:d))] = S_values[$(to_idx(:d))] + S_values[$(to_idx(:dprime))];
          :l2F)
         #=
-        #struct $(generate_edge_type(:l1F, :l2F, 3)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(generate_edge_type(:l1F, :l2F, 3)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l1F, :l2F, 3)) <: $(edge_type) transitions::TransitionSet end
+        @everywhere $(check_constraints(:l1F, :l2F, 3))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         istrue(S_values[$(to_idx(:isabs))]) && S_time <= $t4
-        $(update_state!)(edge::$(generate_edge_type(:l1F, :l2F, 3)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        @everywhere $(update_state!(:l1F, :l2F, 3))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_values[$(to_idx(:d))] = S_values[$(to_idx(:d))] + S_values[$(to_idx(:dprime))];
         :l2F)
 
-        #struct $(generate_edge_type(:l1F, :l2F, 4)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(generate_edge_type(:l1F, :l2F, 4)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l1F, :l2F, 4)) <: $(edge_type) transitions::TransitionSet end
+        @everywhere $(check_constraints(:l1F, :l2F, 4))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         S_time >= $t3 &&
         S_values[$(to_idx(:dprime))] == 0 
-        $(update_state!)(edge::$(generate_edge_type(:l1F, :l2F, 4)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        @everywhere $(update_state!(:l1F, :l2F, 4))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (:l2F)
         =#
 
         # l1F => l3F
-        #struct $(generate_edge_type(:l1F, :l3F, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(generate_edge_type(:l1F, :l3F, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l1F, :l3F, 1)) <: $(edge_type) transitions::TransitionSet end
+        @everywhere $(check_constraints(:l1F, :l3F, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_time <= $t3) &&
         (S_values[$(to_idx(:n))] < $x3 || S_values[$(to_idx(:n))] > $x4)
-        $(update_state!)(edge::$(generate_edge_type(:l1F, :l3F, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        @everywhere $(update_state!(:l1F, :l3F, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_values[$(to_idx(:dprime))] = min(sqrt((S_time - $t3)^2 + (S_values[$(to_idx(:n))] - $x4)^2), 
                                             sqrt((S_time - $t3)^2 + (S_values[$(to_idx(:n))] - $x3)^2));
          :l3F)
 
-        #struct $(generate_edge_type(:l1F, :l3F, 2)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(generate_edge_type(:l1F, :l3F, 2)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l1F, :l3F, 2)) <: $(edge_type) transitions::TransitionSet end
+        @everywhere $(check_constraints(:l1F, :l3F, 2))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         ($x3 <= S_values[$(to_idx(:n))] <= $x4)
-        $(update_state!)(edge::$(generate_edge_type(:l1F, :l3F, 2)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        @everywhere $(update_state!(:l1F, :l3F, 2))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_values[$(to_idx(:dprime))] = 0;
          :l3F)
 
-        #struct $(generate_edge_type(:l1F, :l3F, 3)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(generate_edge_type(:l1F, :l3F, 3)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l1F, :l3F, 3)) <: $(edge_type) transitions::TransitionSet end
+        @everywhere $(check_constraints(:l1F, :l3F, 3))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_time >= $t3) &&
         (S_values[$(to_idx(:n))] < $x3 || S_values[$(to_idx(:n))] > $x4)
-        $(update_state!)(edge::$(generate_edge_type(:l1F, :l3F, 3)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        @everywhere $(update_state!(:l1F, :l3F, 3))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_values[$(to_idx(:dprime))] = min(S_values[$(to_idx(:dprime))], min(abs(S_values[$(to_idx(:n))] - $x3), abs(S_values[$(to_idx(:n))] - $x4)));
          :l3F)
 
         # l3F loc
         # l3F => l1F
-        #struct $(generate_edge_type(:l3F, :l1F, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(generate_edge_type(:l3F, :l1F, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = true
-        $(update_state!)(edge::$(generate_edge_type(:l3F, :l1F, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l3F, :l1F, 1)) <: $(edge_type) transitions::TransitionSet end
+        @everywhere $(check_constraints(:l3F, :l1F, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = true
+        @everywhere $(update_state!(:l3F, :l1F, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_values[$(to_idx(:n))] = x[$(idx_obs_var_F)];
          S_values[$(to_idx(:isabs))] = $(m.isabsorbing)(p, x);
          :l1F)
 
         # l3F => l2F
-        #struct $(generate_edge_type(:l3F, :l2F, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(generate_edge_type(:l3F, :l2F, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l3F, :l2F, 1)) <: $(edge_type) transitions::TransitionSet end
+        @everywhere $(check_constraints(:l3F, :l2F, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_time >= $t4 || istrue(S_values[$(to_idx(:isabs))]))
-        $(update_state!)(edge::$(generate_edge_type(:l3F, :l2F, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        @everywhere $(update_state!(:l3F, :l2F, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_values[$(to_idx(:d))] = S_values[$(to_idx(:d))] + S_values[$(to_idx(:dprime))];
          :l2F)
     end
+    eval(meta_funcs)
 
     @eval begin
         map_edges = Dict{Location, Dict{Location, Vector{$(edge_type)}}}()
@@ -320,91 +328,114 @@ function create_automaton_G_and_F(m::ContinuousTimeModel, x1::Float64, x2::Float
 
         # l0G loc
         # l0G => l1G
-        edge1 = $(generate_edge_type(:l0G, :l1G, 1))(nothing)
+        edge1 = EdgeAutomatonGandF(nothing, $(check_constraints(:l0G, :l1G, 1)), $(update_state!(:l0G, :l1G, 1)))
         map_edges[:l0G][:l1G] = [edge1]
 
         # l1G => l3G
-        edge1 = $(generate_edge_type(:l1G, :l3G, 1))(nothing)
-        edge2 = $(generate_edge_type(:l1G, :l3G, 2))(nothing)
-        edge3 = $(generate_edge_type(:l1G, :l3G, 3))(nothing)
-        edge4 = $(generate_edge_type(:l1G, :l3G, 4))(nothing)
+        edge1 = EdgeAutomatonGandF(nothing, $(check_constraints(:l1G, :l3G, 1)), $(update_state!(:l1G, :l3G, 1)))
+        edge2 = EdgeAutomatonGandF(nothing, $(check_constraints(:l1G, :l3G, 2)), $(update_state!(:l1G, :l3G, 2)))
+        edge3 = EdgeAutomatonGandF(nothing, $(check_constraints(:l1G, :l3G, 3)), $(update_state!(:l1G, :l3G, 3)))
+        edge4 = EdgeAutomatonGandF(nothing, $(check_constraints(:l1G, :l3G, 4)), $(update_state!(:l1G, :l3G, 4)))
         map_edges[:l1G][:l3G] = [edge1, edge2, edge3, edge4]
 
         # l1G => l4G
-        edge1 = $(generate_edge_type(:l1G, :l4G, 1))(nothing)
-        edge2 = $(generate_edge_type(:l1G, :l4G, 2))(nothing)
+        edge1 = EdgeAutomatonGandF(nothing, $(check_constraints(:l1G, :l4G, 1)), $(update_state!(:l1G, :l4G, 1)))
+        edge2 = EdgeAutomatonGandF(nothing, $(check_constraints(:l1G, :l4G, 2)), $(update_state!(:l1G, :l4G, 2)))
         map_edges[:l1G][:l4G] = [edge1, edge2]
 
         # l1G => l2G
         #=
-        edge1 = $(generate_edge_type(:l1G, :l2G, 1))(nothing)
-        edge2 = $(generate_edge_type(:l1G, :l2G, 2))(nothing)
-        edge3 = $(generate_edge_type(:l1G, :l2G, 3))(nothing)
-        edge4 = $(generate_edge_type(:l1G, :l2G, 4))(nothing)
+        edge1 = EdgeAutomatonGandF(nothing, $(check_constraints(:l1G, :l2G, 1)), $(update_state!(:l1G, :l2G, 1)))
+        edge2 = EdgeAutomatonGandF(nothing, $(check_constraints(:l1G, :l2G, 2)), $(update_state!(:l1G, :l2G, 2)))
+        edge3 = EdgeAutomatonGandF(nothing, $(check_constraints(:l1G, :l2G, 3)), $(update_state!(:l1G, :l2G, 3)))
+        edge4 = EdgeAutomatonGandF(nothing, $(check_constraints(:l1G, :l2G, 4)), $(update_state!(:l1G, :l2G, 4)))
         map_edges[:l1G][:l2G] = [edge3, edge4, edge1, edge2]
         =#
 
         # l3G loc
         # l3G => l1G
-        edge1 = $(generate_edge_type(:l3G, :l1G, 1))([:ALL])
+        edge1 = EdgeAutomatonGandF([:ALL], $(check_constraints(:l3G, :l1G, 1)), $(update_state!(:l3G, :l1G, 1)))
         map_edges[:l3G][:l1G] = [edge1]
 
         # l3G => l2G
-        edge1 = $(generate_edge_type(:l3G, :l2G, 1))(nothing)
-        edge2 = $(generate_edge_type(:l3G, :l2G, 2))(nothing)
+        edge1 = EdgeAutomatonGandF(nothing, $(check_constraints(:l3G, :l2G, 1)), $(update_state!(:l3G, :l2G, 1)))
+        edge2 = EdgeAutomatonGandF(nothing, $(check_constraints(:l3G, :l2G, 2)), $(update_state!(:l3G, :l2G, 2)))
         map_edges[:l3G][:l2G] = [edge1, edge2]
 
         # l4 loc
         # l4G => l1G
-        edge1 = $(generate_edge_type(:l4G, :l1G, 1))([:ALL])
+        edge1 = EdgeAutomatonGandF([:ALL], $(check_constraints(:l4G, :l1G, 1)), $(update_state!(:l4G, :l1G, 1)))
         map_edges[:l4G][:l1G] = [edge1]
 
         # l4G => l2G
-        edge1 = $(generate_edge_type(:l4G, :l2G, 1))(nothing)
-        edge2 = $(generate_edge_type(:l4G, :l2G, 2))(nothing)
+        edge1 = EdgeAutomatonGandF(nothing, $(check_constraints(:l4G, :l2G, 1)), $(update_state!(:l4G, :l2G, 1)))
+        edge2 = EdgeAutomatonGandF(nothing, $(check_constraints(:l4G, :l2G, 2)), $(update_state!(:l4G, :l2G, 2)))
         map_edges[:l4G][:l2G] = [edge1,edge2]
 
         # l2G loc
         # l2G => l1F : Transition from autF to autG
-        edge1 = $(generate_edge_type(:l2G, :l1F, 1))(nothing)
+        edge1 = EdgeAutomatonGandF(nothing, $(check_constraints(:l2G, :l1F, 1)), $(update_state!(:l2G, :l1F, 1)))
         map_edges[:l2G][:l1F] = [edge1]
 
         # l1F loc
         # l1F => l3F
-        edge1 = $(generate_edge_type(:l1F, :l2F, 1))(nothing)
-        edge2 = $(generate_edge_type(:l1F, :l2F, 2))(nothing)
+        edge1 = EdgeAutomatonGandF(nothing, $(check_constraints(:l1F, :l2F, 1)), $(update_state!(:l1F, :l2F, 1)))
+        edge2 = EdgeAutomatonGandF(nothing, $(check_constraints(:l1F, :l2F, 2)), $(update_state!(:l1F, :l2F, 2)))
         map_edges[:l1F][:l2F] = [edge1, edge2]
-        #edge3 = $(generate_edge_type(:l1F, :l2F, 3))(nothing)
-        #edge4 = $(generate_edge_type(:l1F, :l2F, 4))(nothing)
+        #edge3 = EdgeAutomatonGandF(nothing, $(check_constraints(:l1F, :l2F, 3)), $(update_state!(:l1F, :l2F, 3)))
+        #edge4 = EdgeAutomatonGandF(nothing, $(check_constraints(:l1F, :l2F, 4)), $(update_state!(:l1F, :l2F, 4)))
         #map_edges[:l1F][:l2F] = [edge1, edge4, edge3, edge2]
 
         # l1F => l3F
-        edge1 = $(generate_edge_type(:l1F, :l3F, 1))(nothing)
-        edge2 = $(generate_edge_type(:l1F, :l3F, 2))(nothing)
-        edge3 = $(generate_edge_type(:l1F, :l3F, 3))(nothing)
+        edge1 = EdgeAutomatonGandF(nothing, $(check_constraints(:l1F, :l3F, 1)), $(update_state!(:l1F, :l3F, 1)))
+        edge2 = EdgeAutomatonGandF(nothing, $(check_constraints(:l1F, :l3F, 2)), $(update_state!(:l1F, :l3F, 2)))
+        edge3 = EdgeAutomatonGandF(nothing, $(check_constraints(:l1F, :l3F, 3)), $(update_state!(:l1F, :l3F, 3)))
         map_edges[:l1F][:l3F] = [edge1, edge2, edge3]
 
         # l3F loc
         # l3F => l1F
-        edge1 = $(generate_edge_type(:l3F, :l1F, 1))([:ALL])
+        edge1 = EdgeAutomatonGandF([:ALL], $(check_constraints(:l3F, :l1F, 1)), $(update_state!(:l3F, :l1F, 1)))
         map_edges[:l3F][:l1F] = [edge1]
 
         # l3F => l2F
-        edge1 = $(generate_edge_type(:l3F, :l2F, 1))(nothing)    
+        edge1 = EdgeAutomatonGandF(nothing, $(check_constraints(:l3F, :l2F, 1)), $(update_state!(:l3F, :l2F, 1)))    
         map_edges[:l3F][:l2F] = [edge1]
     end
 
+    ## Create data separately
+    map_edges_transitions = Dict{Symbol, Dict{Symbol,Vector{TransitionSet}}}()
+    map_edges_check_constraints = Dict{Symbol, Dict{Symbol,Vector{CheckConstraintsFunction}}}()
+    map_edges_update_state = Dict{Symbol, Dict{Symbol,Vector{UpdateStateFunction}}}()
+    for from_loc in keys(map_edges)
+        map_edges_transitions[from_loc] = Dict{Symbol,Vector{TransitionSet}}()
+        map_edges_check_constraints[from_loc] = Dict{Symbol,Vector{CheckConstraintsFunction}}()
+        map_edges_update_state[from_loc] = Dict{Symbol,Vector{UpdateStateFunction}}()
+        for to_loc in keys(map_edges[from_loc])
+            map_edges_transitions[from_loc][to_loc] = TransitionSet[]
+            map_edges_check_constraints[from_loc][to_loc] = CheckConstraintsFunction[]
+            map_edges_update_state[from_loc][to_loc] = UpdateStateFunction[]
+            for edge in map_edges[from_loc][to_loc]
+                push!(map_edges_transitions[from_loc][to_loc], edge.transitions)
+                push!(map_edges_check_constraints[from_loc][to_loc], edge.check_constraints)
+                push!(map_edges_update_state[from_loc][to_loc], edge.update_state!)
+            end
+        end
+    end
+
     ## Constants
     constants = Dict{Symbol,Float64}(:x1 => x1,  :x2 => x2, :t1 => t1, :t2 => t2,
                                      :x3 => x3,  :x4 => x4, :t3 => t3, :t4 => t4)
 
-    # Updating types and simulation methods
+    # Updating types and simulation method
     @everywhere @eval $(MarkovProcesses.generate_code_synchronized_model_type_def(model_name, lha_name))
-    @everywhere @eval $(MarkovProcesses.generate_code_next_state(lha_name, edge_type, check_constraints, update_state!))
+    @everywhere @eval $(MarkovProcesses.generate_code_next_state(lha_name, edge_type))
+    #@everywhere @eval $(MarkovProcesses.generate_code_next_state_with_dicts(lha_name, edge_type))
     @everywhere @eval $(MarkovProcesses.generate_code_synchronized_simulation(model_name, lha_name, edge_type, m.f!, m.isabsorbing))
 
     A = AutomatonGandF(m.transitions, locations, Λ_F, locations_init, locations_final, 
-                       map_var_automaton_idx, flow, map_edges, constants, m.map_var_idx)
+                       map_var_automaton_idx, flow, map_edges, 
+                       map_edges_transitions, map_edges_check_constraints, map_edges_update_state,
+                       constants, m.map_var_idx)
     return A
 end
 
diff --git a/automata/euclidean_distance_automaton.jl b/automata/euclidean_distance_automaton.jl
index ae3ace3f7d9ccca2e5ba651538a447ee840b1f90..be7b1c07e15d29f5d536c99bc9ec41f7141d4a86 100644
--- a/automata/euclidean_distance_automaton.jl
+++ b/automata/euclidean_distance_automaton.jl
@@ -1,6 +1,11 @@
 
 # Creation of the automaton types
-@everywhere @eval abstract type EdgeEuclideanDistanceAutomaton <: Edge end
+#@everywhere @eval abstract type EdgeEuclideanDistanceAutomaton <: Edge end
+@everywhere struct EdgeEuclideanDistanceAutomaton <: Edge
+    transitions::TransitionSet
+    check_constraints::CheckConstraintsFunction
+    update_state!::UpdateStateFunction
+end
 @everywhere @eval $(MarkovProcesses.generate_code_lha_type_def(:EuclideanDistanceAutomaton, :EdgeEuclideanDistanceAutomaton))
 
 function create_euclidean_distance_automaton(m::ContinuousTimeModel, timeline::AbstractVector{Float64}, observations::AbstractVector{Float64}, sym_obs::VariableModel)
@@ -43,14 +48,20 @@ function create_euclidean_distance_automaton(m::ContinuousTimeModel, timeline::A
     basename_func = "$(model_name)_$(id)"
     edge_name(from_loc::Location, to_loc::Location, edge_number::Int) = 
     Symbol("Edge_$(lha_name)_$(basename_func)_$(from_loc)$(to_loc)_$(edge_number)")
-    
+    function check_constraints(from_loc::Location, to_loc::Location, edge_number::Int)
+        return Symbol("check_constraints_$(edge_type)_$(from_loc)$(to_loc)_$(edge_number)_$(model_name)_$(id)")
+    end
+    function update_state!(from_loc::Location, to_loc::Location, edge_number::Int)
+        return Symbol("update_state_$(edge_type)_$(from_loc)$(to_loc)_$(edge_number)_$(model_name)_$(id)!")
+    end
+
     ## check_constraints & update_state!
-    @everywhere @eval begin
+    meta_funcs = quote
         # l0 loc
         # l0 => l1
-        struct $(edge_name(:l0, :l1, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(edge_name(:l0, :l1, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = true
-        $(update_state!)(edge::$(edge_name(:l0, :l1, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l0, :l1, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
+        @everywhere $(check_constraints(:l0, :l1, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = true
+        @everywhere $(update_state!(:l0, :l1, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_values[$(to_idx(:n))] = x[$(idx_obs_var)];
          S_values[$(to_idx(:d))] = 0.0;
          S_values[$(to_idx(:idx))] = 1.0;
@@ -59,32 +70,33 @@ function create_euclidean_distance_automaton(m::ContinuousTimeModel, timeline::A
         # l1 loc
         # l1 => l1
         # Defined below 
-        struct $(edge_name(:l1, :l1, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(edge_name(:l1, :l1, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
+        #struct $(edge_name(:l1, :l1, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
+        @everywhere $(check_constraints(:l1, :l1, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
         (tml = $(Tuple(timeline));
          tml_idx = tml[convert(Int, S_values[$(to_idx(:idx))])];
          S_values[$(to_idx(:t))] >= tml_idx)
-        $(update_state!)(edge::$(edge_name(:l1, :l1, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
+        @everywhere $(update_state!(:l1, :l1, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
         (y_obs = $(Tuple(observations));
          y_obs_idx = y_obs[convert(Int, S_values[$(to_idx(:idx))])];
          S_values[$(to_idx(:d))] = S_values[$(to_idx(:d))]+(S_values[$(to_idx(:n))]-y_obs_idx)^2;
          S_values[$(to_idx(:idx))] = S_values[$(to_idx(:idx))]+1.0;
          :l1)
 
-        struct $(edge_name(:l1, :l1, 2)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(edge_name(:l1, :l1, 2)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = true 
-        $(update_state!)(edge::$(edge_name(:l1, :l1, 2)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l1, :l1, 2)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
+        @everywhere $(check_constraints(:l1, :l1, 2))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = true 
+        @everywhere $(update_state!(:l1, :l1, 2))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_values[$(to_idx(:n))] = x[$(idx_obs_var)];
          :l1)
 
         # l1 => l2
-        struct $(edge_name(:l1, :l2, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(edge_name(:l1, :l2, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l1, :l2, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
+        @everywhere $(check_constraints(:l1, :l2, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         S_values[$(to_idx(:idx))] >= ($nbr_observations + 1)
-        $(update_state!)(edge::$(edge_name(:l1, :l2, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        @everywhere $(update_state!(:l1, :l2, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_values[$(to_idx(:d))] = sqrt(S_values[$(to_idx(:d))]);
          :l2)
     end
+    eval(meta_funcs)
 
     @eval begin
         map_edges = Dict{Location,Dict{Location,Vector{$(edge_type)}}}()
@@ -95,20 +107,24 @@ function create_euclidean_distance_automaton(m::ContinuousTimeModel, timeline::A
         ## Edges
         # l0 loc
         # l0 => l1
-        edge1 = $(edge_name(:l0, :l1, 1))(nothing)
+        edge1 = EdgeEuclideanDistanceAutomaton(nothing, $(check_constraints(:l0, :l1, 1)), $(update_state!(:l0, :l1, 1)))
         map_edges[:l0][:l1] = [edge1]
 
         # l1 loc
         # l1 => l1
-        edge1 = $(edge_name(:l1, :l1, 1))(nothing)
-        edge2 = $(edge_name(:l1, :l1, 2))([:ALL])
+        edge1 = EdgeEuclideanDistanceAutomaton(nothing, $(check_constraints(:l1, :l1, 1)), $(update_state!(:l1, :l1, 1)))
+        edge2 = EdgeEuclideanDistanceAutomaton([:ALL], $(check_constraints(:l1, :l1, 2)), $(update_state!(:l1, :l1, 2)))
         map_edges[:l1][:l1] = [edge1, edge2]
 
         # l1 => l2
-        edge1 = $(edge_name(:l1, :l2, 1))(nothing)
+        edge1 = EdgeEuclideanDistanceAutomaton(nothing, $(check_constraints(:l1, :l2, 1)), $(update_state!(:l1, :l2, 1)))
         map_edges[:l1][:l2] = [edge1]
     end
 
+    map_edges_transitions = Dict{Symbol, Dict{Symbol,Vector{TransitionSet}}}()
+    map_edges_check_constraints = Dict{Symbol, Dict{Symbol,Vector{CheckConstraintsFunction}}}()
+    map_edges_update_state = Dict{Symbol, Dict{Symbol,Vector{UpdateStateFunction}}}()
+    
     ## Constants
     constants = Dict{Symbol,Float64}(:nbr_obs => nbr_observations)
     for i = 1:nbr_observations
@@ -118,11 +134,13 @@ function create_euclidean_distance_automaton(m::ContinuousTimeModel, timeline::A
 
     # Updating types and simulation methods
     @everywhere @eval $(MarkovProcesses.generate_code_synchronized_model_type_def(model_name, lha_name))
-    @everywhere @eval $(MarkovProcesses.generate_code_next_state(lha_name, edge_type, check_constraints, update_state!))
+    @everywhere @eval $(MarkovProcesses.generate_code_next_state(lha_name, edge_type))
     @everywhere @eval $(MarkovProcesses.generate_code_synchronized_simulation(model_name, lha_name, edge_type, m.f!, m.isabsorbing))
 
     A = EuclideanDistanceAutomaton(m.transitions, locations, Λ_F, locations_init, locations_final, 
-                                   map_var_automaton_idx, flow, map_edges, constants, m.map_var_idx)
+                                   map_var_automaton_idx, flow, 
+                                   map_edges, map_edges_transitions, map_edges_check_constraints, map_edges_update_state,
+                                   constants, m.map_var_idx)
 
     return A
 end
diff --git a/automata/euclidean_distance_automaton_2.jl b/automata/euclidean_distance_automaton_2.jl
index ceb7d52eca326070062bfbb11483df93db8f7ffe..c3dfaa4c5863145026de47634fd80eae2dc77ce2 100644
--- a/automata/euclidean_distance_automaton_2.jl
+++ b/automata/euclidean_distance_automaton_2.jl
@@ -1,6 +1,11 @@
 
 # Creation of the automaton types
-@everywhere @eval abstract type EdgeEuclideanDistanceAutomaton2 <: Edge end
+#@everywhere @eval abstract type EdgeEuclideanDistanceAutomaton2 <: Edge end
+@everywhere struct EdgeEuclideanDistanceAutomaton2 <: Edge
+    transitions::TransitionSet
+    check_constraints::CheckConstraintsFunction
+    update_state!::UpdateStateFunction
+end
 @everywhere @eval $(MarkovProcesses.generate_code_lha_type_def(:EuclideanDistanceAutomaton2,:EdgeEuclideanDistanceAutomaton2))
 
 function create_euclidean_distance_automaton_2(m::ContinuousTimeModel, timeline::AbstractVector{Float64}, observations::AbstractVector{Float64}, sym_obs::VariableModel)
@@ -48,99 +53,104 @@ function create_euclidean_distance_automaton_2(m::ContinuousTimeModel, timeline:
     basename_func = "$(model_name)_$(id)"
     edge_name(from_loc::Location, to_loc::Location, edge_number::Int) = 
     Symbol("Edge_$(lha_name)_$(basename_func)_$(from_loc)$(to_loc)_$(edge_number)")
+    function check_constraints(from_loc::Location, to_loc::Location, edge_number::Int)
+        return Symbol("check_constraints_$(edge_type)_$(from_loc)$(to_loc)_$(edge_number)_$(model_name)_$(id)")
+    end
+    function update_state!(from_loc::Location, to_loc::Location, edge_number::Int)
+        return Symbol("update_state_$(edge_type)_$(from_loc)$(to_loc)_$(edge_number)_$(model_name)_$(id)!")
+    end
 
     loc_nbr_obs = Symbol("l$(nbr_observations)")
-    @everywhere @eval begin
+    meta_funcs = quote
         # l0 loc
         # l0 => l1
-        @everywhere struct $(edge_name(:l0, :l1, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(edge_name(:l0, :l1, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = true
-        @everywhere $(update_state!)(edge::$(edge_name(:l0, :l1, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l0, :l1, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
+        @everywhere $(check_constraints(:l0, :l1, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = true
+        @everywhere $(update_state!(:l0, :l1, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_values[$(to_idx(:n))] = x[$(idx_obs_var)];
          S_values[$(to_idx(:d))] = 0.0;
          :l1)
 
         # lnbr_obs => lfinal
-        @everywhere struct $(edge_name(loc_nbr_obs, :lfinal, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(edge_name(loc_nbr_obs, :lfinal, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(loc_nbr_obs, :lfinal, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
+        @everywhere $(check_constraints(loc_nbr_obs, :lfinal, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         S_values[$(to_idx(:t))] >= $(timeline[nbr_observations])
-        @everywhere $(update_state!)(edge::$(edge_name(loc_nbr_obs, :lfinal, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        @everywhere $(update_state!(loc_nbr_obs, :lfinal, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_values[$(to_idx(:d))] = S_values[$(to_idx(:d))]+(S_values[$(to_idx(:n))]-$(observations[nbr_observations]))^2;
          S_values[$(to_idx(:d))] = sqrt(S_values[$(to_idx(:d))]);
          :lfinal)
 
         # lnbr_obs => lnbr_obs
-        @everywhere struct $(edge_name(loc_nbr_obs, loc_nbr_obs, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(edge_name(loc_nbr_obs, loc_nbr_obs, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = true 
-        @everywhere $(update_state!)(edge::$(edge_name(loc_nbr_obs, loc_nbr_obs, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(loc_nbr_obs, loc_nbr_obs, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
+        @everywhere $(check_constraints(loc_nbr_obs, loc_nbr_obs, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = true 
+        @everywhere $(update_state!(loc_nbr_obs, loc_nbr_obs, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_values[$(to_idx(:n))] = x[$(idx_obs_var)];
          $(Meta.quot(loc_nbr_obs)))
     end
+    eval(meta_funcs)
 
     @eval begin
         map_edges = Dict{Location,Dict{Location,Vector{$(edge_type)}}}()
         for loc in $(locations)
             map_edges[loc] = Dict{Location,Vector{$(edge_type)}}()
         end
-        
+
         # l0 loc
         # l0 => l1
-        edge1 = $(edge_name(:l0, :l1, 1))(nothing)
+        edge1 = EdgeEuclideanDistanceAutomaton2(nothing, $(check_constraints(:l0, :l1, 1)), $(update_state!(:l0, :l1, 1)))
         map_edges[:l0][:l1] = [edge1]
 
         # lnbr_obs => lfinal
-        edge1 = $(edge_name(loc_nbr_obs, :lfinal, 1))(nothing)
+        edge1 = EdgeEuclideanDistanceAutomaton2(nothing, $(check_constraints(loc_nbr_obs, :lfinal, 1)), $(update_state!(loc_nbr_obs, :lfinal, 1)))
         map_edges[$(Meta.quot(loc_nbr_obs))][:lfinal] = [edge1]
         # lnbr_obs => lnbr_obs
-        edge1 = $(edge_name(loc_nbr_obs, loc_nbr_obs, 1))([:ALL])
+        edge1 = EdgeEuclideanDistanceAutomaton2([:ALL], $(check_constraints(loc_nbr_obs, loc_nbr_obs, 1)), $(update_state!(loc_nbr_obs, loc_nbr_obs, 1)))
         map_edges[$(Meta.quot(loc_nbr_obs))][$(Meta.quot(loc_nbr_obs))] = [edge1]
     end
 
-    function generate_code_loci_functions(i::Int, loci::Symbol, locip1::Symbol)
-        return quote
-            struct $(edge_name(loci, locip1, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-            $(check_constraints)(edge::$(edge_name(loci, locip1, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
+    for i = 1:(nbr_observations-1)
+        loci = Symbol("l$(i)")
+        locip1 = Symbol("l$(i+1)")
+        meta_funcs = quote
+            #struct $(edge_name(loci, locip1, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
+            @everywhere $(check_constraints(loci, locip1, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
             S_values[$(to_idx(:t))] >= $(timeline[i])
-            $(update_state!)(edge::$(edge_name(loci, locip1, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
+            @everywhere $(update_state!(loci, locip1, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
             (S_values[$(to_idx(:d))] = S_values[$(to_idx(:d))]+(S_values[$(to_idx(:n))]-$(observations[i]))^2;
              $(Meta.quot(locip1)))
 
-            struct $(edge_name(loci, loci, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-            $(check_constraints)(edge::$(edge_name(loci, loci, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = true 
-            $(update_state!)(edge::$(edge_name(loci, loci, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+            #struct $(edge_name(loci, loci, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
+            @everywhere $(check_constraints(loci, loci, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = true 
+            @everywhere $(update_state!(loci, loci, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
             (S_values[$(to_idx(:n))] = x[$(idx_obs_var)];
              $(Meta.quot(loci)))
         end
+        eval(meta_funcs)
+
+        # loci => loci+1
+        edge1 = EdgeEuclideanDistanceAutomaton2(nothing, getfield(Main, check_constraints(loci, locip1, 1)), getfield(Main, update_state!(loci, locip1, 1)))
+        map_edges[loci][locip1] = [edge1]
+        # loci => loci
+        edge1 = EdgeEuclideanDistanceAutomaton2([:ALL], getfield(Main, check_constraints(loci, loci, 1)), getfield(Main, update_state!(loci, loci, 1)))
+        map_edges[loci][loci] = [edge1]
     end
 
-    function generate_code_loci_edges(loci::Symbol, locip1::Symbol)
-        return quote
-            # loci => loci+1
-            edge1 = $(edge_name(loci, locip1, 1))(nothing)
-            map_edges[$(Meta.quot(loci))][$(Meta.quot(locip1))] = [edge1]
-            # loci => loci
-            edge1 = $(edge_name(loci, loci, 1))([:ALL])
-            map_edges[$(Meta.quot(loci))][$(Meta.quot(loci))] = [edge1]
-        end
-    end
-
-    for i = 1:(nbr_observations-1)
-        loci = Symbol("l$(i)")
-        locip1 = Symbol("l$(i+1)")
-        @everywhere @eval $(generate_code_loci_functions(i, loci, locip1))
-        @everywhere @eval $(generate_code_loci_edges(loci, locip1))
-    end
-    
     ## Constants
     constants = Dict{Symbol,Float64}(:nbr_obs => nbr_observations)
 
+    map_edges_transitions = Dict{Symbol, Dict{Symbol,Vector{TransitionSet}}}()
+    map_edges_check_constraints = Dict{Symbol, Dict{Symbol,Vector{CheckConstraintsFunction}}}()
+    map_edges_update_state = Dict{Symbol, Dict{Symbol,Vector{UpdateStateFunction}}}()
+
     # Updating types and simulation methods
     @everywhere @eval $(MarkovProcesses.generate_code_synchronized_model_type_def(model_name, lha_name))
-    @everywhere @eval $(MarkovProcesses.generate_code_next_state(lha_name, edge_type, check_constraints, update_state!))
+    @everywhere @eval $(MarkovProcesses.generate_code_next_state(lha_name, edge_type))
     @everywhere @eval $(MarkovProcesses.generate_code_synchronized_simulation(model_name, lha_name, edge_type, m.f!, m.isabsorbing))
 
     A = EuclideanDistanceAutomaton2(m.transitions, locations, Λ_F, locations_init, locations_final, 
-                                    map_var_automaton_idx, flow, map_edges, constants, m.map_var_idx)
+                                    map_var_automaton_idx, flow, 
+                                    map_edges, map_edges_transitions, map_edges_check_constraints, map_edges_update_state,
+                                    constants, m.map_var_idx)
     return A
 end
 
diff --git a/automata/period_automaton.jl b/automata/period_automaton.jl
index 3b99d94034633d269e0f87aa5e0e8506ce8bd472..5c84347469a04f5aa8cf40c02e76b55039a06b98 100644
--- a/automata/period_automaton.jl
+++ b/automata/period_automaton.jl
@@ -9,7 +9,12 @@
 abs(mean_tp - ref_mean_tp)
 
 # Creation of the automaton types
-@everywhere @eval abstract type EdgePeriodAutomaton <: Edge end
+#@everywhere @eval abstract type EdgePeriodAutomaton <: Edge end
+@everywhere struct EdgePeriodAutomaton <: Edge 
+    transitions::TransitionSet 
+    check_constraints::CheckConstraintsFunction
+    update_state!::UpdateStateFunction
+end
 @everywhere @eval $(MarkovProcesses.generate_code_lha_type_def(:PeriodAutomaton, :EdgePeriodAutomaton))
 
 function create_period_automaton(m::ContinuousTimeModel, L::Float64, H::Float64, N::Int, sym_obs::VariableModel;
@@ -66,30 +71,36 @@ function create_period_automaton(m::ContinuousTimeModel, L::Float64, H::Float64,
     idx_obs_var = getfield(m, :map_var_idx)[sym_obs]
     edge_name(from_loc::Location, to_loc::Location, edge_number::Int) = 
     Symbol("Edge_$(lha_name)_$(basename_func)_$(from_loc)$(to_loc)_$(edge_number)")
+    function check_constraints(from_loc::Location, to_loc::Location, edge_number::Int)
+        return Symbol("check_constraints_$(edge_type)_$(from_loc)$(to_loc)_$(edge_number)_$(model_name)_$(id)")
+    end
+    function update_state!(from_loc::Location, to_loc::Location, edge_number::Int)
+        return Symbol("update_state_$(edge_type)_$(from_loc)$(to_loc)_$(edge_number)_$(model_name)_$(id)!")
+    end
 
     ## check_constraints & update_state!
-    @everywhere @eval begin
+    meta_funcs = quote
         # l0 loc 
         # * l0 => l0
-        struct $(edge_name(:l0, :l0, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(edge_name(:l0, :l0, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l0, :l0, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
+        @everywhere $(check_constraints(:l0, :l0, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         true
-        $(update_state!)(edge::$(edge_name(:l0, :l0, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
+        @everywhere $(update_state!(:l0, :l0, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
         (:l0)
 
         # * l0 => l0prime
-        struct $(edge_name(:l0, :l0prime, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(edge_name(:l0, :l0prime, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l0, :l0prime, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
+        @everywhere $(check_constraints(:l0, :l0prime, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         S_values[$(to_idx(:t))] >= $initT
-        $(update_state!)(edge::$(edge_name(:l0, :l0prime, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
+        @everywhere $(update_state!(:l0, :l0prime, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
         (S_values[$(to_idx(:d))] = Inf;
          :l0prime)
 
         # * l0 => low
-        struct $(edge_name(:l0, :low, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(edge_name(:l0, :low, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l0, :low, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
+        @everywhere $(check_constraints(:l0, :low, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         S_values[$(to_idx(:t))] >= $initT
-        $(update_state!)(edge::$(edge_name(:l0, :low, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
+        @everywhere $(update_state!(:l0, :low, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
         (S_values[$(to_idx(:t))] = 0.0;
          S_values[$(to_idx(:top))] = 0.0;
          S_values[$(to_idx(:n))] = -1;
@@ -99,17 +110,17 @@ function create_period_automaton(m::ContinuousTimeModel, L::Float64, H::Float64,
 
         # l0prime
         # * l0prime => l0prime
-        struct $(edge_name(:l0prime, :l0prime, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(edge_name(:l0prime, :l0prime, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l0prime, :l0prime, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
+        @everywhere $(check_constraints(:l0prime, :l0prime, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         true
-        $(update_state!)(edge::$(edge_name(:l0prime, :l0prime, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
+        @everywhere $(update_state!(:l0prime, :l0prime, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
         (:l0prime)
 
         # * l0prime => low
-        struct $(edge_name(:l0prime, :low, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(edge_name(:l0prime, :low, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:l0prime, :low, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
+        @everywhere $(check_constraints(:l0prime, :low, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         true
-        $(update_state!)(edge::$(edge_name(:l0prime, :low, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
+        @everywhere $(update_state!(:l0prime, :low, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
         (S_values[$(to_idx(:t))] = 0.0;
          S_values[$(to_idx(:top))] = 0.0;
          S_values[$(to_idx(:n))] = -1;
@@ -118,61 +129,61 @@ function create_period_automaton(m::ContinuousTimeModel, L::Float64, H::Float64,
 
         # low 
         # * low => low
-        struct $(edge_name(:low, :low, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(edge_name(:low, :low, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:low, :low, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
+        @everywhere $(check_constraints(:low, :low, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         S_values[$(to_idx(:n))] < $N
-        $(update_state!)(edge::$(edge_name(:low, :low, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
+        @everywhere $(update_state!(:low, :low, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
         (:low)
 
         # * low => mid 
-        struct $(edge_name(:low, :mid, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(edge_name(:low, :mid, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:low, :mid, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
+        @everywhere $(check_constraints(:low, :mid, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         S_values[$(to_idx(:n))] < $N
-        $(update_state!)(edge::$(edge_name(:low, :mid, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
+        @everywhere $(update_state!(:low, :mid, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
         (:mid)
 
         # * low => final
-        struct $(edge_name(:low, :final, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(edge_name(:low, :final, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:low, :final, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
+        @everywhere $(check_constraints(:low, :final, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         S_values[$(to_idx(:n))] == $N
-        $(update_state!)(edge::$(edge_name(:low, :final, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
+        @everywhere $(update_state!(:low, :final, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
         (val_d = $(error_func)(S_values[$(to_idx(:mean_tp))], 
                                S_values[$(to_idx(:var_tp))], 
                                $(ref_mean_tp), $(ref_var_tp));
          S_values[$(to_idx(:d))] = val_d;
-        :final)
+         :final)
 
         # mid
         # * mid => mid
-        struct $(edge_name(:mid, :mid, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(edge_name(:mid, :mid, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:mid, :mid, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
+        @everywhere $(check_constraints(:mid, :mid, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         S_values[$(to_idx(:n))] < $N
-        $(update_state!)(edge::$(edge_name(:mid, :mid, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
+        @everywhere $(update_state!(:mid, :mid, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
         (:mid)
 
         # * mid => low 
-        struct $(edge_name(:mid, :low, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(edge_name(:mid, :low, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:mid, :low, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
+        @everywhere $(check_constraints(:mid, :low, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         S_values[$(to_idx(:n))] < $N &&
         S_values[$(to_idx(:top))] == 0.0
-        $(update_state!)(edge::$(edge_name(:mid, :low, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
+        @everywhere $(update_state!(:mid, :low, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
         (:low)
 
-        struct $(edge_name(:mid, :low, 2)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(edge_name(:mid, :low, 2)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:mid, :low, 2)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
+        @everywhere $(check_constraints(:mid, :low, 2))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         S_values[$(to_idx(:n))] == -1.0 &&
         S_values[$(to_idx(:top))] == 1.0
-        $(update_state!)(edge::$(edge_name(:mid, :low, 2)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
+        @everywhere $(update_state!(:mid, :low, 2))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
         (S_values[$(to_idx(:n))] = S_values[$(to_idx(:n))] + 1;
          S_values[$(to_idx(:top))] = 0.0;
          S_values[$(to_idx(:tp))] = 0.0;
          :low)
 
-        struct $(edge_name(:mid, :low, 3)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(edge_name(:mid, :low, 3)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:mid, :low, 3)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
+        @everywhere $(check_constraints(:mid, :low, 3))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (S_values[$(to_idx(:n))] == 0.0) &&
         S_values[$(to_idx(:top))] == 1.0
-        $(update_state!)(edge::$(edge_name(:mid, :low, 3)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
+        @everywhere $(update_state!(:mid, :low, 3))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
         (S_values[$(to_idx(:n))] = S_values[$(to_idx(:n))] + 1;
          S_values[$(to_idx(:top))] = 0.0;
          S_values[$(to_idx(:mean_tp))] = f_mean_tp(S_values[$(to_idx(:mean_tp))], 
@@ -181,11 +192,11 @@ function create_period_automaton(m::ContinuousTimeModel, L::Float64, H::Float64,
          S_values[$(to_idx(:tp))] = 0.0;
          :low)
 
-        struct $(edge_name(:mid, :low, 4)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(edge_name(:mid, :low, 4)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:mid, :low, 4)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
+        @everywhere $(check_constraints(:mid, :low, 4))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         (1 <= S_values[$(to_idx(:n))] < $N) &&
         S_values[$(to_idx(:top))] == 1.0
-        $(update_state!)(edge::$(edge_name(:mid, :low, 4)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
+        @everywhere $(update_state!(:mid, :low, 4))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
         (S_values[$(to_idx(:n))] = S_values[$(to_idx(:n))] + 1;
          S_values[$(to_idx(:top))] = 0.0;
          S_values[$(to_idx(:var_tp))] = g_var_tp(S_values[$(to_idx(:var_tp))], 
@@ -199,50 +210,51 @@ function create_period_automaton(m::ContinuousTimeModel, L::Float64, H::Float64,
          :low)
 
         # * mid => high
-        struct $(edge_name(:mid, :high, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(edge_name(:mid, :high, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:mid, :high, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
+        @everywhere $(check_constraints(:mid, :high, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         S_values[$(to_idx(:n))] < $N
-        $(update_state!)(edge::$(edge_name(:mid, :high, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
+        @everywhere $(update_state!(:mid, :high, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
         (S_values[$(to_idx(:top))] = 1.0;
          :high)
 
         # * mid => final
-        struct $(edge_name(:mid, :final, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(edge_name(:mid, :final, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:mid, :final, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
+        @everywhere $(check_constraints(:mid, :final, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         S_values[$(to_idx(:n))] == $N
-        $(update_state!)(edge::$(edge_name(:mid, :final, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
+        @everywhere $(update_state!(:mid, :final, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
         (val_d = $(error_func)(S_values[$(to_idx(:mean_tp))],
                                S_values[$(to_idx(:var_tp))],
                                $(ref_mean_tp), $(ref_var_tp));
          S_values[$(to_idx(:d))] = val_d;
-        :final)
+         :final)
 
         # high 
         # * high => high
-        struct $(edge_name(:high, :high, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(edge_name(:high, :high, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:high, :high, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
+        @everywhere $(check_constraints(:high, :high, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         S_values[$(to_idx(:n))] < $N
-        $(update_state!)(edge::$(edge_name(:high, :high, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
+        @everywhere $(update_state!(:high, :high, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
         (:high)
 
         # * high => mid
-        struct $(edge_name(:high, :mid, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(edge_name(:high, :mid, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:high, :mid, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
+        @everywhere $(check_constraints(:high, :mid, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         S_values[$(to_idx(:n))] < $N
-        $(update_state!)(edge::$(edge_name(:high, :mid, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
+        @everywhere $(update_state!(:high, :mid, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
         (:mid)
 
         # * high => final
-        struct $(edge_name(:high, :final, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
-        $(check_constraints)(edge::$(edge_name(:high, :final, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
+        #struct $(edge_name(:high, :final, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
+        @everywhere $(check_constraints(:high, :final, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
         S_values[$(to_idx(:n))] == $N
-        $(update_state!)(edge::$(edge_name(:high, :final, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
+        @everywhere $(update_state!(:high, :final, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) =
         (val_d = $(error_func)(S_values[$(to_idx(:mean_tp))],
                                S_values[$(to_idx(:var_tp))],
                                $(ref_mean_tp), $(ref_var_tp));
          S_values[$(to_idx(:d))] = val_d;
-        :final)
+         :final)
     end
+    eval(meta_funcs)
 
     @eval begin
         map_edges = Dict{Location, Dict{Location, Vector{$(edge_type)}}}()
@@ -252,73 +264,80 @@ function create_period_automaton(m::ContinuousTimeModel, L::Float64, H::Float64,
 
         # l0 loc 
         # * l0 => l0
-        edge1 = $(edge_name(:l0, :l0, 1))([:ALL])
+        edge1 = EdgePeriodAutomaton([:ALL], $(check_constraints(:l0, :l0, 1)), $(update_state!(:l0, :l0, 1)))
         map_edges[:l0][:l0] = [edge1]
         # * l0 => l0prime
-        edge1 = $(edge_name(:l0, :l0prime, 1))(nothing)
+        edge1 = EdgePeriodAutomaton(nothing, $(check_constraints(:l0, :l0prime, 1)), $(update_state!(:l0, :l0prime, 1)))
         map_edges[:l0][:l0prime] = [edge1]
         # * l0 => low
-        edge1 = $(edge_name(:l0, :low, 1))(nothing)
+        edge1 = EdgePeriodAutomaton(nothing, $(check_constraints(:l0, :low, 1)), $(update_state!(:l0, :low, 1)))
         map_edges[:l0][:low] = [edge1]
 
         # l0prime
         # * l0prime => l0prime
-        edge1 = $(edge_name(:l0prime, :l0prime, 1))([:ALL])
+        edge1 = EdgePeriodAutomaton([:ALL], $(check_constraints(:l0prime, :l0prime, 1)), $(update_state!(:l0prime, :l0prime, 1)))
         map_edges[:l0prime][:l0prime] = [edge1]
         # * l0prime => low
-        edge1 = $(edge_name(:l0prime, :low, 1))(nothing)
+        edge1 = EdgePeriodAutomaton(nothing, $(check_constraints(:l0prime, :low, 1)), $(update_state!(:l0prime, :low, 1)))
         map_edges[:l0prime][:low] = [edge1]
 
         # low 
         # * low => low
-        edge1 = $(edge_name(:low, :low, 1))([:ALL])
+        edge1 = EdgePeriodAutomaton([:ALL], $(check_constraints(:low, :low, 1)), $(update_state!(:low, :low, 1)))
         map_edges[:low][:low] = [edge1]
         # * low => mid 
-        edge1 = $(edge_name(:low, :mid, 1))([:ALL])
+        edge1 = EdgePeriodAutomaton([:ALL], $(check_constraints(:low, :mid, 1)), $(update_state!(:low, :mid, 1)))
         map_edges[:low][:mid] = [edge1]
         # * low => final
-        edge1 = $(edge_name(:low, :final, 1))(nothing)
+        edge1 = EdgePeriodAutomaton(nothing, $(check_constraints(:low, :final, 1)), $(update_state!(:low, :final, 1)))
         map_edges[:low][:final] = [edge1]
 
         # mid
         # * mid => mid
-        edge1 = $(edge_name(:mid, :mid, 1))([:ALL])
+        edge1 = EdgePeriodAutomaton([:ALL], $(check_constraints(:mid, :mid, 1)), $(update_state!(:mid, :mid, 1)))
         map_edges[:mid][:mid] = [edge1]
         # * mid => low 
-        edge1 = $(edge_name(:mid, :low, 1))([:ALL])
-        edge2 = $(edge_name(:mid, :low, 2))([:ALL])
-        edge3 = $(edge_name(:mid, :low, 3))([:ALL])
-        edge4 = $(edge_name(:mid, :low, 4))([:ALL])
+        edge1 = EdgePeriodAutomaton([:ALL], $(check_constraints(:mid, :low, 1)), $(update_state!(:mid, :low, 1)))
+        edge2 = EdgePeriodAutomaton([:ALL], $(check_constraints(:mid, :low, 2)), $(update_state!(:mid, :low, 2)))
+        edge3 = EdgePeriodAutomaton([:ALL], $(check_constraints(:mid, :low, 3)), $(update_state!(:mid, :low, 3)))
+        edge4 = EdgePeriodAutomaton([:ALL], $(check_constraints(:mid, :low, 4)), $(update_state!(:mid, :low, 4)))
         map_edges[:mid][:low] = [edge1, edge2, edge3, edge4]
         # * mid => high
-        edge1 = $(edge_name(:mid, :high, 1))([:ALL])
+        edge1 = EdgePeriodAutomaton([:ALL], $(check_constraints(:mid, :high, 1)), $(update_state!(:mid, :high, 1)))
         map_edges[:mid][:high] = [edge1]
         # * mid => final
-        edge1 = $(edge_name(:mid, :final, 1))(nothing)
+        edge1 = EdgePeriodAutomaton(nothing, $(check_constraints(:mid, :final, 1)), $(update_state!(:mid, :final, 1)))
         map_edges[:mid][:final] = [edge1]
 
         # high 
         # * high => high
-        edge1 = $(edge_name(:high, :high, 1))([:ALL])
+        edge1 = EdgePeriodAutomaton([:ALL], $(check_constraints(:high, :high, 1)), $(update_state!(:high, :high, 1)))
         map_edges[:high][:high] = [edge1]
         # * high => mid
-        edge1 = $(edge_name(:high, :mid, 1))([:ALL])
+        edge1 = EdgePeriodAutomaton([:ALL], $(check_constraints(:high, :mid, 1)), $(update_state!(:high, :mid, 1)))
         map_edges[:high][:mid] = [edge1]
         # * high => final
-        edge1 = $(edge_name(:high, :final, 1))(nothing)
+        edge1 = EdgePeriodAutomaton(nothing, $(check_constraints(:high, :final, 1)), $(update_state!(:high, :final, 1)))
         map_edges[:high][:final] = [edge1] 
     end
 
+    ## Create data separately
+    map_edges_transitions = Dict{Symbol, Dict{Symbol,Vector{TransitionSet}}}()
+    map_edges_check_constraints = Dict{Symbol, Dict{Symbol,Vector{CheckConstraintsFunction}}}()
+    map_edges_update_state = Dict{Symbol, Dict{Symbol,Vector{UpdateStateFunction}}}()
+
     ## Constants
     constants = Dict{Symbol,Float64}(:N => N, :L => L, :H => H, :initT => initT)
 
     # Updating types and simulation methods
     @everywhere @eval $(MarkovProcesses.generate_code_synchronized_model_type_def(model_name, lha_name))
-    @everywhere @eval $(MarkovProcesses.generate_code_next_state(lha_name, edge_type, check_constraints, update_state!))
+    @everywhere @eval $(MarkovProcesses.generate_code_next_state(lha_name, edge_type))
     @everywhere @eval $(MarkovProcesses.generate_code_synchronized_simulation(model_name, lha_name, edge_type, m.f!, m.isabsorbing))
 
     A = PeriodAutomaton(m.transitions, locations, Λ_F, locations_init, locations_final, 
-                        map_var_automaton_idx, flow, map_edges, constants, m.map_var_idx)
+                        map_var_automaton_idx, flow, map_edges, 
+                        map_edges_transitions, map_edges_check_constraints, map_edges_update_state,
+                        constants, m.map_var_idx)
     return A
 end
 
diff --git a/bench/pkg/sim_sync_R6.jl b/bench/pkg/sim_sync_R6.jl
index ab5984a18741f5954700ae6179ebe8c532ae9a4f..9af292a4d886eab4caa3aa826ba67e6bde7b7f82 100644
--- a/bench/pkg/sim_sync_R6.jl
+++ b/bench/pkg/sim_sync_R6.jl
@@ -1,6 +1,6 @@
 
 using BenchmarkTools
-using MarkovProcesses
+@everywhere using MarkovProcesses
 using Profile
 
 load_model("ER")
diff --git a/core/MarkovProcesses.jl b/core/MarkovProcesses.jl
index 257be50be470f153d944f878680fb0467a245490..e9f285cf83b2695d64eee87d2231d4b64665db79 100644
--- a/core/MarkovProcesses.jl
+++ b/core/MarkovProcesses.jl
@@ -10,17 +10,19 @@ import Distributed: @everywhere, @distributed
 import Distributions: Product, Uniform, Normal
 import Distributions: Distribution, Univariate, Continuous, UnivariateDistribution, 
                       MultivariateDistribution, product_distribution
+import FunctionWrappers: FunctionWrapper
 import StaticArrays: SVector, @SVector
 
 ## Exports
 export Distribution, Product, Uniform, Normal
 
 # Common types and constructors
-export Observations, AbstractTrajectory, Trajectory, SynchronizedTrajectory
 export SVector, @SVector
+export Observations, AbstractTrajectory, Trajectory, SynchronizedTrajectory
 export Model, ContinuousTimeModel, SynchronizedModel, ParametricModel
 export VariableModel, ParameterModel, Transition, TransitionSet
 export LHA, StateLHA, Edge, Location, VariableAutomaton
+export InvariantPredicateFunction, CheckConstraintsFunction, UpdateStateFunction
 
 # Trajectory related methods
 export +, -, δ, dist_lp, euclidean_distance
diff --git a/core/common.jl b/core/common.jl
index 4a501df49cbc18fc0bfc4bfc8eff803b0d11246e..960c6f90d70cef1ecb9f3a14680a040cc9f8dcd5 100644
--- a/core/common.jl
+++ b/core/common.jl
@@ -11,8 +11,12 @@ abstract type Edge end
 const VariableModel = Symbol
 const ParameterModel = Symbol
 const Transition = Union{Symbol,Nothing}
+const TransitionSet = Union{Vector{Symbol},Nothing}
 const Location = Symbol
 const VariableAutomaton = Symbol
+const InvariantPredicateFunction = FunctionWrapper{Bool,Tuple{Vector{Int}}}
+const CheckConstraintsFunction = FunctionWrapper{Bool,Tuple{Float64,Vector{Float64},Vector{Int},Vector{Float64}}}
+const UpdateStateFunction = FunctionWrapper{Symbol,Tuple{Float64,Vector{Float64},Vector{Int},Vector{Float64}}}
 
 function generate_code_model_type_def(model_name::Symbol)
     return quote
@@ -49,12 +53,15 @@ function generate_code_lha_type_def(lha_name::Symbol, edge_type::Symbol)
         struct $(lha_name) <: LHA
             transitions::Vector{Transition}
             locations::Vector{Location} 
-            Λ::Dict{Location,Function}
+            Λ::Dict{Location,InvariantPredicateFunction}
             locations_init::Vector{Location}
             locations_final::Vector{Location}
             map_var_automaton_idx::Dict{VariableAutomaton,Int} # nvar keys : str_var => idx in values
             flow::Dict{Location,Vector{Float64}} # output of length nvar
             map_edges::Dict{Location, Dict{Location,Vector{$(edge_type)}}}
+            map_edges_transitions::Dict{Location, Dict{Location,Vector{TransitionSet}}}
+            map_edges_check_constraints::Dict{Location, Dict{Location,Vector{CheckConstraintsFunction}}}
+            map_edges_update_state::Dict{Location, Dict{Location,Vector{UpdateStateFunction}}}
             constants::Dict{Symbol,Float64}
             map_var_model_idx::Dict{VariableModel,Int} # of dim d (of a model)
         end
@@ -129,7 +136,9 @@ end
 
 LHA(A::LHA, map_var::Dict{VariableModel,Int}) = 
 getfield(Main, Symbol(typeof(A)))(A.transitions, A.locations, A.Λ, A.locations_init, A.locations_final, 
-                                  A.map_var_automaton_idx, A.flow, A.map_edges, A.constants, map_var)
+                                  A.map_var_automaton_idx, A.flow, A.map_edges, 
+                                  A.map_edges_transitions, A.map_edges_check_constraints, A.map_edges_update_state,
+                                  A.constants, map_var)
 
 function ParametricModel(am::Model, priors::Tuple{ParameterModel,UnivariateDistribution}...)
     m = get_proba_model(am)
diff --git a/core/lha.jl b/core/lha.jl
index 8f5fcc5f1d9514aae63417bee8a3c8e96071086c..fb81e59b80073ddf8eab128a68f871d837c60f89 100644
--- a/core/lha.jl
+++ b/core/lha.jl
@@ -90,8 +90,234 @@ function init_state(A::LHA, x0::Vector{Int}, t0::Float64)
     return S0
 end
 
-function generate_code_next_state(lha_name::Symbol, edge_type::Symbol, 
-                                  check_constraints::Symbol, update_state!::Symbol)
+function generate_code_next_state_with_dicts_lha(lha_name::Symbol, edge_type::Symbol)
+    
+    return quote 
+        # A push! method implementend by myself because of preallocation of edge_candidates
+        function _push_edge!(edge_id_candidates::Vector{Int}, target_loc_candidates::Vector{Symbol}, 
+                             edge_id::Int, target_loc::Symbol, nbr_candidates::Int)
+            if nbr_candidates < length(edge_id_candidates)
+                 edge_id_candidates[nbr_candidates+1] = edge_id
+                 target_loc_candidates[nbr_candidates+1] = target_loc
+            else
+                push!(edge_id_candidates, edge_id)
+                push!(target_loc_candidates, target_loc)
+            end
+        end
+
+        function _find_edge_candidates!(edge_id_candidates::Vector{Int}, target_loc_candidates::Vector{Symbol},
+                                        dict_transitions_from_current_loc::Dict{Location,Vector{TransitionSet}},
+                                        dict_check_constraints_from_current_loc::Dict{Location,Vector{Function}},
+                                        Λ::Dict{Location,InvariantPredicateFunction},
+                                        S_time::Float64, S_values::Vector{Float64},
+                                        x::Vector{Int}, p::Vector{Float64},
+                                        only_asynchronous::Bool)
+            nbr_candidates = 0
+            for target_loc in keys(dict_transitions_from_current_loc)
+                if !Λ[target_loc](x) continue end
+                for i = eachindex(dict_transitions_from_current_loc[target_loc])
+                    check_constraints_edge = dict_check_constraints_from_current_loc[target_loc][i]
+                    if check_constraints_edge(S_time, S_values, x, p)
+                        transitions = dict_transitions_from_current_loc[target_loc][i]
+                        if transitions == nothing
+                            _push_edge!(edge_id_candidates, target_loc_candidates, i, target_loc, nbr_candidates)
+                            nbr_candidates += 1
+                            return nbr_candidates
+                        else
+                            if !only_asynchronous
+                                _push_edge!(edge_id_candidates, target_loc_candidates, i, target_loc, nbr_candidates)
+                                nbr_candidates += 1
+                            end
+                        end
+                    end
+                end
+            end
+            return nbr_candidates
+        end
+
+        function _get_edge_index(edge_id_candidates::Vector{Int}, target_loc_candidates::Vector{Symbol}, nbr_candidates::Int,
+                                 dict_transitions_from_current_loc::Dict{Location,Vector{TransitionSet}},
+                                 detected_event::Bool, tr_nplus1::Transition)
+            ind_edge = 0
+            bool_event = detected_event
+            for i = 1:nbr_candidates
+                target_loc = target_loc_candidates[i]
+                edge_id = edge_id_candidates[i]
+                transitions = dict_transitions_from_current_loc[target_loc][edge_id]
+                # Asynchronous edge detection: we fire it
+                if transitions == nothing
+                    return (i, detected_event)
+                end
+                # Synchronous detection
+                if !detected_event && tr_nplus1 != nothing
+                    if (transitions[1] == :ALL) || (tr_nplus1 in transitions)
+                        ind_edge = i
+                        bool_event = true
+                    end
+                end
+            end
+            return (ind_edge, bool_event)
+        end
+
+        function next_state!(A::$(lha_name),
+                             ptr_loc_state::Vector{Symbol}, values_state::Vector{Float64}, ptr_time_state::Vector{Float64},
+                             xnplus1::Vector{Int}, tnplus1::Float64, tr_nplus1::Transition, 
+                             xn::Vector{Int}, p::Vector{Float64},
+                             edge_id_candidates::Vector{Int}, target_loc_candidates::Vector{Symbol}; verbose::Bool = false)
+            # En fait d'apres observation de Cosmos, après qu'on ait lu la transition on devrait stop.
+            detected_event::Bool = false
+            turns = 0
+            Λ = getfield(A, :Λ)
+            flow = getfield(A, :flow)
+            map_edges = A.map_edges
+            map_edges_transitions = A.map_edges_transitions
+            map_edges_check_constraints = A.map_edges_check_constraints
+            map_edges_update_state = A.map_edges_update_state
+            if verbose 
+                println("##### Begin next_state!")
+                @show xnplus1, tnplus1, tr_nplus1
+            end
+            # First, we check the asynchronous transitions
+            while true
+                turns += 1
+                if verbose @show turns end
+                #edge_candidates = empty!(edge_candidates) 
+                dict_transitions_from_current_loc = map_edges_transitions[ptr_loc_state[1]]
+                dict_check_constraints_from_current_loc = map_edges_check_constraints[ptr_loc_state[1]]
+                # Save all edges that satisfies transition predicate (asynchronous ones)
+                nbr_candidates = _find_edge_candidates!(edge_id_candidates, target_loc_candidates, 
+                                                        dict_transitions_from_current_loc, dict_check_constraints_from_current_loc,
+                                                        Λ, ptr_time_state[1], values_state, xn, p, true)
+                # 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_id_candidates, target_loc_candidates, nbr_candidates, 
+                                                           dict_transitions_from_current_loc,
+                                                           detected_event, nothing)
+                # Update the state with the chosen one (if it exists)
+                # Should be xn here
+                #first_round = false
+                if ind_edge > 0
+                    edge_target_loc = target_loc_candidates[ind_edge]
+                    edge_id = edge_id_candidates[ind_edge]
+                    firing_update_state! = map_edges_update_state[ptr_loc_state[1]][edge_target_loc][edge_id]
+                    ptr_loc_state[1] = firing_update_state!(ptr_time_state[1], values_state, xn, p)
+                else
+                    if verbose 
+                        println("No edge fired:")
+                        @show ind_edge, detected_event, nbr_candidates
+                    end
+                    break 
+                end
+                if verbose
+                    println("Edge fired:")
+                    @show edge_id_candidates, target_loc_candidates
+                    @show ind_edge, detected_event, nbr_candidates
+                    @show ptr_loc_state[1]
+                    @show ptr_time_state[1]
+                    @show values_state
+                    if turns == 500
+                        @warn "We've reached 500 turns"
+                    end
+                end
+                # For debug
+                #=
+                if turns > 100
+                println("Number of turns in next_state! is suspicious")
+                @show first_round, detected_event
+                @show length(edge_candidates)
+                @show tnplus1, tr_nplus1, xnplus1
+                @show edge_candidates
+                error("Unpredicted behavior automaton")
+                end
+                =#
+            end
+            if verbose 
+                println("Time flies with the flow...")
+            end
+            # Now time flies according to the flow
+            for i in eachindex(values_state)
+                 coeff_deriv = flow[ptr_loc_state[1]][i]
+                if coeff_deriv > 0
+                      values_state[i] += coeff_deriv*(tnplus1 - ptr_time_state[1])
+                end
+            end
+            ptr_time_state[1] = tnplus1
+            if verbose 
+                @show ptr_loc_state[1]
+                @show ptr_time_state[1]
+                @show values_state
+            end
+            # Now firing an edge according to the event 
+            while true
+                turns += 1
+                if verbose @show turns end
+                edges_from_current_loc = map_edges[ptr_loc_state[1]]
+                dict_transitions_from_current_loc = map_edges_transitions[ptr_loc_state[1]]
+                dict_check_constraints_from_current_loc = map_edges_check_constraints[ptr_loc_state[1]]
+                # Save all edges that satisfies transition predicate (synchronous ones)
+                nbr_candidates = _find_edge_candidates!(edge_id_candidates, target_loc_candidates,
+                                                        dict_transitions_from_current_loc, dict_check_constraints_from_current_loc,
+                                                        Λ, ptr_time_state[1], values_state, xnplus1, p, false)
+                # Search the one we must chose
+                ind_edge, detected_event = _get_edge_index(edge_id_candidates, target_loc_candidates, nbr_candidates, 
+                                                           dict_transitions_from_current_loc,
+                                                           detected_event, tr_nplus1)
+                # Update the state with the chosen one (if it exists)
+                if ind_edge > 0
+                    edge_target_loc = target_loc_candidates[ind_edge]
+                    edge_id = edge_id_candidates[ind_edge]
+                    firing_update_state! = map_edges_update_state[ptr_loc_state[1]][edge_target_loc][edge_id]
+                    ptr_loc_state[1] = firing_update_state!(ptr_time_state[1], values_state, xnplus1, p)
+                end
+                if ind_edge == 0 || detected_event
+                    if verbose 
+                        if detected_event    
+                            println("Synchronized with $(tr_nplus1)") 
+                            @show edge_id_candidates, target_loc_candidates
+                            @show ind_edge, detected_event, nbr_candidates
+                            @show detected_event
+                            @show ptr_loc_state[1]
+                            @show ptr_time_state[1]
+                            @show values_state
+                        else
+                            println("No edge fired")
+                        end
+                    end
+                    break 
+                end
+                if verbose
+                    @show edge_id_candidates, target_loc_candidates
+                    @show ind_edge, detected_event, nbr_candidates
+                    @show detected_event
+                    @show ptr_loc_state[1]
+                    @show ptr_time_state[1]
+                    @show values_state
+                    if turns == 500
+                        @warn "We've reached 500 turns"
+                    end
+                end
+                # For debug
+                #=
+                if turns > 100
+                println("Number of turns in next_state! is suspicious")
+                @show detected_event
+                @show length(edge_candidates)
+                @show tnplus1, tr_nplus1, xnplus1
+                @show edge_candidates
+                error("Unpredicted behavior automaton")
+                end
+                =#
+            end
+            if verbose 
+                println("##### End next_state!") 
+            end
+        end
+    end
+end
+
+############################################################################################################
+
+function generate_code_next_state(lha_name::Symbol, edge_type::Symbol)
     
     return quote 
         # A push! method implementend by myself because of preallocation of edge_candidates
@@ -105,7 +331,7 @@ function generate_code_next_state(lha_name::Symbol, edge_type::Symbol,
 
         function _find_edge_candidates!(edge_candidates::Vector{$(edge_type)},
                                         edges_from_current_loc::Dict{Location,Vector{$(edge_type)}},
-                                        Λ::Dict{Location,Function},
+                                        Λ::Dict{Location,InvariantPredicateFunction},
                                         S_time::Float64, S_values::Vector{Float64},
                                         x::Vector{Int}, p::Vector{Float64},
                                         only_asynchronous::Bool)
@@ -113,8 +339,8 @@ function generate_code_next_state(lha_name::Symbol, edge_type::Symbol,
             for target_loc in keys(edges_from_current_loc)
                 if !Λ[target_loc](x) continue end
                 for edge in edges_from_current_loc[target_loc]
-                    if $(check_constraints)(edge, S_time, S_values, x, p)
-                        if getfield(edge, :transitions) == nothing
+                    if edge.check_constraints(S_time, S_values, x, p)
+                        if edge.transitions == nothing
                             _push_edge!(edge_candidates, edge, nbr_candidates)
                             nbr_candidates += 1
                             return nbr_candidates
@@ -137,13 +363,12 @@ function generate_code_next_state(lha_name::Symbol, edge_type::Symbol,
             for i = 1:nbr_candidates
                 edge = edge_candidates[i]
                 # Asynchronous edge detection: we fire it
-                if getfield(edge, :transitions) == nothing
+                if edge.transitions == nothing
                     return (i, detected_event)
                 end
                 # Synchronous detection
                 if !detected_event && tr_nplus1 != nothing
-                    if (getfield(edge, :transitions)[1] == :ALL) || 
-                        (tr_nplus1 in getfield(edge, :transitions))
+                    if (edge.transitions[1] == :ALL) || (tr_nplus1 in edge.transitions)
                         ind_edge = i
                         bool_event = true
                     end
@@ -184,7 +409,7 @@ function generate_code_next_state(lha_name::Symbol, edge_type::Symbol,
                 #first_round = false
                 if ind_edge > 0
                     firing_edge = edge_candidates[ind_edge]
-                    ptr_loc_state[1] = $(update_state!)(firing_edge, ptr_time_state[1], values_state, xn, p)
+                    ptr_loc_state[1] = firing_edge.update_state!(ptr_time_state[1], values_state, xn, p)
                 else
                     if verbose println("No edge fired") end
                     break 
@@ -240,7 +465,7 @@ function generate_code_next_state(lha_name::Symbol, edge_type::Symbol,
                 # Update the state with the chosen one (if it exists)
                 if ind_edge > 0
                     firing_edge = edge_candidates[ind_edge]
-                    ptr_loc_state[1] = $(update_state!)(firing_edge, ptr_time_state[1], values_state, xnplus1, p)
+                    ptr_loc_state[1] = firing_edge.update_state!(ptr_time_state[1], values_state, xnplus1, p)
                 end
                 if ind_edge == 0 || detected_event
                     if verbose 
diff --git a/tests/automaton_abc/distributed_R1.jl b/tests/automaton_abc/distributed_R1.jl
index 5fda0e80c3ac1a5068dd964100a06ea8fc6bb859..ecbece35a684a7ff22b7e4548750a84000b46032 100644
--- a/tests/automaton_abc/distributed_R1.jl
+++ b/tests/automaton_abc/distributed_R1.jl
@@ -1,12 +1,12 @@
 
-using Distributed
 using MarkovProcesses
-begin_procs = nprocs()
-if begin_procs == 1
-    addprocs(2)
-end
-path_module = get_module_path() * "/core"
-
+using Distributed
+addprocs(2)
+module_path = get_module_path()
+@everywhere module_path = $module_path
+@everywhere push!(LOAD_PATH, "$(module_path)/core")
+@everywhere using MarkovProcesses
+#=
 @everywhere begin
     path_module = $(path_module)
     push!(LOAD_PATH, path_module)
@@ -14,6 +14,9 @@ path_module = get_module_path() * "/core"
     load_model("ER")
     load_automaton("automaton_F")
 end
+=#
+load_model("ER")
+load_automaton("automaton_F")
 A_F_R1 = create_automaton_F(ER, 50.0, 75.0, 0.025, 0.05, :P)
 sync_ER = A_F_R1*ER 
 pm_sync_ER = ParametricModel(sync_ER, (:k3, Uniform(0.0, 100.0)))
@@ -21,9 +24,7 @@ nbr_pa = 404
 
 r = automaton_abc(pm_sync_ER; nbr_particles = nbr_pa)
 
-if begin_procs == 1
-    rmprocs(workers())
-end
+rmprocs(2)
 
 test = size(r.mat_p_end)[1] == pm_sync_ER.df &&
        size(r.mat_p_end)[2] == nbr_pa &&
diff --git a/tests/run_abc_smc.jl b/tests/run_abc_smc.jl
index c92284053f2411c88850fd570d0fe9d5500f2541..8848094b1460ebd2bdd87d1afc5bc88f447130d7 100644
--- a/tests/run_abc_smc.jl
+++ b/tests/run_abc_smc.jl
@@ -3,7 +3,7 @@ using Test
 
 @testset "ABC SMC and automaton-ABC tests" begin
     @test include("automaton_abc/R1.jl")
-    #test_distributed_R1 = include("automaton_abc/distributed_R1.jl")
+    @test include("automaton_abc/distributed_R1.jl")
     #@test test_distributed_R1
 end