示例#1
0
    def andGetResult(self):
        if self._dist is None:
            raise Exception("No distribution specified for parameter '%s'" %
                            self._name)
        # if there is no transformation defined, use the
        # linear transformation as standard
        if self.__trans is None:
            bounds = self._dist.getBounds()
            if self._dist.getDim() == 1:
                self.__trans = LinearTransformation(bounds[0], bounds[1])
            else:
                self.__trans = JointTransformation()
                for i in range(self._dist.getDim()):
                    a, b = bounds[i]
                    self.__trans.add(LinearTransformation(a, b))

        # check if there are enough identifiers given
        if self._dist.getDim() > 1 and self._dist.getDim() != len(self._name):
            raise AttributeError(
                "not enough names provided; given %i (%s), expected %i" %
                (len(self._name), ", ".join(self._name), self._dist.getDim()))

        # check if there is and SGDE involved that need this
        # transformation
        if isinstance(self._dist, SGDEdist):
            self._dist.transformation = self.__trans

        # check wiener askey scheme
        partOfWienerAskeyScheme = False
        orthogPolyConfig = OrthogonalPolynomialBasis1DConfiguration()
        if isinstance(self.__trans, RosenblattTransformation) or \
                isinstance(self._dist, Uniform):
            orthogPolyConfig.polyParameters.type_ = OrthogonalPolynomialBasisType_LEGENDRE
            orthogPolyConfig.polyParameters.lowerBound_ = self._dist.getBounds(
            )[0]
            orthogPolyConfig.polyParameters.upperBound_ = self._dist.getBounds(
            )[1]
            orthogPoly = OrthogonalPolynomialBasis1D(orthogPolyConfig)
        elif isinstance(self._dist, Normal):
            orthogPolyConfig.polyParameters.type_ = OrthogonalPolynomialBasisType_HERMITE
            orthogPoly = OrthogonalPolynomialBasis1D(orthogPolyConfig)
        elif isinstance(self._dist, Beta):
            orthogPolyConfig.polyParameters.type_ = OrthogonalPolynomialBasisType_JACOBI
            orthogPolyConfig.polyParameters.alpha_ = self._dist.alpha()
            orthogPolyConfig.polyParameters.beta_ = self._dist.beta()
            orthogPoly = OrthogonalPolynomialBasis1D(orthogPolyConfig)
        elif isinstance(self._dist, TLognormal):
            orthogPolyConfig.polyParameters.type_ = OrthogonalPolynomialBasisType_BOUNDED_LOGNORMAL
            orthogPolyConfig.polyParameters.logmean_ = np.log(self._dist.mu)
            orthogPolyConfig.polyParameters.stddev_ = self._dist.sigma
            orthogPolyConfig.polyParameters.lowerBound_ = self._dist.getBounds(
            )[0]
            orthogPolyConfig.polyParameters.upperBound_ = self._dist.getBounds(
            )[1]
            orthogPoly = OrthogonalPolynomialBasis1D(orthogPolyConfig)
        else:
            orthogPoly = None

        return UncertainParameter(self._name, self._dist, self.__trans,
                                  self._value, orthogPoly)
示例#2
0
    def andGetResult(self):
        if self._dist is None:
            raise Exception("No distribution specified for parameter '%s'" %
                            self._name)
        # if there is no transformation defined, use the
        # linear transformation as standard
        if self.__trans is None:
            bounds = self._dist.getBounds()
            if self._dist.getDim() == 1:
                self.__trans = LinearTransformation(bounds[0], bounds[1])
            else:
                self.__trans = JointTransformation()
                for i in xrange(self._dist.getDim()):
                    a, b = bounds[i]
                    self.__trans.add(LinearTransformation(a, b))

        # check if there are enough identifiers given
        if self._dist.getDim() > 1 and self._dist.getDim() != len(self._name):
            raise AttributeError(
                "not enough names provided; given %i (%s), expected %i" %
                (len(self._name), ", ".join(self._name), self._dist.getDim()))

        # check if there is and SGDE involved that need this
        # transformation
        if isinstance(self._dist, SGDEdist):
            self._dist.transformation = self.__trans

        return UncertainParameter(self._name, self._dist, self.__trans,
                                  self._value)
