Sums of the elements in list - prolog

I have to say that there is a similar quetion Sum of elements in list in Prolog needs little explanation, but still makes me confused.
Here is the following solution which needs some explanation.
sum([H],H).
sum([H|T],R):-sum(T,P),R is H + P.
Lets say we do sum([1,2,3],R).
sum([1,2,3],R)
sum([2,3],<unknown-1>)
sum([3],<unknown-2>)
so where it will fulfill the fact sum([H],H) ?
I do write the variable in sum([H],H), the only output for this case is 3,
which means that in the unknown-2 here is 3, why?
Just a beginner in prolog and any answers will be great appreciate.

The short answer: unification.
When, within the scope of a predicate clause, a variable name occurs more than once, all occurrences will be unified with each other. The predicate for unification is =/2, and is declared as operator, so =(A, A) and A = A mean the same. More importantly, this:
=(Term, Term).
is the definition of =/2 (see the documentation!)
In your example, you have a clause that says:
sum([H], H).
This means:
When the first argument of sum/2 is a list with exactly one element, the second argument of sum/2 is that element.
Because term unification is such a fundamental operation in Prolog, usually, it is not spelled out explicitly, as for example:
When the first argument of sum/2 is a list with exactly one element, that element and the second argument of sum/2 are unified with each other.
At least in the SWI-Prolog documentation, if unification is involved, it is usually described with "X is Y" instead of "X and Y are unified". See, for example, the documentation of min_member/2:
min_member(Min, List).
True when Min is the smallest member in the standard order of terms. Fails if List is empty.
It doesn't explicitly tell you that unification is used, and from that, the following behavior follows:
?- min_member(3, [1,2,X]).
X = 3.
I once asked a question about this because I found it too confusing.
By the way, with your current definition of sum/2, you can also get surprises because of the way that unification works. Look:
?- sum([1.5, 2.5], Sum).
Sum = 4.0 ; % unnecessary choice point but at least correct
false.
?- sum([1.5, 2.5], 4).
false. % Oops!
The SWI-Prolog library implementation suffers from the same problem:
?- sum_list([1.5, 2.5], Sum).
Sum = 4.0. % no choice point, at least
?- sum_list([1.5, 2.5], 4).
false. % Oops!
The work-around is to leave the second argument a free variable at first, and then use =:=/2, which does arithmetic comparison of numbers:
?- sum_list([1.5, 2.5], Sum), Sum =:= 4.
Sum = 4.0.
You can do this with your definition of sum/2 as well.

sumList([],0).
sumList([X|Tail],Sum):-
sumList(Tail,Sum1),
Sum is Sum1+X.

Related

Instantiate arguments in Prolog

Consider the PROLOG predicate f(list,integer) with flow model (i,o).
f([],0).
f([H|T],S):-
f(T,S1),
S1 is S-H.
Give the result of the evaluation f([1,2,3,4,5,6,7,8],S)?Justify the answer.
I've seen that we get the error "Arguments are not sufficiently instantied" and that is because the value of S is not updated in the end(only when the list is empty). Is this a good justification?
I've seen that we get the error "Arguments are not sufficiently
instantied" and that is because the value of S is not updated in the
end(only when the list is empty). Is this a good justification?
If this code is supposed to fail, yes.
The correct wording is:
This predicate is called with an unbound variable on second position, either at the top or recursively vai f(T,S1) (where S1 is fresh and thus unbound).
Then the arithmetic evaluation
S1 is S-H.
will have an unbound variable on the right-hand side of is/2 and cannot proceed (i.e. it will throw).
But note that it works if you switch to "constraint satisfaction over finite domains":
?- use_module(library(clpfd)).
true.
Then replacing is/2 by #=:
f([],0).
f([H|T],S):-
f(T,S1),
S1 #= S-H.
yields a working program:
?- f([1,2,3,4,5,6,7,8],S).
S = 36.

Prolog and limitations of backtracking

