How does backtracking in recursion not cause an infinite loop? - prolog

Assume the member/2 predicate is defined as:
member(X,[X|R]).
member(X,[Y|R]) :- member(X,R).
My query is:
member(X, [1, 2, 3]).
Once prolog unifies X with 1, how does prolog get the other possible unifications if I type ;?
Wouldn't Prolog backtrack and then re-read my file containing the definition of member from top to bottom and evaluate member(X,[X|R]). again which would unify X with 1 again?

How about this
Note the following:
The program is read once and then stays in memory, waiting for the user to enter a query (same as for a database scenario)
As it executes it builds a "search tree" in memory
An OR node for every predicate encountered: ANY of the branches (which correspond to clauses of that predicate) must be made TRUE
An AND node for every clause body encountered: all the branches (which correspond to the calls made in the clause body that are seprated by ,) must be made TRUE
The program SUCCEEDS when it can "exit at the bottom of the tree" and
Below any AND node, all the branches are TRUE
Below any OR node, at least one of the branches are TRUE (In Prolog, there is only every exactly ONE "active branch" below an OR node)
The program eventually FAILS if no such tree can be found (which may take some time).
On program success, the tree is kept alive in case the user ask for "more solutions"
If you ask for "more solutions", the tree is re-entered at the bottom and alternative branches are tried.
And:
Variable names are local to a clause
Variable content (which is either a term or a cell with no content if the "variable is unbound" as they say) is always global. If a node deep in the tree "refines" the content of one of its variable, this change is visible at the topmost node of the tree (albeit under another name or part of another term).

The rules you stated are:
member(X, [X | R]).
The pipe operator separates the first element of the list from the rest of the list. So, if list is [1, 2, 3], X = 1, and R = [2, 3].
X is the car of the [X | R] list (i.e. first member).
So in this case, member(1, [1, 2, 3]). is true.
member(X, [Y | R]) :- member(X, R).
This second case covers when the first member of the list is different from X. If this is so, member(X , R) is called and this inspects the cdr of the list (i.e. from second element on).
So, member(1, [1, 2, 3]). doesn't trigger a recursion.
What happens, for instance, when the element is not on the list ?
For brevity, member(1, [2]). is true or false ?
This falls on the second rule, since X = 1 is different from Y = 2.
But then, the cdr of the list is an empty list (i.e. there are no elements beside the first).
So member(1, [2]) :- member(1, [])., and this member(1, []) evaluation is always false.
Prolog's output:
~ $ swipl
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
Please run ?- license. for legal details.
For online help and background, visit http://www.swi-prolog.org
For built-in help, use ?- help(Topic). or ?- apropos(Word).
?- [user].
|: member(X, [X | L]) :- write('Evaluated first clause with X='), write(X), write('.'), nl.
|: member(X, [Y | L]) :- write('Evaluated second clause with X='), write(X), write(' and Y='), write(Y), write('.'), nl, member(X, L).
|: end_of_file.
% user://1 compiled 0.01 sec, 2 clauses
true.
?- member(1, [1, 2, 3]).
Evaluated first clause with X=1.
true .
?- member(2, [1, 2, 3]).
Evaluated second clause with X=2 and Y=1.
Evaluated first clause with X=2.
true .
?- member(4, [1, 2, 3]).
Evaluated second clause with X=4 and Y=1.
Evaluated second clause with X=4 and Y=2.
Evaluated second clause with X=4 and Y=3.
false.
?- X=1, member(X, [1, 2, 3]).
Evaluated first clause with X=1.
X = 1 .
(omitted warnings).

Related

Prolog tries to find multiple solutions when only one exists

