Packages
fixpoint
0.4.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
test/space/space_test.exs
defmodule CPSolverTest.Space do
use ExUnit.Case
describe "Computation space" do
alias CPSolver.IntVariable, as: Variable
alias CPSolver.Space, as: Space
alias CPSolver.Propagator.NotEqual
alias CPSolver.Shared
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.new(x, y), NotEqual.new(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 =
Enum.map(threads, fn {_id, thread} -> thread.thread end)
assert Enum.all?(thread_pids, fn pid -> is_pid(pid) end)
end
test "stable space" do
%{space: space} = create_stable_space(solution_handler: test_solution_handler())
Process.sleep(100)
refute Process.alive?(space)
solutions =
Enum.map(1..2, fn _ ->
receive do
{:solution, sol} -> sol
end
end)
# 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)
end
test "solved space" do
%{space: space} = create_solved_space()
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 -> Variable.fixed?(var) 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.new(x, y), NotEqual.new(y, z)]
Process.flag(:trap_exit, true)
{:ok, space} = Space.create(variables, propagators)
Process.sleep(50)
refute Process.alive?(space)
end
test "solution handler as function" do
solution_handler = test_solution_handler()
## Create a space with the solution handler as a function
%{variables: space_variables} =
create_solved_space(solution_handler: solution_handler)
Process.sleep(10)
## Check the solution against the store
store_vars =
Map.new(space_variables, fn v -> {v.id, Variable.min(v)} end)
assert_receive {:solution, ^store_vars}, 10
end
test "solution handler as a module" do
solution_handler = test_solution_handler()
## Create a space with the solution handler as a function
%{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)
|> Map.new()
assert_receive {:solution, ^store_vars}, 10
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.new(x, y), NotEqual.new(y, z)]
{:ok, space} =
Space.create(
variables,
propagators,
space_opts
|> Keyword.put(:solver_data, Shared.init_shared_data())
|> Keyword.put(:keep_alive, true)
)
{_, space_data} = :sys.get_state(space)
%{space: space, propagators: propagators, variables: space_data.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.new(x, y), NotEqual.new(y, z)]
{:ok, space} =
Space.create(
variables,
propagators,
space_opts
|> Keyword.put(:solver_data, Shared.init_shared_data(self()))
)
{_, space_data} = :sys.get_state(space)
%{space: space, propagators: propagators, variables: space_data.variables, domains: values}
end
defp test_solution_handler() do
target_pid = self()
## The solution will be send to the current process
fn solution ->
send(target_pid, {:solution, solution})
end
end
end
end