Beispiel #1
0
 def test_pow2(self):
     if not numpy_available:
         raise unittest.SkipTest('Numpy is not available')
     x_bounds = [(-2.5, 2.8), (-2.5, -0.5), (0.5, 2.8), (-2.5, 0), (0, 2.8),
                 (-2.5, -1), (1, 2.8), (-1, -0.5), (0.5, 1)]
     c_bounds = [(-2.5, 2.8), (0.5, 2.8), (0, 2.8), (1, 2.8), (0.5, 1)]
     for xl, xu in x_bounds:
         for cl, cu in c_bounds:
             m = pyo.Block(concrete=True)
             m.x = pyo.Var(bounds=(xl, xu))
             m.y = pyo.Var()
             m.c = pyo.Constraint(
                 expr=pyo.inequality(body=m.y**m.x, lower=cl, upper=cu))
             self.tightener(m)
             x = np.linspace(pyo.value(m.x.lb) + 1e-6,
                             pyo.value(m.x.ub),
                             100,
                             endpoint=False)
             z = np.linspace(pyo.value(m.c.lower) + 1e-6,
                             pyo.value(m.c.upper),
                             100,
                             endpoint=False)
             if m.y.lb is None:
                 yl = -np.inf
             else:
                 yl = m.y.lb
             if m.y.ub is None:
                 yu = np.inf
             else:
                 yu = m.y.ub
             y = np.exp(np.split(np.log(np.abs(z)), len(z)) / x)
             self.assertTrue(np.all(yl <= y))
             self.assertTrue(np.all(yu >= y))
Beispiel #2
0
    def __init__(self, center, shape_matrix, scale=1):
        """
        EllipsoidalSet constructor

        Args:
            center: Vector (``list``) of uncertain parameter values around which deviations are restrained.
            shape_matrix: Positive semi-definite matrix, effectively a covariance matrix for
            constraint and bounds determination.
            scale: Right-hand side value for the ellipsoid.
        """

        # === Valid data in lists/matrixes
        if not all(isinstance(elem, (int, float)) for row in shape_matrix for elem in row):
            raise AttributeError("Matrix shape_matrix must be real-valued and numeric.")
        if not all(isinstance(elem, (int, float)) for elem in center):
            raise AttributeError("Vector center must be real-valued and numeric.")
        if not isinstance(scale, (int, float)):
            raise AttributeError("Ellipse scale must be a real-valued numeric.")
        # === Valid matrix dimensions
        num_cols = len(shape_matrix[0])
        if not all(len(row) == num_cols for row in shape_matrix):
               raise AttributeError("Shape matrix must have valid matrix dimensions.")
        # === Ensure shape_matrix is a square matrix
        array_shape_mat = np.asarray(shape_matrix)
        if array_shape_mat.shape[0] != array_shape_mat.shape[1]:
                raise AttributeError("Shape matrix must be square.")
        # === Ensure dimensions of shape_matrix are same as dimensions of uncertain_params
        if array_shape_mat.shape[1] != len(center):
                raise AttributeError("Shape matrix must be "
                                     "same dimensions as vector of uncertain parameters.")
        # === Symmetric shape_matrix
        if not np.all(np.abs(array_shape_mat-array_shape_mat.T) < 1e-8):
            raise AttributeError("Shape matrix must be symmetric.")
        # === Ensure scale is non-negative
        if scale < 0:
            raise AttributeError("Scale of ellipse (rhs) must be non-negative.")
        # === Check if shape matrix is invertible
        try:
            np.linalg.inv(shape_matrix)
        except np.linalg.LinAlgError as err:
            raise("Error with shape matrix supplied to EllipsoidalSet object being singular. %s" % err)
        # === Check is shape matrix is positive semidefinite
        if not all(np.linalg.eigvals(shape_matrix) >= 0):
            raise("Non positive-semidefinite shape matrix.")
        # === Ensure matrix is not degenerate, for determining inferred bounds
        try:
            for i in range(len(shape_matrix)):
                np.power(shape_matrix[i][i], 0.5)
        except:
            raise AttributeError("Shape matrix must be non-degenerate.")

        self.center = center
        self.shape_matrix = shape_matrix
        self.scale = scale
        self.type = "ellipsoidal"
Beispiel #3
0
def _set_axis_limits(g, axis_limits, theta_vals, theta_star):
    
    if theta_star is not None:
        theta_vals = theta_vals.append(theta_star, ignore_index=True)
        
    if axis_limits is None:
        axis_limits = {}
        for col in theta_vals.columns:
            theta_range = np.abs(theta_vals[col].max() - theta_vals[col].min())
            if theta_range < 1e-10:
                theta_range  = theta_vals[col].max()/10
            axis_limits[col] = [theta_vals[col].min() - theta_range/4, 
                                theta_vals[col].max() + theta_range/4]
    for ax in g.fig.get_axes():
        xvar, yvar, (xloc, yloc) = _get_variables(ax,theta_vals.columns)
        if xloc != yloc: # not on diagonal
            ax.set_ylim(axis_limits[yvar])
            ax.set_xlim(axis_limits[xvar])
        else: # on diagonal
            ax.set_xlim(axis_limits[xvar])
