Packages
fixpoint
0.4.0
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/ets_store.ex
defmodule CPSolver.Store.ETS do
alias CPSolver.DefaultDomain, as: Domain
use CPSolver.ConstraintStore
alias CPSolver.ConstraintStore
@impl true
def create(variables, opts \\ []) do
table_id =
:ets.new(__MODULE__, [:set, :public, read_concurrency: true, write_concurrency: true])
space = Keyword.get(opts, :space)
constraint_graph = Keyword.get(opts, :constraint_graph)
store = %{
space: space,
handle: table_id,
store_impl: __MODULE__,
constraint_graph: constraint_graph
}
Enum.each(
variables,
fn var ->
:ets.insert(
table_id,
{var.id, %{id: var.id, store: store, domain: Domain.new(var.domain), subscriptions: []}}
)
end
)
{:ok, table_id}
end
@impl true
def dispose(_store, _vars) do
:ok
end
@impl true
def get_variables(store) do
:ets.tab2list(store) |> Enum.map(fn {_id, var} -> var.id end)
end
@impl true
def get(store, variable, operation, args \\ []) do
handle_request(:get, store, variable, operation, args)
end
@impl true
def update_domain(store, variable, operation, args) do
handle_request(:update, store, variable, operation, args)
end
@impl true
def on_change(_store, _variable, _change) do
:ok
end
@impl true
def on_no_change(_store, _variable) do
:ok
end
@impl true
def on_fail(_store, _variable) do
:ok
end
@impl true
def subscribe(table, subscriptions) do
subscriptions_by_var =
subscriptions
|> Enum.map(&ConstraintStore.normalize_subscription/1)
|> Enum.group_by(fn s -> s.variable end)
Enum.each(subscriptions_by_var, fn {var_id, subscrs} ->
var_rec = lookup(table, var_id)
updated_rec = %{
var_rec
| subscriptions: (var_rec.subscriptions ++ subscrs) |> Enum.uniq_by(fn rec -> rec.pid end)
}
true = :ets.insert(table, {var_id, updated_rec})
end)
end
defp update_variable_domain(
table,
%{id: var_id} = variable,
domain,
event
) do
:ets.insert(table, {var_id, Map.put(variable, :domain, domain)})
|> tap(fn _ -> ConstraintStore.notify(variable, event) end)
end
@impl true
def domain(table, variable) do
table
|> lookup(variable)
|> Map.get(:domain)
end
def lookup(table, %{id: var_id} = _variable) do
lookup(table, var_id)
end
def lookup(table, var_id) do
table
|> :ets.lookup(var_id)
|> hd
|> elem(1)
end
defp handle_request(kind, table, var_id, operation, args) do
variable = lookup(table, var_id)
handle_request_impl(kind, table, variable, operation, args)
end
def handle_request_impl(_kind, _table, %{domain: :fail} = _variable, _operation, _args) do
:fail
end
def handle_request_impl(:get, _table, %{domain: domain} = _variable, operation, args) do
apply(Domain, operation, [domain | args])
end
def handle_request_impl(:update, table, %{domain: domain} = variable, operation, args) do
case apply(Domain, operation, [domain | args]) do
:fail ->
update_variable_domain(table, variable, :fail, :fail)
:fail
:no_change ->
:no_change
{domain_change, new_domain} ->
update_variable_domain(table, variable, new_domain, domain_change)
domain_change
end
end
end