Python 为非零级求根

Python find root for non-zero level

假设我有以下代码

def myfunc(x):
    return monsterMathExpressionOf(x)

我想找到 myfunc(x) == y 不同值 y 的数值解。如果 y == 0 那么有很多可用的根查找程序,例如来自 scipy。但是,如果我想找到解决方案,例如y==1看来我得定义一个新函数了

def myfunc1(x):
    return myfunc(x) - 1

然后使用可用的程序找到它的根目录。这种方式对我不起作用,因为我需要通过 运行 循环找到很多解决方案,并且我不想在循环的每个步骤中重新定义函数。有更简洁的解决方案吗?

您不必为 y 的每个值重新定义函数:只需定义 y 的单个函数,即 returns x 的函数,并在循环中使用该函数:

def wrapper(y):
    def myfunc(x):
        return monsterMathExpressionOf(x) - y
    return myfunc

for y in y_values:
    f = wrapper(y)
    find_root(f, starting_point, ...)

您也可以使用functools.partial,这可能更符合您的喜好:

def f(x, y):
    return monsterMathExpressionOf(x) - y

for y in y_values:
    g = partial(f, y=y)
    find_root(g, starting_point, ...)

阅读文档,看看partial是如何在幕后大致实现的;您会发现它与第一个 wrapper 实施相比可能没有太大不同。

@Evert 的回答显示了如何通过使用 closure 或使用 functools.partial 来做到这一点,这都是很好的解决方案。

许多数值求解器提供了另一种选择。例如,考虑 scipy.optimize.fsolve。该函数提供了 args 参数,它允许您将额外的固定参数传递给要求解的函数。

例如,假设myfunc是x**3 + x

def myfunc(x):
    return x**3 + x

定义一个包含参数 y 作为参数的附加函数:

def myfunc2(x, y):
    return myfunc(x) - y

要解决,比方说,myfunc(x) = 3,你可以这样做:

from scipy.optimize import fsolve

x0 = 1.0  # Initial guess

sol = fsolve(myfunc2, x0, args=(3,))

您可以使用匿名函数作为 fsolve 的第一个参数,而不是定义 myfunc2

sol = fsolve(lambda x, y: myfunc(x) - y, x0, args=(3,))

但是你可以使用

完成同样的事情
sol = fsolve(lambda x: myfunc(x) - 3, x0)