可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Assume the following function:
f(x) = x * cos(x-4)
With x = [-2.5, 2.5]
this function crosses 0
at f(0) = 0
and f(-0.71238898) = 0
.
This was determined with the following code:
import math from scipy.optimize import fsolve def func(x): return x*math.cos(x-4) x0 = fsolve(func, 0.0) # returns [0.] x0 = fsolve(func, -0.75) # returns [-0.71238898]
What is the proper way to use fzero
(or any other Python root finder) to find both roots in one call? Is there a different scipy
function that does this?
fzero
reference
回答1:
Define your function so that it can take either a scalar or a numpy array as an argument:
>>> import numpy as np >>> f = lambda x : x * np.cos(x-4)
Then pass a vector of arguments to fsolve
.
>>> x = np.array([0.0, -0.75]) >>> fsolve(f,x) array([ 0. , -0.71238898])
回答2:
I once wrote a module for this task. It's based on chapter 4.3 from the book Numerical Methods in Engineering with Python by Jaan Kiusalaas:
import math def rootsearch(f,a,b,dx): x1 = a; f1 = f(a) x2 = a + dx; f2 = f(x2) while f1*f2 > 0.0: if x1 >= b: return None,None x1 = x2; f1 = f2 x2 = x1 + dx; f2 = f(x2) return x1,x2 def bisect(f,x1,x2,switch=0,epsilon=1.0e-9): f1 = f(x1) if f1 == 0.0: return x1 f2 = f(x2) if f2 == 0.0: return x2 if f1*f2 > 0.0: print('Root is not bracketed') return None n = int(math.ceil(math.log(abs(x2 - x1)/epsilon)/math.log(2.0))) for i in range(n): x3 = 0.5*(x1 + x2); f3 = f(x3) if (switch == 1) and (abs(f3) >abs(f1)) and (abs(f3) > abs(f2)): return None if f3 == 0.0: return x3 if f2*f3
roots
finds all roots of f
in the interval [a
, b
].
回答3:
In general (i.e. unless your function belongs to some specific class) you can't find all the global solutions - these methods usually do local optimization from given starting points.
However, you can switch math.cos() with numpy.cos() and that will vectorize your function so it can solve for many values at once, e.g. fsolve(func, np.arange(-10,10,0.5)).