From 32613f3862477bc73841cca02960f737cb4a44fe Mon Sep 17 00:00:00 2001 From: Herman Sletmoen Date: Thu, 25 Apr 2024 17:10:46 +0200 Subject: [PATCH 1/3] Fix structural simplification of non-1-indexed variable arrays --- Project.toml | 1 + src/structural_transformation/symbolics_tearing.jl | 6 +++++- test/odesystem.jl | 10 ++++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 6a7a0bcecf..09f984444b 100644 --- a/Project.toml +++ b/Project.toml @@ -32,6 +32,7 @@ Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" MLStyle = "d8e11817-5142-5d16-987a-aa16d5891078" NaNMath = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3" +OffsetArrays = "6fe1bfb0-de20-5000-8ca7-80f57d26f881" OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed" PrecompileTools = "aea7be01-6a6a-4083-8856-8a6e6704d82a" RecursiveArrayTools = "731186ca-8d62-57ce-b412-fbd966d074cd" diff --git a/src/structural_transformation/symbolics_tearing.jl b/src/structural_transformation/symbolics_tearing.jl index f2f27e8606..0764e16c3e 100644 --- a/src/structural_transformation/symbolics_tearing.jl +++ b/src/structural_transformation/symbolics_tearing.jl @@ -1,3 +1,5 @@ +using OffsetArrays: Origin + # N.B. assumes `slist` and `dlist` are unique function substitution_graph(graph, slist, dlist, var_eq_matching) ns = length(slist) @@ -573,7 +575,9 @@ function tearing_reassemble(state::TearingState, var_eq_matching, Symbolics.shape(lhs) !== Symbolics.Unknown() || continue arg1 = arguments(lhs)[1] haskey(obs_arr_subs, arg1) && continue - obs_arr_subs[arg1] = [arg1[i] for i in eachindex(arg1)] + obs_arr_subs[arg1] = [arg1[i] for i in eachindex(arg1)] # e.g. p => [p[1], p[2]] + index_first = eachindex(arg1)[1] + obs_arr_subs[arg1] = Origin(index_first)(obs_arr_subs[arg1]) # respect non-1-indexed arrays end for i in eachindex(neweqs) neweqs[i] = fast_substitute(neweqs[i], obs_arr_subs; operator = Symbolics.Operator) diff --git a/test/odesystem.jl b/test/odesystem.jl index f11ab62a06..bca7f7f99a 100644 --- a/test/odesystem.jl +++ b/test/odesystem.jl @@ -1159,3 +1159,13 @@ for sys in [sys1, sys2] @test variable_index(sys, x[i]) == variable_index(sys, x)[i] end end + +@testset "Non-1-indexed variable array (issue #2670)" begin + @variables x(t)[0:1] # 0-indexed variable array + sys = ODESystem([ + x[0] ~ 0.0 + D(x[1]) ~ x[0] + ], t, [x], []; name=:sys) + @test_nowarn sys = structural_simplify(sys) + @test equations(sys) == [D(x[1]) ~ 0.0] +end \ No newline at end of file From c06abfe86ad6815694732f81e5b757b4fa58ed7e Mon Sep 17 00:00:00 2001 From: Herman Sletmoen Date: Thu, 25 Apr 2024 17:21:08 +0200 Subject: [PATCH 2/3] Format code --- src/structural_transformation/symbolics_tearing.jl | 2 +- test/odesystem.jl | 7 ++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/structural_transformation/symbolics_tearing.jl b/src/structural_transformation/symbolics_tearing.jl index 0764e16c3e..d1d86cac1a 100644 --- a/src/structural_transformation/symbolics_tearing.jl +++ b/src/structural_transformation/symbolics_tearing.jl @@ -576,7 +576,7 @@ function tearing_reassemble(state::TearingState, var_eq_matching, arg1 = arguments(lhs)[1] haskey(obs_arr_subs, arg1) && continue obs_arr_subs[arg1] = [arg1[i] for i in eachindex(arg1)] # e.g. p => [p[1], p[2]] - index_first = eachindex(arg1)[1] + index_first = eachindex(arg1)[1] obs_arr_subs[arg1] = Origin(index_first)(obs_arr_subs[arg1]) # respect non-1-indexed arrays end for i in eachindex(neweqs) diff --git a/test/odesystem.jl b/test/odesystem.jl index bca7f7f99a..cbef18473f 100644 --- a/test/odesystem.jl +++ b/test/odesystem.jl @@ -1162,10 +1162,7 @@ end @testset "Non-1-indexed variable array (issue #2670)" begin @variables x(t)[0:1] # 0-indexed variable array - sys = ODESystem([ - x[0] ~ 0.0 - D(x[1]) ~ x[0] - ], t, [x], []; name=:sys) + @named sys = ODESystem([x[0] ~ 0.0, D(x[1]) ~ x[0]], t, [x], []) @test_nowarn sys = structural_simplify(sys) @test equations(sys) == [D(x[1]) ~ 0.0] -end \ No newline at end of file +end From 163be441de8f7806b0245de80914dc2934d9a010 Mon Sep 17 00:00:00 2001 From: Herman Sletmoen Date: Mon, 7 Oct 2024 12:56:01 +0200 Subject: [PATCH 3/3] Ensure OffsetArrays dependency is removed when non-1-indexed array hack is removed --- src/structural_transformation/symbolics_tearing.jl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/structural_transformation/symbolics_tearing.jl b/src/structural_transformation/symbolics_tearing.jl index f346e20b2a..84cee928cd 100644 --- a/src/structural_transformation/symbolics_tearing.jl +++ b/src/structural_transformation/symbolics_tearing.jl @@ -589,7 +589,10 @@ function tearing_reassemble(state::TearingState, var_eq_matching, haskey(obs_arr_subs, arg1) && continue obs_arr_subs[arg1] = [arg1[i] for i in eachindex(arg1)] # e.g. p => [p[1], p[2]] index_first = eachindex(arg1)[1] - obs_arr_subs[arg1] = Origin(index_first)(obs_arr_subs[arg1]) # respect non-1-indexed arrays + + # respect non-1-indexed arrays + # TODO: get rid of this hack together with the above hack, then remove OffsetArrays dependency + obs_arr_subs[arg1] = Origin(index_first)(obs_arr_subs[arg1]) end for i in eachindex(neweqs) neweqs[i] = fast_substitute(neweqs[i], obs_arr_subs; operator = Symbolics.Operator)