Prolog - Arguments are not sufficiently instantiated. lists/recursion - list

I am trying to get the maximum number from a given list 'L' and assign it to a variable, so I used to write the following function:
max(L,X):-
[H|Q]=L,
(X<H -> X=H),
length(Q,QLEN),
(QLEN>0 -> max(Q,X)),
true.
However after compiling the code and prompting max([1,2,3],X) within SWI-Prolog, I get the following error:
ERROR: Arguments are not sufficiently instantiated ERROR: In: ERROR:
[9] _1064<1 ERROR: [8] max([1,2|...],_1092) at c:/users/kais/desktop/tp3.pl:24 ERROR: [7]
Why I'm getting such error?

As said in the comment you try to compare H with X which is not instantiated. A solution to this problem is to create a predicate maxList/3 and call it inside maxList/2 as follows:
maxList([H|T], Max) :-
maxList(T, H, Max).
maxList([], Max, Max).
maxList([H|T], Max0, Max) :-
Max1 is max(H, Max0),
maxList(T, Max1, Max).
?- maxList([1,2,3],X).
X = 3.
max/2 simply returns the max between two arguments. A possible implementation for max/2 could be:
myMax(M,A,B):-
A > B -> M = A;
M = B.
?- myMax(A,1,2).
A = 2.
BTW, there is already a built in predicate in SWI to do this, which is called max_list/2 (the code I posted before actually comes from this implementation):
?- max_list([1,2,3],X).
X = 3.

Another possible implementation, not relying on an auxiliary predicate, can be done according to the following logic:
If the list contains exactly one element, then it is the maximum.
If the list L contains more than one element, i.e. it is of the form [H|T], and the greatest element of T is M, then the greatest element of L will be H if H>=M, otherwise it will be M.
A rough encoding could be:
maxList([X],X).
maxList([H|T],H) :-
maxList(T,M),
H >= M.
maxList([H|T],M) :-
maxList(T,M),
H < M.
This leaves room for improvement, but respects the logic above stated and returns the greatest element for each non-empty integer list.

Related

Prolog - How to get the sum of a list's elements?

