计算机编程符号问题的艺术

时间:2009-02-19 18:14:27

标签: notation taocp

我刚刚开始阅读TAOCP第1卷,我无法理解风格。

Knuth提到一种计算方法是四倍(Q,I,Omega,f) - 但我无法理解每种方法的意图。我理解他的第一个例子,但不明白他的第二个

我正在看第三版的第8页。


在本章的最后,有一个算法来讨论字符串集。

(我已经用一些更容易输入的希腊变量替换了 - 抱歉)

设A是一组有限的字母,让A *为A上所有字符串的集合。 我们的想法是对计算的状态进行编码,使它们由A *

的字符串表示
Q = (s,j) where s is in A* and j is an integer, 0 <= j <= N 
I = subset of Q with j = 0
Omega = subset with j = N
f = function below  

(请注意,p&amp; w是字符串) 如果和S是A *中的字符串,我们说如果s的字符串形式为字符串p和w的pTw,则T出现在s中。

f(s,j) = (s,aj)             if Tj does not occur in s;
f(s,j) = (pYjw,bj)   if p is the shortest possible string for which s = pYjw
f(s,N) = (s,N)

我理解制作字符串集的概念,但不理解他试图在这里说的所有。为什么我需要Q,I,Omega?真正向我解释的是什么(为什么我需要在f中使用3个函数?)??

任何人都可以帮忙解决一些问题吗?

5 个答案:

答案 0 :(得分:14)

Q =一组状态(以便(s, j)代表s时的状态j I =初始状态(因此要求j == 0
Omega =最终状态(因此要求j == N
f =过渡功能

此外,没有三个名为f的函数,而是f由三个方程式分段定义。

答案 1 :(得分:11)

为了完整披露,我最近wrote an article了解了Knuth(前例)对算法的正式定义。下面的大部分内容只是文章中相关文字的复制/粘贴,深入回答了您的第一个问题;

关于(Q,I,Ω,f)的第一个问题


  

让我们正式定义一个四倍的计算方法(Q,I,   Ω,f),其中Q是包含子集I和Ω的集合,f是a   从Q到自身的功能。

当Knuth将计算方法称为四元组时,他只是说计算方法由四个明确定义的部分组成。他将这四个部分标记为(Q, I, Ω, f)。然后他继续简要描述这个四重奏的每个组成部分。 I是集合(事物集合),Q也是一个集合,其中包含集合I中的内容。在这一点上,很容易错误地认为他意味着Q仅包含集合I而没有其他内容。但我们后来发现事实并非如此。最后,他将f描述为Q自身的函数。这意味着f是一个进程,它接受来自集合Q的元素的输入,并从Q返回或输出另一个元素。

  

此外f应保持Ω点固定;也就是说,f(q)应该   等于q的所有元素q。

这实质上意味着,如果参数是(thing in)set 的成员或元素,我们的函数f返回的内容将与其参数相同(即值不会改变) 。当Knuth在他的下一个声明中作出澄清时,这更有意义;扰流器警报 - 是我们的计算方法的可能输出集。一旦我们知道这一点,就会更容易理解。将输出传递回我们的函数不会改变它。

  

四个量Q,I,Ω,f分别用于表示   计算的状态,输入,输出和   计算规则。

因此Q是一个包含计算的所有可能状态的集合,即输入,输出和其间所有阶段的所有可能变化。集I包含所有可能的输入。集包含所有可能的输出(对不起,如果我之前为你破坏了这个启示)。最后,f代表计算规则;也就是说,进程/ es应用于每个状态以获得下一个状态,最终(希望)直到我们获得输出。


为了澄清,f表示单个函数,其具有基于其可能输入定义的输出。在此特定示例中,它只有三个可能的输出,并且在其他算法中可能有更多(或更少)。那么,以这种方式定义算法组件的目的是什么呢?通过使用正式表示法定义它们,它们也可以在分析特定算法时进行分析并进行数学检验。

关于将算法作为一组字符串处理的问题

我回答another question on this subject here。但基本上Knuth在这里所做的就是使用Markov's algorithm来实现他已经描述的内容。值得研究(并通过几个例子)Markov算法来帮助您准确理解这里发生的事情。

参考

  1. Markov's Algorithms Wiki
  2. My Defining an Algorithm article.
  3. Knuth the art of computer programming ex 1.1.8

答案 2 :(得分:1)

我不是100%肯定,但看起来Q是0&lt; = J&lt; = N的所有有序对(s,j)的集合。这将是你的域。它是给定N和字符串s的所有可能状态的集合。

我是Q的子集,其中所有有序对包含J = 0或初始状态。 Omega是Q的子集,其中所有有序对包含J = N或最终状态。

f是域Q的实际功能。

修改

将函数定义视为一个函数的行,但不同的情况取决于给定的输入。想想你会用一种语言写的函数。例如:

tuple f(string s, int i)
{
    if (Tj not in s)
        (s, aj)
    else if ( p is shortest possible length such that s = pYjw)
        (pYjw,bj)
    else if ( i == N )
        (s, N)
}

另一个例子是Fibonacci function definition。看看如何定义? 有意义吗?

答案 3 :(得分:1)

如果你已经阅读了他在书中早些时候提到的euclid的gcd算法。我们的想法是将每次迭代的开始标记为初始阶段,然后定义将在一次循环迭代(即N)中出现的状态数。现在你会记得当m的余数除以n等于零时我们接受了答案并停止了计算。即我们正在搜索字符串Yj的特定事件。当计算机在循环中到达itz的最后阶段时,它必然会停止或重复。

答案 4 :(得分:1)

记住我们正在定义一种计算方法&#39;而不是算法。什么是天真的计算方法?

  

a&#34;程序&#34;除了可能缺乏有限性之外,它具有算法的所有特征,可以称为计算方法。

简单地说Q是一种计算方法。

Q = {all possible states of computations, I, Ω}
I = {all possible inputs}
Ω = {all possible outputs}
f = computational rule

f是Q中的一个函数。

f: Q  --->  Q
  [I]      [Ω]

f应该保留Ωpointwise,这意味着:

  

f(q)= q,∀q∈Ω   请注意,它不是任何不同的功能,但相同的计算规则只是分开到Ω

现在一个程序将有一个序列。显然,计算方法也必须有一个序列。 因此,

  

集合I中的每个输入x定义计算序列x 0 ,x 1 ,x 2 ,...,如下:                                                                           对于k≥0,x 0 = x且x k + 1 = f(x k )。

x 0 = x? 不要忘记输入x是一个序列,因此初始输入序列将是x 0 。 当我们正在处理一个序列时,当我们关注&#39; k&#39;状态,序列中元素的顺序和位置很重要。因此,计算规则f使得位置或更精确的单词状态为&#39; k th 元素的结果为k + 1 th 状态。 这样,我们可以将函数单独应用于每个新状态以获得后面的状态。

如果x k + 1 不在Ω中,则根据函数的定义没有意义。因此,Knuth的措辞。

  

如果k是x k 为Ω的最小整数,则称计算序列以k步结束,并且在这种情况下,据说产生输出x k 来自x。

因此,这是计算方法的定义。计算规则就是算法。