Example #1
0
def orth_pcd(order, dist, eps=1.e-16, normed=False, **kws):
    """
Create orthogonal polynomial expansion from pivoted Cholesky
decompostion.

Parameters
----------
order : int
    Order of polynomial expansion
dist : Dist
    Distribution space where polynomials are orthogonal
normed : bool
    If True orthonormal polynomials will be used instead of monic.
**kws : optional
    Extra keywords passed to dist.mom

Examples
--------
#  >>> Z = cp.Normal()
#  >>> print cp.orth_pcd(2, Z)
#  [1.0, q0^2-1.0, q0]
    """
    raise DeprecationWarning("Obsolete. Use orth_chol instead.")

    dim = len(dist)
    basis = po.basis(1, order, dim)
    C = Cov(basis, dist)
    N = len(basis)

    L, P = pcd(C, approx=1, pivot=1, tol=eps)
    Li = np.dot(P, np.linalg.inv(L.T))

    if normed:
        for i in xrange(N):
            Li[:, i] /= np.sum(Li[:, i] * P[:, i])
    E_ = -po.sum(E(basis, dist, **kws) * Li.T, -1)

    coefs = np.zeros((N + 1, N + 1))
    coefs[1:, 1:] = Li
    coefs[0, 0] = 1
    coefs[0, 1:] = E_

    out = {}
    out[(0, ) * dim] = coefs[0]
    basis = list(basis)
    for i in xrange(N):
        I = basis[i].keys[0]
        out[I] = coefs[i + 1]

    P = po.Poly(out, dim, coefs.shape[1:], float)
    return P
Example #2
0
def orth_chol(order, dist, normed=True, sort="GR", **kws):
    """
Create orthogonal polynomial expansion from Cholesky decomposition

Parameters
----------
order : int
    Order of polynomial expansion
dist : Dist
    Distribution space where polynomials are orthogonal
normed : bool
    If True orthonormal polynomials will be used instead of monic.
sort : str
    Ordering argument passed to poly.basis.
    If custom basis is used, argument is ignored.
kws : optional
    Keyword argument passed to dist.mom.

Examples
--------
>>> Z = cp.Normal()
>>> print cp.orth_chol(3, Z)
[1.0, q0, 0.707106781187q0^2-0.707106781187, 0.408248290464q0^3-1.22474487139q0]
    """

    dim = len(dist)
    basis = po.basis(1,order,dim, sort)
    C = Cov(basis, dist)
    N = len(basis)

    L, e = chol_gko(C)
    Li = np.linalg.inv(L.T).T
    if not normed:
        Li /= np.repeat(np.diag(Li), len(Li)).reshape(Li.shape)
    E_ = -np.sum(Li*E(basis, dist, **kws), -1)
    coefs = np.empty((N+1, N+1))
    coefs[1:,1:] = Li
    coefs[0,0] = 1
    coefs[0,1:] = 0
    coefs[1:,0] = E_
    coefs = coefs.T

    out = {}
    out[(0,)*dim] = coefs[0]
    for i in xrange(N):
        I = basis[i].keys[0]
        out[I] = coefs[i+1]

    P = po.Poly(out, dim, coefs.shape[1:], float)

    return P
Example #3
0
def orth_chol(order, dist, normed=True, sort="GR", **kws):
    """
Create orthogonal polynomial expansion from Cholesky decomposition

Parameters
----------
order : int
    Order of polynomial expansion
dist : Dist
    Distribution space where polynomials are orthogonal
normed : bool
    If True orthonormal polynomials will be used instead of monic.
sort : str
    Ordering argument passed to poly.basis.
    If custom basis is used, argument is ignored.
kws : optional
    Keyword argument passed to dist.mom.

Examples
--------
>>> Z = cp.Normal()
>>> print cp.orth_chol(3, Z)
[1.0, q0, 0.707106781187q0^2-0.707106781187, 0.408248290464q0^3-1.22474487139q0]
    """

    dim = len(dist)
    basis = po.basis(1, order, dim, sort)
    C = Cov(basis, dist)
    N = len(basis)

    L, e = chol_gko(C)
    Li = np.linalg.inv(L.T).T
    if not normed:
        Li /= np.repeat(np.diag(Li), len(Li)).reshape(Li.shape)
    E_ = -np.sum(Li * E(basis, dist, **kws), -1)
    coefs = np.empty((N + 1, N + 1))
    coefs[1:, 1:] = Li
    coefs[0, 0] = 1
    coefs[0, 1:] = 0
    coefs[1:, 0] = E_
    coefs = coefs.T

    out = {}
    out[(0, ) * dim] = coefs[0]
    for i in xrange(N):
        I = basis[i].keys[0]
        out[I] = coefs[i + 1]

    P = po.Poly(out, dim, coefs.shape[1:], float)

    return P
