Register_symbolic with arrays: What am I doing wrong

Hello,

I am unable to register a symbolic function that takes an array and returns a scalar. This makes me think I need to use register_symbolic rather than the array counterpart. However, the array that is sent is a Vector{SymbolicUtils.BasicSymbolic{Real}}and I need it to convert to something like Vector{Real} as I want to send it to other functions from other packages. A small example work case is below:

using ModelingToolkit, Dierckx, OrdinaryDiffEq
using ModelingToolkit: t_nounits as t, D_nounits as D

function model_eq(;name)
    @variables x(t)[1:10]

    eqs = [D(x) .~ registered(x,t)]

    eqs = Symbolics.scalarize(reduce(vcat,Symbolics.scalarize.(eqs)))

    ODESystem(eqs,t;name)
end

function registered(x::AbstractVector,t::Real)
    y=collect(1.0:10.0)
    spl = Spline1D(y,x,bc="nearest")
    return 1.1 * t
end
@register_symbolic registered(x::AbstractVector,t)

function main()
    @named eq = model_eq()
    comp  =structural_simplify(eq)
    u0 = [comp.x => collect(1.0:10.0)]
    prob=ODEProblem(comp,u0,(0.0,10.0))
    sol =solve(prob,Tsit5();reltol=1e-3,abstol=1e-3)
    return sol
end

sol = main()

Can anyone tell me what I am doing wrong because for example in this case, the spline won’t form, even though it is unnecessary in the MWE, while the vector is in a symbolic form.

Thanks for any help

I have an idea that it is because scalarize makes the vector a normal vector of symbolic values rather than a symbolic vector so the register doesn’t know what to do. Is there a way to do something like reduce(vcat,x) as a pre-step between the registered call and the solve call?
Something like solve(prob…) → call intermediate registered → reduce(vcat,x) → registered(::symbolic_vector,Num)->performs whatever registered does to then work

We fixed that in the registration like a week ago?

Can you make a minimized example that deletes anything not needed?

Is that a new pull request to Symbolics.jl because I must admit I don’t think I’ve updated for a week.
Here is the minimum that works (breaks). I only had the spline as it was an easy error message to notice as it wouldn’t work unless it was a numeric vector.

using ModelingToolkit,  OrdinaryDiffEq
using ModelingToolkit: t_nounits as t, D_nounits as D

function model_eq(;name)
    @variables x(t)[1:10]

    eqs = [D(x) .~ x*pre_registered(x,t)]

    eqs = Symbolics.scalarize(reduce(vcat,Symbolics.scalarize.(eqs)))

    ODESystem(eqs,t;name)
end

function registered(x,t::Real)
    println(x) #will be a Symbolic rather than numeric
    y=collect(1.0:10.0)
    return 1.1 * t
end
@register_symbolic registered(x::Vector{Num},t::Real) 

function main()
    @named eq = model_eq()
    comp  =structural_simplify(eq)
    u0 = [Symbolics.scalarize(comp.x => collect(1.0:10.0))]
    prob=ODEProblem(comp,u0,(0.0,10.0))
    sol =solve(prob,Tsit5();reltol=1e-3,abstol=1e-3)
    return sol
end

sol = main()

It was feat: support passing arrays of symbolics to registered functions by AayushSabharwal · Pull Request #1197 · JuliaSymbolics/Symbolics.jl · GitHub

Maybe @cryptic.ax can look at this.

julia> @register_symbolic registered(x::AbstractVector,t)

This fixes the MWE (if you also call registered and not pre_registered in your equations)

Thank you very much. Sorry about the pre-registered it was a carry over from me trying to build a wrapper around it

Hi, sorry to reawaken this thread but after updating to the newer version, the structural simplify seems to now work but there is a StackOverflow error with the following error stack trace

