Example #1
0
def momgen(order, domain, acc=100, sparse=False, rule="C",
        composite=1, part=None, trans=lambda x:x, **kws):

    if isinstance(domain, di.Dist):
        dim = len(domain)
    else:
        dim = np.array(domain[0]).size

    x0 = trans(np.zeros(dim))
    if np.array(x0).shape==():
        func = trans
        trans = lambda x: [func(x)]

    if part is None:
        X,W = generate_quadrature(order, domain=domain, acc=acc, sparse=sparse,
                rule=rule, composite=composite, part=part, **kws)
        Y = np.array(trans(X))

        def _mom(k):
            out = np.sum(np.prod(Y.T**k, -1)*W, 0)
            return out
    else:

        isdist = not isinstance(domain, (tuple, list, np.ndarray))
        if isdist:
            lo,up = domain.range()
        else:
            lo,up = np.array(domain)

        X,W,Y = [], [], []
        for I in np.ndindex(*part):
            x,w = clenshaw_curtis(order, lo, up, part=(I, part))
            y = np.array(trans(x))
            if isdist:
                w *= domain.pdf(x).flatten()
            if np.any(w):
                X.append(x); W.append(w); Y.append(y)

        def _mom(k):
            out = 0.
            for i in xrange(len(X)):
                out += np.sum(np.prod(Y[i].T**k, -1)*W[i], 0)
            return out

    _mom = lazy_eval(_mom, tuple)

    def mom(K, **kws):
        out = np.array([_mom(k) for k in K.T])
        return out
    return mom
Example #2
0
def momgen(order, domain, acc=100, sparse=False, rule="C",
        composite=1, part=None, trans=lambda x:x, **kws):

    if isinstance(domain, di.Dist):
        dim = len(domain)
    else:
        dim = np.array(domain[0]).size

    x0 = trans(np.zeros(dim))
    if np.array(x0).shape==():
        func = trans
        trans = lambda x: [func(x)]

    if part is None:
        X,W = generate_quadrature(order, domain=domain, acc=acc, sparse=sparse,
                rule=rule, composite=composite, part=part, **kws)
        Y = np.array(trans(X))

        def _mom(k):
            out = np.sum(np.prod(Y.T**k, -1)*W, 0)
            return out
    else:

        isdist = not isinstance(domain, (tuple, list, np.ndarray))
        if isdist:
            lo,up = domain.range()
        else:
            lo,up = np.array(domain)

        X,W,Y = [], [], []
        for I in np.ndindex(*part):
            x,w = clenshaw_curtis(order, lo, up, part=(I, part))
            y = np.array(trans(x))
            if isdist:
                w *= domain.pdf(x).flatten()
            if np.any(w):
                X.append(x); W.append(w); Y.append(y)

        def _mom(k):
            out = 0.
            for i in xrange(len(X)):
                out += np.sum(np.prod(Y[i].T**k, -1)*W[i], 0)
            return out

    _mom = lazy_eval(_mom, tuple)

    def mom(K, **kws):
        out = np.array([_mom(k) for k in K.T])
        return out
    return mom
