Return Integer with Prolog - prolog

I try to understand prolog right now. I want to give the input: convert(s(s(s(X))),Y) and the output should be Y = 3.
convert(s(0), 1).
convert(s(s(0)), 2).
convert(s(X),Y) :- convert(X,Y is (Y+1)).
Those are my rules right now, but only the inputs:
convert(s(0), 1). And
convert(s(s(0)), 2). work.
If my recursion would work right, I wouldn't need the rule: convert(s(s(0)), 2).
Can someone help me with that problem?

There are two problems here:
Y is Y+1, does not makes any sense in Prolog; and
note that you here actually have written a functor.
Prolog sees this as a call:
convert(X,is(Y,Y+1))
where is(Y,Y+1) is not called, but passed as a functor. In Prolog there is no clear input and output. You call predicates and through unification, you obtain results.
We can however solve the problem by using recursion: the convert/2 of 0 is of course 0:
convert(0,0).
and the convert of an s(X), is the convert of X plus one:
convert(s(X),R) :-
convert(X,Y),
R is Y+1.
Or putting these together:
convert(0,0).
convert(s(X),R) :-
convert(X,Y),
R is Y+1.
Now we can call the predicate to list all Peano numbers and the corresponding number, as well as converting a Peano number into a number. We can also validate if a Peano number is a normal number.
Unfortunately we can not use this predicate to obtain the Peano number from a given number: it will unify with the Peano number, but in a attempt to look for another Peano number, will get stuck into an infinite loop.
We can use the clpfd library to help us with this:
:- use_module(library(clpfd)).
convert(0,0).
convert(s(X),R) :-
R #> 0,
Y #= R-1,
convert(X,Y).

Related

Steadfastness: Definition and its relation to logical purity and termination

So far, I have always taken steadfastness in Prolog programs to mean:
If, for a query Q, there is a subterm S, such that there is a term T that makes ?- S=T, Q. succeed although ?- Q, S=T. fails, then one of the predicates invoked by Q is not steadfast.
Intuitively, I thus took steadfastness to mean that we cannot use instantiations to "trick" a predicate into giving solutions that are otherwise not only never given, but rejected. Note the difference for nonterminating programs!
In particular, at least to me, logical-purity always implied steadfastness.
Example. To better understand the notion of steadfastness, consider an almost classical counterexample of this property that is frequently cited when introducing advanced students to operational aspects of Prolog, using a wrong definition of a relation between two integers and their maximum:
integer_integer_maximum(X, Y, Y) :-
Y >= X,
!.
integer_integer_maximum(X, _, X).
A glaring mistake in this—shall we say "wavering"—definition is, of course, that the following query incorrectly succeeds:
?- M = 0, integer_integer_maximum(0, 1, M).
M = 0. % wrong!
whereas exchanging the goals yields the correct answer:
?- integer_integer_maximum(0, 1, M), M = 0.
false.
A good solution of this problem is to rely on pure methods to describe the relation, using for example:
integer_integer_maximum(X, Y, M) :-
M #= max(X, Y).
This works correctly in both cases, and can even be used in more situations:
?- integer_integer_maximum(0, 1, M), M = 0.
false.
?- M = 0, integer_integer_maximum(0, 1, M).
false.
| ?- X in 0..2, Y in 3..4, integer_integer_maximum(X, Y, M).
X in 0..2,
Y in 3..4,
M in 3..4 ? ;
no
Now the paper Coding Guidelines for Prolog by Covington et al., co-authored by the very inventor of the notion, Richard O'Keefe, contains the following section:
5.1 Predicates must be steadfast.
Any decent predicate must be “steadfast,” i.e., must work correctly if its output variable already happens to be instantiated to the output value (O’Keefe 1990).
That is,
?- foo(X), X = x.
and
?- foo(x).
must succeed under exactly the same conditions and have the same side effects.
Failure to do so is only tolerable for auxiliary predicates whose call patterns are
strongly constrained by the main predicates.
Thus, the definition given in the cited paper is considerably stricter than what I stated above.
For example, consider the pure Prolog program:
nat(s(X)) :- nat(X).
nat(0).
Now we are in the following situation:
?- nat(0).
true.
?- nat(X), X = 0.
nontermination
This clearly violates the property of succeeding under exactly the same conditions, because one of the queries no longer succeeds at all.
Hence my question: Should we call the above program not steadfast? Please justify your answer with an explanation of the intention behind steadfastness and its definition in the available literature, its relation to logical-purity as well as relevant termination notions.
In 'The craft of prolog' page 96 Richard O'Keef says 'we call the property of refusing to give wrong answers even when the query has an unexpected form (typically supplying values for what we normally think of as inputs*) steadfastness'
*I am not sure if this should be outputs. i.e. in your query ?- M = 0, integer_integer_maximum(0, 1, M). M = 0. % wrong! M is used as an input but the clause has been designed for it to be an output.
In nat(X), X = 0. we are using X as an output variable not an input variable, but it has not given a wrong answer, as it does not give any answer. So I think under that definition it could be steadfast.
A rule of thumb he gives is 'postpone output unification until after the cut.' Here we have not got a cut, but we still want to postpone the unification.
However I would of thought it would be sensible to have the base case first rather than the recursive case, so that nat(X), X = 0. would initially succeed .. but you would still have other problems..

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!