Stacktrace:
     [1] similar
       @ .\abstractarray.jl:839 [inlined]
     [2] _similar_for
       @ .\array.jl:717 [inlined]
     [3] _collect(c::Vector{…}, itr::Base.Generator{…}, ::Base.EltypeUnknown, isz::Base.HasShape{…})
       @ Base .\array.jl:859
     [4] collect_similar(cont::Vector{Any}, itr::Base.Generator{Vector{…}, Symbolics.var"#247#248"{…}})
       @ Base .\array.jl:763
     [5] map(f::Function, A::Vector{Any})
       @ Base .\abstractarray.jl:3285
     [6] fast_substitute(expr::SymbolicUtils.BasicSymbolic{Real}, subs::Dict{Any, Any}; operator::Type)
       @ Symbolics C:\Users\u5522838\.julia\packages\Symbolics\e7UFe\src\variable.jl:481
     [7] fast_substitute
       @ C:\Users\u5522838\.julia\packages\Symbolics\e7UFe\src\variable.jl:471 [inlined]
     [8] (::Symbolics.var"#247#248"{DataType, Dict{Any, Any}, Base.RefValue{Bool}})(x::SymbolicUtils.BasicSymbolic{Real})
       @ Symbolics C:\Users\u5522838\.julia\packages\Symbolics\e7UFe\src\variable.jl:482
     [9] iterate
       @ .\generator.jl:47 [inlined]
    [10] _collect(c::Vector{…}, itr::Base.Generator{…}, ::Base.EltypeUnknown, isz::Base.HasShape{…})
       @ Base .\array.jl:854
--- the last 7 lines are repeated 4460 more times ---
 [31231] collect_similar(cont::Vector{Any}, itr::Base.Generator{Vector{…}, Symbolics.var"#247#248"{…}})
       @ Base .\array.jl:763
 [31232] map(f::Function, A::Vector{Any})
       @ Base .\abstractarray.jl:3285
 [31233] fast_substitute(expr::SymbolicUtils.BasicSymbolic{Any}, subs::Dict{Any, Any}; operator::Type)
       @ Symbolics C:\Users\u5522838\.julia\packages\Symbolics\e7UFe\src\variable.jl:481
 [31234] fast_substitute
       @ C:\Users\u5522838\.julia\packages\Symbolics\e7UFe\src\variable.jl:471 [inlined]
 [31235] (::Symbolics.var"#247#248"{DataType, Dict{Any, Any}, Base.RefValue{Bool}})(x::SymbolicUtils.BasicSymbolic{Any})
       @ Symbolics C:\Users\u5522838\.julia\packages\Symbolics\e7UFe\src\variable.jl:482
 [31236] iterate
       @ .\generator.jl:47 [inlined]
 [31237] collect_to!(dest::Vector{Any}, itr::Base.Generator{Vector{…}, Symbolics.var"#247#248"{…}}, offs::Int64, st::Int64)
       @ Base .\array.jl:892
 [31238] collect_to!(dest::Vector{typeof(/)}, itr::Base.Generator{Vector{…}, Symbolics.var"#247#248"{…}}, offs::Int64, st::Int64)
       @ Base .\array.jl:900
 [31239] collect_to_with_first!(dest::Vector{…}, v1::Function, itr::Base.Generator{…}, st::Int64)
       @ Base .\array.jl:870
 [31240] _collect(c::Vector{…}, itr::Base.Generator{…}, ::Base.EltypeUnknown, isz::Base.HasShape{…})
       @ Base .\array.jl:864
 [31241] collect_similar(cont::Vector{Any}, itr::Base.Generator{Vector{…}, Symbolics.var"#247#248"{…}})
       @ Base .\array.jl:763
 [31242] map(f::Function, A::Vector{Any})
       @ Base .\abstractarray.jl:3285
 [31243] fast_substitute(expr::Symbolics.ArrayOp{Vector{Real}}, subs::Dict{Any, Any}; operator::Type)
       @ Symbolics C:\Users\u5522838\.julia\packages\Symbolics\e7UFe\src\variable.jl:481
 [31244] fast_substitute
       @ C:\Users\u5522838\.julia\packages\Symbolics\e7UFe\src\variable.jl:471 [inlined]
 [31245] (::Symbolics.var"#247#248"{DataType, Dict{Any, Any}, Base.RefValue{Bool}})(x::Symbolics.ArrayOp{Vector{Real}})
       @ Symbolics C:\Users\u5522838\.julia\packages\Symbolics\e7UFe\src\variable.jl:482
 [31246] iterate
       @ .\generator.jl:47 [inlined]
 [31247] collect_to!(dest::Vector{…}, itr::Base.Generator{…}, offs::Int64, st::Int64)
       @ Base .\array.jl:892
