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

Last change on this file since 1768 was 1768, checked in by wehart, 11 years ago

Rework of Coopr to use the new PyUtilib? package decomposition.

NOTE: to use Coopr with this update, we need to work with a new version of coopr_install.

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