Handling prolog context free grammar

我的梦境 提交于 2019-12-10 19:33:25

问题


Given a CFG

S --> a S b | c | d

I wanna write a predicate like, grammar('S', sentence) which generates all possible

sentences like
sentence=acb,
sentence=acd,
sentence=c,
sentence=ab......................

Using left most derivation, if the encountered symbol is terminal it should print out that terminal, and if the encountered symbol is non terminal 'S', it should backtrack and substitute and one of the grammar a S b or c or d and repeat the process.

I dont want any code...just help me with some tips how to start with


回答1:


Let's use DCGs to encode your grammar literally!

s --> [a], s, [b] | [c] | [d].

?- phrase(s,Xs).
ERROR: Out of local stack

Seems that this query does not terminate. I.e. Prolog's very simple execution strategy did not find a solution. On the other hand, think of it: Your grammar describes an infinite set of sentences. If you are enumerating an infinite set it is easy to start "at the wrong end". That's what Prolog actually does here.

But things are not that bad at all. What about enumerating all sentences of a fixed length. I will try 5:

?- length(Xs,5), phrase(s,Xs).
Xs = "aacbb" ;
Xs = "aadbb" ;
false.

In this case, all sentences are found and Prolog even assures us that there are no further sentences.

?- length(Xs,4), phrase(s,Xs).
false.

There are no sentences of length 4.

We can now enumerate all sentences, by length.

?- length(Xs,N), phrase(s,Xs).
Xs = "c",
N = 1 ;
Xs = "d",
N = 1 ;
Xs = "acb",
N = 3 ;
Xs = "adb",
N = 3 ;
Xs = "aacbb",
N = 5 ;
Xs = "aadbb",
N = 5 ;
Xs = "aaacbbb",
N = 7

What kind of derivation did we use here? Honestly, I don't know and I don't care. What is important to know is when Prolog will terminate. In this case, it will terminate, if the length is known. And that is all we need to know to guarantee that we have a fair enumeration of the infinite set. Things are even slightly better: s//0 will also terminate in cases where the length is not known like

?- Xs = [a,a,b|_], phrase(s,Xs).
false.

?- Xs = [a,a,c|_], phrase(s,Xs).
Xs = "aacbb" ;
false.

?- dif(X,Y), Xs = [X,Y|_], phrase(s,Xs).
X = a,
Y = c,
Xs = "acb" ;
X = a,
Y = d,
Xs = "adb" ;
false.

Edit: I got some questions about the toplevel answers using "acb" for a list [a,c,b]: Please refer to this answer for an explanation and to library(double_quotes).



来源:https://stackoverflow.com/questions/8332100/handling-prolog-context-free-grammar

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!