Skip to content

Commit ffd7e70

Browse files
committed
make Minimum/Maximum a global that implements .value()
1 parent 3f63ebb commit ffd7e70

File tree

2 files changed

+37
-8
lines changed

2 files changed

+37
-8
lines changed

cpmpy/globalconstraints.py

+34-7
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ def min(iterable):
119119
"""
120120
if not any(isinstance(elem, Expression) for elem in iterable):
121121
return np.min(iterable)
122-
return GlobalConstraint("min", list(iterable), is_bool=False)
122+
return Minimum(iterable)
123123

124124
def max(iterable):
125125
"""
@@ -128,7 +128,7 @@ def max(iterable):
128128
"""
129129
if not any(isinstance(elem, Expression) for elem in iterable):
130130
return np.max(iterable)
131-
return GlobalConstraint("max", list(iterable), is_bool=False)
131+
return Maximum(iterable)
132132

133133

134134

@@ -178,6 +178,30 @@ def decompose(self):
178178
return constraints
179179

180180

181+
class Minimum(GlobalConstraint):
182+
"""
183+
Computes the minimum value of the arguments
184+
185+
It is a 'functional' global constraint which implicitly returns a numeric variable
186+
"""
187+
def __init__(self, arg_list):
188+
super().__init__("min", arg_list, is_bool=False)
189+
190+
def value(self):
191+
return min([_argval(a) for a in self.args])
192+
193+
class Maximum(GlobalConstraint):
194+
"""
195+
Computes the maximum value of the arguments
196+
197+
It is a 'functional' global constraint which implicitly returns a numeric variable
198+
"""
199+
def __init__(self, arg_list):
200+
super().__init__("max", arg_list, is_bool=False)
201+
202+
def value(self):
203+
return max([_argval(a) for a in self.args])
204+
181205
class Element(GlobalConstraint):
182206
"""
183207
The 'Element' global constraint enforces that the result equals Arr[Idx]
@@ -197,21 +221,24 @@ def __init__(self, arg_list):
197221
super().__init__("element", arg_list, is_bool=False)
198222

199223
def value(self):
200-
# XXX, make argval shared util function?
201-
def argval(a):
202-
return a.value() if isinstance(a, Expression) else a
203-
idxval = argval(self.args[1])
224+
idxval = _argval(self.args[1])
204225
if not idxval is None:
205-
return argval(self.args[0][idxval])
226+
return _argval(self.args[0][idxval])
206227
return None # default
207228

208229
def __repr__(self):
209230
return "{}[{}]".format(self.args[0], self.args[1])
210231

211232

233+
212234
def _all_pairs(args):
213235
""" internal helper function
214236
"""
215237
pairs = list(combinations(args, 2))
216238
return pairs
217239

240+
# XXX, make argval shared util function?
241+
def _argval(a):
242+
""" returns .value() of Expression, otherwise the variable itself
243+
"""
244+
return a.value() if isinstance(a, Expression) else a

tests/test_globalconstraints.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,6 @@ def test_minimax_cpm(self):
6161
self.assertIsInstance(ma, cp.GlobalConstraint)
6262

6363
self.assertEqual(cp.Model([], minimize=mi).solve(), 1)
64-
self.assertEqual(cp.Model([], minimize=ma).solve(), 9)
64+
self.assertEqual(cp.Model([], minimize=ma).solve(), 1)
65+
self.assertEqual(cp.Model([], maximize=mi).solve(), 9)
66+
self.assertEqual(cp.Model([], maximize=ma).solve(), 9)

0 commit comments

Comments
 (0)