Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
35 changes: 35 additions & 0 deletions test/simulation_and_solving/simulate_ODEs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,41 @@ end

### Other Tests ###

# Checks that solution values have types consistent with their input types.
# Check that both float types are preserved in the solution (and problems), while integers are
# promoted to floats.
# Checks that the time types are correct (`Float64` by default or possibly `Float32`), however,
# type conversion only occurs in the solution, and integer types are preserved in problems.
let
# Create model. Checks when input type is `Float64` the produced values are also `Float64`.
rn = @reaction_network begin
(k1,k2), X1 <--> X2
end
u0 = [:X1 => 1.0, :X2 => 3.0]
ps = [:k1 => 2.0, :k2 => 3.0]
oprob = ODEProblem(rn, u0, 1.0, ps)
osol = solve(oprob)
@test eltype(osol[:X1]) == eltype(osol[:X2]) == typeof(oprob[:X1]) == typeof(oprob[:X2]) == Float64
@test eltype(osol.t) == typeof(oprob.tspan[1]) == typeof(oprob.tspan[2]) == Float64

# Checks that `Int64` values are promoted to `Float64`.
u0 = [:X1 => 1, :X2 => 3]
ps = [:k1 => 2, :k2 => 3]
oprob = ODEProblem(rn, u0, 1, ps)
osol = solve(oprob)
@test eltype(osol[:X1]) == eltype(osol[:X2]) == typeof(oprob[:X1]) == typeof(oprob[:X2]) == Float64
@test eltype(osol.t) == Float64
@test typeof(oprob.tspan[1]) == typeof(oprob.tspan[2]) == Int64
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we care about these remaining integers? That seems degenerate since at some point they will have to be converted to floating point.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like this is asking for trouble since converting them earlier seems reasonable and could be implemented at some point.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally, I really don't care what the type is. However I don't like the idea of theses suddenly jumping around (as it is likely non-intentional and a sign something else might be going on. And if it is intentional it is easy to switch here)

I will ask about it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So apparently the current policy is for XProblem to not do any type promotion. I'm inclined to adding a comment to the test about the situation, and if how XProblems work changes we change the test (after confirming that it is intentional). The potential drawback seems small.

But if you want to remove I will do so.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’d still prefer to use problem appropriate types. So use Float32/16/64 for such tests. It just seems like we are testing a degenerate case here that they could reasonably decide to promote at any moment (since ultimately it is getting promoted during solves), and could then break this test.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or even use BigFloat if you want a less common type.


# Checks when values are `Float32` (a valid type and should be preserved).
u0 = [:X1 => 1.0f0, :X2 => 3.0f0]
ps = [:k1 => 2.0f0, :k2 => 3.0f0]
oprob = ODEProblem(rn, u0, 1.0f0, ps)
osol = solve(oprob)
@test eltype(osol[:X1]) == eltype(osol[:X2]) == typeof(oprob[:X1]) == typeof(oprob[:X2]) == Float32
@test eltype(osol.t) == typeof(oprob.tspan[1]) == typeof(oprob.tspan[2]) == Float32
end

# Tests simulating a network without parameters.
let
no_param_network = @reaction_network begin
Expand Down
35 changes: 35 additions & 0 deletions test/simulation_and_solving/simulate_SDEs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,41 @@ end

### Other Tests ###

# Checks that solution values have types consistent with their input types.
# Check that both float types are preserved in the solution (and problems), while integers are
# promoted to floats.
# Checks that the time types are correct (`Float64` by default or possibly `Float32`), however,
# type conversion only occurs in the solution, and integer types are preserved in problems.
let
# Create model. Checks when input type is `Float64` the produced values are also `Float64`.
rn = @reaction_network begin
(k1,k2), X1 <--> X2
end
u0 = [:X1 => 1.0, :X2 => 3.0]
ps = [:k1 => 2.0, :k2 => 3.0]
sprob = SDEProblem(rn, u0, 1.0, ps)
ssol = solve(sprob, ISSEM())
@test eltype(ssol[:X1]) == eltype(ssol[:X2]) == typeof(sprob[:X1]) == typeof(sprob[:X2]) == Float64
@test eltype(ssol.t) == typeof(sprob.tspan[1]) == typeof(sprob.tspan[2]) == Float64

# Checks that `Int64` values are promoted to `Float64`.
u0 = [:X1 => 1, :X2 => 3]
ps = [:k1 => 2, :k2 => 3]
sprob = SDEProblem(rn, u0, 1, ps)
ssol = solve(sprob, ISSEM())
@test eltype(ssol[:X1]) == eltype(ssol[:X2]) == typeof(sprob[:X1]) == typeof(sprob[:X2]) == Float64
@test eltype(ssol.t) == Float64
@test typeof(sprob.tspan[1]) == typeof(sprob.tspan[2]) == Int64
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment about types


# Checks when values are `Float32` (a valid type and should be preserved).
u0 = [:X1 => 1.0f0, :X2 => 3.0f0]
ps = [:k1 => 2.0f0, :k2 => 3.0f0]
sprob = SDEProblem(rn, u0, 1.0f0, ps)
ssol = solve(sprob, ISSEM())
@test eltype(ssol[:X1]) == eltype(ssol[:X2]) == typeof(sprob[:X1]) == typeof(sprob[:X2]) == Float32
@test eltype(ssol.t) == typeof(sprob.tspan[1]) == typeof(sprob.tspan[2]) == Float32
end

