Dividing two integers with an alternative way - prolog

Let's consider that n=s(s(...s(0)...)) (simply n= s^n(0)). How could write a program calculating the division of two integers? I mean s^(n//m) (thats the definition of the division) . Any ideas? For example, if we had the question:
?-divide(s(s(s(s(0)))),s(0),D).
i have written the following code:
nat(0).
nat(s(X)) :- nat(X).
divide(0,_,D) :- D is 0.
divide(s(X),s(Y),D) :- divide(X,Y,D).

Your predicate divide/3 assumes wrongly that the following equation holds when x and y are numbers:
(x-1)/(y-1) = x/y
A counter-example is: (16-1)/(4-1) = 5 is different from 16/4 = 4
It seems you are trying to base your predicate on the well-know addition predicate:
add(0,Y,Y).
add(s(X),Y,s(Z)) :- add(X,Y,Z).
but division is a multiplicative not an additive operation. A possible way of solving your problem is to think of division as an iterated subtraction (as multiplication is an iterated addition). As your predicate is on natural numbers it must implement integral division as you wrote in the question.

s(0).
s(X):- X.
plus(0, Y, Y).
plus(s(X), Y, s(Z)):- plus(X , Y , Z).
minus(A, B, C) :- plus(C, B, A).
divide(_, 0, 0).
divide(0, _ , 0).
divide(X, s(0), X).
divide(A, B, s(N)) :- minus(A, B, R), divide(R, B, N).
Example:
| ?- divide(s(s(s(0))), s(0), N).
N = s(s(s(0))) ?
yes
| ?- divide(s(s(s(s(0)))), s(s(0)), N).
N = s(s(0)) ?
yes
This solution obviously only works for perfect divisions like 4/2 or 6/3 etc. Since we can only represent natural numbers using Peano's numerals.

Old post,but i have a same assignment.So the answer is:
%nat:Is X natural?,nat2:Is X,Y naturals?
nat(0).
nat(s(X)) :- nat(X).
nat2(0,s(Y)) :- nat(Y).
nat2(s(X),s(Y)) :- nat2(X,Y).
%Summary of X+Y=Z
sum(X,0,X) :- nat(X).
sum(X,s(Y),s(Z)) :- sum(X,Y,Z).
%Minus of X-Y=Z is same as Y+Z=X
minus(X,Y,Z) :- sum(Y,Z,X).
%Multiplication of X*Y,add X+0(Z) Y times(recursive)
mult(X,0,0).
mult(X,s(Y),D):-mult(X,Y,Z), sum(X,Z,D).
%Divide,check special occasions,add to W the s(0)(1) recursive.
divide(X,Y,D) :- div(X,Y,D,_).
div(s(X),0,undefined,_).
div(0,s(Y),0,_).
div(0,0,undefined,_).
div(X,Y,0,X) :- X \== 0,Y \== 0,nat2(X,Y).
div(X,Y,D,L) :- X \== 0,Y \== 0,minus(X,Y,Z),div(Z,Y,W,L),sum(W,s(0),D).

Related

Pure Prolog Peano Number Apartness

Lets assume there is pure_2 Prolog with dif/2 and pure_1 Prolog without dif/2. Can we realize
Peano apartness for values, i.e. Peano numbers, without using dif/2? Thus lets assume we have Peano apartness like this in pure_2 Prolog:
/* pure_2 Prolog */
neq(X, Y) :- dif(X, Y).
Can we replace neq(X,Y) by a more pure definition, namely from pure_1 Prolog that doesn't use dif/2? So that we have a terminating neq/2 predicate that can decide inequality for Peano numbers? So what would be its definition?
/* pure_1 Prolog */
neq(X, Y) :- ??
Using less from this comment:
less(0, s(_)).
less(s(X), s(Y)) :- less(X, Y).
neq(X, Y) :- less(X, Y); less(Y, X).
I had something else in mind, which is derived from two of the Peano Axioms, which is also part of Robinson Arithmetic. The first axiom is already a Horn clause talking about apartness:
∀x(0 ≠ S(x))
∀x∀y(S(x) = S(y) ⇒ x = y)
Applying contraposition to the second axiom gives.
The axiom is now a Horn clause talking about apartness:
∀x∀y(x ≠ y ⇒ S(x) ≠ S(y))
Now we have everything to write some Prolog code.
Adding some symmetry we get:
neq(0, s(_)).
neq(s(_), 0).
neq(s(X), s(Y)) :- neq(X, Y).
Here are some example queries. Whether the predicate leaves a choice
point depends on the Prolog system. I get:
SWI-Prolog 8.3.15 (some choice point):
?- neq(s(s(0)), s(s(0))).
false.
?- neq(s(s(0)), s(0)).
true ;
false.
Jekejeke Prolog 1.4.6 (no choice point):
?- neq(s(s(0)), s(s(0))).
No
?- neq(s(s(0)), s(0)).
Yes
Just removing the unwanted choicepoint (in swi-prolog) from user502187's answer:
neq(0, s(_)).
neq(s(N), M) :-
% Switch args, to use first-arg indexing
neq_(M, s(N)).
neq_(0, s(_)).
neq_(s(N), s(M)) :-
% Switch args back, to fix choicepoint
neq(M, N).
Results in swi-prolog:
?- neq(s(s(0)), s(0)).
true.
?- neq(s(0), s(s(0))).
true.
?- neq(N, M).
N = 0,
M = s(_) ;
N = s(_),
M = 0 ;
N = s(s(_)),
M = s(0) ;
N = s(0),
M = s(s(_)) ;
N = s(s(0)),
M = s(s(s(_))) ;
N = s(s(s(_))),
M = s(s(0)) ;