示例#3
0
 def withLinearTransformation(self):
     if self._dist is not None:
         a, b = self._dist.getBounds()
         self.__trans = LinearTransformation(a, b)
     else:
         raise AttributeError('the distribution of "%s" is not specified \
                               yet but it is needed to know to apply the \
                               LinearTransformation' % self.__name)
     return self
示例#4
0
    def __init__(self, mu, sigma, a, b):
        """
        Constructor
        @param mu: expectation value
        @param sigma: standard deviation
        @param a: lower boundary
        @param b: upper boundary
        """
        super(Normal, self).__init__()
        self.__mu = float(mu)
        self.__sigma = float(sigma)
        self.__a, self.__b = a, b

        # standard normal
        self._dist = norm(loc=mu, scale=sigma)

        self.__linearTrans = LinearTransformation(self._dist.cdf(self.__a),
                                                  self._dist.cdf(self.__b))
示例#5
0
    def marginalize(self):
        """
        NOTE: just returns the marginalized active subset of params
        """
        # marginalize the distribution
        margDistList = []
        margTransformations = []
        activeParams = self.activeParams()
        distributions = activeParams.getIndependentJointDistribution(
        ).getDistributions()
        transformations = activeParams.getJointTransformation(
        ).getTransformations()
        if len(distributions) == len(activeParams):
            return self
        else:
            for dist, trans in zip(distributions, transformations):
                # check if current parameter is independent
                if dist.getDim() == 1:
                    margDistList.append(dist)
                    margTransformations.append(trans)
                else:
                    # marginalize the densities and update the transformations
                    innertrans = trans.getTransformations()
                    for idim in range(dist.getDim()):
                        margDist = dist.marginalizeToDimX(idim)
                        margDistList.append(margDist)
                        # update transformations
                        if isinstance(innertrans[idim],
                                      RosenblattTransformation):
                            margTransformations.append(
                                RosenblattTransformation(margDist))
                        else:
                            a, b = margDist.getBounds()
                            margTransformations.append(
                                LinearTransformation(a, b))

            assert len(margDistList) == len(
                margTransformations) == activeParams.getDim()

            # update the parameter setting
            from pysgpp.extensions.datadriven.uq.parameters.ParameterBuilder import ParameterBuilder
            builder = ParameterBuilder()
            up = builder.defineUncertainParameters()
            for name, dist, trans in zip(activeParams.getNames(), margDistList,
                                         margTransformations):
                up.new().isCalled(name).withDistribution(dist)\
                                       .withTransformation(trans)
            return builder.andGetResult()
示例#6
0
    def testMarginalEstimationStrategy(self):
        xlim = np.array([[-1, 1], [-1, 1]])
        trans = JointTransformation()
        dists = []
        for idim in range(xlim.shape[0]):
            trans.add(LinearTransformation(xlim[idim, 0], xlim[idim, 1]))
            dists.append(Uniform(xlim[idim, 0], xlim[idim, 1]))
        dist = J(dists)

        def f(x):
            return np.prod([(1 + xi) * (1 - xi) for xi in x])

        def F(x):
            return 1. - x**3 / 3.

        grid, alpha_vec = interpolate(f,
                                      1,
                                      2,
                                      gridType=GridType_Poly,
                                      deg=2,
                                      trans=trans)
        alpha = alpha_vec.array()

        q = (F(1) - F(-1))**2
        q1 = doQuadrature(grid, alpha)
        q2 = AnalyticEstimationStrategy().mean(grid, alpha, dist,
                                               trans)["value"]

        self.assertTrue(abs(q - q1) < 1e-10)
        self.assertTrue(abs(q - q2) < 1e-10)

        ngrid, nalpha, _ = MarginalAnalyticEstimationStrategy().mean(
            grid, alpha, dist, trans, [[0]])

        self.assertTrue(abs(nalpha[0] - 2. / 3.) < 1e-10)

        plotSG3d(grid, alpha)
        plt.figure()
        plotSG1d(ngrid, nalpha)
        plt.show()