Example #4
0
def orth_pcd(order, dist, eps=1.e-16, normed=False, **kws):
    """
Create orthogonal polynomial expansion from pivoted Cholesky
decompostion.

Parameters
----------
order : int
    Order of polynomial expansion
dist : Dist
    Distribution space where polynomials are orthogonal
normed : bool
    If True orthonormal polynomials will be used instead of monic.
**kws : optional
    Extra keywords passed to dist.mom

Examples
--------
#  >>> Z = cp.Normal()
#  >>> print cp.orth_pcd(2, Z)
#  [1.0, q0^2-1.0, q0]
    """
    raise DeprecationWarning("Obsolete. Use orth_chol instead.")

    dim = len(dist)
    basis = po.basis(1,order,dim)
    C = Cov(basis, dist)
    N = len(basis)

    L, P = pcd(C, approx=1, pivot=1, tol=eps)
    Li = np.dot(P, np.linalg.inv(L.T))

    if normed:
        for i in xrange(N):
            Li[:,i] /= np.sum(Li[:,i]*P[:,i])
    E_ = -po.sum(E(basis, dist, **kws)*Li.T, -1)

    coefs = np.zeros((N+1, N+1))
    coefs[1:,1:] = Li
    coefs[0,0] = 1
    coefs[0,1:] = E_

    out = {}
    out[(0,)*dim] = coefs[0]
    basis = list(basis)
    for i in xrange(N):
        I = basis[i].keys[0]
        out[I] = coefs[i+1]

    P = po.Poly(out, dim, coefs.shape[1:], float)
    return P
Example #5
0
def lagrange_polynomial(X, sort="GR"):
    """
Lagrange Polynomials

X : array_like
    Sample points where the lagrange polynomials shall be 
    """

    X = np.asfarray(X)
    if len(X.shape) == 1:
        X = X.reshape(1, X.size)
    dim, size = X.shape

    order = 1
    while ber.terms(order, dim) <= size:
        order += 1

    indices = np.array(ber.bindex(1, order, dim, sort)[:size])
    s, t = np.mgrid[:size, :size]

    M = np.prod(X.T[s]**indices[t], -1)
    det = np.linalg.det(M)
    if det == 0:
        raise np.linalg.LinAlgError, "invertable matrix"

    v = po.basis(1, order, dim, sort)[:size]

    coeffs = np.zeros((size, size))

    if size == 2:
        coeffs = np.linalg.inv(M)

    else:
        for i in xrange(size):
            for j in xrange(size):
                coeffs[i, j] += np.linalg.det(M[1:, 1:])
                M = np.roll(M, -1, axis=0)
            M = np.roll(M, -1, axis=1)
        coeffs /= det

    return po.sum(v * (coeffs.T), 1)
Example #6
0
def fit_lagrange(X, Y):
    """Simple lagrange method"""

    X = np.array(X)
    Y = np.array(Y)
    assert X.shape[0] == Y.shape[0]

    if len(X.shape) == 1:
        X = X.reshape(1, X.size)

    N, dim = X.shape

    basis = []
    n = 1
    while len(basis) < N:
        basis = po.basis(0, n, dim)
        n += 1

    basis = basis[:N]

    return fit_regression(basis, X, Y)
Example #7
0
def fit_lagrange(X, Y):
    """Simple lagrange method"""

    X = np.array(X)
    Y = np.array(Y)
    assert X.shape[0] == Y.shape[0]

    if len(X.shape) == 1:
        X = X.reshape(1, X.size)
    
    N, dim = X.shape

    basis = []
    n = 1
    while len(basis) < N:
        basis = po.basis(0, n, dim)
        n += 1

    basis = basis[:N]

    return fit_regression(basis, X, Y)