Example #3
0
def fit_adaptive(func,
                 poly,
                 dist,
                 abserr=1.e-8,
                 relerr=1.e-8,
                 budget=0,
                 norm=0,
                 bufname="",
                 retall=False):
    """Adaptive estimation of Fourier coefficients.

Parameters
----------
func : callable
    Should take a single argument `q` which is 1D array
    `len(q)=len(dist)`.
    Must return something compatible with np.ndarray.
poly : Poly
    Polynomial vector for which to create Fourier coefficients for.
dist : Dist
    A distribution to optimize the Fourier coefficients to.
abserr : float
    Absolute error tolerance.
relerr : float
    Relative error tolerance.
budget : int
    Soft maximum number of function evaluations.
    0 means unlimited.
norm : int
    Specifies the norm that is used to measure the error and
    determine convergence properties (irrelevant for single-valued
    functions). The `norm` argument takes one of the values:
    0 : L0-norm
    1 : L0-norm on top of paired the L2-norm. Good for complex
        numbers where each conseqtive pair of the solution is real
        and imaginery.
    2 : L2-norm
    3 : L1-norm
    4 : L_infinity-norm
bufname : str, optional
    Buffer evaluations to file such that the fit_adaptive can be
    run again without redooing all evaluations.
retall : bool
    If true, returns extra values.

Returns
-------
estimate[, coeffs, norms, coeff_error, norm_error]

estimate : Poly
    The polynomial chaos expansion representation of func.
coeffs : np.ndarray
    The Fourier coefficients.
norms : np.ndarray
    The norm of the orthogonal polynomial squared.
coeff_error : np.ndarray
    Estimated integration error of the coeffs.
norm_error : np.ndarray
    Estimated integration error of the norms.

Examples
--------
>>> func = lambda q: q[0]*q[1]
>>> poly = cp.basis(0,2,2)
>>> dist = cp.J(cp.Uniform(0,1), cp.Uniform(0,1))
>>> res = cp.fit_adaptive(func, poly, dist, budget=100)
>>> print res
    """

    if bufname:
        func = lazy_eval(func, load=bufname)

    dim = len(dist)
    n = [0, 0]

    dummy_x = dist.inv(.5 * np.ones(dim, dtype=np.float64))
    val = np.array(func(dummy_x), np.float64)

    xmin = np.zeros(dim, np.float64)
    xmax = np.ones(dim, np.float64)

    def f1(u, ns, *args):
        qs = dist.inv(u.reshape(ns, dim))
        out = (poly(*qs.T)**2).T.flatten()
        return out

    dim1 = len(poly)
    val1 = np.empty(dim1, dtype=np.float64)
    err1 = np.empty(dim1, dtype=np.float64)
    _cubature(f1, dim1, xmin, xmax, (), "h", abserr, relerr, norm, budget,
              True, val1, err1)
    val1 = np.tile(val1, val.size)

    dim2 = np.prod(val.shape) * dim1
    val2 = np.empty(dim2, dtype=np.float64)
    err2 = np.empty(dim2, dtype=np.float64)

    def f2(u, ns, *args):
        n[0] += ns
        n[1] += 1
        qs = dist.inv(u.reshape(ns, dim))
        Y = np.array([func(q) for q in qs])
        Q = poly(*qs.T)
        out = np.array([Y.T * q1 for q1 in Q]).T.flatten()
        out = out / np.tile(val1, ns)
        return out

    try:
        _ = _cubature
    except:
        raise NotImplementedError("cubature not install properly")
    _cubature(f2, dim2, xmin, xmax, (), "h", abserr, relerr, norm, budget,
              True, val2, err2)

    shape = (dim1, ) + val.shape
    val2 = val2.reshape(shape[::-1]).T

    out = po.transpose(po.sum(poly * val2.T, -1))

    if retall:
        return out, val2, val1, err2, err1
    return val2