示例#7
0
 def andGetResult(self):
     trans = LinearTransformation(self._value, self._value)
     return DeterministicParameter(self._name, self._value, trans)
示例#8
0
def computeBF(grid, U, admissibleSet):
    """
    Compute bilinear form
    (A)_ij = \int phi_i phi_j dU(x)
    on measure U, which is in this case supposed to be a lebesgue measure.
    @param grid: Grid, sparse grid
    @param U: list of distributions, Lebeasgue measure
    @param admissibleSet: AdmissibleSet
    @return: DataMatrix
    """
    gs = grid.getStorage()
    basis = getBasis(grid)
    # interpolate phi_i phi_j on sparse grid with piecewise polynomial SG
    # the product of two piecewise linear functions is a piecewise
    # polynomial one of degree 2.
    ngrid = Grid.createPolyBoundaryGrid(1, 2)
    ngrid.getGenerator().regular(2)
    ngs = ngrid.getStorage()
    nodalValues = DataVector(ngs.size())

    A = DataMatrix(admissibleSet.getSize(), gs.size())
    b = DataVector(admissibleSet.getSize())
    s = np.ndarray(gs.getDimension(), dtype='float')

#     # pre compute basis evaluations
#     basis_eval = {}
#     for li in xrange(1, gs.getMaxLevel() + 1):
#         for i in xrange(1, 2 ** li + 1, 2):
#             # add value with it self
#             x = 2 ** -li * i
#             basis_eval[(li, i, li, i, x)] = basis.eval(li, i, x) * \
#                 basis.eval(li, i, x)
#
#             # left side
#             x = 2 ** -(li + 1) * (2 * i - 1)
#             basis_eval[(li, i, li, i, x)] = basis.eval(li, i, x) * \
#                 basis.eval(li, i, x)
#             # right side
#             x = 2 ** -(li + 1) * (2 * i + 1)
#             basis_eval[(li, i, li, i, x)] = basis.eval(li, i, x) * \
#                 basis.eval(li, i, x)
#
#             # add values for hierarchical lower nodes
#             for lj in xrange(li + 1, gs.getMaxLevel() + 1):
#                 a = 2 ** (lj - li)
#                 j = a * i - a + 1
#                 while j < a * i + a:
#                     # center
#                     x = 2 ** -lj * j
#                     basis_eval[(li, i, lj, j, x)] = basis.eval(li, i, x) * \
#                         basis.eval(lj, j, x)
#                     basis_eval[(lj, j, li, i, x)] = basis_eval[(li, i, lj, j, x)]
#                     # left side
#                     x = 2 ** -(lj + 1) * (2 * j - 1)
#                     basis_eval[(li, i, lj, j, x)] = basis.eval(li, i, x) * \
#                         basis.eval(lj, j, x)
#                     basis_eval[(lj, j, li, i, x)] = basis_eval[(li, i, lj, j, x)]
#                     # right side
#                     x = 2 ** -(lj + 1) * (2 * j + 1)
#                     basis_eval[(li, i, lj, j, x)] = basis.eval(li, i, x) * \
#                         basis.eval(lj, j, x)
#                     basis_eval[(lj, j, li, i, x)] = basis_eval[(li, i, lj, j, x)]
#                     j += 2
#
#     print len(basis_eval)

    # run over all rows
    for i, gpi in enumerate(admissibleSet.values()):
        # run over all columns
        for j in range(gs.size()):
            # print "%i/%i" % (i * gs.size() + j + 1, gs.size() ** 2)
            gpj = gs.getPoint(j)
            for d in range(gs.getDimension()):
                # get level index
                lid, iid = gpi.getLevel(d), gpi.getIndex(d)
                ljd, ijd = gpj.getLevel(d), gpj.getIndex(d)

                # compute left and right boundary of the support of both
                # basis functions
                lb = max([(iid - 1) * 2 ** -lid, (ijd - 1) * 2 ** -ljd])
                ub = min([(iid + 1) * 2 ** -lid, (ijd + 1) * 2 ** -ljd])

                # same level, different index
                if lid == ljd and iid != ijd:
                    s[d] = 0.
                # the support does not overlap
                elif lid != ljd and lb >= ub:
                    s[d] = 0.
                else:
                    # ----------------------------------------------------
                    # do the 1d interpolation ...
                    # define transformation function
                    T = LinearTransformation(lb, ub)
                    for k in range(ngs.size()):
                        x = ngs.getCoordinate(ngs.getPoint(k), 0)
                        x = T.unitToProbabilistic(x)
                        nodalValues[k] = basis.eval(lid, iid, x) * \
                            basis.eval(ljd, ijd, x)
                    # ... by hierarchization
                    v = hierarchize(ngrid, nodalValues)

                    # discretize the following function
                    def f(x, y):
                        xp = T.unitToProbabilistic(x)
                        return float(y * U[d].pdf(xp))

                    # sparse grid quadrature
                    g, w, _ = discretize(ngrid, v, f, refnums=0, level=5,
                                         useDiscreteL2Error=False)
                    s[d] = doQuadrature(g, w) * (ub - lb)
