具有不等变量的下推自动机

时间:2017-10-27 00:51:56

标签: pushdown-automaton

我无法想出一个成功接受以下内容的合适自动机:

当然任何数量的{a,b,c} *组成的字符串,但是 n(a) + n(b) != n(c)

最初,我已经将'x'分配给堆栈中的任何'a'或'b',并在遇到'c'时从堆栈中删除'x'。这将根据需要在两个状态之间循环。当然,在任何数量的c在a和b之前的情况下,这很复杂。我显然无法从空堆栈中删除。欢迎任何想法或建议!

2 个答案:

答案 0 :(得分:1)

这台PDA并非无足轻重。你必须使用两个分支(一个用于增量(A和B),一个用于减量(C))。诀窍是放置一个堆栈顶部标记并寻找这个标记。如果你按住它(不要在你的乐队上更进一步)切换分支并推动你的分支上的负片。

在下文中,我通过三重定义转换:(输入,弹出,推送)

例如:

  1. (A,ε,#)表示:从输入读取A,不弹出任何内容,将#推入堆栈
  2. (ε,#,B)表示:什么都不读(停在实际位置,在此步骤中不要再进一步),pop#,push B
  3. (AB,ε,X)表示:读取A或B并按下X
  4. 对于你的例子:

    S = starting state
    Q1 = "switch branches" state, from here the stack is empty and we move in the branch we need in dependend of the next character read from the input band.
    Q2, Q3 = States of the there-is-an-A-or-B-next branch
    Q4, Q5 = States of the there-is-a-C-next branch
    Q6 = State of acceptance (the only one. all other states are not accepting)
    

    现在转换:

    S -(ϵ,ϵ,#)-> Q1 ' # is our top-of-the-stack-marker
    
    ' first branch (for more As and Bs)
    Q1 -(AB,ϵ,+)-> Q2 ' for every A or B push a + sign on the stack
    Q2 -(AB,ϵ,+)-> Q2
    Q2 -(C,+,ϵ)-> Q3 ' for every C consume a + sign
    Q3 -(AB,ϵ,+)-> Q2
    Q3 -(C,+,ϵ)-> Q3
    Q3 -(ϵ,#,#)-> Q1 ' if we reach the top of the stack, return to the Q1 state
    Q2 -(ϵ,#,#)-> Q1
    Q2 -($,+,+)-> Q6 ' if the input is processed and the stack is not empty => go in the state of acceptance
    Q3 -($,+,+)-> Q6 ' if the input is processed and the stack is not empty => go in the state of acceptance
    
    ' second branch (for more Cs)
    Q1 -(C,ϵ,-)-> Q4 ' for every C push a - sign on the stack
    Q4 -(C,ϵ,-)-> Q4
    Q4 -(AB,-,ϵ)-> Q5 ' for every A or B consume a - sign
    Q5 -(AB,-,ϵ)-> Q5
    Q5 -(C,ϵ,-)-> Q4
    Q5 -(ϵ,#,#)-> Q1
    Q4 -(ϵ,#,#)-> Q1
    Q4 -($,-,-)-> Q6 ' if the input is processed and the stack is not empty => go in the state of acceptance
    Q5 -($,-,-)-> Q6 ' if the input is processed and the stack is not empty => go in the state of acceptance
    

    逻辑描述:

    我们在堆栈上按#-sign来检测堆栈的顶部。 现在我们在两个“区域”运营。与Cs相比,第一个区域处理A和B的正数,而另一个区域处理与Cs相比的As和B的负数。

    我们正在处理作为Stack的一部分的三个标志:

    1. '#= top marker
    2. '+ =有更多的As和Bs读取比Cs
    3. ' - =读取的Cs数量多于As或Bs
    4. 第一个转换是从开始状态到新的开始状态。此转换仅用于推动堆栈顶部标记的原因。永远不会再达到新的原始起始状态。 新的起始状态是开关,每当我们触及堆栈顶部标记时就会命中。从这个状态开始,我们将根据下一个A和B或C访问这些区域。

      我希望能够解释它。描述的自动机应该给你一个好主意。我认为它有一点错误,但是如果你按照这个想法做到了,那么你可以解决它:)

      我用在线模拟器构建描述的自动机来测试它。你可以找到它here。这个模拟器使用epsilon作为输入频段的初始化并且什么都不做......所以它有点令人困惑。我添加了一些可以通过单击“批量测试”旁边的绿色箭头运行的测试。

答案 1 :(得分:1)

我们可以尝试在某种程度上简化问题。你想要n(a) + n(b) != n(c)。在没有其他限制的情况下,这意味着就PDA而言ab是无法区分的;所以这个语言与n(a) != n(c)相同(如果我们让PDA假装ba s)。如果我们可以为这种简单的语言制作PDA,我们就完成了。

我们可能会问这个目标是确定性的还是任何PDA。并非所有无上下文的语言都具有确定性PDA,因此,一般而言,PDA指的是非确定性的PDA。如果我们假设这个问题很好,我们可以通过写下等效条件n(a) != n(c)来进一步简化条件n(a) < n(c) or n(a) > n(c)。这使我们的生活变得更加轻松,因为现在我们只需要为n(a) < n(c)提出一个PDA,然后我们就完成了:我们语言的PDA将不确定地分支到两个PDA,每个方向一个

那么我们如何获得n(a) < n(c)的PDA?好吧,我们可以从n(a) = n(c)的PDA开始,而不是接受没有输入和空堆栈,接受没有输入和堆栈表明ca更多n(a) = n(c)秒。用于n(c) - n(a)的PDA是什么样的?我们需要一个战略。诀窍是使用堆栈来跟踪运行差异n(c) - n(a) = 0,如下所示:

  • 如果Z,则堆栈为空,最顶部的符号为n(c) - n(a) > 0,即堆栈符号的底部。
  • 如果n(c) - n(a),则堆栈包含c的{​​{1}}个实例。
  • 如果n(c) - n(a) < 0,则堆栈包含n(a) - n(c)的{​​{1}}个实例。

要接受a,我们会先阅读n(a) = n(c)a s并消耗输入。然后,我们看到堆栈顶部有什么:

  • 如果堆栈为空,c(请参阅上面的第一个项目符号)
  • 如果堆栈顶部有n(a) = n(c)c(请参阅上面的第二个项目符号)
  • 如果堆栈顶部有n(a) < n(c)a(请参阅上面的第三个项目符号)

要接受n(a) > n(c),只要我们在堆栈顶部看到堆栈底部符号n(a) = n(c),我们就会以非确定方式转换为新的接受状态q

要接受Z,只要我们在堆栈顶部看到n(a) < n(c),我们就会非确定地转换为新的接受状态q。在这种情况下,如果要接受空堆栈,则可以清除处于接受状态的堆栈。

要接受c,只要我们在堆栈顶部看到n(a) > n(c),我们就会非确定地转换为新的接受状态q。在这种情况下,如果要接受空堆栈,则可以清除处于接受状态的堆栈。

观察我们可以一起处理an(a) < n(c);我们甚至不需要在前面进行不确定性的分支。这是刚刚描述的PDA的示例实现:

n(a) > n(c)

您需要像Q x s Q' s' /////////////////////// // count a // /////////////////////// q0 a Z q0 aZ q0 a a q0 aa q0 a c q0 e /////////////////////// // count c // /////////////////////// q0 c Z q0 cZ q0 c a q0 e q0 c c q0 cc /////////////////////// // move to accepting // /////////////////////// q0 e a q a q0 e c q c /////////////////////// // clear stack // /////////////////////// q e a q e q e c q e 一样为b添加转换规则,但ab无法区分,应该这样对待。< / p>

上表中的列如下:

  • a:转换源自的状态
  • Q:导致转换的输入字母表符号,如果转换不消耗输入,则为空字符串x
  • e:最顶层的堆栈符号
  • s:转换终止的状态
  • Q':在转换
  • 时替换最顶层的堆栈符号的内容

例如,行

s'

编码转换,可以描述如下:

  

从堆栈底部符号q0 a Z q0 aZ 的状态q0开始,使用输入符号Z并转换到状态a,推送{{ 1}}位于q0之上。