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!
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.
I'm currently studying Prolog, and in one of the notes I'm reading an example is given of how to use the cut operator correctly. Consider the following function to remove all elements of a particular value from a list.
rm(_,[],[]).
rm(A,[A|L],R) :- rm(A,L,R).
rm(A,[B|L],[B|R]) :- rm(A,L,R).
Due to backtracking, this is not a correct definition of the function, and the function will return all sublists of the list obtained from removing some elements of a particular value, but not necessarily all of them. The notes I'm reading say that a correct way to fix this is to replace the second line by the line
rm(A,[A|L],R) :- !, rm(A,L,R)
But that replacing the line by
rm(A,[A|L],R) :- rm(A,L,R), !
is not correct. I'm not sure why the second example is an incorrect way to fix the function. In swipl, replacing the second term by these fixes seems to always return the same answer on the test cases I consider. What am I missing here?
Your example is a perfect example to illustrate why using the cut here is never a good idea.
Using rm(A,[A|L],R) :- !, rm(A,L,R). makes only sense if both the first and second argument are sufficiently instantiated. But if they are insufficiently instantiated, you get an incomplete answer like:
?- rm(X, [a], R).
X = a, R = []. % incomplete
This clearly misses an answer, as it constrains X to be a only. But if X is anything else, we get a different result, namely:
?- X = b, rm(X,[a],R).
R = [a].
Using the cut at the end as in rm(A,[A|L],R) :- rm(A,L,R), !. is even worse: First, all our assumptions so far must hold, and then additionally the third argument must not be instantiated. Otherwise we get additional incorrect solutions.
?- rm(a,[a],R).
R = [].
?- rm(a,[a],[a]).
true, unexpected. % incorrect
Just recall what we are asking here:
User: When removing a from the list [a] what do we get?
Prolog: Nothing, nil, nada.
User: But can't I have instead of nothing just [a]? Please!
Prolog: OK, I give in.
That's not the way you want to implement an accounting system.
So both uses of cuts are bad. But the second one is clearly worse for it has many more preconditions to remember and is also inefficient.
On the other hand there are some cases where you can use these predicates. But typically it is quite difficult to remember when this is safe. Thus such cuts are a permanent source of errors.
Is there any hope to get rid of all this fine print? Fortunately, there is a way out using if_/3 from library(reif) for SICStus|SWI. Download it and say:
:- use_module(reif).
rm(_,[],[]).
rm(A,[X|Xs], Ys0) :-
if_(A = X, Ys0 = Ys, Ys0 = [X|Ys]),
rm(A, Xs, Ys).
This program is comparably efficient but does not have any of the aforementioned defects:
?- rm(X, [a], R).
X = a, R = []
; R = [a], dif(X, a).
Note the second new answer! It says that for all X that are different to a, the list remains unchanged.
TL;DR: sibling(a,X) succeeds with the answer X = a, but sibling(a,a) fails.
I have the following Prolog file:
children(a, c).
children(a, d).
children(b, c).
children(b, d).
sibling(X, Y) :-
X \== Y, A \== B,
children(X, A), children(X, B),
children(Y, A), children(Y, B).
It seems clear enough to me, two person are siblings if their parents are the same. Also, a person is not their own sibling.
But when I tried to run some queries on GNU Prolog, I get some strange results:
| ?- sibling(a, b).
true ? a
true
true
yes
This is the intended behavior. a and b are siblings. There are three results, which is a bit weird, but I assume Prolog is binding A = c, B = d and A = d, B = c.
| ?- sibling(a, a).
no
I think this means a and a are not siblings.
| ?- sibling(a, X).
X = a ? a
X = b
X = a
X = b
X = a
X = b
X = a
X = b
(15 ms) yes
This is where I got stuck: It says X = a, which means sibling(a,a) is true, but sibling(a,a) failed in the previous query!
I feel that I'm not understanding what \== actually does in Prolog.
What is happening, and how do I fix this?
TL;DR: Use prolog-dif—or iso_dif/2 (on iso-prolog conforming systems like gnu-prolog)!
Good question, +1!
In fact, it's a question I have asked myself, and the answer has to do with logical-purity: logical purity is a central aspect of what
makes Prolog as a language so special, as it enables you to:
describe—not prescribe
write code that is relational—not just functional
think in terms of problems / solutions—not the individual steps of the search process itself
operate on a higher level—not get lost in nitty-gritty details
Unlike many other programming languages, Prolog programs have both procedural semantics (defining the execution steps and their order) and declarative semantics (allowing you to state relations that should hold and let the Prolog processor find a proper way of execution by itself).
But, beware: Prolog has some features that, when used, ruin declarative semantics. To prevent this, try to structure your application into two parts: an impure shell for dealing with side-effects (input/output) and a logically pure base which comprises pure monotonic Prolog code.
Try moving the inequality to the end of the predicate. Maybe it gives you true because it's not instantiated already.
sibling(X,Y):- children(X, A), children(X, B),
children(Y, A), children(Y, B),
X \== Y, A \== B.
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.
How can I write the following rule in PROLOG: if P then not Q
I understand that you can easily write if P then Q the predicates like q(X) :- p(X), but how can you negate the q/1 predicate? I don't want to define new predicates with other semantics like non_q/1.
The clause "if P then not Q" is logically equivalent to the negative clause "not P OR not Q". As such it is a Horn clause without a positive literal, and as an application of the correspondence of SLD theorem proving and Horn clauses, can be represented in Prolog programming as a goal clause or "query":
?- P, Q.
Let's come back to this idea in a minute.
But the goal clause is perhaps not the sort of representation you have in mind. The facts and rules that constitute a Prolog "knowledgebase" are definite clauses, i.e. Horn clauses each with exactly one positive literal. "If P then not Q" has no positive literal, so in this sense it cannot be represented (as a definite clause).
The goal clause shown above "asks" if P and Q can both be proven. Prolog provides a notion of "negation as failure", so a more natural way to "ask" whether "not P OR not Q" holds would be:
?- not((P,Q)).
Then we would get success if either P or Q fails, and failure if both succeed.
However if your purpose is to assert the negation something in the knowledgebase, Prolog doesn't naturally support this. Depending on your application, there may be a reasonable way to work around the Prolog syntax and accomplish what is needed (there's always an unreasonable way to do it, as you've hinted as with a non_q predicate).
Have you ever heard about cut in Prolog?
Anyway I don't know much about Prolog standard, but in SWI-Prolog the symbol \+ means negation. I know it don't have to work in every Prolog's interpreter.
You can make the predicate negation with Prolog's cut. The predicate is defined like:
not(Goal) :- call(Goal),!,fail.
not(Goal).
It means that Goal can't be proven, not the Goal is false.
Maybe this Prolog & Cut link will be useful.
"...if P then not Q" can be represented via the -> if-then control-flow predicate (e.g., GNU) , along with the \+ negation (or 'not-provable') operator (e.g., GNU), as follows:
(P -> \+ Q),
Note that, typically, \+ will implement what is known as negation-as-failure; i.e., the subgoal/expression \+ Q will succeed iff Q cannot. Note that the evaluation of Q under \+ will not affect the bindings of any variables present in the expression Q at execution.
For example, consider:
foo(a).
bar(b).
Given these facts, the following hold:
foo(a) -> \+ bar(a). % succeeds, as bar(a) is not provable.
foo(a) -> \+ bar(b). % fails, as bar(b) is provable.
foo(a) -> \+ bar(X). % fails, as bar(X) is provable; note that X remains unbound.
foo(X) -> \+ bar(X). % succeeds, as bar(X) where X unified to 'a' isn't provable.
Implementing something akin to \+ q(X) :- p(X) as you might want (in terms of a 'rule') isn't straightforward, as you describe, however a potential hack is:
q(X) :- p(X), !, fail.
This definition will only reflect the intention that q(X) is to fail for all X where p(X) succeeds iff it is asserted before any other clauses of q(X), but may not be ideal.
You can use minimal logic to define a negative head. In minimal logic
~A can be viewed as A -> ff. Thus the following
P -> ~Q
Can be viewed as:
P -> (Q -> ff).
Now if we take the following identity (A -> (B -> C)) = (A & B -> C), we
see that the above is equivalent to:
P & Q -> ff.
There is now one problem, how can we ask negative queries? There is one
way to make use of minimal logic which is different from negation as
failure. The idea is that a query of the form:
G |- A -> B
is answered by temporarily adding A to the prolog program G, and then
trying to solve B, i.e. doing the following:
G, A |- B
Now lets turn to Prolog notation, we will show that p, and p -> ~q
implies ~q by executing a (minimal logic) Prolog program. The
prolog program is:
p.
ff :- p, q.
And the query is:
?- q -: ff.
We first need to define the new connective (-:)/2. A quick solution
is as follows:
(A -: B) :- (assert(A); retract(A), fail), B, (retract(A); assert(A), fail).
Here you see a realisation of this minimal logic negation in SWI Prolog:
Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 5.10.4)
Copyright (c) 1990-2011 University of Amsterdam, VU Amsterdam
1 ?- [user].
:- op(1200,xfy,-:).
|: (A -: B) :- (assertz(A); retract(A), fail), B, (retract(A); assertz(A), fail).
|: p.
|: ff :- p, q.
|:
% user://1 compiled 0.02 sec, 1,832 bytes
true.
2 ?- q -: ff.
true .
Best Regards
Reference:
Uniform Proofs as a Foundation for Logic Programming (1989)
by Dale Miller, Gopalan Nadathur, Frank Pfenning, Andre Scedrov