在 SymPy 中,为什么我的解决方案 (nonlinsolve) 返回错误答案? [英] In SymPy, why is my solution (nonlinsolve) returning the wrong answer?

查看:18
本文介绍了在 SymPy 中,为什么我的解决方案 (nonlinsolve) 返回错误答案?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

from sympy import *x, y, z = 符号('x, y, z')dx = x - x ** 3/3 - z + ydy = -y ** 2 * 0.1 + zdz = 0xy_nullcline = nonlinsolve([dx, dy], [x, y, z])打印(xy_nullcline)# {# (x, -3.16227766016838*sqrt(z), z),# (x, 3.16227766016838*sqrt(z), z)# }

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

  • 橙色曲线是dx零斜线,(x,y,z),其中dx=0,三次多项式
  • 紫色曲线是dy零斜线,dy=0,一个平方多项式

两个曲面的交集,我的目标,是 (x,y,z) 的集合,其中 dx=dy=0.您可以在图片中清楚地看到交点所在的位置:它是一条向上的抛物线,但向底部推出.当我将紫色表面向上移动一点时,那个凸起变成了一个单独的椭圆.

找到的解决方案正是紫色曲线,而不是交点.我使用了同样的方法来寻找其他曲线的交点,结果正如预期的那样,只是一条跟踪一个函数与另一个函数相等的线.SymPy 将其作为 FiniteSet 返回,但这作为错误的 2d 表面返回.

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

解决方案

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

在 SymPy 1.1.1 中,我得到 <预><代码>>>>解决([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 参数化的曲线,而不是曲面.

I have a system of 3 equations, and I'd like to find a solution for the line of intersection, or the nullcline, of 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)
# }

In the image below, axes are x, y, z and:

  • orange curve is the dx nullcline, (x,y,z), where dx=0, a cubic polynomial
  • purple curve is the dy nullcline, dy=0, a square polynomial

The intersection of the two surfaces, my goal, is the set of (x,y,z) where dx=dy=0. You can see clearly in the picture where the intersection is: it's an upward parabolic line, but toward the bottom it pushes out. When I move the purple surface upward a little, that bulge turns into a lone ellipse.

The solution that is found is exactly the purple curve, not the intersection. I have used this same method for finding intersections of other curves, and the result is, as expected, just a line that tracks where one function equals the other. SymPy returns it as FiniteSets, but this comes back as the wrong 2d surface.

Am I doing something wrong? Or is this a bug?

解决方案

Looks like nonlinsolve ignores the first of two equations. I prefer to use solve. Also, avoid creating floating point coefficients like 0.1; they cause problems on many levels in SymPy. Use dy = -y ** 2 / 10 + z. See Python numbers vs. SymPy Numbers.

In SymPy 1.1.1, I get

>>> 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}]

So there are three solutions, which are curves parametrized by y, not surfaces.

这篇关于在 SymPy 中,为什么我的解决方案 (nonlinsolve) 返回错误答案?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