Alternate between Disjunctions in Prolog - prolog

Consider the following simple program:
h(n0).
h(p(A,N)) :- (A=a, h(N)) ; (A=b , h(N)).
Query:
1 ?- h(p(A,N)).
A = a,
N = n0 ;
A = a,
N = p(a, n0) ;
A = a,
N = p(a, p(a, n0)) ;
A = a,
N = p(a, p(a, p(a, n0))) ;
A = a,
N = p(a, p(a, p(a, p(a, n0)))) ;
...
Since the first disjunct [(A=a, h(N))] produces infinite number of answers it cannot show the answers produced by the second disjunct [(A=b , h(N))].
The question is:
Is it possible to change the code so that on the query, it alternates between the solutions from the first disjunct and the second one?

To get a fair listing of the results of h/1 you can use an auxiliary predicate, say h2/2 that consists of two goals: 1) A predicate pairs/1 that is only describing the the structure of your solution without concrete values:
pairs(n0).
pairs(p(A,N)) :-
pairs(N).
And yields the following answers:
?- pairs(X).
X = n0 ? ;
X = p(_A,n0) ? ;
X = p(_A,p(_B,n0)) ? ;
X = p(_A,p(_B,p(_C,n0))) ?
...
2) Your predicate h/1 as the second goal that describes what the variables _A, _B, _C,... actually are:
h2(X) :-
pairs(X),
h(X).
If you query this predicate you get the desired results:
?- h2(X).
X = n0 ? ;
X = p(a,n0) ? ;
X = p(b,n0) ? ;
X = p(a,p(a,n0)) ? ;
X = p(a,p(b,n0)) ? ;
X = p(b,p(a,n0)) ? ;
X = p(b,p(b,n0)) ? ;
X = p(a,p(a,p(a,n0))) ? ;
...
Note, how the first goal pairs/2 is producing your nested pair-structure one pair at a time. Then the second goal, your original predicate, is producing all possible combinations of a's and b's for that very pair. Then h/2 is backtracking to the next pair produced by pairs/2. And so on.

Related

How to generate all pairs of natural numbers in Prolog?

Problem statement:
I'm trying to generate all pairs of natural numbers in Prolog (SWI-Prolog),
i.e. formally have a function f(X,Y), such that:
after calling f(X,Y) with unbound variables X, Y, for each pair of natural numbers (m, n) there exists an n0 such that after pressing semicolon n0 times, Prolog will return (X,Y)=(m,n).
Failed attempt:
I was hoping to write the function using Cantor's pairing function. In short, it enumerates the pairs as follows: (0,0), (1,0), (0,1), (2,0), (1,1), (0,2), (3,0), (2,1), (1,2), (0,3), (4,0)...
I expressed it as follows:
gen(0,0). % 'root'
gen(M,0) :- gen(0, X), M is X+1. % 'jump to the previous diagonal'
gen(M,N) :- gen(X, Y), M is X-1, N is Y+1, N > 0. % 'a step inside a diagonal'
However because of how Prolog search actually works, this ends up with the 2nd rule repeatedly invoking itself, ad infinitem, eventually crashing due to running out of stack space (the only results it returns before that are (0,0) and (1,0), then it gets stuck, repeatedly failing the 2nd rule on '0 is 0+1').
Do you have any ideas how to make this or any other elegant approach work?
Thank you.
Edit - my solution.
Based on the accepted answer (thanks!), I wrote the following code, working as intended:
range(Min, _, Min).
range(Min, Max, Val) :- NewMin is Min+1, Max >= NewMin, range(NewMin, Max, Val).
natnum(0).
natnum(N) :-
natnum(N0),
N is N0 + 1.
gen(A,B) :-
natnum(N),
range(0, N, B),
A is N - B.
When used:
?- gen(X,Y).
X = 0,
Y = 0 ;
X = 1,
Y = 0 ;
X = 0,
Y = 1 ;
X = 2,
Y = 0 ;
X = 1,
Y = 1 ;
X = 0,
Y = 2 ;
X = 3,
Y = 0
and so on...
I give you a start:
Let us start with a predicate that creates all natural numbers on backtracking, yielding a single such number with each solution:
natnum(0).
natnum(N) :-
N #= N0 + 1,
natnum(N0).
Sample query:
?- natnum(N).
N = 0 ;
N = 1 ;
N = 2 ;
N = 3 ;
etc.
Then, we observe that we can generate such pairs without falling into an infinite loop by restricting the sum of each pair. For example:
pair(A-B) :-
natnum(N),
N #>= A + B,
A #>= 0,
B #>= 0,
label([A,B]).
Sample query:
?- pair(P).
P = 0-0 ;
P = 0-0 ;
P = 0-1 ;
P = 1-0 ;
P = 0-0 ;
P = 0-1 ;
P = 0-2 ;
P = 1-0 ;
P = 1-1 ;
P = 2-0 ;
P = 0-0 ;
P = 0-1 ;
P = 0-2 ;
P = 0-3 ;
P = 1-0 ;
P = 1-1 .
This is obviously not perfect: For example, some pairs are reported redundantly. However, the general idea should be clear: Use a good building-block to keep the generation of pairs in check.

