检查字符串是否包含在语言中(Prolog)

时间:2016-04-25 15:25:21

标签: prolog context-free-grammar dcg

这是CFG:

S -> T | V
T -> UU
U -> aUb | ab
V -> aVb | aWb
W -> bWa | ba

所以这将接受某种形式:

{a^n b^n a^m b^m | n,m >= 1} U {a^n b^m a^m b^n | n,m >= 1}

以下是我正在使用的代码:

in_lang([]).  
in_lang(L) :-
    mapS(L), !.

mapS(L) :-
    mapT(L) ; mapV(L),!.

mapT(L) :-
    append(L1, mapU(L), L), mapU(L1), !.

mapU([a|T]) :-
    ((append(L1,[b],T), mapU(L1)) ; (T = b)),!.

mapV([a|T]) :-
    ((append(L1,[b],T), mapV(L1)) ; 
     (append(L1,[b],T), mapW(L1))),
    !.

mapW([b|T]) :-
    ((append(L1,[a],T), mapW(L1)) ;
     (T = a)),
    !.

截至目前,对于以下三个字符串,这将返回false:

[a,a,b,b,a,b] // this should be true
[a,a,a,b,b,a,a,b,b,b] // this should be true as well
[a,a,a,b,b,a,b,b,b] // this one IS false

任何帮助或见解都会非常感激,我对Prolog不太满意,所以自己调试这个是一个挑战。

3 个答案:

答案 0 :(得分:6)

只需使用!并library(double_quotes)

:- set_prolog_flag(double_quotes, chars).

s --> t | v.
t --> u, u.
u --> "a",u,"b" | "ab".
v --> "a",v,"b" | "a",w,"b".
w --> "b",w,"a" | "ba".

| ?- use_module(library(double_quotes)).

| ?- length(L,N), phrase(s, L).
L = "abab", N = 4 ? ;
L = "abab", N = 4 ? ;
L = "aabbab", N = 6 ? ;
L = "abaabb", N = 6 ? ;
L = "aababb", N = 6 ? ;
L = "abbaab", N = 6 ? ;
L = "aaabbbab", N = 8 ? ;
L = "aabbaabb", N = 8 ? ;
L = "abaaabbb", N = 8 ? ;
L = "aaababbb", N = 8 ? ...

答案 1 :(得分:1)

mapT的定义中,您尝试使用mapU的“返回值”作为append的参数。但是mapU是一个谓词,而谓词没有返回值。

相反,通常使用未绑定变量编写谓词,谓词绑定到所需的“返回值”;在证明了preciate之后,现在绑定的变量可以用在后续谓词中。

答案 2 :(得分:1)

首先,请注意此代码没有意义:

... append(L1, mapU(L), L) ...

在Prolog中有谓词,而不是函数......

CFG制作规则(非终端)应该“吃”'许多令牌,在Prolog中,这意味着您至少需要2个参数:输入令牌列表,以及生产成功匹配输入的相关部分后剩余的参数。

也就是说,不需要追加/ 3:只是模式匹配,由统一运算符执行(=)/ 2

mapS(L1, L) :- mapT(L1,L) ; mapV(L1,L).
mapT(L1, L) :- mapU(L1,L2), mapU(L2,L).
mapU(L1, L) :- L1=[a|L2], mapU(L2,L3), L3=[b|L] ; L1=[a,b|L].
... complete the translation

然后调用它:

?- mapS([a,a,b,b,a,b],R).
R = [] ;
false.

R = []表示整个序列已匹配...