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;