defmodule CPSolver.Search.Utils do alias CPSolver.Variable.UnfixedTracker, as: Tracker ## Pick all minimal elements according to given minimization function def minimals(data, min_by_fun) do %{initial: initial, reducer_fun: reducer_fun} = minimals_reducer(min_by_fun) Tracker.iterate(data, initial, reducer_fun, false) |> elem(0) end ## Pick all maximal elements according to given maximization function def maximals(data, max_by_fun) do %{initial: initial, reducer_fun: reducer_fun} = maximals_reducer(max_by_fun) Tracker.iterate(data, initial, reducer_fun, false) |> elem(0) end def minimals_reducer(min_by_fun) do make_reducer( {[], nil}, fn var, {minimals_acc, current_min} = acc -> val = min_by_fun.(var) cond do is_nil(current_min) || val < current_min -> {[var], val} is_nil(val) || val > current_min -> acc val == current_min -> {[var | minimals_acc], current_min} end end) end def maximals_reducer(max_by_fun) do make_reducer({ [], -1}, fn var, {maximals_acc, current_max} = acc -> val = max_by_fun.(var) cond do is_nil(val) || val < current_max -> acc val > current_max -> {[var], val} val == current_max -> {[var | maximals_acc], val} end end ) end def make_reducer(initial, reducer_fun) do %{initial: initial, reducer_fun: reducer_fun} end end