Packages
fixpoint
0.13.2
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
lib/solver/constraints/propagators/or.ex
defmodule CPSolver.Propagator.Or do
use CPSolver.Propagator
@moduledoc """
The propagator for 'or' constraint.
Takes the list of boolean variables.
Constraints to have at least one variable to be resolved to true.
"""
@impl true
def variables(args) do
Enum.map(args, fn x_el -> set_propagate_on(x_el, :fixed) end)
end
@impl true
def arguments(args) do
Arrays.new(args, implementation: Aja.Vector)
end
@impl true
def filter(all_vars, nil, changes) do
case initial_reduction(all_vars) do
:resolved ->
:passive
unfixed ->
(MapSet.size(unfixed) == 0 && fail()) ||
filter(all_vars, %{unfixed: unfixed}, changes)
end
end
def filter(all_vars, %{unfixed: unfixed} = _state, changes) when map_size(changes) == 0 do
Enum.reduce_while(unfixed, unfixed, fn idx, unfixed_acc ->
var = Arrays.get(all_vars, idx)
if fixed?(var) do
if min(var) == 1 do
{:halt, :resolved}
else
{:cont, MapSet.delete(unfixed_acc, idx)}
end
else
{:cont, unfixed_acc}
end
end)
|> finalize(all_vars)
end
def filter(all_vars, %{unfixed: unfixed} = _state, changes) do
Enum.reduce_while(changes, unfixed, fn {var_index, :fixed}, unfixed_acc ->
if MapSet.member?(unfixed_acc, var_index) do
if min(Arrays.get(all_vars, var_index)) == 1 do
{:halt, :resolved}
else
{:cont, MapSet.delete(unfixed_acc, var_index)}
end
else
{:cont, unfixed_acc}
end
end)
|> finalize(all_vars)
end
defp initial_reduction(all_vars) do
Enum.reduce_while(0..(Arrays.size(all_vars) - 1), MapSet.new(), fn var_idx, candidates_acc ->
var = Arrays.get(all_vars, var_idx)
if fixed?(var) do
case min(var) do
0 -> {:cont, candidates_acc}
1 -> {:halt, :resolved}
_other_value -> throw(:not_boolean)
end
else
{:cont, MapSet.put(candidates_acc, var_idx)}
end
end)
end
defp finalize(filtering_result, all_vars) do
case filtering_result do
:resolved ->
:passive
unfixed ->
case MapSet.size(unfixed) do
0 ->
fail()
1 ->
last_var_idx = MapSet.to_list(unfixed) |> List.first()
fix(Arrays.get(all_vars, last_var_idx), 1)
:passive
_more ->
{:state, %{unfixed: unfixed}}
end
end
end
defp fail() do
throw(:fail)
end
end