Example #8
0
def lagrange_polynomial(X, sort="GR"):
    """
Lagrange Polynomials

X : array_like
    Sample points where the lagrange polynomials shall be 
    """

    X = np.asfarray(X)
    if len(X.shape)==1:
        X = X.reshape(1,X.size)
    dim,size = X.shape

    order = 1
    while ber.terms(order, dim)<=size: order += 1

    indices = np.array(ber.bindex(1, order, dim, sort)[:size])
    s,t = np.mgrid[:size, :size]

    M = np.prod(X.T[s]**indices[t], -1)
    det = np.linalg.det(M)
    if det==0:
        raise np.linalg.LinAlgError, "invertable matrix"

    v = po.basis(1, order, dim, sort)[:size]

    coeffs = np.zeros((size, size))

    if size==2:
        coeffs = np.linalg.inv(M)

    else:
        for i in xrange(size):
            for j in xrange(size):
                coeffs[i,j] += np.linalg.det(M[1:,1:])
                M = np.roll(M, -1, axis=0)
            M = np.roll(M, -1, axis=1)
        coeffs /= det

    return po.sum(v*(coeffs.T), 1)
Example #9
0
def orth_hybrid(order, dist, eps=1.e-30, normed=True, **kws):
    """
Create orthogonal polynomial expansion from Cholesky decompostion

Parameters
----------
order : int
    Order of polynomial expansion
dist : Dist
    Distribution space where polynomials are orthogonal
eps : float
    The accuracy if PCD is used
normed : bool
    If True orthonormal polynomials will be used instead of monic.
kws : optional
    Keyword argument passed to stieltjes.

Examples
--------
#  >>> Z = cp.Normal()
#  >>> print cp.orth_chol(3, Z)
#  [1.0, q0, 0.707106781187q0^2-0.707106781187, 0.408248290464q0^3-1.22474487139q0]
    """

    if order==1:
        return orth_svd(order, dist, eps, normed, **kws)

    dim = len(dist)
    basis = po.basis(1,order,dim)

    C = Cov(basis, dist)

    L, P = pcd(C, approx=0, pivot=1, tol=eps)
    eig = np.array(np.sum(np.cumsum(P, 0), 0)-1, dtype=int)

    for i in range(len(C)-1):
        try:
            I,J = np.meshgrid(eig[i:], eig[i:])
            D = C[J,I]
            L = np.linalg.cholesky(D)
            break
        except np.linalg.LinAlgError:
            continue

    if i==(len(C)-2):
        return orth_svd(order, dist, eps, normed, **kws)
    if i:
        print "subset", i

    basis = basis[eig[i:]]
    N = len(basis)

    Li = np.linalg.inv(L.T).T
    Ln = Li/np.repeat(np.diag(Li), len(Li)).reshape(Li.shape)
    E_ = -np.sum(Ln*E(basis, dist, **kws), -1)
    coefs = np.empty((N+1, N+1))
    coefs[1:,1:] = Ln
    coefs[0,0] = 1
    coefs[0,1:] = 0
    coefs[1:,0] = E_
    coefs = coefs.T

    out = {}
    out[(0,)*dim] = coefs[0]
    for i in xrange(N):
        I = basis[i].keys[0]
        out[I] = coefs[i+1]

    P = po.Poly(out, dim, coefs.shape[1:], float)

    if normed:
        norm = np.sqrt(Var(P, dist, **kws))
        norm[0] = 1
        P = P/norm

    return P
