I am trying to work out this simple DCG assignment (Prolog) for my course. The prblem is about creating a DCG. I have already defined a Universe of Discourse in my code. But this question is a bit misleading to me. According to what I've read and know, using my own notes and this Learn Prolog Now! - LINK: http://www.learnprolognow.org/lpnpage.php?pagetype=html&pageid=lpn-htmlse29
One can construct a DCG with (a^nb^nc^n). Where a b and c are normal letters and n is the number the letter is to be multiplied with. However, my question is like this.
"Design and implement a DCG to recognize (or generate) the language 0n1n0n."
Can somebody please help me out here? What is exactly wanted by the question?
With regards to one of the answers, I have tried the following code with no luck.
s --> [].
s(M) --> a(M),b(M),c(M).
a --> [].
a(New) --> [0], a(Cnt),{New is Cnt+1}.
b --> [].
b(New) --> [1], b(Cnt),{New is Cnt+1}.
c --> [].
c(New) --> [0], c(Cnt),{New is Cnt+1}.
count(T, N) --> [0,1,0], count(T, M), {N is M+1}.
count(_, 0) --> [].
DCGs are a sublanguage hosted in Prolog, then it's easy to count occurrences of a terminal T.
count(T, N) --> [T], count(T, M), {N is M+1}.
count(_, 0) --> [].
?- phrase(count(a, C), [a,a,a]).
C = 3 ;
false.
Of course, you should find this can solve your question easily.
EDIT: I missed the generation part. count//2 will not work for generation, because of builtin arithmetic. Using the successors notation the code can work as a generator too:
count(T, s(N)) --> [T], count(T, N).
count(_, 0) --> [].
I think "0n1n0n" means "0n1n0n", i.e. some number of zeros, followed by same number of ones and followed by same number of zeros again.
Related
I'm trying to use definite clause grammars in prolog to accept strings of the form u,2,v where u and are strings of zeroes and ones. There is a constraint whereby the number of zeroes in 'u' must equal the number of ones in 'v'.
I can get the interpreter to accept strings of u,2,v but I'm having trouble adding the constraints.
s--> t,
{t(Input,[]),
find_zeroes(Input,X),length(X,Z),
reverse(Input,RevInput),find_ones(RevInput,Y),length(Y,Z)}.
t --> [2].
t --> l,[2],r.
l --> [X],{member(X,[0,1])}.
l --> [X],l,{member(X,[0,1])}.
r --> [Y],{member(Y,[0,1])}.
r --> [Y],r,{member(Y,[0,1])}.
accfindzeroes([H|T],Acc,Result):- H = 0, accfindzeroes(T,[H|Acc],Result).
accfindzeroes([H|T],Acc,Result):- H \= 0, accfindzeroes(T,Acc,Result).
accfindzeroes([2|_],Acc,Acc).
find_zeroes(List,Result):-accfindzeroes(List,[],Result).
accfindones([H|T],Acc,Result):- H = 1, accfindones(T,[H|Acc],Result).
accfindones([H|T],Acc,Result):- H \= 1, accfindones(T,Acc,Result).
accfindones([2|_],Acc,Acc).
find_ones(List,Result):-accfindones(List,[],Result).
For example:
?- t([0,1,1,2,1,0,0],[]).
True.
As required, but,
?- s([0,1,1,2,1,0,0],[]).
Loops infinitely...
I'm pretty sure the problem is in the second line but I don't know how to rectify it. I think the problem is 't' isn't outputting a list before attempting to resolve the constraints so it doesn't work but as I said I'm a bit stuck.
It seems to be a duplicate question, but I have already written the code.
t --> [2].
t --> l(N),[2],r(N).
l(0) --> [].
l(N) --> [0],l(N0), { N is N0 + 1 }.
l(N) --> [1],l(N).
r(0) --> [].
r(N) --> [0],r(N).
r(N) --> [1],r(N0), { N is N0 + 1 }.
Your problem is that the call t(Input,[]) just generates longer and longer sequences, without any connection to your input.
I have a simple grammar, which takes 3 list items and runs a different dcg rule on each.
[debug] ?- phrase(sentence(X), [sky, a, 1], []).
X = [bright, amber, on] .
Code:
sentence([A,C,R]) -->
analyse(A),
colour(C),
rating(R).
analyse(bright) --> [sky].
analyse(dark) --> [cave].
colour(red) --> [r].
colour(amber) --> [a].
colour(green) --> [g].
rating(on) --> [1].
rating(off) --> [0].
This works fine.
My problem is that my input list needs needs to have 2 items, not 3, and the second atom is a concat atom of colour and rating:
[sky, a1]
So somehow I have to (?) split this atom into [a, 1] and then the colour and rating rules will work with a simple dcg rule.
I can't work out how to do this..obviously with normal prolog, I'd just use atom_chars, but I can't work out how to interleave this with the grammar.
In a perfect world, it feels like I should not have to resort to using atom_chars, and I should be able to come up with a simple dcg rule to split it, but I'm not sure if this is possible, since we are parsing lists, not atoms.
As you have said yourself, you just need to use a predicate like atom_chars/2. You can interleave normal code into a DCG rule by enclosing it in { and }.
But there is something fishy about your problem definition. As you have also said yourself, you are parsing a list, not an atom. The list you are parsing should be already properly tokenized, otherwise you cannot expect to define a DCG that can parse it. Or am I seeing this wrong?
So in other words: you take your input, split into single chars, tokenize that using a DCG. Depending on your input, you can do the parsing in the same step.
It was clear that a refined DCG rule could work, but, alas, it took too much time to me to craft a solution for your problem.
Here it is:
sentence([A,C,R]) -->
analyse(A),
colour(C),
rating(R).
analyse(bright) --> [sky].
analyse(dark) --> [cave].
colour(red) --> [r].
colour(amber) --> [a].
colour(green) --> [g].
colour(X), As --> [A], {
atom_codes(A, Cs),
maplist(char2atomic, Cs, L),
phrase(colour(X), L, As)}.
rating(on) --> [1].
rating(off) --> [0].
char2atomic(C, A) :- code_type(C, digit) -> number_codes(A, [C]) ; atom_codes(A, [C]).
yields
?- phrase(sentence(X), [sky, a1], []).
X = [bright, amber, on]
the key it's the use of 'pushback' (i.e. colour(X), As -->...).
Here we split the unparsable input, consume a token, and push back the rest...
As usual, most of time was required to understand where my first attempt failed: I was coding char2atomic(C, A) :- atom_codes(A, [C])., but then rating//1 failed...
I am trying to understand prolog and definite clause grammar but I am having a very hard time understanding both of them.
I am really trying to understand how to use the dcg syntax...
Here I have two examples:
The first is actually the code from another question on this forum but with an additional question:
The code looked like this:
s --> first, operator, second.
first --> [X].
operator --> ['+'].
second --> [X].
And when Prolog is asked about this, it returns true/false but I can't for the life of me figure out how to actually modify this to "bind" the value so if asked s(X, [2,+,2],[]). it would return the value of first, so instead of returning true it'd say X = 2
Anyway back to the actual question. I have a few rules in normal prolog and this is one of them; it doesn't actually do anything and was merely made up as an example.
do(X, Y, [H|T], Sum):-
H == 1, %check if H is 1
X = H,
Y = T,
Additional is H+5,
Sum is Additional+Additional.
Basically, I am asking if someone could translate this to DCG so that I could try and understand the basic syntax of DCG! I've tried reading some tutorials but I feel like I haven't gotten any wiser...
DCG:
foo(A1, A2, A3, ... , An) --> bar.
Prolog:
foo(A1, A2, A3, ... , An, X, Y) :- bar(X,Y)
So, s should be changed to:
s(X) --> first(X), operator, second.
first(X) --> [X].
operator --> ['+'].
second --> [X].
Of course, it might be better to return the actual result; to do this you should encapsulate prolog code in the DCG clause which is done with {}:
s(Z) --> first(X), operator, second(Y), {Z is X+Y}.
first(X) --> [X].
operator --> ['+'].
second(X) --> [X].
(naturally, if you have more operators, the prolog code won't be that simple).
Regarding the do/4 predicate, it should be something like this:
do(X,Y,[H|T],Sum) -->
{H == 1, %check if H is 1
X = H,
Y = T,
Additional is H+5,
Sum is Additional+Additional}.
but I don't see why you would want that.
One last tip: it's recommended to use phrase/3 instead of adding the last two arguments in a DCG predicate.
it's not easy to translate do/4 to DCG in meaningful way. I've removed arguments that 'copy' the hidden arguments of the DCG.
do(Sum) -->
[1], %check if H is 1
{ % braces allow 'normal' Prolog code (but we have no access to 'hidden' arguments)
Additional is H+5,
Sum is Additional+Additional
}.
edit sorry I forgot H in Additional is H+5,, should read Additional is 1+5,...
In grammar rules (dcg), there are several predefined constructs: (',')//2 meaning concatenation, ('|')//2 meaning alternation etc. One construct which is supported by several but not all Prolog systems is (\+)//1.
Personally, I have used it only for the sake of using it. I have never seen it in code written by others.
So, are there legitimate uses of (\+)//1?
Edit: And additionally, are there legitimate uses of (\+)//1 within a query phrase(nt, L) with L an uninstantiated variable.
\+ can be used to create grammars that are less ambiguous.
The advantage of using \+ over ! for example, is a certain
declarativity of \+, so that for example the resulting DCG
rules can be reordered.
Lets make an example, consider the following grammar:
s([X|Y]) --> t(X), s(Y). % 1
s([]) --> []. % 2
t(2) --> [a,a]. % 3
t(1) --> [a]. % 4
The above grammar is highly ambiguous, for example I get multiple
parses for the following input:
?- phrase(s(A),[a,a,a,a,a]).
A = [2,2,1] ;
A = [2,1,2] ;
A = [2,1,1,1] ;
etc..
Now assume I want to prefer the long parse of t over the
short parse of t. I can do this with a cut as follows:
t(2) --> [a,a], !. % 5
t(1) --> [a]. % 6
?- phrase(s(A),[a,a,a,a,a]).
A = [2,2,1] ;
No
Unfortunately I cannot reorder. Since doing the following
does not give the desired result. Although s(A) now yields
the results in a different order, we are back to square one,
since the grammar is ambiguous again:
t(1) --> [a]. % 7
t(2) --> [a,a], !. % 8
?- phrase(s(A),[a,a,a,a,a]).
A = [1,1,1,1,1] ;
A = [1,1,1,2] ;
A = [1,1,2,1] ;
etc...
Now lets try the same with \+. We can replace the cut
by the following negation:
t(2) --> [a,a]. % 9
t(1) --> [a], \+ [a]. % 10
?- phrase(s(A),[a,a,a,a,a]).
A = [2,2,1] ;
No
Now lets try whether we can reorder. We reorder the
grammar rules of t//1:
t(1) --> [a], \+ [a]. % 11
t(2) --> [a,a]. % 12
?- phrase(s(A),[a,a,a,a,a]).
A = [2,2,1] ;
No
The declarativity is very useful. It means for example
that we can use \+ in a right-to-left chart parser that
picks the grammar rules in an arbitrary order. The
declarativity assures that the bottom up forward chaining
of the chart parser yields the same result independently of
the input order of the DCG rules.
It is then possible to apply the DCG technique in large
natural language (NL) projects and it scales well. The
NL grammars can be empirically tuned into determinism.
The more deterministic a grammar the more efficient
its parsing. Complex NL grammars that are otherwise
intractable become feasible.
Bye
When L is not instantiated then the grammar is used for text generation. Then
you don't need the grammar \+ at all. Since there is no more problem of ambiguity
from some text.
Lets make an example, consider the following grammar:
s([X|Y]) --> t(X), s(Y). % 1
s([]) --> []. % 2
t(2) --> [a,a]. % 3
t(1) --> [a]. % 4
Each different parse has a different parse tree. And there is no ambiguity in
using phrase/2 to generate text. The following queries give exactly one
answer:
?- phrase(s([2,1]),L).
L = [a,a,a]
?- phrase(s([1,2]),L).
L = [a,a,a]
?- phrase(s([1,1,1]),L).
L = [a,a,a]
But there is a little reuse problem. Assume I have a NL grammar with \+ for
parsing. I then cannot use it for unparsing. Since the instantiation pattern
of the \+ goal will be different, and therefore the semantic of the construct
changes.
The way out is probably just to use two grammars. One for parsing and one for
unparsing. I guess parsing and unparsing are two different cognitive capabilities.
Remember in school, there were reading exercises and writting exercises. The
same happens in computer science.
I think it is also in some cases possible to use a single grammar, and view \+ as
an annotation for disambiguation, that is dropped during unparse or differently
handled. One could build such a mechanism. But the issues with unparsing versus
parsing are deeper: Bidirectionallity of auxiliary conditions ({}/1), left recursion
during unparsing, etc...
Bye
I'm trying to write some dcg grammar in prolog which will describe language of
a^nb^n n>=0
"",ab,aabb,aaabbb itd
All what I wrote is
s --> slowo.
slowo --> [a],slowo,[b],!.
slowo --> [].
And its good as long as all I want to do is just check if word is correct, but how should dcg grammar look in prolog for ?-phrase(s,X) which will generate all words from my language?
In addition to #Mog's answer, let us consider the more general case:
What, if the grammar is so complex, that reordering DCG-rules will not help? How can we still enumerate all sentences? If the grammar is formulated in such a manner, that it terminates for a fixed length, we get all sentences with
?- length(Xs, N), phrase(s, Xs).
The goal length alone will enumerate all lists in a fair manner. That is, starting with the shortest [] all lists are enumerated:
?- length(Xs, N).
Xs = [], N = 0
; Xs = [_A], N = 1
; Xs = [_A,_B], N = 2
; Xs = [_A,_B,_C], N = 3
; Xs = [_A,_B,_C,_D], N = 4
; ... .
And now, the length being fixed, the goal phrase(s, Xs) will find all answers for that fixed length. As an example, look at Mat's answer to this grammar.
So this is a general method to inspect a grammar's sentences. However - there is a price to pay for this generality! For grammars with finitely many sentences, out method will not terminate:
:- use_module(library(double_quotes)).
s --> "a"|"b".
?- phrase(s, Xs).
Xs = "a"
; Xs = "b".
This grammar works out of the box, but together with length/2 we get now:
?- length(Xs, N),phrase(s, Xs).
Xs = "a", N = 1
; Xs = "b", N = 1
; loops.
This method is often called iterative deepening, although this term more precisely imposes a bound to the depth of the derivation. But we are imposing a bound to the actual "output". So iterative deepening is also able to handle left-recursion, whereas length/2 works only for grammars that terminate for a fixed input length.
What makes this technique so particularly interesting in Prolog is that it meshes perfectly with Prolog's chronological backtracking mechanism.
If you're beginning with Prolog, try to avoid the use of !/0. You can generally do better without it.
Here for example, your grammar could be written as follows:
s --> [].
s --> [a], s, [b].
and queried as follows:
?- phrase(s, X).
Note that prolog clauses are picked from left to right and top to bottom, so a rule written at the top of another one will be prioritized when the backtracking is involved.
In SWI Prolog, I could use:
s(X, []).
or
phrase(s, X).
(as you suggested) to get all of the strings. In order for that to produce any answers without a stack overflow, however, I needed to reverse the order of the two rules for slowo and remove the cut from the recursive rule.