在SymPy中,为什么我的解决方案(nonlinsolve)会返回错误的答案?

时间:2018-03-24 19:36:06

标签: python sympy

我有一个由3个方程组成的系统,我想找到dx=dy的交叉线或零线的解决方案。

from sympy import *

x, y, z = symbols('x, y, z')

dx = x - x ** 3 / 3 - z + y
dy = -y ** 2 * 0.1 + z
dz = 0

xy_nullcline = nonlinsolve([dx, dy], [x, y, z])

print(xy_nullcline)

# {
#   (x, -3.16227766016838*sqrt(z), z), 
#   (x, 3.16227766016838*sqrt(z), z)
# }

在下图中,轴为x, y, z和:

  • 橙色曲线是dx nullcline,(x,y,z), where dx=0,一个三次多项式
  • 紫色曲线是dy nullcline,dy=0,是方形多项式

我的目标是两个表面的交集,是(x,y,z) dx=dy=0的集合。您可以在图片中清楚地看到交点是:它是向上的抛物线,但是向下推出它。当我将紫色表面向上移动一点时,那个凸起会变成一个椭圆形。

找到的解决方案恰好是紫色曲线,而不是交叉点。我已经使用相同的方法来查找其他曲线的交点,结果是,正如预期的那样,只有一条线跟踪一个函数等于另一个函数的位置。 SymPy将其返回为FiniteSet s,但这会返回错误的2d表面。

我做错了吗?或者这是一个错误吗?

enter image description here

1 个答案:

答案 0 :(得分:1)

看起来nonlinsolve忽略了两个方程中的第一个。我更喜欢使用solve。另外,避免创建像0.1这样的浮点系数;它们会在SymPy的许多层面上造成问题。使用dy = -y ** 2 / 10 + z。见Python numbers vs. SymPy Numbers

在SymPy 1.1.1中,我得到了

>>> solve([dx, dy], [x, y, z])

[{x: -(50**(1/3)*(3*y**2 - 30*y + sqrt(9*y**2*(y - 10)**2 - 400))**(2/3)/10 + 20**(1/3))/(3*y**2 - 30*y + sqrt(9*y**2*(y - 10)**2 - 400))**(1/3), z: y**2/10}, 
 {x: (50**(1/3)*(1 - sqrt(3)*I)**2*(3*y**2 - 30*y + sqrt(9*y**2*(y - 10)**2 - 400))**(2/3) + 40*20**(1/3))/(20*(1 - sqrt(3)*I)*(3*y**2 - 30*y + sqrt(9*y**2*(y - 10)**2 - 400))**(1/3)), z: y**2/10}, 
 {x: (50**(1/3)*(1 + sqrt(3)*I)**2*(3*y**2 - 30*y + sqrt(9*y**2*(y - 10)**2 - 400))**(2/3) + 40*20**(1/3))/(20*(1 + sqrt(3)*I)*(3*y**2 - 30*y + sqrt(9*y**2*(y - 10)**2 - 400))**(1/3)), z: y**2/10}]

因此有三种解决方案,即由y参数化的曲线,而不是曲面。