Come simulare un dado dato una moneta giusta


21

Supponiamo che ti venga data una moneta equa e che desideri simulare la distribuzione della probabilità di lanciare ripetutamente un dado (a sei facce). La mia idea iniziale è che dobbiamo scegliere interi appropriati k,m , in modo tale che 2k=6m . Quindi, dopo aver lanciato la moneta k volte, mappiamo il numero codificato dalla stringa di lunghezza k sulle uscite del dado dividendo l'intervallo [0,2k1] in 6 intervalli ciascuno della lunghezza m . Tuttavia, ciò non è possibile, poiché 2k ha due come unico fattore primo ma fattori primi di6m includono tre. Dovrebbe esserci un altro modo semplice per farlo, giusto?


Vedi questa domanda in cui il problema viene affrontato in modo più generale.
Raffaello

Ecco un articolo sull'argomento . Spiega come utilizzare il campionamento del rifiuto e come riutilizzare i bit "sprecati" per accelerare ulteriori rotoli.
ZeroUltimax,

Risposte:


12

Per avere un metodo leggermente più efficiente di quello indicato da @FrankW ma usando la stessa idea, puoi lanciare la tua moneta volte per ottenere un numero inferiore a 2 n . Quindi interpretalo come un lotto di m die flip, dove m è il numero più grande in modo che 6 m < 2 n (come già detto, l'uguaglianza non vale mai qui). Se ottieni un numero maggiore o uguale a 6 m , devi rifiutare il valore e ripetere tutte le n lanci.n2nmm6m<2n6mn

È possibile implementare una funzione che restituisce un singolo lancio di dadi effettuando lanci di monete e quindi memorizzando nella cache il risultato per le seguenti richieste di lancio di dadi m - 1 .nm1

Il punto interessante è che alcuni valori di sono migliori di altri perché hanno un tasso di rifiuto inferiore. Ecco un elenco di buoni valori (ovvero valori che hanno un tasso di rifiuto inferiore rispetto ai precedenti):n

n m r
3 1 0.25
8 3 0.15625
13 5 0.05078125
44 17 0.0378308072686
75 29 0.0247036782182
106 41 0.0113974522704
243 94 0.00933096248381
380 147 0.00726015308463
517 200 0.00518501504347
654 253 0.00310553931213
791 306 0.00102171682348

ottenuto con le formule: .

m=nlog32r=13m2n

La prima riga corrisponde alla risposta di @FrankW con un tasso di rifiuto del 25%. I seguenti numeri sono utili: e n = 13 possono entrambi essere mantenuti in una singola variabile statica intera. In particolare il tasso di rifiuto di n = 13 è solo del 5%, il che rappresenta un sensibile miglioramento rispetto al 25% e lo rende un buon candidato per una possibile implementazione.n=8n=13n=13


Non hai bisogno di 6 ^ m, 6 * m è sufficiente. Quindi potresti usare 5 tiri per ottenere un numero di 5 bit che rifiuta solo 1/16 di casi.
Taemyr,

Il tasso di rifiuto del 5% per 13 tiri è orribile, rispetto al 25% per 3 tiri. Perché il 25% per 3 lanci rifiuta solo 4 volte (cioè spende più di 12 tiri) nello 0,390625% dei casi.
Taemyr,

@Taemyr un numero a 5 bit può rappresentare 32 valori diversi che ti consentono di rappresentare un singolo dado (perché due dadi hanno 36 possibilità). Quindi sono accettabili solo valori 6/32 con un tasso di rifiuto di 27/32 = 84%
Emanuele Paolini,

@Taemyr: un tasso di scarto di su n lanci significa che, in media, ogni lotto di n lanci viene respinto con probabilità r . Quindi, in media, ogni lancio viene rifiutato con la stessa velocità r (non dipendente da n ). rnnrrn
Emanuele Paolini,

Sì. E usando il metodo di FrankW che ha un tasso di rifiuto del 25% per un lotto di 3 lanci, avrai una probabilità di 1-0,00390625 di accettare entro il 4 ° lotto.
Taemyr,

29

Quello che puoi fare è utilizzare un metodo chiamato campionamento del rifiuto :

  • Lancia la moneta 3 volte e interpreta ogni lancio come un po '(0 o 1).
  • Concatena i 3 bit, fornendo un numero binario in .[0,7]
  • Se il numero è presente , prendilo come un tiro di dado.[1,6]
  • Altrimenti, cioè se il risultato è o 7 , ripetere i lanci.07

Dal dei possibili risultati portano alla conclusione in ogni serie, la probabilità di aver bisogno di più di1serie di lanci per ottenere un tiro di dado è68l . Quindi, questo metodo è efficace nella pratica.(168)l=14l

miglioramenti:

@La risposta di Angel sottolinea che il numero di gettoni in ogni set, ma il primo può essere ridotto da 3 a 2, usando la distinzione tra 0 e come primo bit per il set successivo.7

@Emanuele Paolini spiega, come è possibile ridurre il numero di rilanci, se sono necessari più tiri di dado.


Questo metodo non darebbe una maggiore tendenza centrale rispetto a un vero d6?
Red_Shadow il

3
@Red_Shadow No. Si noti che non si aggiungono i lanci di moneta (tre non sarebbe sufficiente, allora), ma a prendervi ogni bit in un -bit numero binario da medaglia. Quindi, campionate uniformemente da [ 0..2 k - 1 ] e rifiutate i numeri non dall'intervallo target; questo può solo produrre una distribuzione uniforme sull'intervallo target. k[0..2k1]
Raffaello

Se sei furbo con l'intervallo rifiutato, in questo caso è davvero facile usarlo per ridurre il numero di lanci di monete necessari nel caso di rifiuto.
Mooing Duck,

@MooingDuck puoi decidere se scartare il tuo risultato dopo 2 lanci: se è 0,0 0,1 o 1,0, lancia di nuovo per l'ultimo bit altrimenti ricomincia da capo
maniaco del cricchetto

1
@NikosM. La probabilità di prendere più tempo di passi sta diminuendo verso lo zero in modo esponenziale, tuttavia, quindi la risposta non fa affermazioni sbagliate: è efficace nella pratica e di fatto ampiamente utilizzata. (Per distribuzioni più complicate, è spesso l'unico metodo noto. A tutti.)k
Raffaello

7

Un'alternativa al campionamento del rifiuto (come descritto nella risposta di FrankW ) consiste nell'utilizzare un algoritmo di ridimensionamento, che tiene conto di una risposta di [7,8] come se si trattasse di un'altra gettoniera.

C'è una spiegazione molto dettagliata su mathforum.org , incluso l'algoritmo ( NextBit()sarebbe lanciare la tua moneta giusta).

Il caso del lancio di un dado con una moneta giusta (campionamento 2 → 6) è più semplice dell'algoritmo generico. Prendi semplicemente un fallimento (7 o 8) come un altro input di monete ed esegui altri due lanci.


2

Un altro approccio per simulare un tiro di un dN usando un dM (nel caso della domanda specifica posta un d6 usando un d2) è quello di suddividere l'intervallo [0, 1) in N intervalli uguali di lunghezza 1 / N, [0, 1 / N), [1 / N, 2 / N), ..., [(N-1) / N, N).

Utilizzare dM per generare una frazione M di base, 0.bbbb ..., in [0, 1). Se questo rientra in [(i-1) / N, i / N), prendi i come il tiro di dN. Nota che devi solo generare abbastanza cifre base-M della frazione per determinare in quale intervallo si trova.


La condizione di terminazione deve essere resa più precisa. Se lancio la moneta una volta finisco con la frazione binaria 0,0 o 0,1 (cioè ½), che rientrano entrambi in un intervallo (corrispondente rispettivamente a 0 e 3, in questo caso). Devi considerare la frazione generata come un intervallo e ti fermi quando l'intero intervallo è all'interno di un singolo intervallo. Sono sicuro che è quello che intendevi, ma non credo sia chiaro.
rici,

1

Una spiegazione forse più semplice di un migliore campionamento del rifiuto.

Sto dando questa spiegazione in quanto si spera possa aiutare a semplificare la comprensione o l'analisi delle probabilità in alcune situazioni.

FrankW suggerisce di utilizzare il campionamento del rifiuto, di lanciare la moneta tre volte, di mantenere il risultato se si trova nel range giusto o di ripetere le tre lancette altrimenti, fino al successo.

Suggerisce Angel di salvare un capovolgimento su ogni prova, sostituendolo con una scelta binaria rimasta dai due valori inutilizzati del precedente set di tre.

Ciò significa che è stato prodotto un po 'di informazione con i primi tre lanci, che non è stato necessario produrre. Più precisamente, dovresti lanciare la moneta solo due volte per sapere se l'attuale serie di lanci avrà successo.

Sapere se la serie corrente di vibrazione avrà successo è l'unica probabilità che conta , poiché l'interpretazione di una serie riuscita di vibrazione è indipendente dalla probabilità. E questo può essere noto prima che tutti i lanci siano completati per quel set.

Ciò può essere ottenuto in almeno due modi, o più precisamente in due diverse interpretazioni dei flip. Potrebbero essercene altri.

Il raggruppamento risulta in coppie

L'idea è di prendere in considerazione solo tre valori (1,2), (3,4) e (5,6) rappresentati da tre configurazioni a doppio flip, ad esempio TT, TH, HT. Quindi, è possibile applicare il campionamento del rifiuto con double-flip, ripetendo ogni volta che si ottiene la configurazione dell'errore HH.

Una volta ottenuta una delle tre configurazioni riuscite, basta lanciare ancora una volta la moneta per decidere se prendere il primo o il secondo valore della coppia corrispondente.

Rilevamento tempestivo di guasti al set di fogli mobili

L'idea è di usare una lettura leggermente diversa della configurazione a tre lanci. Se Head e Tail sono interpretati come 1 e 0, una configurazione dovrebbe corrispondere all'interpretazione binaria più una. Questo è TTT (cioè 000) corrisponde a 1, HTH (ovvero 101) corrisponde a 6, HHT (ovvero 110) e HHH (ovvero 111) corrisponde a 7 e 8, o qualsiasi cosa al di fuori [1,6].

Quindi sappiamo che il flip-set sta funzionando o fallendo solo con i primi due lanci. Se producono HH, il flip set fallisce indipendentemente dall'ultimo flip. Quindi può essere saltato.

Penso che il rilevamento precoce possa sempre essere usato come una spiegazione, ma a seconda del numero di facce sui dadi simulati, il rilevamento dei guasti può avvenire dopo un numero variabile di lanci.

Ad esempio, per un dado a 10 facce è necessario in linea di principio un set di 4 lanci, con 6 configurazioni corrispondenti al fallimento. Il trucco è avere tutte le configurazioni di errore nella parte alta della sequenza di valori binari come segue:

TTTT  0000   1
HTTT  1000   9
HTTH  1001  10
HTHT  1001  11
HTHH  1011  12
HHTT  1100  13
HHHH  1111  16

Le configurazioni riuscite corrispondono all'intervallo [1, 10] e gli errori all'intervallo [11,16].

Quindi fallisci quando i primi due lanci danno HH, o quando i primi tre danno HTH, senza dover nemmeno provare i lanci mancanti del set.

Se non fallisci, devi semplicemente terminare il set di lanci.


1

Ci sono due approcci ben noti a questo. Uno è "campionamento di rifiuto". Ad esempio, utilizzare tre bit per selezionare uno dei sei valori, riprovando per i due campioni aggiuntivi. Oppure usa 14 bit (8192 valori) per selezionare 5 valori da 1 a 6 (7776 possibilità), riprovando in 13 casi su 256.

L'altro sta usando la parte di decompressione di un algoritmo di compressione / decompressione: con la codifica aritmetica, una sequenza di valori casuali da 1 a 6 può essere compressa senza quasi ridondanza. Genera la sequenza compressa in modo casuale e decomprimila. Questo è molto più complicato, ma praticamente non richiederà alcun numero casuale aggiuntivo.


0

Scusate in anticipo se la spiegazione è superflua. Non ero sicuro di quanti dettagli approfondire o di quanto fosse facile comprendere il concetto.

Supponi di avere tre monete (monete giuste). Se assegni in modo incrementale un valore a ciascun lato di ogni moneta, avrai sei valori.

In questo modo: sulla prima moneta, la testa è 1 e la coda è 2. Sulla seconda moneta, la testa è 3 e la coda è 4. Sulla terza moneta, la testa è 5 e la coda è 6.

Lanciare le monete ti lascerà con un set di tre numeri, il tuo set corrente. Ora, il tuo set corrente diventerà il tuo set precedente e ripeterai il processo per ottenere un nuovo set di tre numeri.

Continua a farlo fino a quando uno e un solo numero corrispondono dal tuo set attuale a quello precedente. Questo è il tuo numero.

Quindi se avessi [teste, code, teste] per il set corrente, sarebbe [1, 4, 5]. Ora li capovolgi di nuovo e il tuo set attuale è [2, 4, 5]. Due partite. Non buono. Ritenta. Ottieni [2, 3, 6]. Solo una partita. Il tuo numero è due.

Ci sarà la stessa possibilità che appaia un dato numero, ma non è particolarmente conveniente, dato che c'è solo una modifica di 3/32 che una data coppia di set avrà successo (solo una partita). Quindi, in media, l'algoritmo dovrebbe ripetere circa dieci volte. Inoltre, non è facilmente generalizzabile per i dadi dispari.

Per lo meno, forse è cibo per la riflessione. Domanda molto interessante.


4
Questo funzionerà sempre in modo massiccio, enormemente peggiore del campionamento del rifiuto. Per il campionamento del rifiuto, devi solo capovolgerelogn monete per simulare un nda un lato muore e ogni serie di lanci riesce con probabilità strettamente maggiore di 12. Il metodo che stai proponendo richiede di capovolgeren2 le monete e ogni serie di lanci hanno successo solo con probabilità n/2n.
David Richerby,

0

Girerei la moneta tre volte e interpreterei il risultato come un numero binario, respingendo i risultati fuori portata.

Ad esempio, lascia che head sia 1 e che code 0. Se lo avessi girato tre volte e avessi head, code, head, avresti 101 binari, che è 5 in decimale. HHT = 110b = 6. TTT = 000b = 0 e HHH = 111b = 7, entrambi i quali non rientrano nell'intervallo e verrebbero rifiutati e si ricercherebbe per tutte le cifre.


1
Questa è solo la risposta di Frank.
Raffaello

2
@Raphael In realtà, un sottoinsieme rigoroso della risposta di Frank , poiché Frank si rivolge al tempo di esecuzione previsto.
David Richerby,

0

Sfortunatamente non si può (fedelmente) simulare un dado (giusto) usando (sequenze di) monete giuste.

Semplicemente perché lo spazio degli eventi di un dado ha una dimensionalità di 6 e questo non può essere esattamente eguagliato da un potere di 2 (che è ciò che fornisce lo spazio eventi di una moneta equa).

Ma si può fare questo con una giusta "tri-coin" (se si può usare un termine del genere). Significa una moneta con 3 risultati. E una semplice 2 monete, quindi lo spazio congiunto di queste 2 monete corrisponde esattamente allo spazio degli eventi del dado.

Il campionamento del rifiuto (come indicato in alcune risposte) può effettivamente fornire una simulazione approssimativa . Ma avrà ancora una quantità di errore o errata corrispondenza delle probabilità (a tempo finito). Quindi, se si desidera effettivamente abbinare gli spazi degli eventi di questi 2 sistemi, ci saranno casi in cui non funzionerà.

Nella simulazione probabilistica (di cui un campione di rifiuto è un esempio), le sequenze tipiche generate mostrano effettivamente le probabilità elementari relative (in questo caso lo spazio degli eventi di un dado). Tuttavia (come menzionato nei commenti) ciascuna di queste sequenze tipiche può contenere sottosequenze arbitrariamente lunghe con esattamente gli stessi risultati. Ciò significa che per utilizzare il campionamento del rifiuto (in alcuni casi) o può richiedere arbitrariamente tempo o la distribuzione generata sarà distorta (cioè non è accettabile), a causa della sovrarappresentazione o sottorappresentazione di alcune parti del suo spazio eventi . in caso contrario, sarebbe possibile un algoritmo deterministico che corrisponda esattamente agli spazi degli eventi di un dado e una moneta (che non corrispondono per dimensionalità).


I commenti non sono per una discussione estesa; questa conversazione è stata spostata in chat .
Gilles 'SO- smetti di essere malvagio' il

@Gilles, peccato che il voto negativo sia ancora qui, nonostante tutte le spiegazioni e le chat (per quanto riguarda la correttezza) che sono andate avanti: p
Nikos M.
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.