WeightedRandom.Backend offers a contract to all who implement it:
- The main WeightedRandom package presents a novel interface for generating a list of probabilities or weights
- The custom Backend module decides what to do with those probabilities once they are generated.
Using Backends
To use a different backend, you can either pass it in as an opt (see function docs), or you can put it in your config file:
config :weighted_random,
backend: Your.Backend.ModuleDeveloping a new backend
To create your own backend, copy and change an existing one (like WeightedRandom.Backend.WalkerAlias or WeightedRandom.Backend.Linear).
Your module must implement the callbacks listed below: preprocess/2, take/2, and optionally options/0.
The simplest backend might look like this.
defmodule My.Backend do
use WeightedRandom.Backend
defstruct [:list]
@impl true
def preprocess(probabilities, _opts) do
struct(__MODULE__, %{list: probabilities})
end
@impl true
def take(%__MODULE__{list: li}, count) do
for _ <- 1..count do
Enum.random(li)
end
end
endThis backend doesn't actually apply probability, it is just a glorified Enum.rand(list) for now.
But you can use it in any of the main functions that take an opt of backend
WeightedRandom.rand(0..10, weights, [backend: My.Backend])
=> 3
Summary
Callbacks
A keyword list of options that the backend requires from the WeightedRandom library.
input is a list of floats.
Given the struct returned by preprocess/2, return a list of random indices equal to count.
Types
@type backend_opts() :: [{:probability_type, probability_type()}]
@type index() :: integer()
@type indices() :: [index()]
@type opts() :: keyword()
@type percentage() :: float()
@type probabilities() :: [percentage()]
@type probability_type() :: :weights | :probabilities
@type resolved_weights() :: [float()]
@type table() :: struct()
Callbacks
@callback options() :: backend_opts()
A keyword list of options that the backend requires from the WeightedRandom library.
Currently the only option is :probability_type, which influences the input argument of preprocess/2.
When set to :probabilities (default), the input will be a list of floats that roughly sum to 1.0.
When set to :weights, the input will be a list of floats.
@callback preprocess(input :: probabilities() | resolved_weights(), opts :: opts()) :: table()
input is a list of floats.
This function must return some kind of struct that will later be passed into take/2.
For details about opts, see WeightedRandom.preprocess and WeightedRandom.preprocess_p.
@callback take(table :: struct(), count :: pos_integer()) :: indices :: indices()
Given the struct returned by preprocess/2, return a list of random indices equal to count.