Packages
fixpoint
0.21.0
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/shared/action.ex
defmodule CPSolver.Search.VariableSelector.Action do
@moduledoc """
Action (activity-based) variable selector
(https://www.gecode.org/doc-latest/MPG.pdf, p.8.5.3)
"""
use CPSolver.Search.VariableSelector
alias CPSolver.Space
alias CPSolver.Shared
alias CPSolver.Variable.Interface
alias CPSolver.Utils
@default_action_value 1
@impl true
def select(data, opts) do
data
|> variable_actions(Space.get_shared(data) |> Shared.get_auxillary(:action))
|> select_impl(opts[:mode])
|> Enum.map(fn {var, _afc} -> var end)
end
defp select_impl(actions, :action_min) do
Utils.minimals(actions,
fn {_var, action} -> action end
)
end
defp select_impl(actions, :action_max) do
Utils.maximals(actions,
fn {_var, action} -> action end
)
end
defp select_impl(actions, :action_size_min) do
Utils.minimals(actions,
fn {var, action} -> action / Interface.size(var) end
)
end
defp select_impl(actions, :action_size_max) do
Utils.maximals(actions,
fn {var, action} -> action / Interface.size(var) end
)
end
@doc """
Initialize Action data
"""
@impl true
def initialize(%{variables: variables} = space_data, opts) do
shared = Space.get_shared(space_data)
Shared.get_auxillary(shared, :action) ||
(
action_table = Shared.create_shared_ets_table(shared)
init_variable_actions(variables, action_table)
Shared.put_auxillary(shared, :action, %{
variable_actions: action_table,
decay: opts[:decay]
})
Shared.add_handler(shared, :on_space_finalized, fn solver,
%{variables: variables} = _space_data,
_reason ->
Shared.complete?(solver) ||
update_actions(variables, solver)
end)
)
end
defp init_variable_actions(variables, action_table) do
Enum.each(variables, fn var ->
:ets.insert(action_table, {Interface.id(var), @default_action_value})
end)
end
@doc """
Compute actions of variables in one pass
"""
def variable_actions(space_data, %{variable_actions: action_table} = _action_data) do
actions =
:ets.select(
action_table,
Tracker.iterate(space_data, [], fn var, acc ->
[{{Interface.id(var), :_}, [], [:"$_"]} | acc] end, false)
)
|> Map.new()
Tracker.iterate(space_data, [], fn var, acc ->
var_id = Interface.id(var)
[{var, Map.get(actions, var_id, @default_action_value)} | acc]
end, false)
end
def variable_actions(space_data, _action_data) do
Tracker.iterate(space_data, [], fn var, acc -> [{var, @default_action_value} | acc ] end, false)
end
def update_actions(variables, shared) do
case Shared.get_auxillary(shared, :action) do
nil ->
:ok
%{variable_actions: action_table, decay: decay} ->
Enum.each(variables, fn var -> update_variable_action(var, action_table, decay) end)
end
end
## Update action for individual variable in 'shared'
defp update_variable_action(
%{id: variable_id, initial_size: initial_size} = variable,
action_table,
decay
) do
updated_action =
case get_action(action_table, variable_id) do
nil ->
@default_action_value
current_action ->
## Some variables may fail
current_size =
try do
Interface.size(variable)
catch
:fail ->
0
end
(initial_size > current_size && current_action + 1) || current_action * decay
end
:ets.insert(action_table, {variable_id, updated_action})
end
defp get_action(table, variable_id)
when is_reference(table) and is_reference(variable_id) do
table
|> :ets.lookup(variable_id)
|> then(fn rec ->
(!Enum.empty?(rec) && elem(hd(rec), 1)) ||
@default_action_value
end)
end
end