使用scipy.optimize

时间:2016-08-27 15:23:07

标签: python optimization scipy polynomial-math

我有函数f1 = lambda x: 1 - 1.12 * (x ** 0.5) * ((1-x) ** 0.02),我希望在区间(0,1)中找到它的根。我尝试使用scipy.optimize.brentqscipy.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

3 个答案:

答案 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)

正如您所知,对您的部分问题的直接回答是,fsolve在区间[0.97,0.98]中找不到根,因为那里没有根。至于系统的方式,为什么不使用情节

一旦您将该功能定义为 lambda ,准备好与Brent或其他各种例程一起使用,您只需将所需的子字符串复制并粘贴到的调用中即可情节并指出感兴趣的间隔。如果其中一个根部有点模糊,那么扩大x轴的那一部分。

Function to study

在这种情况下,这是一些典型的代码。

Produce plot and find roots