我有函数f1 = lambda x: 1 - 1.12 * (x ** 0.5) * ((1-x) ** 0.02)
,我希望在区间(0,1)中找到它的根。我尝试使用scipy.optimize.brentq
和scipy.optimize.fsolve
来执行此操作,但这两种方法都会遇到问题。根据一些实验,我得出这个方程的根大致等于0.86322414和0.9961936895432034(我们知道最多有两个根,因为函数在这个区间内有一个拐点):
f1 = lambda x: 1 - 1.12 * (x ** 0.5) * ((1-x) ** 0.02)
print(fsolve(f1, 0.5))
print(f1(0.99))
print(f1(0.999))
print(brentq(f1, 0.99, 0.999))
输出:
[ 0.86322414]
-0.016332046983897452
0.025008640855473052
0.9961936895432034
这里的问题是,为了让brentq工作,函数的值必须在指定的端点处具有相反的符号。此外,当我以接近1的x
值开始fsolve时,我收到了运行时警告消息:
print(fsolve(f1, 0.97))
print(fsolve(f1, 0.98))
输出:
[ 0.97]
[ 0.98]
C:/Users/Alexander/Google Drive/Programming/Projects/Root Finding/roots.py:6: RuntimeWarning: invalid value encountered in power
C:\Users\Alexander\Anaconda3\lib\site-packages\scipy\optimize\minpack.py:161: RuntimeWarning: The iteration is not making good progress, as measured by the
improvement from the last ten iterations.
是否有人有更系统的方法来解决这个等式的根源,以及为什么fsolve不能用于x = 0.97, 0.98
?
答案 0 :(得分:2)
fsolve不支持间隔的根查找。它可能会偏离x< 0或x> 1,因此RuntimeWarning(一次)和垃圾回答。您可以通过使用print(x)检测功能来检查它。
如果间隔包含多个根,则不确定Brentq的行为。
如果您知道拐点,或者知道只有一个拐点,那么您可以通过brentq找到它并使用它来支撑您的两个根。
答案 1 :(得分:2)
如果你取得函数的导数并将其设置为0,在一个小代数之后,你会发现x0 = 0.5 / 0.52时导数为0。 (在微积分类中,此点称为临界点,而不是拐点。)此函数此时具有最小值,并且该值为负值。 x = 0和x = 1的值为正,因此您可以使用[0,x0]和[x0,1]作为brentq
中的包围间隔:
In [17]: from scipy.optimize import brentq
In [18]: f1 = lambda x: 1 - 1.12 * (x ** 0.5) * ((1-x) ** 0.02)
In [19]: x0 = 0.5/0.52
In [20]: brentq(f1, 0, x0)
Out[20]: 0.8632241390303161
In [21]: brentq(f1, x0, 1)
Out[21]: 0.9961936895432096
答案 2 :(得分:1)