Dynamic weighed probability

49 Views Asked by At

If I have a list of objects, and want [programmatically] to randomly pull one out, I can simply choose a random number representing a valid index within the range of elements of the list:

var list = ['a', 'b', 'c', 'd', 'e', 'f'];
var rand = parseInt(Math.random() * list.length, 10);

var randElement = list[rand];

Doing the above enough times (to the order or hundreds of thousands of times), each element will have been selected about the same amount of times as each other (they will each have been selected about 1 / 6 = 16% of the time).

Now, suppose the list has zero or more elements with a weight that represents the percentage of extra times that element should be selected over enough selections.

For example:

var list = [
   {item: 'a'},
   {item: 'b'},
   {item: 'c', weight: 0.2},
   {item: 'd', weight: 0.3},
   {item: 'e', weight: 0.4},
   {item: 'f'}
];

That is, if an element has a weight, it should be selected W% more than the elements without a specified weight (item 'c' should be selected 20% more than items 'a', 'b', and 'f').

How do I go about this?

What I've tried

What I've thought of (which doesn't seem to be the correct solution) is to first find the base probability that one element can be selected (1 / total_items), then make that the weight for elements without a weight, and add that value to the existing weight of elements already weighed. The problem with this that stood out to me is that their total sum (sum of weights) doesn't always add to 1.0 (100%).

1

There are 1 best solutions below

0
On BEST ANSWER

Say you have $n$ elements, $k$ of them unweighted. Assign them probability $p_1$. Now if one element has weight $w_1$, its probability is $(1+w_1)p_1$ [ $1.2p_1$ in the example you gave] add all and equate with 1. Since p is the only unknown. $p_1 = \frac{1}{n + \text{sum of weights}}$