Reputation: 133609
I was wondering which is the simplest and most configurable way to obtain what I need in the following situation:
X
that will be used to extract one of the setsS1, S2, ..
which can be considered total ordered between themselvesX = 0
it will give me S1
, for, let's say, X = 20
it will give me S1
with 70% chance, and S2
with 30% chanceX
will decrease probability of S1
until 0% while increasing S2
up to 100%, then there can be a zone in which it will always give me S2
until a new threshold for which S2
will start to decrease and S3
will start getting its chance and so onI know how to do it by hardcoding everything, but since it will need some tweaking I would like to apply a solution which easily allows me to configure how many sets I have and the single thresholds (start/end of increasing probability and start/end of decreasing prob). Of course I don't need any intersection between more than 2 sets each and a linear increase/decrease of probability is ok.. any good clues?
Thanks in advance!
Upvotes: 1
Views: 227
Reputation: 9326
To assign the distribution of your probabilities, you could use Bernstein polynomials:
http://en.wikipedia.org/wiki/Bernstein_polynomial
These can be efficiently computed using de Casteljau's algorithm (basically it does DP on the recursion in the obvious way):
http://en.wikipedia.org/wiki/De_Casteljau's_algorithm
http://www.cs.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/Bezier/de-casteljau.html
What you get as a result will be a set of weights on the distributions. To select one of your sets, you just generate a uniform random variable in [0,1] then choose the set it lands in based on these weights.
Here is some code in python which does this:
import random
#Selects one of the n sets with a weight based on x
def pick_a_set(n, x):
#Compute bernstein polynomials
weights = [ [ float(i == j) for j in range(n) ] for i in range(n) ]
for k in range(n):
for j in range(n-k-1):
for i in range(n):
weights[j][i] = weights[j][i] * (1.0 - x) + weights[j+1][i] * x
#Select using weights
u = random.random()
for k in range(n):
if u < weights[0][k]:
return k
u -= weights[0][k]
return 0
Upvotes: 1