是否发现两个函数的等价性是不可判定的?

时间:2009-07-15 15:15:35

标签: math compiler-construction function computer-science theory

难道不可能知道两个函数是否相同吗?例如,编译器编写者想要确定开发人员编写的两个函数是否执行相同的操作,他可以​​使用哪些方法来计算出那个函数?或者我们可以做些什么来找出两个TM是相同的?有没有办法规范机器?

编辑:如果一般情况是不可判定的,那么在你能正确地说两个函数是等价的之前,你需要多少信息?

9 个答案:

答案 0 :(得分:45)

给定一个任意函数 f ,我们定义一个函数 f',它在输入 n 上返回 1 如果 f 在输入 n 上停止。现在,对于某些数字 x ,我们定义了一个函数 g ,在输入 n 上,如果 1 > n = x ,否则调用f'(n)。

如果函数等价是可判定的,那么判断 g 是否与 f'相同决定 f 是否在输入 x <上停止/ em>的。这将解决Halting problem。与此讨论相关的是Rice's theorem

结论:功能对等是不可判断的。


下面有一些关于此证明有效性的讨论。因此,让我详细说明证明的作用,并在Python中给出一些示例代码。

  1. 证明创建一个函数 f',它在输入 n 开始计算 f(n)。当这个计算完成时,f'返回1.因此, f'(n) = 1 iff f 在输入 n 上停止,并且 f 没有,则 不会停在 n 上。的Python:

    def create_f_prime(f):
        def f_prime(n):
            f(n)
            return 1
        return f_prime
    
  2. 然后我们创建一个函数 g ,它将 n 作为输入,并将其与某个值 x 进行比较。如果 n = x ,那么 g(n)= g(x)= 1 ,否则 g(n)= f'(n) 。的Python:

    def create_g(f_prime, x):
        def g(n):
            return 1 if n == x else f_prime(n)
        return g
    
  3. 现在的诀窍是,对于所有 n!= x ,我们有 g(n)= f'(n)。此外,我们知道 g(x)= 1 。因此,如果 g = f',则 f'(x)= 1 ,因此 f(x)停止。同样,如果 g!= f'那么必然 f'(x)!= 1 ,这意味着 f(x)不会停止。因此,决定 g = f'是否等同于决定 f 是否在输入 x 上暂停。对上述两个函数使用略有不同的表示法,我们可以总结如下:

    def halts(f, x):
        def f_prime(n): f(n); return 1
        def g(n): return 1 if n == x else f_prime(n)
        return equiv(f_prime, g) # If only equiv would actually exist...
    
  4. 我还将在Haskell中对证明进行说明(GHC执行一些循环检测,我不确定在这种情况下seq的使用是否是万无一失的,但无论如何):

    -- Tells whether two functions f and g are equivalent.
    equiv :: (Integer -> Integer) -> (Integer -> Integer) -> Bool
    equiv f g = undefined -- If only this could be implemented :)
    
    -- Tells whether f halts on input x
    halts :: (Integer -> Integer) -> Integer -> Bool
    halts f x = equiv f' g
      where
        f' n = f n `seq` 1
        g  n = if n == x then 1 else f' n
    

答案 1 :(得分:7)

是的,这是不可判定的。这是halting problem的一种形式。

请注意,我的意思是一般情况下它是不可判定的。正如您可以确定停止足够简单的程序一样,您可以确定足够简单的函数的等效性,并且这对于应用程序来说可能是有用的并不是不可想象的。但是你不能用一般方法来确定任何两个可能函数的等价性。

答案 2 :(得分:4)

赖斯定理的一般情况是不可判定的,正如其他人已经说过的那样(莱斯的定理基本上说,图灵完全形式主义的任何重要属性都是不可判定的)。

有些特殊情况下等价是可判定的,最着名的例子可能是有限状态自动机的等价。如果我记得正确的下推自动机的等价性已经因为减少到Post的通信问题而变得不可判断。

为了证明两个给定的函数是等价的,你需要输入一些形式主义的等价证明,然后你可以检查它是否正确。此证明的基本部分是循环不变量,因为这些不能自动导出。

答案 3 :(得分:2)

在一般情况下,对于相同的输入,两台图灵机是否始终具有相同的输出是不可判定的。既然你甚至无法决定tm是否会停止输入,我看不出应该如何判断是否都停止并输出相同的结果......

答案 4 :(得分:2)

这取决于你所说的“功能”。

如果你所谈论的函数被保证终止 - 例如,因为它们是用所有函数终止的语言编写的 - 并且在有限域上运行,那么它很“容易”(尽管它可能仍然需要非常非常长的时间):当且仅当它们在共享域中的每个点具有相同值时,两个函数是等效的。

这被称为“拉伸”等价,以区别于句法或“内涵”等价。如果两个函数在内涵上是等价的,那么这两个函数在扩展上是等价的,但反之则不成立。

(上述所有其他人都注意到在一般情况下它是不可判定的是非常正确的,当然,这是一种相当罕见的 - 在实践中通常是无趣的 - 特殊情况。)

答案 5 :(得分:2)

请注意,对于线性有界自动机,暂停问题是可判定的。真正的计算机总是受限制的,并且在完成很多步骤之后,它们的程序将始终循环回到先前的配置。如果您使用无界(虚构)计算机来跟踪配置,您可以检测到该循环并将其考虑在内。

答案 6 :(得分:0)

您可以检查编译器以确定它们是否“完全”相同,但确定它们是否返回相同的值将是困难且耗时的。您必须基本上调用该方法并在无限次可能的调用上执行其例程,并将该值与其他例程中的值进行比较。

即使您可以执行上述操作,也必须考虑函数中的全局值变化,在函数中销毁/更改哪些对象不会影响结果。

你真的只能比较编译的代码。那么编译编译后的代码来重构?

想象一下尝试用“那个”编译器编译代码的运行时间。你可以花很多时间在这里回答问题:“忙于编译......”:)

答案 7 :(得分:0)

我认为如果你允许副作用,你可以证明问题可以变成Post correspondence problem,所以你通常不能证明两个函数是否具有能力具有相同的副作用。

答案 8 :(得分:0)

  

是否无法知道两个函数是否相同?

没有。可以知道两个函数是等价的。如果你有f(x),你就知道f(x)相当于f(x)。

如果问题是“有可能确定f(x)和g(x)是否等价于f和g是否为任何函数,对于所有函数g和f”,则答案为否。

但是,如果问题是“编译器是否可以确定f(x)和g(x)是否相等,它们是等效的?”,那么如果它们在输出和副作用方面都是等效的,那么答案是肯定的。副作用的顺序。换句话说,如果一个是另一个保留行为的转换,那么具有足够复杂性的编译器应该能够检测到它。它还意味着编译器可以在给定特定等效定义的情况下将函数f转换为更优等等函数。如果f包含未定义的行为,它会变得更有趣,因为g还可以包含未定义(但不同)的行为!