Packages

Production-ready hyperparameter optimization for Elixir with high Optuna parity. Leverages BEAM fault tolerance, real-time dashboards, and native distributed computing.

Current section

Files

Jump to
scout lib sampler.ex
Raw

lib/sampler.ex

defmodule Scout.Sampler do
@moduledoc """
Behaviour for hyperparameter sampling strategies.
All samplers MUST implement this behaviour. Direct function passing is NOT allowed.
This ensures black-box boundaries and compile-time verification.
## Contract
- `init/1` - Initialize sampler state with configuration
- `next/4` - Generate next parameter suggestion based on history
## Example Implementation
defmodule MyCustomSampler do
@behaviour Scout.Sampler
@impl Scout.Sampler
def init(opts) do
%{seed: opts[:seed] || 0}
end
@impl Scout.Sampler
def next(search_space, trial_index, history, state) do
params = generate_params(search_space, state)
{params, state}
end
end
"""
@typedoc "Search space specification or function returning one"
@type search_space :: map() | (non_neg_integer() -> map())
@typedoc "Trial index (0-based)"
@type trial_index :: non_neg_integer()
@typedoc "Historical trials with params and scores"
@type history :: [map()]
@typedoc "Sampler internal state"
@type state :: map()
@typedoc "Generated parameters"
@type params :: map()
@doc """
Initialize sampler with configuration options.
## Options
- `:seed` - Random seed for reproducibility
- `:gamma` - TPE gamma parameter (fraction for good/bad split)
- Other sampler-specific options
Returns initial sampler state.
"""
@callback init(opts :: map()) :: state()
@doc """
Generate next parameter suggestion.
## Arguments
- `search_space` - Parameter specifications (ranges, choices, etc.)
- `trial_index` - Current trial number (0-based)
- `history` - List of completed trials with params and scores
- `state` - Current sampler state
## Returns
`{params, new_state}` where:
- `params` - Map of parameter name to value
- `new_state` - Updated sampler state
## Constraints
- MUST handle empty history (cold start)
- MUST respect search space bounds
- MUST be deterministic given same inputs and state
"""
@callback next(
search_space :: search_space(),
trial_index :: trial_index(),
history :: history(),
state :: state()
) :: {params :: params(), new_state :: state()}
@doc """
Validates that a module implements the Scout.Sampler behaviour.
Raises at compile time if not.
"""
defmacro __using__(_opts) do
quote do
@behaviour Scout.Sampler
end
end
@doc """
Runtime validation that a module implements Scout.Sampler.
Used by executors to verify sampler modules.
"""
@spec valid_sampler?(module()) :: boolean()
def valid_sampler?(module) when is_atom(module) do
Code.ensure_loaded?(module) and
function_exported?(module, :init, 1) and
function_exported?(module, :next, 4)
end
def valid_sampler?(_), do: false
end