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。

这等于选择一个数字,[0,1)同时将其分为 6 个部分:[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)

如果您查看wikipedia entry,您会发现在这种情况下,累积概率函数将不是由 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 回答
6

np.random.choice在这里没有给出答案有点令人惊讶。

from numpy import random 
def roll(N,bias):
    '''this function rolls N dimensional die with biasing provided'''
    return random.choice(np.range(N),p=bias)

p 选项给出“与a中的每个条目相关联的概率”,其中anp.range(N)代表我们。“如果没有给出样本,则假设在a中的所有条目上均匀分布。”

于 2017-03-27T15:14:50.400 回答
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

只是为了提出一种更有效(和 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 回答
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

我为字典创建了一个代码,给出了一个事件和相应的概率,它返回了相应的键,即那个概率的事件。

import random


def WeightedDie(Probabilities):   


    high_p = 0   
    rand = random.uniform(0,1)

    for j,i in Probabilities.items():
        high_p = high_p + i
        if rand< high_p:
            return j
于 2017-07-16T14:21:33.113 回答
0

我们也可以使用numpy'smultinomial分布

import numpy as np

bias = [0.10,0.10,0.15,0.15,0.14,0.16,0.05,0.06,0.04,0.05]   # a 10-sided biased die
np.where(np.random.multinomial(1, bias, size=1)[0]==1)[0][0]+1 # just 1 roll
# 4

如果您想多次滚动有偏差的骰子(具有给定的bias概率)n,请使用以下函数

def roll(probs, ntimes):   # roll a len(probs) sided biased die with bias probs for ntimes
   return np.apply_along_axis(lambda x: x.tolist().index(1)+1, 1, 
                       np.random.multinomial(1, bias,  size=10)).tolist()

roll(probs=bias, ntimes=10)    # 10 rolls
# [5, 6, 8, 4, 8, 3, 1, 5, 8, 6]
于 2019-09-11T08:13:13.460 回答
0

对于 python 3.6 及更高版本,您可以使用已经是 stdlib 一部分的随机选择()方法。要在您的示例中模拟模具,等效代码将是:-

import random

def roll(N, bias_list):
   return random.choices(list(range(N)), weights=bias_list, k=1)[-1]

   
于 2022-01-26T04:48:56.793 回答