This is probably the most trivial implementation of a function that returns the length of a list in Prolog
count([], 0).
count([_|B], T) :- count(B, U), T is U + 1.
one thing about Prolog that I still cannot wrap my head around is the flexibility of using variables as parameters.
So for example I can run count([a, b, c], 3). and get true. I can also run count([a, b], X). and get an answer X = 2.. Oddly (at least for me) is that I can also run count(X, 3). and get at least one result, which looks something like X = [_G4337877, _G4337880, _G4337883] ; before the interpreter disappears into an infinite loop. I can even run something truly "flexible" like count(X, A). and get X = [], A = 0 ; X = [_G4369400], A = 1., which is obviously incomplete but somehow really nice.
Therefore my multifaceted question. Can I somehow explain to Prolog not to look beyond first result when executing count(X, 3).? Can I somehow make Prolog generate any number of solutions for count(X, A).? Is there a limitation of what kind of solutions I can generate? What is it about this specific predicate, that prevents me from generating all solutions for all possible kinds of queries?
This is probably the most trivial implementation
Depends from viewpoint: consider
count(L,C) :- length(L,C).
Shorter and functional. And this one also works for your use case.
edit
library CLP(FD) allows for
:- use_module(library(clpfd)).
count([], 0).
count([_|B], T) :- U #>= 0, T #= U + 1, count(B, U).
?- count(X,3).
X = [_G2327, _G2498, _G2669] ;
false.
(further) answering to comments
It was clearly sarcasm
No, sorry for giving this impression. It was an attempt to give you a synthetic answer to your question. Every details of the implementation of length/2 - indeed much longer than your code - have been carefully weighted to give us a general and efficient building block.
There must be some general concept
I would call (full) Prolog such general concept. From the very start, Prolog requires us to solve computational tasks describing relations among predicate arguments. Once we have described our relations, we can query our 'knowledge database', and Prolog attempts to enumerate all answers, in a specific order.
High level concepts like unification and depth first search (backtracking) are keys in this model.
Now, I think you're looking for second order constructs like var/1, that allow us to reason about our predicates. Such constructs cannot be written in (pure) Prolog, and a growing school of thinking requires to avoid them, because are rather difficult to use. So I posted an alternative using CLP(FD), that effectively shields us in some situation. In this question specific context, it actually give us a simple and elegant solution.
I am not trying to re-implement length
Well, I'm aware of this, but since count/2 aliases length/2, why not study the reference model ? ( see source on SWI-Prolog site )
The answer you get for the query count(X,3) is actually not odd at all. You are asking which lists have a length of 3. And you get a list with 3 elements. The infinite loop appears because the variables B and U in the first goal of your recursive rule are unbound. You don't have anything before that goal that could fail. So it is always possible to follow the recursion. In the version of CapelliC you have 2 goals in the second rule before the recursion that fail if the second argument is smaller than 1. Maybe it becomes clearer if you consider this slightly altered version:
:- use_module(library(clpfd)).
count([], 0).
count([_|B], T) :-
T #> 0,
U #= T - 1,
count(B, U).
Your query
?- count(X,3).
will not match the first rule but the second one and continue recursively until the second argument is 0. At that point the first rule will match and yield the result:
X = [_A,_B,_C] ?
The head of the second rule will also match but its first goal will fail because T=0:
X = [_A,_B,_C] ? ;
no
In your above version however Prolog will try the recursive goal of the second rule because of the unbound variables B and U and hence loop infinitely.

Finding the longest list in Prolog?

I need to write a predicate longestList/2 such that longestList(L1,L2) is satisfied if L2 is the longest
nested list from the list of lists L1.
?- longestList([[1],[1,2],[1,2,3],[1,2,3,4]],LI).
LI = [[1, 2, 3, 4]] ;
No
?- longestList([[a,b,c],[d,e],[f,g,h]],LI).
LI = [[f, g, h],[a,b,c]];
No
Could someone please help me with intuition to go about solving it?
Here's an outline for a basic, recursive approach. Not quite as crisp as the answer #CapelliC gave, but on the same order of simplicity.
The idea is to traverse the list and keep track of the longest list you've seen so far, and what it's length is. Then you step through the list recursively and update these arguments for the recursion if the conditions indicate so. It's a slight elaboration on the technique used to do a recursive "max list element" predicate. To do this, you set up a call to include more arguments (the current longest list, and its length).
longestList([], []).
longestList([L|Ls], LongestList) :-
length(L, Length),
% Start with the first element (L) being my best choice so far
longestList(Ls, L, Length, LongestList).
Here is the expanded predicate with the new arguments.
longestList([L|Ls], LongestListSoFar, GreatestLengthSoFar, LongestList) :-
% Here, you need to examine L and determine if it should supersede
% the longest list so far and its length. You need to keep in mind that
% if the length of L is the same as the max length so far, then I
% may choose to keep the LongestListSoFar, or choose L. Both are
% valid solutions for this call. This is a good place to use the `;`
% operator, and to be cautious about parenthesizing expressions since
% the comma has higher precedence than the semi-colon.
% Also, you'll need to make a recursive call to longestList(Ls, ??, ??, LongestList).
% The arguments to the recursion will depend upon which way the decision flow goes.
%
% After all that to-do, don't let it scare you: it's about 5 lines of code :)
%
longestList([], LongestListSoFar, ??, ??).
% Fill in the ??. What should they be at list's end ([])?
% Do I even care now what the 3rd argument is?
Hopefully that's enough to give you something to think about to make progress. Or, use #CapelliC's solution and write the member_length/3 predicate. :) Note that, as in his solution, the above solution would generate each maximum list on backtracking if there are more than one. So, you could use findall/3 if you want to get all the solutions in one list.
member/2 will allow you to peek an element (a list for your case) from a list: so, if you have a member_length/3 predicate, you could code
longestList(Lists, Longest) :-
member_length(Lists, Longest, N),
\+ ( member_length(Lists, _Another, M), M > N ).
then to find all longest, you can use findall/3...
Following code, which uses if else, seem to work partially. It has to be called with 0 length and so one cannot get length itself from here.
longest_list([H|T], LongList, LongLen):-
length(H, Len),
(Len > LongLen ->
longest_list(T, [H], Len);
longest_list(T, LongList, LongLen)).
longest_list([],Finallist,_):-writeln(Finallist).
?- longest_list([[1,2,3], [3,4], [4,5,6,7,8], [5,3,4]], Longestlist, 0).
[[4,5,6,7,8]]
true.
However, the variable itself is not coming:
?- writeln(Longestlist).
_G1955
true.
It may give some ideas.

