diff --git a/cpmpy/expressions/globalconstraints.py b/cpmpy/expressions/globalconstraints.py index 4dd300e33..9fffbc5b6 100644 --- a/cpmpy/expressions/globalconstraints.py +++ b/cpmpy/expressions/globalconstraints.py @@ -237,15 +237,21 @@ def decompose(self): """ succ = cpm_array(self.args) n = len(succ) - order = intvar(0,n-1, shape=n) + order = intvar(0,n-1, shape=n, name='order') constraining = [] constraining += [AllDifferent(succ)] # different successors constraining += [AllDifferent(order)] # different orders constraining += [order[n-1] == 0] # symmetry breaking, last one is '0' - - defining = [order[0] == succ[0]] - defining += [order[i] == succ[order[i-1]] for i in range(1,n)] # first one is successor of '0', ith one is successor of i-1 - + a = boolvar(name='a') + + defining = [a == ((Minimum(succ) >= 0) & (Maximum(succ) < n))] + for i in range(n): + defining += [(~a).implies(order[i] == 0)] #make order be totally defined + if i == 0: + defining += [a.implies(order[0] == succ[0])] + else: + defining += [a.implies( + order[i] == succ[order[i - 1]])] # first one is successor of '0', ith one is successor of i-1 return constraining, defining def value(self): diff --git a/tests/test_globalconstraints.py b/tests/test_globalconstraints.py index a4c3db386..49c444fa3 100644 --- a/tests/test_globalconstraints.py +++ b/tests/test_globalconstraints.py @@ -123,10 +123,10 @@ def test_circuit(self): self.assertTrue(cp.Circuit(x).value()) def test_not_circuit(self): - x = cp.intvar(lb=0, ub=2, shape=3) + x = cp.intvar(lb=-1, ub=5, shape=4) circuit = cp.Circuit(x) - model = cp.Model([~circuit, x == [1,2,0]]) + model = cp.Model([~circuit, x == [1,2,3,0]]) self.assertFalse(model.solve()) model = cp.Model([~circuit])