Packages
fixpoint
0.8.23
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/objective/objective.ex
defmodule CPSolver.Objective do
alias CPSolver.Objective.Propagator, as: ObjectivePropagator
alias CPSolver.Variable.Interface
import CPSolver.Variable.View.Factory
import CPSolver.Utils
@spec minimize(Variable.t() | View.t()) :: %{
:propagator => Propagator.t(),
:variable => Variable.t() | View.t(),
:bound_handle => reference()
}
def minimize(variable) do
bound_handle = init_bound_handle()
propagator = ObjectivePropagator.new(variable, bound_handle)
%{
propagator: propagator,
variable: variable,
bound_handle: bound_handle,
target: :minimize
}
end
def maximize(variable) do
minimize(minus(variable))
|> Map.put(:target, :maximize)
end
def get_bound(%{bound_handle: handle}) do
get_bound(handle)
end
def get_bound(handle) when is_reference(handle) do
(on_primary_node?(handle) && get_bound_impl(handle)) || remote_call(handle, :get_bound_impl)
end
def get_bound_impl(handle) when is_reference(handle) do
:atomics.get(handle, 1)
end
def update_bound(handle, value) when is_reference(handle) do
(on_primary_node?(handle) && update_bound_impl(handle, value)) ||
remote_call(handle, :update_bound_impl, [value])
end
def update_bound_impl(bound_handle, value) do
case :atomics.get(bound_handle, 1) do
prev_value when prev_value > value ->
case :atomics.compare_exchange(bound_handle, 1, prev_value, value) do
:ok ->
value
_changed_in_between ->
update_bound_impl(bound_handle, value)
end
prev_value ->
# previous value lesser than the proposed one - keep
prev_value
end
end
def tighten(%{variable: variable, bound_handle: handle} = _objective) do
tighten(variable, handle)
end
def tighten(variable, bound_handle) do
update_bound(bound_handle, Interface.max(variable) - 1)
end
def init_bound_handle() do
ref = :atomics.new(1, signed: true)
reset_bound(ref)
ref
end
def reset_bound(%{bound_handle: ref} = _objective) do
reset_bound(ref)
end
def reset_bound(handle) when is_reference(handle) do
(on_primary_node?(handle) && reset_bound_impl(handle)) ||
remote_call(handle, :reset_bound_impl)
end
def reset_bound_impl(ref) when is_reference(ref) do
:atomics.put(ref, 1, :atomics.info(ref).max)
end
def get_objective_value(%{target: target, bound_handle: handle} = _objective) do
(get_bound(handle) + 1) * ((target == :minimize && 1) || -1)
end
defp remote_call(ref, fun_name, args \\ []) when is_reference(ref) and is_atom(fun_name) do
:erpc.call(node(ref), __MODULE__, fun_name, [ref | args])
end
end