不动点理论和isGoodEnough函数

时间:2015-07-05 01:55:18

标签: scala computer-science fixed-point

在Coursera课程Functional Programming Principles in Scala中,讲师讨论了Fixed Point,并写了一些简单的实现。

def isCloseEnough(x: Double, y: Double) = 
    math.abs((x - y) / x) / x < tolerance

def fixedPoint(f: Double => Double)(guess: Double) = {

    def iterate(guess: Double): Double = {
        val next = f(guess)
        if (isCloseEnough(guess, next)) next
        else iterate(next)
    }
    iterate(guess)
}   

这样的实现将允许以下函数f(x) = 1 + x具有固定点。

然而,这不应该永远不会发生。 如在此函数图中:

enter image description here

这就是维基百科所说的:

  

并非所有函数都有固定点:例如,如果f是函数   在实数上定义为f(x)= x + 1,那么它没有固定的   点,因为对于任何实数,x永远不等于x + 1。

这里的重点在于isCloseEnough,我不知道为什么会这样写。

我在这里了解isCloseEnough及其实施方式 这就是全部。

1 个答案:

答案 0 :(得分:2)

该算法并不完美,显然取决于您对容差的选择。如果我们检查isCloseEnough

def isCloseEnough(x: Double, y: Double) = 
    math.abs((x - y) / x) / x < tolerance

它非常类似于:

| x - y | / x^2 < tolerance

除了由于某种原因它没有取x的外部分区的绝对值,这在x为负时完全打破了算法。

我们的想法是,我们通过找到任意关闭x的{​​{1}}找到一个固定点,即f(x)x之间的差异f(x)尽可能小(低于一些容差)。如果我们能够快速找到固定点,这种方法很好:

scala> fixedPoint(math.sqrt)(2)
res2: Double = 1.0000846162726942

此处,固定点为x = 1,其中math.sqrt(1) = 1。我用了tolerance = 0.0001。如果我使用较小的东西,我显然会更接近固定点1

但现在说我有:

def f(x: Double): Double = x + 1

scala> fixedPoint(f)(1)
res4: Double = 102.0

找到大约102.0的固定点。显然,这是错误的,但这是因为xf(x)之间的差异总是 1这个函数,并且x得到更大,1 / x^2越来越小,直到它低于tolerance。如果我让tolerance更小,我会找到一个更大的固定点。

val tolerance = 0.000000001

scala> fixedPoint(f)(1)
res5: Double = 31624.0

这显然也是错误的。但问题是,对于某些固定点,我应该能够使tolerance 任意小,并且仍能获得一致的结果。使用此功能,很明显,对于任何固定的tolerance,最终1 / x^2将小于它。 但是,对于任何x,我总是可以选择足够小的tolerance,以便1 / x^2总是落在它之外,所以没有固定点。

这不是一个数学证明,但重点是该算法存在某些标准的缺陷。