Prolog does not terminate on query with 2 arguments

I'm new to Prolog and have a question to a programming exercise:
I have a program, that is for my opinion working most of the time, but with a specific query, I do not get an answer
is_number(0).
is_number(s(N)) :-
is_number(N).
numberpair(pair(X,Y)) :-
is_number(X),
is_number(Y).
?- numberpair(pair(A,B)), A=s(s(0)), B=s(s(s(0))).
So I understand, that Prolog now tries every possible number for A and B -> [0,s(0),s(s(0)),s(s(s(0))), ...] but if it founds an answer for A (namely s(s(0))) it fails at B and in the next call, it tries the next answer for A (namely s(s(s(0)))) and so on.
Now the thing is, that I want Prolog to stop, if it founds an answer for A, and only searches now for an answer for B.
Can anybody give me a hint, how to solve this?
Edit: As false pointed out:
The reason you won't find an answer is that your rule numberpair/1 won't terminate. The reason you won't find an answer is that Prolog enumerates your answer in a way that it first lists all possibilities for A and then the possibilities for B (note that both have infinite possibilities). What Prolog tries is to find an answer first for the clause numberpair(pair(A,B)) but and then for the following clauses A=s(s(0)) and B=s(s(s(0))). But since numberpair already won't terminate, it won't "come" so far.
If you change the order of your clauses goals and simply call A=s(s(0)) before numberpair(pair(A,B)), it will give list you all answers for the possibilities of B (note that this still won't terminate!).
?- A=s(s(0)), numberpair(pair(A,B)).
A = s(s(0)),
B = 0 ;
A = s(s(0)),
B = s(0) ;
A = B, B = s(s(0)) ;
A = s(s(0)),
B = s(s(s(0))) .
Edit 2, to provide also a version, which will enumerates in a "fair" way!
is_number(0).
is_number(s(N)) :-
is_number(N).
number_number_sum(0,A,A).
number_number_sum(s(A),B,s(C)) :-
number_number_sum(A,B,C).
numberpair(pair(X,Y)) :-
is_number(Z),
number_number_sum(X,Y,Z).
Which will provide us with
?- numberpair(pair(A,B)).
A = B, B = 0 ;
A = 0,
B = s(0) ;
A = s(0),
B = 0 ;
A = 0,
B = s(s(0)) ;
A = B, B = s(0) ;
A = s(s(0)),
B = 0 ;
A = 0,
B = s(s(s(0))) ;
A = s(0),
B = s(s(0)) ;
A = s(s(0)),
B = s(0) ;
A = s(s(s(0))),
B = 0 .

ERROR: Out of local stack in my Prolog code

I cannot figure out why the following query from the given Prolog code generates the error Out of local stack.
Prolog code:
likes(g,c).
likes(c,a).
likes(c,b).
likes(b,a).
likes(b,d).
likes(X,Z) :- likes(X,Y), likes(Y,Z).
the query
?- likes(g,X).
results in
X = c ;
X = a ;
X = b ;
ERROR: Out of local stack
Edit 1 This is the way I think that Prolog should deal with this query,
likes(g,c) is a fact, so X={c}
likes(g,b) <= likes(g,c) and likes(c,b), so X={c,b}
likes(g,a) <= likes(g,b) and likes(b,a), so X={c,b,a}
likes(g,d) <= likes(g,b) and likes(b,d), so X={c,b,a,d}
likes(g,a) and false, so nothing to add to X
likes(g,d) and false, so nothing to add to X
end of backtracking search.
Edit 2 I managed to get what I was looking for by the following modification of the code:
likes(g,c).
likes(c,a).
likes(c,b).
likes(b,a).
likes(b,d).
indirect_likes(A,B):- likes(A,B).
indirect_likes(A,C):- likes(B,C), indirect_likes(A,B).
the query
?- indirect_likes(g,Which).
results in
Which = c ;
Which = a ;
Which = b ;
Which = a ;
Which = d ;
false.
However, there is still something which I cannot figure out the rationale behind. If I change the last rule to be
indirect_likes(A,C):- indirect_likes(A,B), likes(B,C).
Then I get ERROR: Out of local stack! As far as I know, logical conjunction is commutative.
To get the transitive-closure of binary relation R_2, use meta-predicate closure/3 like so:
?- closure(R_2,From,To).
Let's run a sample query of closure/3 together with likes/2!
?- closure(likes,X,Y).
X = g, Y = c
; X = g, Y = a
; X = g, Y = b
; X = g, Y = a % redundant
; X = g, Y = d
; X = c, Y = a
; X = c, Y = b
; X = c, Y = a % redundant
; X = c, Y = d
; X = b, Y = a
; X = b, Y = d
; false. % query terminates universally
We get the same answers when we use indirect_likes/2, but in a different order:
?- indirect_likes(X,Y).
X = g, Y = c
; X = c, Y = a
; X = c, Y = b
; X = b, Y = a
; X = b, Y = d
; X = g, Y = a
; X = g, Y = b
; X = c, Y = a % redundant
; X = g, Y = a % redundant
; X = c, Y = d
; X = g, Y = d
; false. % query terminates universally
As you stated in your comments to #C.B.'s answer, binary relations are not necessarily reflexive and/or symmetric. With the definition you gave, likes/2 is neither:
?- likes(X,X).
false. % not reflexive (not even close)
?- likes(X,Y), likes(Y,X).
false. % not symmetric (not even close)
So far, so good!
Let's tentatively add the following additional fact to your database:
likes(b,b).
With this expanded definition, indirect_likes/2 behaves erratically:
?- indirect_likes(b,b).
true
; true
; true
... % does not terminate universally
?- indirect_likes(X,Y), false. % do we get finite failure?
... % no! query does not terminate universally
What can we do? Let's use meta-predicate closure/3 with the expanded version of likes/2!
?- closure(likes,b,b).
true % succeeds non-deterministically
; false. % query terminates universally
?- closure(likes,X,Y), false. % do we get finite failure?
false. % yes! query terminates universally
The bottom line?
In pure Prolog, conjunction is commutative, as far as the logical meaning is concerned.
Due to Prolog's SLD resolution, the goal false,repeat finitely fails, but repeat,false does not.
The programmer needs to take care of termination, but usually this is a small price to pay for the raw performance and control that Prolog offers.
In this answer I passed "termination worries" on to the implementor of meta-predicate closure/3 :)
You spin off into infinite recursion.
Once you get to likes(b,a), you call likes(a,_G4382), which has no fact defined so it switches to the rule likes(X,Z) :- likes(X,Y), likes(Y,Z). So it calls likes(a,_G4383) which calls likes(X,Z) :- likes(X,Y), likes(Y,Z). over and over and over.
You might want to define and auxillary predicate aux_likes/2 that hosts all your facts. This will only work if there are no circular relationships, i.e. aux_likes(b,c) and aux_likes(c,b). You would also need to define likes(X,X). This is essentially a graph problem and in graph theory a node has to be connected to itself. If you use it as a generator, it will go off into into infinite recursion (if you have cycles) unless you add cuts which are not ideal.
If using swi-prolog, feel free to enter the debug or spy query to see what's going on.
Code:
aux_likes(g,c).
aux_likes(c,a).
aux_likes(c,b).
aux_likes(b,a).
aux_likes(b,d).
likes(X,Z) :- aux_likes(X,Y), likes(Y,Z).
likes(X,X).
Output with new predicate:
?- likes(g,X),print(X),nl,fail.
a
a
d
b
c
g
false.
This says g can like a through c or through b. It likes d through b, it likes b through c and it likes c directly. It also must like itself inorder to query like this. If you would rather have the usage mode (+,+) meaning you supply it with both terms and no variables (as a checker) you can do
?- likes(g,c).
true .

