Composition of substitutions for unary addition in prolog? - prolog

Can someone explain how the logic of the composition of substitutions works with the following block of code?
plus2(0, X, X). % 0+X = X
plus2(s(X), Y, s(Z)) :-
plus2(Y, X, Z). % (X+1) + Y = Z+1 therefore Y+X=Z

Here is better naming:
% Reduced to zero
peano_add(0, Sum, Sum).
peano_add(s(N), M, s(Sum)) :-
% Decrement towards 0
% Swap N & M, because N + M is M + N
peano_add(M, N, Sum).
This is using Peano arithmetic, which represents natural numbers (i.e. integers starting from zero) in a relative way, as compound terms, as successors ultimately of 0. For example, s(s(0)) represents 2. Such relativity is convenient and elegant for Prolog, because it can be used ("reasoned with") in an uninstantiated (var) variable.
In swi-prolog, this produces:
?- peano_add(N, M, Sum).
N = 0,
M = Sum ; % When N is zero, M is same as Sum - could be 0 or successor
N = Sum, Sum = s(_),
M = 0 ; % When M is zero, N is same as Sum
N = s(0),
M = s(_A),
Sum = s(s(_A)) ; % 1 + 1 = 2
N = s(s(_A)),
M = s(0),
Sum = s(s(s(_A))) ; % 2 + 1 = 3
N = s(s(0)),
M = s(s(_A)),
Sum = s(s(s(s(_A)))) ; % 2 + 2 = 4
N = s(s(s(_A))),
M = s(s(0)),
Sum = s(s(s(s(s(_A))))) % 3 + 2 = 5 etc.
... and if we ask it how we can add two natural numbers to sum to 2:
?- peano_add(N, M, s(s(0))).
N = 0,
M = s(s(0)) ; % 0 + 2
N = s(s(0)),
M = 0 ; % 2 + 0
N = M, M = s(0) ; % 1 + 1
false.
Whereas if we don't swap the arguments:
% Reduced to zero
peano_add(0, Sum, Sum).
peano_add(s(N), M, s(Sum)) :-
% Decrement towards 0
% Not swapping args, to demonstrate weakness
peano_add(N, M, Sum).
... we get:
?- peano_add(N, M, Sum).
N = 0,
M = Sum ;
N = s(0),
Sum = s(M) ;
N = s(s(0)),
Sum = s(s(M)) ;
N = s(s(s(0))),
Sum = s(s(s(M))) ;
N = s(s(s(s(0)))),
Sum = s(s(s(s(M)))) ;
... which is still correct, but doesn't "involve" M as much as it could.
Both methods are counting from 0 upwards to infinity.
Swapping the parameters brings the advantage of checking the 2nd argument, to fail both fast and when appropriate:
?- peano_add(s(s(N)), z, Sum).
false. % Correct, because z is not valid
% Versus, when unswapped, this undesirable:
?- peano_add(s(s(N)), z, Sum).
N = 0,
Sum = s(s(z)) ; % Wrong - did not check whether z is valid
N = s(0),
Sum = s(s(s(z))) ; % Still wrong
N = s(s(0)),
Sum = s(s(s(s(z)))) ; % Will keep being wrong
Sadly, there is a common practice in Prolog example code of using meaningless variable names (such as A, B, X, Y), which adds confusion and should be generally avoided.

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 - Multiples of a Number Below an Upper Limit

I am currently making a program in Prolog that will calculate all of the multiples (including itself) of a number, that do not exceed the value of another number. I was testing with the query below:
?- multiples(4,12,R,0)
This query would list all multiples of 4 that are less than or equal to 12 eg. 4, 8, 12. The R would return the result and 0 is where I was intending to implement a counter that would count up for each multiplication eg. 4*1,4*2,4*3. I am stuck and I am not sure if it would be a better design to simply add the multiples and check if it is below the upper bound or if it can be done with a counter or accumulator.
multiples(N,U,R,Ctr) :-
N =< U,
R is Ctr * N,
R =< U,
increment(Ctr,Ctr2),
multiples(N,U,R,Ctr2).
increment(Num, Num1) :-
Num1 is Num+1.
I believe my program is failing at the recursive step of calling multiples from within itself. I know that recursion needs a base case to allow it to exit, but I am completely stuck here and would appreciate some direction.
The problem with you approach is that there is no basecase: indeed your algorithm will always produce false. It will unify R with N, then do the recursion and that recursion will try to unify R with 2*N which will fail.
Well an idea could be to use an accumulator to which you add the delta each time. Something like:
multiples(N,U,R) :-
multiples(N,N,U,R).
multiples(_,C,U,C) :-
C =< U.
multiples(N,C,U,R) :-
C =< U,
C1 is C+N,
multiples(N,C1,U,R).
So here we call multiples(3,12,R). and it will result in:
?- multiples(4,12,R).
R = 4 ;
R = 8 ;
R = 12 ;
false.
CLP(FD) is very helpful here:
:- use_module(library(clpfd)).
multiple(Multiplicand, Max, Multiple) :-
MaxMultiplier #= Max // Multiplicand,
label([MaxMultiplier]),
Multiplier in 1 .. MaxMultiplier,
Multiple #= Multiplier * Multiplicand,
label([Multiple]).
?- multiple(4, 12, M).
M = 4 ;
M = 8 ;
M = 12.
?-
With CLP(FD) in this case, you can also query with the first argument as a variable:
|?- multiple(N, 12, 8).
N = 8 ;
N = 4 ;
N = 2 ;
N = 1.
Or both the multiplier and result:
?- multiple(N, 4, M).
N = M, M = 3 ;
N = M, M = 4 ;
N = M, M = 2 ;
N = 2,
M = 4 ;
N = M, M = 1 ;
N = 1,
M = 2 ;
N = 1,
M = 3 ;
N = 1,
M = 4.
?-
If you want to collect them in a list, you can use findall/3:
?- findall(Multiple, multiple(4, 12, Multiple), Multiples).
Multiples = [4, 8, 12].
?-