# Tests simulating a network without parameters.
let
no_param_network = @reaction_network begin
Expand Down
44 changes: 44 additions & 0 deletions test/simulation_and_solving/simulate_jumps.jl
Original file line number Diff line number Diff line change
Expand Up @@ -220,3 +220,47 @@ let
@test (means1[1] - means1[2]) < .1 * means1[1]
@test (means2[1] - means2[2]) < .1 * means2[1]
end

### Other Tests ###

# Checks that solution values have types consistent with their input types.
# Check that both float and integer types are preserved in the solution (and problems).
# Checks that the time types are correct (`Float64` by default or possibly `Float32`).
# `JumpInputs` currently does not support integer time spans. When it does, we will check that
# these produce `Float64` time values.
let
# Create model. Checks when input type is `Float64` the produced values are also `Float64`.
rn = @reaction_network begin
(k1,k2), X1 <--> X2
end
u0 = [:X1 => 1.0, :X2 => 3.0]
ps = [:k1 => 2.0, :k2 => 3.0]
jprob = JumpProblem(JumpInputs(rn, u0, (0.0, 1.0), ps))
jsol = solve(jprob)
@test eltype(jsol[:X1]) == eltype(jsol[:X2]) == typeof(jprob[:X1]) == typeof(jprob[:X2]) == Float64
@test eltype(jsol.t) == typeof(jprob.prob.tspan[1]) == typeof(jprob.prob.tspan[2]) == Float64

# Checks that `Int64` gives `Int64` species values.
u0 = [:X1 => 1 :X2 => 3]
ps = [:k1 => 2, :k2 => 3]
jprob = JumpProblem(JumpInputs(rn, u0, (0.0, 1.0), ps))
jsol = solve(jprob)
@test eltype(jsol[:X1]) == eltype(jsol[:X2]) == typeof(jprob[:X1]) == typeof(jprob[:X2]) == Int64
@test eltype(jsol.t) == typeof(jprob.prob.tspan[1]) == typeof(jprob.prob.tspan[2]) == Float64

# Checks when values are `Float32` (a valid type and should be preserved).
u0 = [:X1 => 1.0f0, :X2 => 3.0f0]
ps = [:k1 => 2.0f0, :k2 => 3.0f0]
jprob = JumpProblem(JumpInputs(rn, u0, (0.0f0, 1.0f0), ps))
jsol = solve(jprob)
@test eltype(jsol[:X1]) == eltype(jsol[:X2]) == typeof(jprob[:X1]) == typeof(jprob[:X2]) == Float32
@test eltype(jsol.t) == typeof(jprob.prob.tspan[1]) == typeof(jprob.prob.tspan[2]) == Float32

# Checks when values are `Int32` (a valid species type and should be preserved).
u0 = [:X1 => Int32(1), :X2 => Int32(3)]
ps = [:k1 => Int32(2), :k2 => Int32(3)]
jprob = JumpProblem(JumpInputs(rn, u0, (0.0, 1.0), ps))
jsol = solve(jprob)
@test eltype(jsol[:X1]) == eltype(jsol[:X2]) == typeof(jprob[:X1]) == typeof(jprob[:X2]) == Int32
@test eltype(jsol.t) == typeof(jprob.prob.tspan[1]) == typeof(jprob.prob.tspan[2]) == Float64
end
31 changes: 31 additions & 0 deletions test/simulation_and_solving/solve_nonlinear.jl
Original file line number Diff line number Diff line change
Expand Up @@ -101,3 +101,34 @@ let
@test f_eval(steady_state_network_3, [:X => sol1[X], :Y => sol1[Y], :Y2 => sol1[Y2], :XY2 => sol1[XY2]], p, 0.0) ≈ [0.0, 0.0, 0.0, 0.0] atol=1e-10
@test f_eval(steady_state_network_3, [:X => sol2[X], :Y => sol2[Y], :Y2 => sol2[Y2], :XY2 => sol2[XY2]], p, 0.0) ≈ [0.0, 0.0, 0.0, 0.0] atol=1e-10
end

### Other Tests ###

# Checks that solution values have types consistent with their input types.
# Check for values that types that should be preserved (`Float64` and `Float32`) and types
# that should be converted to the default (conversion of `Int64 to `Float64`).
let
# Create model. Checks when input type is `Float64` that the problem and solution types are `Float64`.
rn = @reaction_network begin
(k1,k2), X1 <--> X2
end
u0 = [:X1 => 1.0, :X2 => 3.0]
ps = [:k1 => 2.0, :k2 => 3.0]
nlprob = NonlinearProblem(rn, u0, ps)
nlsol = solve(nlprob)
@test eltype(nlsol[:X1]) == eltype(nlsol[:X2]) == typeof(nlprob[:X1]) == typeof(nlprob[:X2]) == Float64

# Checks that input type `Int64` is converted to `Float64`.
u0 = [:X1 => 1, :X2 => 3]
ps = [:k1 => 2, :k2 => 3]
nlprob = NonlinearProblem(rn, u0, ps)
nlsol = solve(nlprob)
@test eltype(nlsol[:X1]) == eltype(nlsol[:X2]) == typeof(nlprob[:X1]) == typeof(nlprob[:X2]) == Float64

# Checks that input type `Float32` is preserved
u0 = [:X1 => 1.0f0, :X2 => 3.0f0]
ps = [:k1 => 2.0f0, :k2 => 3.0f0]
nlprob = NonlinearProblem(rn, u0, ps)
nlsol = solve(nlprob)
@test eltype(nlsol[:X1]) == eltype(nlsol[:X2]) == typeof(nlprob[:X1]) == typeof(nlprob[:X2]) == Float32
end
Loading