automaton_G.jl 16.4 KB
Newer Older
1

2
# Creation of the automaton types
3 4 5 6 7 8
#@everywhere @eval abstract type EdgeAutomatonG <: Edge end
@everywhere struct EdgeAutomatonG <: Edge 
    transitions::TransitionSet 
    check_constraints::CheckConstraintsFunction
    update_state!::UpdateStateFunction
end
9
@everywhere @eval $(MarkovProcesses.generate_code_lha_type_def(:AutomatonG, :EdgeAutomatonG))
10

11
function create_automaton_G(m::ContinuousTimeModel, x1::Float64, x2::Float64, t1::Float64, t2::Float64, sym_obs::VariableModel)
12 13 14 15
    # Requirements for the automaton
    @assert sym_obs in m.g "$(sym_obs) is not observed."
    @assert (x1 <= x2) "x1 > x2 impossible for G automaton."
    @assert (t1 <= t2) "t1 > t2 impossible for G automaton."
16 17 18 19 20 21 22 23

    # Automaton types and functions
    model_name = Symbol(typeof(m))
    lha_name = :AutomatonG
    edge_type = :EdgeAutomatonG
    check_constraints = Symbol("check_constraints_$(lha_name)")
    update_state! = Symbol("update_state_$(lha_name)!")

24
    # Locations
25
    locations = [:l0, :l1, :l2, :l3, :l4]
26 27

    # Invariant predicates
28
    @everywhere true_inv_predicate(x::Vector{Int}) = true 
29 30 31
    Λ_F = Dict(:l0 => getfield(Main, :true_inv_predicate), :l1 => getfield(Main, :true_inv_predicate),
               :l2 => getfield(Main, :true_inv_predicate), :l3 => getfield(Main, :true_inv_predicate), 
               :l4 => getfield(Main, :true_inv_predicate))
32

33
    ## Init and final loc
34 35
    locations_init = [:l0]
    locations_final = [:l2]
36 37

    ## Map of automaton variables
38 39
    map_var_automaton_idx = Dict{VariableAutomaton,Int}(:tprime => 1, :in => 2,
                                                        :n => 3,  :d => 4, :isabs => 5)
40 41

    ## Flow of variables
42 43 44 45 46
    flow = Dict{Location,Vector{Float64}}(:l0 => [0.0,0.0,0.0,0.0,0.0], 
                                          :l1 => [0.0,0.0,0.0,0.0,0.0], 
                                          :l2 => [0.0,0.0,0.0,0.0,0.0], 
                                          :l3 => [0.0,0.0,0.0,0.0,0.0], 
                                          :l4 => [1.0,0.0,0.0,0.0,0.0])
47 48

    ## Edges
49
    to_idx(var::Symbol) = map_var_automaton_idx[var]
50
    idx_obs_var = getfield(m, :map_var_idx)[sym_obs]
51 52 53 54
    id = MarkovProcesses.newid()
    basename_func = "$(model_name)_$(id)"
    edge_name(from_loc::Location, to_loc::Location, edge_number::Int) = 
    Symbol("Edge_$(lha_name)_$(basename_func)_$(from_loc)$(to_loc)_$(edge_number)")
55 56 57 58 59 60
    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
61 62

    ## check_constraints & update_state!
63 64
    meta_funcs = quote
        @everywhere istrue(val::Float64) = convert(Bool, val)
65 66
        # l0 loc
        # l0 => l1
67 68 69
        #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}) = 
70 71 72 73 74
        (S_values[$(to_idx(:d))] = 0;
         S_values[$(to_idx(:n))] = x[$(idx_obs_var)];
         S_values[$(to_idx(:in))] = true;
         S_values[$(to_idx(:isabs))] = $(m.isabsorbing)(p,x);
         :l1)
75 76

        # l1 => l3
77 78
        #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}) = 
79
        S_time <= $t1 && 
80
        S_values[$(to_idx(:n))] < $x1 || S_values[$(to_idx(:n))] > $x2
