예제 #1
0
def clone_without_expression_components(expr, substitute):
    ans = [EXPR.clone_expression(expr, substitute=substitute)]
    _stack = [ (ans, 0, 1) ]
    while _stack:
        _argList, _idx, _len = _stack.pop()
        while _idx < _len:
            _sub = _argList[_idx]
            _idx += 1
            if type(_sub) in native_types:
                pass
            elif _sub.is_expression():
                _stack.append(( _argList, _idx, _len ))
                if not isinstance(_sub, EXPR._ExpressionBase):
                    _argList[_idx-1] = EXPR.clone_expression(
                        _sub._args[0], substitute=substitute )
                elif type(_sub) is coopr3._ProductExpression:
                    if _sub._denominator:
                        _stack.append(
                            (_sub._denominator, 0, len(_sub._denominator)) )
                    _argList = _sub._numerator
                else:
                    _argList = _sub._args
                    # HACK: As we may have to replace arguments, if the
                    # _args is a tuple, then we will convert it to a
                    # list.
                    if type(_argList) is tuple:
                        _argList = _sub._args = list(_argList)
                _idx = 0
                _len = len(_argList)
    return ans[0]
예제 #2
0
파일: symbolic.py 프로젝트: qtothec/pyomo
def differentiate(expr, wrt=None, wrt_list=None):
    if not _sympy_available:
        raise RuntimeError(
            "The sympy module is not available.  "
            "Cannot perform automatic symbolic differentiation.")

    if not (( wrt is None ) ^ ( wrt_list is None )):
        raise ValueError(
            "differentiate(): Must specify exactly one of wrt and wrt_list")
    if wrt is not None:
        wrt_list = [ wrt ]
    else:
        # Copy the list because we will normalize things in place below
        wrt_list = list(wrt_list)

    pyomo_vars = list(EXPR.identify_variables(expr))
    sympy_vars = [sympy.var('x%s'% i) for i in range(len(pyomo_vars))]
    sympy2pyomo = dict( zip(sympy_vars, pyomo_vars) )
    pyomo2sympy = dict( (id(pyomo_vars[i]), sympy_vars[i])
                         for i in range(len(pyomo_vars)) )

    ans = []
    for i, target in enumerate(wrt_list):
        if target.__class__ is not tuple:
            wrt_list[i] = target = (target,)
        mismatch_target = False
        for var in target:
            if id(var) not in pyomo2sympy:
                mismatch_target = True
                break
        wrt_list[i] = tuple( pyomo2sympy.get(id(var),None) for var in target )
        ans.append(0 if mismatch_target else None)

    # If there is nothing to do, do nothing
    if all(i is not None for i in ans):
        return ans if wrt is None else ans[0]

    tmp_expr = EXPR.clone_expression( expr, substitute=pyomo2sympy )
    tmp_expr = _map_intrinsic_functions(tmp_expr, sympy2pyomo)
    tmp_expr = str(tmp_expr)

    sympy_expr = sympy.sympify(
        tmp_expr, locals=dict((str(x), x) for x in sympy_vars) )

    for i, target in enumerate(wrt_list):
        if ans[i] is None:
            sympy_ans = sympy_expr.diff(*target)
            ans[i] = _map_sympy2pyomo(sympy_ans, sympy2pyomo)

    return ans if wrt is None else ans[0]
예제 #3
0
파일: symbolic.py 프로젝트: jay1yun/pyomo
def differentiate(expr, wrt=None, wrt_list=None):
    if not _sympy_available:
        raise RuntimeError(
            "The sympy module is not available.  "
            "Cannot perform automatic symbolic differentiation.")

    if not ((wrt is None) ^ (wrt_list is None)):
        raise ValueError(
            "differentiate(): Must specify exactly one of wrt and wrt_list")
    if wrt is not None:
        wrt_list = [wrt]
    else:
        # Copy the list because we will normalize things in place below
        wrt_list = list(wrt_list)

    pyomo_vars = list(EXPR.identify_variables(expr))
    sympy_vars = [sympy.var('x%s' % i) for i in range(len(pyomo_vars))]
    sympy2pyomo = dict(zip(sympy_vars, pyomo_vars))
    pyomo2sympy = dict(
        (id(pyomo_vars[i]), sympy_vars[i]) for i in range(len(pyomo_vars)))

    ans = []
    for i, target in enumerate(wrt_list):
        if target.__class__ is not tuple:
            wrt_list[i] = target = (target, )
        mismatch_target = False
        for var in target:
            if id(var) not in pyomo2sympy:
                mismatch_target = True
                break
        wrt_list[i] = tuple(pyomo2sympy.get(id(var), None) for var in target)
        ans.append(0 if mismatch_target else None)

    # If there is nothing to do, do nothing
    if all(i is not None for i in ans):
        return ans if wrt is None else ans[0]

    tmp_expr = EXPR.clone_expression(expr, substitute=pyomo2sympy)
    tmp_expr = _map_intrinsic_functions(tmp_expr, sympy2pyomo)
    tmp_expr = str(tmp_expr)

    sympy_expr = sympy.sympify(tmp_expr,
                               locals=dict((str(x), x) for x in sympy_vars))

    for i, target in enumerate(wrt_list):
        if ans[i] is None:
            sympy_ans = sympy_expr.diff(*target)
            ans[i] = _map_sympy2pyomo(sympy_ans, sympy2pyomo)

    return ans if wrt is None else ans[0]
