Packages
fixpoint
0.8.9
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/solver/cpsolver_test.exs
defmodule CpSolverTest do
use ExUnit.Case
alias CPSolver.IntVariable
alias CPSolver.Model
alias CPSolver.Constraint.NotEqual
alias CPSolver.Examples.Queens
alias CPSolver.Examples.Knapsack
@solution_handler_test_file "solution_handler_test.tmp"
setup do
File.touch(@solution_handler_test_file)
on_exit(fn -> File.rm(@solution_handler_test_file) end)
:ok
end
test "Solves CSP with 2 variables and a single constraint" do
x = IntVariable.new([1, 2])
y = IntVariable.new([0, 1])
model =
Model.new(
[x, y],
[NotEqual.new(x, y)]
)
{:ok, solver} = CPSolver.solve(model)
Process.sleep(100)
assert CPSolver.statistics(solver).failure_count == 0
## Note: there are 2 "first fail" distributions:
## 1. Variable 'x' triggers distribution into 2 spaces - (x: 1, y: [0, 1]) and (x: 2, y: [0, 1])).
## 2. First space produces solution (x: 1, y: 0)
## 3. Second space triggers distribution into 2 spaces - (x: 2, y: 0) and (x: 2, y: 1)
## 4. These 2 spaces produce remaining solutions.
## 5. There have been 5 spaces - top one, and 4 as described above, which corresponds
## to 5 nodes.
assert CPSolver.statistics(solver).node_count == 5
assert CPSolver.statistics(solver).solution_count == 3
solutions =
solver
|> CPSolver.solutions()
|> Enum.sort_by(fn [x, y] -> x + y end)
assert solutions == [[1, 0], [2, 0], [2, 1]]
end
test "Stops on max_solutions reached" do
max_solutions = 2
{:ok, solver} = Queens.solve(5, stop_on: {:max_solutions, max_solutions})
Process.sleep(100)
assert CPSolver.complete?(solver)
end
test "Synchronous solver" do
{:ok, result} = CPSolver.solve_sync(Queens.model(8))
assert result.statistics.solution_count == 92
## No active nodes - solving is done
assert result.statistics.active_node_count == 0
end
test "Solver status" do
## N-Queens for n = 3 is unatisfiable
{:ok, res} = CPSolver.solve_sync(Queens.model(3))
assert res.status == :unsatisfiable
## N-Queens for n = 4
{:ok, res} = CPSolver.solve_sync(Queens.model(4))
assert res.status == :all_solutions
## N-Queens for n = 8, async solving
{:ok, solver} = CPSolver.solve(Queens.model(8))
Process.sleep(10)
{:running, _} = CPSolver.status(solver)
Process.sleep(100)
assert :all_solutions = CPSolver.status(solver)
## Status for optimization problem
{:ok, solver} = CPSolver.solve(Knapsack.model("data/knapsack/ks_4_0"))
Process.sleep(1)
{:running, info} = CPSolver.status(solver)
assert info[:objective]
Process.sleep(100)
assert {:optimal, [objective: 19]} == CPSolver.status(solver)
end
test "Solution handler" do
x = IntVariable.new([1, 2])
y = IntVariable.new([0, 1])
model =
Model.new(
[x, y],
[NotEqual.new(x, y)]
)
{:ok, res} =
CPSolver.solve_sync(model,
solution_handler: fn solution ->
File.write!(@solution_handler_test_file, :erlang.term_to_binary(solution) <> "\n", [
:append
])
end
)
Process.sleep(100)
solutions_from_file =
@solution_handler_test_file
|> File.read!()
|> String.trim()
|> String.split("\n")
|> Enum.map(fn binary -> :erlang.binary_to_term(binary) end)
## Make {ref, value} list off the solver solutions
## to be able to compare with the output of solutuon handler
solver_solutions =
Enum.map(res.solutions, fn sol -> Enum.zip(res.variables, sol) end)
|> List.flatten()
|> Enum.sort()
handler_solutions = List.flatten(solutions_from_file) |> Enum.sort()
assert solver_solutions == handler_solutions
end
end