如何在Julia中快速求解多项式方程?
我在研究生物系统的进化模拟。我必须解多项式方程,找到根(u*X^3-N*p*r*X^2-N*p*X^2+K^2*u*X-N*K^2*p),其中u和K是常数,N是常数数组,p,r是演化参数。基本上,对于每一代人口中的每个个体,我需要进行以下计算(长度(N)>>长度(p)):如何在Julia中快速求解多项式方程?,julia,differential-equations,polynomial-math,Julia,Differential Equations,Polynomial Math,我在研究生物系统的进化模拟。我必须解多项式方程,找到根(u*X^3-N*p*r*X^2-N*p*X^2+K^2*u*X-N*K^2*p),其中u和K是常数,N是常数数组,p,r是演化参数。基本上,对于每一代人口中的每个个体,我需要进行以下计算(长度(N)>>长度(p)): 我知道我可以通过使用不同的核来求解不同个体的方程来并行代码,甚至在每个个体内,我可以并行求解每个X[j,I]。我想知道处理这种情况的最佳实践/快速方法是什么?有可能以更快的方式解一个方程吗 这个答案比较了根、GSL和多项式根解
我知道我可以通过使用不同的核来求解不同个体的方程来并行代码,甚至在每个个体内,我可以并行求解每个X[j,I]。我想知道处理这种情况的最佳实践/快速方法是什么?有可能以更快的方式解一个方程吗 这个答案比较了
根
、GSL
和多项式根
解决问题版本的软件包。机器上的计时可能不同,最好在本地运行。但本质上,GSL
是最快的,大约比根快1000倍,其中多项式根介于两者之间(但更接近GSL
)。有关更多信息,请参见注释
守则:
# using Julia 0.5.1-pre+4
# Pkg.add("Roots")
# Pkg.add("GSL")
# Pkg.add("PolynomialRoots")
using GSL
using Roots
using PolynomialRoots
function test1(p,r,N,u,K)
X = Matrix{Float64}(length(N),length(p))
for i = 1:length(p)
for j = 1:length(N)
X[j,i] = mean(fzeros(S -> u*S^3 - p[i]*N[j]*r[i]*S^2 - p[i]*N[j]*S^2 + K^2*u*S - p[i]*K^2*N[j], 0, Inf) )
end
end
return X
end
function test2(p,r,N,u,K)
X = Matrix{Float64}(length(N),length(p))
uinv = inv(u)
for i = 1:length(p)
for j = 1:length(N)
X[j,i] = mean(poly_solve_cubic(-uinv*(p[i]*N[j]*r[i]+p[i]*N[j]),K^2,-uinv*p[i]*K^2*N[j]) )
end
end
return X
end
function test3(p,r,N,u,K)
X = Matrix{Float64}(length(N),length(p))
for i = 1:length(p)
for j = 1:length(N)
X[j,i] = mean(filter(x->abs(imag(x))<1.0e-10,
PolynomialRoots.solve_cubic_eq(Complex{Float64}[- p[i]*K^2*N[j], K^2*u, - p[i]*N[j]*r[i] - p[i]*N[j],u])))
end
end
return X
end
K = 1.0
u = 1.0
N = rand(1000)+1.0
p = rand(10)+1.0
r = rand(10)+1.0
res1 = test1(p,r,N,u,K);
res2 = test2(p,r,N,u,K);
res3 = test3(p,r,N,u,K);
using Base.Test
@test_approx_eq res1 res2
@test_approx_eq res1 res3
@time test1(p,r,N,u,K); # Roots
@time test2(p,r,N,u,K); # GSL
@time test3(p,r,N,u,K); # PolynomialRoots
nothing
如果你比较一下这些方法,你会很高兴听到关于实际问题时间安排的报告。谢谢。我怀疑这个问题的答案不是朱莉娅的;熟悉该领域的人可能会向您指出特定的算法及其实现。如果您想要所有根(包括复数根),则可以通过这种方式使用fzeros
(fzeros(f,a,b)
(非常慢。(该算法非常简单,并且依赖于二分法,它比其他算法使用更多的迭代次数。)改用根
。多项式根
包甚至可以提供更快的解决方案。这与微分方程有什么关系?我需要解的方程实际上是一个微分方程,但我需要的是平衡点dX/dt=0,所以基本上是找到多项式方程的根n、 @jverzani谢谢。我想知道获得实根的最快方法是什么?似乎roots
给出了所有实根和复根。毫不奇怪roots这么慢,其他两种方法都是针对立方体的,roots实现是针对任何标量函数的,但我很惊讶GSL比Polynom快得多i根,因为这两个都是针对问题量身定制的。一定是由于在多项式根中进行了复杂的运算。K=50.0 u=1e-4 N=collect(linspace(10.^1.5,10.^5,100))p=[5e-9;5e-9]r=[5;[5.]5.]根:0.536053秒(4.84 M分配:297.875 MB,17.26%gc时间)GSL:0.000087秒(1.61 K分配:83.422 KB)多项式根不起作用。无论如何,GSL比根快6000x+。
# using Julia 0.5.1-pre+4
# Pkg.add("Roots")
# Pkg.add("GSL")
# Pkg.add("PolynomialRoots")
using GSL
using Roots
using PolynomialRoots
function test1(p,r,N,u,K)
X = Matrix{Float64}(length(N),length(p))
for i = 1:length(p)
for j = 1:length(N)
X[j,i] = mean(fzeros(S -> u*S^3 - p[i]*N[j]*r[i]*S^2 - p[i]*N[j]*S^2 + K^2*u*S - p[i]*K^2*N[j], 0, Inf) )
end
end
return X
end
function test2(p,r,N,u,K)
X = Matrix{Float64}(length(N),length(p))
uinv = inv(u)
for i = 1:length(p)
for j = 1:length(N)
X[j,i] = mean(poly_solve_cubic(-uinv*(p[i]*N[j]*r[i]+p[i]*N[j]),K^2,-uinv*p[i]*K^2*N[j]) )
end
end
return X
end
function test3(p,r,N,u,K)
X = Matrix{Float64}(length(N),length(p))
for i = 1:length(p)
for j = 1:length(N)
X[j,i] = mean(filter(x->abs(imag(x))<1.0e-10,
PolynomialRoots.solve_cubic_eq(Complex{Float64}[- p[i]*K^2*N[j], K^2*u, - p[i]*N[j]*r[i] - p[i]*N[j],u])))
end
end
return X
end
K = 1.0
u = 1.0
N = rand(1000)+1.0
p = rand(10)+1.0
r = rand(10)+1.0
res1 = test1(p,r,N,u,K);
res2 = test2(p,r,N,u,K);
res3 = test3(p,r,N,u,K);
using Base.Test
@test_approx_eq res1 res2
@test_approx_eq res1 res3
@time test1(p,r,N,u,K); # Roots
@time test2(p,r,N,u,K); # GSL
@time test3(p,r,N,u,K); # PolynomialRoots
nothing
20.664363 seconds (225.67 M allocations: 13.650 GB, 18.81% gc time) # Roots
0.010303 seconds (80.01 k allocations: 4.044 MB, 75.30% gc time) # GSL
0.215453 seconds (394.90 k allocations: 9.917 MB) # PolynomialRoots