def set_as_constraint(self, uncertain_params, **kwargs): """ Function to generate constraints for the EllipsoidalSet uncertainty set. Args: uncertain_params: uncertain parameter objects for writing constraint objects """ inv_covar = np.linalg.inv(self.shape_matrix) if len(uncertain_params) != len(self.center): raise AttributeError("Center of ellipsoid must be same dimensions as vector of uncertain parameters.") # Calculate row vector of differences diff = [] # === Assume VarList uncertain_param_vars for idx, i in enumerate(uncertain_params): if uncertain_params[idx].is_indexed(): for index in uncertain_params[idx]: diff.append(uncertain_params[idx][index] - self.center[idx]) else: diff.append(uncertain_params[idx] - self.center[idx]) # Calculate inner product of difference vector and covar matrix product1 = [sum([x * y for x, y in zip(diff, column(inv_covar, i))]) for i in range(len(inv_covar))] constraint = sum([x * y for x, y in zip(product1, diff)]) conlist = ConstraintList() conlist.construct() conlist.add(constraint <= self.scale) return conlist
def set_as_constraint(self, uncertain_params, **kwargs): """ Function to generate constraints for the FactorModelSet uncertainty set. Args: uncertain_params: uncertain parameter objects for writing constraint objects """ model = kwargs['model'] # === Ensure dimensions if len(uncertain_params) != len(self.origin): raise AttributeError("Dimensions of origin and uncertain_param lists must be equal.") # Make F-dim cassi variable n = list(range(self.number_of_factors)) model.util.cassi = Var(n, initialize=0, bounds=(-1, 1)) conlist = ConstraintList() conlist.construct() disturbances = [sum(self.psi_mat[i][j] * model.util.cassi[j] for j in n) for i in range(len(uncertain_params))] # Make n equality constraints for i in range(len(uncertain_params)): conlist.add(self.origin[i] + disturbances[i] == uncertain_params[i]) conlist.add(sum(model.util.cassi[i] for i in n) <= +self.beta * self.number_of_factors) conlist.add(sum(model.util.cassi[i] for i in n) >= -self.beta * self.number_of_factors) return conlist
def set_as_constraint(self, uncertain_params, **kwargs): """ Function to generate constraints for the AxisAlignedEllipsoid uncertainty set. Args: uncertain_params: uncertain parameter objects for writing constraint objects """ if len(uncertain_params) != len(self.center): raise AttributeError("Center of ellipsoid must be same dimensions as vector of uncertain parameters.") # square and invert half lengths inverse_squared_half_lengths = list(1.0/(a**2) for a in self.half_lengths) # Calculate row vector of differences diff_squared = [] # === Assume VarList uncertain_param_vars for idx, i in enumerate(uncertain_params): if uncertain_params[idx].is_indexed(): for index in uncertain_params[idx]: diff_squared.append((uncertain_params[idx][index] - self.center[idx])**2) else: diff_squared.append((uncertain_params[idx] - self.center[idx])**2) # Calculate inner product of difference vector and variance matrix constraint = sum([x * y for x, y in zip(inverse_squared_half_lengths, diff_squared)]) conlist = ConstraintList() conlist.construct() conlist.add(constraint <= 1) return conlist
def set_as_constraint(self, uncertain_params, **kwargs): """ Function to generate constraints for the PolyhedralSet uncertainty set. Args: uncertain_params: uncertain parameter objects for writing constraint objects """ # === Ensure valid dimensions of lhs and rhs w.r.t uncertain_params if np.asarray(self.coefficients_mat).shape[1] != len(uncertain_params): raise AttributeError("Columns of coefficients_mat matrix " "must equal length of uncertain parameters list.") set_i = list(range(len(self.coefficients_mat))) conlist = ConstraintList() conlist.construct() for i in set_i: constraint = 0 for j in range(len(uncertain_params)): constraint += float(self.coefficients_mat[i][j]) * uncertain_params[j] conlist.add(constraint <= float(self.rhs_vec[i])) return conlist
def set_as_constraint(self, uncertain_params, **kwargs): """ Function to generate constraints for the CardinalitySet uncertainty set. Args: uncertain_params: uncertain parameter objects for writing constraint objects """ # === Ensure dimensions if len(uncertain_params) != len(self.origin): raise AttributeError("Dimensions of origin and uncertain_param lists must be equal.") model = kwargs['model'] set_i = list(range(len(uncertain_params))) model.util.cassi = Var(set_i, initialize=0, bounds=(0, 1)) # Make n equality constraints conlist = ConstraintList() conlist.construct() for i in set_i: conlist.add(self.origin[i] + self.positive_deviation[i] * model.util.cassi[i] == uncertain_params[i]) conlist.add(sum(model.util.cassi[i] for i in set_i) <= self.gamma) return conlist
def set_as_constraint(self, uncertain_params, **kwargs): """ Function to generate constraints for the IntersectedSet uncertainty set. Args: uncertain_params: list of uncertain param objects participating in the sets to be intersected """ try: nlp_solver = kwargs["config"].global_solver except: raise AttributeError("set_as_constraint for SetIntersection requires access to an NLP solver via" "the PyROS Solver config.") is_empty_intersection = self.is_empty_intersection(uncertain_params=uncertain_params, nlp_solver=nlp_solver) def _intersect(Q1, Q2): return self.intersect(Q1, Q2) if not is_empty_intersection: Qint = functools.reduce(_intersect, self.all_sets) if Qint.type == "discrete": return Qint.set_as_constraint(uncertain_params=uncertain_params) else: conlist = ConstraintList() conlist.construct() for set in Qint.all_sets: for con in list(set.set_as_constraint(uncertain_params=uncertain_params).values()): conlist.add(con.expr) return conlist else: raise AttributeError("Set intersection is empty, cannot proceed with PyROS robust optimization.")
def set_as_constraint(self, uncertain_params, **kwargs): """ Function to generate constraints for the BoxSet uncertainty set. Args: uncertain_params: uncertain parameter objects for writing constraint objects """ conlist = ConstraintList() conlist.construct() set_i = list(range(len(uncertain_params))) for i in set_i: conlist.add(uncertain_params[i] >= self.bounds[i][0]) conlist.add(uncertain_params[i] <= self.bounds[i][1]) return conlist
def set_as_constraint(self, uncertain_params, **kwargs): """ Function to generate constraints for the EllipsoidalSet uncertainty set. Args: uncertain_params: uncertain parameter objects for writing constraint objects """ # === Ensure point is of correct dimensionality as the uncertain parameters dim = len(uncertain_params) if any(len(d) != dim for d in self.scenarios): raise AttributeError("All scenarios must have same dimensions as uncertain parameters.") conlist = ConstraintList() conlist.construct() for n in list(range(len(self.scenarios))): for i in list(range(len(uncertain_params))): conlist.add(uncertain_params[i] == self.scenarios[n][i]) conlist.deactivate() return conlist
def apply(self, **kwds): if __debug__ and logger.isEnabledFor(logging.DEBUG): #pragma:nocover logger.debug("Calling ConnectorExpander") instance = kwds['instance'] blockList = list(instance.block_data_objects(active=True)) noConnectors = True for b in blockList: if b.component_map(Connector): noConnectors = False break if noConnectors: 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. # #options = kwds['options'] #model = kwds['model'] # In general, blocks should be relatively self-contained, so we # should build the connectors from the "bottom up": blockList.reverse() # Expand each constraint involving a connector for block in blockList: if __debug__ and logger.isEnabledFor(logging.DEBUG): #pragma:nocover logger.debug(" block: " + block.cname()) CCC = {} for name, constraint in itertools.chain\ ( iteritems(block.component_map(Constraint)), iteritems(block.component_map(ConstraintList)) ): cList = [] CCC[name+'.expanded'] = cList for idx, c in iteritems(constraint._data): if __debug__ and logger.isEnabledFor(logging.DEBUG): #pragma:nocover logger.debug(" (looking at constraint %s[%s])", name, idx) connectors = [] self._gather_connectors(c.body, connectors) if len(connectors) == 0: continue if __debug__ and logger.isEnabledFor(logging.DEBUG): #pragma:nocover logger.debug(" (found connectors in constraint)") # Validate that all connectors match errors, ref, skip = self._validate_connectors(connectors) if errors: logger.error( ( "Connector mismatch: errors detected when " "constructing constraint %s\n " % (name + (idx and '[%s]' % idx or '')) ) + '\n '.join(reversed(errors)) ) raise ValueError( "Connector mismatch in constraint %s" % \ name + (idx and '[%s]' % idx or '')) if __debug__ and logger.isEnabledFor(logging.DEBUG): #pragma:nocover logger.debug(" (connectors valid)") # Fill in any empty connectors for conn in connectors: if conn.vars: continue for var in ref.vars: if var in skip: continue v = Var() block.add_component(conn.cname() + '.auto.' + var, v) conn.vars[var] = v v.construct() # OK - expand this constraint self._expand_constraint(block, name, idx, c, ref, skip, cList) # Now deactivate the original constraint c.deactivate() for name, exprs in iteritems(CCC): cList = ConstraintList() block.add_component( name, cList ) cList.construct() for expr in exprs: cList.add(expr) # Now, go back and implement VarList aggregators for block in blockList: for conn in itervalues(block.component_map(Connector)): for var, aggregator in iteritems(conn.aggregators): c = Constraint(expr=aggregator(block, var)) block.add_component( conn.cname() + '.' + var.cname() + '.aggregate', c) c.construct()
def apply(self, **kwds): if __debug__ and logger.isEnabledFor(logging.DEBUG): #pragma:nocover logger.debug("Calling ConnectorExpander") instance = kwds['instance'] blockList = list(instance.block_data_objects(active=True)) noConnectors = True for b in blockList: if b.component_map(Connector): noConnectors = False break if noConnectors: 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. # #options = kwds['options'] #model = kwds['model'] # In general, blocks should be relatively self-contained, so we # should build the connectors from the "bottom up": blockList.reverse() # Expand each constraint involving a connector for block in blockList: if __debug__ and logger.isEnabledFor(logging.DEBUG): #pragma:nocover logger.debug(" block: " + block.name) CCC = {} for name, constraint in itertools.chain\ ( iteritems(block.component_map(Constraint)), iteritems(block.component_map(ConstraintList)) ): cList = [] CCC[name+'.expanded'] = cList for idx, c in iteritems(constraint._data): if __debug__ and logger.isEnabledFor(logging.DEBUG): #pragma:nocover logger.debug(" (looking at constraint %s[%s])", name, idx) connectors = [] self._gather_connectors(c.body, connectors) if len(connectors) == 0: continue if __debug__ and logger.isEnabledFor(logging.DEBUG): #pragma:nocover logger.debug(" (found connectors in constraint)") # Validate that all connectors match errors, ref, skip = self._validate_connectors(connectors) if errors: logger.error( ( "Connector mismatch: errors detected when " "constructing constraint %s\n " % (name + (idx and '[%s]' % idx or '')) ) + '\n '.join(reversed(errors)) ) raise ValueError( "Connector mismatch in constraint %s" % \ name + (idx and '[%s]' % idx or '')) if __debug__ and logger.isEnabledFor(logging.DEBUG): #pragma:nocover logger.debug(" (connectors valid)") # Fill in any empty connectors for conn in connectors: if conn.vars: continue for var in ref.vars: if var in skip: continue v = Var() block.add_component(conn.local_name + '.auto.' + var, v) conn.vars[var] = v v.construct() # OK - expand this constraint self._expand_constraint(block, name, idx, c, ref, skip, cList) # Now deactivate the original constraint c.deactivate() for name, exprs in iteritems(CCC): cList = ConstraintList() block.add_component( name, cList ) cList.construct() for expr in exprs: cList.add(expr) # Now, go back and implement VarList aggregators for block in blockList: for conn in itervalues(block.component_map(Connector)): for var, aggregator in iteritems(conn.aggregators): c = Constraint(expr=aggregator(block, var)) block.add_component( conn.local_name + '.' + var.local_name + '.aggregate', c) c.construct()