Skip to content

Commit

Permalink
Merge pull request #20 from voduchuy/exponential
Browse files Browse the repository at this point in the history
Compatibility updates
  • Loading branch information
voduchuy authored Mar 18, 2023
2 parents 49b895a + 042cd03 commit acd2612
Show file tree
Hide file tree
Showing 13 changed files with 72 additions and 52 deletions.
15 changes: 3 additions & 12 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ authors = ["Huy D. Vo <[email protected]> and contributors"]
version = "0.1.3"

[deps]
BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
Catalyst = "479239e8-5488-4da2-87a7-35f2df7eef83"
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
DifferentialEquations = "0c46a032-eb83-5123-abaf-570d42b7fbaa"
Expand All @@ -13,24 +14,14 @@ LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
ModelingToolkit = "961ee093-0014-501f-94e3-6117800e7a78"
Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7"
ReusePatterns = "a39b5e78-89b5-562b-97d8-70689129df0c"
SciMLBase = "0bca4576-84f4-4d90-8ffe-ffa030f20462"
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
Sundials = "c3572dad-4567-51f8-b174-8c6c989267f4"
Symbolics = "0c5d862f-8b57-4792-8d23-62f2024744c7"

[compat]
Catalyst = "10, 11, 12"
DataStructures = "0.18, 0.19"
DifferentialEquations = "7"
DocStringExtensions = "0.8"
ForwardDiff = "0.10, 0.11"
LinearAlgebra = "1"
ModelingToolkit = "8"
ReusePatterns = "0.2, 0.3"
StaticArrays = "1"
Sundials = "4"
Symbolics = "4"
julia = "^1.6"


[extras]
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
Expand Down
4 changes: 2 additions & 2 deletions examples/hog1p.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ function Hog1p(t)
signal = Ahog * (u / (1.0 + u / Mhog))^η
return signal
end
@parameters k01, k10, a, k12, k21, k23, k32, λ0, λ1, λ2, λ3, ktrans, γnuc, γcyt

rn = @reaction_network begin
k01, G0 --> G1
max(0, k10 - a*Hog1p(t)), G1 --> G0
Expand All @@ -28,7 +28,7 @@ rn = @reaction_network begin
γnuc, RNAnuc -->
ktrans, RNAnuc --> RNAcyt
γcyt, RNAcyt -->
end k01 k10 a k12 k21 k23 k32 λ0 λ1 λ2 λ3 γnuc ktrans γcyt
end

