Use ModelingToolkit.jl to build ODEproblem and Optimization respectively to optimize the parameters of ODEproblem with the following code:
using ModelingToolkit, Optimization, ComponentArrays
using ModelingToolkit: t_nounits as t, D_nounits as D
using OrdinaryDiffEq
using OptimizationOptimisers
@mtkmodel FOL begin
@parameters begin
a
b # parameters
end
@variables begin
x(t) # dependent variables
end
@equations begin
D(x) ~ (1 - x) / a + b
end
end
@mtkbuild fol = FOL()
prob = ODEProblem(fol, [fol.x => 0.0], (1.0, 10.0), [fol.a => 3.0, fol.b => 4.0])
sol = OrdinaryDiffEq.solve(prob, Tsit5(), saveat=1.0)
@variables begin
vs[1:2] = [3.0, 4.0] # , [bounds = (-2.0, 2.0)]
end
x_axes = getaxes(ComponentVector(a=1, b=2))
@parameters st=0.0
v1 = 1:10
target = @.((v1 - (v1^2)/2)/3.0+4.0*v1)
loss = begin
params = ComponentVector(vs, x_axes)
new_prob = remake(prob, u0=[fol.x => st], p=[fol.a => params[:a], fol.b => params[:b]])
sol = OrdinaryDiffEq.solve(new_prob, Tsit5(), saveat=1.0)
sol_u = [v[1] for v in sol.u]
sum(abs.(target .- sol_u))
end
@mtkbuild sys = OptimizationSystem(loss, vs, [st]) # , constraints=cons
u0 = [vs[1] => 3.0
vs[2] => 4.0]
prob = OptimizationProblem(sys,
u0,
grad=true,
hess=true,
cons_j=true,
cons_h=true)
solve(prob, OptimizationOptimisers.Adam(), maxiters=10)
Then the code gets this error
ERROR: MethodError: promote_rule(::Type{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Num}, Num, 1}}, ::Type{Num}) is ambiguous.
Candidates:
promote_rule(::Type{ForwardDiff.Dual{T, V, N}}, ::Type{R}) where {T, V, N, R<:Real}
@ ForwardDiff D:\software\Julia-1.10.0\pkg\packages\ForwardDiff\PcZ48\src\dual.jl:428
promote_rule(::Type{<:Number}, ::Type{<:Num})
@ Symbolics D:\software\Julia-1.10.0\pkg\packages\Symbolics\Eas9m\src\num.jl:97
Possible fix, define
promote_rule(::Type{ForwardDiff.Dual{T, V, N}}, ::Type{R}) where {T, V, N, R<:Num}
Stacktrace:
[1] promote_type(::Type{Num}, ::Type{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Num}, Num, 1}})
@ Base .\promotion.jl:313
[2] promote_eltype(::Type{Vector{Num}}, ::Type{ForwardDiff.Dual{ForwardDiff.Tag{…}, Num, 1}})
@ ArrayInterface D:\software\Julia-1.10.0\pkg\packages\ArrayInterface\NIzGA\src\ArrayInterface.jl:114
[3] wrapfun_iip(ff::Function, inputs::Tuple{Vector{…}, Vector{…}, ModelingToolkit.MTKParameters{…}, Float64})
@ DiffEqBase D:\software\Julia-1.10.0\pkg\packages\DiffEqBase\NaUtB\src\norecompile.jl:59
[4] promote_f(f::ODEFunction{…}, ::Val{…}, u0::Vector{…}, p::ModelingToolkit.MTKParameters{…}, t::Float64)
@ DiffEqBase D:\software\Julia-1.10.0\pkg\packages\DiffEqBase\NaUtB\src\solve.jl:1260
[5] get_concrete_problem(prob::ODEProblem{…}, isadapt::Bool; kwargs::@Kwargs{…})
@ DiffEqBase D:\software\Julia-1.10.0\pkg\packages\DiffEqBase\NaUtB\src\solve.jl:1173
[6] solve_up(prob::ODEProblem{…}, sensealg::Nothing, u0::Vector{…}, p::ModelingToolkit.MTKParameters{…}, args::Tsit5{…}; kwargs::@Kwargs{…})
@ DiffEqBase D:\software\Julia-1.10.0\pkg\packages\DiffEqBase\NaUtB\src\solve.jl:1074
[7] solve(prob::ODEProblem{…}, args::Tsit5{…}; sensealg::Nothing, u0::Nothing, p::Nothing, wrap::Val{…}, kwargs::@Kwargs{…})
@ DiffEqBase D:\software\Julia-1.10.0\pkg\packages\DiffEqBase\NaUtB\src\solve.jl:1003
[8] top-level scope
@ f:\julia\DeepFlex.jl\test\pkgs\test_tmk_opt.jl:35
Some type information was truncated. Use `show(err)` to see complete types.
In addition varmap_to_vars to construct new parameters (the rest remains the same), see below:
loss = begin
params = ComponentVector(vs, x_axes)
# unew = [fol.x => st]
# pnew = [fol.a => params[:a], fol.b => params[:b]]
unew = ModelingToolkit.varmap_to_vars([fol.x => st], unknowns(fol))
pnew = ModelingToolkit.MTKParameters(sys, [fol.a => params[:a], fol.b => params[:b]], unew)
new_prob = remake(prob, u0=unew, p=pnew)
sol = OrdinaryDiffEq.solve(new_prob, Tsit5(), saveat=1.0)
sol_u = [v[1] for v in sol.u]
sum(abs.(target .- sol_u))
end
However, the following problems also arise:
ERROR: MethodError: no method matching AbstractFloat(::Type{SymbolicUtils.BasicSymbolic{Real}})
Closest candidates are:
AbstractFloat(::Bool)
@ Base float.jl:264
AbstractFloat(::UInt32)
@ Base float.jl:272
AbstractFloat(::UInt16)
@ Base float.jl:271
...
Stacktrace:
[1] float(x::Type)
@ Base .\float.jl:294
[2] promote_to_concrete(vs::Vector{SymbolicUtils.BasicSymbolic{Real}}; tofloat::Bool, use_union::Bool)
@ ModelingToolkit D:\software\Julia-1.10.0\pkg\packages\ModelingToolkit\kByuD\src\utils.jl:634
[3] varmap_to_vars(varmap::Vector{…}, varlist::Vector{…}; defaults::Dict{…}, check::Bool, toterm::Function, promotetoconcrete::Nothing, tofloat::Bool, use_union::Bool)
@ ModelingToolkit D:\software\Julia-1.10.0\pkg\packages\ModelingToolkit\kByuD\src\variables.jl:163
[4] varmap_to_vars(varmap::Vector{Pair{Num, Num}}, varlist::Vector{SymbolicUtils.BasicSymbolic{Real}})
@ ModelingToolkit D:\software\Julia-1.10.0\pkg\packages\ModelingToolkit\kByuD\src\variables.jl:125
[5] top-level scope
@ f:\julia\DeepFlex.jl\test\pkgs\test_tmk_opt.jl:37
Some type information was truncated. Use `show(err)` to see complete types.
Hopefully someone can solve my problem