Prolog predecessor math

I have an add2 predicate which resolves like this where s(0) is the successor of 0 i.e 1
?- add2(s(0)+s(s(0)), s(s(0)), Z).
Z = s(s(s(s(s(0)))))
?- add2(0, s(0)+s(s(0)), Z).
Z = s(s(s(0)))
?- add2(s(s(0)), s(0)+s(s(0)), Z).
Z = s(s(s(s(s(0)))))
etc..
I'm trying to do add in a predecessor predicate which will work like so
?- add2(p(s(0)), s(s(0)), Z).
Z = s(s(0))
?- add2(0, s(p(0)), Z).
Z = 0
?- add2(p(0)+s(s(0)),s(s(0)),Z).
Z = s(s(s(0)))
?- add2(p(0), p(0)+s(p(0)), Z).
Z = p(p(0))
I can't seem to find a way to do this. My code is below.
numeral(0).
numeral(s(X)) :- numeral(X).
numeral(X+Y) :- numeral(X), numeral(Y).
numeral(p(X)) :- numeral(X).
add(0,X,X).
add(s(X),Y,s(Z)) :- add(X,Y,Z).
add(p(X),Y,p(Z)) :- add(X,Y,Z).
resolve(0,0).
resolve(s(X),s(Y)) :-
resolve(X,Y).
resolve(p(X),p(Y)) :-
resolve(X,Y).
resolve(X+Y,Z) :-
resolve(X,RX),
resolve(Y,RY),
add(RX,RY,Z).
add2(A,B,C) :-
resolve(A,RA),
resolve(B,RB),
add(RA,RB,C).
In general, adding with successor arithmetic means handling successor terms, which have the shape 0 or s(X) where X is also a successor term. This is addressed completely by this part of your code:
add(0,X,X).
add(s(X),Y,s(Z)) :- add(X,Y,Z).
Now you have to make a decision; you can either handle the predecessors and the addition terms here, in add/3, or you can wrap this predicate in another one that will handle them. You appear to have chosen to wrap add/3 with add2/3. In that case, you will definitely need to create a reducing term, such as you've built here with resolve/2, and I agree with your implementation of part of it:
resolve(0,0).
resolve(s(X),s(Y)) :-
resolve(X,Y).
resolve(X+Y,Z) :-
resolve(X,RX),
resolve(Y,RY),
add(RX,RY,Z).
This is all good. What you're missing now is a way to handle p(X) terms. The right way to do this is to notice that you already have a way of deducting by one, by using add/3 with s(0):
resolve(p(X), R) :-
resolve(X, X1),
add(s(0), R, X1).
In other words, instead of computing X using X = Y - 1, we are computing X using X + 1 = Y.
Provided your inputs are never negative, your add2/3 predicate will now work.

how to turn a number from the unit form into an integer in prolog?

