Você tem uma moeda. Você pode girá-lo quantas vezes quiser.
Você deseja gerar um número aleatório tal que onde .a ≤ r < b r , a , b ∈ Z +
A distribuição dos números deve ser uniforme.
É fácil se :
r = a + binary2dec(flip n times write 0 for heads and 1 for tails)
E se ?
algorithms
probability-theory
randomness
random-number-generator
Pratik Deoghare
fonte
fonte
Respostas:
O que você procura é baseado na amostragem de rejeição ou no método de aceitação / rejeição (observe que a página da Wiki é um pouco técnica).
Esse método é útil nesses tipos de situações: você deseja escolher algum objeto aleatório de um conjunto (um número inteiro aleatório no conjunto no seu caso), mas não sabe como fazer isso, mas pode escolher algum objeto aleatório de um conjunto maior contendo o primeiro conjunto (no seu caso, [ a , 2 k + a ] para alguns k, de modo que 2 k + a ≥ b ; isso corresponde a k lançamentos de moedas).[a,b] [a,2k+a] k 2k+a≥b k
Nesse cenário, você continua escolhendo elementos do conjunto maior até escolher aleatoriamente um elemento no conjunto menor. Se o seu conjunto menor for grande o suficiente em comparação com o maior (no seu caso, contém no máximo o dobro de números inteiros que [ a , b ] , o que é bom o suficiente), isso é eficiente.[a,2k+a] [a,b]
Um exemplo alternativo: suponha que você queira escolher um ponto aleatório dentro de um círculo com raio 1. Agora, não é realmente fácil criar um método direto para isso. Voltamos ao método de aceitação e rejeição: amostramos pontos em um quadrado 1x1 que abrange o círculo e testamos se o número que desenhamos está dentro do círculo.
fonte
(detalhes técnicos: a resposta se encaixa na seleção do número )a ≤ x < b
Como você pode jogar sua moeda quantas vezes quiser, você pode obter a probabilidade o mais próximo possível de uniformizar escolhendo uma fração (usando o radical binário: você gira o moeda para cada dígito após o ponto) e multiplique r por b - a para obter um número entre 0 e [ba-1] (arredondando para baixo para um número inteiro). Adicionar este número para um e está feito.r ∈ [ 0 , 1 ] r b - a uma
Exemplo : diga . 1/3 em binário é 0,0101010101 .... Então, se seu flip estiver entre 0 e 0,010101 ... sua escolha será b . se estiver entre 0,010101 .. e 0,10101010 ... sua escolha será um + 1 e, caso contrário, será um + 2 .b - a = 3 b a + 1 a + 2
Se você jogar sua moeda vezes, cada número entre a e b será escolhido com probabilidade 1t uma b .1 1b - a± 2- ( t + 1 )
fonte
Escolha um número na próxima potência maior de 2 e descarte respostas maiores que .b - a
fonte
Ninguém mencionou isso, então deixe-me formalmente provar que, se é um domínio cujo tamanho não é uma potência de dois, em seguida, um número finito de jogadas justo moeda não são suficientes para gerar um membro uniformemente aleatória de D . Suponha que você use k moedas para gerar um membro da D . Para cada d ∈ D , a probabilidade de que o seu algoritmo gerado d é da forma A / 2 k para algum número inteiro um . O teorema fundamental da aritmética mostra que A / 2 k ≠ 1 / | D | .D D k D d∈ D d A / 2k UMA A / 2k≠ 1 / | D |
Se você deseja gerar amostras uniformes independentes de D , o número esperado de lançamentos de moedas que você precisa (sob o algoritmo ideal) é aproximadamente n log 2 | D | . De maneira mais geral, se você deseja gerar a partir de uma distribuição de entropia H , precisa de aproximadamente n H bits aleatórios em expectativa. Um algoritmo que consegue isso é a decodificação aritmética, aplicada a uma sequência (aparentemente) infinita de bits aleatórios.n D n log2| D | H n H
fonte
Se ba não for uma potência de 2, talvez você precise jogar muitas moedas para obter um resultado. Você pode até nunca obter um resultado, mas isso é improvável ao extremo.
Métodos
O método mais simples é gerar um número em [a, a + 2 ^ n), onde 2 ^ n> = ba, até que aconteça em [a, b). Você joga fora muita entropia com esse método.
Um método mais caro permite manter toda a entropia, mas se torna muito caro computacionalmente à medida que o número de lançamentos de moedas / dados aumenta. Intuitivamente, é como tratar a moeda virar como os dígitos de um número binário à direita da vírgula decimal, convertendo esse número da base 2 para a base ab depois e retornando os dígitos desse número à medida que ficam "presos".
Exemplo
O código a seguir converte os rolos de uma matriz justa dos lados em rolos de uma matriz justa dos lados (no seu caso n = 2, m = ab), com um custo marginal crescente à medida que o número de análises aumenta. Observe a necessidade de um tipo de número Rational com precisão arbitrária. Uma boa propriedade é que a conversão de frente e verso para frente e verso retornará o fluxo original, embora talvez tenha sido adiado por alguns rolos, devido à inserção de dígitos.
fonte
Gere um decimal binário. Em vez de armazená-lo explicitamente, basta acompanhar os valores mínimo e máximo possíveis. Quando esses valores estiverem dentro do mesmo número inteiro, retorne esse número inteiro. O esboço do código está abaixo.
(Editar) Explicação mais completa: digamos que você queira gerar um número inteiro aleatório de 1 a 3, inclusive com probabilidade de 1/3 cada. Fazemos isso gerando um real decimal binário aleatório, x no intervalo (0, 1). Se x <1/3, retornar 1, senão se x <2/3 retornar 2, senão retornar 3. Em vez de gerar os dígitos para x explicitamente, apenas controlamos os valores mínimos e máximos possíveis de x. Inicialmente, o valor mínimo de x é 0 e o máximo é 1. Se você virar a cabeça primeiro, o primeiro dígito de x atrás do ponto decimal (em binário) é 1. O valor mínimo possível de x (em binário) se torna 0,100000 = 1/2 e o máximo é 0.111111111 = 1. Agora, se o seu próximo flip for coroa, x começa com 0.10. O valor mínimo possível é 0.1000000 = 1/2 e o máximo é 0.1011111 = 3/4. O valor mínimo possível de x é 1/2, para que você saiba lá ' s sem chance de retornar 1, pois isso requer x <1/3. Você ainda pode retornar 2 se x acabar sendo 1/2 <x <2/3 ou 3 se 2/3 <x <3/4. Agora, suponha que o terceiro flip seja coroa. Então x deve começar com 0.100. Min = 0.10000000 = 1/2 e max = 0.100111111 = 5/8. Agora, já que 1/3 <1/2 <5/8 <2/3 sabemos que x deve cair no intervalo (1/3, 2/3), para que possamos parar de gerar dígitos de x e retornar 2.
O código faz isso essencialmente, exceto que, em vez de gerar x entre 0 e 1, gera x entre a e b, mas o princípio é o mesmo.
Observação: testei esse código contra o método de aceitação / rejeição e ambos produzem distribuições uniformes. Esse código requer menos lançamentos de moedas do que aceitar rejeitar, exceto quando b - a estiver próximo da próxima potência de 2. Ex, se você quiser gerar a = 0, b = 62, aceitar / rejeitar será melhor. Eu pude provar que esse código pode usar, em média, mais de 2 lançamentos de moedas do que aceitar / rejeitar. Pela minha leitura, parece que Knuth e Yao (1976) deram um método para resolver esse problema e provaram que o método deles é ideal no número esperado de lançamentos de moedas. Eles provaram ainda que o número esperado de lançamentos deve ser maior que a entropia de Shannon da distribuição. Não consegui encontrar uma cópia do texto do artigo e ficaria curioso para saber qual é o método deles. (Atualização: acabou de encontrar uma exposição de Knuth Yao 1976 aqui:http://www.nrbook.com/devroye/Devroye_files/chapter_fifteen_1.pdf, mas ainda não o li). Alguém também mencionou Han Hoshi neste tópico, que parece ser mais geral e o resolve usando uma moeda tendenciosa. Veja também http://paper.ijcsns.org/07_book/200909/20090930.pdf de Pae (2009) para uma boa discussão da literatura.
fonte
A resposta simples?
fonte
Esta é uma solução proposta para o caso em que b - a não é igual a 2 ^ k. Supõe-se que ele funcione em um número fixo de etapas (não é necessário descartar candidatos que estão fora do intervalo esperado).
No entanto, não tenho certeza se isso está correto. Critique e ajude a descrever a não uniformidade exata neste gerador de números aleatórios (se houver) e como medi-los / quantificá-los.
Primeiro, converta para o problema equivalente de gerar números aleatórios uniformemente distribuídos no intervalo [0, z-1] onde z = b - a.
Além disso, seja m = 2 ^ k a menor potência de 2> = z.
Conforme a solução acima, já temos um gerador de números aleatórios distribuído uniformemente R (m) no intervalo [0, m-1] (pode ser feito jogando k moedas, uma para cada bit).
O loop while é executado no máximo três vezes, fornecendo o próximo número aleatório em número fixo de etapas (melhor caso = pior caso).
Veja um programa de teste para números [0,2] aqui: http://pastebin.com/zuDD2V6H
fonte
Algoritmo teoricamente ideal
Aqui está uma melhoria da outra resposta que eu postei. A outra resposta tem a vantagem de ser mais fácil estender ao caso mais geral de gerar uma distribuição discreta a partir de outra. De fato, a outra resposta é um caso especial do algoritmo devido a Han e Hoshi.
O algoritmo que descreverei aqui é baseado em Knuth e Yao (1976). Em seu artigo, eles também provaram que esse algoritmo atinge o número mínimo possível de lançamentos de moedas.
Para ilustrá-lo, considere o método de amostragem Rejeição descrito por outras respostas. Como exemplo, suponha que você queira gerar um de 5 números de maneira uniforme [0, 4]. A próxima potência de 2 é 8, para que você jogue a moeda 3 vezes e gere um número aleatório até 8. Se o número for de 0 a 4, você o retornará. Caso contrário, você o joga fora e gera outro número até 8 e tenta novamente até conseguir. Mas quando você joga fora o número, acaba de desperdiçar um pouco de entropia. Em vez disso, você pode condicionar o número que jogou para reduzir o número de lançamentos futuros de moedas que você precisa em expectativa. Concretamente, depois de gerar o número [0, 7], se for [0, 4], retorne. Caso contrário, são 5, 6 ou 7 e você fará algo diferente em cada caso. Se for 5, jogue a moeda novamente e retorne 0 ou 1 com base no flip. Se é 6, jogue a moeda e retorne 2 ou 3. Se for 7, jogue a moeda; se for cara, retorne 4, se a coroa começar de novo.
A entropia restante de nossa tentativa inicial fracassada nos deu três casos (5, 6 ou 7). Se jogarmos isso fora, jogamos fora o log2 (3) lançamentos de moedas. Em vez disso, mantemos e combinamos com o resultado de outro flip para gerar 6 casos possíveis (5H, 5T, 6H, 6T, 7H, 7T), os quais vamos imediatamente tentar novamente para gerar uma resposta final com probabilidade de sucesso 5/6 .
Aqui está o código:
fonte