source: coopr.opt/stable/2.3/coopr/opt/results/container.py @ 2313

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

Merged revisions 2234-2312 via svnmerge from
https://software.sandia.gov/svn/public/coopr/coopr.opt/trunk

........

r2234 | wehart | 2010-02-01 19:34:02 -0700 (Mon, 01 Feb 2010) | 2 lines


Updating changelog.

........

r2236 | wehart | 2010-02-01 19:38:27 -0700 (Mon, 01 Feb 2010) | 2 lines


Tagging coopr.opt 2.3 release

........

r2250 | wehart | 2010-02-03 13:42:06 -0700 (Wed, 03 Feb 2010) | 3 lines


Update to descriptions of solver status and associted termination
conditions.

........

r2251 | wehart | 2010-02-03 13:56:43 -0700 (Wed, 03 Feb 2010) | 3 lines


Changes due to refinement of termination condition management
Bug fix and update to baseline data.

........

r2257 | wehart | 2010-02-03 22:45:40 -0700 (Wed, 03 Feb 2010) | 6 lines


Augmenting the SolverResults? logic to support default values. This
capability is currently disabled, but I'm leaving it in in case we
want to use this in the future.


Misc fix to the activation logic.

........

r2258 | wehart | 2010-02-03 23:33:12 -0700 (Wed, 03 Feb 2010) | 4 lines


Adding a subpackage for optimization-specific testing tools.
Currently, this contains a customized PyUnit? testing class
that contains new testing functions.

........

r2259 | wehart | 2010-02-04 08:58:44 -0700 (Thu, 04 Feb 2010) | 4 lines


Adding new termination conditions.


Fixing problem setting up testing utilities when YAML is not installed.

........

r2263 | wehart | 2010-02-05 08:18:57 -0700 (Fri, 05 Feb 2010) | 6 lines


Misc rework of the converter utility to recognize that *.py files have
Pyomo models.


NOTE: If we start working with PuLP, then we might have an issue
distinguishing PuLP vs Pyomo Python files.

........

r2280 | jwatson | 2010-02-08 11:26:49 -0700 (Mon, 08 Feb 2010) | 1 line


Adding a suffixes attribute to the base solver class. This is a list of suffixes that the solver will - assuming it can - load into a solution. Examples are rc, dual, slack, etc. I modified the derived solver plugin classes to throw an exception if provided a suffix that it can't handle. I have little doubt that this change will cause some tests to fail - I'll look at this in a bit. The change was motivated by the expense of querying a solution, loading a solution, and shipping a lot of unnecessary information across the network.

........

