为Sympy解决建议解决方案

时间:2015-02-28 01:41:46

标签: python optimization sympy solver

我尝试使用SymPy solve来解决许多不同输入值的等式。到目前为止,这是我的代码:

E = np.linspace(Emin,Emax,((Emax-Emin)/Emesh)+1)
z1 = np.zeros(len(E))+0j

for i in xrange(len(E)):    
    z = Symbol('z')
    z1[i] = solve( (d - E[i])/s - z - 1/z, z)

此处ds是常量,E是一维数组。代码工作正常,但速度很慢。由于E[i]变化缓慢,z1[i]几乎等于z1[i+1]。我不是每次都为每个新的E[i]从头开始解决方程式,而是希望使用结果z1[i]作为求解z1[i+1]的起点。另一种选择是根据z[i+1]的值对z[i]的允许值进行限制。基本上我希望尽可能加快这一部分的速度。

有什么建议吗?

2 个答案:

答案 0 :(得分:2)

如果你看看你的等式,

(d - e) / s - z - 1/z == 0

乘以-z

z**2 + ((e - d) / 2) * z + 1 == 0

现在它是我们可以轻松解决的二次方,

b = (e - d) / s

z = (-b +/- (b*b - 4)**0.5) / 2

和numpy代码可以做到这一点,

import numpy as np

# some made-up numbers
e_min = 1.9
e_max = 2.6
e_mesh = 0.05
d = 2.1
s = 0.45

es = np.arange(e_min, e_max, e_mesh, dtype=np.complex)

bs  = (es - d) / s
rts = np.sqrt(bs * bs - 4)
z1 = (-bs + rts) / 2
z2 = (-bs - rts) / 2

,当运行时,产生

z1
Out[118]: 
array([ 0.22222222-0.97499604j,  0.16666667-0.9860133j ,
        0.11111111-0.99380799j,  0.05555556-0.9984556j ,
        0.00000000+1.j        , -0.05555556+0.9984556j ,
       -0.11111111+0.99380799j, -0.16666667+0.9860133j ,
       -0.22222222+0.97499604j, -0.27777778+0.96064536j,
       -0.33333333+0.94280904j, -0.38888889+0.92128466j,
       -0.44444444+0.89580642j, -0.50000000+0.8660254j ,
       -0.55555556+0.83147942j])

z2
Out[119]: 
array([ 0.22222222+0.97499604j,  0.16666667+0.9860133j ,
        0.11111111+0.99380799j,  0.05555556+0.9984556j ,
       -0.00000000-1.j        , -0.05555556-0.9984556j ,
       -0.11111111-0.99380799j, -0.16666667-0.9860133j ,
       -0.22222222-0.97499604j, -0.27777778-0.96064536j,
       -0.33333333-0.94280904j, -0.38888889-0.92128466j,
       -0.44444444-0.89580642j, -0.50000000-0.8660254j ,
       -0.55555556-0.83147942j])

答案 1 :(得分:0)

在这种情况下,您甚至可能不需要使用求解! 你想要做的只是解决方程:

(d - E[i])/s - z - 1/z=0

表示z。在我们的朋友WolframAlpha的帮助下,我们得到:

z=-(-d+E[i]+sqrt(d**2-2*d*E[i]+E[i]**2-4*s**2))/(2*s)

z=(d-E[i]+sqrt(d**2-2*d*E[i]+E[i]**2-4*s**2))/(2*s)

我不确定您的域名,因此您可以选择其中一个或两个。

供参考,完整的功能:

E = np.linspace(Emin,Emax,((Emax-Emin)/Emesh)+1)
z1 = np.zeros(len(E))+0j
for i in xrange(len(E)):    
    z1[i] = z #Replace z with one/both of the expressions above