Julia DifferentialEquations:在“手动”求解有效的情况下(转换错误),MonteCarloProblem解决失败

时间:2018-12-04 10:26:33

标签: julia differentialequations.jl

我正在做一个更大的项目,其中大量使用了MonteCarloProblem类型的DifferentialEquations.jl。通常,一切正常,但是遇到一个奇怪的案例,我无法真正理解,因为针对每个单个问题进行手动迭代都很好。

我在尝试一些可以使解决方案迅速发展到Infinity的系统时遇到了这个问题,并且我天真地使用了恒定的步长积分器,例如Euler,因此解决方案可以包含许多Inf。

一个小例子是众所周知的鞍节点分叉的2d范式,其中随机采样了参数和初始条件。因此,在这种情况下,我们将获得许多Inf。我知道这似乎并不特别有用,但这是我能想到的一个简单的最小示例。

using DifferentialEquations
using Distributions
using StatsBase

struct saddle_node_parameters
   mu 
end

function saddle_node(du,u,p::saddle_node_parameters,t)
   du[1] = p.mu - u[1]*u[1]
   du[2] = - u[2]
end

N = 50
ICs = rand(Uniform(-2,2),2,N)
pars = rand(Uniform(-1,1),N)
odep = ODEProblem(saddle_node, ICs[:,1], (0.,100.), saddle_node_parameters(0.5))
new_prob_func = (prob,i,repeat) -> ODEProblem(saddle_node, ICs[:,i],(0.,100.), saddle_node_parameters(pars[i]))
eval_func = (sol,i) -> (mean_and_std(sol[1,:]),false)
mcp = MonteCarloProblem(odep, prob_func=new_prob_func, output_func=eval_func)

使用默认算法(或自动算法检测)解决此问题是可行的(当然,当解决方案达到无穷大时,您会收到很多警告,但不会出现中断错误)。

用恒定步长的Euler解决它不起作用:

solve(mcp, alg=Euler(), dt=0.1, num_monte=N)

结果

MethodError: Cannot `convert` an object of type Nothing to an object of type Array{Array{Float64,1},1}

...

Stacktrace:
 [1] (::getfield(Base, Symbol("##683#685")))(::Task) at ./asyncmap.jl:178
 [2] foreach(::getfield(Base, Symbol("##683#685")), ::Array{Any,1}) at ./abstractarray.jl:1835
 [3] maptwice(::Function, ::Channel{Any}, ::Array{Any,1}, ::UnitRange{Int64}) at ./asyncmap.jl:178
 [4] #async_usemap#668 at ./asyncmap.jl:154 [inlined]
 [5] #async_usemap at ./none:0 [inlined]
 [6] #asyncmap#667 at ./asyncmap.jl:81 [inlined]
 [7] #asyncmap at ./none:0 [inlined]
 [8] #pmap#215(::Bool, ::Int64, ::Nothing, ::Array{Any,1}, ::Nothing, ::Function, ::Function, ::Distributed.CachingPool, ::UnitRange{Int64}) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.0/Distributed/src/pmap.jl:126
 [9] #pmap at ./none:0 [inlined]
 [10] solve_batch(::MonteCarloProblem{ODEProblem{Array{Float64,1},Tuple{Float64,Float64},true,saddle_node_parameters,ODEFunction{true,typeof(saddle_node),LinearAlgebra.UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Nothing,DiffEqBase.StandardODEProblem},getfield(Main, Symbol("##27#28")),getfield(Main, Symbol("##29#30")),getfield(DiffEqBase, Symbol("##378#384")),Array{Any,1}}, ::Nothing, ::Symbol, ::UnitRange{Int64}, ::Int64, ::Pair{Symbol,Any}, ::Vararg{Pair{Symbol,Any},N} where N) at /home/max/.julia/packages/DiffEqMonteCarlo/c9ztK/src/solve.jl:47
 [11] macro expansion at ./logging.jl:316 [inlined]
 [12] #solve#1(::Int64, ::Int64, ::Int64, ::Symbol, ::Base.Iterators.Pairs{Symbol,Any,Tuple{Symbol,Symbol},NamedTuple{(:alg, :dt),Tuple{Euler,Float64}}}, ::Function, ::MonteCarloProblem{ODEProblem{Array{Float64,1},Tuple{Float64,Float64},true,saddle_node_parameters,ODEFunction{true,typeof(saddle_node),LinearAlgebra.UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Nothing,DiffEqBase.StandardODEProblem},getfield(Main, Symbol("##27#28")),getfield(Main, Symbol("##29#30")),getfield(DiffEqBase, Symbol("##378#384")),Array{Any,1}}, ::Nothing, ::Type{Val{true}}) at /home/max/.julia/packages/DiffEqMonteCarlo/c9ztK/src/solve.jl:21
 [13] (::getfield(DiffEqBase, Symbol("#kw##solve")))(::NamedTuple{(:alg, :dt, :num_monte),Tuple{Euler,Float64,Int64}}, ::typeof(solve), ::MonteCarloProblem{ODEProblem{Array{Float64,1},Tuple{Float64,Float64},true,saddle_node_parameters,ODEFunction{true,typeof(saddle_node),LinearAlgebra.UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Nothing,DiffEqBase.StandardODEProblem},getfield(Main, Symbol("##27#28")),getfield(Main, Symbol("##29#30")),getfield(DiffEqBase, Symbol("##378#384")),Array{Any,1}}, ::Nothing, ::Type{Val{true}}) at ./none:0 (repeats 3 times)
 [14] top-level scope at In[25]:1

即使我只是以MonteCarloProblem的方式手动遍历所有问题时,它仍然有效:

for i=1:N 
   soli=solve(mcp.prob_func(odep, i, false),alg=Euler(), dt=0.1)
   println(eval_func(soli,i))
end

产生的所有均值和sds结果都很好,没有转换错误。

我知道这个示例似乎不太有用,但是对于我的实际项目,即使解决方案扩展到Infinity,我也希望行为保持一致。

在此先感谢您的帮助。

0 个答案:

没有答案