Function to find a list in prolog - prolog

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.

Related

Prolog Program Not Merging Sorted Lists Correctly

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.

Define the predicate Prolog

I'm reviewing some exercise for the coming test and having difficulty at this.
Given a list of integers L, define the predicate: add(L,S) which returns a list of integers S in which each element is the sum of all the elements in L up to the same position.
Example:
?- add([1,2,3,4,5],S).
S = [1,3,6,10,15].
So my question is what define the predicate means? It looks pretty general. I've read some threads but they did not provide much. Thanks!
This is a good exercise to familiarize yourself with two important Prolog concepts:
declarative integer arithmetic to reason about integers in all directions
meta-predicates to shorten your code.
We start with a very simple relation, relating an integer I and a sum of integers S0 to a new sum S:
sum_(I, S0, S) :- S #= S0 + I.
Depending on your Prolog system, you may need a directive like:
:- use_module(library(clpfd)).
to use declarative integer arithmetic.
Second, there is a powerful family of meta-predicates (see meta-predicate) called scanl/N, which are described in Richard O'Keefe's Prolog library proposal, and already implemented in some systems. In our case, we only need scanl/4.
Example query:
?- scanl(sum_, [1,2,3,4,5], 0, Sums).
Sums = [0, 1, 3, 6, 10, 15].
Done!
In fact, more than done, because we can use this in all directions, for example:
?- scanl(sum_, Is, 0, Sums).
Is = [],
Sums = [0] ;
Is = [_2540],
Sums = [0, _2540],
_2540 in inf..sup ;
Is = [_3008, _3014],
Sums = [0, _3008, _3044],
_3008+_3014#=_3044 ;
etc.
This is what we expect from a truly relational solution!
Note also the occurrence of 0 as the first element in the list of partial sums. It satisfies your textual description of the task, but not the example you posted. I leave aligning these as an exercise.
Define the predicate simply means write a predicate that does what the question requires.
In your question you have to write the definition of add/2 predicate( "/2" means that it has two arguments). You could write the definition below:
add(L,S):- add1(L,0,S).
add1([],_,[]).
add1([H|T],Sum,[H1|T1]):- H1 is Sum+H,NSum is Sum+H,add1(T,NSum,T1).
The above predicate gives you the desired output. A simple example:
?- add([1,2,3,4,5],S).
S = [1, 3, 6, 10, 15].
I think the above or something similar predicate is what someone would wait to see in a test.
Some additional information-issues
The problem with the predicate above is that if you query for example:
?- add(S,L).
S = L, L = [] ;
ERROR: is/2: Arguments are not sufficiently instantiated
As you see when you try to ask when your predicate succeeds it gives an obvious solutions and for further solutions it throws an error. This is not a very good-desired property. You could improve that by using module CLPFD:
:- use_module(library(clpfd)).
add(L,S):- add1(L,0,S).
add1([],_,[]).
add1([H|T],Sum,[H1|T1]):- H1 #= Sum+H,NSum #= Sum+H,add1(T,NSum,T1).
Now some querying:
?- add([1,2,3,4,5],S).
S = [1, 3, 6, 10, 15].
?- add(S,[1,3,6]).
S = [1, 2, 3].
?- add(S,L).
S = L, L = [] ;
S = L, L = [_G1007],
_G1007 in inf..sup ;
S = [_G1282, _G1285],
L = [_G1282, _G1297],
_G1282+_G1285#=_G1307,
_G1282+_G1285#=_G1297 ;
...and goes on..
As you can see now the predicate is in the position to give any information you ask! That's because now it has a more relational behavior instead of the functional behavior that it had before due to is/2 predicate. (These are some more information to improve the predicate's behavior. For the test you might not be allowed to use libraries etc... so you may write just a simple solution that at least answers the question).

Why do I get duplicate results in my `length/2` implementation in prolog?

