12

N面バイアスダイをシミュレートしたいですか?

def roll(N,bias):
     '''this function rolls N dimensional die with biasing provided'''
     # do something
     return result

>> N=6
>> bias=( 0.20,0.20,0.15,0.15,0.14,0.16,)
>> roll(N,bias)
   2
4

10 に答える 10

29

ここで少し数学。

通常のサイコロは、等しい確率で1から6までの各数字を与えます1/6。これは、一様分布と呼ばれます(連続バージョンではなく、離散バージョン)。Xつまり、が単一の役割の結果を表す確率変数である場合、 X~U[1,6]-意味Xはダイスロールのすべての可能な結果(1から6)に対して均等に分配されます。

これは、 6つのセクションに[0,1)分割しながら番号を選択することと同じです:、、、、、、 。[0,1/6)[1/6,2/6)[2/6,3/6)[3/6,4/6)[4/6,5/6)[5/6,1)

偏った別の配布を要求しています。これを実現する最も簡単な方法は、必要な[0,1)バイアスに応じてセクションを6つの部分に分割することです。したがって、あなたの場合[0,0.2)、それを次のように分割したいと思うでしょう:、、、、、、 。[0.2,0.4)[0.4,0.55)0.55,0.7)[0.7,0.84)[0.84,1)

ウィキペディアのエントリを見ると、この場合、累積確率関数は6つの等しい長さの部分ではなく、与えたバイアスに応じて長さが異なる6つの部分で構成されていることがわかります。質量分布についても同様です。

質問に戻り、使用している言語に応じて、これをダイスロールに翻訳し直します。Pythonでは、動作しているとはいえ、非常に大雑把な例を次に示します。

import random
sampleMassDist = (0.2, 0.1, 0.15, 0.15, 0.25, 0.15)
# assume sum of bias is 1
def roll(massDist):
    randRoll = random.random() # in [0,1]
    sum = 0
    result = 1
    for mass in massDist:
        sum += mass
        if randRoll < sum:
            return result
        result+=1

print(roll(sampleMassDist))
于 2009-01-26T10:09:03.027 に答える
11

言語に依存しませんが、ルックアップ テーブルを使用できます。

0 ~ 1 の範囲の乱数を使用し、表で値を検索します。

0.00 - 0.20   1
0.20 - 0.40   2
0.40 - 0.55   3
0.55 - 0.70   4
0.70 - 0.84   5
0.84 - 1.00   6
于 2009-01-26T09:47:21.293 に答える
7
import random

def roll(sides, bias_list):
    assert len(bias_list) == sides
    number = random.uniform(0, sum(bias_list))
    current = 0
    for i, bias in enumerate(bias_list):
        current += bias
        if number <= current:
            return i + 1

バイアスは比例します。

>>> print roll(6, (0.20, 0.20, 0.15, 0.15, 0.14, 0.16))
6
>>> print roll(6, (0.20, 0.20, 0.15, 0.15, 0.14, 0.16))
2

整数も使用できます(より良い):

>>> print roll(6, (10, 1, 1, 1, 1, 1))
5
>>> print roll(6, (10, 1, 1, 1, 1, 1))
1
>>> print roll(6, (10, 1, 1, 1, 1, 1))
1
>>> print roll(6, (10, 5, 5, 10, 4, 8))
2
>>> print roll(6, (1,) * 6)
4
于 2009-01-26T10:14:49.537 に答える
1

確率の異なるランダム オブジェクトの Walker のエイリアス メソッドのレシピを参照してください。
例、文字列 ABC または D の確率は .1 .2 .3 .4 --

abcd = dict( A=1, D=4, C=3, B=2 )
  # keys can be any immutables: 2d points, colors, atoms ...
wrand = Walkerrandom( abcd.values(), abcd.keys() )
wrand.random()  # each call -> "A" "B" "C" or "D"
                # fast: 1 randint(), 1 uniform(), table lookup

乾杯
-- デニス

于 2009-01-26T14:29:01.677 に答える
0
from random import random
biases = [0.0,0.3,0.5,0.99]
coins = [1 if random()<bias else 0 for bias in biases]
于 2016-03-10T15:22:48.963 に答える
0

より効率的な (および pythonic3) ソリューションを提案するために、 bisectを使用して蓄積された値のベクトルを検索することができます — さらに、関数への後続の呼び出しが同じ「バイアス」を参照することを期待して、事前に計算して保存することができます (質問の用語に従うため)。

from bisect import bisect
from itertools import accumulate
from random import uniform

def pick( amplitudes ):
    if pick.amplitudes != amplitudes:
        pick.dist = list( accumulate( amplitudes ) )
        pick.amplitudes = amplitudes
    return bisect( pick.dist, uniform( 0, pick.dist[ -1 ] ) )
pick.amplitudes = None

Python 3 の蓄積がない場合は、単純なループを記述して累積合計を計算できます。

于 2014-02-22T09:14:39.427 に答える