Esempio n. 1
0
def get_tracking_cost_expression(
    variables,
    time,
    setpoint_data,
    weight_data=None,
    dereference=True,
):
    """
    Arguments
    ---------
    variables: list
        List of time-indexed variables to include in the tracking cost
        expression.
    setpoint_data: dict
        Maps variable names to setpoint values
    weight_data: dict
        Maps variable names to tracking cost weights

    Returns
    -------
    Pyomo expression. Sum of weighted squared difference between
    variables and setpoint values.

    """
    # TODO: Should setpoints be mutable params? Indexed by variable names?
    # This is tempting as it makes changing the setpoint easy.
    variable_names = [
        # NOTE: passing strings through ComponentUID.
        # This may break things that rely on a particular form of the string.
        # I believe this approach is more consistent, however.
        # This is a temporary measure before I switch to using CUIDs as keys.
        str(ComponentUID(str(get_time_indexed_cuid(var)))) for var in variables
    ]
    #    str(ComponentUID(var))
    #    if not var.is_reference() or not dereference
    #    else str(ComponentUID(var.referent))
    #    for var in variables
    #]
    if weight_data is None:
        weight_data = {name: 1.0 for name in variable_names}

    def tracking_rule(m, t):
        return sum(weight_data[name] * (var[t] - setpoint_data[name])**2
                   for name, var in zip(variable_names, variables))

    # Note that I don't enforce that variables are actually indexed
    # by time. "time" could just be a list of sample points...
    tracking_expr = Expression(time, rule=tracking_rule)
    return tracking_expr
Esempio n. 2
0
    def __init__(self, *args, **kwds):

        if "wrt" in kwds and "withrespectto" in kwds:
            raise TypeError(
                "Cannot specify both 'wrt' and 'withrespectto keywords")

        wrt = kwds.pop('wrt', None)
        wrt = kwds.pop('withrespectto', wrt)

        if wrt is None:
            # Check to be sure Integral is indexed by single
            # ContinuousSet and take Integral with respect to that
            # ContinuousSet
            if len(args) != 1:
                raise ValueError(
                    "Integral indexed by multiple ContinuousSets. "
                    "The desired ContinuousSet must be specified using the "
                    "keyword argument 'wrt'")
            wrt = args[0]

        if type(wrt) is not ContinuousSet:
            raise ValueError(
                "Cannot take the integral with respect to '%s'. Must take an "
                "integral with respect to a ContinuousSet" % wrt)
        self._wrt = wrt

        loc = None
        for i, s in enumerate(args):
            if s is wrt:
                loc = i

        # Check that the wrt ContinuousSet is in the argument list
        if loc is None:
            raise ValueError(
                "The ContinuousSet '%s' was not found in the indexing sets "
                "of the Integral" % wrt.name)
        self.loc = loc

        # Remove the index that the integral is being expanded over
        arg = args[0:loc] + args[loc + 1:]

        # Check that if bounds are given
        bounds = kwds.pop('bounds', None)
        if bounds is not None:
            raise DAE_Error(
                "Setting bounds on integrals has not yet been implemented. "
                "Integrals may only be taken over an entire ContinuousSet")

        # Create integral expression and pass to the expression initialization
        intexp = kwds.pop('expr', None)
        intexp = kwds.pop('rule', intexp)
        if intexp is None:
            raise ValueError(
                "Must specify an integral expression")

        def _trap_rule(m, *a):
            ds = sorted(m.find_component(wrt.local_name))
            return sum(0.5 * (ds[i + 1] - ds[i]) *
                       (intexp(m, * (a[0:loc] + (ds[i + 1],) + a[loc:])) +
                        intexp(m, * (a[0:loc] + (ds[i],) + a[loc:])))
                       for i in range(len(ds) - 1))

        kwds['rule'] = _trap_rule    
        kwds.setdefault('ctype', Integral)
        Expression.__init__(self, *arg, **kwds)
Esempio n. 3
0
    def __init__(self, *args, **kwds):

        if "wrt" in kwds and "withrespectto" in kwds:
            raise TypeError(
                "Cannot specify both 'wrt' and 'withrespectto keywords "
                "in a DerivativeVar")

        wrt = kwds.pop('wrt',None)
        wrt = kwds.pop('withrespectto',wrt)

        if wrt == None:
            # Check to be sure Integral is indexed by single
            # ContinuousSet and take Integral with respect to that
            # ContinuousSet
            if len(args) != 1:
                raise ValueError(
                    "The Integral %s is indexed by multiple ContinuousSets. The desired "
                    "ContinuousSet must be specified using the keyword argument 'wrt'" % (self.name))
            wrt = args[0]

        if type(wrt) is not ContinuousSet:
            raise ValueError(
                "Cannot take the integral with respect to '%s'. Must take an integral "\
                "with respect to a ContinuousSet" %(wrt))
        self._wrt = wrt

        loc = None
        for i,s in enumerate(args):
            if s is wrt:
                loc = i

        # Check that the wrt ContinuousSet is in the argument list
        if loc is None:
            raise ValueError(
                "The ContinuousSet '%s' was not found in the indexing sets of the "
                "Integral '%s'" %(wrt.name,self.name))
        self.loc = loc

        # Remove the index that the integral is being expanded over
        arg = args[0:loc]+args[loc+1:]

        # Check that if bounds are given
        bounds = kwds.pop('bounds',None)
        if bounds is not None:
            raise DAE_Error(
                "Setting bounds on integrals has not yet been implemented. Integrals may only be "\
                "taken over an entire ContinuousSet")

        # Create integral expression and pass to the expression initialization
        intexp = kwds.pop('expr', None)
        intexp = kwds.pop('rule', intexp)
        if intexp is None:
            raise ValueError(
                "Must specify an integral expression for Integral '%s'" %(self))

        def _trap_rule(m,*a):
            ds = sorted(m.find_component(wrt.local_name))
            return sum(0.5*(ds[i+1]-ds[i])*
                      (intexp(m,*(a[0:loc]+(ds[i+1],)+a[loc:]))+intexp(m,*(a[0:loc]+(ds[i],)+a[loc:])))
                      for i in range(len(ds)-1))

        kwds['rule'] = _trap_rule    
        kwds.setdefault('ctype', Integral)
        Expression.__init__(self,*arg,**kwds)