Il campionamento del rifiuto è l'unico modo per ottenere una distribuzione veramente uniforme di numeri casuali?


21

Supponiamo di avere un generatore casuale che emetta numeri nell'intervallo [0..R1] con distribuzione uniforme e che dobbiamo generare numeri casuali nell'intervallo [0..N1] con distribuzione uniforme.

Supponiamo che N<R e N non dividano uniformemente R ; per ottenere una distribuzione davvero uniforme possiamo usare il metodo di campionamento del rifiuto :

  • se k è il numero intero più grande tale che kN<R
  • scegli un numero casuale r in [0..R1]
  • se r<kN quindi genera , altrimenti continua a provare con altri numeri casuali r ', r ", ... fino a quando la condizione non viene soddisfattarmodN
Il campionamento del rifiuto è l'unico modo per ottenere una distribuzione discreta veramente uniforme?

Se la risposta è sì, perché?

Nota: se l'idea è la stessa: genera un numero casuale in [0..R ^ m-1], R ^ m> = N , ad esempio r' = R (... R (R r_1 + r_2) ...) + r_m dove r_i è un numero casuale nell'intervallo [0..R-1]N>Rr[0..Rm1],Rm>=Nr=R(...R(Rr1+r2)...)+rmri[0..R1]


Risposte:


13

Sì e no, a seconda di cosa intendi con "l'unico modo". Sì, in quanto non esiste un metodo che è garantito per terminare, il meglio che puoi fare (per i valori generici di e ) è un algoritmo che termina con probabilità 1. No, in quanto puoi rendere i "rifiuti" piccoli come desidera.RNR

Perché la risoluzione garantita è impossibile in generale

Supponiamo di avere un motore di calcolo deterministico (una macchina di Turing o qualunque cosa galleggi la tua barca), oltre a un oracolo che genera elementi casuali del set di elementi . Il tuo obiettivo è generare un elemento del set -element . L'output del tuo motore dipende solo dalla sequenza di valori restituiti dall'oracolo; è una funzione di quella sequenza potenzialmente infinita .[ 0 .. R - 1 ] N [ 0 , N - 1 ] f ( r 0 , r 1 , r 2 , ... )R[0..R1]N[0,N1]f(r0,r1,r2,)

Supponiamo che il tuo motore chiami l'oracolo al massimo volte. Potrebbero esserci tracce per le quali l'oracolo viene chiamato meno di volte; in tal caso, chiamare i tempi supplementari dell'oracolo in modo che sia sempre chiamato esattamente volte non modifica l'output. Quindi, senza perdita di generalità, assumiamo che l'oracolo sia chiamato esattamente volte. Quindi la probabilità del risultato è il numero di sequenze tale che . Poiché l'oracolo è un generatore casuale uniforme, ogni sequenza è equiprobabile e ha probabilità . Quindi la probabilità di ogni risultato è della formam m m x ( r 0 , , r m - 1 ) f ( r 0 , , r m - 1 ) = x 1 / R m A / R m A 0 R mmmmmx(r0,,rm1)f(r0,,rm1)=x1/RmA/Rmdove è un numero intero compreso tra e .A0Rm

Se divide per alcuni , puoi generare una distribuzione uniforme su elementi chiamando il generatore casuale volte (questo viene lasciato come esercizio al lettore). Altrimenti, questo è impossibile: non c'è modo per ottenere un risultato con probabilità . Nota che la condizione equivale a dire che tutti i fattori primi di sono anche fattori di (questo è più permissivo di quello che hai scritto nella tua domanda; ad esempio puoi scegliere un elemento casuale tra 4 con una fiera a 6 facce muori, anche se 4 non divide 6).R m m N m 1 / N N RNRmmNm1/NNR

Ridurre gli sprechi