Example #4
0
def fit_adaptive(func, poly, dist, abserr=1.e-8, relerr=1.e-8,
        budget=0, norm=0, bufname="", retall=False):
    """Adaptive estimation of Fourier coefficients.

Parameters
----------
func : callable
    Should take a single argument `q` which is 1D array
    `len(q)=len(dist)`.
    Must return something compatible with np.ndarray.
poly : Poly
    Polynomial vector for which to create Fourier coefficients for.
dist : Dist
    A distribution to optimize the Fourier coefficients to.
abserr : float
    Absolute error tolerance.
relerr : float
    Relative error tolerance.
budget : int
    Soft maximum number of function evaluations.
    0 means unlimited.
norm : int
    Specifies the norm that is used to measure the error and
    determine convergence properties (irrelevant for single-valued
    functions). The `norm` argument takes one of the values:
    0 : L0-norm
    1 : L0-norm on top of paired the L2-norm. Good for complex
        numbers where each conseqtive pair of the solution is real
        and imaginery.
    2 : L2-norm
    3 : L1-norm
    4 : L_infinity-norm
bufname : str, optional
    Buffer evaluations to file such that the fit_adaptive can be
    run again without redooing all evaluations.
retall : bool
    If true, returns extra values.

Returns
-------
estimate[, coeffs, norms, coeff_error, norm_error]

estimate : Poly
    The polynomial chaos expansion representation of func.
coeffs : np.ndarray
    The Fourier coefficients.
norms : np.ndarray
    The norm of the orthogonal polynomial squared.
coeff_error : np.ndarray
    Estimated integration error of the coeffs.
norm_error : np.ndarray
    Estimated integration error of the norms.

Examples
--------
>>> func = lambda q: q[0]*q[1]
>>> poly = cp.basis(0,2,2)
>>> dist = cp.J(cp.Uniform(0,1), cp.Uniform(0,1))
>>> res = cp.fit_adaptive(func, poly, dist, budget=100)
>>> print res
    """

    if bufname:
        func = lazy_eval(func, load=bufname)

    dim = len(dist)
    n = [0,0]

    dummy_x = dist.inv(.5*np.ones(dim, dtype=np.float64))
    val = np.array(func(dummy_x), np.float64)

    xmin = np.zeros(dim, np.float64)
    xmax = np.ones(dim, np.float64)

    def f1(u, ns, *args):
        qs = dist.inv(u.reshape(ns, dim))
        out = (poly(*qs.T)**2).T.flatten()
        return out
    dim1 = len(poly)
    val1 = np.empty(dim1, dtype=np.float64)
    err1 = np.empty(dim1, dtype=np.float64)
    _cubature(f1, dim1, xmin, xmax, (), "h", abserr, relerr, norm,
            budget, True, val1, err1)
    val1 = np.tile(val1, val.size)

    dim2 = np.prod(val.shape)*dim1
    val2 = np.empty(dim2, dtype=np.float64)
    err2 = np.empty(dim2, dtype=np.float64)
    def f2(u, ns, *args):
        n[0] += ns
        n[1] += 1
        qs = dist.inv(u.reshape(ns, dim))
        Y = np.array([func(q) for q in qs])
        Q = poly(*qs.T)
        out = np.array([Y.T*q1 for q1 in Q]).T.flatten()
        out = out/np.tile(val1, ns)
        return out
    try:
        _ = _cubature
    except:
        raise NotImplementedError(
                "cubature not install properly")
    _cubature(f2, dim2, xmin, xmax, (), "h", abserr, relerr, norm,
                budget, True, val2, err2)

    shape = (dim1,)+val.shape
    val2 = val2.reshape(shape[::-1]).T

    out = po.transpose(po.sum(poly*val2.T, -1))

    if retall:
        return out, val2, val1, err2, err1
    return val2
Example #5
0
    if ax is None:
        ax = dim - np.argmin(1 * (np.array(I)[::-1] == 0)) - 1

    if not i: return i, ax

    if I[ax] == 0:
        j = parent(parent(i, dim)[0], dim)[0]
        while child(j + 1, dim, ax) < i:
            j += 1
        return j, ax

    out = np.array(I) - 1 * (np.eye(dim)[ax])
    return single_index(out), ax


parent = lazy_eval(parent, int)


def child(i, dim, ax):
    """
Child node according to Bertran's notation.

Parameters
----------
i : int
    Index of the parent node.
dim : int
    Dimensionality of the problem.
ax : int
    Dimension direction to define a child.
    Must have `0<=ax<dim`
Example #6
0
def rule_generator(*funcs):
    """
Constructor for creating quadrature generator

Parameters
----------
*funcs : callable
    One dimensional integration rule where
    for func in funcs:
        nodes, weights = func(order)
    order : int
        Order of integration rule
    nodes : array_like
        Where to evaluate.
    weights : array_like
        Weights corresponding to each node.

Returns
-------
mv_rule : callable
    Multidimensional integration rule
    nodes, weights = rule_gen(order)
    order : int, array_like
        Order of integration rule. If array_like, order along each
        axis.
    nodes : np.ndarray
        Where to evaluate with nodes.shape==(D,K), where
        D=len(funcs) and K is the number of points to evaluate.
    weights : np.ndarray
        Weights to go with the nodes with weights.shape=(K,).
    """

    dim = len(funcs)

    def tensprod_rule(N, part=None):

        N = N * np.ones(dim, int)
        q = [np.array(funcs[i](N[i])) \
                for i in xrange(dim)]

        x = [_[0] for _ in q]
        x = combine(x, part=part).T

        w = [_[1] for _ in q]
        w = np.prod(combine(w, part=part), -1)

        return x, w

    tensprod_rule = lazy_eval(tensprod_rule)

    def mv_rule(order, sparse=False, growth=None, part=None):
        """