I have his code in prolog:
int2term(0,0).
int2term(N,s(T)) :- N>0, M is N-1, int2term(M,T).
int2term(N,p(T)) :- N<0, M is N+1, int2term(M,T).
that shows a number from this form s(s(0)) to this form 2 .
I tried to make the reversed version specically 2 -> s(s(0)) using this but nothing :
term2int(0,0).
term2int(N,T) :- N>0, M is N-1, term2int(M,s(T)).
Any suggestions ?
I have not tested this but it should work:
term2int(0,0).
term2int(s(T),N) :- term2int(T,N1), N is N1+1.
term2int(p(T),N) :- term2int(T,N1), N is N1-1.
No need to check if > 0 or otherwise, just use s and p for that case. Also N works as a counter.
This is a slightly different version which is tail recursive and avoids some of the infinite recursion cases (e.g., try term2int(T, 2). and press ; after the first solution):
term2int(0, 0).
term2int(s(X), Y) :-
term2int(s(X), 0, Y).
term2int(p(X), Y) :-
term2int(p(X), 0, Y).
term2int(0, Y, Y) :- !.
term2int(s(X), A, Y) :-
(integer(Y) -> Y > 0 ; true),
A1 is A+1,
term2int(X, A1, Y).
term2int(p(X), A, Y) :-
(integer(Y) -> Y < 0 ; true),
A1 is A-1,
term2int(X, A1, Y).

Difference between X\=Y and dif(X,Y)

What is the difference between this:
X \= Y
and this piece of code:
dif(X, Y)
I thought that they should behave the same, but they do not. Here's the example:
n_puta(L, N, X) :- nputa(L, N, 0, X).
nputa([], N, C, _) :- N = C.
nputa([G|R], N, C, X) :- G = X, nputa(R, N, Y, X), C is Y - 1.
nputa([G|R], N, C, X) :- dif(G,X), nputa(R, N, C, X).
And here are some calls:
?- n_puta([a,a,b,b,b], 2, X).
X = a ;
false.
?- n_puta([a,a,b,a,b,b], 3, X).
X = a ;
X = b ;
false.
X should be the atom that occurs exactly N times in the list L. If I replace dif(G, X) with G \= X, I don't get the expected result. Can someone tell me what is the difference between these two operators? Can I use anything else except dif(G, X)?
This example works prefectly in SWI-Prolog, but doesn't work in Amzi! Prolog.
dif/2 and (\=)/2 are the same as long as their arguments are ground. But only dif/2 is a pure relation that works correctly also with variables and can be used in all directions. Your example clearly shows that you should use dif/2 in this case, because you use your predicate not only to test, but also to generate solutions. The most widely used Prolog systems all provide dif/2.

Prolog Programming