#                     fig = plt.figure()
#                     plotSG1d(ngrid, v)
#                     x = np.linspace(xlow, ub, 100)
#                     plt.plot(np.linspace(0, 1, 100), U[d].pdf(x))
#                     fig.show()
#                     fig = plt.figure()
#                     plotSG1d(g, w)
#                     x = np.linspace(0, 1, 100)
#                     plt.plot(x,
#                              [evalSGFunction(ngrid, v, DataVector([xi])) * U[d].pdf(T.unitToProbabilistic(xi)) for xi in x])
#                     fig.show()
#                     plt.show()
                    # compute the integral of it
                    # ----------------------------------------------------
            A.set(i, j, float(np.prod(s)))
            if gs.getSequenceNumber(gpi) == j:
                b[i] = A.get(i, j)
    return A, b
示例#9
0
class Normal(Dist):
    """
    Represents a truncated normal distribution

    See: http://en.wikipedia.org/wiki/Truncated_normal_distribution
    """
    def __init__(self, mu, sigma, a, b):
        """
        Constructor
        @param mu: expectation value
        @param sigma: standard deviation
        @param a: lower boundary
        @param b: upper boundary
        """
        super(Normal, self).__init__()
        self.__mu = float(mu)
        self.__sigma = float(sigma)
        self.__a, self.__b = a, b

        # standard normal
        self._dist = norm(loc=mu, scale=sigma)

        self.__linearTrans = LinearTransformation(self._dist.cdf(self.__a),
                                                  self._dist.cdf(self.__b))

    @classmethod
    def by_range(cls, *args, **kws):
        """
        Constructor given a interval
        """
        return cls(*args, **kws)

    @classmethod
    def by_alpha(cls, mu, sigma, alpha):
        """
        Constructor given a confidence value
        @param mu: expectation value
        @param sigma: standard deviation
        @param alpha: confidence value
        """
        U = norm(loc=mu, scale=sigma)
        a = U.ppf(alpha / 2.)
        b = U.ppf(1 - alpha / 2.)

        return cls(mu, sigma, a, b)

    def pdf(self, x):
        if self.__a <= x <= self.__b:
            return self._dist.pdf(x)
        else:
            return 0.0

    def cdf(self, x):
        if self.__a <= x <= self.__b:
            x_unit = self._dist.cdf(x)
            return self.__linearTrans.probabilisticToUnit(x_unit)
        else:
            raise AttributeError("normal: cdf - x out of range [%g, %g]" %
                                 (self.__a, self.__b))

    def ppf(self, x):
        if 0.0 <= x <= 1.0:
            x_unit = self.__linearTrans.unitToProbabilistic(x)
            return self._dist.ppf(x_unit)
        else:
            raise AttributeError("normal: ppf - x out of range [%g, %g]" %
                                 (self.__a, self.__b))

    def mean(self):
        return self.__mu

    def var(self):
        return self.__sigma * self.__sigma

    def std(self):
        return self.__sigma

    def rvs(self, n=1):
        samples = np.zeros(n)
        i = 0
        while i < n:
            newSamples = self._dist.rvs(n - i)
            # check range
            for sample in newSamples:
                if self.__a <= sample <= self.__b:
                    samples[i] = sample
                    i += 1
        return samples

    def getBounds(self):
        return np.array([self.__a, self.__b], dtype='float')

    def getDim(self):
        return 1

    def __str__(self):
        return "N(%g, %g, %g, %g)" % (self.__mu, self.__sigma, self.__a,
                                      self.__b)

    def toJson(self):
        serializationString = '"module" : "' + \
                              self.__module__ + '",\n'

        for attrName in dir(self):
            attrValue = self.__getattribute__(attrName)
            serializationString += ju.parseAttribute(attrValue, attrName)

        s = serializationString.rstrip(",\n")

        return "{" + s + "}"

    @classmethod
    def fromJson(cls, jsonObject):
        """
        Restores the TNormal object from the json object with its
        attributes.
        @param jsonObject: json object
        @return: the restored TNormal object
        """
        key = '_Normal__mu'
        if key in jsonObject:
            mu = jsonObject[key]

        key = '_Normal__sigma'
        if key in jsonObject:
            sigma = jsonObject[key]

        key = '_Normal__a'
        if key in jsonObject:
            a = jsonObject[key]

        key = '_Normal__b'
        if key in jsonObject:
            b = jsonObject[key]

        return Normal(mu, sigma, a, b)