--- the last 9 lines are repeated 2 more times ---
 [31266] collect_to!(dest::Vector{typeof(/)}, itr::Base.Generator{Vector{…}, Symbolics.var"#247#248"{…}}, offs::Int64, st::Int64)
       @ Base .\array.jl:900
 [31267] collect_to_with_first!(dest::Vector{…}, v1::Function, itr::Base.Generator{…}, st::Int64)
       @ Base .\array.jl:870
 [31268] _collect(c::Vector{…}, itr::Base.Generator{…}, ::Base.EltypeUnknown, isz::Base.HasShape{…})
       @ Base .\array.jl:864
 [31269] collect_similar(cont::Vector{Any}, itr::Base.Generator{Vector{…}, Symbolics.var"#247#248"{…}})
       @ Base .\array.jl:763
 [31270] map(f::Function, A::Vector{Any})
       @ Base .\abstractarray.jl:3285
 [31271] fast_substitute(expr::Symbolics.ArrayOp{Vector{Real}}, subs::Dict{Any, Any}; operator::Type)
       @ Symbolics C:\Users\u5522838\.julia\packages\Symbolics\e7UFe\src\variable.jl:481
 [31272] fast_substitute
       @ C:\Users\u5522838\.julia\packages\Symbolics\e7UFe\src\variable.jl:471 [inlined]
 [31273] (::Symbolics.var"#247#248"{DataType, Dict{Any, Any}, Base.RefValue{Bool}})(x::Symbolics.ArrayOp{Vector{Real}})
       @ Symbolics C:\Users\u5522838\.julia\packages\Symbolics\e7UFe\src\variable.jl:482
 [31274] iterate
       @ .\generator.jl:47 [inlined]
 [31275] collect_to!(dest::Vector{…}, itr::Base.Generator{…}, offs::Int64, st::Int64)
       @ Base .\array.jl:892
 [31276] collect_to_with_first!(dest::Vector{…}, v1::SymbolicUtils.BasicSymbolic{…}, itr::Base.Generator{…}, st::Int64)
       @ Base .\array.jl:870
 [31277] _collect(c::Vector{…}, itr::Base.Generator{…}, ::Base.EltypeUnknown, isz::Base.HasShape{…})
       @ Base .\array.jl:864
 [31278] collect_similar(cont::Vector{Any}, itr::Base.Generator{Vector{…}, Symbolics.var"#247#248"{…}})
       @ Base .\array.jl:763
 [31279] map(f::Function, A::Vector{Any})
       @ Base .\abstractarray.jl:3285
 [31280] fast_substitute(expr::SymbolicUtils.BasicSymbolic{Vector{Real}}, subs::Dict{Any, Any}; operator::Type)
       @ Symbolics C:\Users\u5522838\.julia\packages\Symbolics\e7UFe\src\variable.jl:481
 [31281] fast_substitute
       @ C:\Users\u5522838\.julia\packages\Symbolics\e7UFe\src\variable.jl:471 [inlined]
 [31282] (::Symbolics.var"#247#248"{DataType, Dict{Any, Any}, Base.RefValue{Bool}})(x::SymbolicUtils.BasicSymbolic{Vector{Real}})
       @ Symbolics C:\Users\u5522838\.julia\packages\Symbolics\e7UFe\src\variable.jl:482
 [31283] iterate
       @ .\generator.jl:47 [inlined]
 [31284] _collect(c::Vector{…}, itr::Base.Generator{…}, ::Base.EltypeUnknown, isz::Base.HasShape{…})
       @ Base .\array.jl:854
