From 0a2d2796b3ded880c00dc49acbb21670f2e8c1f3 Mon Sep 17 00:00:00 2001
From: Mahmoud Bentriou <mahmoud.bentriou@centralesupelec.fr>
Date: Fri, 20 Nov 2020 22:05:38 +0100
Subject: [PATCH] Restructuration in the package: separate types from methods
 related to an object.

Type stability of simulate, dist, read_trajectory seems to be preserved.
---
 core/MarkovProcesses.jl       | 24 ++++++---
 core/common.jl                | 91 +++++++++++++++++++++++++++++++++++
 core/lha.jl                   | 34 +------------
 core/model.jl                 | 56 ---------------------
 core/trajectory.jl            | 21 ++------
 tests/automata/automaton_F.jl |  4 +-
 6 files changed, 117 insertions(+), 113 deletions(-)
 create mode 100644 core/common.jl

diff --git a/core/MarkovProcesses.jl b/core/MarkovProcesses.jl
index dfb23e6..476b9e5 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 0000000..0f6cb04
--- /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 c3a1359..4c586bd 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 6b46148..8250537 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 37e9697..32afb29 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 8b70061..145da95 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)  
 
-- 
GitLab