Example #1
0
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
Example #2
0
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
Example #3
0
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
Example #4
0
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