source: coopr.pyomo/trunk/coopr/pyomo/base/numvalue.py @ 2201

Last change on this file since 2201 was 2201, checked in by wehart, 10 years ago

Update to Coopr to account for changes in PyUtilib? package names.

File size: 9.1 KB
Line 
1#  _________________________________________________________________________
2#
3#  Coopr: A COmmon Optimization Python Repository
4#  Copyright (c) 2008 Sandia Corporation.
5#  This software is distributed under the BSD License.
6#  Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
7#  the U.S. Government retains certain rights in this software.
8#  For more information, see the Coopr README.txt file.
9#  _________________________________________________________________________
10
11__all__ = ['value', 'NumericValue', 'as_numeric', 'NumericConstant', 'ZeroConstant', 'OneConstant', 'is_constant']
12
13import plugin
14#import pyutilib.component.core
15import pyutilib.math
16import sys
17from set_types import Reals
18
19
20##------------------------------------------------------------------------
21##
22## Standard types of expressions
23##
24##------------------------------------------------------------------------
25
26def create_name(name, ndx):
27    if ndx is None:
28        return name
29    if type(ndx) is tuple:
30        tmp = str(ndx).replace(', ',',')
31        return name+"["+tmp[1:-1]+"]"
32    return name+"["+str(ndx)+"]"
33
34def value(obj):
35    """
36    A utility function that returns the value of an expression
37    """
38    if obj is None:
39        return None
40    elif type(obj) in [bool,int,long,float]:
41        return obj
42    if not isinstance(obj, NumericValue):
43        raise ValueError, "Object "+str(obj)+" is not a NumericValue object"
44    tmp = obj()
45    if tmp is None:
46        raise ValueError, "No value for uninitialized NumericValue object "+obj.name
47    return tmp
48
49def is_constant(obj):
50    """
51    A utility function that returns a boolean that indicates whether the object is a constant
52    """
53    if obj is None:
54        return False   
55    elif type(obj) in [bool,int,long,float]:
56        return True
57    if not isinstance(obj, NumericValue):
58        return False
59    return obj.is_constant()
60
61def as_numeric(obj):
62    """Verify that this obj is a NumericValue or intrinsic value"""
63    if isinstance(obj,NumericValue):
64       return obj.as_numeric()
65    if type(obj) in [bool,int,long,float]:
66       return NumericConstant(value=obj)
67    raise ValueError, "This object is not a numeric value: "+str(obj)
68
69
70class NumericValue(object):
71    """An object that contains a numeric value"""
72
73    __hash__ = None
74
75    def __init__(self, **kwds):
76        if 'name' in kwds:
77            self.name=str(kwds['name'])
78        else:
79            self.name="unknown"
80        if 'domain' in kwds:
81            self.domain=kwds['domain']
82        elif 'within' in kwds:
83            self.domain=kwds['within']
84        else:
85            self.domain=None
86        if 'value' in kwds:
87            if pyutilib.math.is_nan(kwds['value']):
88                self.value=pyutilib.math.nan
89            else:
90                self.set_value(kwds['value'])
91        else:
92            self.value=None
93        self.model=None
94        #print "NUMVAL",self.name,self.domain,self.value
95
96    def is_constant(self):
97        return True
98
99    def fixed_value(self):
100        return False
101
102    def as_numeric(self):
103        return self
104
105    def pprint(self, ostream=None):
106        raise IOError, "NumericValue:pprint is not defined"     #pragma:nocover
107
108    def display(self, ostream=None):
109        self.pprint(ostream=ostream)
110
111    def reset(self):            #pragma:nocover
112        pass                    #pragma:nocover
113
114    def set_value(self, val):
115        if self._valid_value(val):
116            self.value=val
117
118    def __call__(self, exception=True):
119        return self.value
120
121    def __float__(self):
122        tmp = self.__call__()
123        if tmp is None:
124            raise ValueError, "Cannot coerce variable `"+self.name+"' to float because it is uninitialized."
125        return float(tmp)
126
127    def __int__(self):
128        tmp = self.__call__()
129        if tmp is None:
130            raise ValueError, "Cannot coerce variable `"+self.name+"' to integer because it is uninitialized."
131        return int(tmp)
132
133    def _valid_value(self,value,use_exception=True):
134        #print "HERE X", self.domain is None
135        ans = value is None or self.domain is None or value in self.domain
136        if not ans and use_exception:
137           raise ValueError, "Numeric value `"+str(value)+"` is not in domain "+str(self.domain)
138        return ans
139
140    def X__getattr__(self,name):
141        #print "GETATTR",name
142        #d = self.__dict__
143        try:
144            return self.__dict__[name]
145        except:
146            pass
147        try:
148            return self.__dict__["_attr_"+name]
149        except:
150            pass
151        raise AttributeError, "Unknown attribute `"+str(name)+"' for object with type "+str(type(self))
152
153    def X__setattr__(self,name,val):
154        ##print "SETATTR",name,val
155        if name == "__class__":
156           self.__class__ = val
157           return
158        if name[0] == "_":
159           self.__dict__[name] = val
160           return
161        if name in self._standard_attr:
162           self.__dict__["_attr_"+name] = val
163           return
164        raise AttributeError, "Unallowable attribute `"+name+"`"
165        #self._standard_attr[name] = val
166
167    def __lt__(self,other):
168        """Less than operator
169
170        (Called in response to 'self < other' or 'other > self'.)
171        """
172        return plugin.ExpressionFactory('<', [self,as_numeric(other)])
173
174    def __gt__(self,other):
175        """Greater than operator
176
177        (Called in response to 'self > other' or 'other < self'.)
178        """
179        return plugin.ExpressionFactory('>', [self,as_numeric(other)])
180
181    def __le__(self,other):
182        """Less than or equal operator
183
184        (Called in response to 'self <= other' or 'other >= self'.)
185        """
186        return plugin.ExpressionFactory('<=', [self,as_numeric(other)])
187
188    def __ge__(self,other):
189        """Greater than or equal operator
190
191        (Called in response to 'self >= other' or 'other <= self'.)
192        """
193        return plugin.ExpressionFactory('>=', [self,as_numeric(other)])
194
195    def __eq__(self,other):
196        """Equal to operator
197
198        (Called in response to 'self = other'.)
199        """
200        return plugin.ExpressionFactory('=', [self,as_numeric(other)])
201
202    def __add__(self,other):
203        """Binary addition
204
205        (Called in response to 'self + other'.)
206        """
207        return expr.generate_expression('add',self,other)
208
209    def __sub__(self,other):
210        """ Binary subtraction
211
212        (Called in response to 'self - other'.)
213        """
214        return expr.generate_expression('sub',self,other)
215
216    def __mul__(self,other):
217        """ Binary multiplication
218
219        (Called in response to 'self * other'.)
220        """
221        return expr.generate_expression('mul',self,other)
222
223    def __div__(self,other):
224        """ Binary division
225
226        (Called in response to 'self / other'.)
227        """
228        return expr.generate_expression('div',self,other)
229
230    def __pow__(self,other):
231        """ Binary power
232
233        (Called in response to 'self ** other'.)
234        """
235        return expr.generate_expression('pow',self,other)
236
237    def __radd__(self,other):
238        """Binary addition
239
240        (Called in response to 'other + self'.)
241        """
242        return expr.generate_expression('radd',self,other)
243
244    def __rsub__(self,other):
245        """ Binary subtraction
246
247        (Called in response to 'other - self'.)
248        """
249        return expr.generate_expression('rsub',self,other)
250
251    def __rmul__(self,other):
252        """ Binary multiplication
253
254        (Called in response to 'other * self'.)
255        """
256        return expr.generate_expression('rmul',self,other)
257       
258    def __rdiv__(self,other):
259        """ Binary division
260
261        (Called in response to 'other / self'.)
262        """
263        return expr.generate_expression('rdiv',self,other)
264
265    def __rpow__(self,other):
266        """ Binary power
267
268        (Called in response to 'other ** self'.)
269        """
270        return expr.generate_expression('rpow',self,other)
271
272    def __neg__(self):
273        """ Negation
274
275        (Called in response to '- self'.)
276        """
277        return expr.generate_expression('neg',self)
278
279    def __pos__(self):
280        """ Positive expression
281
282        (Called in response to '+ self'.)
283        """
284        return self
285
286    def __abs__(self):
287        """ Absolute value
288
289        (Called in response to 'abs(self)'.)
290        """
291        return expr.generate_expression('abs',self)
292
293
294class NumericConstant(NumericValue):
295    """An object that contains a constant numeric value"""
296
297    def __init__(self, **kwds):
298        if not 'domain' in kwds:
299            kwds['domain'] = Reals
300        NumericValue.__init__(self,**kwds)
301
302    def fixed_value(self):
303        return True
304
305    def __call__(self, exception=True):
306        return self.value
307
308    def __str__(self):
309        return str(self.value)
310
311    def __eq__(self,other):
312        """Equal to operator
313
314        (Called in response to 'self == other'.)
315        """
316        return self.value == other
317
318    def pprint(self, ostream=None):
319        if ostream is None:
320           ostream = sys.stdout
321        print >>ostream, str(self),
322
323    def simplify(self, model):
324        return self                 #pragma:nocover
325
326
327ZeroConstant = NumericConstant(value=0)
328OneConstant = NumericConstant(value=1)
329
330import expr
Note: See TracBrowser for help on using the repository browser.