I have made two programs in Prolog for the nqueens puzzle using hill climbing and beam search algorithms.
Unfortunately I do not have the experience to check whether the programs are correct and I am in dead end.
I would appreciate if someone could help me out on that.
Unfortunately the program in hill climbing is incorrect. :(
The program in beam search is:
queens(N, Qs) :-
range(1, N, Ns),
queens(Ns, [], Qs).
range(N, N, [N]) :- !.
range(M, N, [M|Ns]) :-
M < N,
M1 is M+1,
range(M1, N, Ns).
queens([], Qs, Qs).
queens(UnplacedQs, SafeQs, Qs) :-
select(UnplacedQs, UnplacedQs1,Q),
not_attack(SafeQs, Q),
queens(UnplacedQs1, [Q|SafeQs], Qs).
not_attack(Xs, X) :-
not_attack(Xs, X, 1).
not_attack([], _, _) :- !.
not_attack([Y|Ys], X, N) :-
X =\= Y+N,
X =\= Y-N,
N1 is N+1,
not_attack(Ys, X, N1).
select([X|Xs], Xs, X).
select([Y|Ys], [Y|Zs], X) :- select(Ys, Zs, X).
I would like to mention this problem is a typical constraint satisfaction problem and can be efficiency solved using the CSP module of SWI-Prolog. Here is the full algorithm:
:- use_module(library(clpfd)).
queens(N, L) :-
N #> 0,
length(L, N),
L ins 1..N,
all_different(L),
applyConstraintOnDescDiag(L),
applyConstraintOnAscDiag(L),
label(L).
applyConstraintOnDescDiag([]) :- !.
applyConstraintOnDescDiag([H|T]) :-
insertConstraintOnDescDiag(H, T, 1),
applyConstraintOnDescDiag(T).
insertConstraintOnDescDiag(_, [], _) :- !.
insertConstraintOnDescDiag(X, [H|T], N) :-
H #\= X + N,
M is N + 1,
insertConstraintOnDescDiag(X, T, M).
applyConstraintOnAscDiag([]) :- !.
applyConstraintOnAscDiag([H|T]) :-
insertConstraintOnAscDiag(H, T, 1),
applyConstraintOnAscDiag(T).
insertConstraintOnAscDiag(_, [], _) :- !.
insertConstraintOnAscDiag(X, [H|T], N) :-
H #\= X - N,
M is N + 1,
insertConstraintOnAscDiag(X, T, M).
N is the number of queens or the size of the board (), and , where , being the position of the queen on the line .
Let's details each part of the algorithm above to understand what happens.
:- use_module(library(clpfd)).
It indicates to SWI-Prolog to load the module containing the predicates for constraint satisfaction problems.
queens(N, L) :-
N #> 0,
length(L, N),
L ins 1..N,
all_different(L),
applyConstraintOnDescDiag(L),
applyConstraintOnAscDiag(L),
label(L).
The queens predicate is the entry point of the algorithm and checks if the terms are properly formatted (number range, length of the list). It checks if the queens are on different lines as well.
applyConstraintOnDescDiag([]) :- !.
applyConstraintOnDescDiag([H|T]) :-
insertConstraintOnDescDiag(H, T, 1),
applyConstraintOnDescDiag(T).
insertConstraintOnDescDiag(_, [], _) :- !.
insertConstraintOnDescDiag(X, [H|T], N) :-
H #\= X + N,
M is N + 1,
insertConstraintOnDescDiag(X, T, M).
It checks if there is a queen on the descendant diagonal of the current queen that is iterated.
applyConstraintOnAscDiag([]) :- !.
applyConstraintOnAscDiag([H|T]) :-
insertConstraintOnAscDiag(H, T, 1),
applyConstraintOnAscDiag(T).
insertConstraintOnAscDiag(_, [], _) :- !.
insertConstraintOnAscDiag(X, [H|T], N) :-
H #\= X - N,
M is N + 1,
insertConstraintOnAscDiag(X, T, M).
Same as previous, but it checks if there is a queen on the ascendant diagonal.
Finally, the results can be found by calling the predicate queens/2, such as:
?- findall(X, queens(4, X), L).
L = [[2, 4, 1, 3], [3, 1, 4, 2]]
If I read your code correctly, the algorithm you're trying to implement is a simple depth-first search rather than beam search. That's ok, because it should be (I don't see how beam search will be effective for this problem and it can be hard to program).
I'm not going to debug this code for you, but I will give you a suggestion: build the chess board bottom-up with
queens(0, []).
queens(N, [Q|Qs]) :-
M is N-1,
queens(M, Qs),
between(1, N, Q),
safe(Q, Qs).
where safe(Q,Qs) is true iff none of Qs attack Q. safe/2 is then the conjunction of a simple memberchk/2 check (see SWI-Prolog manual) and your not_attack/2 predicate, which on first sight seems to be correct.
A quick check on Google has found a few candidates for you to compare with your code and find what to change.
My favoured solution for sheer clarity would be the second of the ones linked to above:
% This program finds a solution to the 8 queens problem. That is, the problem of placing 8
% queens on an 8x8 chessboard so that no two queens attack each other. The prototype
% board is passed in as a list with the rows instantiated from 1 to 8, and a corresponding
% variable for each column. The Prolog program instantiates those column variables as it
% finds the solution.
% Programmed by Ron Danielson, from an idea by Ivan Bratko.
% 2/17/00
queens([]). % when place queen in empty list, solution found
queens([ Row/Col | Rest]) :- % otherwise, for each row
queens(Rest), % place a queen in each higher numbered row
member(Col, [1,2,3,4,5,6,7,8]), % pick one of the possible column positions
safe( Row/Col, Rest). % and see if that is a safe position
% if not, fail back and try another column, until
% the columns are all tried, when fail back to
% previous row
safe(Anything, []). % the empty board is always safe
safe(Row/Col, [Row1/Col1 | Rest]) :- % see if attack the queen in next row down
Col =\= Col1, % same column?
Col1 - Col =\= Row1 - Row, % check diagonal
Col1 - Col =\= Row - Row1,
safe(Row/Col, Rest). % no attack on next row, try the rest of board
member(X, [X | Tail]). % member will pick successive column values
member(X, [Head | Tail]) :-
member(X, Tail).
board([1/C1, 2/C2, 3/C3, 4/C4, 5/C5, 6/C6, 7/C7, 8/C8]). % prototype board
The final link, however, solves it in three different ways so you can compare against three known solutions.

Resources