Example #10
0
def orth_hybrid(order, dist, eps=1.e-30, normed=True, **kws):
    """
Create orthogonal polynomial expansion from Cholesky decompostion

Parameters
----------
order : int
    Order of polynomial expansion
dist : Dist
    Distribution space where polynomials are orthogonal
eps : float
    The accuracy if PCD is used
normed : bool
    If True orthonormal polynomials will be used instead of monic.
kws : optional
    Keyword argument passed to stieltjes.

Examples
--------
#  >>> Z = cp.Normal()
#  >>> print cp.orth_chol(3, Z)
#  [1.0, q0, 0.707106781187q0^2-0.707106781187, 0.408248290464q0^3-1.22474487139q0]
    """
    raise DeprecationWarning("Obsolete. Use orth_chol instead.")

    if order == 1:
        return orth_svd(order, dist, eps, normed, **kws)

    dim = len(dist)
    basis = po.basis(1, order, dim)

    C = Cov(basis, dist)

    L, P = pcd(C, approx=0, pivot=1, tol=eps)
    eig = np.array(np.sum(np.cumsum(P, 0), 0) - 1, dtype=int)

    for i in range(len(C) - 1):
        try:
            I, J = np.meshgrid(eig[i:], eig[i:])
            D = C[J, I]
            L = np.linalg.cholesky(D)
            break
        except np.linalg.LinAlgError:
            continue

    if i == (len(C) - 2):
        return orth_svd(order, dist, eps, normed, **kws)
    if i:
        print "subset", i

    basis = basis[eig[i:]]
    N = len(basis)

    Li = np.linalg.inv(L.T).T
    Ln = Li / np.repeat(np.diag(Li), len(Li)).reshape(Li.shape)
    E_ = -np.sum(Ln * E(basis, dist, **kws), -1)
    coefs = np.empty((N + 1, N + 1))
    coefs[1:, 1:] = Ln
    coefs[0, 0] = 1
    coefs[0, 1:] = 0
    coefs[1:, 0] = E_
    coefs = coefs.T

    out = {}
    out[(0, ) * dim] = coefs[0]
    for i in xrange(N):
        I = basis[i].keys[0]
        out[I] = coefs[i + 1]

    P = po.Poly(out, dim, coefs.shape[1:], float)

    if normed:
        norm = np.sqrt(Var(P, dist, **kws))
        norm[0] = 1
        P = P / norm

    return P
Example #11
0
def orth_gs(order, dist, normed=False, sort="GR", **kws):
    """
Gram-Schmidt process for generating orthogonal
polynomials in a weighted function space.

Parameters
----------
order : int, Poly
    The upper polynomial order.
    Alternative a custom polynomial basis can be used.
dist : Dist
    Weighting distribution(s) defining orthogonality.
normed : bool
    If True orthonormal polynomials will be used instead of monic.
sort : str
    Ordering argument passed to poly.basis.
    If custom basis is used, argument is ignored.
kws : optional
    Keyword argument passed to dist.mom if the moments need to be
    estimated.

Returns
-------
P : Poly
    The orthogonal polynomial expansion.

Examples
--------
>>> Z = cp.J(cp.Normal(), cp.Normal())
>>> print cp.orth_gs(2, Z)
[1.0, q1, q0, -1.0+q1^2, q0q1, q0^2-1.0]
    """

    dim = len(dist)

    if isinstance(order, int):
        if order==0:
            return po.Poly(1, dim=dim)
        basis = po.basis(0, order, dim, sort)
    else:
        basis = order

    basis = list(basis)

    P = [basis[0]]

    if normed:
        for i in xrange(1,len(basis)):

            for j in xrange(i):
                tmp = P[j]*E(basis[i]*P[j], dist, **kws)
                basis[i] = basis[i] - tmp

            g = E(P[-1]**2, dist, **kws)
            if g<=0:
                print "Warning: Polynomial cutoff at term %d" % i
                break
            basis[i] = basis[i]/np.sqrt(g)
            P.append(basis[i])

    else:

        G = [1.]
        for i in xrange(1,len(basis)):
            for j in xrange(i):
                tmp = P[j]*(E(basis[i]*P[j], dist, **kws) / G[j])
                basis[i] = basis[i] - tmp

            G.append(E(P[-1]**2, dist, **kws))
            if G[-1]<=0:
                print "Warning: Polynomial cutoff at term %d" % i
                break
            P.append(basis[i])

    return po.Poly(P, dim=dim, shape=(len(P),))
