如何找到在 f(x) 而不是 x 上接受错误的函数的根?
How to find root of a function accepting error on f(x) instead of x?
我有一个类似 e 的函数。 g.:
amountOfCalls = 0
def myFunc(x):
global amountOfCalls
amountOfCalls+=1
y = x ** 3 + x -5
return y
并想找到它的根(即:找到 x
的值,其中 f(x) == 0
)。
如果我使用 scipy
优化器之一,如 ridder,我只能设置 x
的相对或绝对容差,但不能设置 f(x)
.
有没有 possibility/alternative,我可以告诉优化器在 abs(f(x))
变得小于例如0.2
(作为绝对公差)?
备注:由于我的函数实际上是一个黑盒函数,我必须坚持优化方法(不幸的是,分析替代方案不起作用)。
我可能误解了你的问题,但这应该可以解决问题:
global amountOfCalls
amountOfCalls+=1
y = x ** 3 + x -5
if y == 0:
return x
return y
您可以使用 scipy.optimize.root
实现此目的,如 here 所述。
您可以在上述 link 上使用任何提到的方法。我选择broyden1
。在此方法中,您可以将 fatol
设置为 0.2
,因为它是残差的绝对容差。
from scipy.optimize import root
amountOfCalls = 0
def myFunc(x):
global amountOfCalls
amountOfCalls+=1
y = x ** 3 + x -5
return y
x0 = 3
res = root(myFunc, x0, method='broyden1', options={'disp':True, 'fatol':0.2})
print(res)
以上代码将在myFunc(x) < 0.2
时终止。
如果您希望您的条件明确 abs(f(x)) < 0.2
,那么您可以使用 callback 函数,因为它在每次迭代时都会被调用。然后,您可以在每次迭代时检查是否满足条件并引发 Error
以停止寻根方法,如下所示:
from scipy.optimize import root
class Error(Exception):
pass
class AlmostReachedZeroError(Error):
pass
class rootFinder():
def __init__(self):
self.amountOfCalls = 0
def fun(self, x0):
y = x0 ** 3 + x0 - 5
return y
def callback(self, x, f):
# callback to terminate if condition is met
self.amountOfCalls+=1
if abs(self.fun(x[0])) < 0.2:
print("Current x: ", x[0], "Current fval: ", f[0],
"Iterations: ", self.amountOfCalls)
raise AlmostReachedZeroError("Terminating optimization: limit reached")
def find_root(self):
x0 = 3
opt = root(self.fun, x0, method='broyden1', callback=self.callback,
options={'disp':True, 'ftol':0.2})
return opt
rf = rootFinder()
res = rf.find_root()
print(res)
如果abs(f(x)) < 0.2
,上面的代码将终止寻根方法,并产生一个Error
。此外,当前 x 值、当前 fval 以及该方法所采用的 iterations 将是印刷。
我有一个类似 e 的函数。 g.:
amountOfCalls = 0
def myFunc(x):
global amountOfCalls
amountOfCalls+=1
y = x ** 3 + x -5
return y
并想找到它的根(即:找到 x
的值,其中 f(x) == 0
)。
如果我使用 scipy
优化器之一,如 ridder,我只能设置 x
的相对或绝对容差,但不能设置 f(x)
.
有没有 possibility/alternative,我可以告诉优化器在 abs(f(x))
变得小于例如0.2
(作为绝对公差)?
备注:由于我的函数实际上是一个黑盒函数,我必须坚持优化方法(不幸的是,分析替代方案不起作用)。
我可能误解了你的问题,但这应该可以解决问题:
global amountOfCalls
amountOfCalls+=1
y = x ** 3 + x -5
if y == 0:
return x
return y
您可以使用 scipy.optimize.root
实现此目的,如 here 所述。
您可以在上述 link 上使用任何提到的方法。我选择broyden1
。在此方法中,您可以将 fatol
设置为 0.2
,因为它是残差的绝对容差。
from scipy.optimize import root
amountOfCalls = 0
def myFunc(x):
global amountOfCalls
amountOfCalls+=1
y = x ** 3 + x -5
return y
x0 = 3
res = root(myFunc, x0, method='broyden1', options={'disp':True, 'fatol':0.2})
print(res)
以上代码将在myFunc(x) < 0.2
时终止。
如果您希望您的条件明确 abs(f(x)) < 0.2
,那么您可以使用 callback 函数,因为它在每次迭代时都会被调用。然后,您可以在每次迭代时检查是否满足条件并引发 Error
以停止寻根方法,如下所示:
from scipy.optimize import root
class Error(Exception):
pass
class AlmostReachedZeroError(Error):
pass
class rootFinder():
def __init__(self):
self.amountOfCalls = 0
def fun(self, x0):
y = x0 ** 3 + x0 - 5
return y
def callback(self, x, f):
# callback to terminate if condition is met
self.amountOfCalls+=1
if abs(self.fun(x[0])) < 0.2:
print("Current x: ", x[0], "Current fval: ", f[0],
"Iterations: ", self.amountOfCalls)
raise AlmostReachedZeroError("Terminating optimization: limit reached")
def find_root(self):
x0 = 3
opt = root(self.fun, x0, method='broyden1', callback=self.callback,
options={'disp':True, 'ftol':0.2})
return opt
rf = rootFinder()
res = rf.find_root()
print(res)
如果abs(f(x)) < 0.2
,上面的代码将终止寻根方法,并产生一个Error
。此外,当前 x 值、当前 fval 以及该方法所采用的 iterations 将是印刷。