Implementing XOR function with Prolog CLPFD for 32-bit numbers - prolog

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.

Related

Counting the number of valuations via Quine algorithm in Prolog

My logic teacher said in passing that Quines algorithm
can be also used to count valuations. Unfortunately I
cannot get my head around how this is done in Prolog?
The program would for example give, using
the syntax from the answer in Quines algorithm:
?- sat_count(X+Y, C).
C = 3
Since the truth table for the disjunction X+Y
has 3 rows that valuate to true:
X Y X+Y
0 0 0
0 1 1
1 0 1
1 1 1
Point of departure is Quines algorithm with its core predicate eval/2 which has the following specification. The source code of the Quine algorithm and the solution to the question can be found here.
/**
* eval(A, R):
* The predicate succeeds in R with a partial evaluated
* Boolean formula. The predicate starts with the leaves
* and calls simp after forming new nodes.
*/
% eval(+Formula, -Formula)
We first experimented with a labeling predicate, that
will list all valuations without counting them. The predicate
has a fast fail feature, if the partially evaluated formula
is false (0) then labeling needs not to proceed, otherwise we
simply probe the boolean values:
/**
* labeling(L, A):
* The predicate labels the variables from the list L in the formula A.
*/
% labeling(+List, +Formula)
labeling(_, A) :- A == 0, !, fail.
labeling([X|L], A) :- value(X), eval(A, B), labeling(L, B).
labeling([], A) :- A == 1.
Here is an example run:
?- labeling([X,Y], X+Y).
X = 0,
Y = 1 ;
X = 1,
Y = 0 ;
X = 1,
Y = 1
From the labeling predicate we derived a counting predicate
using findall/3 from the ISO core standard. Instead of
succeeding at the end we return 1, inbetween we sum the counts.
This does the job and also profits from fast failing:
/**
* count(L, A, N):
* The predicate silently labels the variables from the list L in the
* formula A and succeeds in N with the count of the solutions.
*/
% count(+List, +Formula, -Integer)
count(_, A, C) :- A == 0, !, C = 0.
count([X|L], A, D) :-
findall(C, (value(X), eval(A, B), count(L, B, C)), R),
sum(R, 0, D).
count([], A, 1) :- A == 1.
Here is an example run:
?- count([X,Y], X+Y, C).
C = 3
The implementation might profit from some optimizations that we didn't implement. For example assigning values to a variable that does not anymore occure in the formula could be optimized away.

Successor Arithmetic Prolog Mod function

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.

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.

Can someone describe this Prolog code step by step?

Prolog is new to me. I'm trying to understand this code. If anyone could explain it step by step in child language that would be a great help ;) thankyou!
divide_by(X,D,I,R) :-
X < D,
I is 0,
R is X.
divide_by(X,D,I,R) :-
X >= D,
Q is X - D,
divide_by(Q, D, S, R),
I is S +1.
Well, I can't. You are asking the wrong question. The right question would be:
What relation does the predicate describe?
Actually, that is quite difficult to answer, as we would have go through it step-by-step. But there is a better and much cleaner way! As your program uses integers only, we can map the moded relations (<)/2, (is)/2 and the like to their declarative counterparts in CLP(FD). So I change < to #<, is to #=, >= to #>=.
:- use_module(library(clpfd)).
divide_by(X,D,I,R):-
X #< D, I #= 0, R #= X.
divide_by(X,D,I,R):-
X #>= D, Q #= X - D,
I #= S +1,
divide_by(Q, D, S, R).
The big advantage now is that I can ask Prolog what it thinks the relation is describing. Simply ask: (Don't worry about the Q=Q, it's just to reorder variables)
N ... dividend
D ... divisor
Q ... quotient
R ... remainder
?- Q=Q, divide_by(N,D,Q,R).
Q = 0, N = R, N#=<D+ -1
This answer reads as follows: The quotient is zero, the dividend and remainder is the same and the remainder is less than the divisor. So this describes all situations where 0 is the "result" or quotient.
Next answer:
; Q = 1, R+D#=N, R#=<D+ -1, N#>=D
The quotient is 1 and the dividend is the divisor plus remainder, and — as in all answers — the remainder is less than the divisor
; Q = 2, _A+D#=N, R+D#=_A, R#=<D+ -1, N#>=D, _A#>=D
This answer is the same as R+D+D#= N. The system has introduced some extra variables. Not wrong, but a bit clumsy to read.
; Q = 3, _A+D#=N, _B+D#=_A, R+D#=_B, R#=<D+ -1, N#>=D, _A#>=D, _B#>=D
; Q = 4, _A+D#=N, _B+D#=_A, _C+D#=_B, R+D#=_C, R#=<D+ -1,
N#>=D, _A#>=D, _B#>=D, _C#>=D
; ... .
And so on. Let me summarize. All answers look like that:
N#>=D, R#< D, R+D+...+D#= N
^^^^^^^ Q times
or even better:
N#>=D, R #< D, R+Q*D #= N, Q #>= 0.
So what we have answered is what this relation is describing.
When you start Prolog, focus on the declarative side. As what (set/relation) a predicate describes. The procedural side will join without any effort later on.
The first rule is called the base case. It will terminate the recursion.
divide_by(X,D,I,R):-
X < D, % this rule apply only if numerically X is < D
I is 0, % will fail if I \= 0
R is X. % if I = 0 assign expression X to R
This other it's the recursive step.
divide_by(X,D, I, R):-
X >= D, % this rule apply only if X is >= D
Q is X - D, % evaluate Q
divide_by(Q, D, S, R), % recursive call. Q & D are surely instantiated
I is S + 1. % evaluate I as S + 1
So, I would say: it will compute the integer division of X by D, with remainder R, when called in mode divide_by(+,+,-,-), that is with first two arguments bound to integers and the last two free.
Anyway, false' answer is very good, as show a possible way to reason about arithmetic that is not available in 'common' programming languages.

