is_list/1 and free variables - list

Here is a first observation:
?- is_list([]), is_list([_,_,_]).
true.
Here is another observation:
?- [] = _, [_,_,_] = _.
true.
Therefore, why would is_list/1 be implemented such that
?- is_list(_).
false.
or
?- is_list([_|_]).
false.
when _ can clearly be unified with a list? Wouldn't that be logically sounder that it be true?
In SWI-Prolog's documentation for is_list/1, a note says: 
In versions before 5.0.1, is_list/1 just checked for [] or [_|_] and proper_list/1 had the role of the current is_list/1. The current definition conforms to the de facto standard.
Why is that the de facto standard?

As you correctly observe, is_list/1 is unsound, or rather incomplete, because it incorrectly says that there are no solutions whatsoever when the most general query is posed.
?- is_list(Ls).
false.
No list exists? Come on!
This unfortunate trait is shared by all hereditary type checking predicates like atom/1, integer/1 etc., whose incorrectness was obvious already when these predicates were conceived yet pushed through after labeling those who correctly opposed their suggested semantics as "purists" (which, at that time, lacked the complimentary character the word has since acquired).
Cases like:
?- is_list(Ls), Ls = [].
false.
?- Ls = [], is_list(Ls).
Ls = [].
clearly illustrate that something is fundamentally broken from a logical point of view with such non-monotonic tests. "Prolog's (,)/2 is not logical conjunction", yes, if you use illogical predicates in the first place in your code. Otherwise, (,)/2 is always a logical conjunction of goals.
A clean and logically correct way out is to throw instantiation errors in cases that cannot yet be determined.
library(error) and in particular must_be/2 go into a sound direction after the incorrectness of inherited illogical predicates has become unbearable even for casual users of Prolog:
?- must_be(list, X).
Arguments are not sufficiently instantiated
?- must_be(list, [_|_]).
Arguments are not sufficiently instantiated
?- must_be(list, [a,b,c]).
true.
must_be/2 is easy to use and a good first step towards more correct logic programs. Other constructs also appear on the horizon, and I hope others comment on the current status.
And now for the actual wording: Putting aside the fundamental problem outlined above, the contention alluded to in the SWI documentation is whether checking the outermost functor suffices to regard a term as a list, or whether the list must actually conform to the inductive definition of a list, which is:
the atom [] is a list.
if Ls is a list, then '.'(_, Ls) is a list.
Note that in recent SWI versions, [] is not even an atom, so it again breaks with this notion.

Related

Is it correct to use 'if' in Prolog this way?

Recently I started to learn logic programming and using Prolog, and a few days ago I found out that conditional statements can be used in Prolog as well.I am wondering, if I have a predicate that must be called in both cases, is it correct to write the code this way:
process(args) :-
(condition -> process_args1; process_args2),
predicateCalledAnyway.
instead of calling it in both cases, like this:
process(args) :-
(condition -> process_args1, predicateCalledAnyway; process_args2, predicateCalledAnyway).
Is there any difference? If yes, what and why? For me it seems the code produces the same results in both cases.
These forms to write the code are equivalent.
The first version is shorter and makes it easier to spot the common parts.
However, note the more fundamental problems that are inherent to both versions: (->)/2 impurely commits to the first solution of the condition, and in general, ( Cond -> Then ; Else ) is only sound if Cond is sufficiently instantiated.
For example:
?- ( member(X, [a,b,c]) -> false ; true ).
false.
Yet, adding a constraint suddenly makes this succeed:
?- X = d, ( member(X, [a,b,c]) -> false ; true ).
X = d.
Declaratively, we expect that adding a constraint leads to a specialization, not a generalization of the program!
Therefore, use (->)/2 with extreme caution: In general, it will break one of the most valuable properties of your Prolog programs, namely their relational nature that allows you to use your predicates in multiple directions and modes.
If at all possible, use either pure Prolog clauses, or the pure if_/3 predicate. See also the related constructs (*->)/2 and if/3 (in SICStus).

Prolog union fails

