コード例 #1
0
ファイル: uncertainty_sets.py プロジェクト: DLWoodruff/pyomo
    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
コード例 #2
0
    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)
コード例 #3
0
        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)
コード例 #4
0
    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]