@@ -145,13 +145,14 @@ def is_var(x):
145
145
146
146
class NumVarImpl (Expression ):
147
147
"""
148
- **Continuous numerical** variable with given lowerbound and upperbound.
148
+ Abstract **continuous numerical** variable with given lowerbound and upperbound.
149
149
"""
150
- def __init__ (self , lb , ub ):
150
+ def __init__ (self , lb , ub , name ):
151
151
assert (is_num (lb ) and is_num (ub ))
152
152
assert (lb <= ub )
153
153
self .lb = lb
154
154
self .ub = ub
155
+ self .name = name
155
156
self ._value = None
156
157
157
158
def is_bool (self ):
@@ -161,6 +162,9 @@ def is_bool(self):
161
162
162
163
def value (self ):
163
164
return self ._value
165
+
166
+ def __repr__ (self ):
167
+ return self .name
164
168
165
169
# for sets/dicts. Because names are unique, so is the str repr
166
170
def __hash__ (self ):
@@ -172,40 +176,36 @@ class IntVarImpl(NumVarImpl):
172
176
"""
173
177
counter = 0
174
178
175
- def __init__ (self , lb , ub , setname = True ):
179
+ def __init__ (self , lb , ub , name = None ):
176
180
assert is_int (lb ), "IntVar lowerbound must be integer {} {}" .format (type (lb ),lb )
177
181
assert is_int (ub ), "IntVar upperbound must be integer {} {}" .format (type (ub ),ub )
178
- #assert (lb >= 0 and ub >= 0) # can be negative?
179
- super ().__init__ (int (lb ), int (ub )) # explicit cast: can be numpy
180
-
181
- if setname :
182
- self .name = IntVarImpl .counter
182
+
183
+ if name is None :
184
+ name = "IV{}" .format (IntVarImpl .counter )
183
185
IntVarImpl .counter = IntVarImpl .counter + 1 # static counter
184
-
185
- def __repr__ (self ):
186
- return "IV{}" .format (self .name )
186
+
187
+ super ().__init__ (int (lb ), int (ub ), name = name ) # explicit cast: can be numpy
187
188
188
189
class BoolVarImpl (IntVarImpl ):
189
190
"""
190
191
**Boolean** constraint variable with given lowerbound and upperbound.
191
192
"""
192
193
counter = 0
193
194
194
- def __init__ (self , lb = 0 , ub = 1 ):
195
+ def __init__ (self , lb = 0 , ub = 1 , name = None ):
195
196
assert (lb == 0 or lb == 1 )
196
197
assert (ub == 0 or ub == 1 )
197
- IntVarImpl .__init__ (self , lb , ub , setname = False )
198
+
199
+ if name is None :
200
+ name = "BV{}" .format (BoolVarImpl .counter )
201
+ BoolVarImpl .counter = BoolVarImpl .counter + 1 # static counter
202
+ IntVarImpl .__init__ (self , lb , ub , name = name )
198
203
199
- self .name = BoolVarImpl .counter
200
- BoolVarImpl .counter = BoolVarImpl .counter + 1 # static counter
201
204
202
205
def is_bool (self ):
203
206
""" is it a Boolean (return type) Operator?
204
207
"""
205
208
return True
206
-
207
- def __repr__ (self ):
208
- return "BV{}" .format (self .name )
209
209
210
210
def __invert__ (self ):
211
211
return NegBoolView (self )
@@ -237,7 +237,7 @@ def value(self):
237
237
return not self ._bv .value ()
238
238
239
239
def __repr__ (self ):
240
- return "~BV {}" .format (self ._bv .name )
240
+ return "~{}" .format (self ._bv .name )
241
241
242
242
def __invert__ (self ):
243
243
return self ._bv
@@ -312,34 +312,32 @@ def sum(self, axis=None, out=None):
312
312
313
313
314
314
# N-dimensional array of Boolean Decision Variables
315
- def BoolVar (shape = None ):
315
+ def BoolVar (shape = None , name = None ):
316
316
"""
317
317
# N-dimensional array of Boolean Decision Variables
318
318
"""
319
319
if shape is None or shape == 1 :
320
- return BoolVarImpl ()
320
+ return BoolVarImpl (name = name )
321
321
elif shape == 0 :
322
322
raise NullShapeError (shape )
323
- length = np .prod (shape )
324
323
325
324
# create base data
326
- data = np .array ([BoolVarImpl () for _ in range ( length )]) # repeat new instances
325
+ data = np .array ([BoolVarImpl (name = _genname ( name , idxs )) for idxs in np . ndindex ( shape )]) # repeat new instances
327
326
# insert into custom ndarray
328
327
return NDVarArray (shape , dtype = object , buffer = data )
329
328
330
329
331
- def IntVar (lb , ub , shape = None ):
330
+ def IntVar (lb , ub , shape = None , name = None ):
332
331
"""
333
332
N-dimensional array of Integer Decision Variables with lower-bound `lb` and upper-bound `ub`
334
333
"""
335
334
if shape is None or shape == 1 :
336
- return IntVarImpl (lb ,ub )
335
+ return IntVarImpl (lb ,ub , name = name )
337
336
elif shape == 0 :
338
337
raise NullShapeError (shape )
339
- length = np .prod (shape )
340
-
338
+
341
339
# create base data
342
- data = np .array ([IntVarImpl (lb ,ub ) for _ in range ( length )]) # repeat new instances
340
+ data = np .array ([IntVarImpl (lb ,ub , name = _genname ( name , idxs )) for idxs in np . ndindex ( shape )]) # repeat new instances
343
341
# insert into custom ndarray
344
342
return NDVarArray (shape , dtype = object , buffer = data )
345
343
@@ -354,3 +352,20 @@ def cparray(arr):
354
352
if not isinstance (arr , np .ndarray ):
355
353
arr = np .array (arr )
356
354
return NDVarArray (shape = arr .shape , dtype = type (arr .flat [0 ]), buffer = arr )
355
+
356
+
357
+ def _genname (basename , idxs ):
358
+ """
359
+ Helper function to 'name' array variables
360
+ - idxs: list of indices, one for every dimension of the array
361
+ - basename: base name to prepend
362
+
363
+ if basename is 'None', then it returns None
364
+
365
+ output: something like "basename[0,1]"
366
+ """
367
+ if basename == None :
368
+ return None
369
+ stridxs = "," .join (map (str ,idxs ))
370
+ return f"{ basename } [{ stridxs } ]" # "<name>[<idx0>,<idx1>,...]"
371
+
0 commit comments