param_values = Dict([
k01=> 2.6e-3,
Expand Down
4 changes: 2 additions & 2 deletions examples/telegraph_cme.jl
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,12 @@ tspan = (0.0, 300.0)
fspsol1 = solve(model, p0, tspan, fspalgorithm)

# Bursting model definition using Catalyst
@parameters k₀₁ k₁₀ λ γ
bursting_rn = @reaction_network begin
k₀₁, G0 --> G1
k₁₀, G1 --> G0
λ, G1 --> G1 + mRNA
γ, mRNA -->
end k₀₁ k₁₀ λ γ
end

parameter_values = [k₀₁ => 0.05, k₁₀ => 0.1, λ => 5.0, γ => 0.5]
model_from_catalyst = CmeModel(bursting_rn, parameter_values)
Expand All @@ -69,3 +68,4 @@ end




File renamed without changes.
6 changes: 3 additions & 3 deletions src/cmemodel/catalyst_interface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ function CmeModel(rn::Catalyst.ReactionSystem, parameter_values)

species_ids = Catalyst.speciesmap(rn)
parameter_ids = Catalyst.paramsmap(rn)
𝔖 = Catalyst.netstoichmat(rn)
stoich_matrix = Catalyst.netstoichmat(rn)

jump_rate_laws = [Catalyst.jumpratelaw(eq) for eq in rn.eqs]
jump_rate_laws = [Catalyst.jumpratelaw(eq) for eq in Catalyst.get_eqs(rn)]

## Convert Catalyst jump rate laws into
@variables t x[1:species_count] p[1:parameter_count]
Expand Down Expand Up @@ -37,5 +37,5 @@ function CmeModel(rn::Catalyst.ReactionSystem, parameter_values)
end
end

return CmeModel(𝔖, converted_propensities, parvec)
return CmeModel(stoich_matrix, converted_propensities, parvec)
end
8 changes: 5 additions & 3 deletions src/forwardsenscme/sparse/forwardsenscmesparse.jl
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,9 @@ function solve(model::CmeModelWithSensitivity,
function affect!(integrator)
DE.terminate!(integrator)
end
# Error constraint for the intermediate solutions. The intermediate sinks must not grow beyond a linear function of time that reaches `fsptol` at the end time
# Error constraint for the intermediate solutions.
# The intermediate sinks must not grow beyond a linear function
# of time that reaches `fsptol` at the end time
function fsp_error_constraint(u, t, integrator)
sinks = u[n-sink_count+1:n]
return sum(sinks) - fsptol * t / tend
Expand All @@ -159,8 +161,8 @@ function solve(model::CmeModelWithSensitivity,
abstol = eps()
)

fsensfspprob = DE.ODEProblem(sensfsprhs!, unow, (tnow, tend), p = get_parameters(model))
integrator = DE.init(fsensfspprob, sensfspalgorithm.ode_method, atol = odeatol, rtol = odertol, callback = fsp_cb, saveat = saveat, progress=true)
fsensfspprob = DE.ODEProblem(sensfsprhs!, unow, (tnow, tend), get_parameters(model))
integrator = DE.init(fsensfspprob, sensfspalgorithm.ode_method, abstol = odeatol, reltol = odertol, callback = fsp_cb, saveat = saveat, progress=true)
DE.step!(integrator, tend - tnow, true)

for (t, u) in zip(integrator.sol.t, integrator.sol.u)
Expand Down
9 changes: 7 additions & 2 deletions src/fspmatrix/fspmatrix.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
export FspMatrix, matvec, matvec!
export AbstractFspMatrix, matvec, matvec!

"""
Abstract type for the FSP-truncated infinitesimal generator of the Chemical Master Equation.
"""
abstract type AbstractFspMatrix end


abstract type FspMatrix end

include("sparse/fspsparsematrix.jl")

Expand Down
23 changes: 9 additions & 14 deletions src/fspmatrix/sparse/fspsparsematrix.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export FspMatrixSparse, get_parameters, get_states, get_rowcount, get_colcount,
"""
The transition rate matrix of the finite Markov chain approximation to the CME (including sink states). This type is based on the sparse representation of the truncated state space.
"""
Base.@kwdef mutable struct FspMatrixSparse{NS,NR,IntT<:Integer,RealT<:AbstractFloat} <: FspMatrix
Base.@kwdef mutable struct FspMatrixSparse{NS,NR,IntT<:Integer,RealT<:AbstractFloat} <: AbstractFspMatrix
parameters::Vector{Any}
states::Vector{MVector{NS,IntT}}

Expand Down Expand Up @@ -185,7 +185,9 @@ function size(A::FspMatrixSparse, dim::Integer)
return (dim == 1) ? A.rowcount : A.colcount
end

# Matrix-vector multiplications
#=
Matrix-vector multiplications
=#
"""
matvec!(out::Vector{RealT}, t::AbstractFloat, A::FspMatrixSparse, v::Vector{RealT})
Expand All @@ -195,12 +197,10 @@ function matvec!(out, t, A::FspMatrixSparse, v)
if A.timeinvariant_matrix isa Nothing
out .= 0.0
else
# out .= A.timeinvariant_matrix*v
SArrays.mul!(out, A.timeinvariant_matrix, v)
end
θ = A.parameters
for (i, r) in enumerate(A.separabletv_propensity_ids)
# out .+= A.propensities[r].tfactor(t, θ...)*A.separabletv_factormatrices[i]*v
SArrays.mul!(out, A.separabletv_factormatrices[i], v, A.propensities[r].tfactor(t, θ), 1)
end
needupdate = false
Expand All @@ -211,7 +211,6 @@ function matvec!(out, t, A::FspMatrixSparse, v)
for (i, r) in enumerate(A.jointtv_propensity_ids)
(needupdate) && _update_sparsematrix!(A.jointtv_matrices[i], A.states, A.propensities[r],
t, θ)
# out .+= A.jointtv_matrices[i]*v
SArrays.mul!(out, A.jointtv_matrices[i], v, 1.0, 1.0)
end
return nothing
Expand Down Expand Up @@ -258,18 +257,14 @@ function matvec(t, A::FspMatrixSparse, v)
return w
end

function (A::FspMatrixSparse)(t::AbstractFloat)
return (t, A)
end

import Base: *
function *(A_at_t::Tuple{AbstractFloat,FspMatrixSparse}, v::Vector{RealT}) where {RealT<:AbstractFloat}
t = A_at_t[1]
A = A_at_t[2]
return matvec(t, A, v)
end

function *(A::FspMatrixSparse, v::Vector{RealT}) where {RealT<:AbstractFloat}
return matvec(0.0, A, v)
end

#=
Interface to DifferentialEquations.jl's Linear operator
=#
# mutable struct FspDiffEqOperator <: AbstractDiffEqOperator
# end
4 changes: 2 additions & 2 deletions src/fspvector/fspvector.jl
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ get_statedict(v::FspVectorSparse) = v.state2idx
nnz(p::FspVectorSparse) = length(get_states(p))

"""
FspVectorSparse(states::Vector{MVector{NS, IntT}}, values::Vector{RealT})
FspVectorSparse(states::Vector{MVector{NS,IntT}}, values::Vector{RealT}; checksizes::Bool = true) where {NS,IntT<:Integer,RealT<:AbstractFloat}
Construct a sparse representation of a FSP-truncated probability distribution with support `states` and proability values `values`.
"""
Expand All @@ -35,7 +35,7 @@ function FspVectorSparse(states::Vector{MVector{NS,IntT}}, values::Vector{RealT}
end

"""
FspVectorSparse(statespace::AbstractStateSpaceSparse{NS, NR, IntT}, statevalpairs::Vector{Pair{VecT, RealT}})
FspVectorSparse(statespace::AbstractStateSpaceSparse{NS,NR,IntT}, statevalpairs::Vector{Pair{VecT,RealT}}) where {NS,NR,IntT<:Integer,VecT<:AbstractVector,RealT<:AbstractFloat}
Construct a sparse representation of a FSP-truncated probability distribution on the state space `statespace` and proability values `values`.
"""
Expand Down
7 changes: 4 additions & 3 deletions src/transientcme/sparse/rstepadapters.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using SciMLBase: get_du!

export RStepAdapter, SelectiveRStepAdapter

Expand Down Expand Up @@ -97,9 +98,9 @@ function adapt!(statespace::StateSpaceSparse, adapter::SelectiveRStepAdapter,
deleteat!(p, dropids)
end
sink_count = get_sink_count(statespace)
du = similar(integrator.u)
f! = integrator.f
f!(du, integrator.u, [], t)
du = similar(integrator.u)
get_du!(du, integrator)

dsinks = du[end-sink_count+1:end]
expandreactions = findall(dsinks .> 0)
nold = get_state_count(statespace)
Expand Down
6 changes: 3 additions & 3 deletions test/test_catalyst_interface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ end

cmemodel1 = CmeModel(𝕊, [a1,a2,a3,a4], θ)

@parameters k01 k10 α γ
# @parameters k01 k10 α γ
rn = @reaction_network begin
k01, G0 --> G1
k10, G1 --> G0
α, G1 --> G1 + RNA
γ*max(0.0, 1.0 - sin* t / L)), RNA -->
end k01 k10 α γ L
end

cmemodel2 = CmeModel(rn, θ)
@test get_species_count(cmemodel2) == 3
Expand All @@ -50,7 +50,7 @@ expand!(test_space, 100)
pass = true
for t in test_times
for state in get_states(test_space)
pass &= cmemodel1.propensities[1](state,θ) cmemodel2.propensities[1](state,θ)
global pass &= cmemodel1.propensities[1](state,θ) cmemodel2.propensities[1](state,θ)
pass &= cmemodel1.propensities[2](state,θ) cmemodel2.propensities[2](state,θ)
pass &= cmemodel1.propensities[3](state,θ) cmemodel2.propensities[3](state,θ)
pass &= cmemodel1.propensities[4](t,state,θ) cmemodel2.propensities[4](t,state,θ)
Expand Down
26 changes: 26 additions & 0 deletions test/test_exponential.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# This test suite verifies that DifferentialEquations.jl Exponential integrators can be used with the FSP
using NumCME
using DifferentialEquations
using StaticArrays
import Catalyst

## Test Fixture: telegraph gene expression
Catalyst.@parameters k₀₁ k₁₀ λ γ
bursting_rn = Catalyst.@reaction_network begin
k₀₁, G0 --> G1
k₁₀, G1 --> G0
λ, G1 --> G1 + mRNA
γ, mRNA -->
end k₀₁ k₁₀ λ γ

parameter_values = [k₀₁ => 0.05, k₁₀ => 0.1, λ => 5.0, γ => 0.5]
model_from_catalyst = CmeModel(bursting_rn, parameter_values)

fspalgorithm = AdaptiveFspSparse(
ode_method=LinearExponential(),
space_adapter=RStepAdapter(5, 10, true)
)
p0 = FspVectorSparse([@MVector [1, 0, 0]], [1.0])
fspsol = solve(model_from_catalyst, p0, (0.0, 100.0), fspalgorithm; saveat=[0.0, 50.0, 100.0])


12 changes: 6 additions & 6 deletions test/test_fspmat.jl
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ expand!(𝔛, 2)
@test size(𝐀, 1) == get_state_count(𝔛) + get_sink_count(𝔛)
@test size(𝐀, 2) == get_state_count(𝔛) + get_sink_count(𝔛)
𝐯 = ones(Float64, size(𝐀, 1))
𝐰 = 𝐀(1.0) * 𝐯
𝐰 = matvec(1.0, 𝐀, 𝐯)
@test sum(𝐰) 0.0 atol = 1.0e-14
𝐰 = 𝐀 * 𝐯
𝐰 = matvec(0.0, 𝐀, 𝐯)
@test sum(𝐰) 0.0 atol = 1.0e-14

# Test mat-vec for time-varying matrix
Expand All @@ -54,15 +54,15 @@ A1 = FspMatrixSparse(𝔛, propensities_tv, parameters=θ)
@test size(A1, 1) == get_state_count(𝔛) + get_sink_count(𝔛)
@test size(A1, 2) == get_state_count(𝔛) + get_sink_count(𝔛)
𝐯 = ones(Float64, size(A1, 1))
w1 = A1(1.0) * 𝐯
w1 = matvec(1.0, A1, 𝐯)
@test sum(w1) 0.0 atol = 1.0e-14
w1 = A1 * 𝐯
w1 = matvec(0.0, A1, 𝐯)
@test sum(w1) 0.0 atol = 1.0e-14

A2 = FspMatrixSparse(𝔛, propensities_tvj, parameters=θ)
w2 = A2(1.0) * 𝐯
w2 = matvec(1.0, A2, 𝐯)
@test sum(w2) 0.0 atol = 1.0e-14
w2 = A2 * 𝐯
w2 = matvec(0.0, A2, 𝐯)

@test sum(w2) 0.0 atol = 1.0e-14
@test norm(w1 -w2) 0
Expand Down

0 comments on commit acd2612

Please sign in to comment.