英文:
solve a system of nonlinear equations using scipy fsolve (math domain error encountered)
问题
我尝试使用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
是常数。基本目标是找到同时满足 f1(x) = f1(y)
和 f2(x) = f2(y)
的 x
和 y
。我知道 x
和 y
的初始猜测值为 0.3
和 0.99
。以下是我的代码。
from scipy.optimize import fsolve
import math
# 一些全局变量
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)
当我执行代码时,我总是遇到"math domain error"错误。然而,如果我尝试使用MAPLE的fsolve
解决它,我可以得到答案(0.2542983070, 0.9999999274)
。
通过将这些值代入方程中,我得到(1.3598772108380786e-09, -1.5558330624053502e-09, -8.434988430355375, -8.435122589529684)
,这表明答案是正确的。
我不知道如何使scipy的fsolve工作。任何建议将不胜感激。
英文:
I tried to use Scipy's fsolve to find the answers to a system of two nonlinear equations.
The two equations are:
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
and chi
are constants in this case. The essential goal is to find x
, y
that satisfies simultaneously f1(x) = f1(y)
and f2(x) = f2(y)
. I know the initial guess for x
, y
are 0.3
and 0.99
. Below is my code.
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)
When I executed the code, I always encountered the math domain error.
However, if I tried to solve it using MAPLE fsolve
. I can get the answers (0.2542983070, 0.9999999274)
.
By plugging these back to the equations, I get (1.3598772108380786e-09, -1.5558330624053502e-09, -8.434988430355375, -8.435122589529684)
which suggests the answers are correct.
I don't know how to make scipy fsolve work. Any suggestions will be greatly appreciated.
答案1
得分: 1
在这种情况下,您可以使用numpy.lib.scimath
中的log
函数,当其参数为负数时返回一个复数。
不要使用scipy.optimize.fsolve
,而是使用scipy.optimize.root
,并将方法更改为lm
,该方法使用Levenberg-Marquardt算法的修改来以最小二乘的方式解决非线性方程组。有关更多方法,请参阅文档。
from scipy.optimize import root
import numpy.lib.scimath as math
# 一些全局变量
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)
ans = root(equations, initial_guess, method='lm')
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)
这将给出以下根:x
和y
的值:array([0.25429812, 0.99999993])
。
英文:
In this case you can use the log
function from numpy.lib.scimath
that returns a complex number when its argument is negative.
Instead of using scipy.optimize.fsolve
, use scipy.optimize.root
and change the method to lm
which solves the system of nonlinear equations in a least squares sense using a modification of the Levenberg-Marquardt algorithm. For more methods, see the documentation.
from scipy.optimize import root
import numpy.lib.scimath as 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)
ans = root(equations, initial_guess, method='lm')
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)
Which gives the following roots x
and y
: : array([0.25429812, 0.99999993])
.
The full output:
(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])
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论