Current section

Files

Jump to
fixpoint test propagators modulo_test.exs
Raw

test/propagators/modulo_test.exs

defmodule CPSolverTest.Propagator.Modulo do
use ExUnit.Case
describe "Propagator filtering" do
alias CPSolver.IntVariable, as: Variable
alias CPSolver.DefaultDomain, as: Domain
alias CPSolver.Variable.Interface
alias CPSolver.Propagator
alias CPSolver.Propagator.Modulo
test "filtering, initial call" do
## Both vars are unfixed
x = 1..10
y = -5..5
m = -10..10
[m_var, _x_var, y_var] = variables = Enum.map([m, x, y], fn d -> Variable.new(d) end)
# before filtering
assert Interface.contains?(y_var, 0)
assert Interface.min(m_var) == -10
p = Modulo.new(variables)
_res = Propagator.filter(p)
## y has 0 removed
refute Interface.contains?(y_var, 0)
## Nothing is fixed
refute Enum.any?(variables, fn var -> Interface.fixed?(var) end)
end
test "filtering, dividend and divisor fixed" do
x = -7
y = 3
m = -10..10
[m_var, _x_var, _y_var] = variables = Enum.map([m, x, y], fn d -> Variable.new(d) end)
p = Modulo.new(variables)
res = Propagator.filter(p)
assert res.changes == %{m_var.id => :fixed}
## Modulo is fixed to x % y
## Dividend and modulo have the same sign
assert Interface.fixed?(m_var) && Interface.min(m_var) == rem(x, y)
end
test "filtering, modulo and dividend fixed" do
x = -10
y = -100..100
m = -2
[_m_var, _x_var, y_var] = variables = Enum.map([m, x, y], fn d -> Variable.new(d) end)
p = Modulo.new(variables)
res = Propagator.filter(p)
refute res == :fail
## All values in domain of y satisfy x % y = m
assert Enum.all?(Domain.to_list(y_var.domain), fn y_val ->
rem(x, y_val) == m
end)
end
test "filtering, modulo and divider fixed" do
x = -100..100
y = -10
m = -2
[_m_var, x_var, _y_var] = variables = Enum.map([m, x, y], fn d -> Variable.new(d) end)
p = Modulo.new(variables)
res = Propagator.filter(p)
refute res == :fail
## All values in domain of x satisfy x % y = m
assert Enum.all?(Domain.to_list(x_var.domain), fn x_val -> rem(x_val, y) == m end)
end
test "inconsistency, if modulo and dividend are fixed to values of different sign" do
x = 10
y = -100..100
m = -2
variables = Enum.map([m, x, y], fn d -> Variable.new(d) end)
p = Modulo.new(variables)
assert :fail = Propagator.filter(p)
end
test "inconsistency, if every modulo value has a different sign with every divident value" do
m = 1..10
y = -100..100
x = -10..-1
variables = Enum.map([m, x, y], fn d -> Variable.new(d) end)
p = Modulo.new(variables)
assert :fail = Propagator.filter(p)
end
end
end