我正在尝试为由方程组控制的优化系统找到多个参数。
在我的代码中,我需要能够使用 4 或 5 个方程并确定优化系统的参数。为了简单起见,我将代码简化为 3 个方程组(但实际上是 5 个方程),如下所示:
function f1(du, u, p, t)
x, y = u
α, β, δ, γ = p
du[1] = dx = α * x - β * x * y
du[2] = dy = -δ * y + γ *x * y
du[3] = dz = α*x
end
u0 = [1.0; 1.0; 1.0]
tspan = (0.0, 10.0)
p = [1.5, 1.0, 3.0, 1.0]
prob = ODEProblem(f1, u0, tspan, p)
t = collect(range(0, stop = 10, length = 200)) # Creates the time vector
data = Array(solve(prob, Tsit5(), saveat = t, abstol = 1e-12, reltol = 1e-12))
bound = Tuple{Float64, Float64}[(0, 10), (0, 10), (0, 10), (0, 10),
(0, 10), (0, 10), (0, 10), (0, 10),
(0, 10), (0, 10), (0, 10), (0, 10),
(0, 10), (0, 10), (0, 10), (0, 10), (0, 10), (0, 10)]
obj = multiple_shooting_objective(prob, Tsit5(), L2Loss(t, data),Optimization.AutoForwardDiff(); discontinuity_weight = 1.0, abstol = 1e-12, reltol = 1e-12)
optprob = Optimization.OptimizationProblem(obj, zeros(18), lb = first.(bound), ub = last.(bound))
optsol = solve(optprob, BBO_adaptive_de_rand_1_bin_radiuslimited(), maxiters = 10000)
Optimised_parameters = optsol.u[(end - 1):end]
println("Optimised parameters: ")
println("p₁: ", Optimised_parameters[1])
println("p₂: ", Optimised_parameters[2])
println(" ")
但是,我收到错误消息:
ERROR: InexactError: Int64(4.666666666666667)
“OptSol”系列。 这表明某个地方正在接收一个整数,但需要一个浮点数。我不知道如何解决这个问题,以便我可以扩展系统以包含更多方程。 任何帮助将不胜感激!
为了提供帮助,这里有一个工作示例(少了一个 du 术语。我试图允许更多的 du 术语):
using DifferentialEquations, RecursiveArrayTools, Plots, DiffEqParamEstim
using Optimization, ForwardDiff, OptimizationOptimJL, OptimizationBBO
function f1(du, u, p, t)
x, y = u
α, β, δ, γ = p
du[1] = dx = α * x - β * x * y
du[2] = dy = -δ * y + γ *x * y
end
u0 = [1.0; 1.0]
tspan = (0.0, 10.0)
p = [1.5, 1.0, 3.0, 1.0]
prob = ODEProblem(f1, u0, tspan, p)
t = collect(range(0, stop = 10, length = 200)) # Creates the time vector
data = Array(solve(prob, Tsit5(), saveat = t, abstol = 1e-12, reltol = 1e-12))
bound = Tuple{Float64, Float64}[(0, 10), (0, 10), (0, 10), (0, 10),
(0, 10), (0, 10), (0, 10), (0, 10),
(0, 10), (0, 10), (0, 10), (0, 10),
(0, 10), (0, 10), (0, 10), (0, 10), (0, 10), (0, 10)]
obj = multiple_shooting_objective(prob, Tsit5(), L2Loss(t, data),Optimization.AutoForwardDiff(); discontinuity_weight = 1.0, abstol = 1e-12, reltol = 1e-12)
optprob = Optimization.OptimizationProblem(obj, zeros(18), lb = first.(bound), ub = last.(bound))
optsol = solve(optprob, BBO_adaptive_de_rand_1_bin_radiuslimited(), maxiters = 10000)
Optimised_parameters = optsol.u[(end - 1):end]
println("Optimised parameters: ")
println("p₁: ", Optimised_parameters[1])
println("p₂: ", Optimised_parameters[2])
println(" ")
可重复。 以下是调试会话中的一些信息,可能有助于某人解释如何纠正问题。
在 Julia 1.10.7 上(对于 Debugger.jl):
using Pkg
Pkg.add("Optimization"); import Optimization: Optimization, ODEProblem, solve
Pkg.add("OptimizationBBO"); import OptimizationBBO: BBO_adaptive_de_rand_1_bin_radiuslimited
Pkg.add("OrdinaryDiffEq"); import OrdinaryDiffEq: Tsit5
Pkg.add("DiffEqParamEstim"); import DiffEqParamEstim: L2Loss, multiple_shooting_objective
function f1(du, u, p, t)
x, y = u
α, β, δ, γ = p
du[1] = dx = α * x - β * x * y
du[2] = dy = -δ * y + γ *x * y
du[3] = dz = α*x
end
u0 = [1.0; 1.0; 1.0]
tspan = (0.0, 10.0)
p = [1.5, 1.0, 3.0, 1.0]
prob = ODEProblem(f1, u0, tspan, p)
t = collect(range(0, stop = 10, length = 200)) # Creates the time vector
data = Array(solve(prob, Tsit5(), saveat = t, abstol = 1e-12, reltol = 1e-12))
bound = Tuple{Float64, Float64}[(0, 10), (0, 10), (0, 10), (0, 10),
(0, 10), (0, 10), (0, 10), (0, 10),
(0, 10), (0, 10), (0, 10), (0, 10),
(0, 10), (0, 10), (0, 10), (0, 10), (0, 10), (0, 10)]
obj = multiple_shooting_objective(prob, Tsit5(), L2Loss(t, data), Optimization.AutoForwardDiff(); discontinuity_weight = 1.0, abstol = 1e-12, reltol = 1e-12)
optprob = Optimization.OptimizationProblem(obj, zeros(18), lb = first.(bound), ub = last.(bound))
Pkg.add("Debugger"); using Debugger; break_on(:error)
@run optsol = solve(optprob, BBO_adaptive_de_rand_1_bin_radiuslimited(), maxiters = 10000)
产品
Breaking for error:
ERROR: InexactError: Int64(4.666666666666667)
Stacktrace:
[1] Int64(x::Float64)
@ Base float.jl:912
[2] (::DiffEqParamEstim.var"#43#48"{Nothing, Float64, DiffEqParamEstim.var"#1#2", @Kwargs{abstol::Float64, reltol::Float64}, ODEProblem{Vector{Float64}, Tuple{Float64, Float64}, true, Vector{Float64}, SciMLBase.ODEFunction{true, SciMLBase.AutoSpecialize, typeof(f1), LinearAlgebra.UniformScaling{Bool}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED), Nothing, Nothing, Nothing, Nothing}, @Kwargs{}, SciMLBase.StandardODEProblem}, Tsit5{typeof(OrdinaryDiffEqCore.trivial_limiter!), typeof(OrdinaryDiffEqCore.trivial_limiter!), Static.False}, L2Loss{Vector{Float64}, Matrix{Float64}, Nothing, Nothing, Nothing}, Nothing})(p::Vector{Float64}, ::SciMLBase.NullParameters)
...
In Int64(x) at float.jl:908
908 function (::Type{$Ti})(x::$Tf)
909 if ($(Tf(typemin(Ti))) <= x < $(Tf(typemax(Ti)))) && isinteger(x)
910 return unsafe_trunc($Ti,x)
911 else
>912 throw(InexactError($(Expr(:quote,Ti.name.name)), $Ti, x))
913 end
914 end
915 end
916 end
About to run: throw(InexactError(:Int64, Int64, 4.666666666666667))
在调试器命令提示符处,将
up
移动到下一帧:
1|debug> up
In #43(p, #unused#) at ~/.julia/packages/DiffEqParamEstim/6z5Ou/src/multiple_shooting_objective.jl:30
29 kwargs...)
30 cost_function = function (p, _ = nothing)
31 t0, tf = prob.tspan
32 P, N = length(prob.p), length(prob.u0)
>33 K = Int((length(p) - P) / N)
34 τ = range(t0, tf, length = K + 1)
35 sol = []
36 loss_val = 0
37 for k in 1:K
About to run: (Int64)(4.666666666666667)
堆栈
fr
名称:
2|debug> fr
[2] #43(p, #unused#) at ~/.julia/packages/DiffEqParamEstim/6z5Ou/src/multiple_shooting_objective.jl:30
| p::Vector{Float64} = <[3.843240561664537, 8.092526443524417, 0.6805655220003193, 4.4963371509026695, 7.785492340246389, 3.6...>
| ::Int64 = 2
| N::Int64 = 3
| P::Int64 = 4
...
评估
w
atch 表达式:
2|debug> w add length(p)
1] length(p): 18
2|debug> q
当N=3,P=4,长度(p)=18,因此(长度(p)-P)/N = 4.666666666666667
这表明 (length(p) - P) 必须是 N 的倍数。(以前的版本在这里使用了
floor
。)
由于与工作版本(以及文档示例)相比,上面的代码添加了变量 u[3],因此 N 增加。 这表明必须增加 18。
18从哪里来? 我找到的唯一解释是“为什么长18(元组)?” “这是参数绑定。前两个是真正的参数,其余的是拐点。然后你必须忽略输出中的那些。” (从这里,评论指出 DiffEqFlux.jl 有一个替代方案。)
将18增加到19后运行。
optprob = Optimization.OptimizationProblem(obj, zeros(19), lb = zeros(19), ub = 10 .* ones(19))
optsol = solve(optprob, BBO_adaptive_de_rand_1_bin_radiuslimited(), maxiters = 10000)
# retcode: MaxIters
# u: 19-element Vector{Float64} ...