Packages
fixpoint
0.7.5
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/store/store_test.exs
defmodule CPSolverTest.Store do
use ExUnit.Case
describe "Store" do
alias CPSolver.ConstraintStore
alias CPSolver.IntVariable, as: Variable
test "create variables in the space" do
v1_values = 1..10
v2_values = -5..5
values = [v1_values, v2_values]
variables = Enum.map(values, fn d -> Variable.new(d) end)
{:ok, bound_vars, _store} = ConstraintStore.create_store(variables)
## Bound vars have space and ids assigned
assert Enum.all?(bound_vars, fn var -> var end)
end
test "Store variables" do
v1_values = 1..10
v2_values = -5..5
v3_values = [0, 3, 6, 9, -1]
values = [v1_values, v2_values, v3_values]
variables = Enum.map(values, fn d -> Variable.new(d) end)
{:ok, bound_vars, store} = ConstraintStore.create_store(variables)
store_var_ids = ConstraintStore.get_variables(store)
assert length(bound_vars) == store_var_ids |> length
## Make sure that the sets of bound vars and store vars coincide.
assert Enum.all?(
Enum.zip(Enum.sort(store_var_ids), Enum.sort_by(bound_vars, fn v -> v.id end)),
fn {store_var, bound_var} ->
store_var == bound_var.id
end
)
end
test "GET operations" do
v1_values = 1..10
v2_values = -5..5
v3_values = 1..1
values = [v1_values, v2_values, v3_values]
variables = Enum.map(values, fn d -> Variable.new(d) end)
{:ok, bound_vars, store} = ConstraintStore.create_store(variables)
# Min
assert Enum.all?(Enum.zip(bound_vars, values), fn {var, vals} ->
ConstraintStore.get(store, var, :min) == Enum.min(vals)
end)
# Max
assert Enum.all?(Enum.zip(bound_vars, values), fn {var, vals} ->
ConstraintStore.get(store, var, :max) == Enum.max(vals)
end)
# Size
assert Enum.all?(Enum.zip(bound_vars, values), fn {var, vals} ->
ConstraintStore.get(store, var, :size) == Range.size(vals)
end)
# Fixed?
assert Enum.all?(Enum.zip(bound_vars, values), fn {var, vals} ->
ConstraintStore.get(store, var, :fixed?) == (Range.size(vals) == 1)
end)
# Contains?
assert Enum.all?(Enum.zip(bound_vars, values), fn {var, vals} ->
Enum.all?(vals, fn val -> ConstraintStore.get(store, var, :contains?, [val]) end)
end)
end
test "UPDATE operations" do
v1_values = 1..10
v2_values = -5..5
v3_values = 1..2
values = [v1_values, v2_values, v3_values]
variables = Enum.map(values, fn d -> Variable.new(d) end)
{:ok, bound_vars, store} = ConstraintStore.create_store(variables, space: nil)
[v1, v2, v3] = bound_vars
# remove
refute Enum.any?(bound_vars, fn var ->
assert ConstraintStore.update(store, var, :remove, [1]) in [
:domain_change,
:min_change,
:fixed
]
ConstraintStore.get(store, var, :contains?, [1])
end)
assert ConstraintStore.get(store, v3, :fixed?)
assert ConstraintStore.get(store, v3, :min) == 2
# Remove on fixed var
assert :fail == ConstraintStore.update(store, v3, :remove, [2])
assert :fail == ConstraintStore.get(store, v3, :contains?, [1])
assert :fail == ConstraintStore.update(store, v3, :remove, [2])
assert :fail == ConstraintStore.get(store, v3, :size)
# removeAbove
:max_change = ConstraintStore.update(store, v1, :removeAbove, [5])
assert ConstraintStore.get(store, v1, :max) == 5
assert ConstraintStore.get(store, v1, :min) == 2
# removeBelow
:min_change = ConstraintStore.update(store, v2, :removeBelow, [0])
assert ConstraintStore.get(store, v2, :max) == 5
assert ConstraintStore.get(store, v2, :min) == 0
# fix variable with value outside the domain
assert ConstraintStore.update(store, v1, :fix, [0]) == :fail
assert ConstraintStore.get(store, v1, :max) == :fail
:fixed = ConstraintStore.update(store, v2, :fix, [0])
assert ConstraintStore.get(store, v2, :max) == 0
end
test "registers fixed variables" do
v1_values = 1..10
v2_values = 0..0
v3_values = -5..5
v4_values = 1..1
values = [v1_values, v2_values, v3_values, v4_values]
variables = Enum.map(values, fn d -> Variable.new(d) end)
{:ok, [v1_var, v2_var, v3_var, v4_var], _store} = ConstraintStore.create_store(variables)
refute ConstraintStore.fixed?(v1_var) || ConstraintStore.fixed?(v3_var)
assert ConstraintStore.fixed?(v2_var) && ConstraintStore.fixed?(v4_var)
end
test "detects conflicts on fixing already fixed variables" do
v1_values = 1..10
v2_values = 0..5
values = [v1_values, v2_values]
variables = Enum.map(values, fn d -> Variable.new(d) end)
{:ok, [v1_var, v2_var], _store} = ConstraintStore.create_store(variables)
## Fixing to different values concurrently
assert :fail ==
Task.async_stream(1..10, fn i -> ConstraintStore.update_fixed(v1_var, i) end)
|> Enum.reduce_while(
:ok,
fn
{:ok, :fail}, _acc -> {:halt, :fail}
{:ok, :fixed}, _acc -> {:cont, :ok}
end
)
## Fixing to the same value concurrently
assert :fixed ==
Task.async_stream(1..10, fn _i -> ConstraintStore.update_fixed(v2_var, 0) end)
|> Enum.reduce_while(
:ok,
fn
{:ok, :fail}, _acc -> {:halt, :fail}
{:ok, :fixed}, _acc -> {:cont, :fixed}
end
)
assert ConstraintStore.fixed?(v2_var)
## Fixing an already fixed variable to the same value
assert :fixed == ConstraintStore.update_fixed(v2_var, 0)
## Fixing an already fixed variable to a different value
assert :fail == ConstraintStore.update_fixed(v2_var, 1)
end
end
end