为识别每个L

时间:2016-07-05 19:03:29

标签: diagram pushdown-automaton

试图理解PDA,但并不是真正掌握如何绘制它们。 首先,如果限制说#a,#b或#c大于零"那么我真的不明白PDA的外观会有什么不同。或者"大于或等于零。"我为每个教科书问题绘制了以下PDA图表。只想看看。

  1. 所以我的第一个PDA的逻辑是每个" a"输入,将有四个的倍数" a"移到了堆栈上。当一个" b"输入输入,每个" a"从堆栈中将导致一个空字符串,清除堆栈。
  2. 对于第二个PDA,我创建了一个非确定性的PDA,因为可以有零" a"或零" b"。因此,对于" bb"堆栈没有变化,因为可以有无数个" bb"但是" a"将被保留在堆栈上,因为它必须在" bb"之后再次被调用。如果有" a"。
  3. enter image description here

1 个答案:

答案 0 :(得分:2)

如果我正确理解你的图表,它们就不正确,似乎背叛了对PDA如何工作的基本误解。我将推出新的PDA并让您将它们与您尝试过的内容相协调,而不是试图与您一起理解您的思考过程。我不会提供图纸,但我会描述图纸的样子;我会提供表格,因为这些表格更容易呈现。

1)L = {a ^ i b ^ j |我> 0,j = 4i + 2}

当您制作任何自动机时,您正在尝试查找状态和过渡。一个好的开始就是想知道最初的状态,因为我们知道我们需要一个。它是我们唯一需要的,还是需要更多?它接受了吗?对于这种语言,我们可以看到它不接受(因为,如果初始状态正在接受,PDA将接受空字符串,因为我们要求i> 0,所以不能使用我们的语言)。由于我们的语言确实包含字符串,因此我们知道我们需要一个接受状态,因此我们知道至少需要两个状态。将它们称为初始状态q0,将q1称为我们知道我们需要的另一个状态。现在我们有几个状态,我们可以暂时关注第一次转换。

现在,我们知道我们需要在字符串的开头允许一些内容。实际上,我们必须要求至少一个。让我们思考一下这意味着什么。假设我们添加从q0到q0的转换接受a。如果我们没有把任何东西放在堆栈上,我们就会丢失有关我们是否看过任何内容的信息。但是,我们确实有一个堆栈,所以我们可以记住我们需要知道的东西:我们之前看过a。因此,我们可以在读取a时添加从q0过渡到q0的能力,并在堆栈上记录该事实。我们稍后需要能够检查堆栈以查看我们是否已经看到了一些问题。现在我们可以问一下我们将把什么放在堆栈上。

我们在这里有一些选择,没有正确或错误的答案。您选择的将取决于您依赖的自动机配方以及您对自动机的设计目标。是的,自动机的设计方式与真机或计算机程序相同。我们希望做出符合我们形式主义规则的设计选择,并且简单易用。一种方法是添加我们以后期望看到的与我们消耗的符号相对应的内容;对于我们现在看到的每一个,我们需要看到后来的四个;所以我们现在可以将bbbb添加到堆栈中,然后从堆栈中弹出一个b,从输入读取每个b。这很方便。请注意,当我们阅读第一个a时,我们可以处理" + 2"通过添加bbbbbb代替bbbb的要求,只要我们知道何时读取第一个a - 我们通过检查堆栈就知道了。

基于所有这些考虑因素,我们可以为我们设计的PDA生成部分表格,然后我们可以评估我们的进度,看看我们还有什么方向:

q    e    S    q'   S'
---  ---  ---  ---  ---
q0   a    Z    q0   bbbbbbZ
q0   a    b    q0   bbbbb

我们使用Z来表示堆栈的底部。当我们看到第一个a(我们知道它是第一个因为堆栈是空的,即最顶层的符号是表示堆栈底部的那个)时,我们添加了bbbbbb。每个连续的a将bbbb添加到堆栈的顶部(通过用bbbbb替换b)。

现在我们必须考虑如何处理b。我们可以通过从q0循环到q0来处理b吗?片刻的想法应该让你相信这不是一个好主意。如果我们在看到b时从q0循环到q0,那么我们就没有简单的工具阻止PDA接受进一步的接受。但这会产生一个字符串,不能用我们想要的语言,因为在我们的语言中,没有一个字母可以在b之后出现。因此,似乎有必要无论过渡接受b,都不要将状态q0作为其目标。因此,我们选择q1作为讨论过渡的目标。来源是什么?到目前为止,我们的PDA中只有q0,我们只有q0和q1可供选择。我们现在有两个选择:要么我们提供一种机制,可以在不看到b的情况下从q0转换到q1,或者我们提供了在b上转换的机制。第一种方法需要基于我们之前的设计选择的非决定性,因此我们可能更喜欢后者更明确,更容易推理。这导致了以下过渡(添加到我们上一个表格):

q    e    S    q'   S'
---  ---  ---  ---  ---
q0   a    Z    q0   bbbbbbZ
q0   a    b    q0   bbbbb
q0   b    b    q1   -

这个转换说当我们在q0中看到一个b并且我们在堆栈之前看到了一个之后,转换到q1并扔掉最顶层的堆栈符号。记住,我们设计堆栈的方式应该总是在输入中读取的每个b上丢弃一个b。

现在我们已经到达州q1,一个自然要问的问题是这个州是否应该接受。答案是它一定不能,否则我们可以接受一个字符串,但没有足够的b来清除它的堆栈;也就是说,我们会有j< 4i + 2.所以我们需要一个新状态,称之为q2,而q1将不会接受。我们应该用q1做什么?通过添加此转换,我们可以轻松地使用它来读取剩余的b并从堆栈中弹出:

q    e    S    q'   S'
---  ---  ---  ---  ---
q0   a    Z    q0   bbbbbbZ
q0   a    b    q0   bbbbb
q0   b    b    q1   -
q1   b    b    q1   -

只要我们在堆栈上阅读和b,就可以进行第四次转换。在此过程中可能会发生三件事:

  • 我们用完了b上的b,但输入中仍有b
  • 在我们读完输入中的所有内容的同时,我们在堆栈上用尽了b
  • 当输入用尽时,我们仍然在堆栈上有b

只有在第二种情况下我们才能接受,并且我们可以通过重复应用第四次转换来达到第二种情况。但是,q1不接受。因此,我们将需要一种从q1过渡到接受状态的方法 - 我们可以将q2称为这种状态 - 当我们可能在其中时。如果我们真的处于那种状态,当我们在q1中看到一个空堆栈时,我们需要一个epsilon转换:

q    e    S    q'   S'
---  ---  ---  ---  ---
q0   a    Z    q0   bbbbbbZ
q0   a    b    q0   bbbbb
q0   b    b    q1   -
q1   b    b    q1   -
q1   -    Z    q2   Z

现在,在q2中,我们可能处于1或2的情况:堆栈是空的,但是我们还有更多符号需要读取吗?事实证明,这不是问题,因为进一步的输入符号将导致PDA在状态q2中立即崩溃。

第二个是练习。