При отсутствии накопления Python 3 можно просто написать простой цикл для вычисления накопленной суммы.

у симулировать 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
 S.Lott26 янв. 2009 г., 13:08
Гиперкуб размерности n имеет 2n «сторон». В этом случае вектор смещения для 6-мерного куба должен иметь 12 значений.
 David Z26 янв. 2009 г., 10:51
Не могли бы вы задать это вместо вашего последнего вопроса?stackoverflow.com/questions/477237/...
 S.Lott26 янв. 2009 г., 12:19
 babbageclunk26 янв. 2009 г., 11:56
Я думаю, ты имеешь в виду N-сторонний кубик. N-мерный кристалл совсем другой.

Ответы на вопрос(7)

Смотрите рецепт дляМетод псевдонима Уокера для случайных объектов с разными вероятностями.
Например, строки A B C или 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

ура
- Денис

 denis29 янв. 2009 г., 13:25
Дэвид, для предвзятого распределения кубика / 1d по нескольким точкам, поиск таблицы просто отлично, метод Уокера излишним; для распределений, скажем, многих звезд в 3d, используйте Walker. (Рецепт / его ссылки имели какой-либо смысл вообще?)
 Pratik Deoghare28 янв. 2009 г., 10:52
выглядит круто, но не могли бы вы уточнить?

Немного удивительно, что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", гдеa являетсяnp.range(N) для нас. «Если не указан образец предполагает равномерное распределение по всем записям вa».

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
 Pratik Deoghare28 янв. 2009 г., 12:19
Спасибо за предложение чистого решения.
Решение Вопроса

Обычный кубик даст каждому числу 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).

Если вы посмотрите назапись в википедиивы увидите, что в этом случае накопленная функция вероятности будет состоять не из 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)
 S.Lott26 янв. 2009 г., 12:22
@wcoenen: онислучайный номера. Никакое распределение случайных чисел никогда не сможет точно соответствовать заданному смещению. Если бы набор чисел соответствовал данному смещению, мы должны были бы отклонить его как не случайный.
 Pratik Deoghare28 янв. 2009 г., 12:18
Спасибо за очень хорошее математическое объяснение.
 Wim Coenen26 янв. 2009 г., 12:03
Здесь есть небольшая проблема. Числа с плавающей запятой имеют ограниченную точность, и поэтому сумма весов, как правило, не будет точно равна 1. Я не знаю, насколько важен этот эффект, но может быть безопаснее вместо этого использовать целые числа для весов.

можно использоватьразрез`ать искать в векторе накопленных значений - которые, кроме того, могут быть предварительно вычислены и сохранены в надежде, что последующие вызовы функции будут ссылаться на тот же «уклон» (чтобы следовать терминологии вопроса).

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 можно просто написать простой цикл для вычисления накопленной суммы.

но вы можете использовать справочную таблицу.

Используйте случайное число в диапазоне 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
 Greg Hewgill26 янв. 2009 г., 10:53
В контексте предвзятых штампов стоит упомянуть равномерное распределение случайного числа :)
from random import random
biases = [0.0,0.3,0.5,0.99]
coins = [1 if random()<bias else 0 for bias in biases]

Ваш ответ на вопрос