diff --git a/solver/src/main/java/org/chocosolver/solver/search/strategy/selectors/values/IntDomainBest.java b/solver/src/main/java/org/chocosolver/solver/search/strategy/selectors/values/IntDomainBest.java index 81790068cc..79f2ffc726 100644 --- a/solver/src/main/java/org/chocosolver/solver/search/strategy/selectors/values/IntDomainBest.java +++ b/solver/src/main/java/org/chocosolver/solver/search/strategy/selectors/values/IntDomainBest.java @@ -18,6 +18,7 @@ import org.chocosolver.solver.variables.IntVar; import java.util.function.BiPredicate; +import java.util.function.Function; /** * Value selector for optimization problems: @@ -43,6 +44,10 @@ public final class IntDomainBest implements IntValueSelector { */ private final BiPredicate condition; + private final IntValueSelector fallbackValueSelector; + + private final Function trigger; + /** * Create a value selector that returns the best value wrt to the objective to optimize. * When an enumerated variable domain exceeds {@link #maxdom}, only bounds are considered. @@ -54,14 +59,40 @@ public final class IntDomainBest implements IntValueSelector { * is kept. *

* - * @param maxdom a maximum domain size to satisfy to use this value selector. - * @param dop the decision operator used to make the decision - * @param condition predicate to break ties + * @param maxdom a maximum domain size to satisfy to use this value selector + * @param intValueSelector fallback value selector + * @param trigger the function that indicates when the best value selector is applied. + * When it returns true, the best value selector is applied. + * Otherwise, the fallback value selector is applied. + * @param dop the decision operator used to make the decision + * @param condition predicate to break ties */ - public IntDomainBest(int maxdom, DecisionOperator dop, BiPredicate condition) { + public IntDomainBest(int maxdom, IntValueSelector intValueSelector, Function trigger, DecisionOperator dop, BiPredicate condition) { this.maxdom = maxdom; this.dop = dop; this.condition = condition; + this.fallbackValueSelector = intValueSelector; + this.trigger = trigger; + } + + /** + * Create a value selector that returns the best value wrt to the objective to optimize. + * When an enumerated variable domain exceeds {@link #maxdom}, only bounds are considered. + * + *

+ * {@code condition} is called when the evaluated {@code value} returns a score + * equals to the current best one. In that case, if {@code condition} returns {@code true} + * then {@code value} is retained as the new best candidate, otherwise the previous one + * is kept. + *

+ * + * @param intValueSelector fallback value selector + * @param trigger the function that indicates when the best value selector is applied. + * When it returns true, the best value selector is applied. + * Otherwise, the fallback value selector is applied. + */ + public IntDomainBest(IntValueSelector intValueSelector, Function trigger) { + this(100, intValueSelector, trigger, DecisionOperatorFactory.makeIntEq(), (k, v) -> false); } /** @@ -76,9 +107,19 @@ public IntDomainBest(int maxdom, DecisionOperator dop, BiPredicate * * @param condition predicate to break ties + * @apiNote The default values are: + *
    + *
  • maxdom is set to 100
  • + *
  • the trigger is set to restart count % 16 == 0
  • + *
  • the decision operator is set to '='
  • + *
*/ public IntDomainBest(BiPredicate condition) { - this(100, DecisionOperatorFactory.makeIntEq(), condition); + this(100, + new IntDomainMin(), + v -> true, + DecisionOperatorFactory.makeIntEq(), + condition); } @@ -86,9 +127,21 @@ public IntDomainBest(BiPredicate condition) { * Create a value selector for assignments that returns the best value wrt to the objective to * optimize. When an enumerated variable domain exceeds 100, only bounds are considered. * Always-false condition is set by default. + * + * @apiNote The default values are: + *
    + *
  • maxdom is set to 100
  • + *
  • the trigger is set to restart count % 16 == 0
  • + *
  • the decision operator is set to '='
  • + *
  • the predicate to break ties is lexico
  • + *
*/ public IntDomainBest() { - this(100, DecisionOperatorFactory.makeIntEq(), (k, v) -> false); + this(100, + new IntDomainMin(), + v -> true, + DecisionOperatorFactory.makeIntEq(), + (k, v) -> false); } /** @@ -96,6 +149,9 @@ public IntDomainBest() { */ @Override public int selectValue(IntVar var) { + if (!trigger.apply(var)) { + return fallbackValueSelector.selectValue(var); + } assert var.getModel().getObjective() != null; if (var.hasEnumeratedDomain() && var.getDomainSize() < maxdom) { int bestCost = Integer.MAX_VALUE;