defmodule CPSolver.Propagator.NotEqual do use CPSolver.Propagator def new(x, y, offset \\ 0) do new([x, y, offset]) end @impl true def variables(args) do args |> Propagator.default_variables_impl() |> Enum.map(fn var -> set_propagate_on(var, :fixed) end) end @impl true def filter([x, y], state, changes) do filter([x, y, 0], state, changes) end def filter([x, y, offset], _state, _changes) do filter_impl(x, y, offset) end def filter_impl(x, y, offset \\ 0) def filter_impl(x, c, offset) when is_integer(c) do remove(x, c + offset) :passive end def filter_impl(x, y, offset) do cond do fixed?(x) -> remove(y, plus(min(x), -offset)) :passive fixed?(y) -> remove(x, plus(min(y), offset)) :passive true -> :stable end end @impl true def failed?([x, y, offset], _state) do fixed?(x) && fixed?(y) && min(x) == plus(min(y), offset) end @impl true def entailed?([x, y, offset], _state) do ## x != y holds on the condition below fixed?(x) && fixed?(y) && min(x) != plus(min(y), offset) end end