Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

remove alldifferent Lists #493

Merged
merged 1 commit into from
Jul 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading