MethodError: no method matching setindex! when using DifferentialEquations.jl

MethodError: no method matching setindex! when using DifferentialEquations.jl

我正在尝试使用 julia 中的 DifferentialEquations 包模拟具有非对角噪声的多维 SDE。 漂移函数具有以下形式:

function mu(dx, x, param, t)
    dx[1] = -param[1]*x[1]*x[2]-param[1]*(x[3]+x[4])*x[1]
    dx[2] = param[1]*x[1]*x[2]-param[3]*x[2]
    dx[3] = param[1]*x[1]*(x[3]+x[4])-param[4]*x[3]
    dx[4] = param[2]*x[5]*(x[3]+x[4])-param[4]*x[4]
    dx[5] = -param[2]*x[5]*(x[3]+x[4])+param[3]*x[2]
    dx[6] = param[4]*(x[3]+x[4])
end

扩散矩阵由下式给出:

function sigma(dx, x, p, t)
    beta = p[1]
    kappa = p[2]
    gamma = p[3]
    zeta = p[4]

    dx[1][1] = -sqrt(beta*x[1]*x[2]/100)
    dx[1][2] = -sqrt(beta*x[1]*(x[3]+x[4])/100)
    dx[2][1] = sqrt(beta*x[1]*x[2]/100)
    dx[2][3] = -sqrt(gamma*x[2]/100)
    dx[3][2] = sqrt(beta*x[1]*(x[3]+x[4])/100)
    dx[3][6] = -sqrt(zeta*x[3]/100)
    dx[4][4] = sqrt(kappa*x[5]*(x[3]+x[4])/100)
    dx[4][5] = -sqrt(zeta*x[4]/100)
    dx[5][4] = sqrt(gamma*x[2]/100)
    dx[5][4] = -sqrt(kappa*x[5]*(x[3]+x[4])/100)
    dx[6][5] = sqrt(zeta*x[4]/100)
    dx[6][6] = sqrt(zeta*x[3]/100)
end

使用以下代码模拟漂移函数指定的 ODE 效果很好。

u0 = [0.96; 0.03; 0.01; 0.0; 0.0; 0.0]
tspan = (0.0, 300.0)
p = [0.08; 0.06; 0.04; 0.02]


problem_ODE = ODEProblem(mu, u0, tspan, p)

solution_ODE = solve(problem_ODE, saveat=0.1)

但是当我想解决SDE时:

u0 = [0.96; 0.03; 0.01; 0.0; 0.0; 0.0]
tspan = (0.0, 300.0)
p = [0.08; 0.06; 0.04; 0.02]


problem = SDEProblem(mu, sigma, u0, tspan, p, noise_rate_prototype=zeros(6,6))

solution = solve(problem, EM(), dt=0.01, adaptive=false)

它不起作用并给出以下错误和 Stacktrace:

MethodError: no method matching setindex!(::Float64, ::Float64, ::Int64)

Stacktrace:
  [1] sigma(dx::Matrix{Float64}, x::Vector{Float64}, p::Vector{Float64}, t::Float64)
    @ Main ~/masterthesis/two_variant_model/own_simulation/final_simulation.ipynb:7
  [2] perform_step!(integrator::StochasticDiffEq.SDEIntegrator{EM{true}, true, Vector{Float64}, Float64, Float64, Float64, Vector{Float64}, Float64, Float64, Float64, NoiseProcess{Float64, 2, Float64, Vector{Float64}, Nothing, Nothing, typeof(DiffEqNoiseProcess.INPLACE_WHITE_NOISE_DIST), typeof(DiffEqNoiseProcess.INPLACE_WHITE_NOISE_BRIDGE), true, ResettableStacks.ResettableStack{Tuple{Float64, Vector{Float64}, Nothing}, true}, ResettableStacks.ResettableStack{Tuple{Float64, Vector{Float64}, Nothing}, true}, RSWM{Float64}, Nothing, RandomNumbers.Xorshifts.Xoroshiro128Plus}, Nothing, Vector{Float64}, RODESolution{Float64, 2, Vector{Vector{Float64}}, Nothing, Nothing, Vector{Float64}, NoiseProcess{Float64, 2, Float64, Vector{Float64}, Nothing, Nothing, typeof(DiffEqNoiseProcess.INPLACE_WHITE_NOISE_DIST), typeof(DiffEqNoiseProcess.INPLACE_WHITE_NOISE_BRIDGE), true, ResettableStacks.ResettableStack{Tuple{Float64, Vector{Float64}, Nothing}, true}, ResettableStacks.ResettableStack{Tuple{Float64, Vector{Float64}, Nothing}, true}, RSWM{Float64}, Nothing, RandomNumbers.Xorshifts.Xoroshiro128Plus}, SDEProblem{Vector{Float64}, Tuple{Float64, Float64}, true, Vector{Float64}, Nothing, SDEFunction{true, typeof(mu), typeof(sigma), LinearAlgebra.UniformScaling{Bool}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED), Nothing}, typeof(sigma), Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}, Matrix{Float64}}, EM{true}, StochasticDiffEq.LinearInterpolationData{Vector{Vector{Float64}}, Vector{Float64}}, DiffEqBase.DEStats}, StochasticDiffEq.EMCache{Vector{Float64}, Vector{Float64}, Matrix{Float64}}, SDEFunction{true, typeof(mu), typeof(sigma), LinearAlgebra.UniformScaling{Bool}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED), Nothing}, typeof(sigma), Nothing, StochasticDiffEq.SDEOptions{Float64, Float64, PIController{Float64}, typeof(DiffEqBase.ODE_DEFAULT_NORM), Nothing, CallbackSet{Tuple{}, Tuple{}}, typeof(DiffEqBase.ODE_DEFAULT_ISOUTOFDOMAIN), typeof(DiffEqBase.ODE_DEFAULT_PROG_MESSAGE), typeof(DiffEqBase.ODE_DEFAULT_UNSTABLE_CHECK), DataStructures.BinaryHeap{Float64, DataStructures.FasterForward}, DataStructures.BinaryHeap{Float64, DataStructures.FasterForward}, Nothing, Nothing, Int64, Float64, Float64, Float64, Tuple{}, Tuple{}, Tuple{}}, Nothing, Float64, Nothing, Nothing}, cache::StochasticDiffEq.EMCache{Vector{Float64}, Vector{Float64}, Matrix{Float64}})
    @ StochasticDiffEq ~/.julia/packages/StochasticDiffEq/Wl3hr/src/perform_step/low_order.jl:40
  [3] solve!(integrator::StochasticDiffEq.SDEIntegrator{EM{true}, true, Vector{Float64}, Float64, Float64, Float64, Vector{Float64}, Float64, Float64, Float64, NoiseProcess{Float64, 2, Float64, Vector{Float64}, Nothing, Nothing, typeof(DiffEqNoiseProcess.INPLACE_WHITE_NOISE_DIST), typeof(DiffEqNoiseProcess.INPLACE_WHITE_NOISE_BRIDGE), true, ResettableStacks.ResettableStack{Tuple{Float64, Vector{Float64}, Nothing}, true}, ResettableStacks.ResettableStack{Tuple{Float64, Vector{Float64}, Nothing}, true}, RSWM{Float64}, Nothing, RandomNumbers.Xorshifts.Xoroshiro128Plus}, Nothing, Vector{Float64}, RODESolution{Float64, 2, Vector{Vector{Float64}}, Nothing, Nothing, Vector{Float64}, NoiseProcess{Float64, 2, Float64, Vector{Float64}, Nothing, Nothing, typeof(DiffEqNoiseProcess.INPLACE_WHITE_NOISE_DIST), typeof(DiffEqNoiseProcess.INPLACE_WHITE_NOISE_BRIDGE), true, ResettableStacks.ResettableStack{Tuple{Float64, Vector{Float64}, Nothing}, true}, ResettableStacks.ResettableStack{Tuple{Float64, Vector{Float64}, Nothing}, true}, RSWM{Float64}, Nothing, RandomNumbers.Xorshifts.Xoroshiro128Plus}, SDEProblem{Vector{Float64}, Tuple{Float64, Float64}, true, Vector{Float64}, Nothing, SDEFunction{true, typeof(mu), typeof(sigma), LinearAlgebra.UniformScaling{Bool}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED), Nothing}, typeof(sigma), Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}, Matrix{Float64}}, EM{true}, StochasticDiffEq.LinearInterpolationData{Vector{Vector{Float64}}, Vector{Float64}}, DiffEqBase.DEStats}, StochasticDiffEq.EMCache{Vector{Float64}, Vector{Float64}, Matrix{Float64}}, SDEFunction{true, typeof(mu), typeof(sigma), LinearAlgebra.UniformScaling{Bool}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED), Nothing}, typeof(sigma), Nothing, StochasticDiffEq.SDEOptions{Float64, Float64, PIController{Float64}, typeof(DiffEqBase.ODE_DEFAULT_NORM), Nothing, CallbackSet{Tuple{}, Tuple{}}, typeof(DiffEqBase.ODE_DEFAULT_ISOUTOFDOMAIN), typeof(DiffEqBase.ODE_DEFAULT_PROG_MESSAGE), typeof(DiffEqBase.ODE_DEFAULT_UNSTABLE_CHECK), DataStructures.BinaryHeap{Float64, DataStructures.FasterForward}, DataStructures.BinaryHeap{Float64, DataStructures.FasterForward}, Nothing, Nothing, Int64, Float64, Float64, Float64, Tuple{}, Tuple{}, Tuple{}}, Nothing, Float64, Nothing, Nothing})
    @ StochasticDiffEq ~/.julia/packages/StochasticDiffEq/Wl3hr/src/solve.jl:611
  [4] #__solve#100
    @ ~/.julia/packages/StochasticDiffEq/Wl3hr/src/solve.jl:7 [inlined]
  [5] #solve_call#39
    @ ~/.julia/packages/DiffEqBase/U3LtB/src/solve.jl:155 [inlined]
  [6] #solve_up#41
    @ ~/.julia/packages/DiffEqBase/U3LtB/src/solve.jl:182 [inlined]
  [7] #solve#40
    @ ~/.julia/packages/DiffEqBase/U3LtB/src/solve.jl:168 [inlined]
  [8] top-level scope
    @ ~/masterthesis/two_variant_model/own_simulation/final_simulation.ipynb:1
  [9] eval
    @ ./boot.jl:360 [inlined]
 [10] include_string(mapexpr::typeof(REPL.softscope), mod::Module, code::String, filename::String)
    @ Base ./loading.jl:1116
 [11] #invokelatest#2
    @ ./essentials.jl:708 [inlined]
 [12] invokelatest
    @ ./essentials.jl:706 [inlined]
 [13] (::VSCodeServer.var"#160#161"{VSCodeServer.NotebookRunCellArguments, String})()
    @ VSCodeServer ~/.vscode-server/extensions/julialang.language-julia-1.6.17/scripts/packages/VSCodeServer/src/serve_notebook.jl:19
 [14] withpath(f::VSCodeServer.var"#160#161"{VSCodeServer.NotebookRunCellArguments, String}, path::String)
    @ VSCodeServer ~/.vscode-server/extensions/julialang.language-julia-1.6.17/scripts/packages/VSCodeServer/src/repl.jl:184
 [15] notebook_runcell_request(conn::VSCodeServer.JSONRPC.JSONRPCEndpoint{Base.PipeEndpoint, Base.PipeEndpoint}, params::VSCodeServer.NotebookRunCellArguments)
    @ VSCodeServer ~/.vscode-server/extensions/julialang.language-julia-1.6.17/scripts/packages/VSCodeServer/src/serve_notebook.jl:13
 [16] dispatch_msg(x::VSCodeServer.JSONRPC.JSONRPCEndpoint{Base.PipeEndpoint, Base.PipeEndpoint}, dispatcher::VSCodeServer.JSONRPC.MsgDispatcher, msg::Dict{String, Any})
    @ VSCodeServer.JSONRPC ~/.vscode-server/extensions/julialang.language-julia-1.6.17/scripts/packages/JSONRPC/src/typed.jl:67
 [17] serve_notebook(pipename::String, outputchannel_logger::Base.CoreLogging.SimpleLogger; crashreporting_pipename::String)
    @ VSCodeServer ~/.vscode-server/extensions/julialang.language-julia-1.6.17/scripts/packages/VSCodeServer/src/serve_notebook.jl:136
 [18] top-level scope
    @ ~/.vscode-server/extensions/julialang.language-julia-1.6.17/scripts/notebook/notebook.jl:32
 [19] include(mod::Module, _path::String)
    @ Base ./Base.jl:384
 [20] exec_options(opts::Base.JLOptions)
    @ Base ./client.jl:285
 [21] _start()
    @ Base ./client.jl:485

由于这是我第一次使用 julia,如果能知道如何解决该问题并模拟 SDE,我将不胜感激。

另一个问题是,是否有人知道是否有办法告诉积分算法模拟过程(SDE 的解)应保持正值。我唯一的想法是使用集成器界面逐步执行集成并在每一步后检查它,但也许有人知道是否有内置解决方案。

但第一个问题更为重要。

提前致谢。

我得到了我的问题的答案,这只是我恼火地不知道在 julia 和 python 中访问矩阵中元素的不同语法。 将扩散函数更改为:

function sigma(dx, x, p, t)
    beta = p[1]
    kappa = p[2]
    gamma = p[3]
    zeta = p[4]

    dx[1, 1] = -sqrt(beta*x[1]*x[2]/100)
    dx[1, 2] = -sqrt(beta*x[1]*(x[3]+x[4])/100)
    dx[2, 1] = sqrt(beta*x[1]*x[2]/100)
    dx[2, 3] = -sqrt(gamma*x[2]/100)
    dx[3, 2] = sqrt(beta*x[1]*(x[3]+x[4])/100)
    dx[3, 6] = -sqrt(zeta*x[3]/100)
    dx[4, 4] = sqrt(kappa*x[5]*(x[3]+x[4])/100)
    dx[4, 5] = -sqrt(zeta*x[4]/100)
    dx[5, 4] = sqrt(gamma*x[2]/100)
    dx[5, 4] = -sqrt(kappa*x[5]*(x[3]+x[4])/100)
    dx[6, 5] = sqrt(zeta*x[4]/100)
    dx[6, 6] = sqrt(zeta*x[3]/100)
end

解决了问题。

但是第二个问题变得更加重要,因为我现在遇到域错误,当出现一些负值时。 通过在每个步骤后使用集成器接口进行检查也解决了这个问题。 有一个 built-in isoutofdomain 选项,或者可以使用 callback-function PositiveDomain,但这只是确保 non-negativity 达到设定的容差,这仍然会产生域错误。