Packages
fixpoint
0.8.46
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/constraints/propagators/modulo.ex
defmodule CPSolver.Propagator.Modulo do
use CPSolver.Propagator
@x_y_fixed [false, true, true]
@m_x_fixed [true, true, false]
@m_y_fixed [true, false, true]
@all_fixed [true, true, true]
def new(m, x, y) do
new([m, x, y])
end
@impl true
def variables(args) do
args
|> Propagator.default_variables_impl()
|> Enum.map(fn var -> set_propagate_on(var, :bound_change) end)
end
@impl true
def filter(args, nil, changes) do
filter(args, initial_state(args), changes)
end
def filter(args, %{fixed_flags: fixed_flags}, changes) do
updated_fixed = update_fixed(args, fixed_flags, changes)
if filter_impl(args, updated_fixed) do
:passive
else
{:state, %{fixed_flags: updated_fixed}}
end
end
## This (no changes) will happen when the propagator doesn't receive changes
## (either because it was first to run or there were no changes)
defp update_fixed(args, fixed_flags, changes) when map_size(changes) == 0 do
for idx <- 0..2 do
Enum.at(fixed_flags, idx) || fixed?(Enum.at(args, idx))
end
end
defp update_fixed(_args, fixed_flags, changes) do
Enum.reduce(changes, fixed_flags, fn
{idx, :fixed}, flags_acc ->
List.replace_at(flags_acc, idx, true)
{_idx, _bound_change}, flags_acc ->
flags_acc
end)
end
def filter_impl([m, x, y] = _args, @x_y_fixed) do
fix(m, rem(min(x), min(y)))
end
def filter_impl([m, x, y], @m_x_fixed) do
m_value = min(m)
x_value = min(x)
domain(y)
|> Domain.to_list()
|> Enum.each(fn y_value ->
rem(x_value, y_value) != m_value &&
remove(y, y_value)
end)
fixed?(y)
end
def filter_impl([m, x, y], @m_y_fixed) do
m_value = min(m)
y_value = min(y)
domain(x)
|> Domain.to_list()
|> Enum.each(fn x_value ->
rem(x_value, y_value) != m_value &&
remove(x, x_value)
end)
fixed?(x)
end
def filter_impl(_args, @all_fixed) do
true
end
def filter_impl(_args, [true | _x_y_flags]) do
false
end
def filter_impl([m, _x, _y] = args, [false | x_y_flags]) do
update_bounds(args)
fixed?(m) && filter_impl(args, [true | x_y_flags])
end
defp update_bounds([m, x, y] = _args) do
max_x = max(x)
min_x = min(x)
max_y = max(y)
min_y = min(y)
{m_lower_bound, m_upper_bound} =
mod_bounds(min_x, max_x, min_y, max_y)
removeAbove(m, m_upper_bound)
removeBelow(m, m_lower_bound)
end
defp initial_state([_m, _x, y] = args) do
remove(y, 0)
%{fixed_flags: Enum.map(args, fn arg -> fixed?(arg) end)}
end
defp mod_bounds(min_x, max_x, min_y, max_y) do
cond do
min_x >= 0 ->
{0, (max(abs(min_y), abs(max_y)) - 1) |> min(max_x)}
max_x < 0 ->
{(-max(abs(min_y), abs(max_y)) + 1) |> max(min_x), 0}
true ->
{
(min(min(min_y, -min_y), min(max_y, -max_y)) + 1) |> max(min_x),
(max(max(min_y, -min_y), max(max_y, -max_y)) - 1) |> min(max_x)
}
end
end
def mod_bounds(x, y) do
mod_bounds(min(x), max(x), min(y), max(y))
end
end