Packages
fixpoint
0.3.4
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
test/propagators/not_equal_test.exs
defmodule CPSolverTest.Propagator.NotEqual do
use ExUnit.Case
import ExUnit.CaptureLog
describe "Propagator filtering" do
alias CPSolver.ConstraintStore
alias CPSolver.IntVariable, as: Variable
alias CPSolver.Propagator.Variable, as: PropagatorVariable
alias CPSolver.Propagator.Thread, as: PropagatorThread
alias CPSolver.Propagator.NotEqual
setup do
Logger.configure(level: :debug)
on_exit(fn -> Logger.configure(level: :error) end)
end
test "filtering, unfixed domains" do
## Both vars are unfixed
x = 1..10
y = -5..5
variables = Enum.map([x, y], fn d -> Variable.new(d) end)
{:ok, bound_vars, _store} = ConstraintStore.create_store(variables)
assert :stable == NotEqual.filter(bound_vars)
assert PropagatorVariable.get_variable_ops() == %{}
[x_var, y_var] = bound_vars
## Fix one of vars
assert :fixed = Variable.fix(x_var, 5)
assert :domain_change == NotEqual.filter(bound_vars)
assert PropagatorVariable.get_variable_ops() == %{y_var.id => :domain_change}
## The filtering should have removed '5' from y_var
assert Variable.max(y_var) == 4
assert Variable.min(y_var) == -5
## Fix second var and filter again
assert :fixed == Variable.fix(y_var, 4)
assert :no_change == NotEqual.filter(bound_vars)
assert PropagatorVariable.get_variable_ops() == %{y_var.id => :no_change}
## Make sure filtering doesn't fail on further calls
refute Enum.any?(
[x_var, y_var],
fn var -> :fail == Variable.min(var) end
)
## Consequent filtering does not trigger domain change events
refute capture_log([level: :debug], fn ->
NotEqual.filter(bound_vars)
Process.sleep(10)
end) =~ "Domain change"
end
test "inconsistency" do
x = 0..0
y = 0..0
[_x_var, y_var] = variables = Enum.map([x, y], fn d -> Variable.new(d) end)
{:ok, bound_vars, _store} = ConstraintStore.create_store(variables)
assert :fail == NotEqual.filter(bound_vars)
assert PropagatorVariable.get_variable_ops() == {:fail, y_var.id}
## One of variables (depending on filtering implementation) will fail
assert Enum.any?(
bound_vars,
fn var -> :fail == Variable.fixed?(var) end
)
end
test "offset" do
x = 5..5
y = -5..10
variables = Enum.map([x, y], fn d -> Variable.new(d) end)
{:ok, [x_var, y_var], _store} = ConstraintStore.create_store(variables)
assert Variable.contains?(y_var, 0)
# (x != y + 5)
offset = 5
NotEqual.filter(x_var, y_var, offset)
refute Variable.contains?(y_var, 0)
# (x != y - 5)
offset = -5
assert Variable.contains?(y_var, 10)
NotEqual.filter(x_var, y_var, offset)
refute Variable.contains?(y_var, 10)
end
test "propagates only when variables become fixed" do
## Both vars are unfixed
x = 1..2
y = 0..3
variables = Enum.map([x, y], fn d -> Variable.new(d) end)
{:ok, [x_var, y_var] = _bound_vars, store} =
ConstraintStore.create_store(variables)
{:ok, _propagator_thread} =
PropagatorThread.create_thread(self(), {NotEqual, variables}, store: store)
Process.sleep(10)
refute capture_log([level: :debug], fn ->
Variable.remove(y_var, 0)
end) =~ "Propagation triggered"
## Fix one of variables, this should trigger propagation
assert capture_log([level: :debug], fn ->
Variable.fix(x_var, 1)
Process.sleep(10)
end) =~ "Propagation triggered"
end
end
end