source: coopr.opt/trunk/coopr/opt/results/container.py @ 2109

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

Changing the API of the SolutionSet? object. Now, all variables, constraints, etc
can be indexed with 1-based integer indices (rather than 0-based). This change
makes this object consistent with the 1-based indexing API supported by Pyomo.

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