I'm very new to prolog and I am trying to write a little program that, given a list, returns the sum of the list's elements. Following all the examples I've seen led me to a solution that looks like this:
addup([],0).
addup([FirstNumber | RestOfList], Total) :-
addup(RestOfList, TotalOfRest),
Total is FirstNumber + TotalOfRest.
But when I test that solution with these values:
?- addup([1,2,3,4],0).
I just get garbage values from it like _34521.
Then I tried a second solution that looks like this:
sum([], 0).
sum([H|T], N):-
X is H+N,
sum(T, X).
This one is able to add up the numbers correctly, but it is unable to pass the final value of X, which is the true answer, into N. So for the test case:
?- sum([1,2,3,4], 0).
I get an answer of 6, the final value of N, and the second-to-last value of X, instead of 10, the final value of X. Any help and/or explanations of why neither of these solutions work would be greatly appreciated. Thanks.
Firstly, the sum of an empty list is 0 - this is the base case, which you already had.
Secondly, the sum N of an element H and a list T is the sum of the list T added to H. Prolog operates on unification, so this says that N is unified with the sum of H and T, where the sum of T is unified with X using sum(T,X).
sum([], 0).
sum([H|T], N):-
sum(T, X),
N is X + H.
This gives:
?- sum([1,2,3,4],N).
N = 10.
In your original question, ?- sum([1,2,3,4], 0). actually says "this is true if the sum of the list [1,2,3,4] is 0" - you need to pass a variable as the second argument to sum to be unified with the answer.
Further information:
_34521 is a representation of an unbound variable - this says that there is a variable, but that it has not yet been unified with a value.
Secondary consideration:
For a suitably long list, the implementation above will run out of stack space, as each frame of the recursion must be stored, so that the addition can happen from the bottom up. In order to prevent a stack error, we can use a tail-recursive accumulator like so:
sum(L, N):-
sum(L, 0, N).
sum([],N,N).
sum([H|T],A,N) :-
A1 is A + H,
sum(T,A1,N).
... which retains the signature of the original method, wrapping sum/3. As there is no choice-point in the body of the rule (given that A + H is always the same for a given A and H, and the list is either empty or not), Prolog will discard each frame as it leaves scope (as there is nothing more to be done with it) and, on completion, will return to the original caller.
Simplified stack for sum([1,2,3],N) in each instance:
non-tail-recursive:
rest-of-stack
rest-of-stack,sum([1|[2,3]],_1001)
rest-of-stack,sum([1|[2,3]],_1001),sum([2|[3]],_1002)
rest-of-stack,sum([1|[2,3]],_1001),sum([2|[3]],_1002),sum([3|[]],_1003)
rest-of-stack,sum([1|[2,3]],_1001),sum([2|[3]],_1002),sum([3|[]],_1003),sum([],0)
rest-of-stack,sum([1|[2,3]],_1001),sum([2|[3]],_1002),sum([3|[]],3)
rest-of-stack,sum([1|[2,3]],_1001),sum([2|[3]],5)
rest-of-stack,sum([1|[2,3]],6)
rest-of-stack
tail-recursive:
rest-of-stack
rest-of-stack,sum([1,2,3],_1001)
rest-of-stack,sum([1|[2,3]],0,_1001)
rest-of-stack,sum([2|[3]],1,_1001)
rest-of-stack,sum([3|[]],3,_1001)
rest-of-stack,sum([],6,6)
rest-of-stack
Note that the tail-recursive stack has a limited depth for any length of list (dependent on what is calling it), where the non-tail-recursive stack goes to a depth directly proportional to the length of the list.
Thus, a call such as N is 10^7,length(L,N),maplist(=(1),L),sum(L,N). (as raised by #false) will likely fail without tail-recursion, and likely succeed with it.

Prolog Calling predicates within predicates correctly

I have two predicates in Prolog, the first one does return a correct dot product of two lists(vectors w/e) ... the second is when you take a list times a list of lists(matrix) which will return a list. The second one fails when I try to pass anything such as ([1,2],[[3,4],[5,6],[7,8]], X). Anyone well versed in Prolog see my mistake? I am kinda stuck since tracing and prolog itself just returns a fail all the time.
getDotProd([],[],0.0).
getDotProd([H1|T1],[H2|T2], N):-
getDotProd(T1,T2,N1),
N is N1 + (H1 * H2).
vecTimesMatrix(_,[[]],[]).
vecTimesMatrix([List], [MH|Mtail],[N]):-
N is getDotProd(List, MH, _),
vecTimesMatrix(List, Mtail, N).
Updated Code thus far now:
getDotProd([],[],0.0).
getDotProd([H1|T1],[H2|T2], N):-
getDotProd(T1,T2,N1),
N is N1 + (H1 * H2).
vecTimesMatrix([],[[]],[]).
vecTimesMatrix([List], [MH|Mtail],[N]):-
getDotProd(List, MH, N),
vecTimesMatrix(List, Mtail, N).
Your remaining problem is in your vecTimesMatrix predicate:
vecTimesMatrix([],[[]],[]).
vecTimesMatrix([List], [MH|Mtail],[N]):-
getDotProd(List, MH, N),
vecTimesMatrix(List, Mtail, N).
Issues:
In the second clause, the first argument is given as [List] which would imply a list of a single element (List). Subsequent calls to getDotProd and vecTimesMatrix in the clause indicate that this should simply be List.
In the second clause, the third argument is shown simply as a list of one argument: [N]. So the third argument never "builds" a list. Additionally, the recursive call to vecTimesMatrix has N as its third argument, and that argument had already been instantiated by the prior query to getDotProd as the dot product of the vector List and the vectory MH. Logically, the recursive call should be saying that the vector product of List with Mtail is the tail of the final product.
The base case assumes that the first argument reduces to [], but this is not so. List always remains as-is throughout the recursive process. So instead of [] you should have _ (it will keep its value, but you don't care about it in the base case).
The base case has as a second argument [[]], but that's not the correct form for an empty list. That's actually a list consisting of one element, that element being the empty list. In reality, even though the second argument is a "list of lists", the empty list is still [].
Putting it all together (and renaming predicates per de facto conventions using underscores rather than camel case):
get_dot_prod([], [], 0.0). % Dot product of empty vectors is 0.0
% (Dot prod of vectors of unequal length
% is not defined and will fail)
get_dot_prod([H1|T1], [H2|T2], N) :- % N is dot product of [H1|T1] [H2|T2] if...
get_dot_prod(T1, T2, N1), % N1 is dot product of T1 T2, and
N is N1 + (H1 * H2). % N is N1 + (H1*H2) [evaluated]
vec_times_matrix(_, [], []). % Product of any vector with
% empty matrix is empty
vec_times_matrix(List, [MH|Mtail], [N|Ntail]):-
% [N|Ntail] is List x [MH|Mtail] if...
get_dot_prod(List, MH, N), % N is dot product of List and MH, and
vec_times_matrix(List, Mtail, Ntail). % Ntail is List x Mtail
This will yield:
| ?- vec_times_matrix([1,2],[[1,0],[0,1]], M).
M = [1.0,2.0] ? a
no
| ?- vec_times_matrix([1,2],[[1,0],[0,1],[1,1]], M).
M = [1.0,2.0,3.0] ? a
(1 ms) no
I added the comments in the code above to illustrate, in a simple way, how to think of the prolog predicate logic, which aids in defining them. As was pointed out already, the prolog "predicate" doesn't act as a "function". It describes a logical relation between entities which will either succeed or fail.
Once you learn to think how prolog thinks (relationally), you'll find it more enjoyable. :)
There are several problems in your code. First, you define both getDotProd/4 and getDotProd/3 predicates. The first one is a typo. I.e. you base case for the getDotProd/3 predicate have a duplicated argument and it should be:
getDotProd([], [], 0).
Second, in the second predicate, vecTimesMatrix/3, you have a goal, a call to the built-in predicate is/2, that will cause an exception:
N is getDotProd(List, MH, _)
You cannot define your own functions on standard Prolog. You need to replace that goal with:
getDotProd(List, MH, N)
There are other problems but this should help you progress.

Prolog: square numbers in a list

Ho do I square numbers in a list in prolog?
The list can contain numbers, atoms and lists.
for example: [a,b,2,3,4,[3],[c,d,9]] and the answer should be [a,b,4,9,16,[3],[c,d,9]].
As we see in the answer it should be a shallow squaring of the values in the list.
2->4
3->9
4->16
What I have tried so far,
square([],X).
square([A|B],X):-number(A), A is A*A, square(B,X).
X will contain squared values. Base case is when empty list is received. I check if head (A) is a number then I go ahead square the number and change A to A * A. Then go ahead and call the square function for remaining part B.
Please suggest where I am doing wrong.
EDIT: Correct answer as follows. By aBathologist. Please read his comment for detailed explanation.
squared_members([], []).
squared_members([L|Ls], [SqrdL|SqrdLs]) :-
number(L),
SqrdL is L * L,
squared_members(Ls, SqrdLs).
squared_members([L|Ls], [L|SqrdLs]) :-
\+number(L),
squared_members(Ls, SqrdLs).
And
squared_members([], []).
squared_members([L|Ls], [M|Ms]) :-
( number(L)
-> M is L * L, squared_members(Ls, Ms)
; M = L, squared_members(Ls, Ms)
).
We're defining a predicate which describes the relationship between one list, A, and another list, B: B should have all the same elements as A, except that any number in A should be squared in B.
Where you've gone wrong:
Your ground condition, square([],X), says that when A is empty, then B is anything (so, for instance, even something like square([], 15) is true). But this doesn't capture the meaning we're after, since the second argument should be a list with the same number of members as the first. That is, when the first list is empty then the second list should be empty.
The same problem occurs with your recursive rule, since, at each iteration, an undetermined variable is passed along, and there is never anything said about the relationship between the first list and the second.
This rule will only succeed if the first element of alist is a number. In the case where the first element is, e.g., a (like in your example), number(a) will be false. Since there are no additional rules for the predicate, it will simply be false unless every member of the first list is a number.
Variables in Prolog must always have the same, consistent value throughout the context in which they appear. They function like variables in arithmetic formula. The formula a + b - b = a is true for any values of a and b but *only if a and b are each assigned one, consistent value throughout the equation. The same is true in Prolog statements of the form <variable> is <expression>. What you've written says a = a * a which cannot be the case.
*What you're definition says is, roughly, this: The list B is a squared version of the list A if A is an empty list and B is anything OR if the first element of A is a number, and that number is equal to itself squared, and B is a squared version of the rest of A.
Here's one possible solution:
squared_members([], []).
squared_members([L|Ls], [SqrdL|SqrdLs]) :-
number(L),
SqrdL is L * L,
squared_members(Ls, SqrdLs).
squared_members([L|Ls], [L|SqrdLs]) :-
\+number(L),
squared_members(Ls, SqrdLs).
Notice that this definition is able to establish a meaningful relationship between the two lists by having them either share variables, or contain elements related by a chain of relations between variables (i.e., SqrdL is related to L by virtue of being L * L). This definition has one more clause then yours, which enables it to take account of the members of a list which are not numbers: those are added to the second list unaltered.
An alternative definition, using If-Then-Else notation for cleaner expression, would be the following:
squared_members([], []).
squared_members([L|Ls], [M|Ms]) :-
( number(L)
-> M is L * L, squared_members(Ls, Ms)
; M = L, squared_members(Ls, Ms)
).

How to add and compare members in a list

I'm trying to write a predicate is_multi(M), defined as:
every element of M has the form X / N, where X is an atom, and N is an integer greater than 0;
M does not contain two elements with the same atom, for what
is_multi([]).
is_multi([a / 2, b / 2]).
are satisfied, but
is_multi([a, b/2]).
is_multi([a/0, b/2]).
is_multi([a/2, 2/4])
is_multi([a/2, b/3, a/2])
is_multi([a/3, b/-4, c/1])
are not.
Here's what I have written so far:
is_multi(M) :- M = [].
is_multi(M) :-
M = [Head|Tail],
Head = X/N,
integer(N),
N > 0,
is_multi(Tail).
But it does not compare two elements if with the same atom. For example, is_multi([a/2, a/3]) is not satisfied. I got stuck for one day with this; could somebody give me some hints?
First, you can simplify your code considerably by moving some of your unifications from the body to the head.
is_multi([]).
is_multi([X/N|Tail]) :-
integer(N), N > 0,
is_multi(Tail).
Cleaning it up reveals one thing you're not doing here which is in your spec is checking that X is an atom. Fix by adding atom(X) to the body.
OK, so this takes care of the basic form, but doesn't ensure that the atoms do not repeat. The simplest thing to do would be to split this into two checks, one that checks that each item is well-formed, and one that checks that the list is well-formed. In fact, I would be inclined to use maplist/2 with a predicate that checks a single element. But all you really have to do is something like this:
is_valid([]).
is_valid([X/_|T]) :- is_valid(T), \+ memberchk(X/_, T).
This just says that the empty list is valid, and if the tail is valid, a list is valid if X over something doesn't occur in the tail.
If that's all you wanted, stop reading there. If you want to refactor, this is how I would approach it:
well_formed(X/N) :- atom(X), integer(N), N > 0.
no_repeating_numerators([]).
no_repeating_numerators([X/_|T]) :- no_repeating_numerators(T), \+ memberchk(X/_, T).
is_multi(L) :- maplist(well_formed, L), no_repeating_numerators(L).
Just to complete Daniel's instructive answer (+1 by me), I want to showcase how your task could be solved by means of some library predicates:
is_multi(L) :-
forall(select(E, L, R),
(E = A/N, atom(A), integer(N), N > 0, \+memberchk(A/_, R))).

Prolog length of a list

How can I calculate the length of a list
?- size_sub([[b,a,g], [9,3,7,4], [6]], X).
X = [3, 4, 1].
?- size_sub([[c,g,e,w], [7]], X).
X = [4, 1].
?- size_sub([], X).
X = [].
Ok you need to start with the base case which is the last answer
so size_sub([],X). is true if X=[] so first you write that as a rule.
size_sub([],[]).
Then you need to do the inductive step a list that is one longer than the previous. I am going to assume that you have a size/2 function for determining the size of a single list (if not please comment).
So the inductive step is going to operate on the length of the first parameter so N->N+1. We would represent this by striping off the head of the list syntax will be [H|T] now the second parameter (your answer) is going to be the length of H with the result of calling size_sub on T. As we cannot specify rules in the parameters in the header we will use N to represent the length of H and T2 to represent the result of size_sub on T.
So the first part of the rule becomes size_sub([H|T],[N|T2]):-
now we follow it with the predicates that will assert the values for N and T2.
size(H,N),
size_sub(T,T2).
putting that all together you get
size_sub([],[]).
size_sub([H|T],[N|T2]):-
size(H,N),
size_sub(T,T2).
size/2 is a far simpler case and following the same process of base + inductive you should be able to create the rules for it. Please comment if you need further help.
** EDIT - Request for size/2 definition **
To define size/2
Start with the base case, the empty list has a size of 0.
size([],0).
Now the inductive step. The size of list of length(N+1) is the size of a list of length(N). So lets define our list as [_|T] I've defined the list using _ to represent the head because we never use it so we can just use the anonymous variable. Lets use N to represent the length of T, and M to be N+1.
so
size([_|T],M):-
now lets define N
size(T,N),
and finally assert that M is equal to N + 1
M is N+1.
so putting everything together
size([],0).
size([_|T],N):-
size(T,M),
N is M+1.
size_sub([],[]).
size_sub([H|T],[N|T2]):-
size(H,N),
size_sub(T,T2).
To map length/2 over a list of lists, we can use the meta-predicate maplist/3 like this:
size_sub(Xss,Ls):-
maplist(length,Xss,Ls).