I'm working through exercises in Prolog. I've implemented a predicate similar to length/2 (called ue_length here) like this:
%%
% ue_length/2
%%
% not a list predicate
\+(T) :- call(T), !, fail.
\+(_).
% target case
ue_length(List, Length) :- \+(is_list(List)), !, fail.
ue_length(List, Length) :- ue_length(List, 0, Length).
% standard cases
ue_length([], Length, Length).
ue_length([X], Part, Length) :- ue_length([], [Part], Length).
ue_length([X| Rest], Part, Length) :- ue_length(Rest, [Part], Length).
The result is supposed to be a term rather than a number: 0 for [], [0] for a list of length one and [...[0]...] (n brackets) for a list of length n.
When I query Prolog (SWI-Prolog 6) with e.g. [1,2,3,4,5] I get the correct result twice.
?- ue_length([1,2,3,4,5], X).
X = [[[[[0]]]]]
X = [[[[[0]]]]].
I'm new to Prolog. Can someone explain why I get a redundant result?
Minimize the problematic query
As a first step, reduce the size of your query. The same problem (redundant solutions) can be observed already with ue_length([1], X). alone.
But there is something else which is much more problematic:
Is your definition a relation?
?- ue_length(L,N).
false.
So your definition succeeds with a list [1] but fails with a variable in its place? This does not make any sense at all! Even looping would be a better behavior.
Another problematic case is
?- ue_length(L,0).
false.
Here, your definition should give L = [] as answer.
The culprit for this is the test using is_list/1. Simply drop the rule
ue_length(List, Length) :- \+(is_list(List)), !, fail. % incorrect!
Now your definition can also be used to ask the most general query which contains distinct variables in the arguments.
?- ue_length(L,N).
L = [], N = 0
; L = [_A], N = [0]
; L = [_A], N = [0]
; L = [_A, _B], N = [[0]]
...
This is one of the very nice properties of Prolog: You do not need to type in concrete data for your test cases. Just enter the most general query like a pro, and Prolog will do the rest for you.
Localize with false
To localize this redundancy, first think of how that could have happened. One simple possibility is that some clause in your program is redundant and can thus be deleted.
Let's say it's the last one. So I will insert a goal false into the last clause. And I try again the most general query. Alas ...
ue_length(List, Length) :- ue_length(List, 0, Length).
% standard cases
ue_length([], Length, Length).
ue_length([_X], Part, Length) :-
ue_length([], [Part], Length).
ue_length([_X| Rest], Part, Length) :-
false,
ue_length(Rest, [Part], Length).
?- ue_length(L,N).
L = [], N = 0
; L = [_A], N = [0]
; false.
That rule must be quite important, for now we get only answers for lists of length zero and one. So my guess was wrong. But my point is that you can see this very easily by simply using the most general query. The actual redundant clause is the other one. And don't forget to ask the most general query such that you can be sure you get all your answers!

Prolog List Squaring, Modifying element in List

