Convert peano number s(N) to integer in Prolog - prolog

I came across this natural number evaluation of logical numbers in a tutorial and it's been giving me some headache:
natural_number(0).
natural_number(s(N)) :- natural_number(N).
The rule roughly states that: if N is 0 it's natural, if not we try to send the contents of s/1 back recursively to the rule until the content is 0, then it's a natural number if not then it's not.
So I tested the above logic implementation, thought to myself, well this works if I want to represent s(0) as 1 and s(s(0)) as 2, but I´d like to be able to convert s(0) to 1 instead.
I´ve thought of the base rule:
sToInt(0,0). %sToInt(X,Y) Where X=s(N) and Y=integer of X
So here is my question: How can I convert s(0) to 1 and s(s(0)) to 2?
Has been answered
Edit: I modified the base rule in the implementation which the answer I accepted pointed me towards:
decode(0,0). %was orignally decode(z,0).
decode(s(N),D):- decode(N,E), D is E +1.
encode(0,0). %was orignally encode(0,z).
encode(D,s(N)):- D > 0, E is D-1, encode(E,N).
So I can now use it like I wanted to, thanks everyone!

Here is another solution that works "both ways" using library(clpfd) of SWI, YAP, or SICStus
:- use_module(library(clpfd)).
natsx_int(0, 0).
natsx_int(s(N), I1) :-
I1 #> 0,
I2 #= I1 - 1,
natsx_int(N, I2).

No problemo with meta-predicate nest_right/4 in tandem with
Prolog lambdas!
:- use_module(library(lambda)).
:- use_module(library(clpfd)).
:- meta_predicate nest_right(2,?,?,?).
nest_right(P_2,N,X0,X) :-
zcompare(Op,N,0),
ord_nest_right_(Op,P_2,N,X0,X).
:- meta_predicate ord_nest_right_(?,2,?,?,?).
ord_nest_right_(=,_,_,X,X).
ord_nest_right_(>,P_2,N,X0,X2) :-
N0 #= N-1,
call(P_2,X1,X2),
nest_right(P_2,N0,X0,X1).
Sample queries:
?- nest_right(\X^s(X)^true,3,0,N).
N = s(s(s(0))). % succeeds deterministically
?- nest_right(\X^s(X)^true,N,0,s(s(0))).
N = 2 ; % succeeds, but leaves behind choicepoint
false. % terminates universally