81
        @everywhere $(update_state!(:l1, :l3, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
82 83 84 85
        (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)

86 87
        #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}) = 
88
        (S_time <= $t1) && 
89
        ($x1 <= S_values[$(to_idx(:n))] <= $x2)
90
        @everywhere $(update_state!(:l1, :l3, 2))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
91 92 93 94
        (S_values[$(to_idx(:d))] = 0;
         S_values[$(to_idx(:in))] = false;
         :l3)

95 96
        #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}) = 
97
        !istrue(S_values[$(to_idx(:in))]) && 
98
        ($t1 <= S_time <= $t2) && 
99
        ($x1 <= S_values[$(to_idx(:n))] <= $x2)
100
        @everywhere $(update_state!(:l1, :l3, 3))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
101 102 103 104
        (S_values[$(to_idx(:d))] = S_values[$(to_idx(:d))] * (S_time - $t1);
         S_values[$(to_idx(:tprime))] = 0.0;
         :l3)

105 106
        #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}) = 
107
        istrue(S_values[$(to_idx(:in))]) && 
108
        ($t1 <= S_time <= $t2) && 
109
        ($x1 <= S_values[$(to_idx(:n))] <= $x2)
110
        @everywhere $(update_state!(:l1, :l3, 4))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
111 112
        (S_values[$(to_idx(:tprime))] = 0.0;
         :l3)
113 114

        # l1 => l4
115 116
        #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}) = 
117
        !istrue(S_values[$(to_idx(:in))]) && 
118
        ($t1 <= S_time <= $t2) && 
119
        (S_values[$(to_idx(:n))] < $x1 || S_values[$(to_idx(:n))] > $x2)
120
        @everywhere $(update_state!(:l1, :l4, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
121 122 123
        (S_values[$(to_idx(:d))] = S_values[$(to_idx(:d))] + S_values[$(to_idx(:d))] * (S_time - $t1);
         :l4)

124 125
        #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}) = 
126
        istrue(S_values[$(to_idx(:in))]) && 
127
        ($t1 <= S_time <= $t2) && 
128
        (S_values[$(to_idx(:n))] < $x1 || S_values[$(to_idx(:n))] > $x2)
129
        @everywhere $(update_state!(:l1, :l4, 2))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
130
        (:l4)
131 132

        # l1 => l2
133
        #=
134 135
        #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}) = 
136
        istrue(S_values[$(to_idx(:in))]) && 
137
        S_time >= $t2
138
        @everywhere $(update_state!(:l1, :l2, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
139
        (:l2)
140

141 142
        #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}) = 
143
        !istrue(S_values[$(to_idx(:in))]) && 
144
        S_time >= $t2
145
        @everywhere $(update_state!(:l1, :l2, 2))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
146 147
        (S_values[$(to_idx(:d))] = S_values[$(to_idx(:d))] * ($t2 - $t1);
        :l2)
148

149 150
        #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}) = 
151
        istrue(S_values[$(to_idx(:isabs))]) && 
152
        S_time <= $t1
153
        @everywhere $(update_state!(:l1, :l2, 3))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
154 155
        (S_values[$(to_idx(:d))] = ($t2 - $t1) * min(abs($x1 - S_values[$(to_idx(:n))]), abs($x2 - S_values[$(to_idx(:n))]));
        :l2)
156

157 158
        #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}) = 
159
        istrue(S_values[$(to_idx(:isabs))]) && 
160
        ($t1 <= S_time <= $t2)
161
        @everywhere $(update_state!(:l1, :l2, 4))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
162 163
        (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)
164
        =#
165 166

        # l3 => l1
167 168 169
        #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}) = 
170 171 172
        (S_values[$(to_idx(:n))] = x[$(idx_obs_var)];
         S_values[$(to_idx(:isabs))] = $(m.isabsorbing)(p, x);
         :l1)
173 174

        # l4 => l1
175 176 177
        #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}) = 
178 179 180 181 182 183
        (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)];
         S_values[$(to_idx(:in))] = true;
         S_values[$(to_idx(:isabs))] = $(m.isabsorbing)(p,x);
         :l1)
184

185
        # l3 => l2
186 187
        #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}) = 
188 189
        istrue(S_values[$(to_idx(:in))]) && 
        (S_time >= $t2 || istrue(S_values[$(to_idx(:isabs))]))
190
        @everywhere $(update_state!(:l3, :l2, 2))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
191 192 193
        (S_values[$(to_idx(:d))] = S_values[$(to_idx(:d))] * ($t2 - $t1);
         :l2)

194 195
        #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}) = 
196 197
        !istrue(S_values[$(to_idx(:in))]) && 
        (S_time >= $t2 || istrue(S_values[$(to_idx(:isabs))]))
198
        @everywhere $(update_state!(:l3, :l2, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
199
        (:l2)
200 201

        # l4 => l2
202 203
        #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}) = 
204
        (istrue(S_values[$(to_idx(:isabs))]))
205
        @everywhere $(update_state!(:l4, :l2, 1))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
206 207 208 209
        (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)

210 211
        #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}) = 
212
        (S_time >= $t2)
213
        @everywhere $(update_state!(:l4, :l2, 2))(S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
214 215 216 217
        (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
218
    eval(meta_funcs)
219 220 221 222 223 224 225 226 227

    @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
228
        edge1 = EdgeAutomatonG(nothing, $(check_constraints(:l0, :l1, 1)), $(update_state!(:l0, :l1, 1)))
229 230 231 232
        map_edges[:l0][:l1] = [edge1]

        # l1 loc
        # l1 => l3
233 234 235 236
        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)))
237 238 239
        map_edges[:l1][:l3] = [edge1, edge2, edge3, edge4]

        # l1 => l4
240 241
        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)))
242 243 244 245
        map_edges[:l1][:l4] = [edge1, edge2]

        # l1 => l2
        #=
246 247 248 249
        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)))
250 251 252 253 254
        map_edges[:l1][:l2] = [edge1, edge2, edge3, edge4]
        =#

        # l3 loc
        # l3 => l1
255
        edge1 = EdgeAutomatonG([:ALL], $(check_constraints(:l3, :l1, 1)), $(update_state!(:l3, :l1, 1)))
256 257 258
        map_edges[:l3][:l1] = [edge1]

        # l3 => l2
259 260
        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)))
261 262 263 264
        map_edges[:l3][:l2] = [edge1, edge2]

        # l4 loc
        # l4 => l1
265
        edge1 = EdgeAutomatonG([:ALL], $(check_constraints(:l4, :l1, 1)), $(update_state!(:l4, :l1, 1)))
266 267 268
        map_edges[:l4][:l1] = [edge1]

        # l4 => l2
269 270
        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)))
271
        map_edges[:l4][:l2] = [edge1,edge2]
272
    end
273

274 275 276 277 278
    ## 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}}}()
    
279
    ## Constants
280
    constants = Dict{Symbol,Float64}(:x1 => x1,  :x2 => x2, :t1 => t1, :t2 => t2)
281

282 283
    # Updating types and simulation methods
    @everywhere @eval $(MarkovProcesses.generate_code_synchronized_model_type_def(model_name, lha_name))
284
    @everywhere @eval $(MarkovProcesses.generate_code_next_state(lha_name, edge_type))
285 286 287
    @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, 
288 289 290
                   map_var_automaton_idx, flow, map_edges, 
                   map_edges_transitions, map_edges_check_constraints, map_edges_update_state,
                   constants, m.map_var_idx)
291 292
    return A

293
end
294