试图构建反函数

时间:2016-01-02 09:00:49

标签: python algorithm math

*如果你在huji做intro2cs要小心......    我知道你为什么在这里*

我正在尝试构建一个函数来获取函数(假设单调的连续性)作为参数并返回其反函数。 从数学我知道我需要将函数反映到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

问题是我不知道该功能的范围输入是什么。 我想我首先需要在小范围上工作,如果我找不到解决方案,我会以指数方式扩展范围。

有什么想法吗?

更新: 好的,所以我试着把它写成@Spektre建议,然后我成功了:

def inverse(g, epsilon=EPSILON):
    """return f s.t. f(g(x)) = x"""

    def helper(y):
        x0=-2
        x1=2
        while x1<10000:
            if solve((lambda x:g(x)-y),x0,x1,epsilon):
                return solve((lambda x:g(x)-y),x0,x1,epsilon)
            else:
                x0=math.pow(x0,3)
                x1=math.pow(x1,3)
    return helper

3 个答案:

答案 0 :(得分:1)

没有y=f(x)

的代数表达式

无法知道实际的xy间隔。

正如您所提到的,您只需要连续且单调的间隔

所以,如果你不知道它你可以尝试找到极值点(第一个推导交叉为零),一些搜索动态步骤依赖于推导值(线性或对数)但是总会有丢失的风险小颠簸。如果您创建这些点的列表,那么它们之间的间隔应该是单调的。在此之后如果x=g(y)功能正常,您可以使用二进制搜索。如果存在小凸起,那么approximation search会更好。

对于未绑定的单调函数y=f(x)

您可以将上面链接中的近似搜索更改为以下内容:

  1. 初步猜测

    x0=0
    

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

  2. 检测搜索步骤dx

    dx=0.0001 // or dx=function(|f(x0),f(x0+0.0001)|)
    if (|f(x0-dx)-y|<|f(x0+dx)-y|) dx=-dx;
    

    所以找到哪种方式更接近解决方案。应该以某种有意义的方式选择0.0001常量。太小会减慢过程太大会错过颠簸。对于动态步骤,您可以使用第一个推导的大小或解决方案本身的距离,例如dx=sign(dx)*abs(f(x)-y)以及dx==0是否停止......

  3. 搜索最接近的匹配

    while (|f(x0)-y|>|f(x0+dx)-y|) x0+=dx;
    

    停在最近的比赛上。如果您想要动态步骤,那么还要添加dx=function(|f(x0),f(x0+0.0001)|)内部循环

  4. 现在您绑定了搜索<x0-dx,x0+dx>

    所以你可以按照上面的链接使用二进制近似搜索。

  5. 如果找不到足够的解决方案

    然后你得到一些错过的颠簸或太大的步骤或初始猜测点是具有对称函数形状的极值点导致初始方向估计失败。因此,您可以更改初始x0常量。

答案 1 :(得分:1)

我刚刚发布了一个精确地执行此操作的python包,并且必须经历许多这些警告。你可能想借用它的一些想法: https://pypi.python.org/pypi/pynverse

它基本上遵循这一策略:

  1. 确定函数是增加还是减少。对于这两个参考点ref1和ref2是必需的:
    • 如果间隔有限,则点参考点在整个区间内为1/4和3/4。
    • 在无限的时间间隔内,任何两个值都可以正常工作。
    • 如果f(ref1)&lt; f(ref2),函数正在增加,否则正在减少。
  2. 计算出区间中函数的图像。
    • 如果提供了值,则使用这些值。
    • 在一个封闭的区间内,只计算f(a)和f(b),其中a和b是区间的末端。
    • 在开放时间间隔内尝试计算f(a)和f(b),如果这有效,则使用它们,否则将假定为(-Inf,Inf)。
  3. 使用以下条件构建有界函数:
    • bounded_f(X):
      • 返回 - 如果x低于间隔,并且f正在增加。
      • 如果x低于间隔,则返回+ Inf,并且f正在减小。
      • 如果x高于间隔,则返回+ Inf,并且f正在增加。
      • 返回 - 如果x高于间隔,则f正在减小。
      • 返回f(x)否则
  4. 如果反转所需的数字y0在图像之外,则引发异常。
  5. 通过最小化(bounded_f(x)-y0)** 2,使用Brent方法找到bounded_f(x)-y0的根,确保最小化的算法从原始内部的某个点开始通过将ref1,ref2设置为括号来设置间隔。只要超出允许的间隔,bounded_f就会返回无限,迫使算法返回到间隔内搜索。
  6. 检查解决方案是否准确并且它们满足f(x0)= y0到某个所需精度,否则会发出警告。

答案 2 :(得分:0)

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