예제 #4
0
    def _apply_to(self, instance, **kwds):
        if __debug__ and logger.isEnabledFor(logging.DEBUG):   #pragma:nocover
            logger.debug("Calling ConnectorExpander")

        connectorsFound = False
        for c in instance.component_data_objects(Connector):
            connectorsFound = True
            break
        if not connectorsFound:
            return

        if __debug__ and logger.isEnabledFor(logging.DEBUG):   #pragma:nocover
            logger.debug("   Connectors found!")

        #
        # At this point, there are connectors in the model, so we must
        # look for constraints that involve connectors and expand them.
        #
        connector_types = set([SimpleConnector, _ConnectorData])
        constraint_list = []
        connector_list = []
        matched_connectors = {}
        found = dict()
        for constraint in instance.component_data_objects(Constraint):
            for c in expr.identify_variables(
                    constraint.body, include_potentially_variable=True):
                if c.__class__ in connector_types:
                    found[id(c)] = c
            if not found:
                continue

            # Note that it is important to copy the set of found
            # connectors, since the matching routine below will
            # manipulate sets in place.
            found_this_constraint = dict(found)
            constraint_list.append( (constraint, found_this_constraint) )

            # Find all the connectors that are used in the constraint,
            # so we know which connectors to validate against each
            # other.  Note that the validation must be transitive (that
            # is, if con1 has a & b and con2 has b & c, then a,b, and c
            # must all validate against each other.
            for cId, c in iteritems(found_this_constraint):
                if cId in matched_connectors:
                    oldSet = matched_connectors[cId]
                    found.update( oldSet )
                    for _cId in oldSet:
                        matched_connectors[_cId] = found
                else:
                    connector_list.append(c)
                matched_connectors[cId] = found

            # Reset found back to empty (this is more efficient as the
            # bulk of the constraints in the model will not have
            # connectors - so if we did this at the top of the loop, we
            # would spend a lot of time clearing empty sets
            found = {}

        # Validate all connector sets and expand the empty ones
        known_conn_sets = {}
        for connector in connector_list:
            conn_set = matched_connectors[id(connector)]
            if id(conn_set) in known_conn_sets:
                continue
            known_conn_sets[id(conn_set)] \
                = self._validate_and_expand_connector_set(conn_set)

        # Expand each constraint
        for constraint, conn_set in constraint_list:
            cList = ConstraintList()
            constraint.parent_block().add_component(
                '%s.expanded' % ( constraint.local_name, ), cList )
            connId = next(iterkeys(conn_set))
            ref = known_conn_sets[id(matched_connectors[connId])]
            for k,v in sorted(iteritems(ref)):
                if v[1] >= 0:
                    _iter = v[0]
                else:
                    _iter = (v[0],)
                for idx in _iter:
                    substitution = {}
                    for c in itervalues(conn_set):
                        if v[1] >= 0:
                            new_v = c.vars[k][idx]
                        elif k in c.aggregators:
                            new_v = c.vars[k].add()
                        else:
                            new_v = c.vars[k]
                        substitution[id(c)] = new_v
                    cList.add((
                        constraint.lower,
                        expr.clone_expression( constraint.body, substitution ),
                        constraint.upper ))
            constraint.deactivate()

        # Now, go back and implement VarList aggregators
        for conn in connector_list:
            block = conn.parent_block()
            for var, aggregator in iteritems(conn.aggregators):
                c = Constraint(expr=aggregator(block, conn.vars[var]))
                block.add_component(
                    '%s.%s.aggregate' % (conn.local_name, var), c )