Example #12
0
def orth_svd(order, dist, eps=1.e-300, normed=False, **kws):
    """
Create orthogonal polynomial expansion from pivoted Cholesky
decompostion. If eigenvalue of covariance matrix is bellow eps, the
polynomial is subset.

Parameters
----------
order : int
    Order of polynomial expansion
dist : Dist
    Distribution space where polynomials are orthogonal
eps : float
    Threshold for when to subset the expansion.
normed : bool
    If True, polynomial will be orthonormal.
**kws : optional
    Extra keywords passed to dist.mom

Examples
--------
#  >>> Z = cp.Normal()
#  >>> print cp.orth_svd(2, Z)
#  [1.0, q0^2-1.0, q0]
    """

    dim = len(dist)
    if isinstance(order, po.Poly):
        basis = order
    else:
        basis = po.basis(1,order,dim)

    basis = list(basis)
    C = Cov(basis, dist, **kws)
    L, P = pcd(C, approx=0, pivot=1, tol=eps)
    N = L.shape[-1]

    if len(L)!=N:
        I = [_.tolist().index(1) for _ in P]
        b_ = [0]*N
        for i in xrange(N):
            b_[i] = basis[I[i]]
        basis = b_
        C = Cov(basis, dist, **kws)
        L, P = pcd(C, approx=0, pivot=1, tol=eps)
        N = L.shape[-1]

    basis = po.Poly(basis)

    Li = rlstsq(L, P, alpha=1.e-300).T

    E_ = -po.sum(E(basis, dist, **kws)*Li.T, -1)

    coefs = np.zeros((N+1, N+1))
    coefs[1:,1:] = Li
    coefs[0,0] = 1
    coefs[0,1:] = E_

    out = {}
    out[(0,)*dim] = coefs[0]
    for i in xrange(N):
        I = basis[i].keys[0]
        out[I] = coefs[i+1]

    P = po.Poly(out, dim, coefs.shape[1:], float)

    if normed:
        norm = np.sqrt(Var(P, dist, **kws))
        norm[0] = 1
        P = P/norm

    return P
Example #13
0
def orth_bert(N, dist, normed=False, sort="GR"):
    """
# Stabilized process for generating orthogonal
polynomials in a weighted function space.
Add a comment to this line

Parameters
----------
N : int
    The upper polynomial order.
dist : Dist
    Weighting distribution(s) defining orthogonality.
    normed

Returns
-------
P : Poly
    The orthogonal polynomial expansion.

Examples
--------
>>> Z = cp.MvNormal([0,0], [[1,.5],[.5,1]])
>>> P = orth_bert(2, Z)
>>> print P
[1.0, q0, q1-0.5q0, q0^2-1.0, -0.5q0^2+q0q1, 0.25q0^2-0.75+q1^2-q0q1]
    """
    dim = len(dist)
    sort = sort.upper()

    # Start orthogonalization
    x = po.basis(1,1,dim)
    if not ("R" in sort):
        x = x[::-1]
    foo = ber.Fourier_recursive(dist)

    # Create order=0
    pool = [po.Poly(1, dim=dim, shape=())]

    # start loop
    M = ber.terms(N,dim)
    for i in xrange(1, M):

        par, ax0 = ber.parent(i, dim)
        gpar, ax1 = ber.parent(par, dim)
        oneup = ber.child(0, dim, ax0)

        # calculate rank to cut some terms
        rank = ber.multi_index(i, dim)
        while rank[-1]==0: rank = rank[:-1]
        rank = dim - len(rank)

        candi = x[ax0]*pool[par]

        for j in xrange(gpar, i):

            # cut irrelevant term
            if rank and np.any(ber.multi_index(j, dim)[-rank:]):
                continue

            A = foo(oneup, par, j)
            P = pool[j]

            candi = candi - P*A

        if normed:
            candi = candi/np.sqrt(foo(i, i, 0))

        pool.append(candi)

    if "I" in sort:
        pool = pool[::-1]

    P = po.Poly([_.A for _ in pool], dim, (ber.terms(N, dim),))
    return P
