Changeset 5803


Ignore:
Timestamp:
May 24, 2012 6:57:33 PM (7 years ago)
Author:
jdsiiro
Message:

Major overhaul of Pyomo Param:

  • adding a new "SparseIndexedComponent? class that implements an improved version of IndexedComponent?. Hopefully this will eventually replace IndexedComponent? entirely.
  • eliminating the param_repn; everything now uses a (sparse) Python dict
  • implementing the concept of "mutability" to determine when we need to preserve _ParamData objects and when we can reduce to native Python floats.
  • Currently, Params default to "mutable" for backwards compatibility
  • All errors for unintialized Params is now deferred to when the Param is *used* (the old Param was inconsistent: singleton Params errored in construct(), but indexed Params deferred it to point of use (if any error was generated at all)
  • all (concrete) Param tests that were previously failing now pass.
Location:
coopr.pyomo/trunk
Files:
1 added
1 deleted
12 edited

Legend:

Unmodified
Added
Removed
  • coopr.pyomo/trunk/coopr/pyomo/base/__init__.py

    r5632 r5803  
    1515from label import *
    1616from plugin import *
    17 import param_repn
    1817from PyomoModelData import *
    1918#
  • coopr.pyomo/trunk/coopr/pyomo/base/block.py

    r5792 r5803  
    408408    def _add_temporary_set(self,val):
    409409        """ TODO """
    410         if val._index_set is not None:
     410        # NB: only "old" IndexedComponent contain _index_set.
     411        # SparseIndexedComponent does not have that attribute
     412        if '_index_set' in dir(val) and val._index_set is not None:
    411413            ctr=0
    412414            for tset in val._index_set:
  • coopr.pyomo/trunk/coopr/pyomo/base/numvalue.py

    r5769 r5803  
    7979        tmp = numeric()
    8080    except:
    81         logger.error("evaluating object as numeric value: %s\n   (object: %s)"
    82                      % (obj, type(obj)))
     81        logger.error(
     82            "evaluating object as numeric value: %s\n\t(object: %s)\n\t%s"
     83            % (obj, type(obj), sys.exc_info()[1]))
    8384        raise ValueError
    8485   
  • coopr.pyomo/trunk/coopr/pyomo/base/param.py

    r5761 r5803  
    1111__all__ = ['Param']
    1212
    13 import sys
    1413import types
    1514import logging
    16 
    17 import pyutilib.misc
     15import weakref
     16
     17from pyutilib.component.core import alias
     18import pyutilib.math
     19
    1820from component import Component
    19 from set_types import Any
    20 from indexed_component import IndexedComponent
    21 from misc import apply_indexed_rule, apply_parameterized_indexed_rule
     21from sparse_indexed_component import SparseIndexedComponent
     22from misc import apply_indexed_rule, apply_parameterized_indexed_rule, \
     23     create_name
     24from numvalue import NumericConstant
     25from set_types import Any, Reals
     26
    2227from numvalue import value
    23 from plugin import ParamRepresentationFactory
    24 from pyutilib.component.core import alias
    25 from param_repn import _ParamData
    2628
    2729logger = logging.getLogger('coopr.pyomo')
    2830
    29 
    30 class Param(IndexedComponent):
     31class _ParamData(NumericConstant):
     32    """Holds the numeric value of a mutable parameter"""
     33
     34    __slots__ = []
     35
     36    def __init__(self, name, domain, value):
     37        """Constructor"""
     38        #
     39        # NumericConstant.__init__(self, name, domain, value)
     40        #
     41        if domain is None:
     42            self.domain = Reals
     43        else:
     44            self.domain = domain
     45        self.name = name
     46        if pyutilib.math.is_nan(value):
     47            self.value = pyutilib.math.nan
     48        else:
     49            self.value = value
     50
     51
     52    def __str__(self):
     53        return str(self.name)
     54
     55    def clear(self):
     56        self.value = None
     57
     58
     59class Param(SparseIndexedComponent):
    3160    """A parameter value, which may be defined over a index"""
    3261
     
    4978    """
    5079
    51     alias("Param", doc="Parameter data that is used to define a model instance.", subclass=True)
     80    alias( "Param",
     81           doc="Parameter data that is used to define a model instance.",
     82           subclass=True )
    5283
    5384    def __new__(cls, *args, **kwds):
     
    6091
    6192    def __init__(self, *args, **kwd):
     93        kwd.pop('repn',None)
     94       
    6295        self._initialize = kwd.pop('initialize', None )
    6396        self._initialize = kwd.pop('rule', self._initialize )
     
    6598        self.domain      = kwd.pop('within', Any )
    6699        self.nochecking  = kwd.pop('nochecking',False)
    67         defaultval       = kwd.pop('default', None )
    68         self.repn_type = kwd.pop('repn', 'pyomo_dict')
     100        self._mutable    = kwd.pop('mutable', True )
     101
     102        self._default_val = None
     103        # Use set_default() so that we vaidate the value against the domain
     104        self.set_default(kwd.pop('default', None ))
     105       
    69106        #
    70107        kwd.setdefault('ctype', Param)
    71         IndexedComponent.__init__(self, *args, **kwd)
    72         #
    73         self._default = _ParamData( self.name, self.domain, value(defaultval))
    74         #
    75         self.clear()
    76 
    77     def clear(self):
    78         """Clear the data in this component"""
    79         self._data = ParamRepresentationFactory( self.repn_type, args=(self,) )
    80         if self._data is None:
    81             raise ValueError, "Unknown parameter representation '%s'" % self.repn_type
    82 
    83     def initialize(self, data):
    84         self._initialize = data
     108        SparseIndexedComponent.__init__(self, *args, **kwd)
     109       
     110        # Because we want to defer the check for defined values until
     111        # runtime, we will undo the weakref to ourselves
     112        if not self.is_indexed():
     113            del self._data[None]
     114
    85115
    86116    def pprint(self, ostream=None, verbose=False):
    87117        if ostream is None:
    88118            ostream = sys.stdout
    89         print >>ostream, "  ",self.name,":",
    90         if not self.doc is None:
    91             print >>ostream, self.doc
    92             print >>ostream, "  ",
    93         print >>ostream, "\tSize="+str(len(self)),
    94         print >>ostream, "\tDomain="+self.domain.name
    95         if None in self.keys():
    96             if self._constructed is True:
    97                 print >>ostream, "\t", self._data(None)
    98             else:
    99                 print >>ostream, "\t", "Not constructed"
    100         else:
    101             tmp=self._data.keys(nondefault=True)
    102             tmp.sort()
    103             for key in tmp:
    104                 val = self._data(key)
    105                 print >>ostream, "\t"+str(key)+" : "+str(val)
    106         if self._default.value is not None and not self._default.value is None:
    107             print >>ostream, "\tdefault: "+str(self._default.value)
     119        ostream.write( "  %s : " % (self.name,))
     120        if self.doc is not None:
     121            ostream.write("\t%s\n" % (self.doc,))
     122        ostream.write( "\tSize=%s \tDomain=%s\n"
     123                       % (len(self), self.domain.name) )
     124        if not self._constructed:
     125            ostream.write("\tNot constructed\n")
     126        elif None in self.keys():
     127            if None in self._data:
     128                ostream.write("\t%s\n" % ( value(self._data[None]()), ))
     129            else:
     130                ostream.write("\tUndefined\n")
     131        else:
     132            for key, val in sorted(self.sparse_iteritems()):
     133                ostream.write("\t%s : %s\n" % (key, value(val)))
     134        if self._default_val is not None:
     135            ostream.write("\tdefault: %s\n" % (value(self._default_val)))
    108136
    109137    #
     
    115143    #       explicitly defined - issues around defaults are bound
    116144    #       to crop up.
     145    # NOTE: Using this method will cause sparse mutable Params to become
     146    #       dense!
    117147    #
    118148    def extract_values(self):
    119         return self._data.extract_values()
    120 
    121     # a utility to set values of a parameter "in bulk", using a dictionary of index<->value pairs.
    122     # far more efficient in some contexts than the approach of doing things by-index in an outer loop.   
    123     def store_values(self, new_values):
    124         return self._data.store_values(new_values)
    125 
    126     def set_default(self, value):
    127         self._default.value = value
    128         self._data.set_default(value)
    129 
    130     def as_numeric(self):
    131         if None in self._data:
    132             return self._data[None]
    133         return self
    134 
    135     def is_expression(self):
    136         return False
    137 
    138     def is_relational(self):
    139         return False
     149        return dict((key,value(val)) for key,val in self.iteritems())
     150
     151    def sparse_extract_values(self):
     152        return dict((key,value(val)) for key,val in self.sparse_iteritems())
     153
     154
     155    def _default(self, idx):
     156        if self._default_val is None:
     157            if idx is None:
     158                idx_str = '%s' % (self.name,)
     159            else:
     160                idx_str = '%s[%s]' % (self.name, idx,)
     161            raise ValueError(
     162                "Error retrieving Param value (%s): The Param value is "
     163                "undefined and no default value is specified"
     164                % ( idx_str,) )
     165        if self._mutable:
     166            if self.is_indexed():
     167                return self._data.setdefault(
     168                    idx, _ParamData( create_name(self.name,idx),
     169                                     self.domain, self._default_val ) )
     170            else:
     171                self[None] = self._default_val
     172                return self
     173        else:
     174            return self._default_val
     175
     176    def set_default(self, val):
     177        if val is not None and val not in self.domain:
     178            raise ValueError(
     179                "Default value (%s) is not valid for Param domain %s" %
     180                ( str(val), self.domain.name ) )
     181        self._default_val = val
    140182
    141183    def __setitem__(self, ndx, val):
    142         # Convert a tuple index value ...
    143         _type = type(ndx)
    144         if _type is tuple or _type is list:
    145             if self._ndim == 1:
    146                 # An index for a single-dimensional parameter is just the first tuple value
    147                 ndx = ndx[0]
    148             else:
    149                 # Flatten index for a multi-dimensional non-singleton parameter
    150                 ndx = tuple(pyutilib.misc.flatten(ndx))
    151 
    152         # a somewhat gory way to see if you have a singleton - the len()=1 check is needed to avoid "None"
    153         # being passed illegally into set membership validation rules. the nochecking screen saves
    154         # significant time here, as the len() computation is remarkably expensive.
    155         if (self.nochecking is False) and (len(self._index) == 1) and (None in self._index) and (ndx is not None): 
    156             # allow for None indexing only if this is truly a singleton
    157             msg = "Cannot set an array value in the simple parameter '%s'"
    158             raise KeyError, msg % self.name
    159         #
    160         if (self.nochecking is False) and (ndx not in self._index):
    161             msg = "Cannot set the value of array parameter '%s' with invalid index '%s'"
    162             raise KeyError, msg % ( self.name, str(ndx) )
    163         #
    164         self._data[ndx] = val
     184        if self._constructed and not self._mutable:
     185            raise TypeError(
     186"""Attempring to set the value of the immutable parameter %s after the
     187parameter has been constructed.  If you intend to change the value of
     188this parameter dynamically, please declare the parameter as mutable
     189[i.e., Param(mutable=True)]""" % (self.name,))
     190
     191        #print "setting %s[%s] = %s" % (self.name, ndx, val)
     192        # Validate the index
     193        if self.nochecking:
     194            # Ironically, if we are *not* checking index values, then we
     195            # *must* flatten the incoming index tuple
     196            ndx = self.normalize_index(ndx)
     197        # Potential optimization: if we find that updating a Param is
     198        # more common than setting it in the first place, then first
     199        # checking the _data and then falling back on the _index *might*
     200        # be more efficient.
     201        #
     202        #elif ndx not in _data and ndx not in self._index:
     203        elif ndx not in self._index:
     204            # We rely on "most" people doing things correctly; that is,
     205            # they send us either a scalar or a valid tuple.  So, for
     206            # efficiency, we will check the index *first*, and only go
     207            # through the hassle of flattening things if the ndx is not
     208            # found.
     209            ndx = self.normalize_index(ndx)
     210            if ndx not in self._index:
     211                if not self.is_indexed():
     212                    msg = "Error setting parameter value: " \
     213                          "Cannot treat the scalar Param '%s' as an array" \
     214                          % ( self.name, )
     215                else:
     216                    msg = "Error setting parameter value: " \
     217                          "Index '%s' is not valid for array Param '%s'" \
     218                          % ( ndx, self.name, )
     219                raise KeyError(msg)
     220
     221        if ndx is None:
     222            self.value = val
     223            self._data[ndx] = weakref.ref(self)
     224        elif self._mutable:
     225            if ndx in self._data:
     226                self._data[ndx].value = val
     227            else:
     228                self._data[ndx] = _ParamData(create_name(self.name,ndx), self.domain, val)
     229        else:
     230            self._data[ndx] = val
     231
    165232        #
    166233        # This is at the end, so the user can write their validation
    167234        # tests as if the data was already added.
    168235        #
    169         if (self.nochecking is False) and (not self._valid_indexed_value(val, ndx, False)):
    170             msg = "Invalid parameter value: %s[%s] = '%s', value type=%s"
    171             raise ValueError, msg % ( self.name, str(ndx), str(val), str(type(val)) )
     236        if self.nochecking:
     237            return
     238        if val not in self.domain:
     239            raise ValueError(
     240                "Invalid parameter value: %s[%s] = '%s', value type=%s.\n"
     241                "\tValue not in parameter domain %s" %
     242                ( self.name, ndx, val, type(val), self.domain.name ) )
     243        if self._validate is not None:
     244            if self.is_indexed():
     245                if type(ndx) is tuple:
     246                    tmp = ndx
     247                else:
     248                    tmp = (ndx,)
     249            else:
     250                tmp = ()
     251            if not apply_parameterized_indexed_rule(
     252                self, self._validate, self._model(), val, tmp ):
     253                raise ValueError(
     254                    "Invalid parameter value: %s[%s] = '%s', value type=%s.\n"
     255                    "\tValue failed parameter validation rule" %
     256                    ( self.name, ndx, val, type(val) ) )
    172257
    173258    def construct(self, data=None):
     
    175260        if __debug__:
    176261            if logger.isEnabledFor(logging.DEBUG):
    177                 logger.debug("Constructing Param, name="+self.name+", from data="+`data`)
     262                logger.debug("Constructing Param, name=%s, from data=%s"
     263                             % ( self.name, `data` ))
    178264        if self._constructed:
    179             raise IOError, "Cannot reconstruct parameter '%s'" % self.name
     265            raise IOError(
     266                "Cannot reconstruct parameter '%s' (already constructed)"
     267                % self.name )
    180268            return
    181269        self.clear()
    182         self._constructed=True
    183         #
    184         # Code optimization with local variables
    185         #
    186         _name=self.name
    187         _domain=self.domain
    188         #
    189         self._data.update_index()
     270        #
    190271        rule = getattr(self,'rule',None)
    191         if not rule is None:
     272        if rule is not None:
    192273            self._initialize=rule
    193274        #
     
    197278        #   1) the 'data' dictionary
    198279        #   2) the self._initialize dictionary
    199         #   3) the default value
    200         #
    201         if data is not None or type(self._initialize) is not types.FunctionType:
    202             #
    203             # Singleton (non-indexed) parameter
    204             #
    205             #print self._data, self._initialize, self._default.value, self._index
    206             if type(self._index) is dict:
    207                 error = False
    208                 if data is not None and None in data.keys():
    209                     self.value=data[None]
    210                 elif not self._initialize is None:
    211                     if type(self._initialize) is not dict:
    212                         self.value=self._initialize
    213                     elif None in self._initialize:
    214                         self.value=self._initialize[None]
    215                     else:
    216                         error = True
    217                 elif self._default.value is not None:
    218                     self.value=self._default.value
     280        #   3) [implicit: fall back on the default value]
     281        #
     282        # To accomplish this, we will first set all the values based on
     283        # self._initialize, and then allow the data to overwrite
     284        # anything
     285        #
     286        # NB: Singleton Params can always be treated as "normal" indexed
     287        # params, indexed by a set {None}.
     288        #
     289
     290        # NB: Previously, we would raise an exception for constructing
     291        # scalar parameters with no defined data.  As that was a special
     292        # case (i.e. didn't apply to arrays) and was frustrating for
     293        # Concrete folks who were going to initialize the value later,
     294        # we will allow an undefined Param to be constructed and will
     295        # instead throw an exception later i the user tries to *use* the
     296        # Param before it is initialized.
     297        #
     298        #if self._initialize is None:
     299        #    if data is None and self._default_val is None:
     300        #        raise ValueError(
     301        #            "Error constructing Param '%s': cannot locate the Param "
     302        #            "data (not found in rule or external data, and no "
     303        #            "default value specified)" % ( self.name, ) )
     304        if self._initialize is not None:
     305            _init = self._initialize
     306            _init_type = type(_init)
     307            if _init_type is dict:
     308                for key, val in _init.iteritems():
     309                    self[key] = val
     310            elif _init_type is types.FunctionType:
     311                if self.is_indexed():
     312                    for idx in self:
     313                        # IMPORTANT: Do *not* call self.__setitem__ here
     314                        #    - we already know the index is valid (and
     315                        #    flattened), and validating indices is far too
     316                        #    expensive to waste time doing it
     317                        #    again. however, we still need to validate the
     318                        #    value generated by the rule, relative to the
     319                        #    parameter domain.
     320                        # REVISION: given the rewrite of __setitem__,
     321                        #    the index is not validated unless it is not
     322                        #    found in the corresponding data / index.  We
     323                        #    *could* reimplement the optimization metioned
     324                        #    above if it proves necessary, but until then,
     325                        #    the DRY principle dictates that we use
     326                        #    __setitem__.
     327                        self[idx] = apply_indexed_rule(
     328                            self, _init, self._model(), idx )
    219329                else:
    220                     error = True
    221                 if error:
    222                     msg = "Attempting to construct parameter '%s' without "   \
    223                           'parameter data'
    224                     raise ValueError, msg % _name
    225 
    226                 #self.pprint()
    227                 #print self.value#, self[None].value
    228                 self[None] = self.value
    229                 self._valid_indexed_value(self.value,(),True)
    230             else:
    231                 #
    232                 # Set external data values (if provided)
    233                 #
    234                 if data is not None:
    235                     #print 'z'
    236                     for key in data:
    237                         if type(key) is tuple and len(key)==1:
    238                             tmpkey=key[0]
    239                         else:
    240                             tmpkey=key
    241                         self.__setitem__(key, data[key])
    242                 #
    243                 # Initialize with initialization data.
    244                 #
    245                 elif self._initialize is not None:
    246                     #print 'y'
    247                     if type(self._initialize) is dict:
    248                         for key in self._initialize:
    249                             self.__setitem__(key, self._initialize[key])
    250                     else:
    251                         self._data.set_item(val=self._initialize)
    252         #
    253         # Construct using the rule
    254         #
    255         elif type(self._initialize) is types.FunctionType:
    256             if (type(self._index) is dict) and (None in self._index):
    257                 # singleton
    258                 self.value = self._initialize(self._model())
    259                 self[None] = self.value
    260             else:
    261                 # non-singleton
    262                 for index in self._index:
    263                     # IMPORTANT: Do *not* call self.__setitem__ here - we already know the index is
    264                     #            valid (and flattened), and validating indices is far too expensive to
    265                     #            waste time doing it again. however, we still need to validate the
    266                     #            value generated by the rule, relative to the parameter domain.
    267                     param_value = apply_indexed_rule(self, self._initialize, self._model(), index)
    268                     if not ((self.domain is Any) or (param_value in self.domain)):
    269                         msg = "Invalid value '%s' specified via rule initializer for parameter '%s', index '%s'"
    270                         raise ValueError, msg % (str(param_value), self.name, index)
    271                     self._data[index] = param_value
    272         #
    273         if self.repn_type != 'pyomo_dict':
    274             self._model().__dict__[self.name] = self._data.model_repn()
    275 
    276     def _valid_indexed_value(self, value, index, use_exception):
    277         if index is ():
    278             if None not in self._index:
    279                 msg = "Invalid index '%s' for parameter '%s'"
    280                 raise ValueError, msg % ( str(None), self.name )
    281         elif type(index) is tuple and len(index)==1:
    282             if index not in self._index and index[0] not in self._index:
    283                 msg = "Invalid index '%s' for parameter '%s'"
    284                 raise ValueError, msg % ( str(index[0]), self.name)
    285         elif index not in self._index:
    286             msg = "Invalid index '%s' for parameter '%s'"
    287             raise ValueError, msg % ( str(index), self.name)
    288         #
    289         if self._validate is not None:
    290             if index is None:
    291                 tmp = ()
    292             elif index == ():
    293                 tmp = (None,)*self._ndim
    294             else:
    295                 tmp = index
    296 
    297             if apply_parameterized_indexed_rule(
    298                 self, self._validate, self._model(), value, tmp ):
    299                 return True
    300         #
    301         elif self.domain is Any or value in self.domain:
    302             return True
    303         #
    304         if use_exception:           #pragma:nocover
    305             msg = "Invalid value '%s' for parameter '%s'"
    306             raise ValueError, msg % ( str(value), self.name )
    307         #
    308         return False
    309 
    310     def data(self):
    311         return self._data.data()
    312 
    313 
    314 class _ParamElement(Param, _ParamData):
     330                    self[None] = _init(self._model())
     331            else:
     332                # if things looks like a dictionary, then we will treat
     333                # it as such
     334                _isDict = '__getitem__' in dir(_init)
     335                if _isDict:
     336                    try:
     337                        for x in _init:
     338                            _init.__getitem__(x)
     339                    except:
     340                        _isDict = False
     341                if _isDict:
     342                    for key in self._initialize:
     343                        self[key] = self._initialize[key]
     344                else:
     345                    for key in self._index:
     346                        self[key] = self._initialize
     347               
     348        if data is not None:
     349            for key, val in data.iteritems():
     350                self[key] = val
     351
     352        self._constructed = True
     353
     354
     355class _ParamElement(_ParamData, Param):
    315356
    316357    def __init__(self, *args, **kwds):
    317         repn_name = kwds.get('repn', 'pyomo_dict')
    318 
    319358        Param.__init__(self, *args, **kwds)
    320         _ParamData.__init__(self, kwds.get('name',None), kwds.get('within',Any), kwds.get('default',None))
    321 
    322         if repn_name == 'pyomo_dict':
    323             self._data.set_item(None, self)
    324         else:
    325             self._data.set_item(None, self._default.value)
     359        _ParamData.__init__(self, self.name, self.domain, kwds.get('default',None))
    326360
    327361    def __getstate__(self):
    328         parambase_result = Param.__getstate__(self)
    329         paramvalue_result = _ParamData.__getstate__(self)
    330         return dict(parambase_result.items() + paramvalue_result.items())   
     362        ans = _ParamData.__getstate__(self)
     363        ans.update(Param.__getstate__(self))
     364        return ans
    331365
    332366    def __setstate__(self, state):
    333367        for (slot_name, value) in state.iteritems():
    334368            setattr(self, slot_name, value)
    335        
    336     def __len__(self):
    337         return 1
    338 
    339     def keys(self):
    340         return [None]
    341 
    342     def __getitem__(self, key):
    343         if not key is None:
    344             raise KeyError, "Undefined key %s for parameter %s" % (key, self.name)
    345         return Param.__getitem__(self,key)
    346 
    347     def __setitem__(self, key, value):
    348         if not key is None:
    349             raise KeyError, "Undefined key %s for parameter %s" % (key, self.name)
    350         return Param.__setitem__(self,key,value)       
    351 
    352     def check_values(self):         #pragma:nocover
    353         #
    354         # Validate the values
    355         #
    356         if None not in self._index:
    357             raise ValueError, "Undefined value for parameter "+self.name
    358         if not self._valid_indexed_value(self.value,None,False):
    359             msg = "Parameter '%s' failed validation test.  Value: %s"
    360             raise ValueError, msg % ( self.name, str(self.value) )
    361 
    362     def __call__(self, exception=True):
    363         return self.value
    364 
     369
     370    # Needed so that users find Param.pprint and not _ParamData.pprint
     371    def pprint(self, ostream=None, verbose=False):
     372        Param.pprint(self, ostream=ostream, verbose=verbose)
     373
     374    # Needed because we rely on self[None] to know if this parameter is valid
     375    def __call__(self, *args, **kwds):
     376        return _ParamData.__call__(self[None], *args, **kwds)
    365377
    366378class _ParamArray(Param):
     
    369381        Param.__init__(self, *args, **kwds)
    370382
    371     def __float__(self):
    372         msg = "Cannot access the value of array parameter '%s'"
    373         raise ValueError, msg % self.name
    374 
    375     def __int__(self):
    376         msg = "Cannot access the value of array parameter '%s'"
    377         raise ValueError, msg % self.name
    378 
    379     def set_value(self, value):
    380         for key in self._data:
    381             self.__setitem__(key,value)
    382 
    383     def check_values(self):         #pragma:nocover
    384         #
    385         # Validate the values
    386         #
    387         for key in self._data:
    388             if key not in self._index:
    389                 msg = "Undefined value for parameter %s[%s]"
    390                 raise ValueError, msg % ( self.name, str(key) )
    391 
    392             val = self._data(key)
    393             if not self._valid_indexed_value( val, key, False ):
    394                 msg = "Parameter %s[%s] failed validation test.  Value: %s"
    395                 raise ValueError, msg % ( self.name, str(key), str(tval) )
    396 
    397     def reset(self):
    398         pass                        #pragma:nocover
    399 
    400     def display(self, ostream=None):
    401         self.pprint(ostream=ostream)
    402 
    403383    def __str__(self):
    404384        return str(self.name)
  • coopr.pyomo/trunk/coopr/pyomo/scripting/util.py

    r5777 r5803  
    190190            action = "running"
    191191
    192         msg = "Unexpected exception while %s %s\n" % (action, name)
     192        msg = "Unexpected exception (%s) while %s %s\n" % (etype.__name__, action, name)
    193193
    194194        #
     
    198198        # quotes at either end of the error message. This undoes all that.
    199199        #
     200        valueStr = str(value)
    200201        if etype == KeyError:
    201             valueStr = str(value).replace("\\n","\n")[1:-1]
    202         else:
    203             valueStr = str(value)
     202            valueStr = valueStr.replace("\\n","\n")
     203            if valueStr[0] == valueStr[-1] and valueStr[0] in "\"'":
     204                valueStr = valueStr[1:-1]
    204205
    205206        logger.error(msg+valueStr)
  • coopr.pyomo/trunk/coopr/pyomo/tests/unit/test_action.py

    r5719 r5803  
    1414from coopr.pyomo import *
    1515
    16 class PyomoModel(unittest.TestCase):
    17 
    18     def setUp(self):
    19         self.model = AbstractModel()
    20 
    21     def construct(self,filename):
    22         self.instance = self.model.create(filename)
    23 
    2416
    2517def action1_fn(model):
     
    3022        model.A[i] = value(model.A[i])+i
    3123
     24def action3_fn(model, i):
     25    if i in model.A.sparse_keys():
     26        model.A[i] = value(model.A[i])+i
    3227
    33 class Simple(PyomoModel):
     28
     29class Simple(unittest.TestCase):
    3430
    3531    def setUp(self):
    3632        #
    37         # Create Model
    38         #
    39         PyomoModel.setUp(self)
    40         #
    4133        # Create model instance
    4234        #
    43         self.model.A = Param(initialize=3.3)
    44         self.model.action1 = BuildAction(rule=action1_fn)
    45         self.instance = self.model.create()
     35        model = AbstractModel()
     36        model.A = Param(initialize=3.3)
     37        model.action1 = BuildAction(rule=action1_fn)
     38        self.instance = model.create()
    4639
    4740    def tearDown(self):
     41        self.instance = None
    4842        if os.path.exists("param.dat"):
    4943            os.remove("param.dat")
     
    5549        self.assertEqual( tmp, 4.3 )
    5650        # BUG  TODO: this is a bug ... but we're going to ignore it for now
    57         #self.assertEqual( value(self.instance.A.value), value(self.instance.A) )
     51        #self.assertEqual( value(instance.A.value), value(instance.A) )
    5852
    5953    def test_getattr(self):
     
    6357
    6458
    65 class Array1(PyomoModel):
     59class Array_Param(unittest.TestCase):
    6660
    67     def setUp(self):
    68         #
    69         # Create Model
    70         #
    71         PyomoModel.setUp(self)
     61    def test_sparse_param_nodefault(self):
    7262        #
    7363        # Create model instance
    7464        #
    75         self.model.Z = Set(initialize=[1,3])
    76         self.model.A = Param(self.model.Z, initialize={1:1.3})
    77         self.model.action2 = BuildAction(self.model.Z, rule=action2_fn)
    78         self.instance = self.model.create()
     65        model = AbstractModel()
     66        model.Z = Set(initialize=[1,3])
     67        model.A = Param(model.Z, initialize={1:1.3})
     68        model.action2 = BuildAction(model.Z, rule=action2_fn)
     69        self.assertRaises(ValueError, model.create)
    7970
    80     def test_value(self):
    81         """Check the value of the parameter"""
    82         tmp = value(self.instance.A[1])
     71    def test_sparse_param_nodefault_sparse_iter(self):
     72        #
     73        # Create model instance
     74        #
     75        model = AbstractModel()
     76        model.Z = Set(initialize=[1,3])
     77        model.A = Param(model.Z, initialize={1:1.3})
     78        model.action2 = BuildAction(model.Z, rule=action3_fn)
     79        instance = model.create()
     80
     81        tmp = value(instance.A[1])
     82        self.assertEqual( type(tmp), float)
     83        self.assertEqual( tmp, 2.3 )
     84
     85    def test_sparse_param_default(self):
     86        #
     87        # Create model instance
     88        #
     89        model = AbstractModel()
     90        model.Z = Set(initialize=[1,3])
     91        model.A = Param(model.Z, initialize={1:1.3}, default=0)
     92        model.action2 = BuildAction(model.Z, rule=action2_fn)
     93        instance = model.create()
     94
     95        tmp = value(instance.A[1])
    8396        self.assertEqual( type(tmp), float)
    8497        self.assertEqual( tmp, 2.3 )
    8598
    8699
    87 class Array2(PyomoModel):
    88 
    89     def setUp(self):
    90         #
    91         # Create Model
    92         #
    93         PyomoModel.setUp(self)
     100    def test_dense_param(self):
    94101        #
    95102        # Create model instance
    96103        #
    97         self.model.Z = Set(initialize=[1,3])
    98         self.model.A = Param(self.model.Z, initialize=1.3)
    99         self.model.action2 = BuildAction(self.model.Z, rule=action2_fn)
    100         self.instance = self.model.create()
     104        model = AbstractModel()
     105        model.Z = Set(initialize=[1,3])
     106        model.A = Param(model.Z, initialize=1.3)
     107        model.action2 = BuildAction(model.Z, rule=action2_fn)
     108        instance = model.create()
    101109
    102     def test_getitem(self):
    103         """Check the use of getitem"""
    104         self.assertEqual( self.instance.A[1], 2.3)
    105         self.assertEqual( value(self.instance.A[3]), 4.3)
     110        self.assertEqual( instance.A[1], 2.3)
     111        self.assertEqual( value(instance.A[3]), 4.3)
    106112
    107113
  • coopr.pyomo/trunk/coopr/pyomo/tests/unit/test_check.py

    r5207 r5803  
    8888        #
    8989        self.model.Z = Set(initialize=[1,3])
    90         self.model.A = Param(self.model.Z, initialize={1:1.3})
     90        self.model.A = Param(self.model.Z, initialize=1.3)
    9191
    9292    def test_true(self):
  • coopr.pyomo/trunk/coopr/pyomo/tests/unit/test_expr.py

    r5707 r5803  
    6767        self.assertTrue(a._valid_value(a.value))
    6868
    69         b = self.create(1.3, Integers)
    70         self.assertRaises(ValueError, b._valid_value, b.value)
    71         self.assertEqual(b._valid_value(b.value, False), False)
     69        try:
     70            # Some platforms will not let us create an invalid value
     71            b = self.create(1.3, Integers)
     72            self.assertRaises(ValueError, b._valid_value, b.value)
     73            self.assertEqual(b._valid_value(b.value, False), False)
     74        except ValueError:
     75            pass
    7276
    7377    def Xtest_getattr(self):
     
    240244
    241245    def create(self,val,domain):
    242         tmp=Param(within=domain)
    243         tmp.value = val
     246        tmp=Param(default=val,within=domain)
    244247        return tmp
    245248
     
    15581561            self.fail("Expected m.z*m.p to raise a TypeError")
    15591562        except TypeError:
     1563            pass
     1564        except ValueError:
    15601565            pass
    15611566
  • coopr.pyomo/trunk/coopr/pyomo/tests/unit/test_misc.py

    r4119 r5803  
    3838        instance = model.create()
    3939        expr = instance.x + 1
    40         instance.reset()
     40        #instance.reset()
    4141        OUTPUT = open(currdir+"/display.out","w")
    4242        display(instance,ostream=OUTPUT)
  • coopr.pyomo/trunk/coopr/pyomo/tests/unit/test_modeldata.py

    r4737 r5803  
    401401        instance = model.create(currdir+'importY.dat')
    402402        self.assertEqual(instance.A.data(), set(['A1','A2','A3','A4']))
    403         self.assertEqual(instance.Y.data(), {'A1':3.3,'A2':3.4,'A3':3.5})
     403        self.assertEqual(instance.Y.sparse_extract_values(), {'A1':3.3,'A2':3.4,'A3':3.5})
    404404        os.remove(currdir+'importY.dat')
    405405
     
    410410        pyutilib.misc.setup_redirect(currdir+'importXW.dat')
    411411        print "import "+os.path.abspath(example_dir+'XW.tab')+": [A] X W;"
     412        pyutilib.misc.reset_redirect()
     413        model=AbstractModel()
     414        model.A = Set(initialize=['A1','A2','A3','A4'])
     415        model.X = Param(model.A)
     416        model.W = Param(model.A)
     417        instance = model.create(currdir+'importXW.dat')
     418        self.assertEqual(instance.A.data(), set(['A1','A2','A3','A4']))
     419        self.assertEqual(instance.X.sparse_extract_values(), {'A1':3.3,'A2':3.4,'A3':3.5})
     420        self.assertEqual(instance.W.sparse_extract_values(), {'A1':4.3,'A2':4.4,'A3':4.5})
     421        os.remove(currdir+'importXW.dat')
     422
     423    def test_tableXW_2(self):
     424        """Like test_tableXW_1, except that set A is not defined."""
     425        pyutilib.misc.setup_redirect(currdir+'importXW.dat')
     426        print "import "+os.path.abspath(example_dir+'XW.tab')+": [A] X W;"
     427        pyutilib.misc.reset_redirect()
     428        model=AbstractModel()
     429        model.A = Set(initialize=['A1','A2','A3'])
     430        model.X = Param(model.A)
     431        model.W = Param(model.A)
     432        instance = model.create(currdir+'importXW.dat')
     433        self.assertEqual(instance.X.sparse_extract_values(), {'A1':3.3,'A2':3.4,'A3':3.5})
     434        self.assertEqual(instance.W.sparse_extract_values(), {'A1':4.3,'A2':4.4,'A3':4.5})
     435        os.remove(currdir+'importXW.dat')
     436
     437    def test_tableXW_3(self):
     438        """Like test_tableXW_1, except that set A is defined in the import statment."""
     439        pyutilib.misc.setup_redirect(currdir+'importXW.dat')
     440        print "import "+os.path.abspath(example_dir+'XW.tab')+": A=[A] X W;"
     441        pyutilib.misc.reset_redirect()
     442        model=AbstractModel()
     443        model.A = Set()
     444        model.X = Param(model.A)
     445        model.W = Param(model.A)
     446        instance = model.create(currdir+'importXW.dat')
     447        self.assertEqual(instance.A.data(), set(['A1','A2','A3']))
     448        self.assertEqual(instance.X.sparse_extract_values(), {'A1':3.3,'A2':3.4,'A3':3.5})
     449        self.assertEqual(instance.W.sparse_extract_values(), {'A1':4.3,'A2':4.4,'A3':4.5})
     450        os.remove(currdir+'importXW.dat')
     451
     452    def test_tableXW_4(self):
     453        """Like test_tableXW_1, except that set A is defined in the import statment and all values are mapped."""
     454        pyutilib.misc.setup_redirect(currdir+'importXW.dat')
     455        print "import "+os.path.abspath(example_dir+'XW.tab')+": B=[A] R=X S=W;"
     456        pyutilib.misc.reset_redirect()
     457        model=AbstractModel()
     458        model.B = Set()
     459        model.R = Param(model.B)
     460        model.S = Param(model.B)
     461        instance = model.create(currdir+'importXW.dat')
     462        self.assertEqual(instance.B.data(), set(['A1','A2','A3']))
     463        self.assertEqual(instance.R.sparse_extract_values(), {'A1':3.3,'A2':3.4,'A3':3.5})
     464        self.assertEqual(instance.S.sparse_extract_values(), {'A1':4.3,'A2':4.4,'A3':4.5})
     465        os.remove(currdir+'importXW.dat')
     466
     467    def test_tableT(self):
     468        """Importing a 2D array of parameters that are transposed."""
     469        pyutilib.misc.setup_redirect(currdir+'importT.dat')
     470        print "import "+os.path.abspath(example_dir+'T.tab')+" format=transposed_array : T;"
     471        pyutilib.misc.reset_redirect()
     472        model=AbstractModel()
     473        model.B = Set(initialize=['I1','I2','I3','I4'])
     474        model.A = Set(initialize=['A1','A2','A3'])
     475        model.T = Param(model.A, model.B)
     476        instance = model.create(currdir+'importT.dat')
     477        self.assertEqual(instance.T.sparse_extract_values(), {('A2', 'I1'): 2.3, ('A1', 'I2'): 1.4, ('A1', 'I3'): 1.5, ('A1', 'I4'): 1.6, ('A1', 'I1'): 1.3, ('A3', 'I4'): 3.6, ('A2', 'I4'): 2.6, ('A3', 'I1'): 3.3, ('A2', 'I3'): 2.5, ('A3', 'I2'): 3.4, ('A2', 'I2'): 2.4, ('A3', 'I3'): 3.5})
     478        os.remove(currdir+'importT.dat')
     479
     480    def test_tableU(self):
     481        """Importing a 2D array of parameters."""
     482        pyutilib.misc.setup_redirect(currdir+'importU.dat')
     483        print "import "+os.path.abspath(example_dir+'U.tab')+" format=array : U;"
     484        pyutilib.misc.reset_redirect()
     485        model=AbstractModel()
     486        model.A = Set(initialize=['I1','I2','I3','I4'])
     487        model.B = Set(initialize=['A1','A2','A3'])
     488        model.U = Param(model.A, model.B)
     489        instance = model.create(currdir+'importU.dat')
     490        self.assertEqual(instance.U.sparse_extract_values(), {('I2', 'A1'): 1.4, ('I3', 'A1'): 1.5, ('I3', 'A2'): 2.5, ('I4', 'A1'): 1.6, ('I3', 'A3'): 3.5, ('I1', 'A2'): 2.3, ('I4', 'A3'): 3.6, ('I1', 'A3'): 3.3, ('I4', 'A2'): 2.6, ('I2', 'A3'): 3.4, ('I1', 'A1'): 1.3, ('I2', 'A2'): 2.4})
     491        os.remove(currdir+'importU.dat')
     492
     493    def test_tableS(self):
     494        """Importing a table, but only reporting the values for the non-index
     495        parameter columns.  The first column is assumed to represent an
     496        index column.  A missing value is represented in the column data."""
     497        pyutilib.misc.setup_redirect(currdir+'importS.dat')
     498        print "import "+os.path.abspath(example_dir+'S.tab')+": [A] S ;"
     499        pyutilib.misc.reset_redirect()
     500        model=AbstractModel()
     501        model.A = Set(initialize=['A1','A2','A3','A4'])
     502        model.S = Param(model.A)
     503        instance = model.create(currdir+'importS.dat')
     504        self.assertEqual(instance.A.data(), set(['A1','A2','A3','A4']))
     505        self.assertEqual(instance.S.sparse_extract_values(), {'A1':3.3,'A3':3.5})
     506        os.remove(currdir+'importS.dat')
     507
     508    def test_tablePO(self):
     509        """Importing a table that has multiple indexing columns"""
     510        pyutilib.misc.setup_redirect(currdir+'importPO.dat')
     511        print "import "+os.path.abspath(example_dir+'PO.tab')+" : J=[A,B] P O;"
     512        pyutilib.misc.reset_redirect()
     513        model=AbstractModel()
     514        model.J = Set(dimen=2)
     515        model.P = Param(model.J)
     516        model.O = Param(model.J)
     517        instance = model.create(currdir+'importPO.dat')
     518        self.assertEqual(instance.J.data(), set([('A3', 'B3'), ('A1', 'B1'), ('A2', 'B2')]) )
     519        self.assertEqual(instance.P.sparse_extract_values(), {('A3', 'B3'): 4.5, ('A1', 'B1'): 4.3, ('A2', 'B2'): 4.4} )
     520        self.assertEqual(instance.O.sparse_extract_values(), {('A3', 'B3'): 5.5, ('A1', 'B1'): 5.3, ('A2', 'B2'): 5.4})
     521        os.remove(currdir+'importPO.dat')
     522
     523
     524class TestCsvImport(unittest.TestCase):
     525
     526    def test_tableA1(self):
     527        """Importing a single column of data"""
     528        pyutilib.misc.setup_redirect(currdir+'importA1.dat')
     529        print "import "+os.path.abspath(csv_dir+'A.csv')+" format=set: A;"
     530        pyutilib.misc.reset_redirect()
     531        model=AbstractModel()
     532        model.A = Set()
     533        instance = model.create(currdir+'importA1.dat')
     534        self.assertEqual(instance.A.data(), set(['A1', 'A2', 'A3']))
     535        os.remove(currdir+'importA1.dat')
     536
     537    def test_tableA2(self):
     538        """Importing a single column of data"""
     539        pyutilib.misc.setup_redirect(currdir+'importA2.dat')
     540        print "import "+os.path.abspath(csv_dir+'A.csv')+" ;"
     541        pyutilib.misc.reset_redirect()
     542        model=AbstractModel()
     543        model.A = Set()
     544        try:
     545            instance = model.create(currdir+'importA2.dat')
     546            self.fail("Should fail because no set name is specified")
     547        except IOError:
     548            pass
     549        os.remove(currdir+'importA2.dat')
     550
     551    def test_tableA3(self):
     552        """Importing a single column of data"""
     553        pyutilib.misc.setup_redirect(currdir+'importA3.dat')
     554        print "import "+os.path.abspath(csv_dir+'A.csv')+" : A ;"
     555        pyutilib.misc.reset_redirect()
     556        model=AbstractModel()
     557        model.A = Set()
     558        try:
     559            instance = model.create(currdir+'importA3.dat')
     560            self.fail("Should fail because no index is specified")
     561        except IOError:
     562            pass
     563        os.remove(currdir+'importA3.dat')
     564
     565    def test_tableB(self):
     566        """Same as test_tableA"""
     567        pyutilib.misc.setup_redirect(currdir+'importB.dat')
     568        print "import "+os.path.abspath(csv_dir+'B.csv')+" format=set:B;"
     569        pyutilib.misc.reset_redirect()
     570        model=AbstractModel()
     571        model.B = Set()
     572        instance = model.create(currdir+'importB.dat')
     573        self.assertEqual(instance.B.data(), set([1, 2, 3]))
     574        os.remove(currdir+'importB.dat')
     575
     576    def test_tableC(self):
     577        """Importing a multi-column table, where all columns are
     578        treated as values for a set with tuple values."""
     579        pyutilib.misc.setup_redirect(currdir+'importC.dat')
     580        print "import "+os.path.abspath(csv_dir+'C.csv')+" format=set: C ;"
     581        pyutilib.misc.reset_redirect()
     582        model=AbstractModel()
     583        model.C = Set(dimen=2)
     584        instance = model.create(currdir+'importC.dat')
     585        self.assertEqual(instance.C.data(), set([('A1',1), ('A1',2), ('A1',3), ('A2',1), ('A2',2), ('A2',3), ('A3',1), ('A3',2), ('A3',3)]))
     586        os.remove(currdir+'importC.dat')
     587
     588    def test_tableD(self):
     589        """Importing a 2D array of data as a set."""
     590        pyutilib.misc.setup_redirect(currdir+'importD.dat')
     591        print "import "+os.path.abspath(csv_dir+'D.csv')+" format=set_array: C ;"
     592        pyutilib.misc.reset_redirect()
     593        model=AbstractModel()
     594        model.C = Set(dimen=2)
     595        instance = model.create(currdir+'importD.dat')
     596        self.assertEqual(instance.C.data(), set([('A1',1), ('A2',2), ('A3',3)]))
     597        os.remove(currdir+'importD.dat')
     598
     599    def test_tableZ(self):
     600        """Importing a single parameter"""
     601        pyutilib.misc.setup_redirect(currdir+'importZ.dat')
     602        print "import "+os.path.abspath(csv_dir+'Z.csv')+" format=param: Z ;"
     603        pyutilib.misc.reset_redirect()
     604        model=AbstractModel()
     605        model.Z = Param(default=99.0)
     606        instance = model.create(currdir+'importZ.dat')
     607        self.assertEqual(instance.Z.value, 1.1)
     608        os.remove(currdir+'importZ.dat')
     609
     610    def test_tableY(self):
     611        """Same as tableXW."""
     612        pyutilib.misc.setup_redirect(currdir+'importY.dat')
     613        print "import "+os.path.abspath(csv_dir+'Y.csv')+" : [A] Y;"
     614        pyutilib.misc.reset_redirect()
     615        model=AbstractModel()
     616        model.A = Set(initialize=['A1','A2','A3','A4'])
     617        model.Y = Param(model.A)
     618        instance = model.create(currdir+'importY.dat')
     619        self.assertEqual(instance.A.data(), set(['A1','A2','A3','A4']))
     620        self.assertEqual(instance.Y.sparse_extract_values(), {'A1':3.3,'A2':3.4,'A3':3.5})
     621        os.remove(currdir+'importY.dat')
     622
     623    def test_tableXW_1(self):
     624        """Importing a table, but only reporting the values for the non-index
     625        parameter columns.  The first column is assumed to represent an
     626        index column."""
     627        pyutilib.misc.setup_redirect(currdir+'importXW.dat')
     628        print "import "+os.path.abspath(csv_dir+'XW.csv')+": [A] X W;"
     629        pyutilib.misc.reset_redirect()
     630        model=AbstractModel()
     631        model.A = Set(initialize=['A1','A2','A3','A4'])
     632        model.X = Param(model.A)
     633        model.W = Param(model.A)
     634        instance = model.create(currdir+'importXW.dat')
     635        self.assertEqual(instance.A.data(), set(['A1','A2','A3','A4']))
     636        self.assertEqual(instance.X.sparse_extract_values(), {'A1':3.3,'A2':3.4,'A3':3.5})
     637        self.assertEqual(instance.W.sparse_extract_values(), {'A1':4.3,'A2':4.4,'A3':4.5})
     638        os.remove(currdir+'importXW.dat')
     639
     640    def test_tableXW_2(self):
     641        """Like test_tableXW_1, except that set A is not defined."""
     642        pyutilib.misc.setup_redirect(currdir+'importXW.dat')
     643        print "import "+os.path.abspath(csv_dir+'XW.csv')+": [A] X W;"
     644        pyutilib.misc.reset_redirect()
     645        model=AbstractModel()
     646        model.A = Set(initialize=['A1','A2','A3'])
     647        model.X = Param(model.A)
     648        model.W = Param(model.A)
     649        instance = model.create(currdir+'importXW.dat')
     650        self.assertEqual(instance.X.sparse_extract_values(), {'A1':3.3,'A2':3.4,'A3':3.5})
     651        self.assertEqual(instance.W.sparse_extract_values(), {'A1':4.3,'A2':4.4,'A3':4.5})
     652        os.remove(currdir+'importXW.dat')
     653
     654    def test_tableXW_3(self):
     655        """Like test_tableXW_1, except that set A is defined in the import statment."""
     656        pyutilib.misc.setup_redirect(currdir+'importXW.dat')
     657        print "import "+os.path.abspath(csv_dir+'XW.csv')+": A=[A] X W;"
     658        pyutilib.misc.reset_redirect()
     659        model=AbstractModel()
     660        model.A = Set()
     661        model.X = Param(model.A)
     662        model.W = Param(model.A)
     663        instance = model.create(currdir+'importXW.dat')
     664        self.assertEqual(instance.A.data(), set(['A1','A2','A3']))
     665        self.assertEqual(instance.X.sparse_extract_values(), {'A1':3.3,'A2':3.4,'A3':3.5})
     666        self.assertEqual(instance.W.sparse_extract_values(), {'A1':4.3,'A2':4.4,'A3':4.5})
     667        os.remove(currdir+'importXW.dat')
     668
     669    def test_tableXW_4(self):
     670        """Like test_tableXW_1, except that set A is defined in the import statment and all values are mapped."""
     671        pyutilib.misc.setup_redirect(currdir+'importXW.dat')
     672        print "import "+os.path.abspath(csv_dir+'XW.csv')+": B=[A] R=X S=W;"
     673        pyutilib.misc.reset_redirect()
     674        model=AbstractModel()
     675        model.B = Set()
     676        model.R = Param(model.B)
     677        model.S = Param(model.B)
     678        instance = model.create(currdir+'importXW.dat')
     679        self.assertEqual(instance.B.data(), set(['A1','A2','A3']))
     680        self.assertEqual(instance.R.sparse_extract_values(), {'A1':3.3,'A2':3.4,'A3':3.5})
     681        self.assertEqual(instance.S.sparse_extract_values(), {'A1':4.3,'A2':4.4,'A3':4.5})
     682        os.remove(currdir+'importXW.dat')
     683
     684    def test_tableT(self):
     685        """Importing a 2D array of parameters that are transposed."""
     686        pyutilib.misc.setup_redirect(currdir+'importT.dat')
     687        print "import "+os.path.abspath(csv_dir+'T.csv')+" format=transposed_array : T;"
     688        pyutilib.misc.reset_redirect()
     689        model=AbstractModel()
     690        model.B = Set(initialize=['I1','I2','I3','I4'])
     691        model.A = Set(initialize=['A1','A2','A3'])
     692        model.T = Param(model.A, model.B)
     693        instance = model.create(currdir+'importT.dat')
     694        self.assertEqual(instance.T.sparse_extract_values(), {('A2', 'I1'): 2.3, ('A1', 'I2'): 1.4, ('A1', 'I3'): 1.5, ('A1', 'I4'): 1.6, ('A1', 'I1'): 1.3, ('A3', 'I4'): 3.6, ('A2', 'I4'): 2.6, ('A3', 'I1'): 3.3, ('A2', 'I3'): 2.5, ('A3', 'I2'): 3.4, ('A2', 'I2'): 2.4, ('A3', 'I3'): 3.5})
     695        os.remove(currdir+'importT.dat')
     696
     697    def test_tableU(self):
     698        """Importing a 2D array of parameters."""
     699        pyutilib.misc.setup_redirect(currdir+'importU.dat')
     700        print "import "+os.path.abspath(csv_dir+'U.csv')+" format=array : U;"
     701        pyutilib.misc.reset_redirect()
     702        model=AbstractModel()
     703        model.A = Set(initialize=['I1','I2','I3','I4'])
     704        model.B = Set(initialize=['A1','A2','A3'])
     705        model.U = Param(model.A, model.B)
     706        instance = model.create(currdir+'importU.dat')
     707        self.assertEqual(instance.U.sparse_extract_values(), {('I2', 'A1'): 1.4, ('I3', 'A1'): 1.5, ('I3', 'A2'): 2.5, ('I4', 'A1'): 1.6, ('I3', 'A3'): 3.5, ('I1', 'A2'): 2.3, ('I4', 'A3'): 3.6, ('I1', 'A3'): 3.3, ('I4', 'A2'): 2.6, ('I2', 'A3'): 3.4, ('I1', 'A1'): 1.3, ('I2', 'A2'): 2.4})
     708        os.remove(currdir+'importU.dat')
     709
     710    def test_tableS(self):
     711        """Importing a table, but only reporting the values for the non-index
     712        parameter columns.  The first column is assumed to represent an
     713        index column.  A missing value is represented in the column data."""
     714        pyutilib.misc.setup_redirect(currdir+'importS.dat')
     715        print "import "+os.path.abspath(csv_dir+'S.csv')+": [A] S ;"
     716        pyutilib.misc.reset_redirect()
     717        model=AbstractModel()
     718        model.A = Set(initialize=['A1','A2','A3','A4'])
     719        model.S = Param(model.A)
     720        instance = model.create(currdir+'importS.dat')
     721        self.assertEqual(instance.A.data(), set(['A1','A2','A3','A4']))
     722        self.assertEqual(instance.S.sparse_extract_values(), {'A1':3.3,'A3':3.5})
     723        os.remove(currdir+'importS.dat')
     724
     725    def test_tablePO(self):
     726        """Importing a table that has multiple indexing columns"""
     727        pyutilib.misc.setup_redirect(currdir+'importPO.dat')
     728        print "import "+os.path.abspath(csv_dir+'PO.csv')+" : J=[A,B] P O;"
     729        pyutilib.misc.reset_redirect()
     730        model=AbstractModel()
     731        model.J = Set(dimen=2)
     732        model.P = Param(model.J)
     733        model.O = Param(model.J)
     734        instance = model.create(currdir+'importPO.dat')
     735        self.assertEqual(instance.J.data(), set([('A3', 'B3'), ('A1', 'B1'), ('A2', 'B2')]) )
     736        self.assertEqual(
     737            instance.P.sparse_extract_values(),
     738            {('A3', 'B3'): 4.5, ('A1', 'B1'): 4.3, ('A2', 'B2'): 4.4} )
     739        self.assertEqual(
     740            instance.O.sparse_extract_values(),
     741            {('A3', 'B3'): 5.5, ('A1', 'B1'): 5.3, ('A2', 'B2'): 5.4} )
     742        os.remove(currdir+'importPO.dat')
     743
     744
     745
     746class TestSpreadsheet(unittest.TestCase):
     747
     748    def test_tableA1(self):
     749        """Importing a single column of data"""
     750        pyutilib.misc.setup_redirect(currdir+'importA1.dat')
     751        print "import "+os.path.abspath(tutorial_dir+'excel.xls')+" range=Atable format=set: A;"
     752        pyutilib.misc.reset_redirect()
     753        model=AbstractModel()
     754        model.A = Set()
     755        instance = model.create(currdir+'importA1.dat')
     756        self.assertEqual(instance.A.data(), set(['A1', 'A2', 'A3']))
     757        os.remove(currdir+'importA1.dat')
     758
     759    def test_tableA2(self):
     760        """Importing a single column of data"""
     761        pyutilib.misc.setup_redirect(currdir+'importA2.dat')
     762        print "import "+os.path.abspath(tutorial_dir+'excel.xls')+" range=Atable ;"
     763        pyutilib.misc.reset_redirect()
     764        model=AbstractModel()
     765        model.A = Set()
     766        try:
     767            instance = model.create(currdir+'importA2.dat')
     768            self.fail("Should fail because no set name is specified")
     769        except IOError:
     770            pass
     771        os.remove(currdir+'importA2.dat')
     772
     773    def test_tableA3(self):
     774        """Importing a single column of data"""
     775        pyutilib.misc.setup_redirect(currdir+'importA3.dat')
     776        print "import "+os.path.abspath(tutorial_dir+'excel.xls')+" range=Atable : A ;"
     777        pyutilib.misc.reset_redirect()
     778        model=AbstractModel()
     779        model.A = Set()
     780        try:
     781            instance = model.create(currdir+'importA3.dat')
     782            self.fail("Should fail because no index is specified")
     783        except IOError:
     784            pass
     785        os.remove(currdir+'importA3.dat')
     786
     787    def test_tableB(self):
     788        """Same as test_tableA"""
     789        pyutilib.misc.setup_redirect(currdir+'importB.dat')
     790        print "import "+os.path.abspath(tutorial_dir+'excel.xls')+" range=Btable format=set:B;"
     791        pyutilib.misc.reset_redirect()
     792        model=AbstractModel()
     793        model.B = Set()
     794        instance = model.create(currdir+'importB.dat')
     795        self.assertEqual(instance.B.data(), set([1, 2, 3]))
     796        os.remove(currdir+'importB.dat')
     797
     798    def test_tableC(self):
     799        """Importing a multi-column table, where all columns are
     800        treated as values for a set with tuple values."""
     801        pyutilib.misc.setup_redirect(currdir+'importC.dat')
     802        print "import "+os.path.abspath(tutorial_dir+'excel.xls')+" range=Ctable format=set: C ;"
     803        pyutilib.misc.reset_redirect()
     804        model=AbstractModel()
     805        model.C = Set(dimen=2)
     806        instance = model.create(currdir+'importC.dat')
     807        self.assertEqual(instance.C.data(), set([('A1',1), ('A1',2), ('A1',3), ('A2',1), ('A2',2), ('A2',3), ('A3',1), ('A3',2), ('A3',3)]))
     808        os.remove(currdir+'importC.dat')
     809
     810    def test_tableD(self):
     811        """Importing a 2D array of data as a set."""
     812        pyutilib.misc.setup_redirect(currdir+'importD.dat')
     813        print "import "+os.path.abspath(tutorial_dir+'excel.xls')+" range=Dtable format=set_array: C ;"
     814        pyutilib.misc.reset_redirect()
     815        model=AbstractModel()
     816        model.C = Set(dimen=2)
     817        instance = model.create(currdir+'importD.dat')
     818        self.assertEqual(instance.C.data(), set([('A1',1), ('A2',2), ('A3',3)]))
     819        os.remove(currdir+'importD.dat')
     820
     821    def test_tableZ(self):
     822        """Importing a single parameter"""
     823        pyutilib.misc.setup_redirect(currdir+'importZ.dat')
     824        print "import "+os.path.abspath(tutorial_dir+'excel.xls')+" range=Zparam format=param: Z ;"
     825        pyutilib.misc.reset_redirect()
     826        model=AbstractModel()
     827        model.Z = Param(default=99.0)
     828        instance = model.create(currdir+'importZ.dat')
     829        self.assertEqual(instance.Z.value, 1.1)
     830        os.remove(currdir+'importZ.dat')
     831
     832    def test_tableY(self):
     833        """Same as tableXW."""
     834        pyutilib.misc.setup_redirect(currdir+'importY.dat')
     835        print "import "+os.path.abspath(tutorial_dir+'excel.xls')+" range=Ytable : [A] Y;"
     836        pyutilib.misc.reset_redirect()
     837        model=AbstractModel()
     838        model.A = Set(initialize=['A1','A2','A3','A4'])
     839        model.Y = Param(model.A)
     840        instance = model.create(currdir+'importY.dat')
     841        self.assertEqual(instance.A.data(), set(['A1','A2','A3','A4']))
     842        self.assertEqual(instance.Y.data(), {'A1':3.3,'A2':3.4,'A3':3.5})
     843        os.remove(currdir+'importY.dat')
     844
     845    def test_tableXW_1(self):
     846        """Importing a table, but only reporting the values for the non-index
     847        parameter columns.  The first column is assumed to represent an
     848        index column."""
     849        pyutilib.misc.setup_redirect(currdir+'importXW.dat')
     850        print "import "+os.path.abspath(tutorial_dir+'excel.xls')+" range=XWtable : [A] X W;"
    412851        pyutilib.misc.reset_redirect()
    413852        model=AbstractModel()
     
    424863        """Like test_tableXW_1, except that set A is not defined."""
    425864        pyutilib.misc.setup_redirect(currdir+'importXW.dat')
    426         print "import "+os.path.abspath(example_dir+'XW.tab')+": [A] X W;"
     865        print "import "+os.path.abspath(tutorial_dir+'excel.xls')+" range=XWtable : [A] X W;"
    427866        pyutilib.misc.reset_redirect()
    428867        model=AbstractModel()
     
    438877        """Like test_tableXW_1, except that set A is defined in the import statment."""
    439878        pyutilib.misc.setup_redirect(currdir+'importXW.dat')
    440         print "import "+os.path.abspath(example_dir+'XW.tab')+": A=[A] X W;"
    441         pyutilib.misc.reset_redirect()
    442         model=AbstractModel()
    443         model.A = Set()
     879        print "import "+os.path.abspath(tutorial_dir+'excel.xls')+" range=XWtable: A=[A] X W;"
     880        pyutilib.misc.reset_redirect()
     881        model=AbstractModel()
     882        model.A = Set(initialize=['A1','A2','A3','A4'])
    444883        model.X = Param(model.A)
    445884        model.W = Param(model.A)
     
    453892        """Like test_tableXW_1, except that set A is defined in the import statment and all values are mapped."""
    454893        pyutilib.misc.setup_redirect(currdir+'importXW.dat')
    455         print "import "+os.path.abspath(example_dir+'XW.tab')+": B=[A] R=X S=W;"
     894        print "import "+os.path.abspath(tutorial_dir+'excel.xls')+" range=XWtable: B=[A] R=X S=W;"
    456895        pyutilib.misc.reset_redirect()
    457896        model=AbstractModel()
     
    468907        """Importing a 2D array of parameters that are transposed."""
    469908        pyutilib.misc.setup_redirect(currdir+'importT.dat')
    470         print "import "+os.path.abspath(example_dir+'T.tab')+" format=transposed_array : T;"
     909        print "import "+os.path.abspath(tutorial_dir+'excel.xls')+" range=Ttable format=transposed_array : T;"
    471910        pyutilib.misc.reset_redirect()
    472911        model=AbstractModel()
     
    481920        """Importing a 2D array of parameters."""
    482921        pyutilib.misc.setup_redirect(currdir+'importU.dat')
    483         print "import "+os.path.abspath(example_dir+'U.tab')+" format=array : U;"
     922        print "import "+os.path.abspath(tutorial_dir+'excel.xls')+" range=Utable format=array : U;"
    484923        pyutilib.misc.reset_redirect()
    485924        model=AbstractModel()
     
    496935        index column.  A missing value is represented in the column data."""
    497936        pyutilib.misc.setup_redirect(currdir+'importS.dat')
    498         print "import "+os.path.abspath(example_dir+'S.tab')+": [A] S ;"
     937        print "import "+os.path.abspath(tutorial_dir+'excel.xls')+" range=Stable : [A] S ;"
    499938        pyutilib.misc.reset_redirect()
    500939        model=AbstractModel()
     
    509948        """Importing a table that has multiple indexing columns"""
    510949        pyutilib.misc.setup_redirect(currdir+'importPO.dat')
    511         print "import "+os.path.abspath(example_dir+'PO.tab')+" : J=[A,B] P O;"
     950        print "import "+os.path.abspath(tutorial_dir+'excel.xls')+" range=POtable : J=[A,B] P O;"
    512951        pyutilib.misc.reset_redirect()
    513952        model=AbstractModel()
     
    517956        instance = model.create(currdir+'importPO.dat')
    518957        self.assertEqual(instance.J.data(), set([('A3', 'B3'), ('A1', 'B1'), ('A2', 'B2')]) )
    519         self.assertEqual(instance.P.data(), {('A3', 'B3'): 4.5, ('A1', 'B1'): 4.3, ('A2', 'B2'): 4.4} )
     958        self.assertEqual(
     959            instance.P.sparse_extract_values(),
     960            {('A3', 'B3'): 4.5, ('A1', 'B1'): 4.3, ('A2', 'B2'): 4.4} )
    520961        self.assertEqual(instance.O.data(), {('A3', 'B3'): 5.5, ('A1', 'B1'): 5.3, ('A2', 'B2'): 5.4})
    521962        os.remove(currdir+'importPO.dat')
    522963
    523 
    524 class TestCsvImport(unittest.TestCase):
     964TestSpreadsheet = unittest.skipIf(not _win32com, "Cannot import 'win32com'")(TestSpreadsheet)
     965
     966
     967class TestModelData(unittest.TestCase):
    525968
    526969    def test_tableA1(self):
    527970        """Importing a single column of data"""
    528         pyutilib.misc.setup_redirect(currdir+'importA1.dat')
    529         print "import "+os.path.abspath(csv_dir+'A.csv')+" format=set: A;"
    530         pyutilib.misc.reset_redirect()
    531         model=AbstractModel()
    532         model.A = Set()
    533         instance = model.create(currdir+'importA1.dat')
     971        md = ModelData()
     972        md.add(os.path.abspath(example_dir+'A.tab'), format='set', set='A')
     973        model=AbstractModel()
     974        model.A = Set()
     975        md.read(model)
     976        instance = model.create(md)
    534977        self.assertEqual(instance.A.data(), set(['A1', 'A2', 'A3']))
    535         os.remove(currdir+'importA1.dat')
    536978
    537979    def test_tableA2(self):
    538980        """Importing a single column of data"""
    539         pyutilib.misc.setup_redirect(currdir+'importA2.dat')
    540         print "import "+os.path.abspath(csv_dir+'A.csv')+" ;"
    541         pyutilib.misc.reset_redirect()
    542         model=AbstractModel()
    543         model.A = Set()
    544         try:
    545             instance = model.create(currdir+'importA2.dat')
     981        md = ModelData()
     982        md.add(os.path.abspath(example_dir+'A.tab'))
     983        model=AbstractModel()
     984        model.A = Set()
     985        try:
     986            md.read(model)
     987            instance = model.create(md)
    546988            self.fail("Should fail because no set name is specified")
    547989        except IOError:
    548990            pass
    549         os.remove(currdir+'importA2.dat')
    550991
    551992    def test_tableA3(self):
    552993        """Importing a single column of data"""
    553         pyutilib.misc.setup_redirect(currdir+'importA3.dat')
    554         print "import "+os.path.abspath(csv_dir+'A.csv')+" : A ;"
    555         pyutilib.misc.reset_redirect()
    556         model=AbstractModel()
    557         model.A = Set()
    558         try:
    559             instance = model.create(currdir+'importA3.dat')
     994        md = ModelData()
     995        md.add(os.path.abspath(example_dir+'A.tab'), set='A')
     996        model=AbstractModel()
     997        model.A = Set()
     998        try:
     999            md.read(model)
     1000            instance = model.create(md)
    5601001            self.fail("Should fail because no index is specified")
    5611002        except IOError:
    5621003            pass
    563         os.remove(currdir+'importA3.dat')
    5641004
    5651005    def test_tableB(self):
    5661006        """Same as test_tableA"""
    567         pyutilib.misc.setup_redirect(currdir+'importB.dat')
    568         print "import "+os.path.abspath(csv_dir+'B.csv')+" format=set:B;"
    569         pyutilib.misc.reset_redirect()
     1007        md = ModelData()
     1008        md.add(os.path.abspath(example_dir+'B.tab'), format='set', set='B')
    5701009        model=AbstractModel()
    5711010        model.B = Set()
    572         instance = model.create(currdir+'importB.dat')
     1011        md.read(model)
     1012        instance = model.create(md)
    5731013        self.assertEqual(instance.B.data(), set([1, 2, 3]))
    574         os.remove(currdir+'importB.dat')
    5751014
    5761015    def test_tableC(self):
    5771016        """Importing a multi-column table, where all columns are
    5781017        treated as values for a set with tuple values."""
    579         pyutilib.misc.setup_redirect(currdir+'importC.dat')
    580         print "import "+os.path.abspath(csv_dir+'C.csv')+" format=set: C ;"
    581         pyutilib.misc.reset_redirect()
     1018        md = ModelData()
     1019        md.add(os.path.abspath(example_dir+'C.tab'), format='set', set='C')
    5821020        model=AbstractModel()
    5831021        model.C = Set(dimen=2)
    584         instance = model.create(currdir+'importC.dat')
     1022        md.read(model)
     1023        instance = model.create(md)
    5851024        self.assertEqual(instance.C.data(), set([('A1',1), ('A1',2), ('A1',3), ('A2',1), ('A2',2), ('A2',3), ('A3',1), ('A3',2), ('A3',3)]))
    586         os.remove(currdir+'importC.dat')
    5871025
    5881026    def test_tableD(self):
    5891027        """Importing a 2D array of data as a set."""
    590         pyutilib.misc.setup_redirect(currdir+'importD.dat')
    591         print "import "+os.path.abspath(csv_dir+'D.csv')+" format=set_array: C ;"
    592         pyutilib.misc.reset_redirect()
     1028        md = ModelData()
     1029        md.add(os.path.abspath(example_dir+'D.tab'), format='set_array', set='C')
    5931030        model=AbstractModel()
    5941031        model.C = Set(dimen=2)
    595         instance = model.create(currdir+'importD.dat')
     1032        md.read(model)
     1033        instance = model.create(md)
    5961034        self.assertEqual(instance.C.data(), set([('A1',1), ('A2',2), ('A3',3)]))
    597         os.remove(currdir+'importD.dat')
    5981035
    5991036    def test_tableZ(self):
    6001037        """Importing a single parameter"""
    601         pyutilib.misc.setup_redirect(currdir+'importZ.dat')
    602         print "import "+os.path.abspath(csv_dir+'Z.csv')+" format=param: Z ;"
    603         pyutilib.misc.reset_redirect()
     1038        md = ModelData()
     1039        md.add(os.path.abspath(example_dir+'Z.tab'), format='param', param='Z')
    6041040        model=AbstractModel()
    6051041        model.Z = Param(default=99.0)
    606         instance = model.create(currdir+'importZ.dat')
     1042        md.read(model)
     1043        instance = model.create(md)
    6071044        self.assertEqual(instance.Z.value, 1.1)
    608         os.remove(currdir+'importZ.dat')
    6091045
    6101046    def test_tableY(self):
    6111047        """Same as tableXW."""
    612         pyutilib.misc.setup_redirect(currdir+'importY.dat')
    613         print "import "+os.path.abspath(csv_dir+'Y.csv')+" : [A] Y;"
    614         pyutilib.misc.reset_redirect()
     1048        md = ModelData()
     1049        md.add(os.path.abspath(example_dir+'Y.tab'), index=['A'], param=['Y'])
    6151050        model=AbstractModel()
    6161051        model.A = Set(initialize=['A1','A2','A3','A4'])
    6171052        model.Y = Param(model.A)
    618         instance = model.create(currdir+'importY.dat')
     1053        md.read(model)
     1054        instance = model.create(md)
    6191055        self.assertEqual(instance.A.data(), set(['A1','A2','A3','A4']))
    620         self.assertEqual(instance.Y.data(), {'A1':3.3,'A2':3.4,'A3':3.5})
    621         os.remove(currdir+'importY.dat')
     1056        self.assertEqual(instance.Y.sparse_extract_values(), {'A1':3.3,'A2':3.4,'A3':3.5})
    6221057
    6231058    def test_tableXW_1(self):
     
    6251060        parameter columns.  The first column is assumed to represent an
    6261061        index column."""
    627         pyutilib.misc.setup_redirect(currdir+'importXW.dat')
    628         print "import "+os.path.abspath(csv_dir+'XW.csv')+": [A] X W;"
    629         pyutilib.misc.reset_redirect()
     1062        md = ModelData()
     1063        md.add(os.path.abspath(example_dir+'XW.tab'), index=['A'], param=['X','W'])
    6301064        model=AbstractModel()
    6311065        model.A = Set(initialize=['A1','A2','A3','A4'])
    6321066        model.X = Param(model.A)
    6331067        model.W = Param(model.A)
    634         instance = model.create(currdir+'importXW.dat')
     1068        md.read(model)
     1069        instance = model.create(md)
    6351070        self.assertEqual(instance.A.data(), set(['A1','A2','A3','A4']))
    636         self.assertEqual(instance.X.data(), {'A1':3.3,'A2':3.4,'A3':3.5})
    637         self.assertEqual(instance.W.data(), {'A1':4.3,'A2':4.4,'A3':4.5})
    638         os.remove(currdir+'importXW.dat')
     1071        self.assertEqual(instance.X.sparse_extract_values(), {'A1':3.3,'A2':3.4,'A3':3.5})
     1072        self.assertEqual(instance.W.sparse_extract_values(), {'A1':4.3,'A2':4.4,'A3':4.5})
    6391073
    6401074    def test_tableXW_2(self):
    6411075        """Like test_tableXW_1, except that set A is not defined."""
    642         pyutilib.misc.setup_redirect(currdir+'importXW.dat')
    643         print "import "+os.path.abspath(csv_dir+'XW.csv')+": [A] X W;"
    644         pyutilib.misc.reset_redirect()
     1076        md = ModelData()
     1077        md.add(os.path.abspath(example_dir+'XW.tab'), index=['A'], param=['X','W'])
    6451078        model=AbstractModel()
    6461079        model.A = Set(initialize=['A1','A2','A3'])
    6471080        model.X = Param(model.A)
    6481081        model.W = Param(model.A)
    649         instance = model.create(currdir+'importXW.dat')
    650         self.assertEqual(instance.X.data(), {'A1':3.3,'A2':3.4,'A3':3.5})
    651         self.assertEqual(instance.W.data(), {'A1':4.3,'A2':4.4,'A3':4.5})
    652         os.remove(currdir+'importXW.dat')
     1082        md.read(model)
     1083        instance = model.create(md)
     1084        self.assertEqual(instance.X.sparse_extract_values(), {'A1':3.3,'A2':3.4,'A3':3.5})
     1085        self.assertEqual(instance.W.sparse_extract_values(), {'A1':4.3,'A2':4.4,'A3':4.5})
    6531086
    6541087    def test_tableXW_3(self):
    6551088        """Like test_tableXW_1, except that set A is defined in the import statment."""
    656         pyutilib.misc.setup_redirect(currdir+'importXW.dat')
    657         print "import "+os.path.abspath(csv_dir+'XW.csv')+": A=[A] X W;"
    658         pyutilib.misc.reset_redirect()
     1089        md = ModelData()
     1090        md.add(os.path.abspath(example_dir+'XW.tab'), index_name='A', index=['A'], param=['X','W'])
    6591091        model=AbstractModel()
    6601092        model.A = Set()
    6611093        model.X = Param(model.A)
    6621094        model.W = Param(model.A)
    663         instance = model.create(currdir+'importXW.dat')
     1095        md.read(model)
     1096        instance = model.create(md)
    6641097        self.assertEqual(instance.A.data(), set(['A1','A2','A3']))
    665         self.assertEqual(instance.X.data(), {'A1':3.3,'A2':3.4,'A3':3.5})
    666         self.assertEqual(instance.W.data(), {'A1':4.3,'A2':4.4,'A3':4.5})
    667         os.remove(currdir+'importXW.dat')
     1098        self.assertEqual(instance.X.sparse_extract_values(), {'A1':3.3,'A2':3.4,'A3':3.5})
     1099        self.assertEqual(instance.W.sparse_extract_values(), {'A1':4.3,'A2':4.4,'A3':4.5})
    6681100
    6691101    def test_tableXW_4(self):
    6701102        """Like test_tableXW_1, except that set A is defined in the import statment and all values are mapped."""
    671         pyutilib.misc.setup_redirect(currdir+'importXW.dat')
    672         print "import "+os.path.abspath(csv_dir+'XW.csv')+": B=[A] R=X S=W;"
    673         pyutilib.misc.reset_redirect()
     1103        md = ModelData()
     1104        md.add(os.path.abspath(example_dir+'XW.tab'), index_name='B', index=['A'], param=['X','W'], param_name={'X':'R', 'W':'S'})
    6741105        model=AbstractModel()
    6751106        model.B = Set()
    6761107        model.R = Param(model.B)
    6771108        model.S = Param(model.B)
    678         instance = model.create(currdir+'importXW.dat')
     1109        md.read(model)
     1110        instance = model.create(md)
    6791111        self.assertEqual(instance.B.data(), set(['A1','A2','A3']))
    680         self.assertEqual(instance.R.data(), {'A1':3.3,'A2':3.4,'A3':3.5})
    681         self.assertEqual(instance.S.data(), {'A1':4.3,'A2':4.4,'A3':4.5})
    682         os.remove(currdir+'importXW.dat')
     1112        self.assertEqual(instance.R.sparse_extract_values(), {'A1':3.3,'A2':3.4,'A3':3.5})
     1113        self.assertEqual(instance.S.sparse_extract_values(), {'A1':4.3,'A2':4.4,'A3':4.5})
    6831114
    6841115    def test_tableT(self):
    6851116        """Importing a 2D array of parameters that are transposed."""
    686         pyutilib.misc.setup_redirect(currdir+'importT.dat')
    687         print "import "+os.path.abspath(csv_dir+'T.csv')+" format=transposed_array : T;"
    688         pyutilib.misc.reset_redirect()
     1117        md = ModelData()
     1118        md.add(os.path.abspath(example_dir+'T.tab'), format='transposed_array', param='T')
    6891119        model=AbstractModel()
    6901120        model.B = Set(initialize=['I1','I2','I3','I4'])
    6911121        model.A = Set(initialize=['A1','A2','A3'])
    6921122        model.T = Param(model.A, model.B)
    693         instance = model.create(currdir+'importT.dat')
    694         self.assertEqual(instance.T.data(), {('A2', 'I1'): 2.3, ('A1', 'I2'): 1.4, ('A1', 'I3'): 1.5, ('A1', 'I4'): 1.6, ('A1', 'I1'): 1.3, ('A3', 'I4'): 3.6, ('A2', 'I4'): 2.6, ('A3', 'I1'): 3.3, ('A2', 'I3'): 2.5, ('A3', 'I2'): 3.4, ('A2', 'I2'): 2.4, ('A3', 'I3'): 3.5})
    695         os.remove(currdir+'importT.dat')
     1123        md.read(model)
     1124        instance = model.create(md)
     1125        self.assertEqual(instance.T.sparse_extract_values(), {('A2', 'I1'): 2.3, ('A1', 'I2'): 1.4, ('A1', 'I3'): 1.5, ('A1', 'I4'): 1.6, ('A1', 'I1'): 1.3, ('A3', 'I4'): 3.6, ('A2', 'I4'): 2.6, ('A3', 'I1'): 3.3, ('A2', 'I3'): 2.5, ('A3', 'I2'): 3.4, ('A2', 'I2'): 2.4, ('A3', 'I3'): 3.5})
    6961126
    6971127    def test_tableU(self):
    6981128        """Importing a 2D array of parameters."""
    699         pyutilib.misc.setup_redirect(currdir+'importU.dat')
    700         print "import "+os.path.abspath(csv_dir+'U.csv')+" format=array : U;"
    701         pyutilib.misc.reset_redirect()
     1129        md = ModelData()
     1130        md.add(os.path.abspath(example_dir+'T.tab'), format='array', param='U')
    7021131        model=AbstractModel()
    7031132        model.A = Set(initialize=['I1','I2','I3','I4'])
    7041133        model.B = Set(initialize=['A1','A2','A3'])
    7051134        model.U = Param(model.A, model.B)
    706         instance = model.create(currdir+'importU.dat')
    707         self.assertEqual(instance.U.data(), {('I2', 'A1'): 1.4, ('I3', 'A1'): 1.5, ('I3', 'A2'): 2.5, ('I4', 'A1'): 1.6, ('I3', 'A3'): 3.5, ('I1', 'A2'): 2.3, ('I4', 'A3'): 3.6, ('I1', 'A3'): 3.3, ('I4', 'A2'): 2.6, ('I2', 'A3'): 3.4, ('I1', 'A1'): 1.3, ('I2', 'A2'): 2.4})
    708         os.remove(currdir+'importU.dat')
     1135        md.read(model)
     1136        instance = model.create(md)
     1137        self.assertEqual(instance.U.sparse_extract_values(), {('I2', 'A1'): 1.4, ('I3', 'A1'): 1.5, ('I3', 'A2'): 2.5, ('I4', 'A1'): 1.6, ('I3', 'A3'): 3.5, ('I1', 'A2'): 2.3, ('I4', 'A3'): 3.6, ('I1', 'A3'): 3.3, ('I4', 'A2'): 2.6, ('I2', 'A3'): 3.4, ('I1', 'A1'): 1.3, ('I2', 'A2'): 2.4})
    7091138
    7101139    def test_tableS(self):
     
    7121141        parameter columns.  The first column is assumed to represent an
    7131142        index column.  A missing value is represented in the column data."""
    714         pyutilib.misc.setup_redirect(currdir+'importS.dat')
    715         print "import "+os.path.abspath(csv_dir+'S.csv')+": [A] S ;"
    716         pyutilib.misc.reset_redirect()
     1143        md = ModelData()
     1144        md.add(os.path.abspath(example_dir+'S.tab'), index=['A'], param=['S'])
    7171145        model=AbstractModel()
    7181146        model.A = Set(initialize=['A1','A2','A3','A4'])
    7191147        model.S = Param(model.A)
    720         instance = model.create(currdir+'importS.dat')
     1148        md.read(model)
     1149        instance = model.create(md)
    7211150        self.assertEqual(instance.A.data(), set(['A1','A2','A3','A4']))
    722         self.assertEqual(instance.S.data(), {'A1':3.3,'A3':3.5})
    723         os.remove(currdir+'importS.dat')
    724 
    725     def test_tablePO(self):
    726         """Importing a table that has multiple indexing columns"""
    727         pyutilib.misc.setup_redirect(currdir+'importPO.dat')
    728         print "import "+os.path.abspath(csv_dir+'PO.csv')+" : J=[A,B] P O;"
    729         pyutilib.misc.reset_redirect()
    730         model=AbstractModel()
    731         model.J = Set(dimen=2)
    732         model.P = Param(model.J)
    733         model.O = Param(model.J)
    734         instance = model.create(currdir+'importPO.dat')
    735         self.assertEqual(instance.J.data(), set([('A3', 'B3'), ('A1', 'B1'), ('A2', 'B2')]) )
    736         self.assertEqual(instance.P.data(), {('A3', 'B3'): 4.5, ('A1', 'B1'): 4.3, ('A2', 'B2'): 4.4} )
    737         self.assertEqual(instance.O.data(), {('A3', 'B3'): 5.5, ('A1', 'B1'): 5.3, ('A2', 'B2'): 5.4})
    738         os.remove(currdir+'importPO.dat')
    739 
    740 
    741 
    742 class TestSpreadsheet(unittest.TestCase):
    743 
    744     def test_tableA1(self):
    745         """Importing a single column of data"""
    746         pyutilib.misc.setup_redirect(currdir+'importA1.dat')
    747         print "import "+os.path.abspath(tutorial_dir+'excel.xls')+" range=Atable format=set: A;"
    748         pyutilib.misc.reset_redirect()
    749         model=AbstractModel()
    750         model.A = Set()
    751         instance = model.create(currdir+'importA1.dat')
    752         self.assertEqual(instance.A.data(), set(['A1', 'A2', 'A3']))
    753         os.remove(currdir+'importA1.dat')
    754 
    755     def test_tableA2(self):
    756         """Importing a single column of data"""
    757         pyutilib.misc.setup_redirect(currdir+'importA2.dat')
    758         print "import "+os.path.abspath(tutorial_dir+'excel.xls')+" range=Atable ;"
    759         pyutilib.misc.reset_redirect()
    760         model=AbstractModel()
    761         model.A = Set()
    762         try:
    763             instance = model.create(currdir+'importA2.dat')
    764             self.fail("Should fail because no set name is specified")
    765         except IOError:
    766             pass
    767         os.remove(currdir+'importA2.dat')
    768 
    769     def test_tableA3(self):
    770         """Importing a single column of data"""
    771         pyutilib.misc.setup_redirect(currdir+'importA3.dat')
    772         print "import "+os.path.abspath(tutorial_dir+'excel.xls')+" range=Atable : A ;"
    773         pyutilib.misc.reset_redirect()
    774         model=AbstractModel()
    775         model.A = Set()
    776         try:
    777             instance = model.create(currdir+'importA3.dat')
    778             self.fail("Should fail because no index is specified")
    779         except IOError:
    780             pass
    781         os.remove(currdir+'importA3.dat')
    782 
    783     def test_tableB(self):
    784         """Same as test_tableA"""
    785         pyutilib.misc.setup_redirect(currdir+'importB.dat')
    786         print "import "+os.path.abspath(tutorial_dir+'excel.xls')+" range=Btable format=set:B;"
    787         pyutilib.misc.reset_redirect()
    788         model=AbstractModel()
    789         model.B = Set()
    790         instance = model.create(currdir+'importB.dat')
    791         self.assertEqual(instance.B.data(), set([1, 2, 3]))
    792         os.remove(currdir+'importB.dat')
    793 
    794     def test_tableC(self):
    795         """Importing a multi-column table, where all columns are
    796         treated as values for a set with tuple values."""
    797         pyutilib.misc.setup_redirect(currdir+'importC.dat')
    798         print "import "+os.path.abspath(tutorial_dir+'excel.xls')+" range=Ctable format=set: C ;"
    799         pyutilib.misc.reset_redirect()
    800         model=AbstractModel()
    801         model.C = Set(dimen=2)
    802         instance = model.create(currdir+'importC.dat')
    803         self.assertEqual(instance.C.data(), set([('A1',1), ('A1',2), ('A1',3), ('A2',1), ('A2',2), ('A2',3), ('A3',1), ('A3',2), ('A3',3)]))
    804         os.remove(currdir+'importC.dat')
    805 
    806     def test_tableD(self):
    807         """Importing a 2D array of data as a set."""
    808         pyutilib.misc.setup_redirect(currdir+'importD.dat')
    809         print "import "+os.path.abspath(tutorial_dir+'excel.xls')+" range=Dtable format=set_array: C ;"
    810         pyutilib.misc.reset_redirect()
    811         model=AbstractModel()
    812         model.C = Set(dimen=2)
    813         instance = model.create(currdir+'importD.dat')
    814         self.assertEqual(instance.C.data(), set([('A1',1), ('A2',2), ('A3',3)]))
    815         os.remove(currdir+'importD.dat')
    816 
    817     def test_tableZ(self):
    818         """Importing a single parameter"""
    819         pyutilib.misc.setup_redirect(currdir+'importZ.dat')
    820         print "import "+os.path.abspath(tutorial_dir+'excel.xls')+" range=Zparam format=param: Z ;"
    821         pyutilib.misc.reset_redirect()
    822         model=AbstractModel()
    823         model.Z = Param(default=99.0)
    824         instance = model.create(currdir+'importZ.dat')
    825         self.assertEqual(instance.Z.value, 1.1)
    826         os.remove(currdir+'importZ.dat')
    827 
    828     def test_tableY(self):
    829         """Same as tableXW."""
    830         pyutilib.misc.setup_redirect(currdir+'importY.dat')
    831         print "import "+os.path.abspath(tutorial_dir+'excel.xls')+" range=Ytable : [A] Y;"
    832         pyutilib.misc.reset_redirect()
    833         model=AbstractModel()
    834         model.A = Set(initialize=['A1','A2','A3','A4'])
    835         model.Y = Param(model.A)
    836         instance = model.create(currdir+'importY.dat')
    837         self.assertEqual(instance.A.data(), set(['A1','A2','A3','A4']))
    838         self.assertEqual(instance.Y.data(), {'A1':3.3,'A2':3.4,'A3':3.5})
    839         os.remove(currdir+'importY.dat')
    840 
    841     def test_tableXW_1(self):
    842         """Importing a table, but only reporting the values for the non-index
    843         parameter columns.  The first column is assumed to represent an
    844         index column."""
    845         pyutilib.misc.setup_redirect(currdir+'importXW.dat')
    846         print "import "+os.path.abspath(tutorial_dir+'excel.xls')+" range=XWtable : [A] X W;"
    847         pyutilib.misc.reset_redirect()
    848         model=AbstractModel()
    849         model.A = Set(initialize=['A1','A2','A3','A4'])
    850         model.X = Param(model.A)
    851         model.W = Param(model.A)
    852         instance = model.create(currdir+'importXW.dat')
    853         self.assertEqual(instance.A.data(), set(['A1','A2','A3','A4']))
    854         self.assertEqual(instance.X.data(), {'A1':3.3,'A2':3.4,'A3':3.5})
    855         self.assertEqual(instance.W.data(), {'A1':4.3,'A2':4.4,'A3':4.5})
    856         os.remove(currdir+'importXW.dat')
    857 
    858     def test_tableXW_2(self):
    859         """Like test_tableXW_1, except that set A is not defined."""
    860         pyutilib.misc.setup_redirect(currdir+'importXW.dat')
    861         print "import "+os.path.abspath(tutorial_dir+'excel.xls')+" range=XWtable : [A] X W;"
    862         pyutilib.misc.reset_redirect()
    863         model=AbstractModel()
    864         model.A = Set(initialize=['A1','A2','A3'])
    865         model.X = Param(model.A)
    866         model.W = Param(model.A)
    867         instance = model.create(currdir+'importXW.dat')
    868         self.assertEqual(instance.X.data(), {'A1':3.3,'A2':3.4,'A3':3.5})
    869         self.assertEqual(instance.W.data(), {'A1':4.3,'A2':4.4,'A3':4.5})
    870         os.remove(currdir+'importXW.dat')
    871 
    872     def test_tableXW_3(self):
    873         """Like test_tableXW_1, except that set A is defined in the import statment."""
    874         pyutilib.misc.setup_redirect(currdir+'importXW.dat')
    875         print "import "+os.path.abspath(tutorial_dir+'excel.xls')+" range=XWtable: A=[A] X W;"
    876         pyutilib.misc.reset_redirect()
    877         model=AbstractModel()
    878         model.A = Set(initialize=['A1','A2','A3','A4'])
    879         model.X = Param(model.A)
    880         model.W = Param(model.A)
    881         instance = model.create(currdir+'importXW.dat')
    882         self.assertEqual(instance.A.data(), set(['A1','A2','A3']))
    883         self.assertEqual(instance.X.data(), {'A1':3.3,'A2':3.4,'A3':3.5})
    884         self.assertEqual(instance.W.data(), {'A1':4.3,'A2':4.4,'A3':4.5})
    885         os.remove(currdir+'importXW.dat')
    886 
    887     def test_tableXW_4(self):
    888         """Like test_tableXW_1, except that set A is defined in the import statment and all values are mapped."""
    889         pyutilib.misc.setup_redirect(currdir+'importXW.dat')
    890         print "import "+os.path.abspath(tutorial_dir+'excel.xls')+" range=XWtable: B=[A] R=X S=W;"
    891         pyutilib.misc.reset_redirect()
    892         model=AbstractModel()
    893         model.B = Set()
    894         model.R = Param(model.B)
    895         model.S = Param(model.B)
    896         instance = model.create(currdir+'importXW.dat')
    897         self.assertEqual(instance.B.data(), set(['A1','A2','A3']))
    898         self.assertEqual(instance.R.data(), {'A1':3.3,'A2':3.4,'A3':3.5})
    899         self.assertEqual(instance.S.data(), {'A1':4.3,'A2':4.4,'A3':4.5})
    900         os.remove(currdir+'importXW.dat')
    901 
    902     def test_tableT(self):
    903         """Importing a 2D array of parameters that are transposed."""
    904         pyutilib.misc.setup_redirect(currdir+'importT.dat')
    905         print "import "+os.path.abspath(tutorial_dir+'excel.xls')+" range=Ttable format=transposed_array : T;"
    906         pyutilib.misc.reset_redirect()
    907         model=AbstractModel()
    908         model.B = Set(initialize=['I1','I2','I3','I4'])
    909         model.A = Set(initialize=['A1','A2','A3'])
    910         model.T = Param(model.A, model.B)
    911         instance = model.create(currdir+'importT.dat')
    912         self.assertEqual(instance.T.data(), {('A2', 'I1'): 2.3, ('A1', 'I2'): 1.4, ('A1', 'I3'): 1.5, ('A1', 'I4'): 1.6, ('A1', 'I1'): 1.3, ('A3', 'I4'): 3.6, ('A2', 'I4'): 2.6, ('A3', 'I1'): 3.3, ('A2', 'I3'): 2.5, ('A3', 'I2'): 3.4, ('A2', 'I2'): 2.4, ('A3', 'I3'): 3.5})
    913         os.remove(currdir+'importT.dat')
    914 
    915     def test_tableU(self):
    916         """Importing a 2D array of parameters."""
    917         pyutilib.misc.setup_redirect(currdir+'importU.dat')
    918         print "import "+os.path.abspath(tutorial_dir+'excel.xls')+" range=Utable format=array : U;"
    919         pyutilib.misc.reset_redirect()
    920         model=AbstractModel()
    921         model.A = Set(initialize=['I1','I2','I3','I4'])
    922         model.B = Set(initialize=['A1','A2','A3'])
    923         model.U = Param(model.A, model.B)
    924         instance = model.create(currdir+'importU.dat')
    925         self.assertEqual(instance.U.data(), {('I2', 'A1'): 1.4, ('I3', 'A1'): 1.5, ('I3', 'A2'): 2.5, ('I4', 'A1'): 1.6, ('I3', 'A3'): 3.5, ('I1', 'A2'): 2.3, ('I4', 'A3'): 3.6, ('I1', 'A3'): 3.3, ('I4', 'A2'): 2.6, ('I2', 'A3'): 3.4, ('I1', 'A1'): 1.3, ('I2', 'A2'): 2.4})
    926         os.remove(currdir+'importU.dat')
    927 
    928     def test_tableS(self):
    929         """Importing a table, but only reporting the values for the non-index
    930         parameter columns.  The first column is assumed to represent an
    931         index column.  A missing value is represented in the column data."""
    932         pyutilib.misc.setup_redirect(currdir+'importS.dat')
    933         print "import "+os.path.abspath(tutorial_dir+'excel.xls')+" range=Stable : [A] S ;"
    934         pyutilib.misc.reset_redirect()
    935         model=AbstractModel()
    936         model.A = Set(initialize=['A1','A2','A3','A4'])
    937         model.S = Param(model.A)
    938         instance = model.create(currdir+'importS.dat')
    939         self.assertEqual(instance.A.data(), set(['A1','A2','A3','A4']))
    940         self.assertEqual(instance.S.data(), {'A1':3.3,'A3':3.5})
    941         os.remove(currdir+'importS.dat')
    942 
    943     def test_tablePO(self):
    944         """Importing a table that has multiple indexing columns"""
    945         pyutilib.misc.setup_redirect(currdir+'importPO.dat')
    946         print "import "+os.path.abspath(tutorial_dir+'excel.xls')+" range=POtable : J=[A,B] P O;"
    947         pyutilib.misc.reset_redirect()
    948         model=AbstractModel()
    949         model.J = Set(dimen=2)
    950         model.P = Param(model.J)
    951         model.O = Param(model.J)
    952         instance = model.create(currdir+'importPO.dat')
    953         self.assertEqual(instance.J.data(), set([('A3', 'B3'), ('A1', 'B1'), ('A2', 'B2')]) )
    954         self.assertEqual(instance.P.data(), {('A3', 'B3'): 4.5, ('A1', 'B1'): 4.3, ('A2', 'B2'): 4.4} )
    955         self.assertEqual(instance.O.data(), {('A3', 'B3'): 5.5, ('A1', 'B1'): 5.3, ('A2', 'B2'): 5.4})
    956         os.remove(currdir+'importPO.dat')
    957 
    958 TestSpreadsheet = unittest.skipIf(not _win32com, "Cannot import 'win32com'")(TestSpreadsheet)
    959 
    960 
    961 class TestModelData(unittest.TestCase):
    962 
    963     def test_tableA1(self):
    964         """Importing a single column of data"""
    965         md = ModelData()
    966         md.add(os.path.abspath(example_dir+'A.tab'), format='set', set='A')
    967         model=AbstractModel()
    968         model.A = Set()
    969         md.read(model)
    970         instance = model.create(md)
    971         self.assertEqual(instance.A.data(), set(['A1', 'A2', 'A3']))
    972 
    973     def test_tableA2(self):
    974         """Importing a single column of data"""
    975         md = ModelData()
    976         md.add(os.path.abspath(example_dir+'A.tab'))
    977         model=AbstractModel()
    978         model.A = Set()
    979         try:
    980             md.read(model)
    981             instance = model.create(md)
    982             self.fail("Should fail because no set name is specified")
    983         except IOError:
    984             pass
    985 
    986     def test_tableA3(self):
    987         """Importing a single column of data"""
    988         md = ModelData()
    989         md.add(os.path.abspath(example_dir+'A.tab'), set='A')
    990         model=AbstractModel()
    991         model.A = Set()
    992         try:
    993             md.read(model)
    994             instance = model.create(md)
    995             self.fail("Should fail because no index is specified")
    996         except IOError:
    997             pass
    998 
    999     def test_tableB(self):
    1000         """Same as test_tableA"""
    1001         md = ModelData()
    1002         md.add(os.path.abspath(example_dir+'B.tab'), format='set', set='B')
    1003         model=AbstractModel()
    1004         model.B = Set()
    1005         md.read(model)
    1006         instance = model.create(md)
    1007         self.assertEqual(instance.B.data(), set([1, 2, 3]))
    1008 
    1009     def test_tableC(self):
    1010         """Importing a multi-column table, where all columns are
    1011         treated as values for a set with tuple values."""
    1012         md = ModelData()
    1013         md.add(os.path.abspath(example_dir+'C.tab'), format='set', set='C')
    1014         model=AbstractModel()
    1015         model.C = Set(dimen=2)
    1016         md.read(model)
    1017         instance = model.create(md)
    1018         self.assertEqual(instance.C.data(), set([('A1',1), ('A1',2), ('A1',3), ('A2',1), ('A2',2), ('A2',3), ('A3',1), ('A3',2), ('A3',3)]))
    1019 
    1020     def test_tableD(self):
    1021         """Importing a 2D array of data as a set."""
    1022         md = ModelData()
    1023         md.add(os.path.abspath(example_dir+'D.tab'), format='set_array', set='C')
    1024         model=AbstractModel()
    1025         model.C = Set(dimen=2)
    1026         md.read(model)
    1027         instance = model.create(md)
    1028         self.assertEqual(instance.C.data(), set([('A1',1), ('A2',2), ('A3',3)]))
    1029 
    1030     def test_tableZ(self):
    1031         """Importing a single parameter"""
    1032         md = ModelData()
    1033         md.add(os.path.abspath(example_dir+'Z.tab'), format='param', param='Z')
    1034         model=AbstractModel()
    1035         model.Z = Param(default=99.0)
    1036         md.read(model)
    1037         instance = model.create(md)
    1038         self.assertEqual(instance.Z.value, 1.1)
    1039 
    1040     def test_tableY(self):
    1041         """Same as tableXW."""
    1042         md = ModelData()
    1043         md.add(os.path.abspath(example_dir+'Y.tab'), index=['A'], param=['Y'])
    1044         model=AbstractModel()
    1045         model.A = Set(initialize=['A1','A2','A3','A4'])
    1046         model.Y = Param(model.A)
    1047         md.read(model)
    1048         instance = model.create(md)
    1049         self.assertEqual(instance.A.data(), set(['A1','A2','A3','A4']))
    1050         self.assertEqual(instance.Y.data(), {'A1':3.3,'A2':3.4,'A3':3.5})
    1051 
    1052     def test_tableXW_1(self):
    1053         """Importing a table, but only reporting the values for the non-index
    1054         parameter columns.  The first column is assumed to represent an
    1055         index column."""
    1056         md = ModelData()
    1057         md.add(os.path.abspath(example_dir+'XW.tab'), index=['A'], param=['X','W'])
    1058         model=AbstractModel()
    1059         model.A = Set(initialize=['A1','A2','A3','A4'])
    1060         model.X = Param(model.A)
    1061         model.W = Param(model.A)
    1062         md.read(model)
    1063         instance = model.create(md)
    1064         self.assertEqual(instance.A.data(), set(['A1','A2','A3','A4']))
    1065         self.assertEqual(instance.X.data(), {'A1':3.3,'A2':3.4,'A3':3.5})
    1066         self.assertEqual(instance.W.data(), {'A1':4.3,'A2':4.4,'A3':4.5})
    1067 
    1068     def test_tableXW_2(self):
    1069         """Like test_tableXW_1, except that set A is not defined."""
    1070         md = ModelData()
    1071         md.add(os.path.abspath(example_dir+'XW.tab'), index=['A'], param=['X','W'])
    1072         model=AbstractModel()
    1073         model.A = Set(initialize=['A1','A2','A3'])
    1074         model.X = Param(model.A)
    1075         model.W = Param(model.A)
    1076         md.read(model)
    1077         instance = model.create(md)
    1078         self.assertEqual(instance.X.data(), {'A1':3.3,'A2':3.4,'A3':3.5})
    1079         self.assertEqual(instance.W.data(), {'A1':4.3,'A2':4.4,'A3':4.5})
    1080 
    1081     def test_tableXW_3(self):
    1082         """Like test_tableXW_1, except that set A is defined in the import statment."""
    1083         md = ModelData()
    1084         md.add(os.path.abspath(example_dir+'XW.tab'), index_name='A', index=['A'], param=['X','W'])
    1085         model=AbstractModel()
    1086         model.A = Set()
    1087         model.X = Param(model.A)
    1088         model.W = Param(model.A)
    1089         md.read(model)
    1090         instance = model.create(md)
    1091         self.assertEqual(instance.A.data(), set(['A1','A2','A3']))
    1092         self.assertEqual(instance.X.data(), {'A1':3.3,'A2':3.4,'A3':3.5})
    1093         self.assertEqual(instance.W.data(), {'A1':4.3,'A2':4.4,'A3':4.5})
    1094 
    1095     def test_tableXW_4(self):
    1096         """Like test_tableXW_1, except that set A is defined in the import statment and all values are mapped."""
    1097         md = ModelData()
    1098         md.add(os.path.abspath(example_dir+'XW.tab'), index_name='B', index=['A'], param=['X','W'], param_name={'X':'R', 'W':'S'})
    1099         model=AbstractModel()
    1100         model.B = Set()
    1101         model.R = Param(model.B)
    1102         model.S = Param(model.B)
    1103         md.read(model)
    1104         instance = model.create(md)
    1105         self.assertEqual(instance.B.data(), set(['A1','A2','A3']))
    1106         self.assertEqual(instance.R.data(), {'A1':3.3,'A2':3.4,'A3':3.5})
    1107         self.assertEqual(instance.S.data(), {'A1':4.3,'A2':4.4,'A3':4.5})
    1108 
    1109     def test_tableT(self):
    1110         """Importing a 2D array of parameters that are transposed."""
    1111         md = ModelData()
    1112         md.add(os.path.abspath(example_dir+'T.tab'), format='transposed_array', param='T')
    1113         model=AbstractModel()
    1114         model.B = Set(initialize=['I1','I2','I3','I4'])
    1115         model.A = Set(initialize=['A1','A2','A3'])
    1116         model.T = Param(model.A, model.B)
    1117         md.read(model)
    1118         instance = model.create(md)
    1119         self.assertEqual(instance.T.data(), {('A2', 'I1'): 2.3, ('A1', 'I2'): 1.4, ('A1', 'I3'): 1.5, ('A1', 'I4'): 1.6, ('A1', 'I1'): 1.3, ('A3', 'I4'): 3.6, ('A2', 'I4'): 2.6, ('A3', 'I1'): 3.3, ('A2', 'I3'): 2.5, ('A3', 'I2'): 3.4, ('A2', 'I2'): 2.4, ('A3', 'I3'): 3.5})
    1120 
    1121     def test_tableU(self):
    1122         """Importing a 2D array of parameters."""
    1123         md = ModelData()
    1124         md.add(os.path.abspath(example_dir+'T.tab'), format='array', param='U')
    1125         model=AbstractModel()
    1126         model.A = Set(initialize=['I1','I2','I3','I4'])
    1127         model.B = Set(initialize=['A1','A2','A3'])
    1128         model.U = Param(model.A, model.B)
    1129         md.read(model)
    1130         instance = model.create(md)
    1131         self.assertEqual(instance.U.data(), {('I2', 'A1'): 1.4, ('I3', 'A1'): 1.5, ('I3', 'A2'): 2.5, ('I4', 'A1'): 1.6, ('I3', 'A3'): 3.5, ('I1', 'A2'): 2.3, ('I4', 'A3'): 3.6, ('I1', 'A3'): 3.3, ('I4', 'A2'): 2.6, ('I2', 'A3'): 3.4, ('I1', 'A1'): 1.3, ('I2', 'A2'): 2.4})
    1132 
    1133     def test_tableS(self):
    1134         """Importing a table, but only reporting the values for the non-index
    1135         parameter columns.  The first column is assumed to represent an
    1136         index column.  A missing value is represented in the column data."""
    1137         md = ModelData()
    1138         md.add(os.path.abspath(example_dir+'S.tab'), index=['A'], param=['S'])
    1139         model=AbstractModel()
    1140         model.A = Set(initialize=['A1','A2','A3','A4'])
    1141         model.S = Param(model.A)
    1142         md.read(model)
    1143         instance = model.create(md)
    1144         self.assertEqual(instance.A.data(), set(['A1','A2','A3','A4']))
    1145         self.assertEqual(instance.S.data(), {'A1':3.3,'A3':3.5})
     1151        self.assertEqual(instance.S.sparse_extract_values(), {'A1':3.3,'A3':3.5})
    11461152
    11471153    def test_tablePO(self):
     
    11591165        instance = model.create(md)
    11601166        self.assertEqual(instance.J.data(), set([('A3', 'B3'), ('A1', 'B1'), ('A2', 'B2')]) )
    1161         self.assertEqual(instance.P.data(), {('A3', 'B3'): 4.5, ('A1', 'B1'): 4.3, ('A2', 'B2'): 4.4} )
    1162         self.assertEqual(instance.O.data(), {('A3', 'B3'): 5.5, ('A1', 'B1'): 5.3, ('A2', 'B2'): 5.4})
     1167        self.assertEqual(
     1168            instance.P.sparse_extract_values(),
     1169            {('A3', 'B3'): 4.5, ('A1', 'B1'): 4.3, ('A2', 'B2'): 4.4} )
     1170        self.assertEqual(instance.O.sparse_extract_values(), {('A3', 'B3'): 5.5, ('A1', 'B1'): 5.3, ('A2', 'B2'): 5.4})
    11631171
    11641172
  • coopr.pyomo/trunk/coopr/pyomo/tests/unit/test_param.py

    r5699 r5803  
    1010#
    1111
    12 import pyutilib.th as unittest
     12import math
    1313import os
    1414import sys
    1515from os.path import abspath, dirname
    1616sys.path.insert(0, dirname(dirname(abspath(__file__)))+"/../..")
     17
     18import pyutilib.th as unittest
    1719from coopr.pyomo import *
    18 import math
    19 
    20 class PyomoModel(unittest.TestCase):
    21 
    22     def config_repn(self):
    23         self.repn = 'pyomo_dict'
    24 
    25     def setUp(self):
    26         self.config_repn()
     20
     21class ParamTester(object):
     22
     23    def setUp(self, **kwds):
     24        #
     25        # Sparse single-index Param, no default
     26        #
    2727        self.model = AbstractModel()
    28 
    29     def construct(self,filename):
    30         self.instance = self.model.create(filename)
    31 
    32 
    33 class SimpleParam(PyomoModel):
    34 
    35     def setUp(self):
    36         #
    37         # Create Model
    38         #
    39         PyomoModel.setUp(self)
    40         #
    41         # Create model instance
    42         #
    43         self.model.A = Param(initialize=3.3, repn=self.repn)
     28        self.model.Z = Set(initialize=[1,3])
     29        self.model.A = Param(self.model.Z, **kwds)
    4430        self.instance = self.model.create()
    4531
    46     def tearDown(self):
    47         if os.path.exists("param.dat"):
    48             os.remove("param.dat")
     32        self.expectTextDomainError = False
     33        self.expectNegativeDomainError = False
     34
     35    def validateDict(self, ref, test):
     36        test = dict(test)
     37        ref = dict(ref)
     38        self.assertEqual( len(test), len(ref) )
     39        for key in test.keys():
     40            self.assertTrue( key in ref )
     41            if ref[key] is None:
     42                self.assertTrue( test[key] is None or test[key].value is None )
     43            else:
     44                self.assertEquals( ref[key], value( test[key] ) )
     45       
    4946
    5047    def test_value(self):
    51         """Check the value of the parameter"""
    52         tmp = value(self.instance.A)
    53         self.assertEqual( type(tmp), float)
    54         self.assertEqual( tmp, 3.3 )
    55         tmp = float(self.instance.A)
    56         self.assertEqual( type(tmp), float)
    57         self.assertEqual( tmp, 3.3 )
    58         tmp = int(self.instance.A)
    59         self.assertEqual( type(tmp), int)
    60         self.assertEqual( tmp, 3 )
    61 
    62     def test_getattr(self):
    63         """Check the use of the __getattr__ method"""
    64         if self.instance.components.A.repn_type == 'pyomo_dict':
    65             self.assertEqual( self.instance.A.value, 3.3)
     48        self.assertRaises(ValueError, value, self.instance.A)
     49        self.assertRaises(TypeError, float, self.instance.A)
     50        self.assertRaises(TypeError, int, self.instance.A)
     51
     52        if self.instance.A._default_val is None:
     53            val_list = self.sparse_data.items()
    6654        else:
    67             self.assertEqual( self.instance.A, 3.3)
    68 
    69     def test_setattr_value(self):
    70         """Check the use of the __setattr__ method"""
    71         self.instance.A = 3.3
    72         self.assertEqual( self.instance.A, 3.3)
    73         self.assertEqual( self.instance.components.A[None], 3.3)
    74         if self.instance.components.A.repn_type == 'pyomo_dict':
    75             self.assertEqual( self.instance.A.value, 3.3)
    76         if self.instance.components.A.repn_type == 'pyomo_dict':
    77             self.instance.A.value = 4.3
    78             self.assertEqual( self.instance.A.value, 4.3)
     55            val_list = self.data.items()
     56
     57        for key, val in val_list:
     58            tmp = value(self.instance.A[key])
     59            self.assertEqual( type(tmp), type(val))
     60            self.assertEqual( tmp, val )
     61           
     62            tmp = float(self.instance.A[key])
     63            self.assertEqual( type(tmp), float)
     64            self.assertEqual( tmp, float(val) )
     65
     66            tmp = int(self.instance.A[key])
     67            self.assertEqual( type(tmp), int)
     68            self.assertEqual( tmp, int(val) )
     69
     70    def test_call(self):
     71        #"""Check the use of the __call__ method"""
     72        self.assertRaises(TypeError, self.instance.A)
     73
     74    def test_get_valueattr(self):
     75        try:
     76            tmp = self.instance.A.value
     77            self.fail("Array Parameters should not contain a value")
     78        except AttributeError:
     79            pass
     80
     81    # JDS: I would like this test to work, but there is no way to
     82    # prevent a user from adding new attributed to the (indexed) Param
     83    # instance.
     84    #
     85    #def test_set_valueattr(self):
     86    #    try:
     87    #        self.instance.A.value = 4.3
     88    #        self.fail("Array Parameters should not be settable")
     89    #    except AttributeError:
     90    #        pass
     91
     92    def test_set_value(self):
     93        try:
     94            self.instance.A = 4.3
     95            self.fail("Array Parameters should not be settable")
     96        except ValueError:
     97            pass
     98
     99    def test_getitem(self):
     100        for key, val in self.data.iteritems():
    79101            try:
    80                 self.instance.A.value = 'A'
     102                test = self.instance.A[key]
     103                self.assertEqual( value(test), val )
    81104            except ValueError:
    82                 self.fail("fail test_setattr_value")
    83             else:
    84                 #
    85                 # NOTE: we can set bad values into a NumericValue object
    86                 #
    87                 pass
    88 
    89     def test_setattr_default(self):
    90         """Check the use of the __setattr__ method"""
    91         self.model.A = Param(repn=self.repn, default=4.3)
    92         self.instance = self.model.create()
    93         self.assertEqual( value(self.instance.A), 4.3)
    94         self.assertEqual( self.instance.components.A[None], 4.3)
    95 
    96     def test_dim(self):
    97         """Check the use of dim"""
    98         self.assertEqual( self.instance.components.A.dim(), 0)
    99 
    100     def test_keys(self):
    101         """Check the use of keys"""
    102         self.assertEqual( len(self.instance.components.A.keys()), 1)
    103 
    104     def test_len(self):
    105         """Check the use of len"""
    106         self.assertEqual( len(self.instance.components.A), 1)
    107 
    108     def test_getitem(self):
    109         import coopr.pyomo.base.param
    110         #print 'xxx',self.instance.components.components()
    111         #print 'XXX',type(self.instance.A),self.instance.A,self.instance.components.A,'YY'
    112         #print 'yyy',self.model.A.repn
    113         #print 'YYY', type(self.instance.A[None])
    114         if self.instance.components.A.repn_type == 'pyomo_dict':
    115             self.assertTrue(isinstance(self.instance.A[None], coopr.pyomo.base.param._ParamData))
    116         self.assertEqual( self.instance.components.A[None], 3.3)
    117 
    118     def test_check_values(self):
    119         """Check the use of check_values"""
    120         self.instance.components.A.check_values()
    121 
    122 
    123 class MSimpleParam(SimpleParam):
    124 
    125     def config_repn(self):
    126         self.repn = 'sparse_dict'
    127 
    128 MSimpleParam = unittest.skipIf(sys.version_info[:2] < (2,6), "Skipping tests because sparse_dict repn is not supported")(MSimpleParam)
    129 
    130 
    131 class ArrayParam1(SimpleParam):
    132 
    133     def setUp(self):
    134         #
    135         # Create Model
    136         #
    137         PyomoModel.setUp(self)
    138         #
    139         # Create model instance
    140         #
    141         self.model.Z = Set(initialize=[1,3])
    142         self.model.A = Param(self.model.Z, initialize={1:1.3}, repn=self.repn)
    143         self.instance = self.model.create()
    144 
    145     def test_value(self):
    146         try:
    147             tmp = value(self.instance.A)
    148         except ValueError:
    149             pass
    150         else:
    151             self.fail("test_value")
    152         try:
    153             tmp = float(self.instance.A)
    154         except TypeError:
    155             pass
    156         except ValueError:
    157             pass
    158         else:
    159             self.fail("test_value")
    160         try:
    161             tmp = int(self.instance.A)
    162         except TypeError:
    163             pass
    164         except ValueError:
    165             pass
    166         else:
    167             self.fail("test_value")
    168         tmp = value(self.instance.A[1])
    169         self.assertEqual( type(tmp), float)
    170         self.assertEqual( tmp, 1.3 )
    171         tmp = float(self.instance.A[1])
    172         self.assertEqual( type(tmp), float)
    173         self.assertEqual( tmp, 1.3 )
    174         tmp = int(self.instance.A[1])
    175         self.assertEqual( type(tmp), int)
    176         self.assertEqual( tmp, 1 )
    177 
    178     def test_call(self):
    179         """Check the use of the __call__ method"""
    180         try:
    181             tmp = self.instance.A()
    182         except TypeError:
    183             pass
    184         else:
    185             self.fail("test_call")
    186 
    187     def test_getattr(self):
    188         """Check the use of the __getattr__ method"""
    189         try:
    190             tmp = self.instance.A.value
    191         except AttributeError:
    192             pass
    193         else:
    194             self.fail("test_call")
    195 
    196     def test_setattr_value(self):
    197         """Check the use of the __setattr__ method"""
    198         import coopr.pyomo.base.param
    199         self.instance.components.A.value = 4.3
    200         #print type(self.instance.components.A)
    201         self.instance.components.A = 4.3
    202         #print type(self.instance.components.A)
    203         if self.instance.components.A.repn_type == 'pyomo_dict':
    204             self.instance.A[1].value = 4.3
    205             self.assertEqual( type(self.instance.A[1]), coopr.pyomo.base.param._ParamData)
    206         self.instance.A[1] = 4.3
    207         if self.instance.components.A.repn_type == 'pyomo_dict':
    208             self.assertEqual( type(self.instance.A[1]), coopr.pyomo.base.param._ParamData)
    209         else:
    210             self.assertEqual( type(self.instance.A[1]), float)
    211 
    212 
    213     def test_setitem(self):
    214         """Check the use of the __setattr__ method"""
    215         self.instance.A[3] = 4.3
    216         self.assertEqual( self.instance.A[3], 4.3)
    217         self.instance.A[1] = 4.3
    218         self.assertEqual( self.instance.A[1], 4.3)
    219         try:
    220             self.instance.A[3] = 'A'
    221         except ValueError:
    222             self.fail("fail test_setitem")
     105                if val is not None:
     106                    raise
     107
     108    def test_setitem_index_error(self):
    223109        try:
    224110            self.instance.A[2] = 4.3
     
    227113            pass
    228114
     115    def test_setitem_preexisting(self):
     116        keys = self.instance.A.sparse_keys()
     117        if not keys:
     118            return
     119       
     120        idx = sorted(keys)[0]
     121        self.assertEqual(self.instance.A[idx], self.data[idx])
     122        if self.instance.A._mutable:
     123            self.assertTrue( isinstance( self.instance.A[idx],
     124                                         coopr.pyomo.base.param._ParamData ) )
     125        else:
     126            self.assertEqual(type(self.instance.A[idx]), float)
     127
     128        self.instance.A[idx] = 4.3
     129        self.assertEqual( self.instance.A[idx], 4.3)
     130        if self.instance.A._mutable:
     131            self.assertTrue( isinstance(self.instance.A[idx],
     132                                        coopr.pyomo.base.param._ParamData ) )
     133        else:
     134            self.assertEqual(type(self.instance.A[idx]), float)
     135   
     136        try:
     137            self.instance.A[idx] = -4.3
     138            if self.expectNegativeDomainError:
     139                self.fail("Expected setitem[%s] to fail with negative data"
     140                          % (idx,))
     141            self.assertEquals( self.instance.A[idx], -4.3 )
     142        except ValueError:
     143            if not self.expectNegativeDomainError:
     144                self.fail(
     145                    "Unexpected exception (%s) for setitem[%s] = negative data"
     146                    % ( str(sys.exc_info()[1]), idx ) )
     147
     148        try:
     149            self.instance.A[idx] = 'x'
     150            if self.expectTextDomainError:
     151                self.fail("Expected setitem[%s] to fail with text data",
     152                          (idx,))
     153            self.assertEquals( value(self.instance.A[idx]), 'x' )
     154        except ValueError:
     155            if not self.expectTextDomainError:
     156                self.fail(
     157                    "Unexpected exception (%s) for setitem[%s] with text data"
     158                    % ( str(sys.exc_info()[1]), idx ) )
     159
     160
     161    def test_setitem_default_override(self):
     162        sparse_keys = set(self.instance.A.sparse_keys())
     163        keys = sorted(self.instance.A.keys())
     164        if len(keys) == len(sparse_keys):
     165            # No default value possible
     166            return
     167        if self.instance.A._default_val is None:
     168            # No default value defined
     169            return
     170
     171        while True:
     172            idx = keys.pop(0)
     173            if not idx in sparse_keys:
     174                break
     175
     176        self.assertEqual( value(self.instance.A[idx]),
     177                          self.instance.A._default_val )
     178        if self.instance.A._mutable:
     179            self.assertEqual( type(self.instance.A[idx]),
     180                              coopr.pyomo.base.param._ParamData )
     181        else:
     182            self.assertEqual(type(self.instance.A[idx]), float)
     183
     184        self.instance.A[idx] = 4.3
     185        self.assertEqual( self.instance.A[idx], 4.3)
     186        if self.instance.A._mutable:
     187            self.assertEqual( type(self.instance.A[idx]),
     188                              coopr.pyomo.base.param._ParamData )
     189        else:
     190            self.assertEqual(type(self.instance.A[idx]), float)
     191   
     192        try:
     193            self.instance.A[idx] = -4.3
     194            if self.expectNegativeDomainError:
     195                self.fail("Expected setitem[%s] to fail with negative data"
     196                          % (idx,))
     197            self.assertEquals( self.instance.A[idx], -4.3 )
     198        except ValueError:
     199            if not self.expectNegativeDomainError:
     200                self.fail(
     201                    "Unexpected exception (%s) for setitem[%s] = negative data"
     202                    % ( str(sys.exc_info()[1]), idx ) )
     203
     204        try:
     205            self.instance.A[idx] = 'x'
     206            if self.expectTextDomainError:
     207                self.fail("Expected setitem[%s] to fail with text data"
     208                          % (idx,))
     209            self.assertEquals( value(self.instance.A[idx]), 'x' )
     210        except ValueError:
     211            if not self.expectTextDomainError:
     212                self.fail(
     213                    "Unexpected exception (%s) for setitem[%s] with text data"
     214                    % ( str(sys.exc_info()[1]), idx) )
     215
     216    def test_dim(self):
     217        key = self.data.keys()[0]
     218        try:
     219            key = tuple(key)
     220        except TypeError:
     221            key = (key,)
     222        self.assertEqual( self.instance.A.dim(), len(key))
     223
     224    def test_is_indexed(self):
     225        self.assertTrue(self.instance.A.is_indexed())
     226
    229227    def test_keys(self):
    230         """Check the use of keys"""
    231         self.assertEqual( len(self.instance.A.keys()), 1)
    232 
    233     def test_dim(self):
    234         """Check the use of dim"""
    235         self.assertEqual( self.instance.components.A.dim(), 1)
     228        test = self.instance.A.keys()
     229        self.assertEqual( type(test), list )
     230        self.assertEqual( sorted(test), sorted(self.data.keys()) )
     231
     232    def test_values(self):
     233        expectException = len(self.sparse_data) < len(self.data) and self.instance.A._default_val is None
     234        try:
     235            test = self.instance.A.values()
     236            self.assertEqual( type(test), list )
     237            test = zip(self.instance.A.keys(), test)
     238            self.validateDict(self.data.items(), test)
     239            self.assertFalse(expectException)
     240        except ValueError:
     241            if not expectException:
     242                raise
     243
     244    def test_items(self):
     245        expectException = len(self.sparse_data) < len(self.data) and self.instance.A._default_val is None
     246        try:
     247            test = self.instance.A.items()
     248            self.assertEqual( type(test), list )
     249            self.validateDict(self.data.items(), test)
     250            self.assertFalse(expectException)
     251        except ValueError:
     252            if not expectException:
     253                raise
     254
     255    def test_iterkeys(self):
     256        test = self.instance.A.iterkeys()
     257        self.assertTrue('next' in dir(test))
     258        self.assertEqual( sorted(test), sorted(self.data.keys()) )
     259
     260    def test_itervalues(self):
     261        expectException = len(self.sparse_data) < len(self.data) and self.instance.A._default_val is None
     262        try:
     263            test = self.instance.A.itervalues()
     264            self.assertTrue('next' in dir(test))
     265            test = zip(self.instance.A.keys(), test)
     266            self.validateDict(self.data.items(), test)
     267            self.assertFalse(expectException)
     268        except ValueError:
     269            if not expectException:
     270                raise
     271
     272    def test_iteritems(self):
     273        expectException = len(self.sparse_data) < len(self.data) and self.instance.A._default_val is None
     274        try:
     275            test = self.instance.A.iteritems()
     276            self.assertTrue('next' in dir(test))
     277            self.validateDict(self.data.items(), test)
     278            self.assertFalse(expectException)
     279        except ValueError:
     280            if not expectException:
     281                raise
     282
     283
     284    def test_sparse_keys(self):
     285        test = self.instance.A.sparse_keys()
     286        self.assertEqual( type(test), list )
     287        self.assertEqual( sorted(test), sorted(self.sparse_data.keys()) )
     288
     289    def test_sparse_values(self):
     290        test = self.instance.A.sparse_values()
     291        self.assertEqual( type(test), list )
     292        test = zip(self.instance.A.keys(), test)
     293        self.validateDict(self.sparse_data.items(), test)
     294
     295    def test_sparse_items(self):
     296        test = self.instance.A.sparse_items()
     297        self.assertEqual( type(test), list )
     298        self.validateDict(self.sparse_data.items(), test)
     299
     300
     301    def test_sparse_iterkeys(self):
     302        test = self.instance.A.sparse_iterkeys()
     303        self.assertTrue('next' in dir(test))
     304        self.assertEqual( sorted(test), sorted(self.sparse_data.keys()) )
     305
     306    def test_sparse_itervalues(self):
     307        test = self.instance.A.sparse_itervalues()
     308        self.assertTrue('next' in dir(test))
     309        test = zip(self.instance.A.keys(), test)
     310        self.validateDict(self.sparse_data.items(), test)
     311
     312    def test_sparse_iteritems(self):
     313        test = self.instance.A.sparse_iteritems()
     314        self.assertTrue('next' in dir(test))
     315        self.validateDict(self.sparse_data.items(), test)
     316
    236317
    237318    def test_len(self):
    238         """Check the use of len"""
    239         self.instance.A[3] = 4.3
    240         self.assertEqual( len(self.instance.A), 2)
     319        #"""Check the use of len"""
     320        self.assertEqual( len(self.instance.A), len(self.data) )
     321        self.assertEqual( len(self.instance.A.keys()), len(self.data) )
     322        self.assertEqual( len(self.instance.A.sparse_keys()),
     323                          len(self.sparse_data) )
    241324
    242325    def test_index(self):
    243         """Check the use of index"""
    244         self.instance.A[3] = 4.3
    245         self.assertEqual( len(self.instance.A.index()), 2)
    246 
    247     def test_getitem(self):
    248         import coopr.pyomo.base.param
    249         try:
    250             self.assertEqual( self.instance.A[1], 1.3)
    251         except KeyError:
    252             self.fail("test_getitem")
    253 
    254         if self.instance.components.A.repn_type == 'pyomo_dict':
    255             self.assertEqual(type(self.instance.A[1]), coopr.pyomo.base.param._ParamData)
    256         else:
    257             self.assertEqual(type(self.instance.A[1]), float)
    258 
    259         try:
    260             self.instance.A[3]
    261         except KeyError:
    262             pass
    263         except ValueError:
    264             pass
    265         else:
    266             self.fail("test_getitem")
    267 
    268 
    269 class MArrayParam1(ArrayParam1):
    270 
    271     def config_repn(self):
    272         self.repn = 'sparse_dict'
    273 
    274 MArrayParam1 = unittest.skipIf(sys.version_info[:2] < (2,6), "Skipping tests because sparse_dict repn is not supported")(MArrayParam1)
    275 
    276 
    277 class ArrayParam2(ArrayParam1):
    278 
    279     def setUp(self):
     326        #"""Check the use of index"""
     327        self.assertEqual( len(self.instance.A.index()),
     328                          len(self.instance.A.keys()) )
     329        self.assertEqual( len(self.instance.A.index()),
     330                          len(self.data.keys()) )
     331
     332
     333class ArrayParam1(ParamTester, unittest.TestCase):
     334
     335    def setUp(self, **kwds):
     336        #
     337        # Sparse single-index Param, no default
     338        #
     339        ParamTester.setUp(self, initialize={1:1.3}, **kwds)
     340       
     341        self.sparse_data = {1:1.3}
     342        self.data = {1:1.3, 3:None}
     343
     344
     345class ArrayParam2(ParamTester, unittest.TestCase):
     346
     347    def setUp(self, **kwds):
     348        #
     349        # Sparse single-index Param, int default
     350        #
     351        ParamTester.setUp(self, initialize={1:1.3}, default=0, **kwds)
     352
     353        self.sparse_data = {1:1.3}
     354        self.data = {1:1.3, 3:0}
     355
     356
     357class ArrayParam3(ParamTester, unittest.TestCase):
     358
     359    def setUp(self, **kwds):
     360        #
     361        # Sparse single-index Param, float default
     362        #
     363        ParamTester.setUp(self, initialize={1:1.3}, default=99.5, **kwds)
     364
     365        self.sparse_data = {1:1.3}
     366        self.data = {1:1.3, 3:99.5}
     367
     368
     369class ArrayParam4(ParamTester, unittest.TestCase):
     370
     371    def setUp(self, **kwds):
     372        #
     373        # Dense single-index Param, float default, init with scalar
     374        #
     375        ParamTester.setUp(self, initialize=1.3, default=99.5, **kwds)
     376
     377        self.sparse_data = {1:1.3, 3:1.3}
     378        self.data = self.sparse_data
     379
     380
     381class ArrayParam5(ParamTester, unittest.TestCase):
     382
     383    def setUp(self, **kwds):
     384        def A_init(model, i):
     385            return 1.5+i
     386        #
     387        # Dense single-index Param, no default, init with rule
     388        #
     389        ParamTester.setUp(self, initialize=A_init, **kwds)
     390
     391        self.sparse_data = {1:2.5, 3:4.5}
     392        self.data = self.sparse_data
     393
     394
     395class ArrayParam6(object):
     396
     397    def setUp(self, **kwds):
    280398        #
    281399        # Create Model
    282400        #
    283         PyomoModel.setUp(self)
    284         #
    285         # Create model instance
    286         #
    287         self.model.Z = Set(initialize=[1,3])
    288         self.model.A = Param(self.model.Z, initialize={1:1.3}, default=0.0, repn=self.repn)
    289         self.instance = self.model.create()
    290 
    291     def test_setattr_default(self):
    292         """Check the use of the __setattr__ method"""
    293         self.model.Z = Set(initialize=[1,3])
    294         self.model.A = Param(self.model.Z, repn=self.repn, default=4.3)
    295         self.instance = self.model.create()
    296         self.assertEqual( self.instance.A[3], 4.3)
    297 
    298     def test_keys(self):
    299         """Check the use of keys"""
    300         self.assertEqual( len(self.instance.A.keys()), 2)
    301 
    302     def test_len(self):
    303         """Check the use of len"""
    304         self.assertEqual( len(self.instance.A), 2)
    305 
    306     def test_getitem(self):
    307         try:
    308             self.assertEqual( self.instance.A[None], 0.0)
    309         except KeyError:
    310             pass
    311         else:
    312             if self.instance.components.A.repn_type == 'pyomo_dict':
    313                 self.fail("test_getitem")
    314         self.assertEqual( self.instance.A[1], 1.3)
    315         self.assertEqual( self.instance.A[3], 0)
    316 
    317 
    318 class MArrayParam2(ArrayParam2):
    319 
    320     def config_repn(self):
    321         self.repn = 'sparse_dict'
    322 
    323 MArrayParam2 = unittest.skipIf(sys.version_info[:2] < (2,6), "Skipping tests because sparse_dict repn is not supported")(MArrayParam2)
    324 
    325 class ArrayParam3(ArrayParam2):
    326 
    327     def setUp(self):
    328         #
    329         # Create Model
    330         #
    331         PyomoModel.setUp(self)
    332         #
    333         # Create model instance
    334         #
    335         self.model.Z = Set(initialize=[1,3])
    336         self.model.A = Param(self.model.Z, initialize={1:1.3}, default=99.0, repn=self.repn)
    337         self.instance = self.model.create()
    338 
    339     def test_len(self):
    340         """Check the use of len"""
    341         self.assertEqual( len(self.instance.A), 2)
    342 
    343     def test_getitem(self):
    344         try:
    345             self.assertEqual( self.instance.A[None], 0.0)
    346         except AssertionError:
    347             if self.instance.components.A.repn_type == 'pyomo_dict':
    348                 self.fail("test_getitem")
    349         except KeyError:
    350             pass
    351         else:
    352             self.fail("test_getitem")
    353         self.assertEqual( self.instance.A[1], 1.3)
    354         self.assertEqual( self.instance.A[3], 99.0)
    355 
    356 
    357 class MArrayParam3(ArrayParam3):
    358 
    359     def config_repn(self):
    360         self.repn = 'sparse_dict'
    361 
    362 MArrayParam3 = unittest.skipIf(sys.version_info[:2] < (2,6), "Skipping tests because sparse_dict repn is not supported")(MArrayParam3)
    363 
    364 
    365 class ArrayParam4(ArrayParam3):
    366 
    367     def setUp(self):
    368         #
    369         # Create Model
    370         #
    371         PyomoModel.setUp(self)
    372         #
    373         # Create model instance
    374         #
    375         self.model.Z = Set(initialize=[1,3])
    376         self.model.A = Param(self.model.Z, initialize=1.3, repn=self.repn)
    377         self.instance = self.model.create()
    378 
    379     def test_keys(self):
    380         """Check the use of keys"""
    381         self.assertEqual( len(self.instance.A.keys()), 2)
    382 
    383     def test_len(self):
    384         """Check the use of len"""
    385         self.assertEqual( len(self.instance.A), 2)
    386 
    387     def test_getitem(self):
    388         try:
    389             self.assertEqual( self.instance.A[None], 0.0)
    390         except KeyError:
    391             pass
    392         else:
    393             self.fail("test_getitem")
    394         self.assertEqual( self.instance.A[1], 1.3)
    395         self.assertEqual( self.instance.A[3], 1.3)
    396 
    397 
    398 class MArrayParam4(ArrayParam4):
    399 
    400     def config_repn(self):
    401         self.repn = 'sparse_dict'
    402 
    403 MArrayParam4 = unittest.skipIf(sys.version_info[:2] < (2,6), "Skipping tests because sparse_dict repn is not supported")(MArrayParam4)
    404 
    405 
    406 class ArrayParam5(ArrayParam4):
    407 
    408     def setUp(self):
    409         #
    410         # Create Model
    411         #
    412         PyomoModel.setUp(self)
    413         #
    414         # Create model instance
    415         #
    416         self.model.Z = Set(initialize=[1,3])
    417         def A_init(model, i):
    418             return 1.3
    419         self.model.A = Param(self.model.Z, initialize=A_init, repn=self.repn)
    420         self.instance = self.model.create()
    421 
    422 
    423 class MArrayParam5(ArrayParam5):
    424 
    425     def config_repn(self):
    426         self.repn = 'sparse_dict'
    427 
    428 MArrayParam5 = unittest.skipIf(sys.version_info[:2] < (2,6), "Skipping tests because sparse_dict repn is not supported")(MArrayParam5)
    429 
    430 
    431 class ArrayParam6(PyomoModel):
     401        self.model = AbstractModel()
     402        self.repn = '_bogus_'
    432403
    433404    def test_index1(self):
     
    524495            pass
    525496
    526 class MArrayParam6(ArrayParam6):
    527 
    528     def config_repn(self):
    529         self.repn = 'sparse_dict'
    530 
    531 MArrayParam6 = unittest.skipIf(sys.version_info[:2] < (2,6), "Skipping tests because sparse_dict repn is not supported")(MArrayParam6)
    532 
    533 
    534 class TestIO(PyomoModel):
     497
     498class SimpleParam(ParamTester):
     499
     500    def setUp(self, **kwds):
     501        self.model = AbstractModel()
     502        self.model.A = Param(initialize=3.3, **kwds)
     503        self.instance = self.model.create()
     504
     505        self.expectTextDomainError = False
     506        self.expectNegativeDomainError = False
     507
     508        self.data = {None:3.3}
     509        self.sparse_data = self.data
     510
     511
     512    def test_value(self):
     513        #"""Check the value of the parameter"""
     514        tmp = value(self.instance.A)
     515        self.assertEqual( type(tmp), float)
     516        self.assertEqual( tmp, self.data[None] )
     517        tmp = float(self.instance.A)
     518        self.assertEqual( type(tmp), float)
     519        self.assertEqual( tmp, float(self.data[None]) )
     520        tmp = int(self.instance.A)
     521        self.assertEqual( type(tmp), int)
     522        self.assertEqual( tmp, int(self.data[None]) )
     523
     524    def test_call(self):
     525        #"""Check the use of the __call__ method"""
     526        self.assertEqual(self.instance.A(), 3.3)
     527
     528    def test_get_valueattr(self):
     529        self.assertEqual(self.instance.A.value, 3.3)
     530
     531    def test_set_valueattr(self):
     532        self.instance.A.value = 4.3
     533        self.assertEqual(self.instance.A.value, 4.3)
     534        self.assertEqual(self.instance.A(), 4.3)
     535
     536    def test_set_value(self):
     537        self.instance.A = 4.3
     538        self.assertEqual(self.instance.A.value, 4.3)
     539        self.assertEqual(self.instance.A(), 4.3)
     540
     541    def test_get_value(self):
     542        self.assertEqual( self.instance.A, 3.3)
     543
     544
     545    def test_is_indexed(self):
     546        self.assertFalse(self.instance.A.is_indexed())
     547
     548    def test_dim(self):
     549        #"""Check the use of dim"""
     550        self.assertEqual( self.instance.components.A.dim(), 0)
     551
     552
     553
     554class TestIO(unittest.TestCase):
    535555
    536556    def setUp(self):
     
    538558        # Create Model
    539559        #
    540         PyomoModel.setUp(self)
     560        self.model = AbstractModel()
     561        self.repn = '_bogus_'
    541562
    542563    def tearDown(self):
     
    727748        self.model.B=Param(self.model.A1,self.model.A2,self.model.A1, repn=self.repn)
    728749        self.instance = self.model.create("param.dat")
    729         self.assertEqual( set(self.instance.B.keys()), set([('e', 2, 'f'), ('c', 2, 'd'), ('a', 2, 'b'), ('i', 4, 'j'), ('g', 4, 'h'), ('k', 6, 'l')]))
    730 
    731 
    732 class MTestIO(TestIO):
    733 
    734     def config_repn(self):
    735         self.repn = 'sparse_dict'
    736 
    737 MTestIO = unittest.skipIf(sys.version_info[:2] < (2,6), "Skipping tests because sparse_dict repn is not supported")(MTestIO)
    738 
    739 
    740 class TestParamConditional(PyomoModel):
     750        self.assertEqual( set(self.instance.B.sparse_keys()), set([('e', 2, 'f'), ('c', 2, 'd'), ('a', 2, 'b'), ('i', 4, 'j'), ('g', 4, 'h'), ('k', 6, 'l')]))
     751
     752
     753
     754class TestParamConditional(unittest.TestCase):
     755
     756    def setUp(self):
     757        self.model = AbstractModel()
    741758
    742759    def test1(self):
     
    790807        instance = model.create()
    791808
     809    def test_get_uninitialized(self):
     810        model=AbstractModel()
     811        model.a = Param()
     812        model.b = Set(initialize=[1,2,3])
     813        model.c = Param(model.b, initialize=2, within=Reals)
     814
     815        instance=model.create()
     816        self.assertRaises(ValueError, value, instance.a)
     817        self.assertRaises(ValueError, instance.a)
     818
    792819    def test_get_set(self):
    793820        model=AbstractModel()
    794         model.a = Param()
     821        model.a = Param(initialize=2)
    795822        model.b = Set(initialize=[1,2,3])
    796823        model.c = Param(model.b, initialize=2, within=Reals)
     
    800827        #except AttributeError:
    801828            #pass
    802         try:
    803             model.a.construct()
    804             self.fail("Can't construct a parameter without data")
    805         except ValueError:
    806             pass
    807         model.a = Param(initialize=2)
    808829        instance=model.create()
    809830        instance.a.value=3
     
    850871        model.e = Param(model.b,model.b,initialize={(1,1):(2,3)}, validate=e_valid)
    851872        instance = model.create()
    852         instance.components.e.check_values()
     873        #instance.components.e.check_values()
    853874        #try:
    854875            #instance.c.value = 'b'
     
    867888        inst = model.create()
    868889       
    869         self.assertAlmostEqual(init_xy[1], inst.CON[None].lower.__float__(), 1e-10)
     890        self.assertAlmostEqual(init_xy[1], inst.CON[None].lower, delta=1e-10)
    870891       
    871892        inst.Q1 = new_xy[0]
    872893        inst.preprocess()
    873         self.assertAlmostEqual(new_xy[1], inst.CON[None].lower.__float__(), tol)
     894        self.assertAlmostEqual(new_xy[1], inst.CON[None].lower, delta=tol)
    874895
    875896    return testMethod
     
    890911        inst = model.create()
    891912       
    892         self.assertAlmostEqual(init_xy[1], inst.CON1[None].lower.__float__(),tol)
    893         self.assertAlmostEqual(init_xy[1], inst.CON2[None].lower.__float__(),tol)
    894         self.assertAlmostEqual(init_xy[1], inst.CON3[None].lower.__float__(),tol)       
     913        self.assertAlmostEqual(init_xy[1], inst.CON1[None].lower, delta=tol)
     914        self.assertAlmostEqual(init_xy[1], inst.CON2[None].lower, delta=tol)
     915        self.assertAlmostEqual(init_xy[1], inst.CON3[None].lower, delta=tol)       
    895916       
    896917        inst.P[1] = new_xy[0]
     
    898919        inst.R[1] = new_xy[0]
    899920        inst.preprocess()
    900         self.assertAlmostEqual(new_xy[1], inst.CON1[None].lower.__float__(),tol)
    901         self.assertAlmostEqual(new_xy[1], inst.CON2[None].lower.__float__(),tol)
    902         self.assertAlmostEqual(new_xy[1], inst.CON3[None].lower.__float__(),tol)
     921        self.assertAlmostEqual(new_xy[1], inst.CON1[None].lower, delta=tol)
     922        self.assertAlmostEqual(new_xy[1], inst.CON2[None].lower, delta=tol)
     923        self.assertAlmostEqual(new_xy[1], inst.CON3[None].lower, delta=tol)
    903924
    904925    return testMethod
     
    935956
    936957           
    937 #class MiscNonIndexedParamBehaviorTests(pyutilib.th.TestCase):
    938 class MiscNonIndexedParamBehaviorTests(object):
     958class MiscNonIndexedParamBehaviorTests(pyutilib.th.TestCase):
    939959
    940960    # Test that non-indexed params are mutable
     
    967987        tmp = f.readlines()
    968988        f.close()
     989        print tmp
    969990        val = float(tmp[1].strip())
    970991        self.assertEquals(model.Q, val)
     
    10411062
    10421063       
    1043 #class MiscIndexedParamBehaviorTests(pyutilib.th.TestCase):
    1044 class MiscIndexedParamBehaviorTests(object):
     1064class MiscIndexedParamBehaviorTests(pyutilib.th.TestCase):
    10451065
    10461066    # Test that indexed params are mutable
  • coopr.pyomo/trunk/examples/pyomo/tutorials/table.out

    r4715 r5803  
    6767        H2 : 3.4
    6868        H3 : 3.5
    69    S :  Size=2  Domain=Any
     69   S :  Size=3  Domain=Any
    7070        A1 : 3.3
    7171        A3 : 3.5
Note: See TracChangeset for help on using the changeset viewer.