I've made a basic predicate ascending/1 to check if a list is in ascending order, on https://swish.swi-prolog.org.
ascending([]).
ascending([_]).
ascending([X, Y| T]) :-
X =< Y,
ascending([Y|T]).
It shows the following if I query ?- ascending([1, 2, 4, 6]).:
As in, it tries to find more solutions. Pressing Next, 10, 100 or 1,000 just returns false, which is a mystery in and of itself - true and false at the same time? Maybe that's because of the anonymous _? Have I not defined completely enough? Why is it not just returning true?
Most Prolog systems implement first-argument indexing, which allows avoid creating spurious choice-points. Assuming that and a call with the first argument bound, in the case of your code, the Prolog runtime is able to able to distinguish between the first clause, whose first argument is an atom, and the two other clauses, whose first argument are lists. But not able (in general) to distinguish between the second and third clauses and avoid trying both for a goal where the first argument is a list. This results in the creation of a choice-point. Hence the results your get:
?- ascending([1, 2, 4, 6]).
true ;
false.
But we can improve on your solution. For example:
ascending([]).
ascending([Head| Tail]) :-
ascending(Tail, Head).
ascending([], _).
ascending([Head| Tail], Previous) :-
Previous =< Head,
ascending(Tail, Head).
We will now get:
?- ascending([1, 2, 4, 6]).
true.
?- ascending([1, 2, 4, 6, 1]).
false.

How do I implement in Prolog the predicate list_for_set

How do I implement in Prolog the predicate list_for_set(Xs, Cs) where Cs is a list that contains the same elements as Xs, in the order of its first occurrence, but whose number of occurrences is only 1. For example, the query
? - list_for_set([1, a, 3.3, a, 1.4], Cs).
it happens only for Cs = [1, a, 3,4]. The consultation
? - list_for_set ([1, a, 3,3, a, 1,4], [a, 1,3,4])
must fail.
The Cs list of the previous statement will be called a set list, that is, a list with only one occurrence of each element.
Ok, there is some trickery involved.
foofilter([],_,_-T) :- T=[]. % close difflist
foofilter([L|Ls],Seen,H-T) :-
member(L,Seen),
!,
foofilter(Ls,Seen,H-T).
foofilter([L|Ls],Seen,H-T) :-
\+member(L,Seen),
!,
T=[L|NewT],
foofilter(Ls,[L|Seen],H-NewT).
:-begin_tests(filter).
data([1, a, 3, 3, a, 1, 4]).
test(one) :- data(L),
DiffList=[[]|T]-T, % Assume [] is never in L
foofilter(L,[],DiffList),
DiffList=[_|Result]-_,
format("~q ==> ~q\n",[L,Result]),
Result = [1,a,3,4].
:-end_tests(filter).
rt :- run_tests(filter).
Run tests:
?- rt.
% PL-Unit: filter [1,a,3,3,a,1,4] ==> [1,a,3,4]
. done
% test passed
true.
Someone will probably come up with a one-liner.

First elements of list of list Prolog

I m studying Prolog and i see this code
foo([],[]).
foo([[A,_ ]|L], [A|P]) :-foo(L ,P).
The result say that this code take N element of list of list,
Ad example if we give this query:
?foo([[car],[house],[man]],X)
X= [c,h,m]
At first read i see that something wrong.
For me this code take the tail of list of list and the rest of first element of the list , so for me first expansion will be (trace)
foo([[house],[man]], ar)
foo([[man]], ouse)
foo([], an)
false.
I try to compile with swi-prolog and give this trace:
[trace] ?- trace,foo([[car],[house],[man]],X).
Call: (9) foo([[car], [house], [man]], _1016) ? creep
Fail: (9) foo([[car], [house], [man]], _1016) ? creep
false.
What are I wrong?
Obtaining the first elements
The pattern [A, _] in your clause is wrong, or at at least not generic enough. [A, _] unifies with a list that contains exactly two elements, but this will thus fail for lists with more than two elements, or with one elements, like you found out.
You need to use the [A|_] pattern: indeed a list where the head is A, and we are not interested in the rest (tail). like:
foo([],[]).
foo([[A|_]|L], [A|P]) :- foo(L, P).
That being said, you can simplify this, by implementing a predicate that takes the head of a list:
head([H|_], H).
and then make use of maplist/3 [swi-doc]:
foo(A, B) :-
maplist(head, A, B).
maplist will thus call head like head(Ai, Bi), with Ai and Bi elements of A and B respectively.
Obtaining a substring with the first character
but based on the sample output, this is not what you want: you also want to obtain the first "character" of the atom, we can do that by using string_chars/2 [swi-doc]:
head_first([A|_], C) :-
string_chars(A, [C|_]).
and then define foo/2 again with maplist/3 [swi-doc]:
foo(A, B) :-
maplist(head_first, A, B).
we then obtain:
?- foo([[car],[house],[man]], X).
X = [c, h, m].