def computeBF(grid, U, admissibleSet):
    """
    Compute bilinear form
    (A)_ij = \int phi_i phi_j dU(x)
    on measure U, which is in this case supposed to be a lebesgue measure.
    @param grid: Grid, sparse grid
    @param U: list of distributions, Lebeasgue measure
    @param admissibleSet: AdmissibleSet
    @return: DataMatrix
    """
    gs = grid.getStorage()
    basis = getBasis(grid)
    # interpolate phi_i phi_j on sparse grid with piecewise polynomial SG
    # the product of two piecewise linear functions is a piecewise
    # polynomial one of degree 2.
    ngrid = Grid.createPolyBoundaryGrid(1, 2)
    ngrid.createGridGenerator().regular(2)
    ngs = ngrid.getStorage()
    nodalValues = DataVector(ngs.size())

    A = DataMatrix(admissibleSet.getSize(), gs.size())
    b = DataVector(admissibleSet.getSize())
    s = np.ndarray(gs.dim(), dtype='float')

#     # pre compute basis evaluations
#     basis_eval = {}
#     for li in xrange(1, gs.getMaxLevel() + 1):
#         for i in xrange(1, 2 ** li + 1, 2):
#             # add value with it self
#             x = 2 ** -li * i
#             basis_eval[(li, i, li, i, x)] = basis.eval(li, i, x) * \
#                 basis.eval(li, i, x)
#
#             # left side
#             x = 2 ** -(li + 1) * (2 * i - 1)
#             basis_eval[(li, i, li, i, x)] = basis.eval(li, i, x) * \
#                 basis.eval(li, i, x)
#             # right side
#             x = 2 ** -(li + 1) * (2 * i + 1)
#             basis_eval[(li, i, li, i, x)] = basis.eval(li, i, x) * \
#                 basis.eval(li, i, x)
#
#             # add values for hierarchical lower nodes
#             for lj in xrange(li + 1, gs.getMaxLevel() + 1):
#                 a = 2 ** (lj - li)
#                 j = a * i - a + 1
#                 while j < a * i + a:
#                     # center
#                     x = 2 ** -lj * j
#                     basis_eval[(li, i, lj, j, x)] = basis.eval(li, i, x) * \
#                         basis.eval(lj, j, x)
#                     basis_eval[(lj, j, li, i, x)] = basis_eval[(li, i, lj, j, x)]
#                     # left side
#                     x = 2 ** -(lj + 1) * (2 * j - 1)
#                     basis_eval[(li, i, lj, j, x)] = basis.eval(li, i, x) * \
#                         basis.eval(lj, j, x)
#                     basis_eval[(lj, j, li, i, x)] = basis_eval[(li, i, lj, j, x)]
#                     # right side
#                     x = 2 ** -(lj + 1) * (2 * j + 1)
#                     basis_eval[(li, i, lj, j, x)] = basis.eval(li, i, x) * \
#                         basis.eval(lj, j, x)
#                     basis_eval[(lj, j, li, i, x)] = basis_eval[(li, i, lj, j, x)]
#                     j += 2
#
#     print len(basis_eval)

    # run over all rows
    for i, gpi in enumerate(admissibleSet.values()):
        # run over all columns
        for j in xrange(gs.size()):
            # print "%i/%i" % (i * gs.size() + j + 1, gs.size() ** 2)
            gpj = gs.get(j)
            for d in xrange(gs.dim()):
                # get level index
                lid, iid = gpi.getLevel(d), gpi.getIndex(d)
                ljd, ijd = gpj.getLevel(d), gpj.getIndex(d)

                # compute left and right boundary of the support of both
                # basis functions
                lb = max([(iid - 1) * 2 ** -lid, (ijd - 1) * 2 ** -ljd])
                ub = min([(iid + 1) * 2 ** -lid, (ijd + 1) * 2 ** -ljd])

                # same level, different index
                if lid == ljd and iid != ijd:
                    s[d] = 0.
                # the support does not overlap
                elif lid != ljd and lb >= ub:
                    s[d] = 0.
                else:
                    # ----------------------------------------------------
                    # do the 1d interpolation ...
                    # define transformation function
                    T = LinearTransformation(lb, ub)
                    for k in xrange(ngs.size()):
                        x = ngs.get(k).getCoord(0)
                        x = T.unitToProbabilistic(x)
                        nodalValues[k] = basis.eval(lid, iid, x) * \
                            basis.eval(ljd, ijd, x)
                    # ... by hierarchization
                    v = hierarchize(ngrid, nodalValues)

                    # discretize the following function
                    def f(x, y):
                        xp = T.unitToProbabilistic(x)
                        return float(y * U[d].pdf(xp))

                    # sparse grid quadrature
                    g, w, _ = discretize(ngrid, v, f, refnums=0, level=5,
                                         useDiscreteL2Error=False)
                    s[d] = doQuadrature(g, w) * (ub - lb)
#                     fig = plt.figure()
#                     plotSG1d(ngrid, v)
#                     x = np.linspace(xlow, ub, 100)
#                     plt.plot(np.linspace(0, 1, 100), U[d].pdf(x))
#                     fig.show()
#                     fig = plt.figure()
#                     plotSG1d(g, w)
#                     x = np.linspace(0, 1, 100)
#                     plt.plot(x,
#                              [evalSGFunction(ngrid, v, DataVector([xi])) * U[d].pdf(T.unitToProbabilistic(xi)) for xi in x])
#                     fig.show()
#                     plt.show()
                    # compute the integral of it
                    # ----------------------------------------------------
            A.set(i, j, float(np.prod(s)))
            if gs.seq(gpi) == j:
                b[i] = A.get(i, j)
    return A, b