I've just started experimenting with Prolog, and I was trying to write a rule to find out whether a list contained only unique elements. I got it working in the second variation (by negating a positive test), but I've completely failed to understand why the first variation doesn't work.
Given this file:
uniqueElements([X|Y]) :-
notmember(X, Y),
uniqueElements(Y).
notmember(X, Y) :-
\+ member(X, Y).
hasRepeatedElements([X|Y]) :-
(
member(X, Y) ->
true
; hasRepeatedElements(Y)
).
uniqueElements_2(X) :-
\+ hasRepeatedElements(X).
The GNU Prolog interpreter gives these responses:
| ?- uniqueElements([1,2,3]).
no
| ?- uniqueElements([1,2,3,2,3]).
no
| ?- uniqueElements_2([1,2,3]).
yes
| ?- uniqueElements_2([1,2,3,2,3]).
no
Why is the first response 'no'? (I would have expected member to return false, be negated to true, and thus have notmemeber return true on each iteration of uniqueElements). I guess I'm expecting '\+' to behave like '!' does in a C if clause, or the 'not' keyword in Python. Is this a misunderstanding?
In uniqueElements, you haven't provided the base case for the recursion:
uniqueElements([]).
Without that clause, when a particular call chain gets to the empty list case, it doesn't find any applicable clauses, which means fail in Prolog. Meaning, "unprovable". So, your call uniqueElements([1,2,3]) has produced an equivalent of true && true && true && false.
Now it should work.
hasRepeatedElements doesn't have a clause defined for the base case either, but its failure in finding whether there were repeated elements in an empty list [] is consistent with its semantics - it should have found that there are no repeated elements in empty list, in the first place.
In Prolog, "not" means "can't prove that ...".
Related
I am working on a prolog problem and need some help here.
/*Write a predicate listtran(L,E) which translates a list of Latin number words
* to the corresponding list of English number words. */
%% predicate
listtran(L,E).
%% clauses
tran(unus,one).
tran(duo,two).
tran(tres,three).
tran(quattuor,four).
tran(quinque,five).
tran(sex,six).
tran(septem,seven).
tran(octo,eight).
tran(novem,nine).
%% rules
% base case: empty list
listtran([], []).
% inductive cases:
listtran([L | T0], [E | T1]) :-
tran(L, E), % translate the head of the list
listtran(T0, T1). % translate the tail of the list, using recursion
What is needed to be written in predicates and query to test:
?- listtran([unus,novem,duo],X).
should give:
X = [one,nine,two].
and
?- listtran(X,[one,seven,six,two]).
it should return:
X = [unus,septem,sex,duo].
Also, what can be done to avoid the error message:
Clauses of listtran/2 are not together in the source-file
Thanks!
That is a discontigous predicate error.
Prolog is complaining that all the clauses of a predicate are not defined in one place. You should just delete the listtrans(L, E).(why is it even there?) at the start and the rest should work fine.
An explanation of the error: https://stackoverflow.com/a/40614467/4437190
I am trying to make an expression simplifier in Prolog, but one part has me stuck.
What I want to happen is simplify(x*(4*x),R). evalutes to simplify(x*4*x,R). then the rest will work its magic. But I can't seem to remove the parens. Here is the evaluation code below
simplify(x,x).
simplify(C*x,C*x) :- atomic(C),number(C),C\==1,C\==0.
simplify(x*C*x,W):- atomic(C),number(C), simplify(C*x^2,W).
simplify(C*x^N,C*W) :- atomic(C),number(C),atomic(N),number(N), simplify(x^N,W).
simplify(x^1,x).
simplify(x^N,x^N) :- atomic(N),number(N),N \== 1.
simplify(U*(V),R2):- simplify(U,U1),simplify(V,V1),simplify(U1*V1,R2).%why will it not return a paren less output
simplify(U*V,R2):- simplify(U,U1),simplify(V,V1),simplify(U1*V1,R2).
Parenthesis are used to change a term interpretation in the presence of operators. Note that, for the Prolog parser, there's no distinction between simplify(U*(V),R2) and simplify(U*V,R2):
| ?- write_canonical(simplify(U*(V),R2)).
simplify(*(_279,_280),_284)
yes
| ?- write_canonical(simplify(U*V,R2)).
simplify(*(_279,_280),_284)
yes
Thus, the last two clauses have the same head; there's a single operator in the U*(V) term.
Now consider the goal simplify(x*(4*x),R). The operator definition for (*)/2 is:
| ?- current_op(Priority, Type, *).
Priority = 400
Type = yfx
yes
I.e. the operator is left-associative. This means that e.g. a*b*c is parsed as *(*(a,b),c). Therefore:
| ?- write_canonical(simplify(x*(4*x),R)).
simplify(*(x,*(4,x)),_285)
yes
| ?- write_canonical(simplify(x*4*x,R)).
simplify(*(*(x,4),x),_285)
yes
I am new to prolog.I want to write compare_lists/2 which will compare 2 lists and return true if they have at least one common element. I know this can be done with something like that
common_list([H|_],T) :- member(H,T).
common_list([_|T],L) :- common_list(T,L).
common_list2(L1,L2) :- member(X,L1),member(X,L2).
but I want to do it without Prolog built-in predicates. I tried writing this
common_elements([H|_],[H|_]).
common_elements(L,[_|T]) :- common_elements(L,T).
common_elements([_|T],L):-common_elements(T,L).
but when I ask the online swish prolog tool common_elements([3,13,8,1],[5,3,7,3,1]). It answers true 37 times not 3 like the common_list/2 and common_list2/2 (I have to use cut to get only 1 instead of 3 but that's a different story).
According to your condition when two Lists have at least one element in common return True and False if they no elements in common.
All you have to do is check if Head of your list exists in your second List. If Head is present in second List return True. Else repeat the process for rest of the process for the tail of the first list.
My approach is given below:-
is_member(X,[X|_]):- !.
is_member(X,[_|T]):- is_member(X,T).
compare1([],[]):- false.
compare1([H|_],List):- is_member(H,List) , !.
compare1([H|T],List):- \+is_member(H,List) , compare1(T,List).
OUTPUT
?- compare1([3,4],[1,2,2]).
false
?- compare1([1,2,3,4],[5,6]).
false
?- compare1([1,2,3],[4,5,6,3]).
true
?- compare1([1,2,3],[]).
false
?- compare1([],[]).
false
?- compare1([],[1,2,3]).
false
Hope this helped you.
You can write the member function very easily yourself
my_member(H, [H|_]).
my_member(X, [_|T]) :-
my_member(X,T).
Can anybody explain the following code? I know it returns true if X is left of Y but I do not understand the stuff with the pipe, underscore and R. Does it mean all other elements of the array except X and Y?
left(X,Y,[X,Y|_]).
left(X,Y,[_|R]) :- left(X,Y,R).
If you are ever unsure about what a term "actually" denotes, you can use write_canonical/1 to obtain its canonical representation.
For example:
| ?- write_canonical([X,Y|_]).
'.'(_16,'.'(_17,_18))
and also:
| ?- write_canonical([a,b|c]).
'.'(a,'.'(b,c))
and in particular:
| ?- write_canonical([a|b]).
'.'(a,b)
This shows you that [a|b] is the term '.'(a,b), i.e., a term with functor . and two arguments.
To reinforce this point:
| ?- [a|b] == '.'(a,b).
yes
#mat answered the original question posted quite precisely and completely. However, it seems you have a bigger question, asked in the comment, about "What does the predicate definition mean?"
Your predicate, left(X, Y, L), defines a relation between two values, X and Y, and a list, L. This predicate is true (a query succeeds) if X is immediately left of Y in the list L.
There are two ways this can be true. One is that the first two elements in the list are X and Y. Thus, your first clause reads:
left(X, Y, [X,Y|_]).
This says that X is immediately left of Y in the list [X,Y|_]. Note that we do not care what the tail of the list is, as it's irrelevant in this case, so we use _. You could use R here (or any other variable name) and write it as left(X, Y, [X,Y|R]). and it would function properly. However, you would get a singleton variable warning because you used R only once without any other references to it. The warning appears since, in some cases, this might mean you have done this by mistake. Also note that [X,Y|_] is a list of at least two elements, so you can't just leave out _ and write [X,Y] which is a list of exactly two elements.
The above clause is not the only case for X to be immediately left of Y in the list. What if they are not the first two elements in the list? You can include another rule which says that X is immediately left of Y in a list if X is immediately left of Y in the tail of the list. This, along with the base case above, will cover all the possibilities and gives a complete recursive definition of left/3:
left(X, Y, [_|R]) :- left(X, Y, R).
Here, the list is [_|R] and the tail of the list is R.
This is about the pattern matching and about the execution mechanism of Prolog, which is built around the pattern matching.
Consider this:
1 ?- [user].
|: prove(T):- T = left(X,Y,[X,Y|_]).
|: prove(T):- T = left(X,Y,[_|R]), prove( left(X,Y,R) ).
|:
|: ^Z
true.
Here prove/1 emulates the Prolog workings proving a query T about your left/3 predicate.
A query is proven by matching it against a head of a rule, and proving that rule's body under the resulting substitution.
An empty body is considered proven right away, naturally.
prove(T):- T = left(X,Y,[X,Y|_]). encodes, "match the first rule's head. There's no body, so if the matching has succeeded, we're done."
prove(T):- T = left(X,Y,[_|R]), prove( left(X,Y,R) ). encodes, "match the second rule's head, and if successful, prove its body under the resulting substitution (which is implicit)".
Prolog's unification, =, performs the pattern matching whilst instantiating any logical variables found inside the terms being matched, according to what's being matched.
Thus we observe,
2 ?- prove( left( a,b,[x,a,b,c])).
true ;
false.
3 ?- prove( left( a,b,[x,a,j,b,c])).
false.
4 ?- prove( left( a,b,[x,a,b,a,b,c])).
true ;
true ;
false.
5 ?- prove( left( a,B,[x,a,b,a,b,c])).
B = b ;
B = b ;
false.
6 ?- prove( left( b,C,[x,a,b,a,b,c])).
C = a ;
C = c ;
false.
The ; is the key that we press to request the next solution from Prolog (while the Prolog pauses, awaiting our command).
I want to print true or false based on some predicate predicate passing. For example, in Greek mythology Athena is not a descendant of Poseidon. I have all of the facts and rules correct to prove it as such, but cannot simply print in the print_solution method whether the predicate is true or not.
I have the rule descendant(athena, poseidon) that will print false in the interpreter as a single statement. E.g. false is printed if I:
$ prolog
['greek_mythology.pl'].
descendant(athena, poseidon).
false
I now want to write the same in my print_solution method:
print_solution :-
write('Athena is a descendant of Poseidon: '), write(?????), nl.
I tried assigning a variable in the solution and printing that:
print_solution :-
Z :- descendant(athena, poseidon),
write('Athena is a descendant of Poseidon: '), write(Z), nl.
but I get the error:
ERROR: /.../greek_mythology.pl:164:17: Syntax error: Operator priority clash
Out of desperation I tried checking to see if poseidon was in the list of descendant(athena, X):
setof(X, descendant(athena, X), Z), // [gaia,kronos,oranos,rheia,zeus]
member(poseidon, Z).
but that just gives back:
Z = [poseidon|_G3320] .
which I don't understand. Apparently member/2 only works on lists, and Z is apparently not a list:
is_list(Z).
false.
How can I simply print true or false in the write function if the predicate returns passes like it does in the interpreter console? Desired output: Athena is a descendant of Poseidon: false.
You can use if/then/else construct in Prolog also
print_solution :-
( descendant(athena, poseidon)
-> Z = true
; Z = false
),
write('Athena is a descendant of Poseidon: '), write(Z), nl.
seems also could be more useful if parametrized
print_solution(Desc, Anc) :-
( descendant(Desc, Anc)
-> Z = true
; Z = false
),
format('~w is a descendant of ~w: ~w~n', [Desc, Anc, Z]).
print_solution :- print_solution(athena, poseidon).
I think (not absolutely sure) that what you want is reification of the success or failure of a query to a truth value. A naive way to do it would be:
goal_success(Goal, true) :-
Goal.
goal_success(Goal, false) :-
\+ Goal.
(This has problems but read on)
Then, you can use it like this:
?- goal_success(descendant(athena, poseidon), S),
/* write whatever */, write(S).
However, what you are trying to do is basically write your own meta-interpreter, and I am not sure it is really that useful. After all, what you show in your question is exactly how you would expect to interact with the Prolog top level (the Prolog interactive prompt). As a programmer (a human) what you want from Prolog is answers to your questions. What you give Prolog, however, is queries, and you get solutions to these queries. Your question is:
Is Athena a descendant of Poseidon?
You evaluate the query:
?- descendant(athena, poseidon).
false.
There is no solution to this query (let's not go into the whole "closed world assumption" discussion now, it is enough to say that not being able to find a proof means that the opposite is true...)
So we interpret this as:
Athena is not a descendant of Poseidon.
Usually, this should be enough. This is why it seems that you want to extend the Prolog top level, and write your own interpreter on top of it, which is of course fine, but more involved. Once you go down that road, you would like to interact with this interpreter like this maybe?
??- Is Athena a descendant to Poseidon?
?>> No, she is not!
Anyway, if you search the internet for "Prolog meta interpreter" you will get enough to get you started. "The Art of Prolog" by Sterling & Shapiro has a whole chapter on that, too.