How to write number classifiers in prolog?

Playing with Prolog for the first time and while I thought I knew what it basically is good for, I find it hard to get anything done in it. So, I tried to find the easiest possible task and even fail to accomplish that.
I think it is due to me not knowing how prolog data types (numbers) are supposed to work or they have special syntax.
So, my first attempt to classify even numbers was:
even(0).
even(X) :- even(X-2).
Result: stack overflow for the query: even(2).
So I thought well if this is not it, then maybe it is:
even(0).
even(X+2) :- even(X).
Result of even(2): false.
So my simple question is: How to write such simple things in prolog? Is it all not working because i use numbers?
Why not do it the normal way:
is_even(X) :-
X /\ 0x1 =:= 0.
If you want to enumerate non-negative even numbers upon backtracking when the argument is not bound, this is a different thing altogether. It is probably easy to just say:
even(X) :-
between(0, infinite, X),
is_even(X).
You can use the second definition like this:
?- even(X).
X = 0 ;
X = 2 ;
X = 4 ;
X = 6 . % and so on
There are some differences between is_even/1 and even/1:
is_even/1 will work for any integer, positive or negative
is_even/1 will, surprisingly enough, work for expressions that evaluate to integers, too, for example, X = 3, ..., is_even(X + 1). This is because =:= accepts an arithmetic expression on either side.
even/1 uses between/3, so the domain of X and error conditions are the same as for the third argument of between/3.
As a consequence, even/1 does not work with negative integers or arithmetic expressions.
But wait, there's more!
Apparently, between(0, infinite, X) is not something you can do in almost any Prolog apart from SWI. So, instead, you can use another predicate that will enumerate positive integers (list lengths):
even_f(X) :-
length(_, X),
is_even(X).
(Thank you to #false for this)
Use is/2 to force the arithmetic evaluation. On their own, Prolog terms are just structural symbolic entities, X-2 is a compound term of arity 2, -(X,2):
3 ?- write_canonical( X-2 ).
-(_,2)
true.
But is is for arithmetic expressions:
4 ?- Z is 5-2.
Z = 3.
Your definition should thus be
even(X):- X=:=0 -> true
; X > 0 -> Y is X-2, even(Y).
The drawback of such definition is that it can't be called in a generative fashion, like even(X) to get all the evens generated one after the other.
It is only good for checking a given number. For simplicity, it ignores the negative numbers and always fails for them.

Prolog greater_than /2 succ

I'm new to Prolog and I'm trying to resolve this exercise:
Define a predicate greater_than/2 that takes two numerals in the notation that we introduced in this lecture (i.e. 0, succ(0), succ(succ(0))...) as arguments and decides whether the first one is greater than the second one. E.g:
?- greater_than( succ(succ(succ(0))), succ(0) ).
yes.
?- greater_than( succ(succ(0)), succ(succ(succ(0))) ).
no.
This is my answer so far:
greater_than(X, 0).
greater_than( succ(succ(X)), succ(Y) ).
but of course doesn't work properly, so I'm asking anyone for help.
Thanks.
As you are looking for a recursive solution, you have to provide a base case and a recursive step.
The base case you provided is almost right. However it fails because it will succeed for example when both numbers are zero. It should succeed only when the left side is of the form succ(_) and the right side is zero.
The recursive step should take an element from each side and apply recursion.
Therefore this should work:
greater_than(succ(_), 0).
greater_than(succ(X), succ(Y)):-
greater_than(X, Y).

Resources