WeightedRandom (weighted_random v1.0.0-alpha.0)

Copy Markdown View Source

Usage

table = WeightedRandom.preprocess(0..100, [%{target: 25, weight: 50, radius: 10}])
[n1, n2, n3, n4] = WeightedRandom.take(table, 4)

Alternately, if you care less about performance, you can do it all at once:

[n1, n2, n3, n4] = WeightedRandom.rand(0..100, [%{target: 25, weight: 50, radius: 10}], [take: 4])

But please note the algorithm is optimized to take a long time ( O(n) ) during preprocessing, in order to be very fast during the sampling step ( O(1) ). So it will be far better to preprocess once, and take many times. rand/3 preprocesses EVERY time it is called.

Summary

Functions

Given a list of outcomes and a list of weights, map the list of outcomes into a list of floats which sum to 1.0 (potentially with rounding errors)

For maximum performance, especially at scale, do this

Returns a random value based on the weights given.

Functions

get_probabilities(outcomes, weights, opts)

Given a list of outcomes and a list of weights, map the list of outcomes into a list of floats which sum to 1.0 (potentially with rounding errors)

preprocess(outcomes, weights)

For maximum performance, especially at scale, do this:

preprocess(outcomes, weight, opts)

rand(outcomes, weights)

Returns a random value based on the weights given.

By default this operates on the index, not the value.

## Examples

iex> :rand.seed(:exsss, {108, 101, 102})

iex> li = 1..10

iex> weights = [ %{target: 7, weight: 100} ]

iex>

iex> # By default this uses the index 7, not the value 7.

iex> WeightedRandom.rand(li, weights)

8

iex> # But we can use the value by passing the option index: false

iex> WeightedRandom.rand(li, weights, index: false)

7

iex> li = [:a, :b, :c, :d, :e, :f, :g, :h, :j, :k, :l]

iex> WeightedRandom.rand(li, weights)

:h

iex> weights = [ %{target: :d, weight: 100} ]

iex> WeightedRandom.rand(li, weights, index: false)

:d

Opts

  • :backend [module]: WeightedRandom.Backend.WalkerAlias. We also provide WeightedRandom.Backend.Linear which can have slightly better performance if you are not taking that many samples. Worse performance in most other cases.
  • :index [boolean]: true. Whether the :target of a %WeightedRandom.Weight{} points at an index of the outcomes (if true), or at the actual value of one of the outcomes (if false).
  • :with_index [boolean]: true. set by backend. Determines whether to call Enum.with_index on the list of probabilities before preprocessing.
  • :probability_type [:float | :fraction]: :float. To avoid floating point precision issues, you can use :fraction so that the probabilities are all tuples of {numenator :: integer(), denominator :: integer()} In which they all have the same denominator which equals the sum of all numinators.

  • :precision [integer]: 3. Only applies when the probability_type is :float. Probability floats will be rounded to this number of decimal places.
  • :take [integer | nil]: nil. If used, then instead of returning one random value, will return a list of random value with size equal to take.

rand(outcomes, weight, opts)

take(processed_struct)

take(processed_struct, count)