예제 #5
0
    def _apply_to(self, instance, **kwds):
        if __debug__ and logger.isEnabledFor(logging.DEBUG):  #pragma:nocover
            logger.debug("Calling ConnectorExpander")

        connectorsFound = False
        for c in instance.component_data_objects(Connector):
            connectorsFound = True
            break
        if not connectorsFound:
            return

        if __debug__ and logger.isEnabledFor(logging.DEBUG):  #pragma:nocover
            logger.debug("   Connectors found!")

        #
        # At this point, there are connectors in the model, so we must
        # look for constraints that involve connectors and expand them.
        #
        connector_types = set([SimpleConnector, _ConnectorData])
        constraint_list = []
        connector_list = []
        matched_connectors = {}
        found = dict()
        for constraint in instance.component_data_objects(Constraint):
            for c in expr.identify_variables(
                    constraint.body, include_potentially_variable=True):
                if c.__class__ in connector_types:
                    found[id(c)] = c
            if not found:
                continue

            # Note that it is important to copy the set of found
            # connectors, since the matching routine below will
            # manipulate sets in place.
            found_this_constraint = dict(found)
            constraint_list.append((constraint, found_this_constraint))

            # Find all the connectors that are used in the constraint,
            # so we know which connectors to validate against each
            # other.  Note that the validation must be transitive (that
            # is, if con1 has a & b and con2 has b & c, then a,b, and c
            # must all validate against each other.
            for cId, c in iteritems(found_this_constraint):
                if cId in matched_connectors:
                    oldSet = matched_connectors[cId]
                    found.update(oldSet)
                    for _cId in oldSet:
                        matched_connectors[_cId] = found
                else:
                    connector_list.append(c)
                matched_connectors[cId] = found

            # Reset found back to empty (this is more efficient as the
            # bulk of the constraints in the model will not have
            # connectors - so if we did this at the top of the loop, we
            # would spend a lot of time clearing empty sets
            found = {}

        # Validate all connector sets and expand the empty ones
        known_conn_sets = {}
        for connector in connector_list:
            conn_set = matched_connectors[id(connector)]
            if id(conn_set) in known_conn_sets:
                continue
            known_conn_sets[id(conn_set)] \
                = self._validate_and_expand_connector_set(conn_set)

        # Expand each constraint
        for constraint, conn_set in constraint_list:
            cList = ConstraintList()
            constraint.parent_block().add_component(
                '%s.expanded' % (constraint.local_name, ), cList)
            connId = next(iterkeys(conn_set))
            ref = known_conn_sets[id(matched_connectors[connId])]
            for k, v in sorted(iteritems(ref)):
                if v[1] >= 0:
                    _iter = v[0]
                else:
                    _iter = (v[0], )
                for idx in _iter:
                    substitution = {}
                    for c in itervalues(conn_set):
                        if v[1] >= 0:
                            new_v = c.vars[k][idx]
                        elif k in c.aggregators:
                            new_v = c.vars[k].add()
                        else:
                            new_v = c.vars[k]
                        substitution[id(c)] = new_v
                    cList.add((constraint.lower,
                               expr.clone_expression(constraint.body,
                                                     substitution),
                               constraint.upper))
            constraint.deactivate()

        # Now, go back and implement VarList aggregators
        for conn in connector_list:
            block = conn.parent_block()
            for var, aggregator in iteritems(conn.aggregators):
                c = Constraint(expr=aggregator(block, conn.vars[var]))
                block.add_component('%s.%s.aggregate' % (conn.local_name, var),
                                    c)
