La procedura a produce an unbiased coin from a biased one è stata attribuita per la prima volta a Von Neumann (un ragazzo che ha svolto un lavoro enorme in matematica e in molti campi correlati). La procedura è semplice super:
- lanciare la moneta due volte.
- Se i risultati corrispondono, ricomincia, dimenticando entrambi i risultati.
- Se i risultati sono diversi, utilizzare il primo risultato, dimenticando il secondo.
Il motivo per cui questo algoritmo funziona è perché la probabilità di ottenere HT è p(1-p)
, che è lo stesso di ottenere TH (1-p)p
. Quindi due eventi sono ugualmente probabili.
Sto anche leggendo questo libro e si chiede il tempo di esecuzione previsto. La probabilità che due lanci non siano uguali è z = 2*p*(1-p)
, pertanto il tempo di esecuzione previsto è 1/z
.
L'esempio precedente sembra incoraggiante (dopo tutto, se si dispone di una moneta sbilanciata con un bias di p=0.99
, è necessario gettare la vostra moneta di circa 50 volte, che non è che molti). Quindi potresti pensare che questo sia un algoritmo ottimale. Purtroppo non lo è.
Ecco come si confronta con lo Shannon's theoretical bound (l'immagine è presa da questo answer). Mostra che l'algoritmo è buono, ma tutt'altro che ottimale.
Si può venire con un miglioramento se si considera che HHTT sarà scartato da questo algoritmo, ma in realtà ha la stessa probabilità di TTHH. Quindi puoi anche fermarti qui e restituire H. Lo stesso è con HHHTTTT e così via. L'utilizzo di questi casi migliora il tempo di esecuzione previsto, ma non lo rende teoricamente ottimale.
E alla fine - codice Python:
import random
def biased(p):
# create a biased coin
return 1 if random.random() < p else 0
def unbiased_from_biased(p):
n1, n2 = biased(p), biased(p)
while n1 == n2:
n1, n2 = biased(p), biased(p)
return n1
p = random.random()
print p
tosses = [unbiased_from_biased(p) for i in xrange(1000)]
n_1 = sum(tosses)
n_2 = len(tosses) - n_1
print n_1, n_2
è abbastanza auto-esplicativo, e qui è un risultato ad esempio:
0.0973181652114
505 495
Come si vede, comunque abbiamo avuto una polarizzazione di 0.097
, abbiamo ottenuto circa lo stesso numero di 1
e 0
Direi che la risposta ha a che fare con l'uso del generatore polarizzato una volta in modo standard e una volta come una funzione inversa in modo che tu abbia la probabilità di una 0 una volta e una (1-p) probabilità di uno 0 la seconda iterazione e mix i due risultati per bilanciare la distribuzione. Tuttavia non conosco la matematica esatta che c'è dietro. –
Eric-si, se hai fatto (rand() + (1-rand()))/2, potresti ragionevolmente aspettarti di ottenere un risultato imparziale. Nota che in precedenza dovresti chiamare rand() due volte, altrimenti ottieni sempre.5 – JohnE
@JohnE: Essenzialmente questo è quello che stavo pensando, ma questo non ti lascia uno 0 o 1 dritto, che è richiesto. Penso che pau abbia colpito il chiodo in testa con la sua risposta. –