Prolog enumerate and test, will recursion work?

I have to make a predicate which will take 2 numbers N,M and will output "yes" when N,M are positive numbers and there are two numbers A,B such that A+B = M and A*B = N.
EDITED CODE:
For example M = 18, N = 45:
A = 0, B = 18, M = 0+18 (true), N = 0*18 (false) so it has to go next with A = 1 & B = 17 and check again...
numbers(M,N) :-
M>0 ,
N>0 ,
A is 0,
B is M,
numbers(N,M,A,B).
numbers(M,N,A,B) :-
M =:= A+B,
N =:= A*B.
numbers(M,N,A,B) :-
M =:= A+B,
not( N =:= A*B),
A is A+1,
B is B-1,
numbers(M,N,A,B).
I don't know how to enumerate A and B variables. Any help will be appreciated.
just add and multiply and check... see is/2 for arithmetic
edit my advice was a bit simplistic, I totally forgot a hint to easily generate integers ranges in Prolog, using nondeterminism:
numbers(M,N) :-
between(1,M,A),between(1,N,B), M =:= A+B, N =:= A*B, writeln((A,B)).
?- numbers(18,45).
3,15
true ;
15,3
true ;
false.
I look at it as a factoring problem:
%
% are M and N magic?
%
magic(M,N) :-
M > 0 ,
N > 0 ,
factor(N,A,B),
M is A+B
.
%
% factor/3: compute the factors of a positive integer
%
factor(N,F1,F2) :-
N > 0 ,
Limit is floor(sqrt(N)) ,
factor(1,Limit,N,F1,F2)
.
factor(F1,Limit,N,F1,F2) :-
F1 =< Limit ,
F2 is N div F1 ,
0 is N mod F1
.
factor(X,Limit,N,F1,F2) :-
X < Limit ,
X1 is X+1 ,
factor(X1,Limit,N,F1,F2)
.

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.

Prolog - dyck path from origin to (2N,0)

Is called Dyck Path.
It is a plane of x and y axis,
where each step will be only (x+1,y+1) or (x+1,y-1)
and will always stay above x-axis
K should means the peak of the Dyck path.
When K is 2 it should means that the peak is 2 and 3.
to form a legal sequence list of matching the parentheses a = '(', and b = ')' and has length 2N
Eg. [a,a,b,b] and [a,b,a,b] are the legal list for N = 2
[a,b,b,a] and [b,a,b,a] do not satisfies for N = 2
need to define the predicate
listFind(L,K,N) satisfies when L has list of order of 2N, for some k >= K
For example
|?- listFind(L,1,3).
L = [a,b,a,b,a,b] ? ;
L = [a,b,a,a,b,b] ? ;
L = [a,a,b,b,a,b] ? ;
L = [a,a,b,a,b,b] ? ;
L = [a,a,a,b,b,b] ? ;
no
|?- listFind(L,2,3).
L = [a,a,b,b,a,b] ? ;
L = [a,a,b,a,b,b] ? ;
L = [a,a,a,b,b,b] ? ;
no
Thanks in advance.
the role of K is unclear to me. Anyway, here is a snippet satisying your test case:
listFind(L, K, N) :-
N2 is N*2,
length(L, N2),
phrase(dyck, L),
% satisfy condition on K
run_length_encoded(L, RLE),
[X-a|_] = RLE, X >= K.
% DCG for Dyck' language over alphabet `a,b`
dyck --> [] ; [a], dyck, [b], dyck.
run_length_encoded([X|S], C) :-
run_length_encoded(S, X, 1, C).
run_length_encoded([Y|S], X, N, E) :-
( X == Y
-> M is N + 1,
run_length_encoded(S, X, M, E)
; E = [N-X|T],
run_length_encoded(S, Y, 1, T)
).
run_length_encoded([], X, C, [C-X]).
As you can see, the interpretation of K is
the sequence must start with at least K consecutives a

Resources