2017-04-07 74 views
3

我有一組函數f_t有幾個根(實際上是兩個)。我想找到「第一個」根,並在fsolve大部分時間都能正常工作。問題在於,當t趨於無窮時,兩個根會聚。 (我的功能簡單例子是f_t(x) = x^2 - 1/t)。所以更大的t得到,更多的錯誤fsolve。是否有預定義的函數,類似於fsolve,我可以告訴它它只應該在給定範圍內查找(例如總是找到[0, inf中的根))。在給定的範圍內找到函數的根

問題與https://mathematica.stackexchange.com/questions/91784/how-to-find-numerically-all-roots-of-a-function-in-a-given-range?noredirect=1&lq=1基本相同,但是對於Mathematica來說,我需要Python中的答案。 PS:我現在怎麼可以寫我自己的算法,但是因爲這些內建函數往往會比較慢,所以我希望找到一個內建函數。尤其是我讀過這篇文章Find root of a function in a given interval

+1

(https://docs.scipy.org/doc/scipy-0.18.1/reference/optimize.html#找到) – Michael

回答

1

人們普遍認爲,對於順暢,功能良好的功能,Brent method是保證給根的最快方法。與列出的其他兩種方法一樣,您必須提供間隔[a,b],該函數在該間隔內是連續的並且會改變符號。

Scipy的實現記錄在here。一個例子用例關於你提到的可能看起來像這樣的功能:?試過這種]

from __future__ import division 
import scipy 

def func(x,t): 
    return(x**2 - 1/t) 

t0 = 1 
min = 0 
max = 100000 # set max to some sufficiently large value 

root = scipy.optimize.brentq(func, min, max, args = (t0)) # args just supplies any extra 
                 # argument for the function that isn't the varied parameter 
+0

只是化妝品,但你可能想要定義't',對於Python2來說,使用'1./t'可能會更好。 +1,很好的解決方案。 – Cleb

+1

好的電話,謝謝。 我在辯論是否擔心在這個小小的代碼分裂。我只是用'from __future__'來做懶惰的事情。 – Alex

+0

任何想法是否可以使用它來查找給定範圍內的所有根,如我在下面的答案中所示?我很驚訝沒有在標準的scipy中找到。 – Cleb

2

您可以使用scipy.optimize.bisect,它採用定義起始間隔的兩個參數ab。但有一些限制:

  • 間隔需要有限。您無法在[0,inf]中搜索。
  • 該函數必須在根上翻轉符號(f(a)f(b)必須有相反的符號),因此,例如,找不到f(x) = abs(x)的根(如果這甚至是數學意義上的「根」)。此外,它不適用於f(x) = x**2 - 1,並且間隔[a,b]與< -1和b> 1。
  • 該方法不是基於漸變的。如果函數的參數非常參差不齊或昂貴,這可能是一個優點,但在其他函數中可能會較慢。

另一種方法是使用scipy.optimize.minimize最小化abs(f(x))。該函數可以包含bounds,其中包括無窮大。但是最小化可能會導致函數的非根局部最小值。

+0

處理無窮大確實是一個問題,同樣在我基於'chebpy'的回答中。但我想出於實用目的,可以插入一個龐大的數字。 – Cleb

+1

@Cleb這是正確的,但是一個巨大的數字會增加平分步驟的數量。每雙倍幅度一步。 – kazemakase

1

經典,你可以使用root

import numpy as np 
from scipy.optimize import root 

def func(x, t): 
    return x ** 2 - 1./t 

t = 5000 

res = root(func, 0.5, args=(t,)).x[0] 
print res 

這將打印出積極的,在這種情況下0.0141421356237

如果你想指定範圍,並確定此區間內所有的根,你可以使用chebpy

from chebpy import chebfun 

x = chebfun('x', [-100000, 100000]) 
t = 5000 
f = x ** 2 - 1./t 

rts = f.roots() 
print rts 

這將打印的積極和消極的根,在這種情況下

[-0.01413648 0.01413648] 

如果你只是想在正的範圍內看,你可以改變

x = chebfun('x', [-100000, 100000]) 

x = chebfun('x', [0, 100000]) 

我,但不知道如何使用無限的,但你可以使用的實際用途非常高的數字,我想。

相關問題