Prolog. Difficult beginnings

At the beginning: I am beginner in Prolog but I have to admit, the language is curious because of the fact other paradigm.
find_kth_e(X, [X|_], 1).
find_kth_e(X, [_|T], K) :- K > 1, K1 is K-1, find_kth_e(X, T, K1).
?- find_kth_e(X, [1,2,3,4,5], 3).
X = 3 ;
false.
What is find_kth_e? Function? Relation? ( Yeah, I know that a function is a relation).
The result is 3. And it is ok. But why the second result is false?
Let's consider a modified version:
find_kth_e(X, [X|_], 1).
find_kth_e(X, [_|T], K) :- K > 1, K1 is K-1, find_kth_e(_, T, K1).
?- find_kth_e(X, [1,2,3,4,5], 3).
X = 3 ;
false.
The only difference is in line: find_kth_e(X, [_|T], K) :- K > 1, K1 is K-1, find_kth_e(_, T, K1).. I replaced X with _. And now:
?- find_kth_e(X, [1,2,3,4,5], 3).
true ;
false.
The answer is true and false. Why there is no 3? After all, the result should be returned by first version of function- I mean find_kth_e(X, [X|_], 1). So, the fact that I replaced X with _ should doesn't matter.
Please explain .
As #EugeneSh. says, Prolog has predicates. A predicate may have one or more predicate clauses (yours has two). A predicate defines a relation between its arguments.
?- find_kth_e(X, [1,2,3,4,5], 3).
X = 3 ;
false.
In this example, you queried whether X is the 3rd argument of list [1,2,3,4,5]. Prolog succeeded with X = 3. But there was a choice point in your predicate, meaning Prolog encountered a place in the code before it succeeded where an alternative decision could be explored. When you pressed ;, you told Prolog to explore that alternative (Prolog backtracks). Prolog found there were no more solutions after X = 3, so Prolog says "false".
When you replaced X with _ you indicated that you didn't care what the first argument is:
?- find_kth_e(_, [1,2,3,4,5], 3).
true ;
false.
As in the first query, Prolog succeeded in finding a 3rd element, but you indicated that you didn't care what that element is. So Prolog succeeds and says only "true". And, as before, the choice point is there. Your ; tells Prolog to backtrack to the choice point and it found no more solutions, so ultimately shows "false".
Here's another little test you can do to show success versus failure:
?- find_kth_e(X, [a,b,c,d,e], 3), write('Success!'), nl.
Success!
X = c ;
false.
Since the find_kth_e/3 succeeded, Prolog continued to the write/1 statement which wrote "Success!" and then showed X = c (Prolog shows all the variables that result in success after the entire clause finishes executing).
Here's a failure case:
?- find_kth_e(X, [a,b,c,d,e], 6), write('Success!'), nl.
false.
?-
find_kth_e/3 could not find a 6th element, so it failed. Prolog did not continue and do the write/1 due to the failure of the prior statement, and you can see "Success!" was not displayed.

PROLOG: Determining if elements in list are equal if order does not matter