Prolog issue with max list function: nondeterm vs procedure

I am trying to do a small project in prolog where a user can input a list and then it calculates the average, max in the list etc. etc.
So far so good, but I ran into a problem when writing the max function (finds max number in the list). The code is:
maxN([X],X):-!.
maxN([X|L],X) :- maxN(L,M), X > M.
maxN([X|L],M) :- maxN(L,M), M >= X.
The function itself works separately, but I get this error message:
The predicate 'forma::maxN/2 (i,o)', which is declared as 'procedure', is actually 'nondeterm' forma.pro
This is my predicate in the *.cl definition:
maxN: (integer* Z, integer U) procedure (i,o).
I cannot declare it as nondeterm because it causes issues with my whole form. Can you help me/give a hint how to make it a procedure? I am thinking I have to make a cut somewhere but my attempts have failed so far.
P.S. I am using Visual Prolog 7.4.
Edit: After trying the alternatives proposed to make the two rules into one or with an accumulator, I now get that the predicate is 'determ' instead of a procedure. According to my Prolog guide that means that the predicate doesn't have multiple solutions now, but instead has a chance to fail. Basically all code variations I've done up to now lead me to a 'determ'.
The problem is that Prolog sees a choice point between your second and third rules. In other words, you, the human, know that both X > M and M >= X cannot both be true, but Prolog is not able to infer that.
IMO the best thing to do would be to rephrase those two rules with one rule:
maxN([X], X) :- !.
maxN([X|L], Max) :-
maxN(L, M),
X > M -> Max = X
; Max = M.
This way there isn't ever an extra choice point that would need to be pruned with a cut.
Following #CapelliC's advice, you could also reformulate this with an accumulator:
maxN([X|Xs], Max) :- maxN_loop(Xs, X, Max).
maxN_loop([], Max, Max).
maxN_loop([X|Xs], Y, Max) :-
X > Y -> maxN_loop(Xs, X, Max)
; maxN_loop(Xs, Y, Max).
sorry, I don't know the Prolog dialect you're using, my advice is to try to add a cut after the second clause:
maxN([X|L],X) :- maxN(L,M), X > M, !.
Generally, I think a recursive procedure can be made deterministic transforming it to tail recursive. Unfortunately, this requires to add an accumulator:
maxN([],A,A).
maxN([X|L],A,M) :- X > A, !, maxN(L,X,M).
maxN([X|L],A,M) :- maxN(L,A,M).
Of course, top level call should become
maxN([F|L],M) :- maxN(L,F,M).

Prolog - converting succ representation into decimal

