Packages
fixpoint
0.12.8
0.22.1
0.21.5
0.21.4
0.21.3
0.21.2
0.21.1
0.21.0
0.20.6
0.20.5
0.20.4
0.20.3
0.20.2
0.20.1
0.19.5
0.19.4
0.19.3
0.19.2
0.19.1
0.18.2
0.18.1
0.17.6
0.17.5
0.17.4
0.17.3
0.17.2
0.17.1
0.16.5
0.16.4
0.16.3
0.16.2
0.16.1
0.16.0
0.15.6
0.15.5
0.15.4
0.15.3
0.15.2
0.15.1
0.15.0
0.14.9
0.14.8
0.14.7
0.14.6
0.14.5
0.14.4
0.14.3
0.14.2
0.14.1
0.13.5
0.13.4
0.13.2
0.13.1
0.12.9
0.12.8
0.12.7
0.12.6
0.12.5
0.12.4
0.12.2
0.12.1
0.11.8
0.11.7
0.11.6
0.11.5
0.11.4
0.11.3
0.11.2
0.11.1
0.10.7
0.10.6
0.10.5
0.10.4
0.10.3
0.10.2
0.10.1
0.9.12
0.9.11
0.9.10
0.9.9
0.9.8
0.9.7
0.9.6
0.9.5
0.9.4
0.9.3
0.9.2
0.9.1
0.9.0
0.8.52
0.8.51
0.8.50
0.8.49
0.8.48
0.8.46
0.8.44
0.8.43
0.8.42
0.8.41
0.8.40
0.8.39
0.8.38
0.8.37
0.8.36
0.8.35
0.8.34
0.8.33
0.8.32
0.8.31
0.8.30
0.8.29
0.8.28
0.8.27
0.8.26
0.8.25
0.8.24
0.8.23
0.8.22
0.8.21
0.8.20
0.8.19
0.8.18
0.8.17
0.8.16
0.8.15
0.8.14
0.8.13
0.8.12
0.8.11
0.8.10
0.8.9
0.8.8
0.8.7
0.8.6
0.8.5
0.8.4
0.8.3
0.8.2
0.8.1
0.8.0
0.7.10
0.7.9
0.7.8
0.7.7
0.7.6
0.7.5
0.7.4
0.7.3
0.7.2
0.7.1
0.7.0
0.6.5
0.6.4
0.6.3
0.6.2
0.6.1
0.6.0
0.5.12
0.5.11
0.5.10
0.5.9
0.5.8
0.5.7
0.5.6
0.5.5
0.5.4
0.5.3
0.5.2
0.5.1
0.5.0
0.4.3
0.4.2
0.4.1
0.4.0
0.3.6
0.3.5
0.3.4
0.3.3
0.3.2
0.3.1
0.3.0
0.2.3
0.2.2
0.2.1
0.1.3
0.1.2
0.1.1
0.1.0
Constraint Programming Solver
Current section
Files
Jump to
Current section
Files
lib/solver/search/strategy/variable/variable_selector.ex
defmodule CPSolver.Search.VariableSelector do
@callback initialize(map(), any()) :: :ok
@callback update(map(), Keyword.t()) :: :ok
@callback select([Variable.t()], map(), any()) :: Variable.t() | nil
alias CPSolver.Variable.Interface
alias CPSolver.Search.VariableSelector.{
FirstFail,
MostConstrained,
MostCompleted,
DomDeg,
MaxRegret,
AFC,
Action,
CHB
}
defmacro __using__(_) do
quote do
alias CPSolver.Search.VariableSelector
alias CPSolver.Variable.Interface
alias CPSolver.DefaultDomain, as: Domain
@behaviour VariableSelector
def initialize(_data, _opts) do
:ok
end
def update(_data, _opts) do
:ok
end
defoverridable initialize: 2, update: 2
end
end
def initialize(selector, _space_data) do
selector
end
def select_variable(variables, data, variable_choice) when is_atom(variable_choice) do
select_variable(variables, data, strategy(variable_choice))
end
def select_variable(variables, data, variable_choice) when is_function(variable_choice) do
variables
|> Enum.reject(fn v -> Interface.fixed?(v) end)
|> then(fn
[] -> throw(all_vars_fixed_exception())
unfixed_vars -> execute_variable_choice(variable_choice, unfixed_vars, data)
end)
end
def all_vars_fixed_exception() do
:all_vars_fixed
end
def failed_variables_in_search_exception() do
:failed_variables_in_search
end
defp execute_variable_choice(variable_choice, unfixed_vars, _data)
when is_function(variable_choice, 1) do
variable_choice.(unfixed_vars)
end
defp execute_variable_choice(variable_choice, unfixed_vars, data)
when is_function(variable_choice, 2) do
variable_choice.(unfixed_vars, data)
end
######################################
## Variable choice (shortcuts) ##
######################################
def strategy({afc_mode, decay})
when afc_mode in [:afc_min, :afc_max, :afc_size_min, :afc_size_max] do
afc({afc_mode, decay}, &Enum.random/1)
end
def strategy({action_mode, decay})
when action_mode in [:action_min, :action_max, :action_size_min, :action_size_max] do
action({action_mode, decay}, &Enum.random/1)
end
def strategy(chb_mode)
when chb_mode in [:chb_min, :chb_max, :chb_size_min, :chb_size_max] do
chb(chb_mode, &Enum.random/1)
end
def strategy(:first_fail) do
first_fail(&List.first/1)
end
def strategy(:input_order) do
fn variables ->
Enum.sort_by(variables, fn %{index: idx} -> idx end)
|> List.first()
end
end
def strategy(:most_constrained) do
most_constrained(&Enum.random/1)
end
def strategy(:most_completed) do
most_completed(&Enum.random/1)
end
def strategy(:dom_deg) do
dom_deg(&Enum.random/1)
end
def strategy(:max_regret) do
max_regret(&Enum.random/1)
end
def strategy(impl) when is_atom(impl) do
if Code.ensure_loaded(impl) == {:module, impl} && function_exported?(impl, :select, 3) do
impl
else
throw({:unknown_strategy, impl})
end
end
###################################
## Implementations (top-level) ##
###################################
def most_constrained(break_even_fun \\ &Enum.random/1)
def most_constrained(break_even_fun) when is_function(break_even_fun) do
variable_choice(MostConstrained, break_even_fun)
end
def most_completed(break_even_fun \\ &Enum.random/1)
def most_completed(break_even_fun) do
variable_choice(MostCompleted, extract_strategy(break_even_fun))
end
def max_regret(break_even_fun \\ &Enum.random/1)
def max_regret(break_even_fun) when is_function(break_even_fun) do
variable_choice(MaxRegret, break_even_fun)
end
def first_fail(break_even_fun \\ &Enum.random/1)
def first_fail(break_even_fun) when is_function(break_even_fun) do
variable_choice(FirstFail, break_even_fun)
end
def dom_deg(break_even_fun \\ &Enum.random/1)
def dom_deg(break_even_fun) when is_function(break_even_fun) do
variable_choice(DomDeg, break_even_fun)
end
def afc({afc_mode, decay}, break_even_fun \\ FirstFail)
when afc_mode in [:afc_min, :afc_max, :afc_size_min, :afc_size_max] do
variable_choice({AFC, mode: afc_mode, decay: decay}, break_even_fun)
end
def action({action_mode, decay}, break_even_fun \\ FirstFail)
when action_mode in [:action_min, :action_max, :action_size_min, :action_size_max] do
variable_choice({Action, mode: action_mode, decay: decay}, break_even_fun)
end
def chb(chb_mode, break_even_fun \\ FirstFail)
def chb({chb_mode, q_score}, break_even_fun)
when chb_mode in [:chb_min, :chb_max, :chb_size_min, :chb_size_max] do
variable_choice(
{CHB, mode: chb_mode, q_score: q_score},
break_even_fun
)
end
def chb(chb_mode, break_even_fun) do
chb({chb_mode, CHB.default_q_score()}, break_even_fun)
end
defp extract_strategy(shortcut) when is_atom(shortcut) do
strategy(shortcut)
end
defp extract_strategy(strategy) when is_function(strategy) do
strategy
end
def mixed(strategies) do
Enum.random(strategies)
|> extract_strategy()
end
defp execute_break_even(selection, _data, break_even_fun) when is_function(break_even_fun, 1) do
break_even_fun.(selection)
end
defp execute_break_even(selection, data, break_even_fun) when is_function(break_even_fun, 2) do
break_even_fun.(selection, data)
end
def variable_choice(strategy_fun, break_even_fun \\ &Enum.random/1)
def variable_choice(strategy_fun, break_even_fun) when is_function(strategy_fun) do
fn vars, data ->
vars
|> strategy_fun.(data)
|> execute_break_even(data, break_even_fun)
end
end
def variable_choice({strategy_impl, args}, break_even_fun) when is_atom(strategy_impl) do
impl = strategy(strategy_impl)
initialize? = function_exported?(impl, :initialize, 2)
strategy_fun = fn vars, data ->
initialize? && impl.initialize(data, args)
impl.select(vars, data, args)
end
variable_choice(strategy_fun, break_even_fun)
end
def variable_choice(strategy_impl, break_even_fun) when is_atom(strategy_impl) do
variable_choice({strategy_impl, nil}, break_even_fun)
end
end