diff --git a/core/MarkovProcesses.jl b/core/MarkovProcesses.jl index dfb23e636f9006dae1ff89f483f3f3068cf29155..476b9e55c2bf365b8581b64fb2c91a8c5b269777 100644 --- a/core/MarkovProcesses.jl +++ b/core/MarkovProcesses.jl @@ -3,23 +3,33 @@ module MarkovProcesses import Base: +, -, * import Base: copy, getfield, getindex, lastindex, setindex!, getproperty, setproperty! -export Model, ContinuousTimeModel, DiscreteTimeModel -export simulate, set_param!, get_param, set_observed_var! -export is_bounded -export load_model, get_module_path -include("model.jl") +import StaticArrays: SVector +# Common types and constructors export Observations, AbstractTrajectory, Trajectory +export LHA, StateLHA, Edge +export Model, ContinuousTimeModel, DiscreteTimeModel + +# Trajectory related methods export +, -, δ, dist_lp export get_obs_var, length_states, length_obs_var, get_state_from_time export is_bounded, times, transitions export check_consistency, is_steadystate -include("trajectory.jl") -export LHA, StateLHA, Edge +# LHA related methods export init_state, next_state!, read_trajectory export load_automaton, get_index, get_value, length_var + +# Model related methods +export simulate, set_param!, get_param, set_observed_var! +export is_bounded +export load_model, get_module_path + +include("common.jl") + +include("trajectory.jl") include("lha.jl") +include("model.jl") end diff --git a/core/common.jl b/core/common.jl new file mode 100644 index 0000000000000000000000000000000000000000..0f6cb04decded7f70e825195f9bf26998e404ccb --- /dev/null +++ b/core/common.jl @@ -0,0 +1,91 @@ + +abstract type Model end +abstract type AbstractTrajectory end + +const Transition = Union{String,Nothing} +const Location = String +const VariableAutomaton = String + +mutable struct ContinuousTimeModel <: Model + d::Int # state space dim + k::Int # parameter space dim + map_var_idx::Dict{String,Int} # maps str to full state space + _map_obs_var_idx::Dict{String,Int} # maps str to observed state space + map_param_idx::Dict{String,Int} # maps str in parameter space + l_transitions::Vector{Transition} + p::Vector{Float64} + x0::Vector{Int} + t0::Float64 + f!::Function + g::Vector{String} # of dimension dobs + _g_idx::Vector{Int} # of dimension dobs + is_absorbing::Function + time_bound::Float64 + buffer_size::Int +end + +struct Trajectory <: AbstractTrajectory + m::ContinuousTimeModel + values::Matrix{Int} + times::Vector{Float64} + transitions::Vector{Transition} +end + +struct Edge + transitions::Vector{Transition} + check_constraints::Function + update_state!::Function +end + +struct LHA + l_transitions::Vector{Transition} + l_loc::Vector{Location} + Λ::Dict{Location,Function} + l_loc_init::Vector{Location} + l_loc_final::Vector{Location} + map_var_automaton_idx::Dict{VariableAutomaton,Int} # nvar keys : str_var => idx in l_var + l_flow::Dict{Location,Vector{Float64}} # output of length nvar + map_edges::Dict{Tuple{Location,Location},Vector{Edge}} + l_ctes::Dict{String,Float64} + map_var_model_idx::Dict{String,Int} # of dim d (of a model) +end + +mutable struct StateLHA + A::LHA + loc::Location + l_var::Vector{Float64} + time::Float64 +end + +mutable struct SynchronizedModel + m::ContinuousTimeModel + automaton::LHA +end + +# Constructors +function ContinuousTimeModel(d::Int, k::Int, map_var_idx::Dict, map_param_idx::Dict, l_transitions::Vector{String}, + p::Vector{Float64}, x0::Vector{Int}, t0::Float64, + f!::Function, is_absorbing::Function; + g::Vector{String} = keys(map_var_idx), time_bound::Float64 = Inf, buffer_size::Int = 10) + dobs = length(g) + _map_obs_var_idx = Dict() + _g_idx = Vector{Int}(undef, dobs) + for i = 1:dobs + _g_idx[i] = map_var_idx[g[i]] # = ( (g[i] = i-th obs var)::String => idx in state space ) + _map_obs_var_idx[g[i]] = i + end + + if length(methods(f!)) >= 2 + @warn "You have possibly redefined a function Model.f! used in a previously instantiated model." + end + if length(methods(is_absorbing)) >= 2 + @warn "You have possibly redefined a function Model.is_absorbing used in a previously instantiated model." + end + + return ContinuousTimeModel(d, k, map_var_idx, _map_obs_var_idx, map_param_idx, l_transitions, p, x0, t0, f!, g, _g_idx, is_absorbing, time_bound, buffer_size) +end + +LHA(A::LHA, map_var::Dict{String,Int}) = LHA(A.l_transitions, A.l_loc, A.Λ, + A.l_loc_init, A.l_loc_final, A.map_var_automaton_idx, A.l_flow, + A.map_edges, A.l_ctes, map_var) + diff --git a/core/lha.jl b/core/lha.jl index c3a1359f21325003170185931e2a73f370e35d9a..4c586bde4049299a752a72b7a1a18c22eea07d08 100644 --- a/core/lha.jl +++ b/core/lha.jl @@ -1,39 +1,8 @@ -const Location = String -const VariableAutomaton = String - -struct Edge - transitions::Vector{Transition} - check_constraints::Function - update_state!::Function -end - -struct LHA - l_transitions::Vector{Transition} - l_loc::Vector{Location} - Λ::Dict{Location,Function} - l_loc_init::Vector{Location} - l_loc_final::Vector{Location} - map_var_automaton_idx::Dict{VariableAutomaton,Int} # nvar keys : str_var => idx in l_var - l_flow::Dict{Location,Vector{Float64}} # output of length nvar - map_edges::Dict{Tuple{Location,Location},Vector{Edge}} - l_ctes::Dict{String,Float64} - map_var_model_idx::Dict{String,Int} # of dim d (of a model) -end +load_automaton(automaton::String) = include(get_module_path() * "/automata/$(automaton).jl") -LHA(A::LHA, map_var::Dict{String,Int}) = LHA(A.l_transitions, A.l_loc, A.Λ, - A.l_loc_init, A.l_loc_final, A.map_var_automaton_idx, A.l_flow, - A.map_edges, A.l_ctes, map_var) length_var(A::LHA) = length(A.map_var_automaton_idx) get_value(A::LHA, x::SubArray{Int,1}, var::String) = x[A.map_var_model_idx[var]] -load_automaton(automaton::String) = include(get_module_path() * "/automata/$(automaton).jl") - -mutable struct StateLHA - A::LHA - loc::Location - l_var::Vector{Float64} - time::Float64 -end copy(S::StateLHA) = StateLHA(S.A, S.loc, S.l_var, S.time) # Not overring getproperty, setproperty to avoid a conversion Symbol => String for the dict key @@ -50,6 +19,7 @@ function Base.show(io::IO, S::StateLHA) end end +# Methods for synchronize / read the trajectory function init_state(A::LHA, x0::SubArray{Int,1}, t0::Float64) S0 = StateLHA(A, "", zeros(length_var(A)), t0) for loc in A.l_loc_init diff --git a/core/model.jl b/core/model.jl index 6b4614814c5ba92a00634483ede1e95337fc5116..82505371324f9ec8ac24deccf9a0260e5208168c 100644 --- a/core/model.jl +++ b/core/model.jl @@ -1,58 +1,4 @@ -import StaticArrays: SVector - -abstract type Model end -abstract type DiscreteTimeModel <: Model end -const Transition = Union{String,Nothing} - -# Model types -mutable struct ContinuousTimeModel <: Model - d::Int # state space dim - k::Int # parameter space dim - map_var_idx::Dict{String,Int} # maps str to full state space - _map_obs_var_idx::Dict{String,Int} # maps str to observed state space - map_param_idx::Dict{String,Int} # maps str in parameter space - l_transitions::Vector{Transition} - p::Vector{Float64} - x0::Vector{Int} - t0::Float64 - f!::Function - g::Vector{String} # of dimension dobs - _g_idx::Vector{Int} # of dimension dobs - is_absorbing::Function - time_bound::Float64 - buffer_size::Int -end - -function ContinuousTimeModel(d::Int, k::Int, map_var_idx::Dict, map_param_idx::Dict, l_transitions::Vector{String}, - p::Vector{Float64}, x0::Vector{Int}, t0::Float64, - f!::Function, is_absorbing::Function; - g::Vector{String} = keys(map_var_idx), time_bound::Float64 = Inf, buffer_size::Int = 10) - dobs = length(g) - _map_obs_var_idx = Dict() - _g_idx = Vector{Int}(undef, dobs) - for i = 1:dobs - _g_idx[i] = map_var_idx[g[i]] # = ( (g[i] = i-th obs var)::String => idx in state space ) - _map_obs_var_idx[g[i]] = i - end - - if length(methods(f!)) >= 2 - @warn "You have possibly redefined a function Model.f! used in a previously instantiated model." - end - if length(methods(is_absorbing)) >= 2 - @warn "You have possibly redefined a function Model.is_absorbing used in a previously instantiated model." - end - - return ContinuousTimeModel(d, k, map_var_idx, _map_obs_var_idx, map_param_idx, l_transitions, p, x0, t0, f!, g, _g_idx, is_absorbing, time_bound, buffer_size) -end - -#= -mutable struct SynchronizedModel - m::ContinuousTimeModel - automaton::LHA -end -=# - # Simulation function simulate(m::ContinuousTimeModel) # trajectory fields @@ -99,7 +45,6 @@ function simulate(m::ContinuousTimeModel) return Trajectory(m, values, times, transitions) end -#= function simulate(product::SynchronizedModel) # trajectory fields m = product.m @@ -153,7 +98,6 @@ function simulate(product::SynchronizedModel) values = view(full_values, :, m._g_idx) return Trajectory(m, values, times, transitions) end -=# function simulate(m::ContinuousTimeModel, n::Int) obs = ContinuousObservations(undef, n) diff --git a/core/trajectory.jl b/core/trajectory.jl index 37e969764f16ad6281e3ded37f380b6a5076c510..32afb2947e56be934f11fe76bde59be3c0288131 100644 --- a/core/trajectory.jl +++ b/core/trajectory.jl @@ -1,18 +1,4 @@ -abstract type AbstractTrajectory end -ContinuousObservations = AbstractVector{AbstractTrajectory} - -struct Trajectory <: AbstractTrajectory - m::ContinuousTimeModel - values::Matrix{Int} - times::Vector{Float64} - transitions::Vector{Transition} -end - -# Operations -function +(σ1::AbstractTrajectory,σ2::AbstractTrajectory) end -function -(σ1::AbstractTrajectory,σ2::AbstractTrajectory) end - # Top-level Lp distance function """ `dist_lp(l_σ1, l_σ2; verbose, p, str_stat_list, str_stat_trajectory)` @@ -170,7 +156,6 @@ function check_consistency(σ::AbstractTrajectory) end is_steadystate(σ::AbstractTrajectory) = (σ.m).is_absorbing((σ.m).p, σ[end]) - # Properties of the trajectory length_states(σ::AbstractTrajectory) = length(σ.times) length_obs_var(σ::AbstractTrajectory) = size(σ.values)[2] @@ -200,7 +185,6 @@ function get_state_from_time(σ::AbstractTrajectory, t::Float64) end error("Unexpected behavior") end -δ(σ::AbstractTrajectory,idx::Int) = times(σ)[i+1] - times(σ)[i] states(σ::AbstractTrajectory) = σ.values times(σ::AbstractTrajectory) = σ.times @@ -214,3 +198,8 @@ getindex(σ::AbstractTrajectory, var::String, idx::Int) = get_value(σ, var, idx getindex(σ::AbstractTrajectory, var::String) = get_var_values(σ, var) lastindex(σ::AbstractTrajectory) = length_states(σ) +# Operations +function +(σ1::AbstractTrajectory,σ2::AbstractTrajectory) end +function -(σ1::AbstractTrajectory,σ2::AbstractTrajectory) end +δ(σ::AbstractTrajectory,idx::Int) = times(σ)[i+1] - times(σ)[i] + diff --git a/tests/automata/automaton_F.jl b/tests/automata/automaton_F.jl index 8b70061e297bb87ed66ce9027926ee051b1ed267..145da95fe7e207b60ef9077b3ca1b2cb14131a26 100644 --- a/tests/automata/automaton_F.jl +++ b/tests/automata/automaton_F.jl @@ -7,6 +7,6 @@ SIR.time_bound = 120.0 x1, x2, t1, t2 = 0.0, Inf, 100.0, 120.0 A_F = create_automaton_F(SIR, x1, x2, t1, t2, "I") # <: LHA -#sync_SIR = SIR * A_F -#σ, state_lha = simulate(sync_SIR) +sync_SIR = SIR * A_F +σ, state_lha = simulate(sync_SIR)