automaton_G.jl 14.8 KB
Newer Older
1

2
3
4
# Creation of the automaton types
@everywhere @eval abstract type EdgeAutomatonG <: Edge end
@everywhere @eval $(MarkovProcesses.generate_code_lha_type_def(:AutomatonG, :EdgeAutomatonG))
5

6
function create_automaton_G(m::ContinuousTimeModel, x1::Float64, x2::Float64, t1::Float64, t2::Float64, sym_obs::VariableModel)
7
8
9
10
    # 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."
11
12
13
14
15
16
17
18

    # 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)!")

19
    # Locations
20
    locations = [:l0, :l1, :l2, :l3, :l4]
21
22

    # Invariant predicates
23
    @everywhere true_inv_predicate(x::Vector{Int}) = true 
24
25
26
    Λ_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))
27

28
    ## Init and final loc
29
30
    locations_init = [:l0]
    locations_final = [:l2]
31
32

    ## Map of automaton variables
33
34
    map_var_automaton_idx = Dict{VariableAutomaton,Int}(:tprime => 1, :in => 2,
                                                        :n => 3,  :d => 4, :isabs => 5)
35
36

    ## Flow of variables
37
38
39
40
41
    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])
42
43

    ## Edges
44
    to_idx(var::Symbol) = map_var_automaton_idx[var]
45
    idx_obs_var = getfield(m, :map_var_idx)[sym_obs]
46
47
48
49
50
51
52
53
    id = MarkovProcesses.newid()
    basename_func = "$(model_name)_$(id)"
    edge_name(from_loc::Location, to_loc::Location, edge_number::Int) = 
    Symbol("Edge_$(lha_name)_$(basename_func)_$(from_loc)$(to_loc)_$(edge_number)")

    ## check_constraints & update_state!
    @everywhere @eval begin
        istrue(val::Float64) = convert(Bool, val)
54
55
        # l0 loc
        # l0 => l1
56
57
58
59
60
61
62
63
        struct $(edge_name(:l0, :l1, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
        $(check_constraints)(edge::$(edge_name(:l0, :l1, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = true
        $(update_state!)(edge::$(edge_name(:l0, :l1, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
        (S_values[$(to_idx(: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)
64
65

        # l1 => l3
66
67
        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}) = 
68
        S_time <= $t1 && 
69
70
71
72
73
74
75
76
        S_values[$(to_idx(:n))] < $x1 || S_values[$(to_idx(:n))] > $x2
        $(update_state!)(edge::$(edge_name(:l1, :l3, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
        (S_values[$(to_idx(:d))] = min(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}) = 
77
        (S_time <= $t1) && 
78
79
80
81
82
83
84
85
86
        ($x1 <= S_values[$(to_idx(:n))] <= $x2)
        $(update_state!)(edge::$(edge_name(:l1, :l3, 2)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
        (S_values[$(to_idx(:d))] = 0;
         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}) = 
        !istrue(S_values[$(to_idx(:in))]) && 
87
        ($t1 <= S_time <= $t2) && 
88
89
90
91
92
93
94
95
96
        ($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}) = 
        (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}) = 
        istrue(S_values[$(to_idx(:in))]) && 
97
        ($t1 <= S_time <= $t2) && 
98
99
100
101
        ($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}) = 
        (S_values[$(to_idx(:tprime))] = 0.0;
         :l3)
102
103

        # l1 => l4
104
105
106
        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}) = 
        !istrue(S_values[$(to_idx(:in))]) && 
107
        ($t1 <= S_time <= $t2) && 
108
109
110
111
112
113
114
115
        (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}) = 
        (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}) = 
        istrue(S_values[$(to_idx(:in))]) && 
116
        ($t1 <= S_time <= $t2) && 
117
118
        (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}) = 
119
        (:l4)
120
121

        # l1 => l2
122
        #=
123
124
125
        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}) = 
        istrue(S_values[$(to_idx(:in))]) && 
126
        S_time >= $t2
127
        $(update_state!)(edge::$(edge_name(:l1, :l2, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
128
        (:l2)
129

130
131
132
        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}) = 
        !istrue(S_values[$(to_idx(:in))]) && 
133
        S_time >= $t2
134
135
136
        $(update_state!)(edge::$(edge_name(: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)
137

138
139
140
        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}) = 
        istrue(S_values[$(to_idx(:isabs))]) && 
141
        S_time <= $t1
142
143
144
        $(update_state!)(edge::$(edge_name(: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)
145

146
147
148
        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}) = 
        istrue(S_values[$(to_idx(:isabs))]) && 
149
        ($t1 <= S_time <= $t2)
150
151
152
        $(update_state!)(edge::$(edge_name(: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)
153
        =#
154
155

        # l3 => l1
156
157
158
159
160
161
        struct $(edge_name(:l3, :l1, 1)) <: $(edge_type) transitions::Union{Nothing,Vector{Symbol}} end
        $(check_constraints)(edge::$(edge_name(:l3, :l1, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = true
        $(update_state!)(edge::$(edge_name(:l3, :l1, 1)), S_time::Float64, S_values::Vector{Float64}, x::Vector{Int}, p::Vector{Float64}) = 
        (S_values[$(to_idx(:n))] = x[$(idx_obs_var)];
         S_values[$(to_idx(:isabs))] = $(m.isabsorbing)(p, x);
         :l1)
162
163

        # l4 => l1
164
165
166
167
168
169
170
171
172
        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}) = 
        (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)
173

174
        # l3 => l2
175
176
177
178
179
180
181
182
183
184
185
186
187
        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}) = 
        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}) = 
        (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}) = 
        !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}) = 
