Voglio generare numeri casuali secondo alcune distribuzioni. Come posso fare questo?Genera numeri casuali in base alle distribuzioni
risposta
Il generatore di numeri casuali standard che hai ottenuto (rand()
in C dopo una semplice trasformazione, equivalenti in molte lingue) è un'approssimazione abbastanza buona a una distribuzione uniforme nell'intervallo [0,1]. Se è quello di cui hai bisogno, hai finito. È anche banale convertirlo in un numero casuale generato su un intervallo intero leggermente più ampio.
La conversione di una distribuzione uniforme in una distribuzione normale ha already been covered on SO, così come è andata allo Exponential distribution.
[EDIT]: Per il triangular distribution, la conversione di una variabile uniforme è relativamente semplice (in qualcosa di simile al C):
double triangular(double a,double b,double c) {
double U = rand()/(double) RAND_MAX;
double F = (c - a)/(b - a);
if (U <= F)
return a + sqrt(U * (b - a) * (c - a));
else
return b - sqrt((1 - U) * (b - a) * (b - c));
}
questo è solo la conversione della formula data sulla pagina di Wikipedia. Se vuoi gli altri, questo è il posto dove iniziare a cercare; in generale, si utilizza la variabile uniforme per selezionare un punto sull'asse verticale del cumulative density function della distribuzione desiderata (supponendo che sia continuo) e invertire il CDF per ottenere il valore casuale con la distribuzione desiderata.
no ho solo bisogno di avere alcuni numeri che sono in esponenziale, normale, triangolare ... ecc.? L'analizzatore di ingresso Rockwell Arena esegue questa operazione ma non so come usarlo? –
+1 Apprezzo questo pseudocodice C, perché stavo guardando l'articolo di wikipedia sulla distribuzione triangolare e non riuscivo a capire come trasformarlo in codice. Una correzione: rand() restituisce un numero intero da 0 a RAND_MAX, quindi penso che tu voglia 'U = ((double) rand())/RAND_MAX'. Altrimenti, il tuo sqrt ((1 - U) ...) uscirà immaginario. – LarsH
@LarsH: Accidenti! Hai dimenticato che C è strano in questo modo. Grazie per la correzione. –
In realtà dipende dalla distribuzione. Il modo più generale è il seguente. Sia P (X) la probabilità che il numero casuale generato in base alla tua distribuzione sia inferiore a X.
Si inizia con la generazione di X casuali uniformi tra zero e uno. Dopo di che trovi Y tale che P (Y) = X e l'uscita Y. Potresti trovare tale Y usando la ricerca binaria (poiché P (X) è una funzione crescente di X).
Questo non è molto efficiente, ma funziona per le distribuzioni in cui P (X) potrebbe essere calcolato in modo efficiente.
È possibile cercare metodo dell'inversione, il rifiuto di campionamento così come il libro di Devroye "Nonuniform random variate generation"/Springer Verlag 1986
Il modo giusto per farlo è quello di scomporre la distribuzione in n-1 distribuzioni binarie. Cioè se si dispone di una distribuzione come questo:
A: 0.05
B: 0.10
C: 0.10
D: 0.20
E: 0.55
È trasformarlo in 4 distribuzioni binarie:
1. A/E: 0.20/0.80
2. B/E: 0.40/0.60
3. C/E: 0.40/0.60
4. D/E: 0.80/0.20
Selezionare uniformemente dalle distribuzioni n-1, e quindi selezionare il primo o il secondo simbolo base sulla probabilità se ciascuno nella distribuzione binaria.
Si presume che la distribuzione sia discreta. – pjs
I am am - che è il caso tipico nella programmazione (ad esempio tabelle di transizione di probabilità, modelli di markov nascosti ecc.). Ma se noti che il metodo è * tempo costante *. Ciò significa che non vi è alcuna penalità sulle prestazioni in termini di tempo per la generazione di enormi distribuzioni. Quindi, per una distribuzione continua, è possibile discrimizzarla in tutti i contenitori necessari per ottenere un'approssimazione sufficientemente buona e utilizzare il mio metodo. –
I RV discreti possono essere più comuni nel tipo di programmazione che si fa, ma molti di noi hanno bisogno di distribuzioni gaussiane, esponenziali, triangolari, log-normali, beta, gamma, Weibull, ecc. Ecc. Per il nostro lavoro. Anche con distribuzioni discrete non funzionano per intervalli infiniti (Poisson, geometrico). Le tabelle alias generano valori in tempo costante, ma anche la maggior parte delle inversioni o composizioni continue. Nel frattempo, l'approssimazione delle distribuzioni continue con le tabelle richiede un'impostazione e una memorizzazione massicce non necessari per approcci computazionali. Le tabelle alias sono adorabili quando applicabili, ma non sono una soluzione generale. – pjs
È possibile convertire da bidoni discreti per galleggiare/doppia con interpolazione. Semplice lineare funziona bene. Se la memoria della tabella è vincolata, è possibile utilizzare altri metodi di interpolazione. -jlp
Mettendo da parte il fatto che i computer generano solo numeri pseudo casuali, sicuramente se sono generati da una distribuzione nota, non sono affatto casuali. Per quali distribuzioni stai cercando di generare dati di esempio? – Lazarus
Il modo più semplice è trovare una libreria che faccia questo. Hai in mente qualche lingua particolare? –
Se usi Java, puoi provare la libreria [Uncommons Maths di Dan Dyer] (http://maths.uncommons.org/) (* nota il commento precedente *) che fornisce generatori di numeri casuali, distribuzioni di probabilità, combinatori e statistiche . – hengxin