What does --> mean in Prolog?
Could you provide one concrete example and explain how it works?
hardmath has already explained a lot. But the more fascinating thing about DCG is, that although the -->/2 syntax suggests context free grammars, its actually more. One can also model more complex languages thanks to attributes, which are simply parameters to the non-terminals.
Here is a DCG that generates and accepts the language L = {a^n b^n c^n}. The DCG reads as follows:
:- use_module(library(clpfd)).
start(N) --> as(N), bs(N), cs(N).
as(N) --> {N #> 0, M #= N-1}, [a], as(M).
as(0) --> [].
bs(N) --> {N #> 0, M #= N-1}, [b], bs(M).
bs(0) --> [].
cs(N) --> {N #> 0, M #= N-1}, [c], cs(M).
cs(0) --> [].
The above code makes use of a so called auxiliary conditions(*), embraced by {}, this is normal code interspersed into the DCG. And to allow bidirectional use of the DCG we were using CLP(FD) instead of ordinary arithmetic. Here are some example runs in SWI-Prolog:
?- phrase(start(X),[a,a,a,b,b,b,c,c,c]).
X = 3
?- phrase(start(3),Y).
Y = [a,a,a,b,b,b,c,c,c]
But in practice DCGs are also often found because of their ability to pass around state. They allow a form of monads in Prolog. Just replace the input list and the output list with input state and output state.
Bye
(*)
An early paper promoting DCG is:
Pereira, F.C.N. and Warren, D.H.D. (1980):
Definite Clause Grammars for Language Analysis –
A Survey of the Formalism and a Comparison with
Augmented Transition Networks, North-Holland
Publishing Company, Artificial Intelligence, 13, 231 – 278
http://cgi.di.uoa.gr/~takis/pereira-warren.pdf
The symbol --> is used in many Prolog implementations to create Declarative Clause Grammar (DCG) rules, which take the form:
head --> body.
as analogous to normal Prolog rules:
head :- body.
In fact every DCG rule can be translated into a normal Prolog rule (and is, internally), but the DCG syntax serves as a convenient and very powerful shorthand for creating rules that relate lists to a variety of Prolog structures. Often DCG rules are used for a fairly limited purpose of parsing lists.
The Question posed here is to give a simple example of the use of -->, in other words showing how DCG rules work in a simple case. The head of a DCG rule is effectively a predicate of an underlying Prolog rule with two extra arguments that represent a difference list, namely one list represented as a longer list minus some trailing portion of that longer list.
Here's a DCG example taken from the SWI-Prolog DCG tutorial adapted by Ann Ogborn from the tutorial by Markus Triska given in Boris's Comment:
as --> [ ]. % empty list is okay
as --> [a], as. % list [a|T] is okay iff T is okay
To distinguish this from a normal Prolog predicate we denote this as//0, but it is equivalent to a normal Prolog predicate with two additional arguments. We can query the underlying Prolog predicate directly by supplying the two additional arguments:
?- as([ ],[ ]).
true
This succeeds because the difference between the two lists (which is again an empty list) is okay according to as//0. Also:
?- as([a],[ ]).
true
succeeds because the difference between the two lists is [a], which is okay by recursion with as//0.
Another way to use as//0 is with the built-in Prolog predicate phrase/2, which takes as a first argument a DCG head and as a second argument a list. In this case phrase/2 will generate lists that satisfy as//0:
?- phrase(as, Ls).
Ls = '[]' ;
Ls = [a] ;
Ls = [a, a] ;
Ls = [a, a, a] ;
and so on, until you terminate the query successfully by hitting return.
This example also works with Amzi! Prolog with only minor differences in output.
Related
I am attempting to learn basic Prolog. I have read some basic tutorials on the basic structures of lists, variables, and if/and logic. A project I am attempting to do to help learn some of this is to match DNA sequences.
Essentially I want it to match reverse compliments of DNA sequences.
Example outputs can be seen below:
?- dnamatch([t, t, a, c],[g, t, a, a]).
true
While it's most likely relatively simple, being newer to Prolog I am currently figuring it out.
I started by defining basic matching rules for the DNA pairs:
pair(a,t).
pair(g,c).
etc...
I was then going to try to implement this into lists somehow, but am unsure how to make this logic apply to longer lists of sequences. I am unsure if my attempted start is even the correct approach. Any help would be appreciated.
Since your relation is describing lists, you could opt to use DCGs. You can describe the complementary nucleobases like so:
complementary(t) --> % thymine is complementary to
[a]. % adenine
complementary(a) --> % adenine is complementary to
[t]. % thymine
complementary(g) --> % guanine is complementary to
[c]. % cytosine
complementary(c) --> % cytosine is complementary to
[g]. % guanine
This corresponds to your predicate pair/2. To describe a bonding sequence in reverse order you can proceed like so:
bond([]) --> % the empty sequence
[]. % doesn't bond
bond([A|As]) --> % the sequence [A|As] bonds with
bond(As), % a bonding sequence to As (in reverse order)
complementary(A). % followed by the complementary nucleobase of A
The reverse order is achieved by writing the recursive goal first and then the goal that describes the complementary nucleobase to the one in the head of the list. You can query this using phrase/2 like so:
?- phrase(bond([t,t,a,c]),S).
S = [g,t,a,a]
Or you can use a wrapper predicate with a single goal containing phrase/2:
seq_complseq(D,M) :-
phrase(bond(D),M).
And then query it:
?- seq_complseq([t,t,a,c],C).
C = [g,t,a,a]
I find the description of lists with DCGs easier to read than the corresponding predicate version. Of course, describing a complementary sequence in reverse order is a relatively easy task. But once you want to describe more complex structures like, say the cloverleaf structure of tRNA DCGs come in real handy.
A solution with maplist/3 and reverse/2:
dnamatch(A,B) :- reverse(B,C), maplist(pairmatch,A,C).
If you want to avoid traversing twice you can also maybe do it like this?
rev_comp(DNA, RC) :-
rev_comp(DNA, [], RC).
rev_comp([], RC, RC).
rev_comp([X|Xs], RC0, RC) :-
pair(X, Y),
rev_comp(Xs, [Y|RC0], RC).
Then:
?- rev_comp([t,c,g,a], RC).
RC = [t, c, g, a].
This is only hand-coded amalgamation of reverse and maplist. Is it worth it? Maybe, maybe not. Probably not.
Now that I thought about it a little bit, you could also do it with foldl which reverses, but now you really want to reverse so it is more useful than annoying.
rev_comp([], []).
rev_comp([X|Xs], Ys) :-
pair(X, Y),
foldl(rc, Xs, [Y], Ys).
rc(X, Ys, [Y|Ys]) :- pair(X, Y).
But this is even less obvious than solution above and solution above is still less obvious than solution by #Capellic so maybe you can look at code I wrote but please don't write such code unless of course you are answering questions of Stackoverflow and want to look clever or impress a girl that asks your help for exercise in university.
So I just started Prolog and I was wondering two things:
1) Is there built in functions (or are they all called predicates?) for simple things like max of 2 numbers, or sine of a number, etc... If so, how do I access them?
2) How can I call a predicate from another one? I wrote two predicates called car and cdr. car returns the head of a list and cdr returns the list without the head. But now I want to call car on the cdr. Here are some examples for clarification:
car([3,4,5,5], H). would return H = 3
cdr([3,4,5,5],L). would return L = [4,5,5]
and what I am asking is how can I do this:
car(cdr[3,4,5,5]))
??
As others have pointed out, the predicates in Prolog are called that for a reason: they really aren't functions. Many newcomers to Prolog start out by trying to map the functionality they know in other languages over to Prolog and it generally fails. Prolog is a very different programming tool than most other languages. So it's a bit like using a variety of hammers for a long time, then having someone hand you a wrench, and you wonder why it doesn't make a good hammer.
In Prolog, predicates are a means of declaring relations between entities. If you say foo(a, b) it means there's a relationship between a and b called foo. You've probably seen the examples: knows(joe, jim). and knows(jim, sally). And you can define a relation, like:
remotely_acquainted(X, Y) :- knows(X, Z), knows(Z, Y), \+ knows(X, Y).
Or something like that.
A predicate does not return a value. It either succeeds or it fails. If you have a sequence of predicates separated by commas (an "and" relationship) and Prolog encounters a predicate that fails, it backs up (backtracks) to the nearest prior predicate which it can make succeed again with different instantiation of its arguments and moves forward again.
Just to add a little to the confusion, there are some predicates in Prolog designed specifically for the evaluation of arithmetic expressions. These act like functions, but they are special case. For example:
X is Y / gcd(Z, 4).
Here, gcd of Z and 4 is computed an its value returned, and then Y is divided by that value and the result is instantiated into X. There are a variety of other functions as well, such as max/2, sin/1, etc. You can look them up in the documentation.
Arithmetic comparative operators function this way as well (using =:=/2, >/2, </2, etc with numeric expressions). So if you say:
X < Y + Z
The Prolog will consider numerical evaluation of these arguments and then compare them.
So having said all that, Prolog does allow embedding of term structures. You could have something like:
car(cdr([1,2,3]))
as a term. Prolog will not interpret it. Interpretation is left up to the programmer. I could then create a predicate which defines an evaluation of such terms:
car([H|_], H).
cdr([_|T], T).
proc_list(car(X), Result) :-
proc_list(X, R1),
car(R1, Result), !.
proc_list(cdr(X), Result) :-
proc_list(X, R1),
cdr(R1, Result), !.
proc_list(X, X).
The cut in the above clauses prevents backtracking to proc_list(X, X) when I don't want it.
Then:
| ?- proc_list(car(cdr([1,2,3])), R).
R = 2
yes
| ?- proc_list(car(cdr(cdr([1,2,3]))), R).
R = 3
yes
| ?-
Note this is a simple case and I may not have captured all of the subtleties of doing a proper sequence of car and cdr. It can also be made more general using =.. and call, etc, instead of discrete terms car and cdr in the parameters. For example, a slightly more general proc_list might be:
proc_list(Term, Result) :-
Term =.. [Proc, X], % Assumes terms have just one argument
member(Proc, [car, cdr]), % True only on recognized terms
proc_list(X, R1), % Recursively process embedded term
ProcCall =.. [Proc, R1, Result], % Construct a calling term with Result
call(ProcCall), !.
proc_list(X, X).
This technique of processing a term does step away from relational behavior which Prolog is best at, and leans into functional behavior, but with an understand of how Prolog works.
Prolog has a really different attitude to computing...
You don't define functions, but relations among arguments. The most similar and well known language I'm aware of is SQL. Think of predicates as tables (or stored procedures, when some computation not predefined by database engine is required).
car([H|_],H).
cdr([_|T],T).
car_of_cdr(L, Car) :- cdr(L, Cdr), car(Cdr, Car).
but since lists' syntax is a core part of the language, a better definition could be
car_of_cdr([_,X|_], X).
Anyway, I think you should spend some time on some Prolog tutorial. SO info page has much more information...
:- use_module(support).
This means the module will use predicates written in other modules.
<module_name>:<predicate_name>(<atoms / Variables>).
This way you can call a predicate in another module.
I have the DCG format I want to simulate this code:
s --> [a].
s --> s, s.
and invokes with:
?- phrase(s, X).
I made up with the below code, but something is missing.
rule(s,[a]).
rule(s,[s,s]).
And for the phrase part I don't know how can call these rule such as in phrase?
a DCG is usually implemented adding a pair of arguments to the rules, to get the fast list processing required to accomplish the parsing, an application of a basic technique known as difference lists. You can inspect the translation with listing/1:
?- [user].
|: s --> [a].
|: s --> s, s.
% user://1 compiled 0.04 sec, 4 clauses
?- listing(s).
s([a|A], A).
s(A, C) :-
s(A, B),
s(B, C).
phrase/2 'just' associates the tokens' list to the first grammar (hidden) argument, and associates the empty list to the second hidden one, to means that the entire tokens' list must be consumed by parsing.
Since you are simulating the DCG, your task then should reduce to adding a token list to your code. If the code is properly implemented (not easy to do right), the simulation will be able to parse as well as generate any legal phrase. In your case, a sequence of at least 1 a.
Without knowing how you interpret your rule/2, it's hard to give any sensible hint...
To implement s -> a ,with such a function rule(s,[a]) I came up with below code , but it doesn't work because of lower case s.
if we had a grammar based on this format, how can I write the rule?
format: grammar(Nonterminals, Terminals, Rules, Start)
grammar([s], [a], [rule(s, [a]), rule(s, [s, s])], [s]).
rule(A,B):- B is A.
There are a lot of confused ideas in this (B is A is almost never what you want), and you would surely benefit from reviewing the fundamentals of Prolog some. DCGs are how grammars are implemented in Prolog, but they have nothing to do with the formalism you're trying to work with. Your example grammar would look something like this:
s --> [a].
s --> s, s.
Note that the terminal/nonterminal distinction is implicit. "Terminals" in a DCG context are whatever shows up in the list notation on the right hand side (in this example, the atom a). The rules are implicit because we're reusing Prolog's global predicate namespace. And the start rule is whatever you pass to phrase/2. You would invoke this grammar by calling phrase/2 like this:
phrase(s, X).
where perhaps X is some list you came up with elsewhere. And you could see that this works:
?- phrase(s, X).
X = [a] ;
X = [a, a] ;
X = [a, a, a] ;
X = [a, a, a, a] ;
X = [a, a, a, a, a] .
However, you'll find that if you need to backtrack, this current formalism won't be sufficient:
?- phrase(s, [a,a]).
true ;
ERROR: Out of local stack
This is because the second rule expands s to s, s, which is too much recursion. There are several practical fixes to this problem; the simplest would probably be to change your second rule to this:
s --> [a], s.
If you are dead-set on using your formalism, you're probably going to have to write a meta-interpreter. This task isn't as hard as it sounds, but you're going to want a firmer grounding in the essentials before you aim for it. I myself have never written a DCG meta-interpreter so I can't comment on how much work that is going to entail. I'd want it to look and work more like phrase/2 with DCG-style input than your example; I'd imagine something more like this:
% accept(Grammar, Sentence) is true if Sentence is in Grammar,
% where Grammar is a structure "grammar(Start, Rules)"
% and Rules is a list of rules in the DCG notation
accept(grammar(s, [(s --> [a]), (s --> [a], s)]), X).
but I don't know precisely how I'd go about coding accept/2. Hope this helps!
I am new to prolog and was trying to create a binary predicate which will give
a list in which all numbers are squared, including those in sublists.
e.g.
?-dcountSublists([a,[[3]],b,4,c(5),4],C).
C=[a,[[9]],b,c(5),16]
Can anyone guide me how i can do this.
Thank You. Answer with a snippet is appreciated
This is easily achieved using recursion in Prolog. Remember that everything in Prolog is either a variable, or a term (atoms are just 0-arity terms), so a term like the following:
[a,[[3]],b,4,c(5),4]
...is easily deconstructed (also note that the list syntax [..] is sugar for the binary predicate ./2). Prolog offers a range of predicates to test for particular types of terms as well, such as numbers, strings, or compound terms (such as compound/1).
To build the predicate you're after, I recommend writing it using several predicates like this:
dcountSublists(In, Out) :-
% analyze type of In
% based on type, either:
% 1. split term into subterms for recursive processing
% 2. term cannot be split; either replace it, or pass it through
Here's an example to get you started which does the hard bit. The following recognizes compound terms and breaks them apart with the term de/constructor =../2:
dcountSublists(In, Out) :-
% test if In has type compound term
compound(In),
% cut to exclude backtracking to other cases below this predicate
!,
% deconstruct In into functor and an argument list
In =.. [Func|Args],
% apply dcountSublists/2 to every argument, building new args
maplist(dcountSublists, Args, NewArgs),
% re-construct In using the new arguments
Out =.. [Func|NewArgs].
dcountSublists(In, Out) :-
% test if In has type atom
atom(In), !,
% pass it through
Out = In.
Testing:
?- dcountSublists([a,[[e]],b,a,c(s),a], L).
L = [a, [[e]], b, a, c(s), a].
Note that this fails if the input term has numbers, because it doesn't have a predicate to recognize and deal with them. I'll leave this up to you.
Good luck!
SWI-Prolog has the predicate maplist/[2-5] which allows you to map a predicate over some lists.
Using that, you only have to make a predicate that will square a number or the numbers in a list and leave everything else the same. The predicates number/1, is_list/1 are true if their argument is a number or a list.
Therefore:
square(N,NN):-
integer(N),
NN is N*N.
square(L,LL):-
is_list(L),
dcountSublists(square,L,LL).
square(Other,Other):-
\+ number(Other),
\+ is_list(Other).
dcountSublists(L,LSquared):-
maplist(square,L,LSquared).
with the negation in the final predicate we avoid multiple (wrong) solutions:
for example dcountSublists([2],X) would return X=[4] and X=[2] otherwise.
This could be avoided if we used an if-then-else structure for square or once/1 to call square/2.
If this is homework maybe you should not use maplist since (probably) the aim of the exercise is to learn how to build a recursive function; in any case, I would suggest to try and write an equivalent predicate without maplist.