Here is mine:
Peano numbers that are actually better adapted to Prolog, in the form of lists.
Why lists?
There is an isomorphism between
a list of length N containing only s and terminating in the empty list
a recursive linear structure of depth N with function symbols s
terminating in the symbol zero
... so these are the same things (at least in this context).
There is no particular reason to hang onto what 19th century mathematicians
(i.e Giuseppe Peano )
considered "good structure structure to reason with" (born from function
application I imagine).
It's been done before: Does anyone actually use Gödelization to encode
strings? No! People use arrays of characters. Fancy that.
Let's get going, and in the middle there is a little riddle I don't know how to
solve (use annotated variables, maybe?)
% ===
% Something to replace (frankly badly named and ugly) "var(X)" and "nonvar(X)"
% ===
ff(X) :- var(X). % is X a variable referencing a fresh/unbound/uninstantiated term? (is X a "freshvar"?)
bb(X) :- nonvar(X). % is X a variable referencing an nonfresh/bound/instantiated term? (is X a "boundvar"?)
% ===
% This works if:
% Xn is boundvar and Xp is freshvar:
% Map Xn from the domain of integers >=0 to Xp from the domain of lists-of-only-s.
% Xp is boundvar and Xn is freshvar:
% Map from the domain of lists-of-only-s to the domain of integers >=0
% Xp is boundvar and Xp is boundvar:
% Make sure the two representations are isomorphic to each other (map either
% way and fail if the mapping gives something else than passed)
% Xp is freshvar and Xp is freshvar:
% WE DON'T HANDLE THAT!
% If you have a freshvar in one domain and the other (these cannot be the same!)
% you need to set up a constraint between the freshvars (via coroutining?) so that
% if any of the variables is bound with a value from its respective domain, the
% other is bound auotmatically with the corresponding value from ITS domain. How to
% do that? I did it awkwardly using a lookup structure that is passed as 3rd/4th
% argument, but that's not a solution I would like to see.
% ===
peanoify(Xn,Xp) :-
(bb(Xn) -> integer(Xn),Xn>=0 ; true), % make sure Xn is a good value if bound
(bb(Xp) -> is_list(Xp),maplist(==(s),Xp) ; true), % make sure Xp is a good value if bound
((ff(Xn),ff(Xp)) -> throw("Not implemented!") ; true), % TODO
length(Xp,Xn),maplist(=(s),Xp).
% ===
% Testing is rewarding!
% Run with: ?- rt(_).
% ===
:- begin_tests(peano).
test(left0,true(Xp=[])) :- peanoify(0,Xp).
test(right0,true(Xn=0)) :- peanoify(Xn,[]).
test(left1,true(Xp=[s])) :- peanoify(1,Xp).
test(right1,true(Xn=1)) :- peanoify(Xn,[s]).
test(left2,true(Xp=[s,s])) :- peanoify(2,Xp).
test(right2,true(Xn=2)) :- peanoify(Xn,[s,s]).
test(left3,true(Xp=[s,s,s])) :- peanoify(3,Xp).
test(right3,true(Xn=3)) :- peanoify(Xn,[s,s,s]).
test(f1,fail) :- peanoify(-1,_).
test(f2,fail) :- peanoify(_,[k]).
test(f3,fail) :- peanoify(a,_).
test(f4,fail) :- peanoify(_,a).
test(f5,fail) :- peanoify([s],_).
test(f6,fail) :- peanoify(_,1).
test(bi0) :- peanoify(0,[]).
test(bi1) :- peanoify(1,[s]).
test(bi2) :- peanoify(2,[s,s]).
:- end_tests(peano).
rt(peano) :- run_tests(peano).

Related

Prolog: nat(s(s(0))) to "normal" decimal numbers

If an integers is defined like this in Prolog:
nat(0).
nat(s(X)) :- nat(X).
How do I convert such a number to a decimal number?
The input is for example:
s(s(s(0)))
I probably should add that I am very new to Prolog.
EDIT:
I tried it this way:
nat(0).
nat(s(X)) :- nat(X).
convert(N, C) :-
C is C + 1,
nat(N),
convert(N, C).
There are basically two cases you need to cover:
the base case 0 that maps on 0; and
the recursive case s(X) that makes use of the result for X.
The base case thus looks like:
convert(0, 0).
the recursive case thus looks like:
convert(S(X), N) :-
convert(X, N1),
….
where … is thus a step you need to do to determine N given N1. I leave this as an exercise.

Magic Square NxN

