Packages
fixpoint
0.3.6
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/propagators/propagator.ex
defmodule CPSolver.Propagator do
@type propagator_event :: :domain_change | :bound_change | :min_change | :max_change | :fixed
@callback filter(args :: list()) :: map() | :stable | :failure
@callback variables(args :: list()) :: list()
@callback events() :: list()
alias CPSolver.Variable
alias CPSolver.Propagator.Variable, as: PropagatorVariable
defmacro __using__(_) do
quote do
alias CPSolver.Propagator
import CPSolver.Propagator.Variable
@behaviour Propagator
def variables(args) do
Propagator.default_variables_impl(args)
end
## Events that trigger propagation
def events() do
CPSolver.Common.domain_events()
end
defoverridable variables: 1
defoverridable events: 0
end
end
def propagator_events() do
[:domain_change, :bound_change, :min_change, :max_change, :fixed]
end
def default_variables_impl(args) do
args
|> Enum.filter(fn
%Variable{} -> true
_ -> false
end)
end
@spec normalize([Propagator.t()], ConstraintStore.t()) :: %{reference() => Propagator.t()}
def normalize(propagators, store \\ nil)
def normalize(propagators, store) when is_list(propagators) do
propagators
|> Enum.map(fn p -> normalize(p, store) end)
|> Enum.uniq()
|> Map.new(fn p -> {make_ref(), p} end)
end
def normalize({mod, args} = _propagator, store) when is_list(args) do
{mod,
Enum.map(
args,
fn
%Variable{} = var ->
var
|> then(fn var -> (store && Map.put(var, :store, store)) || var end)
const ->
const
end
)}
end
def normalize(propagator, store) when is_tuple(propagator) do
[mod | args] = Tuple.to_list(propagator)
normalize({mod, args}, store)
end
def filter(mod, args) do
PropagatorVariable.reset_variable_ops()
case mod.filter(args) do
:stable ->
:stable
_res ->
## If propagator doesn't explicitly return 'stable',
## we retrieve the map of variable operations created by PropagatorVariable wrapper
case PropagatorVariable.get_variable_ops() do
{:fail, var} ->
{:fail, var}
op_results when is_map(op_results) ->
process_op_changes(op_results)
end
end
end
## How domain events map to propagator events
## (see Propagator.events() callback).
def to_domain_events(:domain_change) do
[:domain_change, :min_change, :max_change, :fixed]
end
def to_domain_events(:bound_change) do
[:min_change, :max_change, :fixed]
end
def to_domain_events(:min_change) do
[:min_change, :fixed]
end
def to_domain_events(:max_change) do
[:max_change, :fixed]
end
def to_domain_events(:fixed) do
[:fixed]
end
@spec process_op_changes(%{reference() => atom()}) ::
:stable | {:changed, [{atom(), reference()}]}
defp process_op_changes(op_results) do
op_results
|> Enum.flat_map(fn {var, result} ->
(result == :no_change && []) || [{result, var}]
end)
|> then(fn changes -> (changes == [] && :stable) || {:changed, changes} end)
end
end