Packages
fixpoint
0.6.1
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/core/shared.ex
defmodule CPSolver.Shared do
def init_shared_data(solver_pid \\ self()) do
%{
caller: self(),
sync_mode: false,
solver_pid: solver_pid,
statistics:
:ets.new(__MODULE__, [:set, :public, read_concurrency: true, write_concurrency: false])
|> tap(fn stats_ref -> :ets.insert(stats_ref, {:stats, 0, 0, 0, 0}) end),
solutions:
:ets.new(__MODULE__, [:set, :public, read_concurrency: true, write_concurrency: true]),
active_nodes:
:ets.new(__MODULE__, [:set, :public, read_concurrency: true, write_concurrency: false]),
complete_flag: init_complete_flag()
}
end
def complete?(%{complete_flag: complete_flag} = _solver) do
:persistent_term.get(complete_flag, true)
end
def set_complete(%{complete_flag: complete_flag, caller: caller, sync_mode: sync?} = solver) do
:persistent_term.put(complete_flag, true)
|> tap(fn _ -> sync? && send(caller, {:solver_completed, complete_flag}) end)
|> tap(fn _ -> CPSolver.stop_spaces(solver) end)
end
defp init_complete_flag() do
make_ref()
|> tap(fn ref -> :persistent_term.put(ref, false) end)
end
@active_node_count_pos 2
@failure_count_pos 3
@solution_count_pos 4
@node_count_pos 5
def add_active_spaces(
%{statistics: stats_table, active_nodes: active_nodes_table} = _solver,
spaces
) do
try do
incr = length(spaces)
update_stats_counters(stats_table, [{@active_node_count_pos, incr}, {@node_count_pos, incr}])
Enum.each(spaces, fn n -> :ets.insert(active_nodes_table, {n, n}) end)
rescue
_e -> :ok
end
end
def remove_space(
%{statistics: stats_table, active_nodes: active_nodes_table} = solver,
space,
reason
) do
try do
update_stats_counters(stats_table, [
{@active_node_count_pos, -1} | update_stats_ops(reason)
])
:ets.delete(active_nodes_table, space)
## The solving is done when there is no more active nodes
:ets.info(active_nodes_table, :size) == 0 && set_complete(solver)
rescue
_e -> :ok
end
end
def cleanup(%{solver_pid: solver_pid, complete_flag: complete_flag} = solver) do
Enum.each([:solutions, :statistics, :active_nodes], fn item ->
Map.get(solver, item) |> :ets.delete()
end)
Process.alive?(solver_pid) && GenServer.stop(solver_pid)
:persistent_term.erase(complete_flag)
end
def stop_spaces(solver) do
Enum.each(active_nodes(solver), fn space ->
Process.alive?(space) && Process.exit(space, :normal)
end)
end
defp update_stats_ops(:failure) do
[{@failure_count_pos, 1}]
end
defp update_stats_ops(:solved) do
[]
end
defp update_stats_ops(_) do
[]
end
defp update_stats_counters(stats_table, update_ops) do
:ets.update_counter(stats_table, :stats, update_ops)
end
def statistics(solver) do
[{:stats, active_node_count, failure_count, solution_count, node_count}] =
:ets.lookup(solver.statistics, :stats)
%{
active_node_count: active_node_count,
failure_count: failure_count,
solution_count: solution_count,
node_count: node_count
}
end
def solutions(%{solutions: solution_table} = _solver) do
try do
solution_table
|> :ets.tab2list()
|> Enum.map(fn {_ref, solution} ->
Enum.map(solution, fn {_var, value} ->
value
end)
end)
rescue
_e -> []
end
end
def active_nodes(%{active_nodes: active_nodes_table} = _solver) do
try do
:ets.tab2list(active_nodes_table) |> Enum.map(fn {_k, n} -> n end)
rescue
_e -> []
end
end
def add_failure(%{statistics: stats_table} = _solver) do
update_stats_counters(stats_table, [{@failure_count_pos, 1}])
end
def add_solution(%{solutions: solution_table, statistics: stats_table} = _solver, solution) do
try do
update_stats_counters(stats_table, [{@solution_count_pos, 1}])
:ets.insert(solution_table, {make_ref(), solution})
rescue
_e -> :ok
end
end
end