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
test/space/space_test.exs
defmodule CPSolverTest.Space do
use ExUnit.Case
import ExUnit.CaptureLog
import CPSolver.Test.Helpers
describe "Computation space" do
alias CPSolver.Store.Registry, as: Store
alias CPSolver.IntVariable, as: Variable
alias CPSolver.Space, as: Space
alias CPSolver.Propagator.NotEqual
alias CPSolver.Solution
alias CPSolver.Utils
test "create space" do
x_values = 1..10
y_values = -5..5
z_values = 0..2
values = [x_values, y_values, z_values]
[x, y, z] = variables = Enum.map(values, fn d -> Variable.new(d) end)
propagators = [{NotEqual, [x, y]}, {NotEqual, [y, z]}]
{:ok, space} = Space.create(variables, propagators)
# Process.sleep(1)
{state,
%{variables: space_variables, propagator_threads: threads} =
_data} = Space.get_state_and_data(space)
assert state == :propagating
assert length(propagators) == map_size(threads)
assert length(variables) == length(space_variables)
thread_pids =
[x_y_propagator_pid, y_z_propagator_pid] =
Enum.map(threads, fn {_id, thread} -> thread.thread end)
assert Enum.all?(thread_pids, fn pid -> is_pid(pid) end)
# Check subscriptions
## propagators -> variables
[x_space, y_space, z_space] = space_variables
assert x_y_propagator_pid in CPSolver.Variable.subscribers(x_space)
assert x_y_propagator_pid in CPSolver.Variable.subscribers(y_space)
assert y_z_propagator_pid in CPSolver.Variable.subscribers(y_space)
assert y_z_propagator_pid in CPSolver.Variable.subscribers(z_space)
## space -> propagators
assert Enum.all?(threads, fn {thread_id, _thread} ->
space in Utils.subscribers({:propagator, thread_id})
end)
end
test "stable space" do
%{space: space} = create_stable_space()
Process.sleep(100)
refute Process.alive?(space)
solutions =
Enum.map(1..2, fn _ ->
receive do
{:solution, sol} -> sol
end
end)
node_creations =
Enum.reduce(1..1, 0, fn _, acc ->
receive do
{:nodes, nodes} -> length(nodes) + acc
end
end)
assert_received({:shutdown_space, _pid})
assert_received({:shutdown_space, _pid})
assert_received({:shutdown_space, _pid})
# Only 2 solutions and one first_fail distribution (2 nodes) , nothing else has come in the mailbox
refute_receive _msg, 10
# For all solutions, constraints (x != y and y != z) are satisfied.
assert Enum.all?(solutions, fn variables ->
[x, y, z] = Enum.map(variables, fn {_id, value} -> value end)
x != y && y != z
end)
assert node_creations == 2
end
test "solved space" do
%{space: space} = create_solved_space()
{state, _data} = Space.get_state_and_data(space)
assert state == :propagating
Process.sleep(10)
{state, %{variables: space_variables} = _data} = Space.get_state_and_data(space)
assert state == :solved
## Check if all space variables are fixed
assert Enum.all?(space_variables, fn var -> Store.get(space, var, :fixed?) end)
end
test "failing space" do
x_values = 1..1
y_values = 1..2
z_values = 2..2
values = [x_values, y_values, z_values]
[x, y, z] = variables = Enum.map(values, fn d -> Variable.new(d) end)
propagators = [{NotEqual, [x, y]}, {NotEqual, [y, z]}]
{:ok, space} = Space.create(variables, propagators)
Process.sleep(10)
refute Process.alive?(space)
end
test "solution handler as function" do
target_pid = self()
## The solution will be send to the current process
solution_handler = fn solution ->
send(target_pid, Enum.sort_by(solution, fn {var, _value} -> var end))
end
## Create a space with the solution handler as a function
%{space: space, variables: space_variables} =
create_solved_space(solution_handler: solution_handler)
Process.sleep(10)
## Check the solution against the store
store_vars =
Enum.map(space_variables, fn v -> {v.id, Variable.min(v)} end)
|> Enum.sort_by(fn {var, _value} -> var end)
assert_receive ^store_vars, 10
end
test "solution handler as a module" do
solution_handler = Solution.default_handler()
## Create a space with the solution handler as a function
log =
capture_log(fn ->
_ = create_solved_space(solution_handler: solution_handler)
Process.sleep(10)
end)
assert log =~ "Solution found"
assert number_of_occurences(log, "<- 2") == 2
assert number_of_occurences(log, "<- 1") == 1
end
test "distribute space" do
%{space: _space} = create_stable_space()
Process.sleep(10)
:to_complete
end
defp create_solved_space(space_opts \\ []) do
x_values = 1..2
y_values = 1..1
z_values = 1..2
values = [x_values, y_values, z_values]
[x, y, z] = variables = Enum.map(values, fn d -> Variable.new(d) end)
propagators = [{NotEqual, [x, y]}, {NotEqual, [y, z]}]
{:ok, space} = Space.create(variables, propagators, space_opts)
%{space: space, propagators: propagators, variables: variables}
end
defp create_stable_space(space_opts \\ []) do
x_values = 1..2
y_values = 1..2
z_values = 1..2
values = [x_values, y_values, z_values]
[x, y, z] = variables = Enum.map(values, fn d -> Variable.new(d) end)
propagators = [{NotEqual, [x, y]}, {NotEqual, [y, z]}]
{:ok, space} = Space.create(variables, propagators, space_opts)
%{space: space, propagators: propagators, variables: variables, domains: values}
end
end
end