def pcm_lr(func, order, dist_out, sample=None, dist_in=None, rule="H", orth=3, regression="LS", retall=False): """ Probabilistic Collocation Method using Linear Least Squares fit Parameters ---------- Required arguemnts func : callable The model to be approximated. Must accept arguments on the form `z` is an 1-dimensional array with `len(z)==len(dist)`. order : int The order of chaos expansion. dist_out : Dist Distributions for models parameter. Optional arguments sample : int The order of the sample scheme to be used. If omited it defaults to 2*len(orth). dist_in : Dist If included, space will be mapped using a Rosenblatt transformation from dist_out to dist_in before creating an expansin in terms of dist_in rule: rule for generating samples, where d is the number of dimensions. Key Name Nested ---- ---------------- ------ "K" Korobov no "R" (Pseudo-)Random no "L" Latin hypercube no "S" Sobol yes "H" Halton yes "M" Hammersley yes orth : int, str, callable, Poly Orthogonal polynomial generation. int, str : orth will be passed to orth_select for selection of orthogonalization. See orth_select doc for more details. callable : the return of orth(M, dist) will be used. Poly : it will be used directly. It must be of length N+1=comb(M+D, M) regression : str Linear regression method used. See fit_regression for more details. retall : bool If True, return extra values. # Examples # -------- # # Define function: # >>> func = lambda z: -z[1]**2 + 0.1*z[0] # # Define distribution: # >>> dist = cp.J(cp.Normal(), cp.Normal()) # # Perform pcm: # >>> q, x, y = cp.pcm_lr(func, 2, dist, retall=True) # >>> print cp.around(q, 10) # -q1^2+0.1q0 # >>> print len(x.T) # 12 """ if dist_in is None: dist = dist_out else: dist = dist_in # orthogonalization if orth is None: if dist.dependent(): orth = "chol" else: orth = "ttr" if isinstance(orth, (str, int, long)): orth = orth_select(orth) if not isinstance(orth, po.Poly): orth = orth(order, dist) # sampling if sample is None: sample = 2 * len(orth) x = samplegen(sample, dist, rule) # Rosenblatt if not (dist_in is None): x = dist_out.ppf(dist_in.cdf(x)) # evals y = np.array(map(func, x.T)) shape = y.shape[1:] y = y.reshape(len(y), y.size / len(y)) if sample == 0: y_ = y[:] R = orth * y else: R, y_ = fit_regression(orth, x, y, regression, retall=1) R = po.reshape(R, shape) if retall: return R, x, y return R
def generate_quadrature(order, domain, acc=100, sparse=False, rule="C", composite=1, growth=None, part=None, **kws): """ Numerical quadrature node and weight generator Parameters ---------- order : int The order of the quadrature. domain : array_like, Dist If array is provided domain is the lower and upper bounds (lo,up). Invalid if gaussian is set. If Dist is provided, bounds and nodes are adapted to the distribution. This includes weighting the nodes in Clenshaw-Curtis quadrature. acc : int If gaussian is set, but the Dist provieded in domain does not provide an analytical TTR, ac sets the approximation order for the descitized Stieltje's method. sparse : bool If True used Smolyak's sparse grid instead of normal tensor product grid. rule : str Quadrature rule Key Description "Gaussian", "G" Optimal Gaussian quadrature from Golub-Welsch Slow for high order. "Legendre", "E" Gauss-Legendre quadrature "Clenshaw", "C" Clenshaw-Curtis quadrature. Exponential growth rule is used when sparse is True to make the rule nested. "Leja", J" Leja quadrature. Linear growth rule is nested. "Genz", "Z" Hermite Genz-Keizter 16 rule. Nested. Valid to order 8. "Patterson", "P" Gauss-Patterson quadrature rule. Nested. Valid to order 8. If other is provided, Monte Carlo integration is assumed and arguemnt is passed to samplegen with order and domain. composite : int, optional If provided, composite quadrature will be used. Value determines the number of domains along an axis. Ignored in the case gaussian=True. growth : bool, optional If True sets the growth rule for the composite quadrature rule to exponential for Clenshaw-Curtis quadrature. Selected from context if omitted. **kws : optional Extra keywords passed to samplegen. See also -------- samplegen Sample generator """ rule = rule.upper() if rule == "GAUSSIAN": rule = "G" elif rule == "LEGENDRE": rule = "E" elif rule == "CLENSHAW": rule = "C" elif rule == "LEJA": rule = "J" elif rule == "GENZ": rule = "Z" elif rule == "PATTERSON": rule = "P" if rule != "C" and growth and order: if isinstance(order, int): order = 2**order else: order = tuple([2**o for o in order]) if rule == "G": assert isinstance(domain, di.Dist) if sparse: func = lambda m: golub_welsch(m, domain, acc) order = np.ones(len(domain), dtype=int) * order m = np.min(order) skew = [o - m for o in order] x, w = sparse_grid(func, m, len(domain), skew=skew) else: x, w = golub_welsch(order, domain, acc) elif rule in "ECJZP": isdist = not isinstance(domain, (tuple, list, np.ndarray)) if isdist: lo, up = domain.range() dim = len(domain) else: lo, up = np.array(domain) dim = lo.size if sparse: if rule == "C": if growth is None: growth = True func = lambda m: clenshaw_curtis( m, lo, up, growth=growth, composite=composite) elif rule == "E": func = lambda m: gauss_legendre(m, lo, up, composite) elif rule == "J": foo = [lambda m: leja(m, domain[i]) \ for i in range(dim)] func = rule_generator(*foo) elif rule == "Z": func = rule_generator(*[gk16] * dim) elif rule == "P": foo = [lambda m: gp(m, lo[i], up[i]) \ for i in range(dim)] func = rule_generator(*foo) order = np.ones(dim, dtype=int) * order m = np.min(order) skew = [o - m for o in order] x, w = sparse_grid(func, m, dim, skew=skew) else: if rule == "C": if growth is None: growth = False x, w = clenshaw_curtis(order, lo, up, growth=growth, composite=composite) elif rule == "E": x, w = gauss_legendre(order, lo, up, composite) elif rule == "J": x, w = leja(order, domain) elif rule == "Z": x, w = gk16(order) if isdist: W = np.sum(w) eps = 1e-5 while (W - np.sum(w[w > eps])) > 1e-15: eps *= .1 valid = w > eps x, w = x[:, valid], w[valid] w /= np.sum(w) else: x = di.samplegen(order, domain, rule, **kws) w = np.ones(x.shape[-1]) / x.shape[-1] return x, w
def pcm_lr(func, order, dist_out, sample=None, dist_in=None, rule="H", orth=3, regression="LS", retall=False): """ Probabilistic Collocation Method using Linear Least Squares fit Parameters ---------- Required arguemnts func : callable The model to be approximated. Must accept arguments on the form `z` is an 1-dimensional array with `len(z)==len(dist)`. order : int The order of chaos expansion. dist_out : Dist Distributions for models parameter. Optional arguments sample : int The order of the sample scheme to be used. If omited it defaults to 2*len(orth). dist_in : Dist If included, space will be mapped using a Rosenblatt transformation from dist_out to dist_in before creating an expansin in terms of dist_in rule: rule for generating samples, where d is the number of dimensions. Key Name Nested ---- ---------------- ------ "K" Korobov no "R" (Pseudo-)Random no "L" Latin hypercube no "S" Sobol yes "H" Halton yes "M" Hammersley yes orth : int, str, callable, Poly Orthogonal polynomial generation. int, str : orth will be passed to orth_select for selection of orthogonalization. See orth_select doc for more details. callable : the return of orth(M, dist) will be used. Poly : it will be used directly. It must be of length N+1=comb(M+D, M) regression : str Linear regression method used. See fit_regression for more details. retall : bool If True, return extra values. # Examples # -------- # # Define function: # >>> func = lambda z: -z[1]**2 + 0.1*z[0] # # Define distribution: # >>> dist = cp.J(cp.Normal(), cp.Normal()) # # Perform pcm: # >>> q, x, y = cp.pcm_lr(func, 2, dist, retall=True) # >>> print cp.around(q, 10) # -q1^2+0.1q0 # >>> print len(x.T) # 12 """ if dist_in is None: dist = dist_out else: dist = dist_in # orthogonalization if orth is None: if dist.dependent(): orth = "chol" else: orth = "ttr" if isinstance(orth, (str, int, long)): orth = orth_select(orth) if not isinstance(orth, po.Poly): orth = orth(order, dist) # sampling if sample is None: sample = 2*len(orth) x = samplegen(sample, dist, rule) # Rosenblatt if not (dist_in is None): x = dist_out.ppf(dist_in.cdf(x)) # evals y = np.array(map(func, x.T)) shape = y.shape[1:] y = y.reshape(len(y), y.size/len(y)) if sample==0: y_ = y[:] R = orth * y else: R, y_ = fit_regression(orth, x, y, regression, retall=1) R = po.reshape(R, shape) if retall: return R, x, y return R
def generate_quadrature(order, domain, acc=100, sparse=False, rule="C", composite=1, growth=None, part=None, **kws): """ Numerical quadrature node and weight generator Parameters ---------- order : int The order of the quadrature. domain : array_like, Dist If array is provided domain is the lower and upper bounds (lo,up). Invalid if gaussian is set. If Dist is provided, bounds and nodes are adapted to the distribution. This includes weighting the nodes in Clenshaw-Curtis quadrature. acc : int If gaussian is set, but the Dist provieded in domain does not provide an analytical TTR, ac sets the approximation order for the descitized Stieltje's method. sparse : bool If True used Smolyak's sparse grid instead of normal tensor product grid. rule : str Quadrature rule Key Description "Gaussian", "G" Optimal Gaussian quadrature from Golub-Welsch Slow for high order. "Legendre", "E" Gauss-Legendre quadrature "Clenshaw", "C" Clenshaw-Curtis quadrature. Exponential growth rule is used when sparse is True to make the rule nested. "Leja", J" Leja quadrature. Linear growth rule is nested. "Genz", "Z" Hermite Genz-Keizter 16 rule. Nested. Valid to order 8. "Patterson", "P" Gauss-Patterson quadrature rule. Nested. Valid to order 8. If other is provided, Monte Carlo integration is assumed and arguemnt is passed to samplegen with order and domain. composite : int, optional If provided, composite quadrature will be used. Value determines the number of domains along an axis. Ignored in the case gaussian=True. growth : bool, optional If True sets the growth rule for the composite quadrature rule to exponential for Clenshaw-Curtis quadrature. Selected from context if omitted. **kws : optional Extra keywords passed to samplegen. See also -------- samplegen Sample generator """ rule = rule.upper() if rule == "GAUSSIAN": rule = "G" elif rule == "LEGENDRE": rule = "E" elif rule == "CLENSHAW": rule = "C" elif rule == "LEJA": rule = "J" elif rule == "GENZ": rule = "Z" elif rule == "PATTERSON":rule = "P" if rule != "C" and growth and order: if isinstance(order, int): order = 2**order else: order = tuple([2**o for o in order]) if rule == "G": assert isinstance(domain, di.Dist) if sparse: func = lambda m: golub_welsch(m, domain, acc) order = np.ones(len(domain), dtype=int)*order m = np.min(order) skew = [o-m for o in order] x, w = sparse_grid(func, m, len(domain), skew=skew) else: x, w = golub_welsch(order, domain, acc) elif rule in "ECJZP": isdist = not isinstance(domain, (tuple, list, np.ndarray)) if isdist: lo,up = domain.range() dim = len(domain) else: lo,up = np.array(domain) dim = lo.size if sparse: if rule=="C": if growth is None: growth = True func = lambda m: clenshaw_curtis(m, lo, up, growth=growth, composite=composite) elif rule=="E": func = lambda m: gauss_legendre(m, lo, up, composite) elif rule=="J": func = lambda m: leja(m, domain) elif rule=="Z": func = lambda m: gk(m, domain) elif rule=="P": func = lambda m: gp(m, domain) order = np.ones(dim, dtype=int)*order m = np.min(order) skew = [o-m for o in order] x, w = sparse_grid(func, m, dim, skew=skew) else: if rule=="C": if growth is None: growth = False x, w = clenshaw_curtis(order, lo, up, growth=growth, composite=composite) # foo = [lambda o: clenshaw_curtis(o[i], lo[i], up[i], # growth=growth, composite=composite) for i in xrange(dim)] elif rule=="E": x, w = gauss_legendre(order, lo, up, composite) # foo = [lambda o: gauss_legendre(o[i], lo[i], up[i], # composite) for i in xrange(dim)] elif rule=="J": x, w = leja(order, domain) elif rule=="Z": x, w = gk(order, domain) if dim == 1: x = x.reshape(1, x.size) assert len(w) == x.shape[1] assert len(x.shape) == 2 if isdist: W = np.sum(w) eps = 1e-5 while (W-np.sum(w[w>eps]))>1e-15: eps *= .1 valid = w>eps x, w = x[:, valid], w[valid] w /= np.sum(w) else: x = di.samplegen(order, domain, rule, **kws) w = np.ones(x.shape[-1])/x.shape[-1] return x, w