Beispiel #4
0
    def solve_tear_direct(self, G, order, function, tears, outEdges, iterLim,
                          tol, tol_type, report_diffs):
        """
        Use direct substitution to solve tears. If multiple tears are
        given they are solved simultaneously.

        Arguments
        ---------
            order
                List of lists of order in which to calculate nodes
            tears
                List of tear edge indexes
            iterLim
                Limit on the number of iterations to run
            tol
                Tolerance at which iteration can be stopped

        Returns
        -------
            list
                List of lists of diff history, differences between input and
                output values at each iteration
        """
        hist = []  # diff at each iteration in every variable

        if not len(tears):
            # no need to iterate just run the calculations
            self.run_order(G, order, function, tears)
            return hist

        logger.info("Starting Direct tear convergence")

        ignore = tears + outEdges
        itercount = 0

        while True:
            svals, dvals = self.tear_diff_direct(G, tears)
            err = self.compute_err(svals, dvals, tol_type)
            hist.append(err)

            if report_diffs:
                print("Diff matrix:\n%s" % err)

            if numpy.max(numpy.abs(err)) < tol:
                break

            if itercount >= iterLim:
                logger.warning("Direct failed to converge in %s iterations" %
                               iterLim)
                return hist

            self.pass_tear_direct(G, tears)

            itercount += 1
            logger.info("Running Direct iteration %s" % itercount)
            self.run_order(G, order, function, ignore)

        self.pass_edges(G, outEdges)

        logger.info("Direct converged in %s iterations" % itercount)

        return hist
Beispiel #5
0
    def solve_tear_wegstein(self, G, order, function, tears, outEdges, iterLim,
                            tol, tol_type, report_diffs, accel_min, accel_max):
        """
        Use Wegstein to solve tears. If multiple tears are given
        they are solved simultaneously.

        Arguments
        ---------
            order
                List of lists of order in which to calculate nodes
            tears
                List of tear edge indexes
            iterLim
                Limit on the number of iterations to run
            tol
                Tolerance at which iteration can be stopped
            accel_min
                Minimum value for Wegstein acceleration factor
            accel_max
                Maximum value for Wegstein acceleration factor
            tol_type
                Type of tolerance value, either "abs" (absolute) or
                "rel" (relative to current value)

        Returns
        -------
            list
                List of lists of diff history, differences between input and
                output values at each iteration
        """
        hist = []  # diff at each iteration in every variable

        if not len(tears):
            # no need to iterate just run the calculations
            self.run_order(G, order, function, tears)
            return hist

        logger.info("Starting Wegstein tear convergence")

        itercount = 0
        ignore = tears + outEdges

        gofx = self.generate_gofx(G, tears)
        x = self.generate_first_x(G, tears)

        err = self.compute_err(gofx, x, tol_type)
        hist.append(err)

        if report_diffs:
            print("Diff matrix:\n%s" % err)

        # check if it's already solved
        if numpy.max(numpy.abs(err)) < tol:
            logger.info("Wegstein converged in %s iterations" % itercount)
            return hist

        # if not solved yet do one direct step
        x_prev = x
        gofx_prev = gofx
        x = gofx
        self.pass_tear_wegstein(G, tears, gofx)

        while True:
            itercount += 1

            logger.info("Running Wegstein iteration %s" % itercount)
            self.run_order(G, order, function, ignore)

            gofx = self.generate_gofx(G, tears)

            err = self.compute_err(gofx, x, tol_type)
            hist.append(err)

            if report_diffs:
                print("Diff matrix:\n%s" % err)

            if numpy.max(numpy.abs(err)) < tol:
                break

            if itercount > iterLim:
                logger.warning("Wegstein failed to converge in %s iterations" %
                               iterLim)
                return hist

            denom = x - x_prev
            # this will divide by 0 at some points but we handle that below,
            # so ignore division warnings
            old_settings = numpy.seterr(divide='ignore', invalid='ignore')
            slope = numpy.divide((gofx - gofx_prev), denom)
            numpy.seterr(**old_settings)
            # if isnan or isinf then x and x_prev were the same,
            # so just do direct sub for those elements
            slope[numpy.isnan(slope)] = 0
            slope[numpy.isinf(slope)] = 0
            accel = slope / (slope - 1)
            accel[accel < accel_min] = accel_min
            accel[accel > accel_max] = accel_max
            x_prev = x
            gofx_prev = gofx
            x = accel * x_prev + (1 - accel) * gofx_prev
            self.pass_tear_wegstein(G, tears, x)

        self.pass_edges(G, outEdges)

        logger.info("Wegstein converged in %s iterations" % itercount)

        return hist