How to know if a Peano number is even - prolog

So I'm having a hard time trying with Peano and I need some help. I want to know if a Peano number is even and if yes then add:
0 + s(s(0)) = s(s(0))
0 + s(0) = No because one of the numbers odd
The code I have so far:
s(0).
s(X):-
X.
add(0,Y,Y).
add(s(X), Y, s(Z)):-
add(X,Y,Z).

Do not think about Peano numbers as numbers but as symbols.
Realize that the even Paeno numbers are 0 and a repeat of the pattern s(s(X)) where X can be 0 or the pattern s(s(X))
Also I look at 0 and s(0) etc. as data, and you are using s as a predicate name. I am not saying it will not work this way, but that is not how I think about this.
The name of the predicate is paeno_even and it takes one argument.
The base case is
paeno_even(0).
next for recursive case
paeno_even(P)
and the processing on P just removes s(s(X)) so do that in the head as
paeno_even(s(s(X)))
and then just do the recursive call
paeno_even(s(s(X))) :-
paeno_even(X).
A few test to demonstrate:
?- paeno_even(0).
true.
?- paeno_even(s(0)).
false.
?- paeno_even(s(s(0))).
true.
?- paeno_even(s(s(s(0)))).
false.
The entire code as one snippet:
paeno_even(0).
paeno_even(s(s(X))) :-
paeno_even(X).

Related

How can Prolog derive nonsense results such as 3 < 2?

