Successor Arithmetic Prolog Mod function - prolog

How to write mod/3 function for successor arithmetic (Peano's Numbers) in prolog?

Think of it this way:
If you want to find the mod of 10 and 4, you divide 10 by 4 and return the reminder. But since divide is multiple subtractions we will use the multiple subtraction logic here.
For Example: 10 mod 4 is same as 10-4 mod 4 which is 6 mod 4 which is again same as 6-4 mod 4 = 2 mod 4. Since the first element (2) is less than the second (4), we terminate the program here and return first element (2).
mod(_, 0, 0). Says that anything mod 0 is 0.
mod(0, _ , 0). Says that 0 mod anything is 0.
mod(X, s(0), 0). Says that anything mod 1 is 0.
This is the tricky part:
mod(A, B, N) :- minus(A, B, R), (R #< B -> N = R ; mod(R, B, N)). This uses the multiple minus logic. If first removes second from first and then checks if first is smaller that the second. If yes, recursively call the mod function. If not return the first element.
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).
mod(_, 0, 0).
mod(0, _ , 0).
mod(X, s(0), 0).
mod(A, B, N) :- minus(A, B, R), (R #< B -> N = R ; mod(R, B, N)).
Thank you #Toby for the edit request.

Related

Increment a variable by constant in recursive rules in prolog

Here's the line of code written in prolog to make an lcm (Least Common Multiple) rule:
lcm(A, B, A) :-
A > B,
A mod B =:= 0,
!.
lcm(A, B, B) :-
B > A,
B mod A =:= 0,
!.
lcm(A, B, X) :-
A < B,
ImproveB is B + B,
lcm(A, ImproveB, X).
lcm(A, B, X) :-
A > B,
ImproveA is A + A,
lcm(ImproveA, B, X).
I noticed that there's a bug in these lines of code.
For example, the case is lcm(16,10,X) which operated as below:
lcm(16,10,X).
lcm(32,10,X).
lcm(64,10,X).
lcm(128,10,X).
...
It will double the larger number and not increment it by the expected constant. The expected operation is as below:
lcm(16,10,X).
lcm(32,10,X).
lcm(48,10,X).
lcm(64,10,X).
lcm(80,10,X).
since 80 mod 10 is 0, so the result of X is 80
So, how to handle this situation?
To solve the problem, the constant value to be added must be passed as an extra argument (which does not change). Also, to reduce the number of clauses, you can fix the order of the arguments so that the first one is the maximum and the second one is the minimum:
lcm(A, B, C) :-
Min is min(A, B),
Max is max(A ,B),
lcm_loop(Max, Min, Max, C).
lcm_loop(A, B, K, C) :-
( A mod B =:= 0
-> C = A
; A1 is A + K,
lcm_loop(A1, B, K, C) ).

Prolog - print the sum of the EVEN numbers from 1 to 10

I am trying to print all the even numbers from 1 to 10 using Prolog, and here is what I have tried:
printn(10,0):- write(10),!.
printn(X,Sum):-
( X mod 2 =:= 0 -> Sum is X+Sum, Next is X+1, nl, printn(Next);
Next is X+1, printn(Next) ).
but it returns false.
You don't need to create the list with the numbers from the beginning, it is better to examine numbers once:
print(X,Y):-print_even(X,Y,0).
print_even(X, X, Sum):-
( X mod 2 =:= 0 -> Sum1 is X+Sum;
Sum1 = Sum
), print(Sum1).
print_even(X, Y, Sum):-
X<Y, Next is X+1,
( X mod 2 =:= 0 -> Sum1 is X+Sum, print_even(Next, Y, Sum1);
print_even(Next, Y, Sum)
).
Keep in mind that in Prolog Sum is Sum+1 always fails you need to use a new variable e.g Sum1.
Example:
?- print(1,10).
30
true ;
false.
The most useful way of obtaining Prolog output is to capture the solution in a variable, either individually through backtracking, or in a list. The idea of "printing", which carries over from using other languages allows for formatting, etc, but is not considered the best way to express a solution.
In Prolog, you want to express your problem as a relation. For example, we might say, even_with_max(X, Max) is true (or succeeds) if X is an even number less than or equal to Max. In Prolog, when reasoning with integers, the CLP(FD) library is what you want to use.
:- use_module(library(clpfd)).
even_up_to(X, Max) :-
X in 1..Max,
X mod 2 #= 0, % EDIT: as suggested by Taku
label([X]).
This will yield:
3 ?- even_up_to(X, 10).
X = 2 ;
X = 4 ;
X = 6 ;
X = 8 ;
X = 10.
If you then want to collect into a list, you can use: findall(X, even_up_to(X), Evens).
What error do you have? Here is my solution:
Create list [1...10]
Filter it, excluding odd numbers
Sum elements of the list
Code:
sumList([], 0).
sumList([Head|Tail], Sum) :-
sumList(Tail, Rest),
Sum is Head + Rest.
isOdd(X) :-
not((X mod 2) =:= 0).
sumOfEvenNums(A, B, Out) :-
numlist(A, B, Numbers),
exclude(isOdd, Numbers, Even_numbers),
sumList(Even_numbers, Out).
Now you can call sumOfEvenNums(1, 10, N)
In ECLiPSe, you can write with iterator:
sum_even(Sum):-
( for(I,1,10),fromto(0,In,Out,Sum)
do
(I mod 2 =:= 0 -> Out is In + I;Out is In)
)
With library(aggregate):
evens_upto(Sum) :-
aggregate(sum(E), (between(1, 10, E), E mod 2 =:= 0), Sum).
Thanks to #CapelliC for the inspiration.

Prolog - summing up predicate results

Let's say i have the following predicate:
func1(X,B,R)
I provide it with a certain X and B and in return it gives me 5 different results for R.
EDIT:
The X and B do not specify a range. rather, X specify an integer (say 120) and B specifies all integers (starting from 1) whose cubic is less than X.
What func1 does is calculating R as the result the remainder.
In this case where X=120:
B = 1, R = 119 (120-1^3)
B = 2, R = 112 (120-2^3)
B = 3, R = 93 (120-3^3)
B = 4, R = 56 (120-4^3)
It would not calculate B=5 since 5^3 = 125 which is greater than 120, so it stops here.
How can i make a predicate such as:
func2(R,S)
That would accept all of the results given by R, sum them up and store them in S?
Thanks!
To start with, since the values of B are totally derivable from the value of X, I wouldn't include both as arguments in func1. I'll introduce a predicate func3/2 which is true if the second argument is derivable from the first (i.e., func3(X, B) is true if B is derivable from X):
func1(X, R) :-
func3(X, B),
...
What will happen if you query func1(120, R) is you'd get one or more results for R. Then you can use findall/3 as I indicated in my comment:
func2(X, S) :-
findall(R, func1(X, R), Rs),
sumlist(Rs, S).
To define func3/2 the cleanest approach would be to use CLP(FD):
:- use_module(library(clpfd)).
func3(X, B) :-
B #>= 0,
(X - B^3) #>= 0,
label([B]).
Here's an example of what func3 does:
?- func3(120, B).
B = 1 ;
B = 2 ;
B = 3 ;
B = 4.
A much less desirable way to do this if you can't use CLP(FD) would be to use between and define the upper limit of B to be the greatest integer not exceeding the cube root of X:
func3(X, B) :-
Limit is floor(exp(log(X) / 3)),
between(1, Limit, B).
Which yields the same result as above.

Implementing XOR function with Prolog CLPFD for 32-bit numbers

I try to implement efficient exclusive-or (XOR) in Prolog CLPFD. This should be simple predicate like:
xor(A, B, AxorB).
A, B, AxorB are natural numbers (with 0) and AxorB is a result of A xor B.
My main problem is with efficiency. Firstly, I wasn't able to find any way to XOR two number without breaking those numbers into separate parts that could be further processed/constrained, and the process of breaking those numbers (creating proper constraints and then resolving them) is taking some processing time. Secondly, I wans't able to come up with any efficient way to "simulate" XOR functions on natural numbers other than presented in the second code below.
Lets start from my first code. This is the most simple XOR implementation possible and it works only for 1 bit values (0 and 1):
xor_1bit_values(A, B, AxorB) :-
AxorB #= (A + B) mod 2.
To use it for numbers larger than 1, numbers must be broken into bits:
xor_number(A, B, Result, Bits) :-
Count is Bits - 1,
xor_number(A, B, Result, Count, 0).
xor_number(A, B, Result, 0, Sum) :-
xor_1bit_values(A, B, Xor),
Result #= Xor + Sum.
xor_number(A, B, Result, Count, Sum) :-
P is 2^Count,
X #= A / P,
Y #= B / P,
xor_1bit_values(X, Y, Tmp),
NewSum #= Sum + P*Tmp,
NewCount is Count - 1,
xor_number(A, B, Result, NewCount, NewSum).
Sample input and output:
?- time(xor_number(123456789, 987654321, R, 32)).
% 943 inferences, 0.000 CPU in 0.001 seconds (0% CPU, Infinite Lips)
R = 1032168868
Now, this is too slow for my purposes, as in my code I have sometimes need to guess A and B when I have AxorB where all of these should be 32-bit numbers. And for numbers that need more than 10 bits this goes into literal millions of inferences that seem to increase expotentially. And I use the best labeling strategies, XOR arguments swapping and other tricks to speed up calculations.
So, I tried to do some maths. What I devised is XOR function for 2-bit values (0, 1, 2, 3):
xor_2bit_values(A, B, Result) :-
Result #= ((A + B*((-1)^A)) mod 4).
To use it in numbers larger than 3 there is code similar to what I presented before:
xor_number2(A, B, Result, Bits) :-
Count is (Bits / 2) - 1,
xor_number2(A, B, Result, Count, 0).
xor_number2(A, B, Result, 0, Sum) :-
xor_2bit_values(A, B, Xor),
Result #= Xor + Sum,
!.
xor_number2(A, B, Result, Count, Sum) :-
P is 4^Count,
X #= A / P,
Y #= B / P,
xor_2bit_values(X, Y, Tmp),
NewSum #= Sum + P*Tmp,
NewCount is Count - 1,
xor_number2(A, B, Result, NewCount, NewSum).
This seems to work nearly 50% faster than the first code. But still, two-fold difference is still too small for me.
So, my question for you is this: how can I implement efficient XOR for 32-bit numbers? If this is not possible on modern machines and you can prove it by some sort of calcucation then it is also a nice answer to my question. Eventually, how can I best improve my code? Maybe you have some ideas how to deal with numbers without breaking them apart or how to XOR numbers in other way?
Additional info: If it happens to you to try my code to guess two from three arguments or XOR, then because of possibility to freely swap arguments of that functions (which comes from its mathematical properties) I recommend setting A as bound variable and B and AxorB as unbound. CLPFD seems to work fastest that way. Also, the best labeling strategy would be labeling([bisect], [B,AxorB].
I think I would try to precompute some table of 'bit chunks', and then, using modulo and division (both supported operations), would do N lookups into the table. The idea it's that a lookup could work faster than the (huge!) arithmetic expansion performed by the library. This is the usual 'trade space for time' trick.
/** <module> bits_clpfd
*
* naive implementation of basic bit operations on constrained variables
* --------
*
* source file /home/carlo/prolog/bits_clpfd.pl
* created at dom mag 18 07:57:03 2014
*
* #author carlo
* #version 0.9.9
* #copyright carlo
* #license LGPL v2.1
*/
:- module(bits_clpfd,
[bits_clpfd_prepare_lut/2
]).
:- use_module(library(clpfd)).
:- dynamic lut_and_or_xor/5.
:- dynamic chunk_size/2.
%% bits_clpfd_prepare_lut(Bits, Max) is det.
%
% setup the lookup table for basic most operations on constrained variables
% the cost is mainly controlled by Bits, being the LUT size 2^(Bits*2)
%
% #arg Bits how many bits to store
% #arg Max describe Max
%
bits_clpfd_prepare_lut(Bits, BMax) :-
( nonvar(Bits) ; Bits = 4 ),
( nonvar(BMax) ; BMax = 32 ),
retractall(chunk_size(_, _)),
Max is 1 << BMax,
assert(chunk_size(Bits, Max)),
retractall(lut_and_or_xor(_,_, _,_,_)),
N is (1 << Bits) - 1,
forall((between(0, N, A), between(0, N, B)), (
And is A /\ B,
Or is A \/ B,
Xor is A xor B,
assertz(lut_and_or_xor(A,B, And,Or,Xor))
)).
%% xor_clpfd(A, B, C) is nondet.
%
% naive constraint A xor B #= C
%
% #arg A constrained variable
% #arg B constrained variable
% #arg C constrained variable
%
xor_clpfd(A, B, C) :-
maplist(check_domain_range, [A,B,C]),
split_apply_xor(1, A, B, C).
split_apply_xor(L, A, B, C) :-
chunk_size(NBits, Max),
( L < Max
-> Mod is (2 << NBits),
Am #= A mod Mod,
Bm #= B mod Mod,
Cm #= C mod Mod,
lut_and_or_xor(Am, Bm, _, _, Cm),
Ad #= A / Mod,
Bd #= B / Mod,
Cd #= C / Mod,
M is L << NBits,
split_apply_xor(M, Ad, Bd, Cd)
; true
).
check_domain_range(V) :-
chunk_size(_, Max),
assertion((fd_dom(V, Inf .. Sup), Inf>=0, Sup < Max)).
:- begin_tests(bits_clpfd).
test(1) :-
bits_clpfd_prepare_lut(2, 4),
Vs = [A,B,C], Vs ins 0..15,
A #= 1, B #= 1, C #= 0,
xor_clpfd(A, B, C).
:- end_tests(bits_clpfd).
test
?- run_tests(bits_clpfd).
% PL-Unit: bits_clpfd
Warning: /home/carlo/prolog/bits_clpfd.pl:83:
PL-Unit: Test 1: Test succeeded with choicepoint
done
% test passed
true.
anyway, this is a naive approach, the right one should be to compile your own run_propagator/2. But I've never done it...
Maybe it wasn't available then but now, we can do this:
Y in 0..5, X #= Y xor 1, label([Y]).
From the docs, it's written that:
The bitwise operations ()/1, (/)/2, (/)/2, (>>)/2, (<<)/2, lsb/1, msb/1, popcount/1 and (xor)/2 are also supported.
See if you can adapt this for your purposes.

Beginner - add multiples of 3 and 5

I'm trying to find the sum of all positive multiples of 3 and 5 below 1000. After adding the portion that's supposed to remove the multiples of 3 from the sum of the multiples of 5, gprolog will keep spitting out "No" for the query ?- sigma(1000,N).
The problem apparently lies in sigma5, but I can't quite spot it:
sigma(Num, Result) :- sigma3(Num, 3, Result3),
sigma5(Num, 5, Result5),
Result is Result3 + Result5.
sigma3(Num, A, Result) :- A < Num,
Ax is A+3,
sigma3(Num, Ax, ResultX),
Result is ResultX + A.
sigma3(Num, A, Result) :- A >= Num,
Result is 0.
sigma5(Num, A, Result) :- A < Num,
mod3 is A mod 3,
0 \= mod3,
Ax is A+5,
sigma5(Num, Ax, ResultX),
Result is ResultX + A.
sigma5(Num, A, Result) :- A < Num,
mod3 is A mod 3,
0 == mod3,
Ax is A+5,
sigma5(Num, Ax, ResultX),
Result is ResultX.
sigma5(Num, A, Result) :- A >= Num,
Result is 0.
What's the problem with my code?
As integers are involved, consider using finite domain constraints. For example, with SWI-Prolog:
?- use_module(library(clpfd)).
true.
?- findall(N, (N mod 3 #= 0 #\/ N mod 5 #= 0, N in 0..999, indomain(N)), Ns),
sum(Ns, #=, Sum).
Ns = [0, 3, 5, 6, 9, 10, 12, 15, 18|...],
Sum = 233168.
Prolog has never been popular for it's arithmetic capabilities.
This is due to the need to represent 'term constructors' for symbolic processing, without undue evaluation, so when actual arithmetic is required we must explicitly allocate the 'space' (a variable) for the result, instead that 'passing down' an expression. This lead to rather verbose and unpleasant code.
But using some popular extension, like CLP(FD), available in GProlog as well as SWI-Prolog, we get much better results, not readily available in other languages: namely, a closure of the integer domain over the usual arithmetic operations. For instance, from the SWI-Prolog CLP(FD) library, a 'bidirectional' factorial
n_factorial(0, 1).
n_factorial(N, F) :- N #> 0, N1 #= N - 1, F #= N * F1, n_factorial(N1, F1).
?- n_factorial(X, 3628800).
X = 10 .
Anyway, here is a simple minded solution to the original problem, similar to what you attempted, but using an accumulator to compute result. This simple trick allows writing a tail recursive procedure, that turns out in better efficiency.
sigma(Num, Result) :-
sigma(1, Num, 0, Result).
sigma(N, M, Acc, Tot) :-
( N < M, !,
( (0 is N mod 3 ; 0 is N mod 5)
-> Sum is Acc + N
; Sum is Acc
),
N1 is N + 1,
sigma(N1, M, Sum, Tot)
; Tot is Acc
).
Test:
?- sigma(1000, X).
X = 233168 .
mod3 is A mod 3,
(as well all the other occurrences of mod3) should be Mod3 since it is a variable.
with that fix, the program runs correctly (at least for N=1000)
btw here is my solution (using higher-order predicates):
sum(S):-
findall(X,between(1,999,X),L), % create a list with all numbers between 1 and 999
include(div(3),L,L3), % get the numbers of list L which are divisible by 3
include(div(5),L,L5), % get the numbers of list L which are divisible by 5
append(L3,L5,LF), % merge the two lists
list_to_set(LF,SF), % eliminate double elements
sumlist(SF,S). % find the sum of the members of the list
div(N,M):-
0 is M mod N.
it's less efficient of course but the input is too small to make a noticeable difference
This all seems very complicated to me.
sum_of( L , S ) :-
L > 0 ,
sum_of( 0 , L , 0 , S )
.
sum_of( X , X , S , S ) . % if we hit the upper bound, we're done.
sum_of( X , L , T , S ) :- % if not, look at it.
X < L , % - backtracking once we succeeded.
add_mult35( X , T , T1 ) , % - add any multiple of 3 or 5 to the accumulator
X1 is X + 1 , % - next X
sum_of( X1 , L , T1 , S ) % - recurse
.
add_mult35( X , T , T ) :- % no-op if X is
X mod 3 =\= 0 , % - not a multiple of 3, and
X mod 5 =\= 0 , % - not a multiple of 5
!. %
add_mult35( X , T , T1 ) :- % otherwise,
T1 is T + X % increment the accumulator by X
.
This could be even more concise than it is.
Aside from my code probably being extraordinarily horrible (it's actually longer than my C solution, which is quite a feat on it's own),
ANSI C:
int sum_multiples_of_three_and_five( int lower_bound , int upper_bound )
{
int sum = 0 ;
for ( int i = lower_bound ; i <= upper_bound ; ++i )
{
if ( 0 == i % 3 || 0 == i % 5 )
{
sum += i ;
}
}
return sum ;
}

Resources