Skip to content

Commit

Permalink
Increasing decreasing, adding tests + minizinc (#472)
Browse files Browse the repository at this point in the history
* increasing and decreasing in minizinc
  • Loading branch information
Dimosts authored May 10, 2024
1 parent dfa81ff commit 3a94691
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 9 deletions.
4 changes: 2 additions & 2 deletions cpmpy/expressions/globalconstraints.py
Original file line number Diff line number Diff line change
Expand Up @@ -574,7 +574,7 @@ class IncreasingStrict(GlobalConstraint):
"""

def __init__(self, *args):
super().__init__("increasing_strict", flatlist(args))
super().__init__("strictly_increasing", flatlist(args))

def decompose(self):
"""
Expand All @@ -597,7 +597,7 @@ class DecreasingStrict(GlobalConstraint):
"""

def __init__(self, *args):
super().__init__("decreasing_strict", flatlist(args))
super().__init__("strictly_decreasing", flatlist(args))

def decompose(self):
"""
Expand Down
9 changes: 5 additions & 4 deletions cpmpy/solvers/choco.py
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,8 @@ def transform(self, cpm_expr):
cpm_cons = toplevel_list(cpm_expr)
supported = {"min", "max", "abs", "count", "element", "alldifferent", "alldifferent_except0", "allequal",
"table", "InDomain", "cumulative", "circuit", "gcc", "inverse", "nvalue", "increasing",
"decreasing","increasing_strict","decreasing_strict"}
"decreasing","strictly_increasing","strictly_decreasing"}

# choco supports reification of any constraint, but has a bug in increasing and decreasing
supported_reified = {"min", "max", "abs", "count", "element", "alldifferent", "alldifferent_except0",
"allequal", "table", "InDomain", "cumulative", "circuit", "gcc", "inverse", "nvalue"}
Expand Down Expand Up @@ -495,7 +496,7 @@ def _get_constraint(self, cpm_expr):
elif isinstance(cpm_expr, GlobalConstraint):

# many globals require all variables as arguments
if cpm_expr.name in {"alldifferent", "alldifferent_except0", "allequal", "circuit", "inverse","increasing","decreasing","increasing_strict","decreasing_strict"}:
if cpm_expr.name in {"alldifferent", "alldifferent_except0", "allequal", "circuit", "inverse","increasing","decreasing","strictly_increasing","strictly_decreasing"}:
chc_args = self._to_vars(cpm_expr.args)
if cpm_expr.name == 'alldifferent':
return self.chc_model.all_different(chc_args)
Expand All @@ -511,9 +512,9 @@ def _get_constraint(self, cpm_expr):
return self.chc_model.increasing(chc_args,0)
elif cpm_expr.name == "decreasing":
return self.chc_model.decreasing(chc_args,0)
elif cpm_expr.name == "increasing_strict":
elif cpm_expr.name == "strictly_increasing":
return self.chc_model.increasing(chc_args,1)
elif cpm_expr.name == "decreasing_strict":
elif cpm_expr.name == "strictly_decreasing":
return self.chc_model.decreasing(chc_args,1)

# but not all
Expand Down
3 changes: 2 additions & 1 deletion cpmpy/solvers/minizinc.py
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,8 @@ def transform(self, cpm_expr):
"""
cpm_cons = toplevel_list(cpm_expr)
supported = {"min", "max", "abs", "element", "count", "nvalue", "alldifferent", "alldifferent_except0", "allequal",
"inverse", "ite" "xor", "table", "cumulative", "circuit", "gcc"}
"inverse", "ite" "xor", "table", "cumulative", "circuit", "gcc", "increasing",
"decreasing","strictly_increasing","strictly_decreasing"}
return decompose_in_tree(cpm_cons, supported, supported_reified=supported - {"circuit"})


Expand Down
4 changes: 2 additions & 2 deletions tests/test_constraints.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
EXCLUDE_GLOBAL = {"ortools": {},
"gurobi": {},
"minizinc": {"circuit"},
"pysat": {"circuit", "element","min","max","count", "nvalue", "allequal","alldifferent","cumulative","increasing","decreasing","increasing_strict","decreasing_strict"},
"pysdd": {"circuit", "element","min","max","count", "nvalue", "allequal","alldifferent","cumulative","xor","increasing","decreasing","increasing_strict","decreasing_strict"},
"pysat": {"circuit", "element","min","max","count", "nvalue", "allequal","alldifferent","cumulative","increasing","decreasing","strictly_increasing","strictly_decreasing"},
"pysdd": {"circuit", "element","min","max","count", "nvalue", "allequal","alldifferent","cumulative","xor","increasing","decreasing","strictly_increasing","strictly_decreasing"},
"exact": {},
"choco": {}
}
Expand Down
44 changes: 44 additions & 0 deletions tests/test_globalconstraints.py
Original file line number Diff line number Diff line change
Expand Up @@ -770,6 +770,50 @@ def test_allEqual(self):
self.assertTrue(cp.Model([cp.AllEqual(a,b,False, a | b)]).solve())
#self.assertTrue(cp.Model([cp.AllEqual(x,y,b)]).solve())

def test_increasing(self):
x = cp.intvar(-8, 8)
y = cp.intvar(-7, -1)
b = cp.boolvar()
a = cp.boolvar()
self.assertTrue(cp.Model([cp.Increasing(x,y)]).solve())
self.assertTrue(cp.Model([cp.Increasing(a,b)]).solve())
self.assertTrue(cp.Model([cp.Increasing(x,y,b)]).solve())
z = cp.intvar(2,5)
self.assertFalse(cp.Model([cp.Increasing(z,b)]).solve())

def test_decreasing(self):
x = cp.intvar(-8, 8)
y = cp.intvar(-7, -1)
b = cp.boolvar()
a = cp.boolvar()
self.assertTrue(cp.Model([cp.Decreasing(x,y)]).solve())
self.assertTrue(cp.Model([cp.Decreasing(a,b)]).solve())
self.assertFalse(cp.Model([cp.Decreasing(x,y,b)]).solve())
z = cp.intvar(2,5)
self.assertTrue(cp.Model([cp.Decreasing(z,b)]).solve())

def test_increasing_strict(self):
x = cp.intvar(-8, 8)
y = cp.intvar(-7, -1)
b = cp.boolvar()
a = cp.boolvar()
self.assertTrue(cp.Model([cp.IncreasingStrict(x,y)]).solve())
self.assertTrue(cp.Model([cp.IncreasingStrict(a,b)]).solve())
self.assertTrue(cp.Model([cp.IncreasingStrict(x,y,b)]).solve())
z = cp.intvar(1,5)
self.assertFalse(cp.Model([cp.IncreasingStrict(z,b)]).solve())

def test_decreasing_strict(self):
x = cp.intvar(-8, 8)
y = cp.intvar(-7, 0)
b = cp.boolvar()
a = cp.boolvar()
self.assertTrue(cp.Model([cp.DecreasingStrict(x,y)]).solve())
self.assertTrue(cp.Model([cp.DecreasingStrict(a,b)]).solve())
self.assertFalse(cp.Model([cp.DecreasingStrict(x,y,b)]).solve())
z = cp.intvar(1,5)
self.assertTrue(cp.Model([cp.DecreasingStrict(z,b)]).solve())

def test_circuit(self):
x = cp.intvar(-8, 8)
y = cp.intvar(-7, -1)
Expand Down

0 comments on commit 3a94691

Please sign in to comment.