diff --git a/cpmpy/expressions/__init__.py b/cpmpy/expressions/__init__.py index 435c5f04c..bb3ffa069 100644 --- a/cpmpy/expressions/__init__.py +++ b/cpmpy/expressions/__init__.py @@ -21,7 +21,7 @@ # others need to be imported by the developer explicitely from .variables import boolvar, intvar, cpm_array from .variables import BoolVar, IntVar, cparray # Old, to be deprecated -from .globalconstraints import AllDifferent, AllDifferentExcept0, AllDifferentExceptN, AllDifferentLists, AllEqual, AllEqualExceptN, Circuit, Inverse, Table, Xor, Cumulative, \ +from .globalconstraints import AllDifferent, AllDifferentExcept0, AllDifferentExceptN, AllEqual, AllEqualExceptN, Circuit, Inverse, Table, Xor, Cumulative, \ IfThenElse, GlobalCardinalityCount, DirectConstraint, InDomain, Increasing, Decreasing, IncreasingStrict, DecreasingStrict, \ LexLess, LexLessEq, LexChainLess, LexChainLessEq, Precedence, NoOverlap from .globalconstraints import alldifferent, allequal, circuit # Old, to be deprecated diff --git a/cpmpy/expressions/globalconstraints.py b/cpmpy/expressions/globalconstraints.py index 06976331f..8c8d6c95e 100644 --- a/cpmpy/expressions/globalconstraints.py +++ b/cpmpy/expressions/globalconstraints.py @@ -99,7 +99,6 @@ def my_circuit_decomp(self): AllDifferent AllDifferentExcept0 AllDifferentExceptN - AllDifferentLists AllEqual AllEqualExceptN Circuit @@ -202,6 +201,7 @@ def value(self): vals = [argval(a) for a in self.args[0] if argval(a) not in argvals(self.args[1])] return len(set(vals)) == len(vals) + class AllDifferentExcept0(AllDifferentExceptN): """ All nonzero arguments have a distinct value @@ -211,33 +211,6 @@ def __init__(self, *arr): super().__init__(arr, 0) -class AllDifferentLists(GlobalConstraint): - """ - Ensures none of the lists given are exactly the same. - Called 'lex_alldifferent' in the global constraint catalog: - https://sofdem.github.io/gccat/gccat/Clex_alldifferent.html#uid24923 - """ - def __init__(self, lists): - if any(not is_any_list(lst) for lst in lists): - raise TypeError(f"AllDifferentLists expects a list of lists, but got {lists}") - if any(len(lst) != len(lists[0]) for lst in lists): - raise ValueError("Lists should have equal length, but got these lengths:", list(map(len, lists))) - super().__init__("alldifferent_lists", [flatlist(lst) for lst in lists]) - - def decompose(self): - """Returns the decomposition - """ - from .python_builtins import any as cpm_any - constraints = [] - for lst1, lst2 in all_pairs(self.args): - constraints += [cpm_any(var1 != var2 for var1, var2 in zip(lst1, lst2))] - return constraints, [] - - def value(self): - lst_vals = [tuple(argvals(a)) for a in self.args] - return len(set(lst_vals)) == len(self.args) - - def allequal(args): warnings.warn("Deprecated, use AllEqual(v1,v2,...,vn) instead, will be removed in stable version", DeprecationWarning) return AllEqual(*args) # unfold list as individual arguments @@ -258,6 +231,7 @@ def decompose(self): def value(self): return len(set(argvals(self.args))) == 1 + class AllEqualExceptN(GlobalConstraint): """ All arguments except those equal to a value in n have the same value. diff --git a/tests/test_constraints.py b/tests/test_constraints.py index cad4c7fde..b8a4827eb 100644 --- a/tests/test_constraints.py +++ b/tests/test_constraints.py @@ -15,7 +15,7 @@ # Exclude some global constraints for solvers NUM_GLOBAL = { - "AllEqual", "AllDifferent", "AllDifferentLists", "AllDifferentExcept0", + "AllEqual", "AllDifferent", "AllDifferentExcept0", "AllDifferentExceptN", "AllEqualExceptN", "GlobalCardinalityCount", "InDomain", "Inverse", "Table", "Circuit", "Increasing", "IncreasingStrict", "Decreasing", "DecreasingStrict", @@ -234,10 +234,7 @@ def global_constraints(solver): expr = LexChainLess(X) elif name == "LexChainLessEq": X = intvar(0, 3, shape=(3,3)) - expr = LexChainLess(X) - elif name == "AllDifferentLists": - vars = intvar(0,10, shape=(3,4)) - expr = cls(vars) + expr = LexChainLess(X) else: # default constructor, list of numvars expr= cls(NUM_ARGS) diff --git a/tests/test_globalconstraints.py b/tests/test_globalconstraints.py index b060717e9..ceda6de84 100644 --- a/tests/test_globalconstraints.py +++ b/tests/test_globalconstraints.py @@ -55,26 +55,6 @@ def test_alldifferent2(self): var._value = val assert (c.value() == oracle), f"Wrong value function for {vals,oracle}" - def test_alldifferent_lists(self): - # test known input/outputs - tuples = [ - ([(1,2,3),(1,3,3),(1,2,4)], True), - ([(1,2,3),(1,3,3),(1,2,3)], False), - ([(0,0,3),(1,3,3),(1,2,4)], True), - ([(1,2,3),(1,3,3),(3,3,3)], True) - ] - iv = cp.intvar(0,4, shape=(3,3)) - c = cp.AllDifferentLists(iv) - for (vals, oracle) in tuples: - ret = cp.Model(c, iv == vals).solve() - assert (ret == oracle), f"Mismatch solve for {vals,oracle}" - # don't try this at home, forcibly overwrite variable values (so even when ret=false) - for (var,val) in zip(iv,vals): - for (vr, vl) in zip(var, val): - vr._value = vl - assert (c.value() == oracle), f"Wrong value function for {vals,oracle}" - - def test_not_alldifferent(self): # from fuzztester of Ruben Kindt, #143 pos = cp.intvar(lb=0, ub=5, shape=3, name="positions")