def point_in_set(self, point): """ Calculates if supplied ``point`` is contained in the uncertainty set. Returns True or False. Args: point: the point being checked for membership in the set """ inv_psi = np.linalg.pinv(self.psi_mat) diff = np.asarray(list(point[i] - self.origin[i] for i in range(len(point)))) cassis = np.dot(inv_psi, np.transpose(diff)) if abs(sum(cassi for cassi in cassis)) <= self.beta * self.number_of_factors and \ all(cassi >= -1 and cassi <= 1 for cassi in cassis): return True else: return False
def test_create_objective_from_numpy(self): # Test issue #87 model = ConcreteModel() nsample = 3 nvariables = 2 X0 = np.array(range(nsample)).reshape([nsample, 1]) model.X = 1 + np.array(range(nsample * nvariables)).reshape( (nsample, nvariables)) X = np.concatenate([X0, model.X], axis=1) model.I = RangeSet(1, nsample) model.J = RangeSet(1, nvariables) error = np.ones((nsample, 1)) beta = np.ones((nvariables + 1, 1)) model.Y = np.dot(X, beta) + error model.beta = Var(model.J) model.beta0 = Var() def obj_fun(model): return sum( abs(model.Y[i - 1] - (model.beta0 + sum(model.X[i - 1, j - 1] * model.beta[j] for j in model.J))) for i in model.I) model.OBJ = Objective(rule=obj_fun) def obj_fun_quad(model): return sum( (model.Y[i - 1] - (model.beta0 + sum(model.X[i - 1, j - 1] * model.beta[j] for j in model.J)))**2 for i in model.I) model.OBJ_QUAD = Objective(rule=obj_fun_quad) self.assertEqual( str(model.OBJ.expr), "abs(4.0 - (beta[1] + 2*beta[2] + beta0)) + " "abs(9.0 - (3*beta[1] + 4*beta[2] + beta0)) + " "abs(14.0 - (5*beta[1] + 6*beta[2] + beta0))") self.assertEqual(model.OBJ.expr.polynomial_degree(), None) self.assertEqual(model.OBJ_QUAD.expr.polynomial_degree(), 2)
def sear(depth, prevY): # This is a recursive function for generating tear sets. # It selects one edge from a cycle, then calls itself # to select an edge from the next cycle. It is a branch # and bound search tree to find best tear sets. # The function returns when all cycles are torn, which # may be before an edge was selected from each cycle if # cycles contain common edges. for i in range(len(cycleEdges[depth])): # Loop through all the edges in cycle with index depth y = list(prevY) # get list of already selected tear stream y[cycleEdges[depth][i]] = 1 # calculate number of times each cycle is torn Ay = numpy.dot(A, y) maxAy = max(Ay) sumY = sum(y) if maxAy > upperBound[0]: # breaking a cycle too many times, branch is no good continue elif maxAy == upperBound[0] and sumY > upperBound[1]: # too many tears, branch is no good continue # Call self at next depth where a cycle is not broken if min(Ay) > 0: if maxAy < upperBound[0]: upperBound[0] = maxAy # most important factor upperBound[1] = sumY # second most important elif sumY < upperBound[1]: upperBound[1] = sumY # record solution ySet.append([list(y), maxAy, sumY]) else: for j in range(depth + 1, nr): if Ay[j] == 0: sear(j, y)
def select_tear_heuristic(self, G): """ This finds optimal sets of tear edges based on two criteria. The primary objective is to minimize the maximum number of times any cycle is broken. The seconday criteria is to minimize the number of tears. This function uses a branch and bound type approach. Returns ------- tsets List of lists of tear sets. All the tear sets returned are equally good. There are often a very large number of equally good tear sets. upperbound_loop The max number of times any single loop is torn upperbound_total The total number of loops Improvemnts for the future I think I can imporve the efficency of this, but it is good enough for now. Here are some ideas for improvement: 1. Reduce the number of redundant solutions. It is possible to find tears sets [1,2] and [2,1]. I eliminate redundent solutions from the results, but they can occur and it reduces efficency. 2. Look at strongly connected components instead of whole graph. This would cut back on the size of graph we are looking at. The flowsheets are rarely one strongly conneted component. 3. When you add an edge to a tear set you could reduce the size of the problem in the branch by only looking at strongly connected components with that edge removed. 4. This returns all equally good optimal tear sets. That may not really be necessary. For very large flowsheets, there could be an extremely large number of optimial tear edge sets. """ def sear(depth, prevY): # This is a recursive function for generating tear sets. # It selects one edge from a cycle, then calls itself # to select an edge from the next cycle. It is a branch # and bound search tree to find best tear sets. # The function returns when all cycles are torn, which # may be before an edge was selected from each cycle if # cycles contain common edges. for i in range(len(cycleEdges[depth])): # Loop through all the edges in cycle with index depth y = list(prevY) # get list of already selected tear stream y[cycleEdges[depth][i]] = 1 # calculate number of times each cycle is torn Ay = numpy.dot(A, y) maxAy = max(Ay) sumY = sum(y) if maxAy > upperBound[0]: # breaking a cycle too many times, branch is no good continue elif maxAy == upperBound[0] and sumY > upperBound[1]: # too many tears, branch is no good continue # Call self at next depth where a cycle is not broken if min(Ay) > 0: if maxAy < upperBound[0]: upperBound[0] = maxAy # most important factor upperBound[1] = sumY # second most important elif sumY < upperBound[1]: upperBound[1] = sumY # record solution ySet.append([list(y), maxAy, sumY]) else: for j in range(depth + 1, nr): if Ay[j] == 0: sear(j, y) # Get a quick and I think pretty good tear set for upper bound tearUB = self.tear_upper_bound(G) # Find all the cycles in a graph and make cycle-edge matrix A # Rows of A are cycles and columns of A are edges # 1 if an edge is in a cycle, 0 otherwise A, _, cycleEdges = self.cycle_edge_matrix(G) (nr, nc) = A.shape if nr == 0: # no cycles so we are done return [[[]], 0, 0] # Else there are cycles, so find edges to tear y_init = [False] * G.number_of_edges() # whether edge j is in tear set for j in tearUB: # y for initial u.b. solution y_init[j] = 1 Ay_init = numpy.dot(A, y_init) # number of times each loop torn # Set two upper bounds. The fist upper bound is on number of times # a loop is broken. Second upper bound is on number of tears. upperBound = [max(Ay_init), sum(y_init)] y_init = [False] * G.number_of_edges() #clear y vector to start search ySet = [] # a list of tear sets # Three elements are stored in each tear set: # 0 = y vector (tear set), 1 = max(Ay), 2 = sum(y) # Call recursive function to find tear sets sear(0, y_init) # Screen tear sets found # A set can be recorded before upper bound is updated so we can # just throw out sets with objectives higher than u.b. deleteSet = [] # vector of tear set indexes to delete for i in range(len(ySet)): if ySet[i][1] > upperBound[0]: deleteSet.append(i) elif ySet[i][1] == upperBound[0] and ySet[i][2] > upperBound[1]: deleteSet.append(i) for i in reversed(deleteSet): del ySet[i] # Check for duplicates and delete them deleteSet = [] for i in range(len(ySet) - 1): if i in deleteSet: continue for j in range(i + 1, len(ySet)): if j in deleteSet: continue for k in range(len(y_init)): eq = True if ySet[i][0][k] != ySet[j][0][k]: eq = False break if eq == True: deleteSet.append(j) for i in reversed(sorted(deleteSet)): del ySet[i] # Turn the binary y vectors into lists of edge indexes es = [] for y in ySet: edges = [] for i in range(len(y[0])): if y[0][i] == 1: edges.append(i) es.append(edges) return es, upperBound[0], upperBound[1]