This is my code:
numeral(0).
numeral(succ(X)) :- numeral(X).
convertToD(A,0).
convertToD(succ(S), Y) :- numeral(S), Y1 is Y-1, convertToD(S, Y1).
Why does this give me such an output?
convertTo(succ(succ(0)), N).
N = 0 ;
ERROR: convertTo/2: Arguments are not sufficiently instantiated
Well, you're getting more than one answer because of this:
convertToD(A,0).
What you mean to have here is convertToD(0, 0), because otherwise you're saying "convertToD is true between anything and 0" when you mean "convertToD is 0 for 0." This is also why Prolog thinks you have multiple results.
Having given it some thought and noticed a question this question is a duplicate of, I see what you were trying to accomplish with the second clause. What you're trying to do is emulate the clpfd solution from there in ordinary Prolog. With clpfd:
convertToD(succ(S), Y) :- numeral(S), Y0 #= Y-1, convertToD(S, Y0).
A straightforward copy of that into vanilla Prolog gets us your code here, but what doesn't happen is all the magic clpfd brings to the table. Without clpfd, it's very difficult to make a predicate that works for any instantiation combination and never loops. One thing that helps is to move the arithmetic last:
convertToD(succ(S), Y) :- numeral(S), convertToD(S, Y1), succ(Y1, Y).
This gets us a predicate with all the desirable properties, except it loops here:
?- convertToD(X, 3).
X = s(s(s(0))) ;
^CAction (h for help) ? abort
I've messed with this with when/2 and var/1/nonvar/1 and haven't been able to solve that little problem.

studying for prolog/haskell programming exam

I starting to study for my upcoming exam and I'm stuck on a trivial prolog practice question which is not a good sign lol.
It should be really easy, but for some reason I cant figure it out right now.
The task is to simply count the number of odd numbers in a list of Int in prolog.
I did it easily in haskell, but my prolog is terrible. Could someone show me an easy way to do this, and briefly explain what you did?
So far I have:
odd(X):- 1 is X mod 2.
countOdds([],0).
countOdds(X|Xs],Y):-
?????
Your definition of odd/1 is fine.
The fact for the empty list is also fine.
IN the recursive clause you need to distinguish between odd numbers and even numbers. If the number is odd, the counter should be increased:
countOdds([X|Xs],Y1) :- odd(X), countOdds(Xs,Y), Y1 is Y+1.
If the number is not odd (=even) the counter should not be increased.
countOdds([X|Xs],Y) :- \+ odd(X), countOdds(Xs,Y).
where \+ denotes negation as failure.
Alternatively, you can use ! in the first recursive clause and drop the condition in the second one:
countOdds([X|Xs],Y1) :- odd(X), !, countOdds(Xs,Y), Y1 is Y+1.
countOdds([X|Xs],Y) :- countOdds(Xs,Y).
In Prolog you use recursion to inspect elements of recursive data structs, as lists are.
Pattern matching allows selecting the right rule to apply.
The trivial way to do your task:
You have a list = [X|Xs], for each each element X, if is odd(X) return countOdds(Xs)+1 else return countOdds(Xs).
countOdds([], 0).
countOdds([X|Xs], C) :-
odd(X),
!, % this cut is required, as rightly evidenced by Alexander Serebrenik
countOdds(Xs, Cs),
C is Cs + 1.
countOdds([_|Xs], Cs) :-
countOdds(Xs, Cs).
Note the if, is handled with a different rule with same pattern: when Prolog find a non odd element, it backtracks to the last rule.
ISO Prolog has syntax sugar for If Then Else, with that you can write
countOdds([], 0).
countOdds([X|Xs], C) :-
countOdds(Xs, Cs),
( odd(X)
-> C is Cs + 1
; C is Cs
).
In the first version, the recursive call follows the test odd(X), to avoid an useless visit of list'tail that should be repeated on backtracking.
edit Without the cut, we get multiple execution path, and so possibly incorrect results under 'all solution' predicates (findall, setof, etc...)
This last version put in evidence that the procedure isn't tail recursive. To get a tail recursive procedure add an accumulator:
countOdds(L, C) :- countOdds(L, 0, C).
countOdds([], A, A).
countOdds([X|Xs], A, Cs) :-
( odd(X)
-> A1 is A + 1
; A1 is A
),
countOdds(Xs, A1, Cs).

Resources