Example #14
0
def orth_bert(N, dist, normed=False, sort="GR"):
    """
# Stabilized process for generating orthogonal
polynomials in a weighted function space.
Add a comment to this line

Parameters
----------
N : int
    The upper polynomial order.
dist : Dist
    Weighting distribution(s) defining orthogonality.
    normed

Returns
-------
P : Poly
    The orthogonal polynomial expansion.

Examples
--------
>>> Z = cp.MvNormal([0,0], [[1,.5],[.5,1]])
>>> P = orth_bert(2, Z)
>>> print P
[1.0, q0, q1-0.5q0, q0^2-1.0, -0.5q0^2+q0q1, 0.25q0^2-0.75+q1^2-q0q1]
    """
    dim = len(dist)
    sort = sort.upper()

    # Start orthogonalization
    x = po.basis(1, 1, dim)
    if not ("R" in sort):
        x = x[::-1]
    foo = ber.Fourier_recursive(dist)

    # Create order=0
    pool = [po.Poly(1, dim=dim, shape=())]

    # start loop
    M = ber.terms(N, dim)
    for i in xrange(1, M):

        par, ax0 = ber.parent(i, dim)
        gpar, ax1 = ber.parent(par, dim)
        oneup = ber.child(0, dim, ax0)

        # calculate rank to cut some terms
        rank = ber.multi_index(i, dim)
        while rank[-1] == 0:
            rank = rank[:-1]
        rank = dim - len(rank)

        candi = x[ax0] * pool[par]

        for j in xrange(gpar, i):

            # cut irrelevant term
            if rank and np.any(ber.multi_index(j, dim)[-rank:]):
                continue

            A = foo(oneup, par, j)
            P = pool[j]

            candi = candi - P * A

        if normed:
            candi = candi / np.sqrt(foo(i, i, 0))

        pool.append(candi)

    if "I" in sort:
        pool = pool[::-1]

    P = po.Poly([_.A for _ in pool], dim, (ber.terms(N, dim), ))
    return P
Example #15
0
def orth_gs(order, dist, normed=False, sort="GR", **kws):
    """
Gram-Schmidt process for generating orthogonal
polynomials in a weighted function space.

Parameters
----------
order : int, Poly
    The upper polynomial order.
    Alternative a custom polynomial basis can be used.
dist : Dist
    Weighting distribution(s) defining orthogonality.
normed : bool
    If True orthonormal polynomials will be used instead of monic.
sort : str
    Ordering argument passed to poly.basis.
    If custom basis is used, argument is ignored.
kws : optional
    Keyword argument passed to dist.mom if the moments need to be
    estimated.

Returns
-------
P : Poly
    The orthogonal polynomial expansion.

Examples
--------
>>> Z = cp.J(cp.Normal(), cp.Normal())
>>> print cp.orth_gs(2, Z)
[1.0, q1, q0, -1.0+q1^2, q0q1, q0^2-1.0]
    """

    dim = len(dist)

    if isinstance(order, int):
        if order == 0:
            return po.Poly(1, dim=dim)
        basis = po.basis(0, order, dim, sort)
    else:
        basis = order

    basis = list(basis)

    P = [basis[0]]

    if normed:
        for i in xrange(1, len(basis)):

            for j in xrange(i):
                tmp = P[j] * E(basis[i] * P[j], dist, **kws)
                basis[i] = basis[i] - tmp

            g = E(P[-1]**2, dist, **kws)
            if g <= 0:
                print "Warning: Polynomial cutoff at term %d" % i
                break
            basis[i] = basis[i] / np.sqrt(g)
            P.append(basis[i])

    else:

        G = [1.]
        for i in xrange(1, len(basis)):
            for j in xrange(i):
                tmp = P[j] * (E(basis[i] * P[j], dist, **kws) / G[j])
                basis[i] = basis[i] - tmp

            G.append(E(P[-1]**2, dist, **kws))
            if G[-1] <= 0:
                print "Warning: Polynomial cutoff at term %d" % i
                break
            P.append(basis[i])

    return po.Poly(P, dim=dim, shape=(len(P), ))
