Tôi cố gắng thực hiện độc quyền hoặc (XOR) hiệu quả trong Prolog CLPFD. Điều này cần được đơn giản ngữ như:Thực hiện chức năng XOR với Prolog CLPFD cho các số 32 bit
xor(A, B, AxorB).
A
, B
, AxorB
là số tự nhiên (với 0) và AxorB
là kết quả của A
xorB
.
Vấn đề chính của tôi là hiệu quả. Thứ nhất, tôi đã không thể tìm thấy bất kỳ cách nào để XOR hai số mà không vi phạm các số đó thành các phần riêng biệt có thể được xử lý/hạn chế hơn nữa và quá trình phá vỡ các số đó (tạo ra các ràng buộc thích hợp và sau đó giải quyết chúng) thời gian. Thứ hai, tôi không thể đưa ra bất kỳ cách hiệu quả nào để "mô phỏng" các hàm XOR trên các số tự nhiên khác ngoài các mã được trình bày trong mã thứ hai bên dưới.
Cho phép bắt đầu từ mã đầu tiên của tôi. Đây là XOR thực hiện đơn giản nhất có thể và nó chỉ hoạt động cho các giá trị 1 bit (0 và 1):
xor_1bit_values(A, B, AxorB) :-
AxorB #= (A + B) mod 2.
Để sử dụng nó cho số lớn hơn 1, số phải được chia thành các bit:
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).
mẫu đầu vào và đầu ra:
?- time(xor_number(123456789, 987654321, R, 32)).
% 943 inferences, 0.000 CPU in 0.001 seconds (0% CPU, Infinite Lips)
R = 1032168868
Bây giờ, đây là quá chậm cho các mục đích của tôi, như trong mã của tôi, tôi có đôi khi cần phải đoán A
và B
khi tôi có 0.123.trong đó tất cả các số này phải là số 32 bit. Và đối với những con số cần nhiều hơn 10 bit, điều này đi vào hàng triệu suy luận theo nghĩa đen dường như gia tăng theo cấp số nhân. Và tôi sử dụng các chiến lược ghi nhãn tốt nhất, các đối số XOR trao đổi và các thủ thuật khác để tăng tốc độ tính toán.
Vì vậy, tôi đã cố gắng thực hiện một số phép toán. Những gì tôi nghĩ ra là chức năng XOR cho các giá trị 2-bit (0, 1, 2, 3):
xor_2bit_values(A, B, Result) :-
Result #= ((A + B*((-1)^A)) mod 4).
Để sử dụng nó với số lượng lớn hơn 3 có mã tương tự như những gì tôi đã trình bày trước đây:
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).
Điều này dường như hoạt động nhanh hơn gần 50% so với mã đầu tiên. Nhưng vẫn còn, sự khác biệt hai lần vẫn còn quá nhỏ đối với tôi.
Vì vậy, câu hỏi của tôi dành cho bạn là: làm thế nào tôi có thể triển khai XOR hiệu quả cho các số 32 bit? Nếu điều này là không thể trên máy móc hiện đại và bạn có thể chứng minh nó bằng một số loại calcucation sau đó nó cũng là một câu trả lời tốt đẹp cho câu hỏi của tôi. Cuối cùng, làm cách nào để tôi có thể cải thiện mã của mình tốt nhất? Có lẽ bạn có một số ý tưởng làm thế nào để đối phó với các con số mà không vi phạm chúng ngoài hoặc làm thế nào để XOR số theo cách khác?
Thông tin bổ sung: Nếu bạn thử mã của tôi để đoán hai từ ba đối số hoặc XOR, thì có khả năng tự do trao đổi đối số của hàm đó (xuất phát từ các thuộc tính toán học). dưới dạng biến số ràng buộc và B
và AxorB
là không bị ràng buộc. CLPFD dường như hoạt động nhanh nhất theo cách đó. Ngoài ra, chiến lược ghi nhãn tốt nhất sẽ là labeling([bisect], [B,AxorB]
.
Nghiên cứu nguồn: Có hướng dẫn cách tạo các tiện ích mở rộng như vậy một cách hiệu quả. – false