# [ACCEPTED]-How do I simulate biased die in python?-probability

Score: 29

A little bit of math here.

A regular die 24 will give each number 1-6 with equal probability, namely 23 `1/6`. This is referred to as uniform distribution (the discrete 22 version of it, as opposed to the continuous 21 version). Meaning that if `X` is a random variable 20 describing the result of a single role then 19 `X~U[1,6]` - meaning `X` is distributed equally against 18 all possible results of the die roll, 1 17 through 6.

This is equal to choosing a number 16 in `[0,1)` while dividing it into 6 sections: `[0,1/6)`, `[1/6,2/6)`, `[2/6,3/6)`, `[3/6,4/6)`, `[4/6,5/6)`, `[5/6,1)`.

You 15 are requesting a different distribution, which 14 is biased. The easiest way to achieve this 13 is to divide the section `[0,1)` to 6 parts depending 12 on the bias you want. So in your case you 11 would want to divide it into the following: `[0,0.2)`, `[0.2,0.4)`, `[0.4,0.55)`, `0.55,0.7)`, `[0.7,0.84)`, `[0.84,1)`.

If 10 you take a look at the wikipedia entry, you will see that 9 in this case, the cumulative probability 8 function will not be composed of 6 equal-length 7 parts but rather of 6 parts which differ 6 in length according to the bias you gave them. Same 5 goes for the mass distribution.

Back to the 4 question, depending on the language you 3 are using, translate this back to your die 2 roll. In Python, here is a very sketchy, albeit 1 working, example:

``````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))
``````
Score: 11

More language agnostic, but you could use 2 a lookup table.

Use a random number in the 1 range 0-1 and lookup the value in a table:

``````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
``````
Score: 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
``````

The bias will be proportional.

``````>>> 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
``````

Could use 1 integers too (better):

``````>>> 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
``````
Score: 6

It is a little surprising that the `np.random.choice` answer 5 hasn't been given here.

``````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)
``````

The p option gives 4 "the probabilities associated with 3 each entry in a", where a is `np.range(N)` for us. "If 2 not given the sample assumes a uniform distribution 1 over all entries in a".

Score: 1

See the recipe for Walker's alias method for random objects with 3 different probablities.
An example, strings 2 A B C or D with probabilities .1 .2 .3 .4 1 --

``````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
``````

cheers
-- denis

Score: 0

Just to suggest a more efficient (and pythonic3) solution, one 8 can use bisect to search in the vector of accumulated 7 values — that can moreover be precomputed 6 and stored in the hope that subsequent calls 5 to the function will refer to the same "bias" (to 4 follow the question parlance).

``````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
``````

In absence 3 of Python 3 accumulate, one can just write 2 a simple loop to compute the cumulative 1 sum.

Score: 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]
``````

0

Score: 0

i have created a code for a dictionary giving 3 a event and corresponding probability, it 2 gives back the corresponding key ie the 1 event of that probability.

``````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
``````
Score: 0

We could use `numpy`'s `multinomial` distribution too

``````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
``````

If you 3 want to roll the biased die (with the given 2 `bias` probabilities) for `n` times, use the following 1 function

``````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]
``````
Score: 0

For python 3.6 and above, you can make use 3 of random's choices() method already part 2 of stdlib. To simulate the die in your example, the 1 equivalent code would be:-

``````import random

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

``````

More Related questions