Nella tua strategia, quando , non devi ridisegnare immediatamente. Intuitivamente, c'è ancora un po 'di entropia in che puoi tenere nel mix.[ krkN[kN..R1]

Si supponga per un momento che si continui in realtà la generazione di numeri casuali sotto per sempre, e si genera di loro alla volta, rendendo disegna. Se un semplice campionamento del rifiuto su questa generazione raggruppata, lo spreco su è , ovvero il resto diviso per il numero di pareggi. Questo può essere piccolo quanto . Quando e sono coprimi, è possibile rendere i rifiuti arbitrariamente piccoli selezionando valori sufficientemente grandi di . Per i valori generali di eu d d R d - kNudd RdmodNugcd(R,N)RNdRNgcd(R,N)N/gcd(R,N)RdkNudRdmodNugcd(R,N)RNdRN, il calcolo è più complicato perché è necessario tenere conto della generazione di e separatamente, ma ancora una volta è possibile rendere i rifiuti arbitrariamente piccoli con gruppi abbastanza grandi.gcd(R,N)N/gcd(R,N)

In pratica, anche con numeri casuali relativamente inefficienti (ad esempio nella crittografia), raramente vale la pena fare qualsiasi cosa tranne un semplice campionamento del rifiuto, a meno che sia piccolo. Ad esempio, nella crittografia, dove è in genere una potenza di 2 e genere centinaia o migliaia di bit, la generazione di numeri casuali uniformi di solito procede mediante campionamento di rifiuto diretto nell'intervallo desiderato.R NNRN


La prima prova è imperfetta: l'esistenza di è troppo forte. Possiamo avere una macchina che consuma arbitrariamente molti elementi, ma termina sempre . Fondamentalmente, vogliamo escludere una sequenza (quella che non si interrompe mai) ma ne escludiamo tutte tranne finitamente molte. m
Raffaello

@Raphael Non sono sicuro di aver capito cosa intendi. Puoi fare un esempio di tale macchina?
Gilles 'SO- smetti di essere malvagio' il

Ah, la mia preoccupazione era troppo generale. Qui - data l'assenza di input - hai ragione. Se tutti i calcoli terminano, ce ne sono finitamente molti (nessun input, numero finito di decisioni per passo, ergo un albero finito), quindi c'è un più lungo che ti dà . m
Raffaello

@Raphael Il tuo commento mi fa pensare a una presentazione migliore per un pubblico TCS: rendere l'RNG l'input di una TM anziché un oracolo. Partiamo dal presupposto che la TM termina (altrimenti l'algoritmo non è corretto). Se esiste una tale che qualunque sia l'input, la TM osserva al massimo celle di input, quindi <blah blah divisibile per blah non può avere esiti equiprobabili>. Altrimenti, per tutti , la probabilità di richiedere almeno pareggi è almeno . m R m N m m R - mmmRmNmmRm
Gilles 'SO- smetti di essere malvagio' il

1
@Raphael: il lemma di König mostra che se la macchina termina sempre, allora c'è effettivamente un limite superiore nel suo tempo di esecuzione. Funziona finché il set di output dell'RNG è finito (e altrimenti è banalmente falso).
Yuval Filmus,

6

Il teorema del codice sorgente di Shannon mostra che, in un certo senso, hai bisogno di campioni (in media) del tipo per generare un numero casuale del tipo . Più precisamente, Shannon fornisce un algoritmo (inefficiente) che fornisce campioni del primo tipo, genera campioni del secondo tipo, con alta probabilità. Mostra anche che è impossibile produrre con alta probabilità.[ 0 , , R - 1 ] [ 0 , , N - 1 ] m m ( log N / log R - ϵ ) m ( log N / log R + ϵ )logN/logR[0,,R1][0,,N1]mm(logN/logRϵ)m(logN/logR+ϵ)

Il teorema di Shannon funziona anche nel caso più generale di una distribuzione di input distorta (e probabilmente anche di una distribuzione di output distorta). In tal caso, è necessario sostituire il logaritmo con l'entropia. Mentre l'algoritmo fornito dal teorema è definito in modo casuale, in alcuni casi è possibile derandomizzarlo (a costo di prestazioni leggermente peggiori).


5

In realtà, no, il campionamento del rifiuto è tutt'altro che l'unico modo di procedere. Sfortunatamente, considerando che i computer memorizzano tutte le informazioni come bit, e quindi possono solo manipolare bit di informazioni casuali, qualsiasi algoritmo per disegnare una variabile casuale uniforme dell'intervallo sarà infinito, se lo sviluppo della base binaria di è infinito.NNN

Questo teorema è un risultato classico di Knuth e Yao (1976), che hanno sviluppato la struttura degli alberi DDG (distribuzione discreta che genera alberi).

I metodi esposti da Gilles sono il tipico tipo di cose che sono state fatte per mitigare i rifiuti sostenuti dal rifiuto, ma ovviamente se uno può generare seguendo gli alberi di Knuth e Yao è molto, molto più efficiente - in media il 96% di bit casuali sono salvati.

Ho fornito maggiori informazioni al riguardo nel seguente post di CStheory .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.