What is wrong with my simple prolog recursion? - prolog

I'm new to Prolog. Trying to write a predicate named leaftree, that is True if the given tree is a leaf tree. A tree is a leaf tree if all its leaves are atoms, or if it's empty. There's my predicate:
leaftree(nil).
leaftree(t(nil, X, nil)):-
atom(X).
leaftree(t(L, X, R)):-
leaftree(L), leaftree(R).
There's the input I'm using to test this predicate:
leaftree(t(t(nil, 5, nil), X, nil)).
Well, the output is True but it should be False because 5 isn't an atom. I played around with the leaftree(t(nil, X, nil)):- atom(X) part; it seems like the predicate is called, but it always returns True. Even if I explicitly write fail or other false statements. If matters, I'm using Swish. I'd love your thoughts!
Thanks so much in advance. Orel

The result of your input is true because it matches the third definition of the predicate. So it exists a predicate that is true for your query.
This happens because in the third definition X is free to be anything. When consulting your file with swi-prolog i receive, in fact, a warning saying: Singleton variable [X].
You could replace the second and the third definition with the following (which include both)
leaftree(t(L, X, R)):-
leaftree(L), atom(X), leaftree(R).

Thanks a lot! I uncovered the problem thanks to your comment.
Since nodes that aren't leaves don't have to be atoms, I sense that I should still use two different predicates. I added a ! and replaced the singleton variable X, and now it works perfectly:
leaftree(nil).
leaftree(t(nil, X, nil)):-
!, atom(X).
leaftree(t(L, _, R)):-
leaftree(L), leaftree(R).
Thanks A lot!
Orel

Related

Prolog - a predicate to compare three arguments

I am new into prolog and I've already done some coding, but I have a task I cannot handle. Could you please tell me how to describe a working predicate, that compares arg1, arg2 and arg3 and returns yes it arg1>arg2>arg3? Many thanks in advance!
Szymon
The solution is quite easy:
compare3(X, Y, Z):-
X>Y,
Y>Z.
?- compare3(5,4,3).
true.
Keep in mind that you cannot define predicates with an arbitrary number of input parameters (so obviously compare/3 could be called only with 3 input). To make it more flexible you can insert the element in a list and rewrite it like this
myCompare([]).
myCompare([_]):- !.
myCompare([A,B|T]):-
A>B,
myCompare([B|T]).
?- myCompare([5,4,3]).
true.
Now myCompare/1 accepts a list and return true if the list is sorted, false otherwise.

Commutativity of Cut Operator in Prolog

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.

Prolog predicate regarding list manipulation

E.g: given 3 statement:
car(toyota,[sedan,5_seater,head_rest]).
car(nissan,[4_seater,sedan,2_door,head_rest,blue]).
car(peugeot,[head_rest,sedan,5_seater,sun_roof]).
How to write a Prolog predicate items(A, X, Y) that is true if A is the list car that contain all the parts in X but do not contain any of the parts in Y.
Really hope somebody can help me. Thanks in advance!
see subtract/3
items(A, X, Y) :- subtract(X, Y, A).
if you keep your lists sorted (i.e. like sets), ord_subtract/3 is a much better alternative
edit: sorry for the useless answer, here is the amended one.
The relevant list processing predicate is intersection/3, while setof/3 is a powerful list 'constructor'.
items/3 could be written in this way
items(A, Present, Miss) :-
setof(Car, Parts^(car(Car, Parts),
intersection(Parts, Present, Present),
intersection(Parts, Miss, [])), A).
since your database is a bit meager, to test I enter
?- items(L,[sedan],[blue]).
L = [peugeot, toyota].

Simple Prolog delete from list

