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)
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)
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
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))
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()
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()
def andGetResult(self): trans = LinearTransformation(self._value, self._value) return DeterministicParameter(self._name, self._value, trans)
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
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