Example #16
0
def orth_svd(order, dist, eps=1.e-300, normed=False, **kws):
    """
Create orthogonal polynomial expansion from pivoted Cholesky
decompostion. If eigenvalue of covariance matrix is bellow eps, the
polynomial is subset.

Parameters
----------
order : int
    Order of polynomial expansion
dist : Dist
    Distribution space where polynomials are orthogonal
eps : float
    Threshold for when to subset the expansion.
normed : bool
    If True, polynomial will be orthonormal.
**kws : optional
    Extra keywords passed to dist.mom

Examples
--------
#  >>> Z = cp.Normal()
#  >>> print cp.orth_svd(2, Z)
#  [1.0, q0^2-1.0, q0]
    """
    raise DeprecationWarning("Obsolete")

    dim = len(dist)
    if isinstance(order, po.Poly):
        basis = order
    else:
        basis = po.basis(1, order, dim)

    basis = list(basis)
    C = Cov(basis, dist, **kws)
    L, P = pcd(C, approx=0, pivot=1, tol=eps)
    N = L.shape[-1]

    if len(L) != N:
        I = [_.tolist().index(1) for _ in P]
        b_ = [0] * N
        for i in xrange(N):
            b_[i] = basis[I[i]]
        basis = b_
        C = Cov(basis, dist, **kws)
        L, P = pcd(C, approx=0, pivot=1, tol=eps)
        N = L.shape[-1]

    basis = po.Poly(basis)

    Li = rlstsq(L, P, alpha=1.e-300).T

    E_ = -po.sum(E(basis, dist, **kws) * Li.T, -1)

    coefs = np.zeros((N + 1, N + 1))
    coefs[1:, 1:] = Li
    coefs[0, 0] = 1
    coefs[0, 1:] = E_

    out = {}
    out[(0, ) * dim] = coefs[0]
    for i in xrange(N):
        I = basis[i].keys[0]
        out[I] = coefs[i + 1]

    P = po.Poly(out, dim, coefs.shape[1:], float)

    if normed:
        norm = np.sqrt(Var(P, dist, **kws))
        norm[0] = 1
        P = P / norm

    return P
Example #17
0
def golub_welsch(order, dist, acc=100, **kws):
    """
Golub-Welsch algorithm for creating quadrature nodes and weights

Parameters
----------
order : int
    Quadrature order
dist : Dist
    Distribution nodes and weights are found for with
    `dim=len(dist)`
acc : int
    Accuracy used in discretized Stieltjes procedure.
    Will be increased by one for each itteration.

Returns
-------
x : numpy.array
    Optimal collocation nodes with `x.shape=(dim, order+1)`
w : numpy.array
    Optimal collocation weights with `w.shape=(order+1,)`

Examples
--------
>>> Z = cp.Normal()
>>> x, w = cp.golub_welsch(3, Z)
>>> print x
[[-2.33441422 -0.74196378  0.74196378  2.33441422]]
>>> print w
[ 0.04587585  0.45412415  0.45412415  0.04587585]

Multivariate
>>> Z = cp.J(cp.Uniform(), cp.Uniform())
>>> x, w = cp. golub_welsch(1, Z)
>>> print x
[[ 0.21132487  0.21132487  0.78867513  0.78867513]
 [ 0.21132487  0.78867513  0.21132487  0.78867513]]
>>> print w
[ 0.25  0.25  0.25  0.25]
    """

    o = np.array(order)*np.ones(len(dist), dtype=int)+1
    P,g,a,b = stieltjes(dist, np.max(o), acc=acc, retall=True, **kws)

    X,W = [], []
    dim = len(dist)

    for d in xrange(dim):
        if o[d]:
            A = np.empty((2, o[d]))
            A[0] = a[d, :o[d]]
            A[1,:-1] = np.sqrt(b[d, 1:o[d]])
            vals, vecs = eig_banded(A, lower=True)

            x, w = vals.real, vecs[0,:]**2
            indices = np.argsort(x)
            x, w = x[indices], w[indices]


            p = P[-1][d]
            dp = po.differential(p, po.basis(1,1,dim)[d])

            x = x - p(x)/dp(x)
            x = x - p(x)/dp(x)
            x = x - p(x)/dp(x)

            z = np.arange(dim)
            b = dist.mom([k*(z == d)
                for k in range(2*o[d]-3)])
            X_,r = np.meshgrid(x, np.arange(2*o[d]-3))
            X_ = X_**r
            w = np.linalg.lstsq(X_, b)[0].T[0]

        else:
            x,w = np.array([a[d,0]]), np.array([1.])

        X.append(x)
        W.append(w)

    if dim==1:
        x = np.array(X).reshape(1,o[0])
        w = np.array(W).reshape(o[0])
    else:
        x = combine(X).T
        w = np.prod(combine(W), -1)

    assert len(x)==dim
    assert len(w)==len(x.T)

    return x, w