Learning prolog, some list functions

I am working on an assignment that deals with lists in prolog. The basic idea is that given a list, prolog should be able to determine if a value is repeated at all, repeated only once, or repeated only twice, etc. I thought the simplest solution would be to count the number of times a value occurs and then use that count to determine how many times it is repeated.
list_count([],X,0).
list_count([X|T],X,Y) :- list_count(T,X,Z), Y is 1 + Z.
list_count([X1|T],X,Z) :- X1 \= X, list_count(T,X,Z).
repeated_in(+E,+List) :- list_count(List,E,Num), Num >= 2.
No matter what I do though my first predicate always fails. Help?
list_count/3 does work. I think the only issue is the improper usage of prefix '+': try
% repeated_in(+E,+List)
repeated_in(E,List):- list_count(List,E,Num), Num >= 2.
note: prefixing arguments is used for documentation purpose, as a recap about mode usage
Here a logically pure implementation, based on
if_/3 and (=)/3 by #false.
atLeastOnceMember_of(E,[X|Xs]) :-
if_(E = X, true, atLeastOnceMember_of(E,Xs)).
atLeastTwiceMember_of(E,[X|Xs]) :-
if_(E = X, atLeastOnceMember_of(E,Xs), atLeastTwiceMember_of(E,Xs)).
First, let's look at the queries you suggested in your question:
?- atLeastTwiceMember_of(a,[a,b,a,b,a,c]).
true. % succeeds deterministically
?- atLeastTwiceMember_of(b,[a,b,a,b,a,c]).
true. % succeeds deterministically
?- atLeastTwiceMember_of(c,[a,b,a,b,a,c]).
false.
?- atLeastTwiceMember_of(x,[a,b,a,b,a,c]).
false.
The code is monotone, so we get logically sound answers for more general uses, too!
?- atLeastTwiceMember_of(X,[a,b,a,b,a,c]).
X = a ;
X = b ;
false.
At last, let us consider a generalization of above query:
?- atLeastTwiceMember_of(X,[A,B,C,D,E,F]).
X = A, A = B ;
X = A, A = C, dif(C,B) ;
X = A, A = D, dif(D,C), dif(D,B) ;
X = A, A = E, dif(E,D), dif(E,C), dif(E,B) ;
X = A, A = F, dif(F,E), dif(F,D), dif(F,C), dif(F,B) ;
X = B, B = C, dif(C,A) ;
X = B, B = D, dif(D,C), dif(D,A) ;
X = B, B = E, dif(E,D), dif(E,C), dif(E,A) ;
X = B, B = F, dif(F,E), dif(F,D), dif(F,C), dif(F,A) ;
X = C, C = D, dif(D,B), dif(D,A) ;
X = C, C = E, dif(E,D), dif(E,B), dif(E,A) ;
X = C, C = F, dif(F,E), dif(F,D), dif(F,B), dif(F,A) ;
X = D, D = E, dif(E,C), dif(E,B), dif(E,A) ;
X = D, D = F, dif(F,E), dif(F,C), dif(F,B), dif(F,A) ;
X = E, E = F, dif(F,D), dif(F,C), dif(F,B), dif(F,A) ;
false.