I am trying to write a short Prolog program which takes a list of numbers and returns a list where all numbers have been squared.
Ie: [2,4,5] => [4,16,25]
My code so far:
list_of_squares([X], L) :-
L is X^2.
list_of_squares([X|XS], [X^2|M]) :-
list_of_squares(XS, M).
For some reason though Prolog doesn't like me squaring X while adding it to a list... Any thoughts on how I could do this?
You're not that far off, but you make two small mistakes:
Firstly, you mix element X with list L. Your first clause should be:
list_of_squares([X], [Y]):-
Y is X ^ 2.
Secondly, you cannot perform an arithmetic function in list notation.
Your second clauses should be as follows:
list_of_squares([X|Xs], [Y|Ys]):-
Y is X ^ 2,
list_of_squares(Xs, Ys).
Thirdly, there is a more fundamental problem. With the first two fixes, your code works, but the base case, i.e. the first clause, is not that well chosen. (A) the code cannot process the empty list. (B) For a singleton list the code is needlessly nondeterministic, because both clauses apply. This is solved by choosing the base case wisely:
squares([], []).
squares([X|Xs], [Y|Ys]):-
Y is X ^ 2,
squares(Xs, Ys).
Here is a general method how you can localize such an error. First, let's start with your exemple:
?- list_of_squares([2,4,5],[4,16,25]).
false.
Oh no! It fails! There is a very general method what to do in such a situation:
Generalize the query
So we replace [4,16,25] by a new, fresh (ah, true freshness!) variable:
?- list_of_squares([2,4,5],L).
L = [2^2,4^2|25]
; false.
That's way better: Now you know that there is a "result", but that result it not what you expected.
Next,
Minimize the query
The list is way too long, so I will chop off some elements. Say, the first two:
?- list_of_squares([5],L).
L = 25
; false.
Again, wrong, but smaller. Now, where is the error for that? To get it
Specialize your program
list_of_squares([X], L) :-
L is X^2.
list_of_squares([X|XS], [X^2|M]) :- false,
list_of_squares(XS, M).
That program, again gives the same wrong answer! So in there is a bug in the visible part. What we expect is
?- list_of_squares([5],[25]).
false.
this to succeed. But where is the error? Again:
Generalize the query
?- list_of_squares([5],[X]).
false.
HET!
Now, you should realize that that rule might be:
list_of_squares([X], [Y]):-
Y is X ^ 2.
And the same (is)/2 should be used in the recursive rule. And, why not accept [].
I, personally, would rather write using library(lambda):
list_of_squares(Xs, Ys) :-
maplist(\X^XX^(XX is X^2), Xs, Ys).
Or, even better, using library(clpfd)
list_of_squares(Xs, Ys) :-
maplist(\X^XX^(XX #= X^2), Xs, Ys).
Prolog doesn't have a 'functional' mindset, but some standard builtin predicate can help working with lists. In this case
list_of_squares(L,S) :- findall(Sq,(member(E,L),Sq is E*E),S).
?- list_of_squares([2,4,5], R).
R = [4, 16, 25].
in this case, member/2 play a role similar to lambda expressions, giving a 'name' to each element E available in L. findall/3 compute all solutions of its goal ,(member(E,L),Sq is E*E),, and collects results (the 'template' expression, that is, Sq).

Why prolog outputs a weird tree-like list?

In this Prolog code I intend to list the first N primes,
(...)
biggerPrime(N,P) :-
isPrime(N),
P is N,
!.
biggerPrime(N,P) :-
N1 = N+1,
biggerPrime(N1,P).
primeListAcc(0,A,R,R) :- !.
primeList(N,L) :-
primeListAcc(N,1,[],L).
primeListAcc(N,A,L,R) :-
N1 is N-1,
biggerPrime(A,P),
A1 is P+1,
primeListAcc(N1,A1,[P|L],R).
And it works fine if I want the list ordered backwards:
?- primeList(5,L).
L = [11, 7, 5, 3, 2].
But if I change the last line of the code from [P|L] to [L|P] like this:
primeListAcc(N,A,L,R) :-
N1 is N-1,
biggerPrime(A,P),
A1 is P+1,
primeListAcc(N1,A1,[L|P],R).
I get:
?- primeList(5,L).
L = [[[[[[]|2]|3]|5]|7]|11].
What am I missing? This is driving me mad!
Recall that a list is either the empty list [] or a term with functor '.' and two arguments, whose second argument is a list. The syntax [P|Ps] is shorthand notation for the term '.'(P, Ps), which is a list if Ps is a list (as is the case in your example). The term '.'(Ps, P), on the other hand, which can also be written as [Ps|P] (as you are doing), is not a list if P is not a list. You can obtain a reverse list with reverse/2.
Great, so you've discovered the problem of adding elements to the end of a list. In Prolog, we can do it with
add(X,L,Z):- L=[X|Z].
wait, what? How to read this? We must know the calling convention here. We expect L and Z to come in as uninstantiated variables, and we arrange for L from now on to point to a newly created cons node with X at its head, and Z its tail. Z to be instantiated, possibly, in some future call.
IOW what we create here is an open-ended list, L = [X|Z] = [X, ...]:
primeList(N,L) :-
primeListAcc(N,1,[],L).
primeListAcc(N,A,Z,L) :- N > 0, % make it explicitly mutually-exclusive,
N1 is N-1, % do not rely on red cuts which are easily
biggerPrime(A,P), % invalidated if clauses are re-arranged!
A1 is P+1,
L = [P|R], % make L be a new, open-ended node, holding P
primeListAcc(N1,A1,Z,R). % R, the tail of L, to be instantiated further
primeListAcc(0,A,R,R). % keep the predicate's clauses together
We can see now that Z is not really needed here, as it carries the [] down the chain of recursive calls, unchanged. So we can re-write primeListAcc without the Z argument, so that its final clause will be
primeListAcc(0,A,R):- R=[].
Keeping Z around as uninstantiated variable allows for it to be later instantiated possibly with a non-empty list as well (of course, only once (unless backtracking occurs)). This forms the basis of "difference list" technique.
To answer your literal question - here, consider this interaction transcript:
1 ?- X=[a|b].
X = [a|b]
2 ?- X=[a|b], Y=[X|c].
X = [a|b]
Y = [[a|b]|c]
the [a|b] output is just how a cons node gets printed, when its tail (here, b) is not a list. Atoms, as numbers, are not lists.

Resources