Weighted Random Choice Between Symbols

ingmar rheinhausen's icon

I find myself quite often in a situation where a need a choice between several symbols (or integer values), each with a different probability. Before run-time I neither know how many elements there will be nor their probabilities (but this will be an integer number). – Example:
* 'a' with probability share of 2,
* 'bb' with probability share of 3,
* 'ccc' with probability share of 7.

My usual solution is using a coll object, generating 2 entries for 'a', 3 entries for 'bb' and 7 for 'ccc', then selecting randomly between the entries. If changes occur, I just clear the coll and start from the scratch. No problem.

But this feels a bit cumbersome and complex, and I wonder if there is perhaps a simple standard solution in Max?

Thank you.

Jean-Francois Charles's icon

That's the kind of thing I would do:

Max Patch
Copy patch and select New From Clipboard in Max.

Roman Thilenius's icon

if it is only a few messages you could think of your data as integer ranges - and then use [split] to distribute a random number generator output accordingly: [split 5 12] -> [t ccc]

or if the amounts are very small vallues, you could make copies of the data: [t ccc] [t ccc] [t ccc] [t ccc] [t ccc] [t ccc] [t ccc]


supercollider has .choose for that kind of thing, and there never were a max equivalent.

and when you are going to build your own [choose ccc 7], you will quickly notice that there are several different possible designs for such a function and that you run out of patcher arguments sooner than you wished.

the logic behind it is very similar to a markov chain mechanism, just without a starting point for the transitions (the starting point will always be the random number generator...)

if you start start with a [coll], it should almost show you the way. i suppose you use integer number as indexes...

ingmar rheinhausen's icon

Thank you.

Actually, I know the [split] module… : - )

My issue here was, as I said, that I do not know the actual symbols, their number or their probability shares before. Meaning, my objects will receive a message and will have to parse it for the details. These can also change again at runtime.

Anyway, some detail in your answers gave me food for thought. Instead of one big object filling a [coll], I now tried using a number of small identical objects, all connected, that each wrap one [split] object. This solution is working well and feels quite elegant… if somebody needs something like this, I can share it.