A paper I'm reading says the following:
Plaisted [3] showed that it is possible to write formally correct
PROLOG programs using first-order predicate-calculus semantics and yet
derive nonsense results such as 3 < 2.
It is referring to the fact that Prologs didn't use the occurs check back then (the 1980s).
Unfortunately, the paper it cites is behind a paywall. I'd still like to see an example such as this. Intuitively, it feels like the omission of the occurs check just expands the universe of structures to include circular ones (but this intuition must be wrong, according to the author).
I hope this example isn't
smaller(3, 2) :- X = f(X).
That would be disappointing.
Here is the example from the paper in modern syntax:
three_less_than_two :-
less_than(s(X), X).
less_than(X, s(X)).
Indeed we get:
?- three_less_than_two.
true.
Because:
?- less_than(s(X), X).
X = s(s(X)).
Specifically, this explains the choice of 3 and 2 in the query: Given X = s(s(X)) the value of s(X) is "three-ish" (it contains three occurrences of s if you don't unfold the inner X), while X itself is "two-ish".
Enabling the occurs check gets us back to logical behavior:
?- set_prolog_flag(occurs_check, true).
true.
?- three_less_than_two.
false.
?- less_than(s(X), X).
false.
So this is indeed along the lines of
arbitrary_statement :-
arbitrary_unification_without_occurs_check.
I believe this is the relevant part of the paper you can't see for yourself (no paywall restricted me from viewing it when using Google Scholar, you should try accessing this that way):
Ok, how does the given example work?
If I write it down:
sm(s(s(s(z))),s(s(z))) :- sm(s(X),X). % 3 < 2 :- s(X) < X
sm(X,s(X)). % forall X: X < s(X)
Query:
?- sm(s(s(s(z))),s(s(z)))
That's an infinite loop!
Turn it around
sm(X,s(X)). % forall X: X < s(X)
sm(s(s(s(z))),s(s(z))) :- sm(s(X),X). % 3 < 2 :- s(X) < X
?- sm(s(s(s(z))),s(s(z))).
true ;
true ;
true ;
true ;
true ;
true
The deep problem is that X should be Peano number. Once it's cyclic, one is no longer in Peano arithmetic. One has to add some \+cyclic_term(X) term in there. (maybe later, my mind is full now)

Multiple instances of Prolog clauses with identical ground head. Any uses besides for this besides (dubious) control of computation?

In SWI Prolog:
Exact clause duplicates are allowed:
a(1).
a(1).
?- a(X).
X = 1 ;
X = 1.
or even:
c :- format("Hello from first c!").
c :- format("Hello from second c!").
Hello from first c!
true ;
Hello from second c!
true.
More generally, so are clauses with identical fully ground heads but differing bodies:
b(1) :- format("Hello from first b!").
b(1) :- format("Hello from second b!").
?- b(1).
Hello from first b!
true ;
Hello from second b!
true.
Clauses with identical non-ground head feel somewhat more reasonable:
p(X) :- format("Yup, this is p(~w)",X).
p(X) :- format("Yup, this is also p(~w)",X).
p(X) :- format("You think you can get rid of good old p(~w) just like that?",X).
?- p('homer simpson').
Yup, this is p(homer simpson)
true ;
Yup, this is also p(homer simpson)
true ;
You think you can get rid of good old p(homer simpson) just like that?
true.
?- p(X).
Yup, this is p(_4782)
true ;
Yup, this is also p(_4782)
true ;
You think you can get rid of good old p(_4782) just like that?
true.
This covers the reasonable case of clauses with a guarded body:
p(X) :- X < 0, format("It's less than 0: ~w", X).
p(X) :- X =:= 0, format("It's exactly 0: ~w", X).
p(X) :- X > 0, format("It's larger than 0: ~w", X).
On second thoughts ... we already encounter the ultimate case in the built-in repeat:
?- repeat.
true ;
true ;
true ;
true ;
…
Or can construct an intermediate case easily:
h :- member(_,[1,2,3]).
?- h.
true ;
true ;
true.
Somehow textbooks gloss over the fact that predicates have additional semantics: they can not only be false or true for any given ground arguments, but they can actually be true(n) - "true n times, n ≥ 0" .
From a theory standpoint, this is dubious, at least for vanilla classical logic.
On the other hand, it is useful from a computational standpoint for:
Side-effects (rather for output than for input, and rather marginally).
Control of the computation (i.e. repeat).
Are there any other uses?
I really feel the compiler should flag variable-less cases like a/1, c/0, b/1 above as errors (easy to detect), and even repeat/0 should probably have a value: repeat(Count). Anything which redoes successfully should NOT redo successfully in the same context on exactly the same ground arguments. It has the same squishy feeling of irrelevancy as a(X) :- b(Y). b(Z). Brrr!.
Yes, for diagnostic purposes in pure programs. By duplicating a clause you can answer the question how often the clause contributes to solutions.
That is, you count the answers/solutions you get from a query and compare these to the same program plus the duplicated clause. If the number of (redundant) solutions now increases you know that this clause contributes. The ld factor tells you how often.
Note that a tracer cannot tell you this as easily.
Some observations in the particular case of duplicated clauses.
If the repeated clauses for predicate a/1 are found in a Logtalk object or in a Prolog module that can be compiled as an object, the Logtalk linter can warn you of duplicated clauses. For example, given the following module:
:- module(duplicates, []).
a(1).
a(1).
We get:
?- set_logtalk_flag(duplicated_clauses, warning).
true.
?- {duplicates}.
* Duplicated clause: a(1)
* first found at or above line 3
* while compiling object duplicates
* in file /Users/pmoura/duplicates.lgt at or above line 4
*
% [ /Users/pmoura/duplicates.lgt loaded ]
% 1 compilation warning
true.
This particular lint warning is usually turned off by default due to its computational cost. If you load the tutor tool prior to the compilation of the module, you will get instead:
?- {tutor(loader)}.
...
% (0 warnings)
true.
?- set_logtalk_flag(duplicated_clauses, warning).
true.
?- {duplicates}.
* Duplicated clause: a(1)
* first found at or above line 3
* while compiling object duplicates
* in file /Users/pmoura/Desktop/duplicates.lgt at or above line 4
* Duplicated clauses are usually a source code editing error and can
* result in spurious choice-points, degrading performance. Delete or
* correct the duplicated clause to fix this warning.
*
% [ /Users/pmoura/Desktop/duplicates.lgt loaded ]
% 1 compilation warning
true.
The warning is useful and proved itself worth in non-trivial codebases.
#false mentions in his answer using duplicated clauses to "answer the question how often the clause contributes to solutions." He also mentions "that a tracer cannot tell you this as easily".
A better solution to this use case is to use a ports profiler tool as found in e.g. ECLiPSe and Logtalk. No need to duplicate clauses to gather that information.
As an example, consider the following pure program, saved in a pure.pl file:
a :- b, c.
b.
b :- d.
c.
d.
Let's include this code in an object. We can define it in a source file:
:- object(pure).
:- set_logtalk_flag(debug, on).
:- public(a/0).
:- include('pure.pl').
:- end_object.
Alternatively, we can create pure as a dynamic object:
?- create_object(pure, [], [set_logtalk_flag(debug,on), public(a/0), include('pure.pl')], []).
true.
Either way, after loading or creating the pure object and loading the ports_profiler tool, we can e.g. query all solutions for the a/0 predicate and then print the profiling data:
?- {ports_profiler(loader)}.
...
% (0 warnings)
true.
?- pure::a.
true ;
true.
?- ports_profiler::data.
-------------------------------------------------------------------
Entity Predicate Fact Rule Call Exit *Exit Fail Redo Error
-------------------------------------------------------------------
pure a/0 0 1 1 1 1 0 1 0
pure b/0 1 1 1 1 1 0 1 0
pure c/0 2 0 2 2 0 0 0 0
pure d/0 1 0 1 1 0 0 0 0
-------------------------------------------------------------------
true.
The table displays port crossing information for all predicates used in the query to the a/0 predicate. For example, that the predicate c/0 as called twice (for the two solutions to a/0) and exited deterministically. On the other hand, the predicate b/0 was called once by succeeded twice (on of them non-deterministically) due to backtracking.
For details on the portable port_profiler tool and a discussion on the insights that it can provide, see:
https://logtalk.org/manuals/devtools/ports_profiler.html

Return Integer with 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).

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!

Why is this elementary Prolog predicate not stopping execution?

