Skip to content

Commit f773a97

Browse files
committed
isisomorphic and convert_system fix
1 parent cdcf181 commit f773a97

File tree

5 files changed

+98
-2
lines changed

5 files changed

+98
-2
lines changed

Project.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ version = "8.8.1"
66
[deps]
77
AbstractTrees = "1520ce14-60c1-5f80-bbc7-55ef81b5835c"
88
ArrayInterface = "4fba245c-0d91-5ea0-9b3e-6abc04ee57a9"
9+
Combinatorics = "861a8166-3701-5b0c-9a16-15d98fcdc6aa"
910
ConstructionBase = "187b0558-2788-49d3-abe0-74a17ed4e7c9"
1011
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
1112
DiffEqBase = "2b5f629d-d688-5b77-993f-72d75c75574e"

src/ModelingToolkit.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import MacroTools: splitdef, combinedef, postwalk, striplines
2323
import Libdl
2424
using DocStringExtensions
2525
using Base: RefValue
26+
using Combinatorics
2627
import IfElse
2728

2829
import Distributions

src/systems/diffeqs/abstractodesystem.jl

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -900,3 +900,53 @@ end
900900
function SteadyStateProblemExpr(sys::AbstractODESystem, args...; kwargs...)
901901
SteadyStateProblemExpr{true}(sys, args...; kwargs...)
902902
end
903+
904+
# SU 442 and Symbolics 588 copied over for CI, will be removed
905+
(f::Symbolic{<:FnType})(args...; kwargs...) = Term{promote_symtype(f, symtype.(args)...)}(f, [args...]; kwargs...)
906+
function SymbolicUtils.substitute(op::Symbolics.Differential, dict; kwargs...)
907+
@set! op.x = substitute(op.x, dict; kwargs...)
908+
end
909+
910+
function _match_eqs(eqs1, eqs2)
911+
eqpairs = Pair[]
912+
for (i, eq) in enumerate(eqs1)
913+
for (j, eq2) in enumerate(eqs2)
914+
if isequal(eq, eq2)
915+
push!(eqpairs, i => j)
916+
break
917+
elseif !isequal(eq, eq2) && j == length(eqs2)
918+
end
919+
end
920+
end
921+
eqpairs
922+
end
923+
924+
function isisomorphic(sys1::AbstractODESystem, sys2::AbstractODESystem; verbose=false)
925+
sys1 = flatten(sys1)
926+
sys2 = flatten(sys2)
927+
928+
iv1, iv2 = independent_variable(sys1), independent_variable(sys2) # not needed
929+
sys1 = convert_system(ODESystem, sys1, iv2)
930+
s1, s2 = states(sys1), states(sys2)
931+
p1, p2 = parameters(sys1), parameters(sys2)
932+
933+
(length(s1) != length(s2)) || (length(p1) != length(p2)) && return false
934+
935+
eqs1 = equations(sys1)
936+
eqs2 = equations(sys2)
937+
938+
pps = permutations(p2)
939+
psts = permutations(s2)
940+
orig = [p1; s1]
941+
perms = [[x; y] for x in pps for y in psts]
942+
943+
for perm in perms
944+
rules = Dict(orig .=> perm)
945+
neweqs1 = substitute(eqs1, rules)
946+
eqpairs = _match_eqs(neweqs1, eqs2)
947+
if length(eqpairs) == length(eqs1)
948+
return true
949+
end
950+
end
951+
return false
952+
end

src/systems/diffeqs/odesystem.jl

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,7 @@ function convert_system(::Type{<:ODESystem}, sys, t; name=nameof(sys))
367367
newsts[i] = s
368368
continue
369369
end
370-
ns = operation(s)(t)
370+
ns = operation(s)(t; metadata=SymbolicUtils.metadata(s))
371371
newsts[i] = ns
372372
varmap[s] = ns
373373
else
@@ -377,7 +377,9 @@ function convert_system(::Type{<:ODESystem}, sys, t; name=nameof(sys))
377377
end
378378
end
379379
sub = Base.Fix2(substitute, varmap)
380+
iv = independent_variable(sys)
381+
sub.x[iv] = t # otherwise the Differentials aren't fixed
380382
neweqs = map(sub, equations(sys))
381383
defs = Dict(sub(k) => sub(v) for (k, v) in defaults(sys))
382-
return ODESystem(neweqs, t, newsts, parameters(sys); defaults=defs, name=name,checks=false)
384+
return ODESystem(neweqs, t, newsts, parameters(sys); defaults=defs, name=name, checks=false)
383385
end

test/odesystem.jl

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -672,3 +672,45 @@ let
672672
@named sys = ODESystem(eqs, t)
673673
@test length(equations(structural_simplify(sys))) == 2
674674
end
675+
676+
let
677+
eq_to_lhs(eq) = eq.lhs - eq.rhs ~ 0
678+
eqs_to_lhs(eqs) = eq_to_lhs.(eqs)
679+
680+
@parameters σ = 10 ρ = 28 β = 8 / 3 sigma rho beta
681+
@variables t t2 x(t) = 1 y(t) = 0 z(t) = 0 x2(t2) = 1 y2(t2) = 0 z2(t2) = 0 u[1:3](t2)
682+
683+
D = Differential(t)
684+
D2 = Differential(t2)
685+
686+
eqs = [D(x) ~ σ * (y - x),
687+
D(y) ~ x *- z) - y,
688+
D(z) ~ x * y - β * z]
689+
690+
eqs2 = [
691+
D2(y2) ~ x2 * (rho - z2) - y2,
692+
D2(x2) ~ sigma * (y2 - x2),
693+
D2(z2) ~ x2 * y2 - beta * z2
694+
]
695+
696+
eqs3 = copy(eqs2)
697+
698+
# array u
699+
eqs3 = [D2(u[1]) ~ sigma * (u[2] - u[1]),
700+
D2(u[2]) ~ u[1] * (rho - u[3]) - u[2],
701+
D2(u[3]) ~ u[1] * u[2] - beta * u[3]]
702+
eqs3 = eqs_to_lhs(eqs3)
703+
704+
@named sys1 = ODESystem(eqs)
705+
@named sys2 = ODESystem(eqs2)
706+
@named sys3 = ODESystem(eqs3, t2)
707+
ssys3 = structural_simplify(sys3)
708+
709+
@test ModelingToolkit.isisomorphic(sys1, sys2)
710+
@test !ModelingToolkit.isisomorphic(sys1, sys3)
711+
@test ModelingToolkit.isisomorphic(sys1, ssys3) # I don't call structural_simplify in isisomorphic
712+
713+
# 1281
714+
iv2 = independent_variable(sys2)
715+
@test isequal(independent_variable(convert_system(ODESystem, sys1, iv2)), iv2)
716+
end

0 commit comments

Comments
 (0)