188
        (:l2)
189
190

        # l4 => l2
191
192
193
194
195
196
197
198
199
200
        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}) = 
        (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}) = 
        (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}) = 
201
        (S_time >= $t2)
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
        $(update_state!)(edge::$(edge_name(: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 begin
        map_edges = Dict{Location, Dict{Location, Vector{$(edge_type)}}}()
        for loc in $(locations)
            map_edges[loc] = Dict{Location, Vector{$(edge_type)}}()
        end

        # l0 loc
        # l0 => l1
        edge1 = $(edge_name(:l0, :l1, 1))(nothing)
        map_edges[:l0][:l1] = [edge1]

        # l1 loc
        # l1 => 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)
        map_edges[:l1][:l3] = [edge1, edge2, edge3, edge4]

        # l1 => l4
        edge1 = $(edge_name(:l1, :l4, 1))(nothing)
        edge2 = $(edge_name(:l1, :l4, 2))(nothing)
        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)
        map_edges[:l1][:l2] = [edge1, edge2, edge3, edge4]
        =#

        # l3 loc
        # l3 => l1
        edge1 = $(edge_name(:l3, :l1, 1))([:ALL])
        map_edges[:l3][:l1] = [edge1]

        # l3 => l2
        edge1 = $(edge_name(:l3, :l2, 1))(nothing)
        edge2 = $(edge_name(:l3, :l2, 2))(nothing)
        map_edges[:l3][:l2] = [edge1, edge2]

        # l4 loc
        # l4 => l1
        edge1 = $(edge_name(:l4, :l1, 1))([:ALL])
        map_edges[:l4][:l1] = [edge1]

        # l4 => l2
        edge1 = $(edge_name(:l4, :l2, 1))(nothing)
        edge2 = $(edge_name(:l4, :l2, 2))(nothing)
        map_edges[:l4][:l2] = [edge1,edge2]
261
    end
262
263

    ## Constants
264
    constants = Dict{Symbol,Float64}(:x1 => x1,  :x2 => x2, :t1 => t1, :t2 => t2)
265

266
267
268
269
270
271
272
    # Updating types and simulation methods
    @everywhere @eval $(MarkovProcesses.generate_code_synchronized_model_type_def(model_name, lha_name))
    @everywhere @eval $(MarkovProcesses.generate_code_next_state(lha_name, edge_type, check_constraints, update_state!))
    @everywhere @eval $(MarkovProcesses.generate_code_synchronized_simulation(model_name, lha_name, edge_type, m.f!, m.isabsorbing))

    A = AutomatonG(m.transitions, locations, Λ_F, locations_init, locations_final, 
                   map_var_automaton_idx, flow, map_edges, constants, m.map_var_idx)
273
274
    return A

275
end
276