I'm trying to make a Prolog predicate iscontained/2: iscontained(List, Search) where it returns true. if the Search is listed within the given List, false. if not. And if it is a variable that is inputted, then it just returns that it equals each element in the list.
Example:
?- iscontained([a, b, c], a).
true.
?- iscontained([a, b, c], d).
false.
?- iscontained([a, b, c], A).
A = a;
A = b;
A = c;
false.
I need a shove in the right direction, not asking for a hand out, unless you know a quick way to do it. Any help is appreciated, thanks.
Please note that the frequently proposed member/2 predicate admits solutions that are no lists at all:
?- member(e,[e|nonlist]).
true.
This is not a big problem in many situations, but should be mentioned nevertheless.
A natural, symmetric definition that only admits lists uses DCGs:
... --> [] | [_], ... .
iscontained(Es, E) :-
phrase((...,[E],...), Es).
The ... is a non-terminal which denotes an arbitrary sequence.
While this is entirely overkill for this tiny example, it gives you a template for more interesting patterns. Like
iscontainedtwice(Es, E) :-
phrase((...,[E],...,[E],...), Es).
You will need to consider two cases. I'll leave the body of the rules up to you.
iscontained([A|Xs],A)
iscontained([X|Xs],A)
[edited to remove reference to the empty list: the empty list contains nothing: if encountered, the predicate fails.]
Now that you certainly already came up with a solution, I'd like to mention one thing:
The classical version:
member(Item, [Item|_List]).
member(Item, [_Head|List]) :- member(Item, List).
leaves a choice point after having found the last element possible, ie:
?- member(A, [1, 2, 3]).
A = 1;
A = 2;
A = 3;
false.
while
member2(Item, [Head|List]) :-
member2(List, Item, Head).
member2(_List, Item, Item).
member2([Head|List], Item, _PreviousHead) :-
member2(List, Item, Head).
treats the empty list at the same time as the last element and allows optimization:
?- member2(A, [1, 2, 3]).
A = 1;
A = 2;
A = 3.
That's the version used in SWI-Prolog (and certainly Jekejeke Prolog and maybe others). Its author is Gertjan van Noord.
That's just meant as a reminder that, while the exercise of coming up yourself with a member/2 implementation is excellent, it should not lead you not use the built-ins afterwards, they're often fine tuned and more efficient!
Related
I am new to Prolog and I am trying to write a function that finds a list that follows some rules.
More specifically, given two numbers, N and K, I want my function to find a list with K powers of two that their sum is N. The list must not contain each power but the total sum of each power. For example if N=13 and K=5, I want my list to be [2,2,1] where the first 2 means two 4, the second 2 means two 2, and the third 1 means one 1 (4+4+2+2+1=13). Consider that beginning from the end of the list each position i represents the 2^i power of 2. So I wrote this code:
sum2(List, SUM, N) :-
List = [] -> N=SUM;
List = [H|T],
length(T, L),
NewSUM is SUM + (H * 2**L),
sum2(T, NewSUM, N).
powers2(N,K,X):-
sum2(X,0,N),
sum_list(X, L),
K = L.
The problem is:
?- sum2([2,2,1],0,13).
true.
?- sum2([2,2,1],0,X).
X = 13.
?- sum2(X,0,13).
false.
?- powers2(X,5,[2,2,1]).
X = 13.
?- powers2(13,5,[2,2,1]).
true.
?- powers2(13,X,[2,2,1]).
X = 5.
?- powers2(13,5,X).
false.
In the cases, X represents the list I expected the output to be a list that follows the rules and not false. Could you help me to find how can I solve this and have a list for output in these cases?
The immediate reason for the failure of your predicate with an unbound list is due to your use of the -> construct for control flow.
Here is a simplified version of what you are trying to do, a small predicate for checking whether a list is empty or not:
empty_or_not(List, Answer) :-
( List = []
-> Answer = empty
; List = [H|T],
Answer = head_tail(H, T) ).
(Side note: The exact layout is a matter of taste, but you should always use parentheses to enclose code if you use the ; operator. I also urge you to never put ; at the end of a line but rather in a position where it really sticks out. Using ; is really an exceptional case in Prolog, and if it's formatted too similarly to ,, it can be hard to see that it's even there, and what parts of the clause it applies to.)
And this seems to work, right?
?- empty_or_not([], Answer).
Answer = empty.
?- empty_or_not([1, 2, 3], Answer).
Answer = head_tail(1, [2, 3]).
OK so far, but what if we call this with an unbound list?
?- empty_or_not(List, Answer).
List = [],
Answer = empty.
Suddenly only the empty list is accepted, although we know from above that non-empty lists are fine as well.
This is because -> cuts away any alternatives once it has found that its condition is satisfied. In the last example, List is a variable, so it is unifiable with []. The condition List = [] will succeed (binding List to []), and the alternative List = [H|T] will not be tried. It seems simple, but -> is really an advanced feature of Prolog. It should only be used by more experienced users who know that they really really will not need to explore alternatives.
The usual, and usually correct, way of implementing a disjunction in Prolog is to use separate clauses for the separate cases:
empty_or_not([], empty).
empty_or_not([H|T], head_tail(H, T)).
This now behaves logically:
?- empty_or_not([], Answer).
Answer = empty.
?- empty_or_not([1, 2, 3], Answer).
Answer = head_tail(1, [2, 3]).
?- empty_or_not(List, Answer).
List = [],
Answer = empty ;
List = [_2040|_2042],
Answer = head_tail(_2040, _2042).
And accordingly, your definition of sum2 should look more like this:
sum2([], SUM, N) :-
N = SUM.
sum2([H|T], SUM, N) :-
length(T, L),
NewSUM is SUM + (H * 2**L),
sum2(T, NewSUM, N).
This is just a small step, however:
?- sum2(X, 0, 13).
ERROR: Arguments are not sufficiently instantiated
ERROR: In:
ERROR: [9] _2416 is 0+_2428* ...
ERROR: [8] sum2([_2462],0,13) at /home/gergo/sum.pl:5
ERROR: [7] <user>
You are trying to do arithmetic on H, which has no value. If you want to use "plain" Prolog arithmetic, you will need to enumerate appropriate values that H might have before you try to do arithmetic on it. Alternatively, you could use arithmetic constraints. See possible implementations of both at Arithmetics in Prolog, represent a number using powers of 2.
I have a simple program I'm trying to write in Prolog. Essentially, as I learning exercise, I'm trying to write a program that takes two sorted lists as input, and returns the merged list that is also sorted. I have dubbed the predicate "merge2" as to no be confused with the included predicate "merge" that seems to do this already.
I am using recursion. My implementation is below
merge2([],[],[]).
merge2([X],[],[X]).
merge2([],[Y],[Y]).
merge2([X|List1],[Y|List2],[X|List]):- X =< Y,merge2(List1,[Y|List2],List).
merge2([X|List1],[Y|List2],[Y|List]):- merge2([X|List1],List2,List).
When I run this, I get X = [1,2,4,5,3,6] which is obviously incorrect. I've been able to code multiple times and tried to draw out the recursion. To the best of my knowledge, this should be returning the correct result. I'm not sure why the actualy result is so strange.
Thank you.
QuickCheck is your friend. In this case, the property that you want to verify can be expressed using the following predicate:
sorted(L1, L2) :-
sort(L1, S1),
sort(L2, S2),
merge2(S1, S2, L),
sort(L, S),
L == S.
Note that sort/2 is a standard Prolog built-in predicate. Using the QuickCheck implementation provided by Logtalk's lgtunit tool, which you can run using most Prolog systems, we get:
?- lgtunit::quick_check(sorted(+list(integer),+list(integer))).
* quick check test failure (at test 2 after 0 shrinks):
* sorted([0],[0])
false.
I.e. you code fails for L1 = [0] and L2 = [0]:
?- merge2([0], [0], L).
L = [0, 0] ;
L = [0, 0] ;
false.
Tracing this specific query should allow you to quickly find at least one of the bugs in your merge2/4 predicate definition. In most Prolog systems, you can simply type:
?- trace, merge2([0], [0], L).
If you want to keep duplicates in the merged list, you can use the de facto standard predicates msort/2 in the definition of the property:
sorted(L1, L2) :-
sort(L1, S1),
sort(L2, S2),
merge2(S1, S2, L),
msort(L, S),
L == S.
In this case, running QuickCheck again:
?- lgtunit::quick_check(sorted(+list(integer),+list(integer))).
* quick check test failure (at test 3 after 8 shrinks):
* sorted([],[475,768,402])
false.
This failure is more informative if you compare the query with your clauses that handle the case where the first list is empty...
This is done using difference list and since you are learning it uses reveals, AKA spoiler, which are the empty boxes that you have to mouse over to ravel the contents. Note that the reveals don't allow for nice formatting of code. At the end is the final version of the code with nice formatting but not hidden by a reveal so don't peek at the visible code at the very end if you want to try it for yourself.
This answer takes it that you have read my Difference List wiki.
Your basic idea was sound and the basis for this answer using difference list. So obviously the big change is to just change from closed list to open list.
As your code is recursive, the base case can be used to set up the pattern for the rest of the clauses in the predicate.
Your simplest base case is
merge2([],[],[]).
but a predicate using difference list can use various means to represent a difference list with the use of L-H being very common but not one I chose to use. Instead this answer will follow the pattern in the wiki of using two variables, the first for the open list and the second for the hole at the end of the open list.
Try to create the simple base case on your own.
merge2_prime([],[],Hole,Hole).
Next is needed the two base cases when one of the list is empty.
merge2_prime([X],[],Hole0,Hole) :-
Hole0 = [X|Hole].
merge2_prime([],[Y],Hole0,Hole) :-
Hole0 = [Y|Hole].
Then the cases that select an item from one or the other list.
merge2_prime([X|List1],[Y|List2],Hole0,Hole) :-
X =< Y,
Hole0 = [X|Hole1],
merge2_prime(List1,[Y|List2],Hole1,Hole).
merge2_prime(List1,[Y|List2],Hole0,Hole) :-
Hole0 = [Y|Hole1],
merge2_prime(List1,List2,Hole1,Hole).
Lastly a helper predicate is needed so that the query merge2(L1,L2,L3) can be used.
merge2(L1,L2,L3) :-
merge2_prime(L1,L2,Hole0,Hole),
Hole = [],
L3 = Hole0.
If you run the code as listed it will produce multiple answer because of backtracking. A few cuts will solve the problem.
merge2(L1,L2,L3) :-
merge2_prime(L1,L2,Hole0,Hole),
Hole = [],
L3 = Hole0.
merge2_prime([],[],Hole,Hole) :- !.
merge2_prime([X],[],Hole0,Hole) :-
!,
Hole0 = [X|Hole].
merge2_prime([],[Y],Hole0,Hole) :-
!,
Hole0 = [Y|Hole].
merge2_prime([X|List1],[Y|List2],Hole0,Hole) :-
X =< Y,
!,
Hole0 = [X|Hole1],
merge2_prime(List1,[Y|List2],Hole1,Hole).
merge2_prime(List1,[Y|List2],Hole0,Hole) :-
Hole0 = [Y|Hole1],
merge2_prime(List1,List2,Hole1,Hole).
Example run:
?- merge2([1,3,4],[2,5,6],L).
L = [1, 2, 3, 4, 5, 6].
?- merge2([0],[0],L).
L = [0, 0].
I didn't check this with lots of examples as this was just to demonstrate that an answer can be found using difference list.
?- append([], [X1], [a,b]).
Why does this return no and not
X1 = a,b
Since
? - append([], [a,b], [a,b])
returns yes?
To understand a Prolog program you have two choices:
Think about the program as you do this in other programming languages by simulating the moves of the processor. This will lead to your mental exasperation very soon unless your name is Ryzen or in other words:
You are a processor
Let Prolog do the thinking and use Prolog to understand programs.
Whenever you see a failing goal, narrow down the reason why the goal fails by generalizing that goal (by replacing some term by a variable). You do not need to understand the precise definition at all. It suffices to try things out. In the case of your query
?- append([], [X1], [a,b]).
false.
We have three arguments. Maybe the first is the culprit? So I will replace it by a new variable:
?- append(Xs, [X1], [a,b]).
Xs = [a], X1 = b
; false.
Nailed it! Changing the first argument will lead to success. But what about the second argument?
?- append([], Ys, [a,b]).
Ys = [a, b].
Again, culprit, too. And now for the third:
?- append([], [X1], Zs).
Zs = [X1].
Verdict: All three kind-of guilty. That is, it suffices to blame one of them. Which one is up to you to choose.
Do this whenever you encounter a failing goal. It will help you gain the relational view that makes Prolog such a special language.
And if we are at it. It often helps to consider maximal failing generalizations. That is, generalizations that still fail but where each further step leads to success. In your example this is:
?- append([], [X1], [a,b]). % original query
false.
?- append([], [_], [_,_|_]). % maximal failing generalization
false.
From this you can already draw some conclusions:
The lists' elements are irrelevant.
Only the length of the three lists is of relevance
The third list needs to be two elements or longer.
See: append/3
append(?List1, ?List2, ?List1AndList2)
List1AndList2 is the concatenation of List1 and List2
So for
?- append([], [X1], [a,b]).
[] is the empty list and [X1] is a list with a variable X1
If you run the query like this
?- append([],[X1],A).
you get
A = [X1].
which means that A is the concatenation of [] and [X1].
In your query it is asking if the concatenation of [] and [X1] is [a,b] which is false, or no.
For your second query
? - append([], [a,b], [a,b])
it is asking if the concatenation of [] and [a,b] is [a,b] which is true, or yes.
How will Prolog respond to the following inquiry? Draw a search tree for the inquiry, too.
?- member(2, [2, a, X]).
So first of all, what does this inquiry mean?
Let's take another more clear example:
?- member(vincent,[yolanda,trudy,vincent,jules]).
Prolog will check if vincent is in the list. It checks one by one, so it will first compare vincent and yolanda. No match, now recursive rule aka go to second clause. Now it looks like that:
?- member(vincent,[trudy,vincent,jules]).
vincent and trudy, no match. Recursive rule:
?- member(vincent,[vincent,jules]).
vincent and vincent, match! So return true.
Back to our example. Prolog will immediately return true as 2 is in the list (namely the head of it).
But how will the search tree look like? I really have no idea and I'm scared they will ask me to draw a search tree in the test...
That query means
For which X is 2 an element of the list [2, a, X]?
Well, let's see how Prolog answers this:
?- member(2, [2, a, X]).
true
; X = 2.
The first answer we get is true which is the empty answer substitution. It means here that 2 is a member of that list for any X. Really any! Can this be true?
?- X = any, member(2, [2, a, X]).
X = any
; false. % that is no solution
It's even true for any!
Now back to the original query: The second answer is a simple solution X = 2. So Prolog tells us that also 2 might be such an element. Alas, we already know that, for we know that this holds for any term. And thus also 2. Therefore, the second answer is redundant.
You can avoid many such redundancies by using memberd/2 instead!
As for the search tree, member/2 always visits the entire list. One solution after the other. So the search tree only depends on the number of elements in the list.
I have been given a question in my assignment that asks to write a Prolog program that takes as input a list of numbers and succeeds if the list
contains only 0s.
I am having trouble on how to make the program search for zeroes. For example, a query like:
?- zero([0,0,0,0]).
Should give us true and it should return false whenever there's a number other than zero in it.
Usually, one would not define a proper predicate for this, but rather use maplist/2 for the purpose:
..., maplist(=(0), Zs), ...
To give a concrete example:
?- Zs =[A,B,C], maplist(=(0), Zs).
This query corresponds to:
?- Zs = [A,B,C], call(=(0), A), call(=(0), B), call(=(0), C).
or even simpler:
?- Zs = [A,B,C], 0 = A, 0 = B, 0 = C.
If you want to define this as a separate predicate, remember to use a good name for it. Each element of the list is a zero, and the relation describes the entire list of such zeros. The convention for lists in this case is to use the plural word. Thus zeros/1:
zeros([]).
zeros([0|Zs]) :-
zeros(Zs).
why are you asking us to do your homework for you?
anyway, it's very simple recursion. something like:
zero([]).
zero([0|T]) :- zero(T).
just keep peeling of zero's until your list is empty. it isn't so hard ;)