defmodule CPSolver.Search.VariableSelector.Action do @moduledoc """ Action (activity-based) varaible selector (https://www.gecode.org/doc-latest/MPG.pdf, p.8.5.3) """ alias CPSolver.Space alias CPSolver.Shared alias CPSolver.Variable.Interface alias CPSolver.Utils def select(variables, data, action_mode) when action_mode in [:action_min, :action_max, :action_size_min, :action_size_max] do select_impl(variables, data, action_mode) |> Enum.map(fn {var, _action} -> var end) end defp select_impl(variables, data, :action_min) do Utils.minimals( variable_actions(variables, Space.get_shared(data)), fn {_var, action} -> action end ) end defp select_impl(variables, data, :action_max) do Utils.maximals( variable_actions(variables, Space.get_shared(data)), fn {_var, action} -> action end ) end defp select_impl(variables, data, :action_size_min) do Utils.minimals( variable_actions(variables, Space.get_shared(data)), fn {var, action} -> action / Interface.size(var) end ) end defp select_impl(variables, data, :action_size_max) do Utils.maximals( variable_actions(variables, Space.get_shared(data)), fn {var, action} -> action / Interface.size(var) end ) end @doc """ Initialize Action data """ def initialize(space_data, decay) do shared = Space.get_shared(space_data) Shared.get_auxillary(shared, :action) || ( action_table = Shared.create_shared_ets_table(shared) Shared.put_auxillary(shared, :action, %{propagator_actions: action_table, decay: decay}) ) end @doc """ Compute actions of variables in one pass """ def variable_actions(variables, shared) do action_data = Shared.get_auxillary(shared, :action) global_failure_count = Shared.get_failure_count(shared) if action_data && global_failure_count do %{variable_actions: action_table, decay: decay} = action_data Enum.zip(variables, :ets.select(action_table, for(var <- variables, do: {{Interface.id(var), :_}, [], [:"$_"]}))) else Enum.map(variables, fn var -> {var, 1} end) end end end