Optimization 使用scipy fsolve(遇到数学域错误)求解非线性方程组

Optimization 使用scipy fsolve(遇到数学域错误)求解非线性方程组,optimization,scipy,Optimization,Scipy,我试图用Scipy的fsolve找到两个非线性方程组的答案。 这两个方程是: f1 = math.log(x) + 1. - ((1. + (m - 1)*x) / m) + chi * (1 - x)**2 f2 = math.log(1 - x) - (m - 1)*x + chi*m*x**2 在这种情况下,m和chi是常数。基本目标是找到同时满足f1x=f1y和f2x=f2y的x,y。我知道x,y的初始猜测是0.3和0.99。下面是我的代码 from scipy.optimize im

我试图用Scipy的fsolve找到两个非线性方程组的答案。 这两个方程是:

f1 = math.log(x) + 1. - ((1. + (m - 1)*x) / m) + chi * (1 - x)**2
f2 = math.log(1 - x) - (m - 1)*x + chi*m*x**2
在这种情况下,m和chi是常数。基本目标是找到同时满足f1x=f1y和f2x=f2y的x,y。我知道x,y的初始猜测是0.3和0.99。下面是我的代码

from scipy.optimize import fsolve
import math

# some global variables
m = 46.663
chi = 1.1500799949128826

def binodal_fsolve():
    def equations(p):
        x, y = p
        out = []
        out.append(math.log(x) + 1. - ((1. + (m - 1)*x) / m) + chi * (1 - x)**2 - (math.log(y) + 1. - ((1. + (m - 1)*y) / m) + chi * (1 - y)**2))
        out.append(math.log(1 - x) - (m - 1)*x + chi*m*x**2 - (math.log(1 - y) - (m - 1)*y + chi*m*y**2))

        return out

    initial_guess = [0.3, 0.99]
    ans = fsolve(equations, initial_guess)

    return ans

def test_answers(phiL, phiR):
    def functions(x):
        return math.log(x) + 1. - ((1. + (m - 1)*x) / m) + chi * (1 - x)**2, math.log(1 - x) - (m - 1)*x + chi*m*x**2

    return functions(phiL)[0], functions(phiR)[0], functions(phiL)[1], functions(phiR)[1]

print (test_answers(0.2542983070, 0.9999999274))
# (1.3598772108380786e-09, -1.5558330624053502e-09, -8.434988430355375, -8.435122589529684)
res = binodal_fsolve()
print (res)
当我执行代码时,我总是遇到数学域错误。 但是,如果我尝试使用MAPLE fsolve解决它。我可以得到答案0.254298370,0.999999274

通过将这些插入方程,我得到了1.3598772108380786e-09,-1.555833064053502E-09,-8.434988430355375,-8.435122589529684,这表明答案是正确的。
我不知道如何使scipy fsolve工作。如果您有任何建议,我们将不胜感激。

在这种情况下,您可以使用numpy.lib.scimath中的log函数,该函数在参数为负数时返回复数

与其使用scipy.optimize.fsolve,不如使用scipy.optimize.root,并将方法更改为lm,该方法通过修改Levenberg-Marquardt算法,在最小二乘意义上求解非线性方程组。有关更多方法,请参阅

从scipy.optimize导入根目录 将numpy.lib.scimath作为数学导入 一些全局变量 m=46.663 chi=1.1500799949128826 def binodal_fsolve: def方程SP: x、 y=p out=[] out.appendmath.logx+1。-1. + m-1*x/m+chi*1-x**2-数学、逻辑学+1.-1. + m-1*y/m+chi*1-y**2 out.appendmath.log1-x-m-1*x+chi*m*x**2-math.log1-y-m-1*y+chi*m*y**2 返回 初始猜测=[0.3,0.99] ans=F溶剂方程,初始猜测 ans=根方程,初始猜测,方法='lm' 返回ans def测试应答器,phiR: def功能X: 返回math.logx+1。-1. + m-1*x/m+chi*1-x**2,math.log1-x-m-1*x+chi*m*x**2 返回functionsphiL[0],functionsphiR[0],functionsphiL[1],functionsphiR[1] 打印测试答案0.2542983070,0.999999274 1.3598772108380786e-09,-1.555833064053502E-09,-8.434988430355375,-8.435122589529684 res=双对数解 打印资源 它给出了以下根x和y::数组[0.25429812,0.99999993]

完整输出:


在迭代的相对早期,y=1.2733826071980916,因此1-y为负值,在math.log中产生域错误,这对我来说是有意义的。在平方根运算中,数学域错误通常为零或负。任何对其施加约束以获得物理上有意义的结果的建议。我们知道x和y在0,1范围内,不包括在内。我不知道为什么MAPLE fsolve只使用了与Scipy fsolve类似的基本命令就找到了正确答案。MAPLE是一种符号数学语言。Python中最接近的东西是sympy。fsolve是一个纯数值解算器。我没有看到fsolve的约束选项,但同一个包中的minimize确实有基于约束的方法。@Chenyang:这解决了你的问题吗?是的。这解决了我的问题。我也用root做过实验,也就是说,把它转换成一个优化问题,但没有成功。我想关键的一步是numpy.lib.scimath,而不是Python默认的数学,我以前不知道。但是是的,谢谢你。
(1.3598772108380786e-09, -1.5558330624053502e-09, -8.434988430355375, -8.435122589529684)
/home/user/.local/lib/python3.6/site-packages/scipy/optimize/minpack.py:401: ComplexWarning: Casting complex values to real discards the imaginary part
  gtol, maxfev, epsfcn, factor, diag)
   cov_x: array([[6.49303571e-01, 8.37627537e-07],
       [8.37627537e-07, 1.08484856e-12]])
    fjac: array([[ 1.52933340e+07, -1.00000000e+00],
       [-1.97290115e+01, -1.24101235e+00]])
     fun: array([-2.22945317e-07, -7.20367503e-04])
    ipvt: array([2, 1], dtype=int32)
 message: 'The relative error between two consecutive iterates is at most 0.000000'
    nfev: 84
     qtf: array([-0.00338589,  0.00022828])
  status: 2
 success: True
       x: array([0.25429812, 0.99999993])