I'm trying to figure out a way to check if two lists are equal regardless of their order of elements.
My first attempt was:
areq([],[]).
areq([],[_|_]).
areq([H1|T1], L):- member(H1, L), areq(T1, L).
However, this only checks if all elements of the list on the left exist in the list on the right; meaning areq([1,2,3],[1,2,3,4]) => true. At this point, I need to find a way to be able to test thing in a bi-directional sense. My second attempt was the following:
areq([],[]).
areq([],[_|_]).
areq([H1|T1], L):- member(H1, L), areq(T1, L), append([H1], T1, U), areq(U, L).
Where I would try to rebuild the lest on the left and swap lists in the end; but this failed miserably.
My sense of recursion is extremely poor and simply don't know how to improve it, especially with Prolog. Any hints or suggestions would be appreciated at this point.
As a starting point, let's take the second implementation of equal_elements/2 by #CapelliC:
equal_elements([], []).
equal_elements([X|Xs], Ys) :-
select(X, Ys, Zs),
equal_elements(Xs, Zs).
Above implementation leaves useless choicepoints for queries like this one:
?- equal_elements([1,2,3],[3,2,1]).
true ; % succeeds, but leaves choicepoint
false.
What could we do? We could fix the efficiency issue by using
selectchk/3 instead of
select/3, but by doing so we would lose logical-purity! Can we do better?
We can!
Introducing selectd/3, a logically pure predicate that combines the determinism of selectchk/3 and the purity of select/3. selectd/3 is based on
if_/3 and (=)/3:
selectd(E,[A|As],Bs1) :-
if_(A = E, As = Bs1,
(Bs1 = [A|Bs], selectd(E,As,Bs))).
selectd/3 can be used a drop-in replacement for select/3, so putting it to use is easy!
equal_elementsB([], []).
equal_elementsB([X|Xs], Ys) :-
selectd(X, Ys, Zs),
equal_elementsB(Xs, Zs).
Let's see it in action!
?- equal_elementsB([1,2,3],[3,2,1]).
true. % succeeds deterministically
?- equal_elementsB([1,2,3],[A,B,C]), C=3,B=2,A=1.
A = 1, B = 2, C = 3 ; % still logically pure
false.
Edit 2015-05-14
The OP wasn't specific if the predicate
should enforce that items occur on both sides with
the same multiplicities.
equal_elementsB/2 does it like that, as shown by these two queries:
?- equal_elementsB([1,2,3,2,3],[3,3,2,1,2]).
true.
?- equal_elementsB([1,2,3,2,3],[3,3,2,1,2,3]).
false.
If we wanted the second query to succeed, we could relax the definition in a logically pure way by using meta-predicate
tfilter/3 and
reified inequality dif/3:
equal_elementsC([],[]).
equal_elementsC([X|Xs],Ys2) :-
selectd(X,Ys2,Ys1),
tfilter(dif(X),Ys1,Ys0),
tfilter(dif(X),Xs ,Xs0),
equal_elementsC(Xs0,Ys0).
Let's run two queries like the ones above, this time using equal_elementsC/2:
?- equal_elementsC([1,2,3,2,3],[3,3,2,1,2]).
true.
?- equal_elementsC([1,2,3,2,3],[3,3,2,1,2,3]).
true.
Edit 2015-05-17
As it is, equal_elementsB/2 does not universally terminate in cases like the following:
?- equal_elementsB([],Xs), false. % terminates universally
false.
?- equal_elementsB([_],Xs), false. % gives a single answer, but ...
%%% wait forever % ... does not terminate universally
If we flip the first and second argument, however, we get termination!
?- equal_elementsB(Xs,[]), false. % terminates universally
false.
?- equal_elementsB(Xs,[_]), false. % terminates universally
false.
Inspired by an answer given by #AmiTavory, we can improve the implementation of equal_elementsB/2 by "sharpening" the solution set like so:
equal_elementsBB(Xs,Ys) :-
same_length(Xs,Ys),
equal_elementsB(Xs,Ys).
To check if non-termination is gone, we put queries using both predicates head to head:
?- equal_elementsB([_],Xs), false.
%%% wait forever % does not terminate universally
?- equal_elementsBB([_],Xs), false.
false. % terminates universally
Note that the same "trick" does not work with equal_elementsC/2,
because of the size of solution set is infinite (for all but the most trivial instances of interest).
A simple solution using the sort/2 ISO standard built-in predicate, assuming that neither list contains duplicated elements:
equal_elements(List1, List2) :-
sort(List1, Sorted1),
sort(List2, Sorted2),
Sorted1 == Sorted2.
Some sample queries:
| ?- equal_elements([1,2,3],[1,2,3,4]).
no
| ?- equal_elements([1,2,3],[3,1,2]).
yes
| ?- equal_elements([a(X),a(Y),a(Z)],[a(1),a(2),a(3)]).
no
| ?- equal_elements([a(X),a(Y),a(Z)],[a(Z),a(X),a(Y)]).
yes
In Prolog you often can do exactly what you say
areq([],_).
areq([H1|T1], L):- member(H1, L), areq(T1, L).
bi_areq(L1, L2) :- areq(L1, L2), areq(L2, L1).
Rename if necessary.
a compact form:
member_(Ys, X) :- member(X, Ys).
equal_elements(Xs, Xs) :- maplist(member_(Ys), Xs).
but, using member/2 seems inefficient, and leave space to ambiguity about duplicates (on both sides). Instead, I would use select/3
?- [user].
equal_elements([], []).
equal_elements([X|Xs], Ys) :-
select(X, Ys, Zs),
equal_elements(Xs, Zs).
^D here
1 ?- equal_elements(X, [1,2,3]).
X = [1, 2, 3] ;
X = [1, 3, 2] ;
X = [2, 1, 3] ;
X = [2, 3, 1] ;
X = [3, 1, 2] ;
X = [3, 2, 1] ;
false.
2 ?- equal_elements([1,2,3,3], [1,2,3]).
false.
or, better,
equal_elements(Xs, Ys) :- permutation(Xs, Ys).
The other answers are all elegant (way above my own Prolog level), but it struck me that the question stated
efficient for the regular uses.
The accepted answer is O(max(|A| log(|A|), |B|log(|B|)), irrespective of whether the lists are equal (up to permutation) or not.
At the very least, it would pay to check the lengths before bothering to sort, which would decrease the runtime to something linear in the lengths of the lists in the case where they are not of equal length.
Expanding this, it is not difficult to modify the solution so that its runtime is effectively linear in the general case where the lists are not equal (up to permutation), using random digests.
Suppose we define
digest(L, D) :- digest(L, 1, D).
digest([], D, D) :- !.
digest([H|T], Acc, D) :-
term_hash(H, TH),
NewAcc is mod(Acc * TH, 1610612741),
digest(T, NewAcc, D).
This is the Prolog version of the mathematical function Prod_i h(a_i) | p, where h is the hash, and p is a prime. It effectively maps each list to a random (in the hashing sense) value in the range 0, ...., p - 1 (in the above, p is the large prime 1610612741).
We can now check if two lists have the same digest:
same_digests(A, B) :-
digest(A, DA),
digest(B, DB),
DA =:= DB.
If two lists have different digests, they cannot be equal. If two lists have the same digest, then there is a tiny chance that they are unequal, but this still needs to be checked. For this case I shamelessly stole Paulo Moura's excellent answer.
The final code is this:
equal_elements(A, B) :-
same_digests(A, B),
sort(A, SortedA),
sort(B, SortedB),
SortedA == SortedB.
same_digests(A, B) :-
digest(A, DA),
digest(B, DB),
DA =:= DB.
digest(L, D) :- digest(L, 1, D).
digest([], D, D) :- !.
digest([H|T], Acc, D) :-
term_hash(H, TH),
NewAcc is mod(Acc * TH, 1610612741),
digest(T, NewAcc, D).
One possibility, inspired on qsort:
split(_,[],[],[],[]) :- !.
split(X,[H|Q],S,E,G) :-
compare(R,X,H),
split(R,X,[H|Q],S,E,G).
split(<,X,[H|Q],[H|S],E,G) :-
split(X,Q,S,E,G).
split(=,X,[X|Q],S,[X|E],G) :-
split(X,Q,S,E,G).
split(>,X,[H|Q],S,E,[H|G]) :-
split(X,Q,S,E,G).
cmp([],[]).
cmp([H|Q],L2) :-
split(H,Q,S1,E1,G1),
split(H,L2,S2,[H|E1],G2),
cmp(S1,S2),
cmp(G1,G2).
A simple solution using cut.
areq(A,A):-!.
areq([A|B],[C|D]):-areq(A,C,D,E),areq(B,E).
areq(A,A,B,B):-!.
areq(A,B,[C|D],[B|E]):-areq(A,C,D,E).
Some sample queries:
?- areq([],[]).
true.
?- areq([1],[]).
false.
?- areq([],[1]).
false.
?- areq([1,2,3],[3,2,1]).
true.
?- areq([1,1,2,2],[2,1,2,1]).
true.

Resources