I'm trying to understand the use of union (the built in predicate) in Prolog. In many cases it seems to fail when it should succeed. It seems it has something to do with the order of the elements of the lists. All of the below cases fail (they come back with "false.").
?- union([1,2,3],[],[2,3,1]).
?- union([1,5,3], [1,2], [1,5,3,2]).
?- union([4,6,2,1], [2], [1,2,4,6]).
?- union([1,2], [], [2,1]).
Shouldn't all of these be true? Any explanation as to why these cases keep failing would be very helpful.
Also: Why does the below not succeed and find the correct list for A?
?- union([1,5,3], A, [4,1,5,3,2]). /** comes back with "fail." */
There are a couple of issues here. Declarative and procedural ones. Let's start with the declarative ones, they are really sitting a bit deeper. The procedural aspects can be handled easily with appropriate programming techniques, as in this answer.
When we consider declarative properties of a predicate, we consider its set of solutions. So we pretend that all we care about is what solutions the predicate will describe. We will completely ignore how all of this is implemented. For very simple predicates, that's a simple enumeration of facts - just like a database table. It is all obvious in such situations. It becomes much more unintuitive if the set of solutions is infinite. And this happens so easily. Think of the query
?- length(Xs,1).
This harmless looking query asks for all lists of length one. All of them! Let me count - that's infinitely many!
Before we look at the actual answer Prolog produces, think what you would do in such a situation. How would you answer that query? Some of my feeble attempts
?- length(Xs,1).
Xs = [1]
; Xs = [42]
; Xs = [ben+jerry]
; Xs = [feel([b,u,r,n])]
; Xs = [cromu-lence]
; Xs = [[[]]]
; ... . % I am running out of imagination
Should Prolog produce all those infinitely many values? How much time would this take? How much time do you have to stare at walls of text? Your lifetime is clearly not enough.
Taming the number of solutions, from solutions to answers
There is a way out: The logic variable!
?- length(Xs, 1).
Xs = [_A].
% ^^
This little _A permits us to collapse all strange solutions into a single answer!
So here we really had a lot of luck: we tamed the infinity with this nice variable.
Now back to your relation. There, we want to represent sets as lists. Lists are clearly not sets per se. Consider the list [a,a] and the list [a]. While they are different, they are meant to represent the same set. Think of it: How many alternate representations are there for [a]? Yep, infinitely many. But now, the logic variable cannot help us to represent all of them compactly1. Thus we have to enumerate them one-by-one. But if we have to enumerate all those answers, practically all queries will not terminate due to infinitely many solutions to enumerate explicitly. OK, some still will:
?- union([], [], Xs).
Xs = [].
And all ground queries. And all failing queries. But once we have a variable like
?- union([a], [], Xs).
Xs = [a]
; Xs = [a,a]
; Xs = [a,a,a]
; ... .
we already are deep into non-termination.
So given that, we have to make some decisions. We somehow need to tame that infinity. One idea is to consider a subset of the actual relation that leans somehow to a side. If we want to ask questions like union([1,2],[3,4], A3) then it is quite natural to impose a subset where we have this functional dependency
A1, A2 → A3
With this functional dependency we now determine exactly one value for A3 for each pair of A1, A2. Here are some examples:
?- union([1,5,3], [1,2], A3).
A3 = [5,3,1,2].
?- union([1,2,3], [], A3).
A3 = [1,2,3].
Note that Prolog always puts a . a the end. That means Prolog says:
Dixi! I have spoken. There are no more solutions.
(Other Prologs will moan "No" at the end.) As a consequence, the queries (from your comments) now fail:
?- union([1,5,3], [1,2], [1,5,3,2]).
false.
?- union([1,2,3],[],[2,3,1]).
false.
So imposing that functional dependency now restricts the set of solutions drastically. And that restriction was an arbitrary decision of the implementer. It could have been different! Sometimes, duplicates are removed, sometimes not. If A1 and A2 both are duplicate free lists, the result A3 will be duplicate free, too.
After looking into its implementation, the following seems to hold (you do not need to do this, the documentation should be good enough - well it isn't): The elements in the last argument are structured as follows and in that order:
The elements of A1 that do not occur in A2, too. In the relative order of A1.
All elements of A2 in their original order.
So with this functional dependency further properties have been sneaked in. Such as that A2 is always a suffix of A3! Consequently the following cannot be true, because there is no suffix of A3 that would make this query true:
?- union([1,5,3], A2, [4,1,5,3,2]).
false.
And there are even more irregularities that can be described on a declarative level. Often, for the sake of efficiency, relations are too general. Like:
?- union([],non_list,non_list).
Such concerns are often swiped away by noting that we are only interested in goals with arguments that are either lists (like [a,b]) or partial lists (like [a,b|Xs]).
Anyway. We finally have now described all the declarative properties we expect. Now comes the next part: That relation should be implemented adequately! There again a new bunch of problems awaits us!
With library(lists) of SWI, I get:
?- union([1,2], [X], [1,2,3]).
false.
?- X = 3, union([1,2], [X], [1,2,3]).
X = 3.
Which is really incorrect: This can only be understood procedurally, looking at the actual implementation. This no longer is a clean relation. But this problem can be fixed!
You can avoid the correctness issues altogether by sticking to the pure, monotonic subset of Prolog. See above for more.
1) To tell the truth, it would be possible to represent that infinite set with some form of constraints. But the mere fact that there is not a single library for sets provided by current Prolog systems should make it clear that this is not an obvious choice.