I'm new to Prolog and I'm trying to write fully working magic square program, but to say the truth I don't really know how to do, I have started but I feel that I'm doing it wrong. I'm sharing my code and I hope someone will help me, now when numbers are good I get true, but when they are not I get like out of stack error... (here is only checking rows and columns I know about obliquely check)
thanks for your attention!
:- use_module(library(clpfd)).
:- use_module(library(lists)).
magicSq(List, N) :-
Number is N * N,
belongs(Number ,List), % check if numbers are correct.
all_different(List), % check if numbers not occur.
Suma is N*(N*N + 1)/2,
checkC(List,N,N,Suma), % check column
checkR(List,1,N,Suma). % check row
belongs(0, _).
belongs(N, List) :- member(N,List) , Index is N - 1 , belongs(Index, List).
consecutiveSum(_, 0 , _,0).
consecutiveSum(List, HowMuch , From,Sum):-
Index is HowMuch - 1,
From1 is From +1,
nth1(From, List,Element),
consecutiveSum(List,Index,From1,Z),
Sum is Z + Element,!.
sumObliCol(0,_, [], _,_). % sums by columns or obliquely
sumObliCol(X,Number, [H|T], Ind, Residue) :-
Index is Ind + 1,
Y is mod(Index,Number),
Y =:= Residue,
sumObliCol(Z,Number, T, Index,Residue),
X is Z + H, !.
sumObliCol(X,Number, [_|T], Ind,Residue) :-
Index is Ind + 1,
sumObliCol(X,Number, T, Index,Residue).
checkC(_,0,_,_). % check column
checkC(List,N, Number,Answ):-
N1 is N-1,
checkC(List,N1, Number,Answ),
sumObliCol(Ats,Number,List,0,N1),Ats is Answ,!.
checkR(_,N,Number,_):- N>(Number*Number). % check row
checkR(List,N,Number,Answ):-
consecutiveSum(List,Number,N,Sum), Sum is Answ,
N1 is N + Number,
checkR(List,N1, Number,Answ),!.
In programming one often assumes that
everything is deeply intertwingled ... since the cross-connections among the myriad topics of this world/program simply cannot be divided up neatly.1
But in Prolog, sometimes, we can divide things up much more neatly. In particular, if you concentrate on a single property like non-termination. So let's consider magic squares of size one — very magic indeed! Like so using a failure-slice:
?- magicSq(Xs,1), false.
magicSq(List, N) :-
Number is N * N,
belongs(Number ,List), false,
all_different(List),
Suma is N*(N*N + 1)/2,
checkC(List,N,N,Suma),
checkR(List,1,N,Suma).
belongs(0, _) :- false.
belongs(N1, List) :-
member(N1,List), false,
N2 is N1 - 1,
belongs(N2, List).
That's all you need to understand! Evidently, the List is unconstrained and thus the goal member(N1, List) cannot terminate. That's easy to fix, adding a goal length(List, Number). And still, the program does not terminate but in a different area:
?- magicSq(Xs,1), false.
magicSq(List, N) :-
Number is N * N,
length(List, Number),
belongs(Number ,List), false,
all_different(List),
Suma is N*(N*N + 1)/2,
checkC(List,N,N,Suma),
checkR(List,1,N,Suma).
belongs(0, _) :- false.
belongs(N1, List) :-
member(N1,List),
N2 is N1 - 1,
belongs(N2, List), false.
Now this does not terminate, for N1 may be negative, too. We need to improve that adding N1 > 0.
Now, considering the program with a false in front of all_different/1, I get:
?- time(magicSq(List, 3)).
% 8,571,007 inferences
That looks like an awful lot of inferences! In fact, what you are doing is to enumerate all possible configurations first. Thus, you do not use the powers of constraint programming. Please go through tutorials on this. Start here.
However, the problems do not stop here! There is much more to it, but the remaining program is very difficult to understand, for you are using the ! in completely unrelated places.

Insert a given value v after the 1-st, 2-nd, 4-th, 8-th ... element of a list. (Prolog)

