From 5b7b50f206089c52daf6ab7d59b1b9829e5a6bda Mon Sep 17 00:00:00 2001 From: Jean-Guillaume Fages Date: Fri, 21 Jul 2023 17:55:18 +0200 Subject: [PATCH] use square when possible and stronger filtering practical interest to be confirmed by experiments --- .../constraints/IIntConstraintFactory.java | 4 +- .../solver/constraints/binary/PropSquare.java | 44 ++++++++++--------- 2 files changed, 26 insertions(+), 22 deletions(-) diff --git a/solver/src/main/java/org/chocosolver/solver/constraints/IIntConstraintFactory.java b/solver/src/main/java/org/chocosolver/solver/constraints/IIntConstraintFactory.java index e857536d7b..fc844e9b25 100644 --- a/solver/src/main/java/org/chocosolver/solver/constraints/IIntConstraintFactory.java +++ b/solver/src/main/java/org/chocosolver/solver/constraints/IIntConstraintFactory.java @@ -736,7 +736,9 @@ default Constraint mod(IntVar X, IntVar Y, IntVar Z) { */ @SuppressWarnings("SuspiciousNameCombination") default Constraint times(IntVar X, IntVar Y, IntVar Z) { - if (Y.isInstantiated()) { + if (X == Y) { + return square(Z, X); + } else if (Y.isInstantiated()) { return times(X, Y.getValue(), Z); } else if (X.isInstantiated()) { return times(Y, X.getValue(), Z); diff --git a/solver/src/main/java/org/chocosolver/solver/constraints/binary/PropSquare.java b/solver/src/main/java/org/chocosolver/solver/constraints/binary/PropSquare.java index 1daf550ad1..00aa828474 100644 --- a/solver/src/main/java/org/chocosolver/solver/constraints/binary/PropSquare.java +++ b/solver/src/main/java/org/chocosolver/solver/constraints/binary/PropSquare.java @@ -117,7 +117,6 @@ protected void updateLowerBoundofX() throws ContradictionException { protected void updateUpperBoundofX() throws ContradictionException { vars[0].updateUpperBound(Math.max(sqr(vars[1].getLB()), sqr(vars[1].getUB())), this); - } protected boolean updateHolesinX() throws ContradictionException { @@ -158,7 +157,11 @@ protected boolean updateHolesinX() throws ContradictionException { } protected boolean updateLowerBoundofY() throws ContradictionException { - return vars[1].updateLowerBound(-ceil_sqrt(vars[0].getUB()), this); + if (vars[1].getLB() >= 0) { + return vars[1].updateLowerBound(ceil_sqrt(vars[0].getLB()), this); + } else { + return vars[1].updateLowerBound(-floor_sqrt(vars[0].getUB()), this); + } } protected boolean updateUpperBoundofY() throws ContradictionException { @@ -166,8 +169,19 @@ protected boolean updateUpperBoundofY() throws ContradictionException { } protected boolean updateHolesinY() throws ContradictionException { - // remove intervals to deal with consecutive value removal and upper bound modification - if (bothEnum) { + if (vars[0].isInstantiatedTo(0)) { + return vars[1].instantiateTo(0, this); + } + boolean impact = false; + // remove interval around 0 based on X LB + if (vars[1].hasEnumeratedDomain()) { + int val = ceil_sqrt(vars[0].getLB()) - 1; + if (val >= 0) { + impact = vars[1].removeInterval(-val, val, this); + } + } + // remove values based on X holes + if (bothEnum && hasHoles(vars[0])) { int ub = vars[1].getUB(); vrms.clear(); vrms.setOffset(vars[1].getLB()); @@ -176,24 +190,12 @@ protected boolean updateHolesinY() throws ContradictionException { vrms.add(value); } } - return vars[1].removeValues(vrms, this); - } else if (vars[1].hasEnumeratedDomain()) { - int lb = vars[1].getLB(); - int ub = vars[1].getUB(); - while (!vars[0].contains(sqr(lb))) { - lb = vars[1].nextValue(lb); - if (lb > ub) break; - } - boolean filter = vars[1].updateLowerBound(lb, this); - - while (!vars[0].contains(sqr(ub))) { - ub = vars[1].nextValue(ub); - if (ub < lb) break; - } - return filter | vars[1].updateUpperBound(ub, this); + impact |= vars[1].removeValues(vrms, this); } - return false; + return impact; } - + private boolean hasHoles(IntVar var) { + return (var.getUB() - var.getLB() + 1) > var.getDomainSize(); + } }