Prolog 找到至少一个被有限自动机接受的偶数长度的字

Prolog 找到至少一个被有限自动机接受的偶数长度的字,prolog,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) <=&

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

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]).

看起来您已经成功地在Prolog中对自动机进行了编码。您实际上缺少的是执行它的代码。所以,让我们思考一下需要做些什么。首先,我们需要通过将输入传递给运行它的对象来启动执行。第一件事就是找到启动状态并使用它。然后我们将运行一个循环,查找此状态、下一个输入值和下一个状态的转换。如果输入用完并处于最终状态,那么我们就成功了。因此,第一个调用的唯一特殊之处似乎是它查找初始状态

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

step(State, []) :- finalStates(FinalStates), memberchk(State, FinalStates).
这只是说,如果我们在输入不足时尝试执行一个步骤,那么我们所处的状态就在最终状态列表中。现在,让我们尝试运行一个不是最后一步的步骤。我们将递归调用步骤/2来实现一个循环

step(State, [Sym|Tape]) :-
    transition(State, Sym, NextState),
    step(NextState, Tape), 
    !.
这只是剥离磁带上的下一个符号,并根据它找到正确的下一个状态,然后递归。我在这里添加了切口,以防止它试图找到其他过渡;如果你正在建立一个NFA,你可能想删除它。现在我们缺少的是初始驱动程序,我将其称为evaluate:

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不是最终状态

?- evaluate([a,a,a]).
false.
现在开始查找匹配的字符串。我们可以很容易地生成它们,因为我们手头有一套符号;让我们做一个小助手谓词:

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].
要找到有效的偶数符号列表,请创建一个用于查找偶数的助手,我们将使用/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] 

我试过这一个,但我有错评估[a,a,a,a]。我理解你写的所有东西,但它不起作用。我的任务不同。我需要检查自动机是否允许至少一个单词的长度为3的倍数。也许,我需要这样的倍数:-L mod 3=0 L-length@NastassiaBu我对答案进行了编辑,以展示您如何使用它来找到解决方案。我不知道为什么它对您不起作用,也许您需要制作一个新的控制台并再次粘贴代码?没关系。非常感谢。