Python 如何使用scipy.optimize.fsolve避免运行时错误 问题:
我正在尝试使用Python 如何使用scipy.optimize.fsolve避免运行时错误 问题:,python,scipy,scipy-optimize,Python,Scipy,Scipy Optimize,我正在尝试使用scipy.optimize.fsolve数值求解一个非线性代数方程组 我求解系统的几个不同参数值(k1、k2、k3如下)。对于某些参数值,fsolve会找到正确的解决方案,而对于其他参数值,则会出现以下警告 RuntimeWarning: The iteration is not making good progress, as measured by the improvement from the last five Jacobian evaluations. wa
scipy.optimize.fsolve
数值求解一个非线性代数方程组
我求解系统的几个不同参数值(k1、k2、k3
如下)。对于某些参数值,fsolve会找到正确的解决方案,而对于其他参数值,则会出现以下警告
RuntimeWarning: The iteration is not making good progress, as measured by the
improvement from the last five Jacobian evaluations.
warnings.warn(msg, RuntimeWarning)
从这些情况下的结果来看,很明显有些地方出了问题,因为h(result)
不是零向量。
毫无疑问,这个解决方案确实存在,它与那些找到正确解决方案的情况在质量上没有什么不同
在这些情况下通常推荐什么?这是一个初始条件的问题吗
例子 在下文中,我将展示如何求解方程组:
import numpy as np
from scipy.optimize import fsolve
# Parameters for the system of equations
k1, k2, k3 = 2., 4.5, 0.1
# Function for evaluating the residual of the system
def h(x):
x1, x2, x3=x
eqn1 = k1*x1 + k2*x2**2 - x3
eqn2 = x1 - 2.*x2 + k3*x3
eqn3 = x1 + x2 + x3 - 1.
return eqn1, eqn2, eqn3
# An initial guess
x0 = np.array([1., 0.5, 1.])
# Get the solution of the system of equations
result = fsolve(h, x0=x0, xtol=1e-5)
# Now, verify that the solution is correct
print(h(result)) # Should be near (0,0,0)
这有时非常有效,但对于k1、k2、k3的某些值,它会引发上面讨论的RuntimeWarning
,并返回错误的结果
#参数不正确
k1,k2,k3=2,4.5,-1。
#坏结果
结果=fsolve(h,x0=x0,xtol=1e-5)
#验证表明残差不接近(0,0,0)
打印(h(结果))
我不知道如何使用fsolve
摆脱您的运行时警告。如果你不介意用代数来解你的方程组,这里有一些方法
从你原来的方程组开始
def h(x):
x1,x2,x3=x
方程N1=k1*x1+k2*x2**2-x3
方程n2=x1-2.*x2+k3*x3
方程n3=x1+x2+x3-1。
返回eqn1、eqn2、eqn3
矩阵化
mat=np.array([
[k1,0,k2,-1],
[1,-2,0,k3],
[ 1, 1, 0, 1 ]
],dtype=float)
vec=np.array([0,0,1],dtype=float)
def h(x):
x1,x2,x3=x
返回矩阵@(x1,x2,x2**2,x3)-vec
在mat
的空空间中查找4d向量y
求解mat@y=vec
以及向量ns
y=np.linalg.lstsq(mat,vec,rcond=None)[0]
从scipy.linalg导入空_空间
ns=null_空间(mat).flatte()
现在使用这样一个事实,z=y+a*ns
也将为任何标量a
求解mat@z=vec
。这允许我们找到一些满足的z
。对于这样的z
,我们将x=z[[0,1,3]]
作为原始方程组的解
将z=y+a*ns
插入约束z[1]**2=z[2]
,我们需要(y[1]+a*ns[1])**2=y[2]+a*ns[2]
。求解a
的这个二次方程得到
a=np.root([ns[1]**2,2*y[1]*ns[1]-ns[2],y[1]**2-y[2])
既然你声称原始方程组有解,a
应该包含实数
#如果(且仅当)原始系统没有解决方案,此断言将失败。
断言np.isreal(a).all()
最后,我们可以得到原始方程组的两个解
soln1=(y+a[0]*ns)[[0,1,3]]
soln2=(y+a[1]*ns)[[0,1,3]]
您在这里忘记了运算符:eqn1=x1 k1+k2*x2**2-x3
并且您在这里有一个语法错误:eqn3=x1+x2+x3=1。
如果启动条件不好,数值方法通常会给出不好/没有结果。因此,一般来说,通过选择更好的初始值,您将获得更好的结果。自动实现这一点的一种方法是在一个循环中使用两个不同的初始参数调用fsolve,并检查哪个结果从0开始以较小的导数解出您的方程。@3sm1r您能否分享一个k1、k2、k3
的示例,您在其中遇到了您提到的RuntimeWarning
k1,k2,k3=np。数组([2,4.5,0.1])
对我来说运行良好。@moormany-Ty谢谢你的帮助。我已经根据你的建议编辑了这个问题。为了清楚起见,我只想强调,问题不在于解决方案不存在。我确实知道,但算法没有找到它。