Packages
fixpoint
0.1.0
0.22.2
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/store/registry_store.ex
defmodule CPSolver.Store.Registry do
alias CPSolver.ConstraintStore, as: Store
alias CPSolver.DefaultDomain, as: Domain
alias CPSolver.Variable
alias CPSolver.Utils
require Logger
@behaviour Store
@variable_registry CPSolver.Store.Registry
@impl true
@spec create(any(), [Variable.t()]) :: {:ok, [any()]}
def create(space, variables) do
{:ok,
Enum.map(
variables,
fn var ->
{:ok, _pid} =
Agent.start(
fn ->
Domain.new(var.domain)
|> tap(fn _ ->
Process.put(:fire_on_no_change, true)
{:ok, _} = Registry.register(@variable_registry, var.id, space)
end)
end,
name: variable_proc_id(var)
)
%{}
|> Map.put(:id, var.id)
|> Map.put(:space, space)
end
)}
end
@impl true
def dispose(_space, variable) do
Agent.stop(variable_proc_id(variable))
end
def variable_proc_id(variable) do
{:global, variable.id}
end
@impl true
def get(_store, var, operation, args \\ []) do
Agent.get(
variable_proc_id(var),
fn
:fail ->
:fail
|> tap(fn _ -> handle_op_on_failed_var(var, operation) end)
domain ->
apply(Domain, operation, [domain | args])
end
)
end
@impl true
def domain(_space, var) do
Agent.get(variable_proc_id(var), fn
:fail ->
:fail
|> tap(fn _ -> handle_op_on_failed_var(var, :domain) end)
domain ->
domain
end)
end
@impl true
def update(_store, var, operation, args \\ []) do
Agent.update(
variable_proc_id(var),
fn
:fail ->
:fail
|> tap(fn _ -> handle_op_on_failed_var(var, operation) end)
domain ->
case apply(Domain, operation, [domain | args]) do
:fail ->
:fail
|> tap(fn _ -> handle_failure(var) end)
:none ->
domain
|> tap(fn _ -> handle_domain_no_change(var) end)
{domain_change, new_domain} ->
new_domain
|> tap(fn _ -> handle_domain_change(domain_change, var, new_domain) end)
end
end
)
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_op_on_failed_var(var, operation) do
Logger.warning(
"Attempt to request #{inspect(operation)} on failed variable #{inspect(var.id)}"
)
end
defp handle_domain_no_change(var) do
## Publish no_change only once between domain change events
fire_on_no_change?() &&
publish(var, {:no_change, var.id})
|> tap(fn _ ->
Logger.debug("No change for variable #{inspect(var.id)}")
Process.put(:fire_on_no_change, false)
end)
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)}")
Process.put(:fire_on_no_change, true)
end)
end
defp publish(var, message) do
Utils.publish({:variable, var.id}, message)
end
defp fire_on_no_change?() do
Process.get(:fire_on_no_change)
end
@impl true
@spec get_variables(any()) :: [reference()]
def get_variables(space) do
Registry.select(CPSolver.Store.Registry, [
{{:"$1", :_, :"$3"}, [{:==, :"$3", space}], [:"$1"]}
])
end
end