I want to write a predicate that determines if a number is prime or not. I am doing this by a brute force O(sqrt(n)) algorithm:
1) If number is 2, return true and do not check any more predicates.
2) If the number is even, return false and do no more checking predicates.
3) If the number is not even, check the divisors of the number up to the square root. Note that
we need only to check the odd divisors starting at 3 since if we get to this part of
the program the number is not even. Evens were eliminated in step 2.
4) If we find an even divisor, return false and do not check anything else.
5) If the divisor we are checking is larger than the square root of the number,
return true, we found no divisors. Do no more predicate checking.
Here is the code I have:
oddp(N) :- M is N mod 2, M = 1.
evenp(N) :- not(oddp(N)).
prime(2) :- !.
prime(X) :- X < 2, write_ln('case 1'), false, !.
prime(X) :- evenp(X), write_ln('case 2'), false, !.
prime(X) :- not(evenp(X)), write_ln('calling helper'),
prime_helper(X,3).
prime_helper(X, Divisor) :- K is X mod Divisor, K = 0,
write_ln('case 3'), false, !.
prime_helper(X, Divisor) :- Divisor > sqrt(X),
write_ln('case 4'), !.
prime_helper(X, Divisor) :- write_ln('case 5'),
Temp is Divisor + 2, prime_helper(X,Temp).
I am running into problems though. For example, if I query prime(1). the program is still checking the divisors. I thought that adding '!' would make the program stop checking if the prior conditions were true. Can someone tell me why the program is doing this? Keep in mind I am new at this and I know the code can be simplified. However, any tips would be appreciated!
#Paulo cited the key issues with the program that cause it to behave improperly and a couple of good tips. I'll add a few more tips on this particular program.
When writing a predicate, the focus should be on what's true. If your
predicate properly defines successful cases, then you don't need to explicitly
define the failure cases since they'll fail by default. This means your statements #2 and #4 don't need to be specifically defined as clauses.
You're using a lot of cuts which is usually a sign that your program
isn't defined efficiently or properly.
When writing the predicates, it's helpful to first state the purpose in logical language form (which you have done in your statements 1 through 5, but I'll rephrase here):
A number is prime if it is 2 (your statement #1), or if it is odd and it is not divisible by an odd divisor 3 or higher (your statement #3). If we write this out in Prolog, we get:
prime(X) :- % X is prime if...
oddp(X), % X is odd, AND
no_odd_divisors(X). % X has no odd divisors
prime(2). % 2 is prime
A number X is odd if X module 2 evaluates to 1.
oddp(X) :- X mod 2 =:= 1. % X is odd if X module 2 evaluates to 1
Note that rather than create a helper which essentially fails when I want success, I'm going to create a helper which succeeds when I want it to. no_odd_divisors will succeeds if X doesn't have any odd divisors >= 3.
A number X has no odd divisors if it is not divisible by 3, and if it's not divisible by any number 3+2k up to sqrt(X) (your statement #5).
no_odd_divisors(X) :- % X has no odd divisors if...
no_odd_divisors(X, 3). % X has no odd divisors 3 or above
no_odd_divisors(X, D) :- % X has no odd divisors D or above if...
D > sqrt(X), !. % D is greater than sqrt(X)
no_odd_divisors(X, D) :- % X has no odd divisors D or above if...
X mod D =\= 0, % X is not divisible by D, AND
D1 is D + 2, % X has no odd divisors D+2 or above
no_odd_divisors(X, D1).
Note the one cut above. This indicates that when we reach more than sqrt(X), we've made the final decision and we don't need to backtrack to other options for "no odd divisor" (corresponding to, Do no more predicate checking. in your statement #5).
This will yield the following behavior:
| ?- prime(2).
yes
| ?- prime(3).
(1 ms) yes
| ?- prime(6).
(1 ms) no
| ?- prime(7).
yes
| ?-
Note that I did define the prime(2) clause second above. In this case, prime(2) will first fail prime(X) with X = 2, then succeed prime(2) with nowhere else to backtrack. If I had defined prime(2) first, as your first statement (If number is 2, return true and do not check any more predicates.) indicates:
prime(2). % 2 is prime
prime(X) :- % X is prime if...
oddp(X), % X is odd, AND
no_odd_divisors(X). % X has no odd divisors
Then you'd see:
| ?- prime(2).
true ? a
no
| ?-
This would be perfectly valid since Prolog first succeeded on prime(2), then knew there was another clause to backtrack to in an effort to find other ways to make prime(2) succeed. It then fails on that second attempt and returns "no". That "no" sometimes confuses Prolog newcomers. You could also prevent the backtrack on the prime(2) case, regardless of clause order, by defining the clause as:
prime(2) :- !.
Which method you choose depends ultimately on the purpose of your predicate relations. The danger in using cuts is that you might unintentionally prevent alternate solutions you may actually want. So it should be used very thoughtfully and not as a quick patch to reduce outputs.
There are several issues on your program:
Writing a cut, !/0, after a call to false/0 is useless and as the cut will never be reached. Try exchanging the order of these two calls.
The first clause can be simplified to oddp(N) :- N mod 2 =:= 1. You can also apply this simplification in other clauses.
The predicate not/1 is better considered deprecated. Write instead evenp(N) :- \+ oddp(N).. The (\+)/1 is the standard operator/control construct for negation as failure.

Resources