File size: 12.1 KB
Line 
1
2__all__ = ['UndefinedData', 'undefined', 'ignore', 'ScalarData', 'ListContainer', 'MapContainer', 'default_print_options', 'ScalarType']
3
4from pyutilib.misc import Bunch
5from pyutilib.enum import EnumValue, Enum
6import StringIO
7import copy
8
9ScalarType = Enum('int', 'time', 'string', 'float', 'enum', 'undefined')
10
11default_print_options = Bunch(schema=False, ignore_time=False)
12
13strict=False
14
15class UndefinedData(object):
16
17    def __str__(self):
18        return "<undefined>"
19        #raise TypeError, "Cannot print undefined data"
20
21undefined = UndefinedData()
22ignore    = UndefinedData()
23
24
25class ScalarData(object):
26
27    def __init__(self, value=undefined, description=None, units=None, scalar_description=None, type=ScalarType.undefined, required=False):
28        self.value = value
29        self.description = description
30        self.units = units
31        self.scalar_description = scalar_description
32        self.scalar_type = type
33        self._required=required
34
35    def get_value(self):
36        if type(self.value) is EnumValue:
37            value = str(self.value)
38        elif type(self.value) is UndefinedData:
39            value = '<undefined>'
40        else:
41            value = self.value
42        return value
43
44    def _repn_(self, option):
45        if not option.schema and not self._required and self.value is undefined:
46            return ignore
47        if option.ignore_time and str(self.scalar_type) == str(ScalarType.time):
48            return ignore
49        value = self.get_value()
50        #
51        # Disabled logic for managing default values, and the
52        # ignore_defaults option
53        #
54        #if option.ignore_defaults:
55        #    try:
56        #        if self._default == value:
57        #            return ignore
58        #    except AttributeError:
59        #        pass
60        if option.schema:
61            tmp = {'value':value}
62            if not self.description is None:
63                tmp['description'] = self.description
64            if not self.units is None:
65                tmp['units'] = self.units
66            if not self.scalar_description is None:
67                tmp['description'] = self.scalar_description
68            if not self.scalar_type is ScalarType.undefined:
69                tmp['type'] = self.scalar_type
70            return tmp
71        if not (self.description is None and self.units is None):
72            tmp = {'value':value}
73            if not self.description is None:
74                tmp['description'] = self.description
75            if not self.units is None:
76                tmp['units'] = self.units
77            return tmp
78        return value
79
80    def pprint(self, ostream, option, prefix="", repn=None):
81        if not option.schema and not self._required and self.value is undefined:
82            return ignore
83        if option.ignore_time and str(self.scalar_type) == str(ScalarType.time):
84            return ignore
85        value = self.yaml_fix(self.get_value())
86        if not option.schema and self.description is None and self.units is None:
87            print >>ostream, value
88        else:
89            print >>ostream, ""
90            print >>ostream, prefix+'Value:',value
91            if not option.schema:
92                if not self.description is None:
93                    print >>ostream, prefix+'Description:',self.yaml_fix(self.description)
94                if not self.units is None:
95                    print >>ostream, prefix+'Units:',self.units
96            else:
97                if not self.scalar_description is None:
98                    print >>ostream, prefix+'Description:',self.yaml_fix(self.scalar_description)
99                if not self.scalar_type is ScalarType.undefined:
100                    print >>ostream, prefix+'Type:',self.yaml_fix(self.scalar_type)
101
102    def yaml_fix(self, val):
103        if not isinstance(val,basestring):
104            return val
105        return val.replace(':','\\x3a')
106           
107    def load(self, repn):
108        if type(repn) is dict:
109            for key in repn:
110                setattr(self, key, repn[key])
111        else:
112            self.value = repn
113
114
115#
116# This class manages a list of MapContainer objects.
117#
118class ListContainer(object):
119
120    def __init__(self, cls):
121        self._cls=cls
122        self._list = []
123        self._active=True
124        self._required=False
125
126    def __len__(self):
127        if '_list' in self.__dict__:
128            return len(self.__dict__['_list'])
129        return 0
130
131    def __getitem__(self,i):
132        return self._list[i]
133
134    def __call__(self,i=0):
135        return self._list[i]
136
137    def __getattr__(self,name):
138        try:
139            return self.__dict__[name]
140        except:
141            pass
142        if len(self) == 0:
143            self.add()
144        return getattr(self._list[0], name)
145
146    def __setattr__(self,name,val):
147        if name == "__class__":
148           self.__class__ = val
149           return
150        if name[0] == "_":
151           self.__dict__[name] = val
152           return
153        if len(self) == 0:
154            self.add()
155        setattr(self._list[0], name, val)
156
157    def insert(self, obj):
158        self._active=True
159        self._list.append( obj )
160
161    def add(self):
162        self._active=True
163        obj = self._cls()
164        self._list.append( obj )
165        return obj
166
167    def _repn_(self, option):
168        if not option.schema and not self._active and not self._required:
169            return ignore
170        if option.schema and len(self) == 0:
171            self.add()
172        tmp = []
173        for item in self._list:
174            tmp.append( item._repn_(option) )
175        return tmp
176
177    def pprint(self, ostream, option, prefix="", repn=None):
178        if not option.schema and not self._active and not self._required:
179            return ignore
180        print >>ostream, ""
181        i=0
182        for i in xrange(len(self._list)):
183            item = self._list[i]
184            print >>ostream, prefix+'-',
185            item.pprint(ostream, option, from_list=True, prefix=prefix+"  ", repn=repn[i])
186
187    def load(self, repn):
188        for data in repn:
189            item = self.add()
190            item.load(data)
191
192    def __getstate__(self):
193        return copy.copy(self.__dict__)
194
195    def __setstate__(self, state):
196        self.__dict__.update(state)
197
198
199#
200# This class manages use-defined attributes in
201# a dictionary.  Attributes are translated into
202# a string where '_' is replaced by ' ', and where the
203# first letter is capitalized.
204#
205class MapContainer(dict):
206
207    def __init__(self, ordered=False):
208        dict.__init__(self)
209        self._active=True
210        self._required=False
211        self._ordered=ordered
212        self._order=[]
213        self._option=default_print_options
214
215    def keys(self):
216        return self._order
217
218    def __getattr__(self,name):
219        try:
220            return self.__dict__[name]
221        except:
222            pass
223        try:
224            self._active=True
225            return self[self._convert(name)]
226        except Exception, err:
227            #if name[0] != '_':
228                #print "EXCEPTION: ",str(err),name
229            pass
230        raise AttributeError, "Unknown attribute `"+str(name)+"' for object with type "+str(type(self))
231
232    def __setattr__(self,name,val):
233        if name == "__class__":
234           self.__class__ = val
235           return
236        if name[0] == "_":
237           self.__dict__[name] = val
238           return
239        self._active=True
240        tmp = self._convert(name)
241        if tmp not in self:
242            if strict:
243                raise AttributeError, "Unknown attribute `"+str(name)+"' for object with type "+str(type(self))
244            #else:
245                #print "WARNING: creating attribute '"+str(name)+"' for object with type "+str(type(self))
246            #print "DECL1"
247            self.declare(tmp)
248        self._set_value(tmp,val)
249
250    def __setitem__(self, name, val):
251        self._active=True
252        tmp = self._convert(name)
253        if tmp not in self:
254            if strict:
255                raise AttributeError, "Unknown attribute `"+str(name)+"' for object with type "+str(type(self))
256            #else:
257                #print "WARNING: creating attribute '"+str(name)+"' for object with type "+str(type(self))
258            #print "DECL1"
259            self.declare(tmp)
260        self._set_value(tmp,val)
261
262    def _set_value(self, name, val):
263        dict.__getitem__(self, name).value = val
264
265    def __getitem__(self, name):
266        tmp = self._convert(name)
267        if tmp not in self:
268            raise AttributeError, "Unknown attribute `"+str(name)+"' for object with type "+str(type(self))
269        item = dict.__getitem__(self, tmp)
270        if isinstance(item,ListContainer) or isinstance(item,MapContainer):
271            return item
272        return item.value
273
274    def declare(self, name, **kwds):
275        if name in self or type(name) is int:
276            return
277        tmp = self._convert(name)
278        self._order.append(tmp)
279        if 'value' in kwds and (isinstance(kwds['value'],MapContainer) or isinstance(kwds['value'],ListContainer)):
280            if 'active' in kwds:
281                kwds['value']._active = kwds['active']
282            if 'required' in kwds and kwds['required'] is True:
283                kwds['value']._required = True
284            dict.__setitem__(self, tmp, kwds['value'])
285        else:
286            data = ScalarData(**kwds)
287            if 'required' in kwds and kwds['required'] is True:
288                data._required = True
289            #
290            # This logic would setup a '_default' value, which copies the
291            # initial value of an attribute.  I don't think we need this,
292            # but for now I'm going to leave this logic in the code.
293            #
294            #if 'value' in kwds:
295            #    data._default = kwds['value']
296            dict.__setitem__(self, tmp, data)
297
298    def _repn_(self, option):
299        if not option.schema and not self._active and not self._required:
300            return ignore
301        if self._ordered:
302            tmp = []
303            for key in self._order:
304                rep = dict.__getitem__(self, key)._repn_(option)
305                if not rep == ignore:
306                    tmp.append({key:rep})
307        else:
308            tmp = {}
309            for key in self.keys():
310                rep = dict.__getitem__(self, key)._repn_(option)
311                if not rep == ignore:
312                    tmp[key] = rep
313        return tmp
314
315    def _convert(self, name):
316        if not isinstance(name,basestring):
317            return name
318        tmp = name.replace('_',' ')
319        return tmp[0].upper() + tmp[1:]
320
321    def __repr__(self):
322        return str(self._repn_(self._option))
323
324    def __str__(self):
325        ostream = StringIO.StringIO()
326        option=default_print_options
327        self.pprint(ostream, self._option, repn=self._repn_(self._option))
328        return ostream.getvalue()
329
330    def pprint(self, ostream, option, from_list=False, prefix="", repn=None):
331        if from_list:
332            _prefix=""
333        else:
334            _prefix=prefix
335            print >>ostream, ""
336        for key in self._order:
337            if not key in repn:
338                continue
339            item = dict.__getitem__(self,key)
340            print >>ostream, _prefix+key+":",
341            _prefix=prefix
342            if isinstance(item, ListContainer):
343                item.pprint(ostream, option, prefix=_prefix, repn=repn[key])
344            else:
345                item.pprint(ostream, option, prefix=_prefix+"  ", repn=repn[key])
346
347    def load(self, repn):
348        for key in repn:
349            tmp = self._convert(key)
350            if tmp not in self:
351                self.declare(tmp)
352            item = dict.__getitem__(self,tmp)
353            item._active=True
354            item.load(repn[key])
355
356    def __getstate__(self):
357        return copy.copy(self.__dict__)
358 
359    def __setstate__(self, state):
360        self.__dict__.update(state)
361
362
363if __name__ == '__main__':
364    d=MapContainer()
365    d.declare('f')
366    d.declare('g')
367    d.declare('h')
368    d.declare('i', value=ListContainer(UndefinedData))
369    d.declare('j', value=ListContainer(UndefinedData), active=False)
370    print "X"
371    d.f = 1
372    print "Y"
373    print d.f
374    print d.keys()
375    d.g = None
376    print d.keys()
377    try:
378        print d.f, d.g, d.h
379    except:
380        pass
381    d['h'] = None
382    print ""
383    print "FINAL"
384    print d.f, d.g, d.h, d.i, d.j
385    print d.i._active, d.j._active
386    d.j.add()
387    print d.i._active, d.j._active
388
Note: See TracBrowser for help on using the repository browser.