WeightedRandom (weighted_random v1.0.0-rc.1)

Copy Markdown View Source

Tutorials

The best way to learn is through the Livebook

Or the static equivalent Guide

Summary

Functions

Given a non-empty list (or range) of possible outcomes, and a list of weight maps, build a struct that can later be passed into WeightedRandom.take/2 for very fast random sampling.

Given a non-empty list of percentages (floats from 0.0 - 1.0), build the struct.

Returns a random value based on the weights given. If you need a lot of random numbers over time, this is suboptimal and you should use preprocess + take instead.

similar to rand/3 but instead of a list of outcomes, and a list of weights, rand_p/3 accepts a list of probability floats. If you need a lot of random numbers over time, this is suboptimal and you should use preprocess + take instead.

Given a WeightedRandom struct, return a single random value.

Given a WeightedRandom struct, return a list of random values

Functions

preprocess(outcomes, weights, opts \\ [])

Given a non-empty list (or range) of possible outcomes, and a list of weight maps, build a struct that can later be passed into WeightedRandom.take/2 for very fast random sampling.

Examples

iex> r = WeightedRandom.preprocess(0..10, [%{target: 2, amount: 1000}])
iex> li = WeightedRandom.take(r, 5)
[2, 2, 2, 2, 2]

Supported options:

  • :backend (atom/0) - Required. Any module which implements the @behaviour: WeightedRandom.Backend. This is the core algorithm providing the randomness functionality.

  • :precision (pos_integer/0) - The number of decimal places to use when rounding. Leave nil for no rounding.

  • :tolerance (float/0) - When WeightedRandom automatically normalizes your probabilities to make sure they add up to 1.0, sometimes they are off slightly due to floating point precision issues. How close does it need to be? By default we use 1.0e-10, which means that: 0.99 is NOT close enough, but 0.9999999999 is close enough. The default value is 1.0e-10.

  • :outcome_type - When you take a random sample, will it return the index of an outcome, or the value?

    • index: pick random indices from the list of outcomes. For example if your outcomes are 125..130 then the results will be between 0 and 5.
    • value: pick random values from the list of outcomes. For example if your outcomes are 125..130 then the results will be between 125 and 130.

    The default value is :index.

preprocess_p(probabilities, opts \\ [])

Given a non-empty list of percentages (floats from 0.0 - 1.0), build the struct.

Next, pass the resulting struct into WeightedRandom.take/2 to get rand

Examples

iex> r = WeightedRandom.preprocess_p([0.01, 0.01, 0.98])
iex> li = WeightedRandom.take(r, 5)
[2, 2, 2, 2, 2]

Supported options:

  • :backend (atom/0) - Required. Any module which implements the @behaviour: WeightedRandom.Backend. This is the core algorithm providing the randomness functionality.

  • :precision (pos_integer/0) - The number of decimal places to use when rounding. Leave nil for no rounding.

  • :tolerance (float/0) - When WeightedRandom automatically normalizes your probabilities to make sure they add up to 1.0, sometimes they are off slightly due to floating point precision issues. How close does it need to be? By default we use 1.0e-10, which means that: 0.99 is NOT close enough, but 0.9999999999 is close enough. The default value is 1.0e-10.

rand(outcomes, weights, opts \\ [])

Returns a random value based on the weights given. If you need a lot of random numbers over time, this is suboptimal and you should use preprocess + take instead.

Supported options:

  • :precision (pos_integer/0) - The number of decimal places to use when rounding. Leave nil for no rounding.

  • :tolerance (float/0) - When WeightedRandom automatically normalizes your probabilities to make sure they add up to 1.0, sometimes they are off slightly due to floating point precision issues. How close does it need to be? By default we use 1.0e-10, which means that: 0.99 is NOT close enough, but 0.9999999999 is close enough. The default value is 1.0e-10.

  • :outcome_type - When you take a random sample, will it return the index of an outcome, or the value?

    • index: pick random indices from the list of outcomes. For example if your outcomes are 125..130 then the results will be between 0 and 5.
    • value: pick random values from the list of outcomes. For example if your outcomes are 125..130 then the results will be between 125 and 130.

    The default value is :index.

  • :take (pos_integer/0) - If used, then instead of returning one random value, will return a list (size == :take) of random values

  • :backend (atom/0) - Any module which implements the @behaviour: WeightedRandom.Backend. This is the core algorithm providing the randomness functionality.

rand_p(probabilities, opts \\ [])

similar to rand/3 but instead of a list of outcomes, and a list of weights, rand_p/3 accepts a list of probability floats. If you need a lot of random numbers over time, this is suboptimal and you should use preprocess + take instead.

Supported options:

  • :backend (atom/0) - Any module which implements the @behaviour: WeightedRandom.Backend. This is the core algorithm providing the randomness functionality.

  • :precision (pos_integer/0) - The number of decimal places to use when rounding. Leave nil for no rounding.

  • :tolerance (float/0) - When WeightedRandom automatically normalizes your probabilities to make sure they add up to 1.0, sometimes they are off slightly due to floating point precision issues. How close does it need to be? By default we use 1.0e-10, which means that: 0.99 is NOT close enough, but 0.9999999999 is close enough. The default value is 1.0e-10.

  • :take (pos_integer/0) - If used, then instead of returning one random value, will return a list (size == :take) of random values

take(processed_struct)

@spec take(WeightedRandom.Backend.t()) :: any()

Given a WeightedRandom struct, return a single random value.

Examples

iex> r = WeightedRandom.preprocess(0..10, [%{target: 2, amount: 1000}])
iex> li = WeightedRandom.take(r)
2

take(processed_struct, count)

@spec take(WeightedRandom.Backend.t(), count :: integer()) :: list()

Given a WeightedRandom struct, return a list of random values

Examples

iex> # Make the item at index 2 1000x more likely than any other single index.
iex> r = WeightedRandom.preprocess(0..10, [%{target: 2, amount: 1000}])
iex> li = WeightedRandom.take(r, 3)
[2, 2, 2]