Skip to content

Commit

Permalink
remove alldifferent Lists
Browse files Browse the repository at this point in the history
  • Loading branch information
Wout4 committed Jun 17, 2024
1 parent 7e86304 commit 8eba5e9
Show file tree
Hide file tree
Showing 4 changed files with 5 additions and 54 deletions.
2 changes: 1 addition & 1 deletion cpmpy/expressions/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
30 changes: 2 additions & 28 deletions cpmpy/expressions/globalconstraints.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,6 @@ def my_circuit_decomp(self):
AllDifferent
AllDifferentExcept0
AllDifferentExceptN
AllDifferentLists
AllEqual
AllEqualExceptN
Circuit
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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.
Expand Down
7 changes: 2 additions & 5 deletions tests/test_constraints.py
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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)

Expand Down
20 changes: 0 additions & 20 deletions tests/test_globalconstraints.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down

0 comments on commit 8eba5e9

Please sign in to comment.