alias CPSolver.Variable.Interface
alias CPSolver.Variable
alias CPSolver.Variable.View
alias CPSolver.DefaultDomain, as: Domain
defimpl Interface, for: Variable do
def id(var), do: var.id
def variable(var), do: var
def map(_var, value), do: value
def domain(var), do: Variable.domain(var)
def iterator(var, opts \\ []), do: Variable.iterator(var, opts)
def size(var), do: Variable.size(var)
def min(var), do: Variable.min(var)
def max(var), do: Variable.max(var)
def fixed?(var), do: Variable.fixed?(var)
def contains?(var, val), do: Variable.contains?(var, val)
def remove(var, val), do: Variable.remove(var, val)
def removeAbove(var, val), do: Variable.removeAbove(var, val)
def removeBelow(var, val), do: Variable.removeBelow(var, val)
def fix(var, val), do: Variable.fix(var, val)
def update(var, field, value), do: Map.put(var, field, value)
end
defimpl Interface, for: View do
def id(view), do: view.variable.id
def variable(view), do: view.variable
def map(view, value), do: View.get_mapper(view).(value)
def domain(view), do: View.domain(view)
def iterator(var, opts \\ []), do: View.iterator(var, opts)
def size(view), do: View.size(view)
def min(view), do: View.min(view)
def max(view), do: View.max(view)
def fixed?(view), do: View.fixed?(view)
def contains?(view, val), do: View.contains?(view, val)
def remove(view, val), do: View.remove(view, val)
def removeAbove(view, val), do: View.removeAbove(view, val)
def removeBelow(view, val), do: View.removeBelow(view, val)
def fix(view, val), do: View.fix(view, val)
def update(view, field, value) do
updated_variable = Map.put(variable(view), field, value)
Map.put(view, :variable, updated_variable)
end
end
defimpl Interface, for: Integer do
def variable(_any), do: nil
def id(_val), do: nil
defdelegate map(val, mapper), to: Domain
def iterator(var, _opts), do: List.wrap(var)
def domain(val), do: val
defdelegate size(val), to: Domain
defdelegate min(val), to: Domain
defdelegate max(val), to: Domain
defdelegate fixed?(val), to: Domain
defdelegate contains?(val, value), to: Domain
defdelegate remove(val, remove_val), to: Domain
defdelegate removeAbove(val, removeAbove), to: Domain
defdelegate removeBelow(val, removeBelow), to: Domain
defdelegate fix(value, fixed_value), to: Domain
def update(val, _field, _value), do: val
end
defimpl Interface, for: Any do
def variable(_any), do: nil
def id(non_var), do: not_supported(:id, non_var)
def map(non_var, _value), do: non_var
def iterator(non_var, _opts), do: not_supported(:domain, non_var)
def domain(non_var), do: not_supported(:domain, non_var)
def size(non_var), do: not_supported(:size, non_var)
def min(non_var), do: not_supported(:min, non_var)
def max(non_var), do: not_supported(:max, non_var)
def fixed?(_), do: true
def contains?(non_var, _val), do: not_supported(:contains, non_var)
def remove(non_var, _val), do: not_supported(:remove, non_var)
def removeAbove(non_var, _val), do: not_supported(:removeAbove, non_var)
def removeBelow(non_var, _val), do: not_supported(:removeBelow, non_var)
def fix(non_var, _val), do: not_supported(:fix, non_var)
def update(non_var, _field, _value), do: not_supported(:update, non_var)
defp not_supported(non_var, op) do
throw({:operation_not_supported, op, for: non_var})
end
end
defmodule CPSolver.Variable.Interface.ThrowIfFails do
alias CPSolver.Variable.Interface
@behaviour Interface
defdelegate id(var), to: Interface
defdelegate variable(var), to: Interface
defdelegate map(var, value), to: Interface
def iterator(_var, _opts), do: :ignore
def domain(var), do: handle_fail(Interface.domain(var), var)
def size(var), do: handle_fail(Interface.size(var), var)
def min(var), do: handle_fail(Interface.min(var), var)
def max(var), do: handle_fail(Interface.max(var), var)
def fixed?(var), do: handle_fail(Interface.fixed?(var), var)
def contains?(var, val), do: handle_fail(Interface.contains?(var, val), var)
def remove(var, val), do: handle_fail(Interface.remove(var, val), var)
def removeAbove(var, val), do: handle_fail(Interface.removeAbove(var, val), var)
def removeBelow(var, val), do: handle_fail(Interface.removeBelow(var, val), var)
def fix(var, val), do: handle_fail(Interface.fix(var, val), var)
def update(var, field, value), do: handle_fail(Interface.update(var, field, value), var)
defp handle_fail(:fail, _var), do: throw(:fail)
defp handle_fail(result, _var), do: result
end