查找有限自动机接受的至少一个偶数长度的单词

时间:2019-05-14 13:26:18

标签: prolog

我有一个自动机。 这里的问题是:如何找到给定的有限自动机接受的至少一个偶数长度的单词?

states      /* states(Q) <=> Q is the list of automata's states */
symbols     /* symbols(Sigma) <=> Sigma is the list of automata's input symbols */
transition  /* transition(X, A, Y) <=> δ(X, A)=Y */
startState  /* startState(S) <=> S is the start state of automata */
finalStates /* finalStates(F) <=> F is the list of automata's final states */


states([q0, q1, q2]).
symbols([a, b]).
transition(q0, a, q1).
transition(q0, b, q2).
transition(q1, a, q2).
transition(q1, b, q0).
transition(q2, a, q1).
transition(q2, b, q2).
startState(q0).
finalStates([q2]).

1 个答案:

答案 0 :(得分:1)

您似乎已经在Prolog中成功编码了自动机。您实际上缺少的是执行它的代码。因此,让我们考虑一下这样做的必要性。首先,我们需要通过将输入传递给运行的东西来开始执行。第一件事将找到开始状态并使用它。然后,我们将运行一个循环,查找此状态以及下一个输入值和下一个状态的过渡。如果我们用光了输入并处于最终状态,那么我们就成功了。因此,似乎第一个调用的唯一特别之处在于它查找了初始状态。

以真正的归纳方式,让我们先写终止条件。

step(State, []) :- finalStates(FinalStates), memberchk(State, FinalStates).

这只是说,如果我们在输入不足的情况下尝试执行某个步骤,则所处的状态将在最终状态列表中。现在,让我们尝试运行不是最后一步的步骤。我们将递归调用step/2来实现循环。

step(State, [Sym|Tape]) :-
    transition(State, Sym, NextState),
    step(NextState, Tape), 
    !.

这只是剥离磁带上的下一个符号,并根据它找到正确的下一个状态,然后重复执行。我在此处添加了剪切,以防止其尝试查找其他过渡。如果您要建立NFA,则可能要删除它。现在我们缺少的是初始驱动程序,我将其称为评估:

evaluate(Tape) :-
    startState(Start),
    step(Start, Tape).

让我们在一些输入上尝试一下:

?- evaluate([a,a,a,a]).
true.

之所以成功,是因为它从q0-> q1-> q2-> q1-> q2过渡并且q2是最终状态。

?- evaluate([a,a,a]).
false.

此操作失败,因为它是从q0-> q1-> q2-> q1过渡而q1不是最终状态。

现在继续查找匹配的字符串。因为手头上有一组符号,所以我们可以很容易地生成它们。让我们做一个辅助谓词:

symbol(X) :- symbols(Symbols), member(X, Symbols).

这是我们可以方便地与maplist/2一起使用来生成示例输入的内容:

?- length(L, 3), maplist(symbol, L).
L = [a, a, a] ;
L = [a, a, b] ;
L = [a, b, a] ;
L = [a, b, b] ;
L = [b, a, a] ;
L = [b, a, b] ;
L = [b, b, a] ;
L = [b, b, b].

现在,您可以使用Prolog进行经典的生成和测试:

?- length(L, 3), maplist(symbol, L), evaluate(L).
L = [a, a, b] ;
L = [a, b, b] ;
L = [b, a, a] ;
L = [b, b, b].

要找到有效的符号偶数列表,请使用辅助函数查找偶数,我们将使用between/3生成这些长度的列表,然后执行相同的操作:

even(X) :- 0 is X mod 2.

尝试:

?- between(1,100,X), even(X).
X = 2 ;
X = 4 ;
X = 6 ;
X = 8 .

?- between(1,100,X), even(X), length(L, X).
X = 2,
L = [_2954, _2960] ;
X = 4,
L = [_2954, _2960, _2966, _2972] ;
X = 6,
L = [_2954, _2960, _2966, _2972, _2978, _2984] .

?- between(1,100,X), even(X), length(L, X), maplist(symbol, L).
X = 2,
L = [a, a] ;
X = 2,
L = [a, b] ;
X = 2,
L = [b, a] ;
X = 2,
L = [b, b] ;
X = 4,
L = [a, a, a, a] ;
X = 4,
L = [a, a, a, b] ;
X = 4,
L = [a, a, b, a] ;
X = 4,
L = [a, a, b, b] ;
X = 4,
L = [a, b, a, a] ;
X = 4,
L = [a, b, a, b] ;
X = 4,
L = [a, b, b, a] ;
X = 4,
L = [a, b, b, b] ;
X = 4,
L = [b, a, a, a] .

?- between(1,100,X), even(X), length(L, X), maplist(symbol, L), evaluate(L).
X = 2,
L = [a, a] ;
X = 2,
L = [b, b] ;
X = 4,
L = [a, a, a, a] ;
X = 4,
L = [a, a, b, b] ;
X = 4,
L = [a, b, a, a] ;
X = 4,
L = [a, b, b, b] ;
X = 4,
L = [b, a, a, b] ;
X = 4,
L = [b, a, b, b] ;
X = 4,
L = [b, b, a, a] ;
X = 4,
L = [b, b, b, b] ;
X = 6,
L = [a, a, a, a, a, a]