From fd3f1e9c3e413e58e2afe8c30acd7f54e08b9e43 Mon Sep 17 00:00:00 2001 From: cprudhom Date: Thu, 12 Oct 2023 17:12:13 +0200 Subject: [PATCH] Fix error in affine view detection --- .../constraints/IIntConstraintFactory.java | 5 ++-- .../solver/variables/IViewFactory.java | 13 ++++++++- .../variables/view/integer/IntAffineView.java | 29 +++++++------------ .../view/integer/IntAffineViewTest.java | 21 ++++---------- 4 files changed, 31 insertions(+), 37 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 5dc8fad05b..7b1a5a39d1 100644 --- a/solver/src/main/java/org/chocosolver/solver/constraints/IIntConstraintFactory.java +++ b/solver/src/main/java/org/chocosolver/solver/constraints/IIntConstraintFactory.java @@ -2582,7 +2582,7 @@ default Constraint tree(IntVar[] succs, IntVar nbTrees, int offset) { * Get the list of values in the domains of vars * * @param vars an array of integer variables - * @return the list of values in the domains of vars + * @return the array of values in the domains of vars */ default int[] getDomainUnion(IntVar... vars) { int m = vars[0].getLB(), M = vars[0].getUB(), j, k; @@ -2640,7 +2640,8 @@ static Object[] variableUniqueness(Object[]... vars) { for (int i = 0; i < allvars.size(); i++) { for (int j = i + 1; j < allvars.size(); j++) { if (allvars.get(i).equals(allvars.get(j))) { - allvars.set(j, IntAffineView.make(allvars.get(i), 1, 0)); + // force the view to be created, no call to ref().intView() here ! + allvars.set(j, new IntAffineView<>(allvars.get(i), 1, 0)); } } } diff --git a/solver/src/main/java/org/chocosolver/solver/variables/IViewFactory.java b/solver/src/main/java/org/chocosolver/solver/variables/IViewFactory.java index 2e48fd278f..8ec7f11f8a 100644 --- a/solver/src/main/java/org/chocosolver/solver/variables/IViewFactory.java +++ b/solver/src/main/java/org/chocosolver/solver/variables/IViewFactory.java @@ -131,7 +131,18 @@ default IntVar intView(int a, IntVar var, int b) { } } } - return IntAffineView.make(var, a, b); + if (var instanceof IntAffineView) { + IntAffineView view = (IntAffineView) var; + int av = (view.p ? 1 : -1) * view.a * a; + int bv = view.a * b + view.b; + if (av == 1 && bv == 0) { + return view.getVariable(); + }else{ + return intView(av, view.getVariable(), bv); + } + } else { + return new IntAffineView<>(var, a, b); + } } else { int lb, ub; if (a > 0) { diff --git a/solver/src/main/java/org/chocosolver/solver/variables/view/integer/IntAffineView.java b/solver/src/main/java/org/chocosolver/solver/variables/view/integer/IntAffineView.java index 1132d644ce..aab0b13d93 100644 --- a/solver/src/main/java/org/chocosolver/solver/variables/view/integer/IntAffineView.java +++ b/solver/src/main/java/org/chocosolver/solver/variables/view/integer/IntAffineView.java @@ -34,30 +34,21 @@ */ public final class IntAffineView extends IntView { - final boolean p; // positive - final int a; - final int b; - - - public static IntAffineView make(IntVar var, int a, int b) { - if (var instanceof IntAffineView) { - IntAffineView view = (IntAffineView) var; - return new IntAffineView<>(view.getVariable(), view.p & (a >= 0), view.a * Math.abs(a), view.a * b + view.b); - } else { - return new IntAffineView<>(var, a >= 0, Math.abs(a), b); - } - } + public final boolean p; // positive + public final int a; + public final int b; /** - * y is an affine view of x: y = (-1)a*x + b. + * y is an affine view of x: y = a*x + b. * * @param var a integer variable + * @param a a coefficient + * @param b a constant */ - private IntAffineView(final I var, boolean p, int a, int b) { - super((p ? "" : "-") + a + ".(" + var.getName() + ") + " + b, var); - assert a > 0; - this.p = p; - this.a = a; + public IntAffineView(final I var, int a, int b) { + super(a + ".(" + var.getName() + ") + " + b, var); + this.p = a >= 0; + this.a = Math.abs(a); this.b = b; } diff --git a/solver/src/test/java/org/chocosolver/solver/variables/view/integer/IntAffineViewTest.java b/solver/src/test/java/org/chocosolver/solver/variables/view/integer/IntAffineViewTest.java index 2bd270119a..cc76055b5c 100644 --- a/solver/src/test/java/org/chocosolver/solver/variables/view/integer/IntAffineViewTest.java +++ b/solver/src/test/java/org/chocosolver/solver/variables/view/integer/IntAffineViewTest.java @@ -65,7 +65,7 @@ public Object[][] configurations() { public void testNextValue(int a, int b, int... domain) { Model model = new Model(); IntVar x = model.intVar("x", domain); - IntVar y = IntAffineView.make(x, a, b); + IntVar y = new IntAffineView<>(x, a, b); int[] values = Arrays.stream(domain).map(i -> (a * i) + b).sorted().toArray(); @@ -78,20 +78,11 @@ public void testNextValue(int a, int b, int... domain) { Assert.assertEquals(y.nextValue(values[2]), Integer.MAX_VALUE); } - @Test(groups = "1s") - public void testNextValue2() { - Model model = new Model(); - IntVar x = model.intVar("x", 2, 9); - IntVar y = IntAffineView.make(x, 5, 7); - - - } - @Test(groups = "1s", dataProvider = "configurations") public void testPreviousValue(int a, int b, int... domain) { Model model = new Model(); IntVar x = model.intVar("x", domain); - IntVar y = IntAffineView.make(x, a, b); + IntVar y = new IntAffineView<>(x, a, b); int[] values = Arrays.stream(domain).map(i -> a * i + b).sorted().toArray(); @@ -108,7 +99,7 @@ public void testPreviousValue(int a, int b, int... domain) { public void testNextValueOut(int a, int b, int... domain) { Model model = new Model(); IntVar x = model.intVar("x", domain); - IntVar y = IntAffineView.make(x, a, b); + IntVar y = new IntAffineView<>(x, a, b); int[] values = Arrays.stream(domain).map(i -> (a * i) + b).sorted().toArray(); BitSet valuesOut = new BitSet(); @@ -129,7 +120,7 @@ public void testNextValueOut(int a, int b, int... domain) { public void testPreviousValueOut(int a, int b, int... domain) { Model model = new Model(); IntVar x = model.intVar("x", domain); - IntVar y = IntAffineView.make(x, a, b); + IntVar y = new IntAffineView<>(x, a, b); int[] values = Arrays.stream(domain).map(i -> (a * i) + b).sorted().toArray(); BitSet valuesOut = new BitSet(); @@ -151,7 +142,7 @@ public void testPreviousValueOut(int a, int b, int... domain) { public void testValueIterator(int a, int b, int... domain) { Model model = new Model(); IntVar x = model.intVar("x", domain); - IntVar y = IntAffineView.make(x, a, b); + IntVar y = new IntAffineView<>(x, a, b); int[] values = Arrays.stream(domain).map(i -> a * i + b).sorted().toArray(); @@ -178,7 +169,7 @@ public void testValueIterator(int a, int b, int... domain) { public void testRangeIterator(int a, int b, int... domain) { Model model = new Model(); IntVar x = model.intVar("x", domain); - IntVar y = IntAffineView.make(x, a, b); + IntVar y = new IntAffineView<>(x, a, b); int[] values = Arrays.stream(domain).map(i -> a * i + b).sorted().toArray();