Skip to content

Handle different parameters types #797

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 20 commits into from
Apr 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion src/reactionsystem.jl
Original file line number Diff line number Diff line change
Expand Up @@ -500,7 +500,7 @@ struct ReactionSystem{V <: NetworkProperties} <:
"""Dependent unknown variables representing species"""
species::Vector{BasicSymbolic{Real}}
"""Parameter variables. Must not contain the independent variable."""
ps::Vector{BasicSymbolic{Real}}
ps::Vector{Any}
"""Maps Symbol to corresponding variable."""
var_to_name::Dict{Symbol, Any}
"""Equations for observed variables."""
Expand Down Expand Up @@ -546,6 +546,11 @@ struct ReactionSystem{V <: NetworkProperties} <:
name, systems, defaults, connection_type, nps, cls, cevs, devs,
metadata = nothing, complete = false; checks::Bool = true)

# Checks that all parameters have the appropriate Symbolics type.
for p in ps
(p isa Symbolics.BasicSymbolic) || error("Parameter $p is not a `BasicSymbolic`. This is required.")
end

# unit checks are for ODEs and Reactions only currently
nonrx_eqs = Equation[eq for eq in eqs if eq isa Equation]
if checks && isempty(sivs)
Expand Down
16 changes: 9 additions & 7 deletions src/spatial_reaction_systems/spatial_reactions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -92,26 +92,28 @@ function check_spatial_reaction_validity(rs::ReactionSystem, tr::TransportReacti
end

# Checks that the species does not exist in the system with different metadata.
if any([isequal(tr.species, s) && !isequivalent(tr.species, s) for s in species(rs)])
if any(isequal(tr.species, s) && !isequivalent(tr.species, s) for s in species(rs))
error("A transport reaction used a species, $(tr.species), with metadata not matching its lattice reaction system. Please fetch this species from the reaction system and used in transport reaction creation.")
end
if any([isequal(rs_p, tr_p) && !equivalent_metadata(rs_p, tr_p)
for rs_p in parameters(rs), tr_p in Symbolics.get_variables(tr.rate)])
if any(isequal(rs_p, tr_p) && !isequivalent(rs_p, tr_p)
for rs_p in parameters(rs), tr_p in Symbolics.get_variables(tr.rate))
error("A transport reaction used a parameter with metadata not matching its lattice reaction system. Please fetch this parameter from the reaction system and used in transport reaction creation.")
end

# Checks that no edge parameter occur among rates of non-spatial reactions.
if any([!isempty(intersect(Symbolics.get_variables(r.rate), edge_parameters)) for r in reactions(rs)])
if any(!isempty(intersect(Symbolics.get_variables(r.rate), edge_parameters)) for r in reactions(rs))
error("Edge paramter(s) were found as a rate of a non-spatial reaction.")
end
end
equivalent_metadata(p1, p2) = isempty(setdiff(p1.metadata, p2.metadata, [Catalyst.EdgeParameter => true]))

# Since MTK's "isequal" ignores metadata, we have to use a special function that accounts for this.
# This is important because whether something is an edge parameter is defined in metadata.
const ep_metadata = Catalyst.EdgeParameter => true
function isequivalent(sym1, sym2)
!isequal(sym1, sym2) && (return false)
(sym1.metadata != sym2.metadata) && (return false)
isequal(sym1, sym2) || (return false)
any((md1 != ep_metadata) && !(md1 in sym2.metadata) for md1 in sym1.metadata) && (return false)
any((md2 != ep_metadata) && !(md2 in sym1.metadata) for md2 in sym2.metadata) && (return false)
(typeof(sym1) != typeof(sym2)) && (return false)
return true
end

Expand Down
45 changes: 45 additions & 0 deletions test/dsl/dsl_options.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

# Fetch packages.
using Catalyst, ModelingToolkit, OrdinaryDiffEq, Plots, Test
using Symbolics: unwrap

# Sets the default `t` to use.
t = default_t()
Expand Down Expand Up @@ -344,6 +345,50 @@ let
@test merge(ModelingToolkit.defaults(rn28), defs28) == ModelingToolkit.defaults(rn27)
end

# Tests that parameter type designation works.
let
# Creates a model.
rn = @reaction_network begin
@parameters begin
k1
l1
k2::Float64 = 2.0
l2::Float64
k3::Int64 = 2, [description="A parameter"]
l3::Int64
k4::Float32, [description="Another parameter"]
l4::Float32
k5::Rational{Int64}
l5::Rational{Int64}
end
(k1,l1), X1 <--> Y1
(k2,l2), X2 <--> Y2
(k3,l3), X3 <--> Y3
(k4,l4), X4 <--> Y4
(k5,l5), X5 <--> Y5
end

# Checks parameter types.
@test unwrap(rn.k1) isa SymbolicUtils.BasicSymbolic{Real}
@test unwrap(rn.l1) isa SymbolicUtils.BasicSymbolic{Real}
@test unwrap(rn.k2) isa SymbolicUtils.BasicSymbolic{Float64}
@test unwrap(rn.l2) isa SymbolicUtils.BasicSymbolic{Float64}
@test unwrap(rn.k3) isa SymbolicUtils.BasicSymbolic{Int64}
@test unwrap(rn.l3) isa SymbolicUtils.BasicSymbolic{Int64}
@test unwrap(rn.k4) isa SymbolicUtils.BasicSymbolic{Float32}
@test unwrap(rn.l4) isa SymbolicUtils.BasicSymbolic{Float32}
@test unwrap(rn.k5) isa SymbolicUtils.BasicSymbolic{Rational{Int64}}
@test unwrap(rn.l5) isa SymbolicUtils.BasicSymbolic{Rational{Int64}}

# Checks that other parameter properties are assigned properly.
@test !ModelingToolkit.hasdefault(unwrap(rn.k1))
@test ModelingToolkit.getdefault(unwrap(rn.k2)) == 2.0
@test ModelingToolkit.getdefault(unwrap(rn.k3)) == 2
@test ModelingToolkit.getdescription(unwrap(rn.k3)) == "A parameter"
@test ModelingToolkit.getdescription(unwrap(rn.k4)) == "Another parameter"
@test !ModelingToolkit.hasdescription(unwrap(rn.k5))
end

### Observables ###

# Test basic functionality.
Expand Down
Loading