Changeset 2994


Ignore:
Timestamp:
Sep 4, 2010 6:07:46 PM (9 years ago)
Author:
jwatson
Message:

Improving the efficiency of the NumericValue? constructor - it is called a huge number of times in the typical run, with the dictionary/keyword processing showing up in run-time profile.

File:
1 edited

Legend:

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

    r2650 r2994  
    3535    """
    3636    A utility function that returns the value of an expression
    37     """
     37        # NOTE: This is a terminal class, so no need to pop the keyword/argument
     38        #       I would actually argue that we just need to make the inputs named
     39        #       keywords, to by-pass all of this overhead.    """
    3840    if obj is None:
    3941        return None
     
    7476
    7577    def __init__(self, **kwargs):
    76         self.name   = str(kwargs.pop('name', 'unknown'))
    77         self.domain = kwargs.pop('domain', None )
    78         self.domain = kwargs.pop('within', self.domain )
    79         value       = kwargs.pop('value', None )
    80 
    81         if ( value and pyutilib.math.is_nan(value) ):
     78
     79        self.name = 'unknown'
     80        self.domain = None
     81       
     82        # a value of None indicates unassigned; None is also
     83        # (treated as) a member of all domains.
     84        value = None # validated prior to assigning to self.value
     85
     86        # because this is a terminal class (not passing keyword arguments
     87        # further to the 'object' base class), there is a good reason in terms
     88        # of performance - given how often NumericValue objects are created -
     89        # to avoid the usual technique of invoking kwargs.pop(name,default).
     90        # manipulating the keyword dictionary takes too much time.
     91        for keyword, keywordvalue in kwargs.items():
     92           if keyword is 'value':
     93              value = keywordvalue           
     94           elif keyword is 'within':
     95              self.domain = keywordvalue
     96           elif keyword is 'domain':
     97              self.domain = keywordvalue             
     98           elif keyword is 'name':
     99              self.name = keywordvalue             
     100           # this class can't deal with any other keywords - in principle,
     101           # we could throw an exception for debug/diagnostic purposes.
     102
     103        if (value and pyutilib.math.is_nan(value)):
    82104            value = pyutilib.math.nan
    83105
    84         self.set_value(value)
    85         self.model=None
    86 
     106        # a numeric value is only constrained by the domain,
     107        # if specified. avoid invoking set_value() here to
     108        # accelerate object construction, which takes
     109        # significant time due to the typical number of
     110        # occurrences. similarly, we are avoiding the
     111        # invocation of _valid_value.
     112        if (value is not None) and (self.domain is not None) and (value not in self.domain):
     113           raise ValueError, "Numeric value `"+str(value)+"` is not in domain "+str(self.domain)           
     114
     115        self.value = value
     116       
     117        self.model = None
    87118
    88119    def is_constant(self):
Note: See TracChangeset for help on using the changeset viewer.