Skip to content

Commit 5f250f6

Browse files
authored
Merge pull request #1543 from anandijain/aj/iso2
isisomorphic and convert_system fix
2 parents cdcf181 + 42752c9 commit 5f250f6

File tree

5 files changed

+105
-2
lines changed

5 files changed

+105
-2
lines changed

Project.toml

Lines changed: 2 additions & 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"
@@ -45,6 +46,7 @@ Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d"
4546
[compat]
4647
AbstractTrees = "0.3"
4748
ArrayInterface = "3.1.39, 4, 5"
49+
Combinatorics = "1"
4850
ConstructionBase = "1"
4951
DataStructures = "0.17, 0.18"
5052
DiffEqBase = "6.81.0"

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: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -900,3 +900,51 @@ 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+
function SymbolicUtils.substitute(op::Symbolics.Differential, dict; kwargs...)
906+
@set! op.x = substitute(op.x, dict; kwargs...)
907+
end
908+
909+
function _match_eqs(eqs1, eqs2)
910+
eqpairs = Pair[]
911+
for (i, eq) in enumerate(eqs1)
912+
for (j, eq2) in enumerate(eqs2)
913+
if isequal(eq, eq2)
914+
push!(eqpairs, i => j)
915+
break
916+
end
917+
end
918+
end
919+
eqpairs
920+
end
921+
922+
function isisomorphic(sys1::AbstractODESystem, sys2::AbstractODESystem)
923+
sys1 = flatten(sys1)
924+
sys2 = flatten(sys2)
925+
926+
iv2 = only(independent_variables(sys2))
927+
sys1 = convert_system(ODESystem, sys1, iv2)
928+
s1, s2 = states(sys1), states(sys2)
929+
p1, p2 = parameters(sys1), parameters(sys2)
930+
931+
(length(s1) != length(s2)) || (length(p1) != length(p2)) && return false
932+
933+
eqs1 = equations(sys1)
934+
eqs2 = equations(sys2)
935+
936+
pps = permutations(p2)
937+
psts = permutations(s2)
938+
orig = [p1; s1]
939+
perms = ([x; y] for x in pps for y in psts)
940+
941+
for perm in perms
942+
rules = Dict(orig .=> perm)
943+
neweqs1 = substitute(eqs1, rules)
944+
eqpairs = _match_eqs(neweqs1, eqs2)
945+
if length(eqpairs) == length(eqs1)
946+
return true
947+
end
948+
end
949+
return false
950+
end

src/systems/diffeqs/odesystem.jl

Lines changed: 6 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 = similarterm(s, operation(s), (t,); metadata=SymbolicUtils.metadata(s))
371371
newsts[i] = ns
372372
varmap[s] = ns
373373
else
@@ -377,7 +377,11 @@ function convert_system(::Type{<:ODESystem}, sys, t; name=nameof(sys))
377377
end
378378
end
379379
sub = Base.Fix2(substitute, varmap)
380+
if sys isa AbstractODESystem
381+
iv = only(independent_variables(sys))
382+
sub.x[iv] = t # otherwise the Differentials aren't fixed
383+
end
380384
neweqs = map(sub, equations(sys))
381385
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)
386+
return ODESystem(neweqs, t, newsts, parameters(sys); defaults=defs, name=name, checks=false)
383387
end

test/odesystem.jl

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -672,3 +672,51 @@ 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+
# array u
697+
eqs3 = [D2(u[1]) ~ sigma * (u[2] - u[1]),
698+
D2(u[2]) ~ u[1] * (rho - u[3]) - u[2],
699+
D2(u[3]) ~ u[1] * u[2] - beta * u[3]]
700+
eqs3 = eqs_to_lhs(eqs3)
701+
702+
eqs4 = [
703+
D2(y2) ~ x2 * (rho - z2) - y2,
704+
D2(x2) ~ sigma * (y2 - x2),
705+
D2(z2) ~ y2 - beta * z2 # missing x2 term
706+
]
707+
708+
@named sys1 = ODESystem(eqs)
709+
@named sys2 = ODESystem(eqs2)
710+
@named sys3 = ODESystem(eqs3, t2)
711+
ssys3 = structural_simplify(sys3)
712+
@named sys4 = ODESystem(eqs4)
713+
714+
@test ModelingToolkit.isisomorphic(sys1, sys2)
715+
@test !ModelingToolkit.isisomorphic(sys1, sys3)
716+
@test ModelingToolkit.isisomorphic(sys1, ssys3) # I don't call structural_simplify in isisomorphic
717+
@test !ModelingToolkit.isisomorphic(sys1, sys4)
718+
719+
# 1281
720+
iv2 = only(independent_variables(sys2))
721+
@test isequal(only(independent_variables(convert_system(ODESystem, sys1, iv2))), iv2)
722+
end

0 commit comments

Comments
 (0)