From c2159b6c22c2bb839c816e658a3a708e3925b01e Mon Sep 17 00:00:00 2001 From: Mahmoud Bentriou <mahmoud.bentriou@centralesupelec.fr> Date: Mon, 16 Nov 2020 14:27:32 +0100 Subject: [PATCH] Reorganisation of the tests directory: - a script to run the different categories - now the execution of simulation/ scripts is checked - several minor changes and add of tests New directory : models/_bench_perf_tests. Models for performance benchmarking purposes. --- core/_tests_simulate.jl | 158 ++++++++++++++++++ models/_bench_perf_test/SIR_col.jl | 49 ++++++ models/_bench_perf_test/SIR_col_buffer.jl | 49 ++++++ models/_bench_perf_test/SIR_row_buffer.jl | 49 ++++++ tests/run_all.jl | 4 + tests/run_simulation.jl | 14 ++ tests/simulation/sim_er.jl | 4 +- tests/simulation/sim_sir.jl | 4 +- tests/simulation/sim_sir_bounded.jl | 4 +- .../simulation/sim_sir_col_buffer_bounded.jl | 16 ++ 10 files changed, 348 insertions(+), 3 deletions(-) create mode 100644 core/_tests_simulate.jl create mode 100644 models/_bench_perf_test/SIR_col.jl create mode 100644 models/_bench_perf_test/SIR_col_buffer.jl create mode 100644 models/_bench_perf_test/SIR_row_buffer.jl create mode 100644 tests/run_all.jl create mode 100644 tests/run_simulation.jl create mode 100644 tests/simulation/sim_sir_col_buffer_bounded.jl diff --git a/core/_tests_simulate.jl b/core/_tests_simulate.jl new file mode 100644 index 0000000..0f55f06 --- /dev/null +++ b/core/_tests_simulate.jl @@ -0,0 +1,158 @@ + +# File for benchmarking simulation and memory access of the package. + +_get_values_col(σ::AbstractTrajectory, var::String) = +σ.values[(σ.m)._map_obs_var_idx[var],:] +_get_values_row(σ::AbstractTrajectory, var::String) = +σ.values[:,(σ.m)._map_obs_var_idx[var]] + + +function _simulate_col(m::ContinuousTimeModel) + # trajectory fields + full_values = zeros(m.d, 0) + times = zeros(0) + transitions = Vector{Union{String,Nothing}}(undef,0) + # values at time n + n = 0 + xn = m.x0 + tn = m.t0 + tr = [""] + # at time n+1 + xnplus1 = zeros(Int, m.d) + tnplus1 = zeros(Float64, 1) + is_absorbing = (m.is_absorbing(m.p,xn))::Bool + while !is_absorbing && (tn <= m.time_bound) + m.f!(xnplus1, tnplus1, tr, xn, tn, m.p) + full_values = hcat(full_values, xnplus1) + push!(times, tnplus1[1]) + push!(transitions, tr[1]) + xn, tn = xnplus1, tnplus1[1] + n += 1 + is_absorbing = m.is_absorbing(m.p,xn)::Bool + end + values = @view full_values[m._g_idx,:] + if is_bounded(m) + if times[end] > m.time_bound + values[:, end] = values[:,end-1] + times[end] = m.time_bound + transitions[end] = nothing + end + end + return Trajectory(m, values, times, transitions) +end + +function _simulate_row(m::ContinuousTimeModel) + # trajectory fields + full_values = zeros(m.d, 0) + times = zeros(0) + transitions = Vector{Union{String,Nothing}}(undef,0) + # values at time n + n = 0 + xn = m.x0 + tn = m.t0 + tr = [""] + # at time n+1 + xnplus1 = zeros(Int, m.d) + tnplus1 = zeros(Float64, 1) + is_absorbing = (m.is_absorbing(m.p,xn))::Bool + while !is_absorbing && (tn <= m.time_bound) + m.f!(xnplus1, tnplus1, tr, xn, tn, m.p) + full_values = vcat(full_values, xnplus1) + push!(times, tnplus1[1]) + push!(transitions, tr[1]) + xn, tn = xnplus1, tnplus1[1] + n += 1 + is_absorbing = m.is_absorbing(m.p,xn)::Bool + end + values = @view full_values[m._g_idx,:] + if is_bounded(m) + if times[end] > m.time_bound + values[:, end] = values[:,end-1] + times[end] = m.time_bound + transitions[end] = nothing + end + end + return Trajectory(m, values, times, transitions) +end + + +function _simulate_col_buffer(m::ContinuousTimeModel; buffer_size::Int = 5) + # trajectory fields + full_values = zeros(m.d, 0) + times = zeros(0) + transitions = Vector{Union{String,Nothing}}(undef,0) + # values at time n + n = 0 + xn = m.x0 + tn = m.t0 + # at time n+1 + mat_x = zeros(Int, m.d, buffer_size) + l_t = zeros(Float64, buffer_size) + l_tr = Vector{String}(undef, buffer_size) + is_absorbing = m.is_absorbing(m.p,xn)::Bool + while !is_absorbing && (tn <= m.time_bound) + i = 0 + while i < buffer_size && !is_absorbing && (tn <= m.time_bound) + i += 1 + m.f!(mat_x, l_t, l_tr, i, xn, tn, m.p) + xn = @view mat_x[:,i] + tn = l_t[i] + is_absorbing = m.is_absorbing(m.p,xn)::Bool + end + full_values = hcat(full_values, @view mat_x[:,1:i]) + append!(times, @view l_t[1:i]) + append!(transitions, @view l_tr[1:i]) + n += i + is_absorbing = m.is_absorbing(m.p,xn)::Bool + end + values = @view full_values[m._g_idx,:] + if is_bounded(m) + if times[end] > m.time_bound + values[:, end] = values[:,end-1] + times[end] = m.time_bound + transitions[end] = nothing + end + end + return Trajectory(m, values, times, transitions) +end + +function _simulate_row_buffer(m::ContinuousTimeModel; buffer_size::Int = 5) + # trajectory fields + full_values = zeros(0, m.d) + times = zeros(0) + transitions = Vector{Union{String,Nothing}}(undef,0) + # values at time n + n = 0 + xn = m.x0 + tn = m.t0 + # at time n+1 + mat_x = zeros(Int, buffer_size, m.d) + l_t = zeros(Float64, buffer_size) + l_tr = Vector{String}(undef, buffer_size) + is_absorbing = m.is_absorbing(m.p,xn)::Bool + while !is_absorbing && (tn <= m.time_bound) + i = 0 + while i < buffer_size && !is_absorbing && (tn <= m.time_bound) + i += 1 + m.f!(mat_x, l_t, l_tr, i, xn, tn, m.p) + xn = @view mat_x[:,i] + tn = l_t[i] + is_absorbing = m.is_absorbing(m.p,xn)::Bool + end + full_values = vcat(full_values, @view mat_x[1:i,:]) + append!(times, @view l_t[1:i]) + append!(transitions, @view l_tr[1:i]) + n += i + is_absorbing = m.is_absorbing(m.p,xn)::Bool + end + values = @view full_values[:,m._g_idx] + if is_bounded(m) + if times[end] > m.time_bound + values[end,:] = values[end-1,:] + times[end] = m.time_bound + transitions[end] = nothing + end + end + return Trajectory(m, values, times, transitions) +end + diff --git a/models/_bench_perf_test/SIR_col.jl b/models/_bench_perf_test/SIR_col.jl new file mode 100644 index 0000000..00cf2e4 --- /dev/null +++ b/models/_bench_perf_test/SIR_col.jl @@ -0,0 +1,49 @@ + +import StaticArrays: SVector, SMatrix, @SMatrix + +d=3 +k=2 +dict_var = Dict("S" => 1, "I" => 2, "R" => 3) +dict_p = Dict("ki" => 1, "kr" => 2) +l_tr = ["R1","R2"] +p = [0.0012, 0.05] +x0 = [95, 5, 0] +t0 = 0.0 +function f!(xnplus1::Vector{Int}, tnplus1::Vector{Float64}, tr::Vector{String}, + xn::Vector{Int}, tn::Float64, p::Vector{Float64}) + a1 = p[1] * xn[1] * xn[2] + a2 = p[2] * xn[2] + l_a = SVector(a1, a2) + asum = sum(l_a) + # column-major order + l_nu = @SMatrix [-1 0; + 1 -1; + 0 1] + + u1, u2 = rand(), rand() + tau = - log(u1) / asum + b_inf = 0.0 + b_sup = a1 + reaction = 0 + for i = 1:2 + if b_inf < asum*u2 < b_sup + reaction = i + break + end + b_inf += l_a[i] + b_sup += l_a[i+1] + end + + nu = @view l_nu[:,reaction] # macro for avoiding a copy + xnplus1[1] = xn[1]+nu[1] + xnplus1[2] = xn[2]+nu[2] + xnplus1[3] = xn[3]+nu[3] + tnplus1[1] = tn + tau + tr[1] = "R$(reaction)" +end +is_absorbing_sir(p::Vector{Float64}, xn::Vector{Int}) = (p[1]*xn[1]*xn[2] + p[2]*xn[2]) === 0.0 +g = ["I"] + +SIR_col = CTMC(d,k,dict_var,dict_p,l_tr,p,x0,t0,f!,is_absorbing_sir; g=g) +export SIR_col + diff --git a/models/_bench_perf_test/SIR_col_buffer.jl b/models/_bench_perf_test/SIR_col_buffer.jl new file mode 100644 index 0000000..d37828b --- /dev/null +++ b/models/_bench_perf_test/SIR_col_buffer.jl @@ -0,0 +1,49 @@ + +import StaticArrays: SVector, SMatrix, @SMatrix + +d=3 +k=2 +dict_var = Dict("S" => 1, "I" => 2, "R" => 3) +dict_p = Dict("ki" => 1, "kr" => 2) +l_tr = ["R1","R2"] +p = [0.0012, 0.05] +x0 = [95, 5, 0] +t0 = 0.0 +function f!(mat_x::Matrix{Int}, l_t::Vector{Float64}, l_tr::Vector{String}, idx::Int, + xn::AbstractVector{Int}, tn::Float64, p::Vector{Float64}) + a1 = p[1] * xn[1] * xn[2] + a2 = p[2] * xn[2] + l_a = SVector(a1, a2) + asum = sum(l_a) + # column-major order + l_nu = @SMatrix [-1 0; + 1 -1; + 0 1] + + u1, u2 = rand(), rand() + tau = - log(u1) / asum + b_inf = 0.0 + b_sup = a1 + reaction = 0 + for i = 1:2 + if b_inf < asum*u2 < b_sup + reaction = i + break + end + b_inf += l_a[i] + b_sup += l_a[i+1] + end + + nu = @view l_nu[:,reaction] # macro for avoiding a copy + for i = 1:3 + mat_x[i,idx] = xn[i]+nu[i] + end + l_t[idx] = tn + tau + l_tr[idx] = "R$(reaction)" +end +is_absorbing_sir(p::Vector{Float64}, xn::AbstractVector{Int}) = (p[1]*xn[1]*xn[2] + p[2]*xn[2]) === 0.0 +g = ["I"] + +SIR_col_buffer = CTMC(d,k,dict_var,dict_p,l_tr,p,x0,t0,f!,is_absorbing_sir; g=g) +export SIR_col_buffer + diff --git a/models/_bench_perf_test/SIR_row_buffer.jl b/models/_bench_perf_test/SIR_row_buffer.jl new file mode 100644 index 0000000..366b68b --- /dev/null +++ b/models/_bench_perf_test/SIR_row_buffer.jl @@ -0,0 +1,49 @@ + +import StaticArrays: SVector, SMatrix, @SMatrix + +d=3 +k=2 +dict_var = Dict("S" => 1, "I" => 2, "R" => 3) +dict_p = Dict("ki" => 1, "kr" => 2) +l_tr = ["R1","R2"] +p = [0.0012, 0.05] +x0 = [95, 5, 0] +t0 = 0.0 +function f!(mat_x::Matrix{Int}, l_t::Vector{Float64}, l_tr::Vector{String}, idx::Int, + xn::AbstractVector{Int}, tn::Float64, p::Vector{Float64}) + a1 = p[1] * xn[1] * xn[2] + a2 = p[2] * xn[2] + l_a = SVector(a1, a2) + asum = sum(l_a) + # column-major order + l_nu = @SMatrix [-1 0; + 1 -1; + 0 1] + + u1, u2 = rand(), rand() + tau = - log(u1) / asum + b_inf = 0.0 + b_sup = a1 + reaction = 0 + for i = 1:2 + if b_inf < asum*u2 < b_sup + reaction = i + break + end + b_inf += l_a[i] + b_sup += l_a[i+1] + end + + nu = @view l_nu[:,reaction] # macro for avoiding a copy + for i = 1:3 + mat_x[idx,i] = xn[i]+nu[i] + end + l_t[idx] = tn + tau + l_tr[idx] = "R$(reaction)" +end +is_absorbing_sir(p::Vector{Float64}, xn::AbstractVector{Int}) = (p[1]*xn[1]*xn[2] + p[2]*xn[2]) === 0.0 +g = ["I"] + +SIR_row_buffer = CTMC(d,k,dict_var,dict_p,l_tr,p,x0,t0,f!,is_absorbing_sir; g=g) +export SIR_row_buffer + diff --git a/tests/run_all.jl b/tests/run_all.jl new file mode 100644 index 0000000..d8c11f7 --- /dev/null +++ b/tests/run_all.jl @@ -0,0 +1,4 @@ + +include("run_unit.jl") +include("run_simulation.jl") + diff --git a/tests/run_simulation.jl b/tests/run_simulation.jl new file mode 100644 index 0000000..224820f --- /dev/null +++ b/tests/run_simulation.jl @@ -0,0 +1,14 @@ + +using Test +import MarkovProcesses: get_module_path + +str_dir_pics = get_module_path() * "/tests/simulation/res_pics" +if !isdir(str_dir_pics) mkdir(str_dir_pics) end + +@testset "Simulation tests" begin + @test include("simulation/sim_sir.jl") + @test include("simulation/sim_sir_bounded.jl") + @test include("simulation/sim_sir_col_buffer_bounded.jl") + @test include("simulation/sim_er.jl") +end + diff --git a/tests/simulation/sim_er.jl b/tests/simulation/sim_er.jl index f46aaac..09d4575 100644 --- a/tests/simulation/sim_er.jl +++ b/tests/simulation/sim_er.jl @@ -7,6 +7,8 @@ load_model("ER") σ = simulate(ER) plt.figure() plt.step(σ["times"], σ["P"], "ro--", marker="x", where="post", linewidth=1.0) -plt.savefig("sim_er.png") +plt.savefig(get_module_path() * "/tests/simulation/res_pics/sim_er.png", dpi=480) plt.close() +return true + diff --git a/tests/simulation/sim_sir.jl b/tests/simulation/sim_sir.jl index dca855f..2a1f00f 100644 --- a/tests/simulation/sim_sir.jl +++ b/tests/simulation/sim_sir.jl @@ -7,6 +7,8 @@ load_model("SIR") σ = simulate(SIR) plt.figure() plt.step(σ["times"], σ["I"], "ro--", marker="x", where="post", linewidth=1.0) -plt.savefig("sim_sir.png") +plt.savefig(get_module_path() * "/tests/simulation/res_pics/sim_sir.png") plt.close() +return true + diff --git a/tests/simulation/sim_sir_bounded.jl b/tests/simulation/sim_sir_bounded.jl index bbca053..95d6434 100644 --- a/tests/simulation/sim_sir_bounded.jl +++ b/tests/simulation/sim_sir_bounded.jl @@ -8,6 +8,8 @@ SIR.time_bound = 100.0 σ = simulate(SIR) plt.figure() plt.step(σ["times"], σ["I"], "ro--", marker="x", where="post", linewidth=1.0) -plt.savefig("sim_sir_bounded.png") +plt.savefig(get_module_path() * "/tests/simulation/res_pics/sim_sir_bounded.png") plt.close() +return true + diff --git a/tests/simulation/sim_sir_col_buffer_bounded.jl b/tests/simulation/sim_sir_col_buffer_bounded.jl new file mode 100644 index 0000000..94335f9 --- /dev/null +++ b/tests/simulation/sim_sir_col_buffer_bounded.jl @@ -0,0 +1,16 @@ + +using MarkovProcesses +include(get_module_path() * "/core/_tests_simulate.jl") +using PyPlot + +load_model("_bench_perf_test/SIR_col_buffer") +SIR_col_buffer.time_bound = 100.0 + +σ = _simulate_col_buffer(SIR_col_buffer) +plt.figure() +plt.step(σ["times"], σ["I"], "ro--", marker="x", where="post", linewidth=1.0) +plt.savefig(get_module_path() * "/tests/simulation/res_pics/sim_sir_col_buffer_bounded.png") +plt.close() + +return true + -- GitLab