예제 #6
0
 def to_standard_form(self):
     #
     # Add auxilliary variables and constraints that ensure
     # a monotone transformation of general complementary constraints to
     # the form:
     #       l1 <= v1 <= u1   OR   l2 <= v2 <= u2
     #
     # Note that this transformation creates more variables and constraints
     # than are strictly necessary.  However, we don't have a complete list of
     # the variables used in a model's complementarity conditions when adding
     # a single condition, so we add additional variables.
     #
     # This has the form:
     #
     #  e:   l1 <= expression <= l2
     #  v:   l3 <= var <= l4
     #
     # where exactly two of l1, l2, l3 and l4 are finite, and with the
     # equality constraint:
     #
     #  c:   v == expression
     #
     _e1 = self._canonical_expression(EXPR.clone_expression(self._args[0]))
     _e2 = self._canonical_expression(EXPR.clone_expression(self._args[1]))
     if len(_e1) == 2:
         # Ignore _e2; _e1 is an equality constraint
         self.c = Constraint(expr=_e1)
         return
     if len(_e2) == 2:
         # Ignore _e1; _e2 is an equality constraint
         self.c = Constraint(expr=_e2)
         return
     #
     if (_e1[0] is None) + (_e1[2] is None) + (_e2[0] is None) + (
             _e2[2] is None) != 2:
         raise RuntimeError(
             "Complementarity condition %s must have exactly two finite bounds"
             % self.name)
     #
     if _e1[0] is None and _e1[2] is None:
         # Only e2 will be an unconstrained expression
         _e1, _e2 = _e2, _e1
     #
     if _e2[0] is None and _e2[2] is None:
         self.c = Constraint(expr=(None, _e2[1], None))
         self.c._type = 3
     elif _e2[2] is None:
         self.c = Constraint(expr=_e2[0] <= _e2[1])
         self.c._type = 1
     elif _e2[0] is None:
         self.c = Constraint(expr=-_e2[2] <= -_e2[1])
         self.c._type = 1
     #
     if not _e1[0] is None and not _e1[2] is None:
         if not _e1[0].is_constant():
             raise RuntimeError(
                 "Cannot express a complementarity problem of the form L < v < U _|_ g(x) where L is not a constant value"
             )
         if not _e1[2].is_constant():
             raise RuntimeError(
                 "Cannot express a complementarity problem of the form L < v < U _|_ g(x) where U is not a constant value"
             )
         self.v = Var(bounds=(_e1[0], _e1[2]))
         self.ve = Constraint(expr=self.v == _e1[1])
     elif _e1[2] is None:
         self.v = Var(bounds=(0, None))
         self.ve = Constraint(expr=self.v == _e1[1] - _e1[0])
     else:
         # _e1[0] is None:
         self.v = Var(bounds=(0, None))
         self.ve = Constraint(expr=self.v == _e1[2] - _e1[1])
예제 #7
0
 def to_standard_form(self):
     #
     # Add auxilliary variables and constraints that ensure
     # a monotone transformation of general complementary constraints to
     # the form:
     #       l1 <= v1 <= u1   OR   l2 <= v2 <= u2
     #
     # Note that this transformation creates more variables and constraints
     # than are strictly necessary.  However, we don't have a complete list of
     # the variables used in a model's complementarity conditions when adding
     # a single condition, so we add additional variables.
     #
     # This has the form:
     #
     #  e:   l1 <= expression <= l2
     #  v:   l3 <= var <= l4
     #
     # where exactly two of l1, l2, l3 and l4 are finite, and with the
     # equality constraint:
     #
     #  c:   v == expression
     #
     _e1 = self._canonical_expression(EXPR.clone_expression(self._args[0]))
     _e2 = self._canonical_expression(EXPR.clone_expression(self._args[1]))
     if len(_e1) == 2:
         # Ignore _e2; _e1 is an equality constraint
         self.c = Constraint(expr=_e1)
         return
     if len(_e2) == 2:
         # Ignore _e1; _e2 is an equality constraint
         self.c = Constraint(expr=_e2)
         return
     #
     if (_e1[0] is None) + (_e1[2] is None) + (_e2[0] is None) + (_e2[2] is None) != 2:
         raise RuntimeError("Complementarity condition %s must have exactly two finite bounds" % self.name)
     #
     if _e1[0] is None and _e1[2] is None:
         # Only e2 will be an unconstrained expression
         _e1, _e2 = _e2, _e1
     #
     if _e2[0] is None and _e2[2] is None:
         self.c = Constraint(expr=(None, _e2[1], None))
         self.c._type = 3
     elif _e2[2] is None:
         self.c = Constraint(expr=_e2[0] <= _e2[1])
         self.c._type = 1
     elif _e2[0] is None:
         self.c = Constraint(expr=- _e2[2] <= - _e2[1])
         self.c._type = 1
     #
     if not _e1[0] is None and not _e1[2] is None:
         if not _e1[0].is_constant():
             raise RuntimeError("Cannot express a complementarity problem of the form L < v < U _|_ g(x) where L is not a constant value")
         if not _e1[2].is_constant():
             raise RuntimeError("Cannot express a complementarity problem of the form L < v < U _|_ g(x) where U is not a constant value")
         self.v = Var(bounds=(_e1[0], _e1[2]))
         self.ve = Constraint(expr=self.v == _e1[1])
     elif _e1[2] is None:
         self.v = Var(bounds=(0, None))
         self.ve = Constraint(expr=self.v == _e1[1] - _e1[0])
     else:
         # _e1[0] is None:
         self.v = Var(bounds=(0, None))
         self.ve = Constraint(expr=self.v == _e1[2] - _e1[1])