Skip to content

Commit 36eed89

Browse files
committed
Add checks for unique subsystem names. Fixes #819.
1 parent 448247a commit 36eed89

File tree

10 files changed

+76
-7
lines changed

10 files changed

+76
-7
lines changed

src/systems/control/controlsystem.jl

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ struct ControlSystem <: AbstractControlSystem
6060
ps::Vector
6161
observed::Vector{Equation}
6262
"""
63-
Name: the name of the system
63+
Name: the name of the system. These are required to have unique names.
6464
"""
6565
name::Symbol
6666
"""
@@ -84,6 +84,10 @@ function ControlSystem(loss, deqs::AbstractVector{<:Equation}, iv, dvs, controls
8484
if !(isempty(default_u0) && isempty(default_p))
8585
Base.depwarn("`default_u0` and `default_p` are deprecated. Use `defaults` instead.", :ControlSystem, force=true)
8686
end
87+
sysnames = nameof.(systems)
88+
if length(unique(sysnames)) != length(sysnames)
89+
throw(ArgumentError("System names must be unique."))
90+
end
8791
iv′ = value(iv)
8892
dvs′ = value.(dvs)
8993
controls′ = value.(controls)

src/systems/diffeqs/sdesystem.jl

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ struct SDESystem <: AbstractODESystem
6363
"""
6464
name::Symbol
6565
"""
66-
Systems: the internal systems
66+
Systems: the internal systems. These are required to have unique names.
6767
"""
6868
systems::Vector{SDESystem}
6969
"""
@@ -89,7 +89,10 @@ function SDESystem(deqs::AbstractVector{<:Equation}, neqs, iv, dvs, ps;
8989
iv′ = value(iv)
9090
dvs′ = value.(dvs)
9191
ps′ = value.(ps)
92-
92+
sysnames = nameof.(systems)
93+
if length(unique(sysnames)) != length(sysnames)
94+
throw(ArgumentError("System names must be unique."))
95+
end
9396
if !(isempty(default_u0) && isempty(default_p))
9497
Base.depwarn("`default_u0` and `default_p` are deprecated. Use `defaults` instead.", :SDESystem, force=true)
9598
end

src/systems/jumps/jumpsystem.jl

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ struct JumpSystem{U <: ArrayPartition} <: AbstractSystem
3838
"""The parameters of the system."""
3939
ps::Vector
4040
observed::Vector{Equation}
41-
"""The name of the system."""
41+
"""The name of the system. . These are required to have unique names."""
4242
name::Symbol
4343
"""The internal systems."""
4444
systems::Vector{JumpSystem}
@@ -62,7 +62,10 @@ function JumpSystem(eqs, iv, states, ps;
6262
name = gensym(:JumpSystem),
6363
connection_type=nothing,
6464
)
65-
65+
sysnames = nameof.(systems)
66+
if length(unique(sysnames)) != length(sysnames)
67+
throw(ArgumentError("System names must be unique."))
68+
end
6669
ap = ArrayPartition(MassActionJump[], ConstantRateJump[], VariableRateJump[])
6770
for eq in eqs
6871
if eq isa MassActionJump

src/systems/nonlinear/nonlinearsystem.jl

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ struct NonlinearSystem <: AbstractSystem
3232
"""
3333
jac::RefValue{Any}
3434
"""
35-
Name: the name of the system
35+
Name: the name of the system. These are required to have unique names.
3636
"""
3737
name::Symbol
3838
"""
@@ -66,6 +66,10 @@ function NonlinearSystem(eqs, states, ps;
6666
if !(isempty(default_u0) && isempty(default_p))
6767
Base.depwarn("`default_u0` and `default_p` are deprecated. Use `defaults` instead.", :NonlinearSystem, force=true)
6868
end
69+
sysnames = nameof.(systems)
70+
if length(unique(sysnames)) != length(sysnames)
71+
throw(ArgumentError("System names must be unique."))
72+
end
6973
jac = RefValue{Any}(Matrix{Num}(undef, 0, 0))
7074
defaults = todict(defaults)
7175
defaults = Dict(value(k) => value(v) for (k, v) in pairs(defaults))

src/systems/optimization/optimizationsystem.jl

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ struct OptimizationSystem <: AbstractSystem
2727
equality_constraints::Vector{Equation}
2828
inequality_constraints::Vector
2929
"""
30-
Name: the name of the system
30+
Name: the name of the system. These are required to have unique names.
3131
"""
3232
name::Symbol
3333
"""
@@ -53,6 +53,10 @@ function OptimizationSystem(op, states, ps;
5353
if !(isempty(default_u0) && isempty(default_p))
5454
Base.depwarn("`default_u0` and `default_p` are deprecated. Use `defaults` instead.", :OptimizationSystem, force=true)
5555
end
56+
sysnames = nameof.(systems)
57+
if length(unique(sysnames)) != length(sysnames)
58+
throw(ArgumentError("System names must be unique."))
59+
end
5660
defaults = todict(defaults)
5761
defaults = Dict(value(k) => value(v) for (k, v) in pairs(defaults))
5862

test/controlsystem.jl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,14 @@ sys = runge_kutta_discretize(sys,dt,tspan)
1818
u0 = rand(length(states(sys))) # guess for the state values
1919
prob = OptimizationProblem(sys,u0,[0.1,0.1],grad=true)
2020
sol = solve(prob,BFGS())
21+
22+
# issue #819
23+
@testset "Combined system name collisions" begin
24+
eqs_short = [
25+
D(x) ~ - p[2]*x
26+
D(v) ~ p[1]*u^3
27+
]
28+
sys1 = ControlSystem(loss,eqs_short,t,[x,v],[u],p,name=:sys1)
29+
sys2 = ControlSystem(loss,eqs_short,t,[x,v],[u],p,name=:sys1)
30+
@test_throws ArgumentError ControlSystem(loss,[sys2.v ~ sys1.v],t, [],[],[],systems=[sys1, sys2])
31+
end

test/jumpsystem.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,3 +153,9 @@ dprob = DiscreteProblem(js4, [S => 999], (0,1000.), [β => 100.,γ => .01])
153153
jprob = JumpProblem(js4, dprob, Direct())
154154
sol = solve(jprob, SSAStepper());
155155

156+
# issue #819
157+
@testset "Combined system name collisions" begin
158+
sys1 = JumpSystem([maj1,maj2], t, [S], [β,γ],name=:sys1)
159+
sys2 = JumpSystem([maj1,maj2], t, [S], [β,γ],name=:sys1)
160+
@test_throws ArgumentError JumpSystem([sys1.γ ~ sys2.γ], t,[],[], systems=[sys1, sys2])
161+
end

test/nonlinearsystem.jl

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,3 +118,20 @@ eqs = [0 ~ σ*(y-x),
118118
ns = NonlinearSystem(eqs, [x,y,z], [σ,ρ,β])
119119
np = NonlinearProblem(ns, [0,0,0], [1,2,3], jac=true, sparse=true)
120120
@test ModelingToolkit.get_jac(ns)[] isa SparseMatrixCSC
121+
122+
# issue #819
123+
@testset "Combined system name collisions" begin
124+
function makesys(name)
125+
@parameters a
126+
@variables x f
127+
128+
NonlinearSystem([0 ~ -a*x + f],[x,f],[a], name=name)
129+
end
130+
131+
function issue819()
132+
sys1 = makesys(:sys1)
133+
sys2 = makesys(:sys1)
134+
@test_throws ArgumentError NonlinearSystem([sys2.f ~ sys1.x, sys1.f ~ 0],[],[], systems=[sys1, sys2])
135+
end
136+
issue819()
137+
end

test/optimizationsystem.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,9 @@ _p = [1.0, 100.0]
5454
f = OptimizationFunction(rosenbrock,ModelingToolkit.AutoModelingToolkit(),x0,_p,grad=true,hess=true)
5555
prob = OptimizationProblem(f,x0,_p)
5656
sol = solve(prob,Optim.Newton())
57+
58+
# issue #819
59+
@testset "Combined system name collisions" begin
60+
sys2 = OptimizationSystem(loss,[x,y],[a,b],name=:sys1)
61+
@test_throws ArgumentError OptimizationSystem(loss2,[z],[β],systems=[sys1,sys2])
62+
end

test/sdesystem.jl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,3 +432,14 @@ du = similar(u0, size(prob.noise_rate_prototype))
432432
fdif!(du,u0,p,t)
433433
@test du == [ cos(p[1])*sin(u0[1]) cos(p[1])*cos(u0[1]) -sin(p[1])*sin(u0[2]) -sin(p[1])*cos(u0[2])
434434
sin(p[1])*sin(u0[1]) sin(p[1])*cos(u0[1]) cos(p[1])*sin(u0[2]) cos(p[1])*cos(u0[2])]
435+
436+
# issue #819
437+
@testset "Combined system name collisions" begin
438+
@variables t
439+
eqs_short = [D(x) ~ σ*(y-x),
440+
D(y) ~ x*-z)-y,
441+
]
442+
sys1 = SDESystem(eqs_short,noiseeqs,t,[x,y,z],[σ,ρ,β],name=:sys1)
443+
sys2 = SDESystem(eqs_short,noiseeqs,t,[x,y,z],[σ,ρ,β],name=:sys1)
444+
@test_throws ArgumentError SDESystem([sys2.y ~ sys1.z], t,[],[],[], systems=[sys1, sys2])
445+
end

0 commit comments

Comments
 (0)