Python 尝试建立反函数

Python 尝试建立反函数,python,algorithm,math,Python,Algorithm,Math,*如果你在胡吉做介绍,要小心。。。 我知道你为什么来这里* 我试图构建一个函数,它以一个函数(假设单调的连续性)作为参数,并返回它的反函数。 从数学上我知道我需要将函数反映到y=x。 但这并不顺利 我写了一些东西,它将给我x0,使f(x0)=0 def solve(f, x0=-10000, x1=10000, epsilon=EPSILON): """return the solution to f in the range between x0 and x1""" while x1-x0&

*如果你在胡吉做介绍,要小心。。。 我知道你为什么来这里*

我试图构建一个函数,它以一个函数(假设单调的连续性)作为参数,并返回它的反函数。 从数学上我知道我需要将函数反映到
y=x
。 但这并不顺利

我写了一些东西,它将给我
x0
,使
f(x0)=0

def solve(f, x0=-10000, x1=10000, epsilon=EPSILON):
"""return the solution to f in the range between x0 and x1"""

while x1-x0>EPSILON:

    if (f(x0)*f((x1+x0)/2))<0:
        x1=((x1+x0)/2)
    elif (f(x0)*f((x1+x0)/2))>0:
        x0=((x1+x0)/2)
    elif (f(x0)*f(x1))==0:
        if f(x0)==0:
            return x0
        else:
            return x1
if f(x0)*f(x1)<0:
    return (x1+x0)/2
else:
    return None

我建议先进行小范围的研究,而不是指数级的扩展。如果使用[-1,1]、-2,2]、-4,4]等范围,即使在最坏的情况下,开销也会保持不变。

没有代数表达式
y=f(x)

dx=0.0001 // or dx=function(|f(x0),f(x0+0.0001)|)
if (|f(x0-dx)-y|<|f(x0+dx)-y|) dx=-dx;
无法知道实际的
x
y
间隔

如您所述,您只需要连续和单调的间隔

因此,如果你不知道,你可以尝试寻找极值点(一阶导数与零交叉的地方),通过一些搜索,动态步长取决于导数值(线性或对数),但总有丢失一些小凸起的风险。如果创建这些点的列表,则它们之间的间隔应该是单调的。在此之后,如果
x=g(y)
是函数,则可以使用二进制搜索。如果存在小凸起,则更好

对于无约束单调函数
y=f(x)

dx=0.0001 // or dx=function(|f(x0),f(x0+0.0001)|)
if (|f(x0-dx)-y|<|f(x0+dx)-y|) dx=-dx;
您可以将近似搜索从上面的链接更改为以下内容:

  • 初步猜测

    x0=0
    
    如果没有更多关于
    g,f
    的信息,我们将无能为力。如果
    x0=0
    不是选项,请使用任何其他安全值

  • 检测搜索步骤
    dx

    dx=0.0001 // or dx=function(|f(x0),f(x0+0.0001)|)
    if (|f(x0-dx)-y|<|f(x0+dx)-y|) dx=-dx;
    
    在最近的比赛中停下来。如果需要动态步骤,则还需添加
    dx=函数(| f(x0),f(x0+0.0001)|)
    内部循环

  • 现在您已绑定搜索

    dx=0.0001 // or dx=function(|f(x0),f(x0+0.0001)|)
    if (|f(x0-dx)-y|<|f(x0+dx)-y|) dx=-dx;
    
    所以你们可以按原样从上面的链接使用二进制近似搜索

  • 如果未找到足够接近的解决方案

    然后,您会遇到一些遗漏的凹凸,或者步长过大,或者初始猜测点是具有对称函数形状的极值点,从而导致初始方向估计失败。因此,您可以更改初始
    x0
    常数


  • 我刚刚发布了一个python包,它正好做到了这一点,并且必须经历许多警告。您可能想从中借用一些想法:

    它基本上遵循这一战略:

  • 找出函数是增加还是减少。为此,需要两个参考点ref1和ref2:
    • 在有限间隔的情况下,点参考点为间隔的1/4和3/4
    • 在无限的时间间隔内,任何两个值都能起作用
    • 如果f(ref1)
  • 找出区间中函数的图像。
    • 如果提供了值,则使用这些值
    • 在闭合区间中,只需计算f(a)和f(b),其中a和b是区间的端点
    • 在开放区间中,尝试计算f(a)和f(b),如果这有效,则使用它们,否则将假定为(-Inf,Inf)
  • 使用以下条件构建有界函数:
    • 有界f(x):
      • 如果x低于间隔,且f增加,则返回-Inf
      • 如果x低于间隔,且f减小,则返回+Inf
      • 如果x大于间隔,且f增加,则返回+Inf
      • 如果x大于间隔,且f减小,则返回-Inf
      • 否则返回f(x)
  • 如果反转所需的数字y0在图像之外,则引发异常
  • 通过使用
    Brent
    方法最小化(有界的_f(x)-y0)**2,找到有界的_f(x)-y0的根,通过将ref1、ref2设置为括号,确保最小化算法从原始间隔内的一个点开始。一旦if超出允许的区间,bounded_f返回无穷大,迫使算法返回到区间内搜索
  • 检查解决方案是否准确,是否满足f(x0)=y0的某些期望精度,否则会发出警告
    多次执行相同的函数调用是低效的;Python不会为您优化这些。你可以从维基百科上的文章中获得一些改进代码的想法。FWIW,要进行函数反演,你可以使用牛顿法,或是与之密切相关的方法。对于括号内的更快的方法,使用regula-falsi-假位置法,并进行伊利诺伊州反失速修正。它比二分法快得多,只比相关的割线法慢一点。嗨,Spektre!我按照你的要求做了,把它写下来,并更新成问题。谢谢。