(This is NOT a coursework question. Just my own personal learning.)
I'm trying to do an exercise in Prolog to delete elements from a list. Here's my code :
deleteall([],X,[]).
deleteall([H|T],X,Result) :-
H==X,
deleteall(T,X,Result).
deleteall([H|T],X,[H|Result]) :- deleteall(T,X,Result).
When I test it, I first get a good answer (ie. with all the Xs removed.) But then the backtracking offers me all the other variants of the list with some or none of the instances of X removed.
Why should this be? Why do cases where H==X ever fall through to the last clause?
When you are using (==)/2 for comparison you would need the opposite in the third rule, i.e. (\==)/2. On the other hand, such a definition is no longer a pure relation. To see this, consider deleteall([X],Y,Zs), X = Y.
For a pure relation we need (=)/2 and dif/2. Many Prologs like SWI, YAP, B, SICStus offer dif/2.
deleteall([],X,[]).
deleteall([H|T],X,Result) :-
H=X,
deleteall(T,X,Result).
deleteall([H|T],X,[H|Result]) :-
dif(H,X),
deleteall(T,X,Result).
Look at the answers for deleteall([X,Y],Z,Xs)!
Edit (after four years):
More efficiently, but in the same pure vein, this can be written using if_/3 and (=)/3:
deleteall([], _X, []).
deleteall([E|Es], X, Ys0) :-
if_( E = X, Ys0 = Ys, Ys0 = [E|Ys] ),
deleteall(Es, X, Ys).
The last clause says that when removing X from a list, the head element may stay (independently of its value). Prolog may use this clause at any time it sees fit, independently of whether the condition in the preceding clause is true or not backtrack into this clause if another clause fails, or if you direct it to do so (e.g. by issuing ; in the top-level to get the next solution). If you add a condition that the head element may not equal X, it should work.
Edit: Removed the incorrect assertion I originally opened with.

Pairing Two Lists

Hey guys, a few simple prolog questions that I'm hoping you can help me on. Basically, I am trying to write a function that takes input as two lists, and an integer. From there, the function will try to find an x in the first list and a y in the second list such that x + y is equal to the input integer.
So far I am thinking to just recurse down by doing something such as follows:
sum([H1|T1], [H2|T2], Value) :-
NewVal is H1+H2
% Check for equality?
sum(List1, T2, Value)
sum(T1, List2, Value).
So, a few questions regarding this method.
1) How do I refer the the "whole" list after I've passed it in as H1|T1? In the example I just named them List1 and List2 for reading ease.
2) I can check for equality, but how do I "stop" searching and force output?
You need a disjunction, not a conjunction: EITHER h1+h2 is ok, OR there is a solution without h1, OR there is a solution without h2.
There are two syntaxes in prolog for disjunction. You can use a semicolon:
sum([H1|T1], [H2|T2], Value) :- Value is H1+H2 ; sum([H1|T1], T2, Value) ; sum(T1, [H2|T2], Value).
Or you can use separate clauses:
sum([H1|_], [H2|_], Value) :- Value is H1+H2.
sum([H1|T1], [_|T2], Value) :- sum([H1|T1], T2, Value).
sum([_|T1], [H2|T2], Value) :- sum(T1, [H2|T2], Value).
IIRC, I think you should be able to pass the whole list as a parameter using [H1|T1].
Most likely you would want to use the Prolog cut, which stops searching for solutions.
1) Kaleb is right, to do this, just reconstruct the list as the head cons with the tail.
2) Jerome is right, but here's another way of putting it...
Your question "How do I make it stop?" actually hints at a missing part of your predicate. You currently have a recursive predicate with no base case - the recursion has no way of being able to stop. Well I guess in this case it will get to the end of one of the lists, but since this will then be the empty list it will then fail when being unified with the term [H|T] as there is no head item.
When writing a recursive predicate that is looking for a particular element of a list it is common to make the base contain the constraints which define the solution. You can see this in Jerome's solution. This results in a predicate that succeeds once it has found a solution and doesn't continue to process the list afterwards. It will however continue on after this point if you tell it to backtrack and look for more solutions. If you don't care about these further solutions, then you can use the cut to discard them.

Resources