Cerco di implementare l'esclusivo esclusivo o XOR in Prolog CLPFD. Questo dovrebbe essere predicato semplice come:Implementazione della funzione XOR con Prolog CLPFD per numeri a 32 bit
xor(A, B, AxorB).
A
, B
, AxorB
sono numeri naturali (con 0) e AxorB
è il risultato di A
xorB
.
Il mio problema principale è l'efficienza. In primo luogo, non sono stato in grado di trovare un modo per XOR due numeri senza infrangere quei numeri in parti separate che potrebbero essere ulteriormente elaborati/vincolati, e il processo di rottura di quei numeri (creando vincoli appropriati e poi risolvendoli) sta prendendo un po 'di elaborazione tempo. In secondo luogo, non sono in grado di trovare un modo efficace per "simulare" le funzioni XOR su numeri naturali diversi da quelli presentati nel secondo codice qui sotto.
Iniziamo dal mio primo codice. Ciò è possibile la più semplice attuazione XOR e funziona solo per valori 1 bit (0 e 1):
xor_1bit_values(A, B, AxorB) :-
AxorB #= (A + B) mod 2.
utilizzarlo per numeri maggiori di 1, numeri devono essere suddivisi in 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).
di ingresso del campione e l'uscita:
?- time(xor_number(123456789, 987654321, R, 32)).
% 943 inferences, 0.000 CPU in 0.001 seconds (0% CPU, Infinite Lips)
R = 1032168868
Ora, questo è troppo lento per i miei scopi, come nel mio codice che ho a volte hanno bisogno di indovinare A
e B
quando ho 0.123.dove tutti questi dovrebbero essere numeri a 32 bit. E per i numeri che richiedono più di 10 bit, ciò si traduce in milioni di inferenze letterali che sembrano aumentare espotenzialmente. E io uso le migliori strategie di etichettatura, lo scambio degli argomenti XOR e altri trucchi per accelerare i calcoli.
Quindi, ho provato a fare alcuni calcoli matematici. Quello che ho ideato è la funzione XOR per i valori 2-bit (0, 1, 2, 3):
xor_2bit_values(A, B, Result) :-
Result #= ((A + B*((-1)^A)) mod 4).
di usarlo in numero maggiore di 3 c'è un codice simile a quello che ho presentato prima:
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).
Sembra funzionare quasi il 50% più veloce del primo codice. Ma ancora, la doppia differenza è ancora troppo piccola per me.
Quindi, la mia domanda per voi è questa: come posso implementare XOR efficiente per i numeri a 32 bit? Se questo non è possibile su macchine moderne e puoi provarlo con una sorta di calcolo allora è anche una bella risposta alla mia domanda. Alla fine, come posso migliorare al meglio il mio codice? Forse hai qualche idea su come gestire i numeri senza dividerli o come fare i numeri XOR in altro modo?
Ulteriori informazioni: Se succede a voi di provare il mio codice di indovinare due da tre argomenti o XOR, poi a causa della possibilità di scambiare liberamente argomenti di che le funzioni (che proviene dalle sue proprietà matematiche) vi consiglio di impostare A
come variabile associata e B
e AxorB
come non associati. CLPFD sembra funzionare più velocemente in questo modo. Inoltre, la migliore strategia di etichettatura sarebbe labeling([bisect], [B,AxorB]
.
Studiare la fonte: ci sono istruzioni su come rendere tali estensioni in modo efficiente. – false