请在这件事上与我同在。我首先要描述书中的一个例子,然后在最后提出我的问题。

根据有关编程语言范例的文字:



自上而下的定义:

当且仅当自然数n在S中

  • n = 0或
  • n -3∈S.

  • 我们知道0∈S。因此3∈S,因为(3 − 3)= 0且
    0∈S。类似地6∈S,因为(6−3)= 3和3∈S。
    可以得出结论:3的所有倍数都在S中。

    那其他自然数呢? 1∈S?我们知道1!= 0,所以
    第一个条件不满足。此外,(1-3)= -2,这不是自然的
    数字,因此不是S的成员。因此,第二个条件
    不满意。

    自底向上定义:

    将集合S定义为N中包含的最小集合,并满足
    以下两个属性:
  • 0∈S和
  • 如果n∈S,则n +3∈S。

  • “最小集合”是满足属性1和2的集合,即
    满足属性1和2的任何其他集合的子集。
    只能有一个这样的集合:如果S1和S2都满足属性1和
    2,且两者均最小,则S1⊆S2(因为S1最小)和S2⊆S1
    (由于S2最小),因此S1 = S2。我们需要这种额外条件,因为
    否则,有很多满足其余两个条件的集合

    推理规则:
    _____
    0 ∈ S
    
    n ∈ S
    ---------
    (n+3) ∈ S
    

    这只是该定义的先前版本的简写形式。
    每个条目都称为推理规则,或仅称为规则。水平
    行被视为“if-then”。线上方的部分称为假设
    或先行者;或线下的部分称为结论或结果。
    当列出两个或多个假设时,它们通过
    隐式的“和”

    现在是问题了。
  • 可能最重要的问题是,为什么我需要知道这些归纳定义,它们在实际情况下如何有用?
  • 为什么Google几乎没有归纳定义返回任何结果?
  • 如果自上而下,自下而上和推理规则本质上显示相同的内容,为什么我们需要3种编写相同内容的方式?
  • 为什么我很难找到关于问题的归纳定义,而这些归纳定义比本书的示例要复杂一些,例如以下示例。

  • 我想找到以下两个问题的自上而下,自下而上和自卑的定义。您不必给我答案,但是我确实想知道如何得出归纳定义。我从哪里开始?是否有系统的方法来解决这类问题?
    1. {2n+3m +1 | n,m ∈ N}
    2. {(n, 2n+1) | n ∈ N}
    

    最佳答案

    您在这里提出了很多问题,因此希望此答复能回答所有这些问题。如果您想澄清什么,请告诉我。

    您的第一个问题-为什么我们需要归纳定义? -最容易回答。在计算机科学中,大量结构是归纳定义的。例如,您的简单链表具有归纳定义

  • 空列表是一个链接列表。
  • 链表后面的单个节点是链表

  • 或二叉树:
  • 空树是二叉树。
  • 具有两个作为二叉树的子节点的节点是二叉树。

  • 或正则表达式:
  • ∅是一个正则表达式。
  • ε是一个正则表达式。
  • a是每个字符
  • 的正则表达式
  • 如果R1和R2是正则表达式,则R1 | R2是一个正则表达式。
  • 如果R1和R2是正则表达式,则R1 R2是正则表达式。
  • 如果R为正则表达式,则R *为正则表达式。
  • 如果R是一个正则表达式,则(R)是一个正则表达式。

  • 这些定义具有许多不错的属性。首先,它们适合于递归算法。如果要访问二叉树中的每个节点,我们可以使用二叉树的归纳定义来构建一个简单的访问算法:
  • 要访问空树,请勿执行任何操作。
  • 要访问由一个节点和两个子树组成的树:
  • 访问节点
  • 访问左侧子树
  • 访问正确的子树

  • 类似地,如果我们要操纵正则表达式的结构(例如,可能要为其构建匹配的自动机),则归纳定义使我们可以逐段从正则表达式中构建自动机。

    归纳定义也可以用于形式证明结构的性质。例如,这是AVL树的正式定义:
  • 单个节点是0阶
  • 的AVL树
  • 具有一个或两个 child 的节点,这些节点是0阶的AVL树,是1阶的AVL树。
  • 有两个子节点(分别为n-1阶的AVL树)或具有一个子节点(即n-1阶的AVL树)和另一个子节点(即n-3阶的AVL树)的节点是n阶的AVL树。

  • 使用此定义,可以正式证明AVL树是平衡的。

    我们可以类似地使用这些定义来证明有关编程语言的属性。大多数语言都有某种归纳定义,因此通过证明程序的每个部分都保留了一些信息,我们可以从头开始建立正确性证明。

    您的第二个问题-Google为什么不提供任何归纳定义示例? -我认为是因为它将其解释为“定义归纳”,而不是术语本身。如果您查找递归定义,那么您会发现很多归纳定义的示例,因为归纳定义和递归定义彼此非常相似。

    您的第三个问题-为什么我们需要多种表达同一事物的方式? -也很容易。如果您想证明有关系统的某些知识,则归纳定义非常有用。如果证明它适用于基本元素,然后证明较大的元素保留了该属性,则可以证明它始终是正确的。递归定义对于编写程序很有用,因为递归函数倾向于向后运行归纳。推理规则与逻辑证明系统相关联,并为使用经典逻辑证明系统属性提供了起点。

    您的第四个问题-为什么找不到任何示例? -只需花一点时间查看一下您所了解的经典数据结构和算法,即可轻松解决该问题。您可以归纳定义多少个数据结构?尝试查看链接列表,二叉树,红黑树,AVL树等以获取启发。您将如何定义图形? DAG?同样,尝试查看语法结构。例如,如何归纳定义平衡括号内的字符串? C语言中的函数原型(prototype)怎么样?

    您的最后一个问题-是否有系统的方法来解决这些问题? -答案是否定的。您可以定义与在输入上模拟任意图灵机等效的重复发生,并且由于无法确定暂停问题,因此没有解决此类问题的通用程序。但是,确实存在许多方法。尝试查看Graham,Knuth和Patashnik撰写的“具体数学”,以获取有关如何通过重复进行工作的灵感。

    希望这可以帮助!

    09-27 11:13