Finding the k'th occurence of a given element

I just started in Prolog and have the problem:
(a) Given a list L, an object X, and a positive integer K, it returns
the position of the K-th occurrence of X in L if X appears at least K
times in L otherwise 0.
The goal pos([a,b,c,b],b,2,Z) should succeed with the answer Z = 4.
So far I have:
pos1([],H,K,F).
pos1([H],H,1,F).
pos1([H|T],H,K,F):- NewK is K - 1, pos1(T,H,NewK,F), F is F + 1.
pos1([H|T],X,K,F):- pos1(T,X,K,F).
But I can't figure out why I'm getting:
ERROR: is/2: Arguments are not sufficiently instantiated
Any help would be much appreciated!
Use clpfd!
:- use_module(library(clpfd)).
We define pos/4 based on (#>)/2, (#=)/2, if_/3, dif/3, and (#<)/3:
pos(Xs,E,K,P) :-
K #> 0,
pos_aux(Xs,E,K,1,P).
pos_aux([X|Xs],E,K,P0,P) :-
P0+1 #= P1,
if_(dif(X,E),
pos_aux(Xs,E,K,P1,P),
if_(K #< 2,
P0 = P,
(K0+1 #= K,
pos_aux(Xs,E,K0,P1,P)))).
Sample query as given by the OP:
?- X = b, N = 2, pos([a,b,c,b],X,N,P).
X = b, N = 2, P = 4. % succeeds deterministically
How about the following more general query?
?- pos([a,b,c,b],X,N,P).
X = a, N = 1, P = 1
; X = b, N = 1, P = 2
; X = b, N = 2, P = 4 % (exactly like in above query)
; X = c, N = 1, P = 3
; false.
Let's take a high-level approach to it, trading the efficiency of the resulting code for the ease of development:
pos(L,X,K,P):-
numerate(L,X,LN,1), %// [A1,A2,A3...] -> [A1-1,A2-2,A3-3...], where Ai = X.
( drop1(K,LN,[X-P|_]) -> true ; P=0 ).
Now we just implement the two new predicates. drop1(K,L,L2) drops K-1 elements from L, so we're left with L2:
drop1(K,L2,L2):- K<2, !.
drop1(K,[_|T],L2):- K1 is K-1, drop1(K1,T,L2).
numerate(L,X,LN,I) adds an I-based index to each element of L, but keeps only Xs:
numerate([],_,[],_).
numerate([A|B],X,R,I):- I1 is I+1, ( A=X -> R=[A-I|C] ; R=C ), numerate(B,X,C,I1).
Testing:
5 ?- numerate([1,b,2,b],b,R,1).
R = [b-2, b-4].
6 ?- pos([1,b,2,b],b,2,P).
P = 4.
7 ?- pos([1,b,2,b],b,3,P).
P = 0.
I've corrected your code, without changing the logic, that seems already simple enough.
Just added a 'top level' handler, passing to actual worker pos1/4 and testing if worked, else returning 0 - a debatable way in Prolog, imo is better to allow to fail, I hope you will appreciate how adopting this (see comments) simplified your code...
pos(L,X,K,F):- pos1(L,X,K,F) -> true ; F=0.
% pos1([],H,K,F). useless: let it fail
% pos1([H],H,1,F). useless: already handled immediatly bottom
pos1([H|T],H,K,P):- K==1 -> P=1 ; NewK is K - 1, pos1(T,H,NewK,F), P is F + 1.
pos1([_|T],X,K,P):- pos1(T,X,K,F),P is F+1.
I hope you're allowed to use the if/then/else construct. Anyway, yields
7 ?- pos([a,b,c,b],b,2,Z).
Z = 4.
8 ?- pos([a,b,c,b],b,3,Z).
Z = 0.
Something like this. An outer predicate (this one enforces the specified constraints) that invokes an inner worker predicate:
kth( L , X , K , P ) :-
is_list( L ) , % constraint: L must be a list
nonvar(X) , % constriant: X must be an object
integer(K) , K > 0 % constraint: K must be a positive integer
kth( Ls , X , K , 1 , P ) % invoke the worker predicate with its accumulator seeded to 1
. % easy!
is_list/2 ensures you've got a list:
is_list(X) :- var(X) , !, fail .
is_list([]).
is_list([_|_]).
The predicate that does all the work is this one:
kth( [] , _ , _ , _ , 0 ) . % if we hit the end of the list, P is 0.
kth( [X|Ls] , X , K , K , K ) :- ! . % if we find the Kth desired element, succeed (and cut: we won't find another Kth element)
kth( [_|Ls] , X , K , N , P ) :- % otherwise
N < K , % - if we haven't got to K yet ...
N1 is N+1 , % - increment our accumulator , and
kth(Ls,X,K,N1,P) % - recurse down.
. % easy!
Though the notion of returning 0 instead of failure is Not the Prolog Way, if you ask me.

Resources