Packages
fixpoint
0.1.3
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/variables/registry_variable.ex
defmodule CPSolver.Variable.Agent do
alias CPSolver.DefaultDomain, as: Domain
alias CPSolver.Store.Registry, as: StoreRegistry
alias CPSolver.Variable
alias CPSolver.Utils
require Logger
@behaviour GenServer
def create(%{id: id} = variable) do
{:ok, _} = Registry.register(StoreRegistry, id, self())
{:ok, _pid} =
GenServer.start_link(__MODULE__, variable, name: StoreRegistry.variable_proc_id(variable))
end
def dispose(variable) do
topic = {variable, variable.id}
Enum.each(Utils.subscribers(topic), fn s -> Utils.unsubscribe(s, topic) end)
GenServer.cast(StoreRegistry.variable_proc_id(variable), :dispose)
end
def alive?(variable) do
case GenServer.whereis(StoreRegistry.variable_proc_id(variable)) do
nil -> false
pid -> Process.alive?(pid)
end
end
@impl true
@spec init(atom | %{:domain => any, optional(any) => any}) :: {:ok, :gb_sets.set(any)}
def init(variable) do
{:ok, Domain.new(variable.domain)}
end
def operation(var, operation, args \\ []) do
GenServer.call(StoreRegistry.variable_proc_id(var), {var, operation, args})
end
@impl true
def handle_call({var, op, _args}, _from, :fail) do
handle_op_on_failed_var(var, op)
{:reply, :fail, :fail}
end
## Read ops
def handle_call({_var, :domain, _args}, _from, domain) do
{:reply, domain, domain}
end
def handle_call({_var, op, args}, _from, domain)
when op in [:size, :fixed?, :min, :max, :contains?] do
{:reply, apply(Domain, op, [domain | args]), domain}
end
## Write ops
def handle_call({var, op, args}, _from, domain)
when op in [:remove, :removeAbove, :removeBelow, :fix] do
{result, updated_domain} =
case apply(Domain, op, [domain | args]) do
:fail ->
{:fail, :fail}
|> tap(fn _ -> handle_failure(var) end)
:none ->
{:no_change, domain}
|> tap(fn _ -> handle_domain_no_change(var) end)
{domain_change, new_domain} ->
{domain_change, new_domain}
|> tap(fn _ -> handle_domain_change(domain_change, var, new_domain) end)
end
{:reply, result, updated_domain}
end
@impl true
def handle_cast(:dispose, state) do
{:stop, :normal, state}
end
defp handle_op_on_failed_var(var, operation) do
Logger.warning(
"Attempt to request #{inspect(operation)} on failed variable #{inspect(var.id)}"
)
end
defp handle_failure(var) do
Logger.debug("Failure for variable #{inspect(var.id)}")
## TODO: notify space (and maybe don't notify propagators)
publish(var, {:fail, var.id})
end
defp handle_domain_no_change(_var) do
:ok
end
defp handle_domain_change(domain_change, var, _domain) do
publish(var, {domain_change, var.id})
|> tap(fn _ ->
Logger.debug("Domain change (#{domain_change}) for #{inspect(var.id)}")
maybe_unsubscribe_all(domain_change, var)
end)
end
defp publish(var, message) do
Variable.publish(var, message)
end
defp maybe_unsubscribe_all(:fixed, var) do
Enum.each(Variable.subscribers(var), fn pid -> Variable.unsubscribe(pid, var) end)
end
defp maybe_unsubscribe_all(_, _var) do
:ok
end
end