--- the last 16 lines are repeated 1 more time ---
 [31301] collect_similar(cont::Vector{Any}, itr::Base.Generator{Vector{…}, Symbolics.var"#247#248"{…}})
       @ Base .\array.jl:763
 [31302] map(f::Function, A::Vector{Any})
       @ Base .\abstractarray.jl:3285
 [31303] fast_substitute(expr::SymbolicUtils.BasicSymbolic{Real}, subs::Dict{Any, Any}; operator::Type)
       @ Symbolics C:\Users\u5522838\.julia\packages\Symbolics\e7UFe\src\variable.jl:481
 [31304] fixpoint_sub(x::SymbolicUtils.BasicSymbolic{Real}, dict::Dict{Any, Any}; operator::Type)
       @ Symbolics C:\Users\u5522838\.julia\packages\Symbolics\e7UFe\src\variable.jl:430
 [31305] tearing_reassemble(state::TearingState{…}, var_eq_matching::ModelingToolkit.BipartiteGraphs.Matching{…}, full_var_eq_matching::Nothing; simplify::Bool, mm::ModelingToolkit.SparseMatrixCLIL{…})        
       @ ModelingToolkit.StructuralTransformations C:\Users\u5522838\.julia\packages\ModelingToolkit\K6okj\src\structural_transformation\symbolics_tearing.jl:487
 [31306] tearing_reassemble (repeats 2 times)
       @ C:\Users\u5522838\.julia\packages\ModelingToolkit\K6okj\src\structural_transformation\symbolics_tearing.jl:229 [inlined]
 [31307] #dummy_derivative#131
       @ C:\Users\u5522838\.julia\packages\ModelingToolkit\K6okj\src\structural_transformation\symbolics_tearing.jl:684 [inlined]
 [31308] _structural_simplify!(state::TearingState{…}, io::Nothing; simplify::Bool, check_consistency::Bool, fully_determined::Bool, warn_initialize_determined::Bool, dummy_derivative::Bool, kwargs::@Kwargs{…})
       @ ModelingToolkit C:\Users\u5522838\.julia\packages\ModelingToolkit\K6okj\src\systems\systemstructure.jl:695
 [31309] _structural_simplify!
       @ C:\Users\u5522838\.julia\packages\ModelingToolkit\K6okj\src\systems\systemstructure.jl:675 [inlined]
 [31310] structural_simplify!(state::TearingState{…}, io::Nothing; simplify::Bool, check_consistency::Bool, fully_determined::Bool, warn_initialize_determined::Bool, kwargs::@Kwargs{…})
       @ ModelingToolkit C:\Users\u5522838\.julia\packages\ModelingToolkit\K6okj\src\systems\systemstructure.jl:635
 [31311] __structural_simplify(sys::ODESystem, io::Nothing; simplify::Bool, kwargs::@Kwargs{…})
       @ ModelingToolkit C:\Users\u5522838\.julia\packages\ModelingToolkit\K6okj\src\systems\systems.jl:85
 [31312] __structural_simplify
       @ C:\Users\u5522838\.julia\packages\ModelingToolkit\K6okj\src\systems\systems.jl:66 [inlined]
 [31313] structural_simplify(sys::ODESystem, io::Nothing; simplify::Bool, split::Bool, allow_symbolic::Bool, allow_parameter::Bool, conservative::Bool, fully_determined::Bool, kwargs::@Kwargs{})
       @ ModelingToolkit C:\Users\u5522838\.julia\packages\ModelingToolkit\K6okj\src\systems\systems.jl:24
 [31314] structural_simplify
       @ C:\Users\u5522838\.julia\packages\ModelingToolkit\K6okj\src\systems\systems.jl:20 [inlined]
Some type information was truncated. Use `show(err)` to see complete types.

This is only for my real code and not the MWE. I can attach a zip of the real code as it is hard to create an MWE of this and it is a multi file program using includes. I’m not sure if this is an issue you are aware of with the recent updates as I haven’t seen anything on the github

Not aware of what could cause that. Would need a reproducer.

When I get a minute I shall try to compile a single workflow file that performs the necessary functions if that is workable

Here is a single script that does everything and reproduces the stack overflow. It is 200 lines long but I couldn’t get it shorter
SingleScriptforStackOverflow.jl (11.4 KB)

Please open an issue with the reproducer and the error message, and ping me on it.