Prolog Predicate Solution

I am going through some past exam questions for my prolog exam that is coming up.
Here is the question:
(a) Write a predicate insert(Xs, Y, Zs) that holds when Zs is the list obtained
by inserting Y into the list Xs. A query such as:
? - insert([1,2,3], 4, Zs).
should succeed four times and give the following answers:
Zs = [4, 1, 2, 3]
Zs = [1, 4, 2, 3]
Zs = [1, 2, 4, 3]
Zs = [1, 2, 3, 4].
I'm a bit concerned because I have no idea where to start. Would anyone be able to help out as I need example solutions to practice for my exam.
Would really appreciate any help with this.
We start by changing the terrible name of this predicate: The predicate should describe what holds, not what to do. The name should reflect that. I suggest list_with_element/3, and encourage you to try finding even better names, ideally making clear what each argument stands for.
Then, we do what we set out to do: Describe the cases that make this relation hold.
For example:
list_with_element([], E, [E]).
list_with_element([L|Ls], E, [E,L|Ls]).
list_with_element([L|Ls0], E, [L|Ls]) :-
...
I leave filling in the ... as an easy exercise. State the condition that is necessary for the clause head to be true!
EDIT: I would like to say a bit more about the pattern above. In my experience, a good way—and definitely in the beginning—to reason about predicates that describe lists is to consider two basic cases:
the atom [], denoting the empty list
terms of the form '.'(E, Es), also written as [E|Es], where E is the first element of the list and Es is again a list.
This follows the inductive definition of lists.
The drawback in this specific case is that this approach leads to a situation where case (2) again needs to be divided into two subcases, and somehow unexpectedly necessitates three clauses to handle the two basic cases. This obviously runs counter to our intuitive expectation that two clauses should suffice. Indeed they do, but we need to be careful not to accidentally lose solutions. In this case, the first two clauses above are both subsumed by the fact:
list_with_element(Ls, E, [E|Ls]).
Every experienced Prolog coder will write such predicates in this way, or just, as in this case, use select/3 directly. This is what #lurker sensed and hinted at, and #tas correctly shows that a different clause (which is easy to come up with accidentally) does not fully subsume all cases we want to express.
Thus, I still find it a lot easier to think first about the empty list explicitly, make sure to get that case correct, then continue with more complex cases, and then see if you can write the existing program more compactly. This is the way I also used for this sample code, but I did not make it as short as possible. Note that with monotonic code, it is completely OK to have redundant facts!
Note that is is specifically not OK to just replace the first two clauses by:
list_with_element([L|Ls], E, [E|Ls]).
because this clause does not subsume case (1) above.
I guess that one answer that the question might be looking for goes along these lines:
insert(List, Element, NewList) :-
append(Front, Back, List), % split list in two
append(Front, [Element|Back], NewList). % reassemble list
If you would like a declarative reading:
NewList has Element between the front and the back of List.
Check carefully if append/3 or a predicate with the same semantics appears in the earlier questions or the study material.
And note that this is in essence the exact same solution as the suggestion by #mat, if I understand it correctly. Consult the textbook definition of append/3 for details. Or even better, look at the textbook definition of append/3 and adapt it to use if for "inserting".
There is a built-in predicate select/3 that does the same thing, although with the arguments in a different order.
Remember that (if defined correctly) a predicate can work in different directions. For instance, it can tell you what a list would look like after removing an element, it can (although it's fairly trivial) tell you what element to remove from one list to get another, or it can tell you what lists, after having a given element removed, would resemble a given list.
(Hint: you may want to look into that last one).

Define a rule to determine if a list contains a given member

I have recently started learning prolog, and facing a problem with this question:
Define a rule to determine if a list contains a given member.
I searched all over stack overflow to get some links to understand this problem better and write solutions for it but couldn't find anything. Could anyone of you advice to solve this particular problem?
My Approach:
Iterative over the list and see if your member matches with head:
on(Item,[Item|Rest]). /* is my target item on the list */
on(Item,[DisregardHead|Tail]):-
on(Item,Tail).
Do you think my approach is correct?
What you have is indeed a "correct" implementation. The standard name for a predicate that does that is member/2, and is available (under that name) in any Prolog, and should be quite easy to find once you know its name.
Some things to note however. First, with the classical definition (this is exactly as in "The Art of Prolog" by Sterling and Shapiro, p. 58, and identical to yours):
member_classic(X, [X|Xs]).
member_classic(X, [Y|Ys]) :-
member_classic(X, Ys).
If you try to compile this, you will get singleton errors. This is because you have named variables that appear only once in their scope: the Xs in the first clause and the Y in the second. This aside, here is what the program does:
?- member_classic(c, [a,b,c,x]).
true ;
false.
?- member_classic(c, [c]).
true ;
false.
?- member_classic(X, [a,b,c]).
X = a ;
X = b ;
X = c ;
false.
In other words, with this definition, Prolog will leave behind a choice point even when it is quite obvious that there could not be further solutions (because it is at the end of the list). One way to avoid this is to use a technique called "lagging", as demonstrated by the SWI-Prolog library implementation of member/2.
And another thing: with your current problem statement, it might be that this is considered undesirable behaviour:
?- member_classic(a, [a,a,a]).
true ;
true ;
true ;
false.
There is another predicate usually called member_check/2 or memberchk/2 which does exactly what you have written, namely, succeeds or fails exactly once:
?- memberchk(a, [a,a,a]).
true.
?- memberchk(a, [x,y,z]).
false.
It has, however, the following behaviour when the first argument is a variable that might be undesirable:
?- memberchk(X, [a,b,c]).
X = a. % no more solutions!
There are valid uses for both member/2 and memberchk/2 IMHO (but interestingly enough, some people might argue otherwise).
Yes, your solution is correct and works in all directions. Nice!
Notes:
Your solution is in fact more general than what the task asks for. This is a good thing! The task, in my view, is badly worded. First of all, the first clause is not a rule, but a fact. It would have been better to formulate the task like: "Write a Prolog program that is true if a term occurs in a list." This leaves open other use cases that a good solution will also automatically solve, such as generating solutions.
This common predicate is widely known as member/2. Just like your solution, it also works in all directions. Try for example ?- member(E, Ls).
The name for the predicate could be better. A good naming convention for Prolog makes clear what each argument means. Consider for example: element_list/2, and start from there.

Implementing "last" in Prolog

I am trying to get a feel for Prolog programming by going through Ulle Endriss' lecture notes. When my solution to an exercise does not behave as expected, I find it difficult to give a good explanation. I think this has to do with my shaky understanding of the way Prolog evaluates expressions.
Exercise 2.6 on page 20 calls for a recursive implementation of a predicate last1 which behaves like the built-in predicate last. My attempt is as follows:
last1([_ | Rest], Last) :- last1(Rest, Last).
last1([Last], Last).
It gives the correct answer, but for lists with more than one element, I have to key in the semicolon to terminate the query. This makes last1 different from the built-in last.
?- last1([1], Last).
Last = 1.
?- last1([1, 2], Last).
Last = 2 ;
false.
If I switch the order in which I declared the rule and fact, then I need to key in the semicolon in both cases.
I think I know why Prolog thinks that last1 may have one more solution (thus the semicolon). I imagine it follows the evaluation sequence
last1([1, 2], Last).
==> last1([2], Last).
==> last1([], Last). OR Last = 2.
==> false OR Last = 2.
That seems to suggest that I should look for a way to avoid matching Rest with []. Regardless, I have no explanation why switching the order of declaration ought to have any effect at all.
Question 1: What is the correct explanation for the behavior of last1?
Question 2: How can I implement a predicate last1 which is indistinguishable from the built-in last?
Question 1:
Prolog systems are not always able to decide whether or not a clause will apply prior to executing it. The precise circumstances are implementation dependent. That is, you cannot rely on that decision in general. Systems do improve here from release to release. Consider as the simplest case:
?- X = 1 ; 1 = 2.
X = 1
; false.
A very clever Prolog could detect that 1 = 2 always fails, and thus simply answer X = 1. instead. On the other hand, such "cleverness" is very costly to implement and time is better spent for optimizing more frequent cases.
So why do Prologs show this at all? The primary reason is to avoid asking meekly for another answer, if Prolog already knows that there is no further answer. So prior to this improvement, you were prompted for another answer for all queries containing variables and got the false or "no" on each and every query with exactly one answer. This used to be so cumbersome that many programmers never asked for the next answer and thus were not alerted about unintended answers.
And the secondary reason is to keep you aware of the limitations of the implementation: If Prolog asks for another answer on this general query, this means that it still uses some space which might accumulate and eat up all your computing resources.
In your example with last1/2 you encounter such a case. And you already did something very smart, BTW: You tried to minimize the query to see the first occurrence of the unexpected behavior.
In your example query last1([1,2],X) the Prolog system does not look at the entire list [1,2] but only looks at the principal functor. So for the Prolog system the query looks the same as last1([_|_],X) when it decides which clauses to apply. This goal now fits to both clauses, and this is the reason why Prolog will remember the second clause as an alternative to try out.
But, think of it: This choice is now possible for all elements but the last! Which means that you pay some memory for each element! You can actually observe this by using a very long list. This I get on my tiny 32-bit laptop — you might need to add another zero or two on a larger system:
?- length(L,10000000), last1(L,E).
resource_error(_). % ERROR: Out of local stack
On the other hand, the predefined last/2 works smoothly:
?- length(L,10000000), last(L,E).
L = [_A,_B,_C,_D,_E,_F,_G,_H,_I|...].
In fact, it uses constant space!
There are now two ways out of this:
Try to optimize your definition. Yes, you can do this, but you need to be very smart! The definition by #back_dragon for example is incorrect. It often happens that beginners try to optimize a program when in fact they are destroying its semantics.
Ask yourself if you are actually defining the same predicate as last/2. In fact, you're not.
Question 2:
Consider:
?- last(Xs, X).
Xs = [X]
; Xs = [_A,X]
; Xs = [_A,_B,X]
; Xs = [_A,_B,_C,X]
; Xs = [_A,_B,_C,_D,X]
; ... .
and
?- last1(Xs, X).
loops.
So your definition differs in this case with SWI's definition. Exchange the order of the clauses.
?- length(L,10000000), last2(L,E).
L = [_A,_B,_C,_D,_E,_F,_G,_H,_I|...]
; false.
Again, this false! But this time, the big list works. And this time, the minimal query is:
?- last2([1],E).
E = 1
; false.
And the situation is quite similar: Again, Prolog will look at the query in the same way as last2([_|_],E) and will conclude that both clauses apply. At least, we now have constant overhead instead of linear overhead.
There are several ways to overcome this overhead in a clean fashion - but they all very much depend on the innards of an implementation.
SWI-Prolog attempts to avoid prompting for more solutions when it can determine that there are none. I think that the interpreter inspect the memory looking for some choice point left, and if it can't find any, simply state the termination. Otherwise it waits to let user choice the move.
I would attempt to make last1 deterministic in this way:
last1([_,H|Rest], Last) :- !, last1([H|Rest], Last).
last1([Last], Last).
but I don't think it's indistinguishable from last. Lurking at the source code of the library (it's simple as ?- edit(last).)
%% last(?List, ?Last)
%
% Succeeds when Last is the last element of List. This
% predicate is =semidet= if List is a list and =multi= if List is
% a partial list.
%
% #compat There is no de-facto standard for the argument order of
% last/2. Be careful when porting code or use
% append(_, [Last], List) as a portable alternative.
last([X|Xs], Last) :-
last_(Xs, X, Last).
last_([], Last, Last).
last_([X|Xs], _, Last) :-
last_(Xs, X, Last).
we can appreciate a well thought implementation.
this code would work:
last1([Last], Last).
last1([_ | Rest], Last) :- last1(Rest, Last), !.
it is because prolog things there might be more combinations but, with this symbol: !, prolog won't go back after reaching this point