如何找到在 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 将是印刷。