Sequence of Fibonnaci Numbers - Prolog

While attempting to learn Prolog I came across a good exercise which was to write a program that displays the Nth Fibonacci number. After some work I got it working and then decided to see if I could write a program that displays a range of Fibonacci numbers according to the input.
For instance the input:
?- fib_sequence(2,5,Output).
Gives the output:
?- Output = [1,1,2,3]
I am having difficulty, however, in finding a good starting point. This is what I have so far:
fib(0, 0).
fib(1, 1).
fib(N, F) :- X is N - 1, Y is N - 2, fib(X, A), fib(Y, B), F is A + B.
fib_sequence(A,B,R) :- fib(A,Y) , fib(B,Z).
I know I must assign a value to R, but I'm not sure how to assign multiple values. Any help is greatly appreciated.
Observe that your fib_sequence cannot be done in a single predicate clause: you need at least two to keep things recursive - one to produce an empty list when A is greater than B (i.e. we've exhausted the range from A to B), and another one to prepend X from fib(A,X) to a list that you are building, increment A by 1, and call fib_sequence recursively to produce the rest of the sequence.
The first predicate clause would look like this:
fib_sequence(A,B,[]) :- A > B.
The second predicate clause is a bit harder:
fib_sequence(A,B,[H|T]) :-
A =< B /* Make sure A is less than or equal to B */
, fib(A, H) /* Produce the head value from fib(A,...) */
, AA is A + 1 /* Produce A+1 */
, fib_sequence(AA, B, T). /* Produce the rest of the list */
Prolog has some helper builtin to handle numeric sequences, then as an alternative to dasblinkenlight' answer, here is an idiomatic 'query':
fib_sequence(First, Last, Seq) :-
findall(F, (between(First,Last,N), fib(N,F)), Seq).
note that it will not work out-of-the-box with your fib/2, because there is a bug: I've added a condition that avoid the endless loop you would experience trying to backtrack on fib/2 solutions:
fib(N, F) :- N > 1, % added sanity check
X is N - 1, Y is N - 2, fib(X, A), fib(Y, B), F is A + B.
Here's yet another approach. First, I redid fib a little so that it only recursively calls itself once instead of twice. To do this, I created a predicate that returns the prior the last two Fibonacci values instead of the last one:
fib(N, F) :-
fib(N, F, _).
fib(N, F, F1) :-
N > 2,
N1 is N-1,
fib(N1, F1, F0),
F is F0 + F1.
fib(1, 1, 0).
fib(2, 1, 1).
For getting the sequence, I chose an algorithm with the Fibonacci calculation built-in so that it doesn't need to call fib O(n^2) times. It does, however, need to reverse the list when complete:
fib_sequence(A, B, FS) :-
fib_seq_(A, B, FSR),
reverse(FSR, FS).
fib_sequence_(A, B, []) :-
A > B.
fib_sequence_(A, B, [F]) :-
A =:= B,
fib(A, F, _).
fib_sequence_(A, B, [F1,F0]) :-
1 is B - A,
fib(B, F1, F0).
fib_sequence_(A, B, [F2,F1,F0|FT] ) :-
B > A,
B1 is B - 1,
fib_sequence_(A, B1, [F1,F0|FT]),
F2 is F1 + F0.
Here's one more way, to do it without the reverse, but the reverse method above still appears to be a little faster in execution.
fib_sequence_dl(A, B, F) :-
fib_sequence_dl_(A, B, F, [_,_|[]]).
fib_sequence_dl_(A, B, [], _) :-
A > B, !.
fib_sequence_dl_(A, B, [F], _) :-
A =:= B,
fib(A, F, _), !.
fib_sequence_dl_(A, B, [F0,F1|T], [F0,F1|T]) :-
1 is B - A,
fib(B, F1, F0), !.
fib_sequence_dl_(A, B, F, [F1,F2|T]) :-
A < B,
B1 is B - 1,
fib_sequence_dl_(A, B1, F, [F0,F1|[F2|T]]),
F2 is F0 + F1.

Resources