I'm trying to solve this problem in SWI Prolog, and my code currently looks like this:
insert(L1,X,L2):-
COUNTER = 1,
NEXT = 1,
insert_plus(L1,COUNTER,NEXT,X,L2).
insert_plus([],_,_,_,[]).
insert_plus([H|T],COUNTER,NEXT,X,[H|T1]) :- % don't insert
COUNTER \= NEXT,
insert_plus(T,COUNTER+1,NEXT,X,T1).
insert_plus([H|T],COUNTER,NEXT,X,[H|[X|T]]) :- % DO insert
COUNTER = NEXT,
insert_plus(T,COUNTER+1,NEXT*2,X,T).
Can someone explain why this does not always work as expected?
?- insert([1,2,3,4,5,6,7],9,X).
X = [1,9,2,3,4,5,6,7]. % BAD! expected: `X = [1,9,2,9,3,4,9,5,6,7]`
Prolog doesn't evaluate expressions, it proves relations. So arithmetic must be carried away explicitly. Here
...
insert_plus(T, COUNTER+1, NEXT, X, T1).
you need
...
SUCC is COUNTER+1,
insert_plus(T, SUCC, NEXT, X, T1).
the same problem - with both COUNTER and NEXT - occurs in the last rule.
The absolute bare minimum that you need to change is:
insert_plus([],_,_,_,[]).
insert_plus([H|T],COUNTER,NEXT,X,[H|T1]) :-
COUNTER =\= NEXT, % `(=\=)/2` arithmetic not-equal
insert_plus(T,COUNTER+1,NEXT,X,T1).
insert_plus([H|T],COUNTER,NEXT,X,[H|[X|T1]]) :- % use `T1`, not `T`
COUNTER =:= NEXT, % `(=:=)/2` arithmetic equal
insert_plus(T,COUNTER+1,NEXT*2,X,T1). % use `T1` (as above)
Sample query:
?- insert([1,2,3,4,5,6,7],9,X).
X = [1,9,2,9,3,4,9,5,6,7]. % expected result
In addition to the above changes I recommend you take advise that #CapelliC gave
in his answer concerning arithmetic expression evaluation using the builtin Prolog predicate (is)/2...
... or, even better, use clpfd!

How to make a fact work both way in Prolog (takes arguments in any order)?

I want to define facts which are true both ways (They all have an arity of 2). I had success with a fact expressing the relationship "opposite" this way:
oppositeDeclare(plus, minus).
opposite(X, Y) :- oppositeDeclare(Y, X).
opposite(X, Y) :- oppositeDeclare(X, Y).
I'm trying to make a simple equation solver, and I would also like to define that if A=B then B=A. I can't just write:
equal(A, B):-equal(B,A).
because I get out of local stack error. However I can't do the same as I did with the "opposite" fact because "equal" needs to work based on the some rules. ("opposite" got it's input from facts only).
Is there a way I can avoid defining all the rules for "equal" twice?
Edit:
I only want to declare simple mathematical facts to see if I can use Prolog to solve other more complicated tasks where I don't know the mechanism for the solution only simple facts.
So far I have used equal/2 to define things like: if A=B+C, then C=A-B. I want to define equal/2 two ways so that I don't have to define if B+C=A, then A-B=C. Ideally after the new rule it could solve an equation for c like this: a=(b+c)/d -> b+c=a/d -> c=(a/d)-b.
The reason I can't use swap is because I have recursive rules for equal/2.
Bear in mind that it will not always work even for simple equations, because not all necessary facts are defined.
Here's the current program with a query:
5 ?- equal(v, X).
X = opr(s, per, t)
% operators: per, times, plus, minus
% equation(LHS, RHS): used to declare physics equations
% equal(LHS, RHS): checks equality in a query
equation(s, opr(v, times, t)). % s=v*t
equation(a, opr(opr(b, plus, c), per, d)). % a=(b+c)/d
oppositeDeclare(plus, minus).
oppositeDeclare(per, times).
opposite(X, Y) :- oppositeDeclare(Y, X).
opposite(X, Y) :- oppositeDeclare(X, Y).
equal(R, opr(A, O, B)) :- equation(R, opr(A, O, B)).
% if there's an equation R=A O B , then R = A O B, where O is an operator (+-*/)
equal(A, opr(R, OY, B)) :- equal(R, opr(A, OX, B)), opposite(OY, OX).
%declaring in one go: if R=A/B then A=R*B, if R=A-B then A=R+B, if R=A+B then A=R-B, if R=A-B then A=R+B
I am not sure I understand you correctly, but aren't you after this simple code?
equal(X, X).
Could you please show some sample input and output that you would like to achieve by using equal/2?
And about opposites, I would write this that way:
oppositeDeclare(plus, minus).
oppositeDeclare(good, evil).
oppositeDeclare(windows, linux).
swap(P, X, Y) :- permutation([X,Y], [X1,Y1]), call(P, X1, Y1).
opposite(X, Y) :- swap(oppositeDeclare, X, Y).
Anytime you would like to use predicate with arity 2 and try swapping arguments, you can use swap/3 in a way presented above.