Multidimensional integration rule

Parameters
----------
order : int, array_like
    Order of integration rule. If array_like, order along each
    axis.

Returns
-------
nodes, weights

nodes : np.ndarray
    Where to evaluate with nodes.shape==(D,K), where
    D=len(funcs) and K is the number of points to evaluate.
weights : np.ndarray
    Weights to go with the nodes with weights.shape=(K,).
        """

        if growth:

            def foo(N):
                N = N * np.ones(dim, int)
                return tensprod_rule([growth(n) for n in N], part=part)
        else:

            def foo(N):
                return tensprod_rule(N, part=part)

        if sparse:
            order = np.ones(dim, dtype=int) * order
            m = np.min(order)
            skew = [o - m for o in order]
            return sparse_grid(foo, m, dim, skew=skew)
        return foo(order)

    return mv_rule
Example #7
0
def rule_generator(*funcs):
    """
Constructor for creating quadrature generator

Parameters
----------
*funcs : callable
    One dimensional integration rule where
    for func in funcs:
        nodes, weights = func(order)
    order : int
        Order of integration rule
    nodes : array_like
        Where to evaluate.
    weights : array_like
        Weights corresponding to each node.

Returns
-------
mv_rule : callable
    Multidimensional integration rule
    nodes, weights = rule_gen(order)
    order : int, array_like
        Order of integration rule. If array_like, order along each
        axis.
    nodes : np.ndarray
        Where to evaluate with nodes.shape==(D,K), where
        D=len(funcs) and K is the number of points to evaluate.
    weights : np.ndarray
        Weights to go with the nodes with weights.shape=(K,).
    """

    dim = len(funcs)
    def tensprod_rule(N, part=None):

        N = N*np.ones(dim, int)
        q = [np.array(funcs[i](N[i])) \
                for i in xrange(dim)]

        x = [_[0] for _ in q]
        x = combine(x, part=part).T

        w = [_[1] for _ in q]
        w = np.prod(combine(w, part=part), -1)

        return x, w
    tensprod_rule = lazy_eval(tensprod_rule)

    def mv_rule(order, sparse=False, growth=None, part=None):
        """
Multidimensional integration rule

Parameters
----------
order : int, array_like
    Order of integration rule. If array_like, order along each
    axis.

Returns
-------
nodes, weights

nodes : np.ndarray
    Where to evaluate with nodes.shape==(D,K), where
    D=len(funcs) and K is the number of points to evaluate.
weights : np.ndarray
    Weights to go with the nodes with weights.shape=(K,).
        """

        if growth:
            def foo(N):
                N = N*np.ones(dim, int)
                return tensprod_rule([growth(n) for n in N], part=part)
        else:
            def foo(N):
                return tensprod_rule(N, part=part)

        if sparse:
            order = np.ones(dim, dtype=int)*order
            m = np.min(order)
            skew = [o-m for o in order]
            return sparse_grid(foo, m, dim, skew=skew)
        return foo(order)

    return mv_rule
Example #8
0
    I = multi_index(i, dim)
    if ax is None:
        ax = dim - np.argmin(1*(np.array(I)[::-1]==0))-1

    if not i: return i, ax

    if I[ax]==0:
        j = parent(parent(i, dim)[0], dim)[0]
        while child(j+1, dim, ax)<i: j += 1
        return j, ax

    out = np.array(I) - 1*(np.eye(dim)[ax])
    return single_index(out), ax

parent = lazy_eval(parent, int)


def child(i, dim, ax):
    """
Child node according to Bertran's notation.

Parameters
----------
i : int
    Index of the parent node.
dim : int
    Dimensionality of the problem.
ax : int
    Dimension direction to define a child.
    Must have `0<=ax<dim`