defmodule CPSolver.Search.Strategy.FirstFail do
alias CPSolver.Search.Strategy
@behaviour Strategy
alias CPSolver.DefaultDomain, as: Domain
alias CPSolver.Search.DomainPartition
@impl true
def select_variable(variables) do
initial_acc = {nil, :infinity}
{min_var, _size} =
choice =
Enum.reduce_while(variables, initial_acc, fn var, {_v, v_size} = acc ->
case Domain.size(var.domain) do
## Skip fixed vars
1 -> {:cont, acc}
s when s < v_size -> {:cont, {var, s}}
_s -> {:cont, acc}
end
end)
cond do
choice == initial_acc ->
{:error, Strategy.all_vars_fixed_exception()}
true ->
{:ok, min_var}
end
end
@impl true
def partition(domain) do
## Choice of value doesn't matter for first_fail
DomainPartition.by_min(domain)
end
end