Prolog - sequence in list

We want to build a predicate that gets a list L and a number N and is true if N is the length of the longest sequence of list L.
For example:
?- ls([1,2,2,4,4,4,2,3,2],3).
true.
?- ls([1,2,3,2,3,2,1,7,8],3).
false.
For this I built -
head([X|S],X). % head of the list
ls([H|T],N) :- head(T,X),H=X, NN is N-1 , ls(T,NN) . % if the head equal to his following
ls(_,0) :- !. % get seq in length N
ls([H|T],N) :- head(T,X) , not(H=X) ,ls(T,N). % if the head doesn't equal to his following
The concept is simply - check if the head equal to his following , if so , continue with the tail and decrement the N .
I checked my code and it works well (ignore cases which N = 1) -
ls([1,2,2,4,4,4,2,3,2],3).
true ;
false .
But the true answer isn't finite and there is more answer after that , how could I make it to return finite answer ?
Prolog-wise, you have a few problems. One is that your predicate only works when both arguments are instantiated, which is disappointing to Prolog. Another is your style—head/2 doesn't really add anything over [H|T]. I also think this algorithm is fundamentally flawed. I don't think you can be sure that no sequence of longer length exists in the tail of the list without retaining an unchanged copy of the guessed length. In other words, the second thing #Zakum points out, I don't think there will be a simple solution for it.
This is how I would have approached the problem. First a helper predicate for getting the maximum of two values:
max(X, Y, X) :- X >= Y.
max(X, Y, Y) :- Y > X.
Now most of the work sequence_length/2 does is delegated to a loop, except for the base case of the empty list:
sequence_length([], 0).
sequence_length([X|Xs], Length) :-
once(sequence_length_loop(X, Xs, 1, Length)).
The call to once/1 ensures we only get one answer. This will prevent the predicate from usefully generating lists with sequences while also making the predicate deterministic, which is something you desired. (It has the same effect as a nicely placed cut).
Loop's base case: copy the accumulator to the output parameter:
sequence_length_loop(_, [], Length, Length).
Inductive case #1: we have another copy of the same value. Increment the accumulator and recur.
sequence_length_loop(X, [X|Xs], Acc, Length) :-
succ(Acc, Acc1),
sequence_length_loop(X, Xs, Acc1, Length).
Inductive case #2: we have a different value. Calculate the sequence length of the remainder of the list; if it is larger than our accumulator, use that; otherwise, use the accumulator.
sequence_length_loop(X, [Y|Xs], Acc, Length) :-
X \= Y,
sequence_length([Y|Xs], LengthRemaining),
max(Acc, LengthRemaining, Length).
This is how I would approach this problem. I don't know if it will be useful for you or not, but I hope you can glean something from it.
How about adding a break to the last rule?
head([X|S],X). % head of the list
ls([H|T],N) :- head(T,X),H=X, NN is N-1 , ls(T,NN) . % if the head equal to his following
ls(_,0) :- !. % get seq in length N
ls([H|T],N) :- head(T,X) , not(H=X) ,ls(T,N),!. % if the head doesn't equal to his following
Works for me, though I'm no Prolog expert.
//EDIT: btw. try
14 ?- ls([1,2,2,4,4,4,2,3,2],2).
true ;
false.
Looks false to me, there is no check whether N is the longest sequence. Or did I get the requirements wrong?
Your code is checking if there is in list at least a sequence of elements of specified length. You need more arguments to keep the state of the search while visiting the list:
ls([E|Es], L) :- ls(E, 1, Es, L).
ls(X, N, [Y|Ys], L) :-
( X = Y
-> M is N+1,
ls(X, M, Ys, L)
; ls(Y, 1, Ys, M),
( M > N -> L = M ; L = N )
).
ls(_, N, [], N).

Resources