Beispiel #1
0
def sym_tri_eigen(diags, select_indices=None):
    """
    Compute eigenvalues of a symmetric tridiagonal matrix using
    `scipy.linalg.eigvals_banded()`.
    """
    if select_indices is not None:
        n = diags.shape[1]
        select_indices = nm.minimum(select_indices, n)
        eigs = eigvals_banded(diags, lower=True, select='i',
                              select_range=select_indices)

    else:
        eigs = eigvals_banded(diags, lower=True, select='a')

    return eigs
def problem1(l):
    '''
    print the answer to problem 1 in the Beam buckling lab.
    Inputs:
        l -- length of the beam in feet
    '''
    # initialize constants, do unit conversion
    r = 1.0
    E = 4.35*r*12**2*10**6
    L = l
    I = np.pi*r**4/4
    n = 1000
    h = L/n
    
    # build the tri-diagonal matrix
    diag = -2*np.ones(n)*E*I/h**2
    odiag = np.ones(n-1)*E*I/h**2
    band = np.zeros((2,n))
    band[0,1:] = -odiag
    band[1,:] = -diag
    
    # calculate and print smallest eigenvalue
    evals = la.eigvals_banded(band)
    print evals[0]
    
    # print the analytically calculated answer
    print np.pi**2*E*I/L**2
Beispiel #3
0
    def log_likelihood(self, p):
        """Returns the log-likelihood of the data under the model, but
        efficiently.

        """
        p = self.to_params(p)

        try:
            alpha = self._alpha_matrix(p)
            beta = self._beta_matrix(p, alpha=alpha)
        except np.linalg.LinAlgError:
            warnings.warn('exception in alpha/beta computation, probably too-small timescales',
                          BadParameterWarning)
            return np.NINF

        xs = np.zeros(self.n)

        al.log_likelihood_xs_loop(self.n, self.p, alpha, self.ys - p['mu'], xs)

        try:
            evals = sl.eigvals_banded(beta, lower=False)
            if np.any(evals <= 0):
                warnings.warn('found non-positive-definite transformed covariance',
                              BadParameterWarning)
                return np.NINF

            log_evals = np.log(evals)

            return -0.5*self.n*np.log(2.0*np.pi) - 0.5*np.sum(log_evals) - 0.5*np.dot(xs, sl.solveh_banded(beta, xs, lower=False))
        except sl.LinAlgError:
            warnings.warn('exception in log-likelihood computation, probably singular cov',
                          BadParameterWarning)
            return np.NINF
Beispiel #4
0
def problem1(l):
    '''
    print the answer to problem 1 in the Beam buckling lab.
    Inputs:
        l -- length of the beam in feet
    '''
    # initialize constants, do unit conversion
    r = 1.0
    E = 4.35 * r * 12**2 * 10**6
    L = l
    I = np.pi * r**4 / 4
    n = 1000
    h = L / n

    # build the tri-diagonal matrix
    diag = -2 * np.ones(n) * E * I / h**2
    odiag = np.ones(n - 1) * E * I / h**2
    band = np.zeros((2, n))
    band[0, 1:] = -odiag
    band[1, :] = -diag

    # calculate and print smallest eigenvalue
    evals = la.eigvals_banded(band)
    print evals[0]

    # print the analytically calculated answer
    print np.pi**2 * E * I / L**2
Beispiel #5
0
def sym_tri_eigen(diags, select_indices=None):
    """
    Compute eigenvalues of a symmetric tridiagonal matrix using
    `scipy.linalg.eigvals_banded()`.
    """
    if select_indices is not None:
        n = diags.shape[1]
        select_indices = nm.minimum(select_indices, n)
        eigs = eigvals_banded(diags,
                              lower=True,
                              select='i',
                              select_range=select_indices)

    else:
        eigs = eigvals_banded(diags, lower=True, select='a')

    return eigs
Beispiel #6
0
def _dpss(N, half_nbw, Kmax):
    """Compute DPSS windows."""
    # here we want to set up an optimization problem to find a sequence
    # whose energy is maximally concentrated within band [-W,W].
    # Thus, the measure lambda(T,W) is the ratio between the energy within
    # that band, and the total energy. This leads to the eigen-system
    # (A - (l1)I)v = 0, where the eigenvector corresponding to the largest
    # eigenvalue is the sequence with maximally concentrated energy. The
    # collection of eigenvectors of this system are called Slepian
    # sequences, or discrete prolate spheroidal sequences (DPSS). Only the
    # first K, K = 2NW/dt orders of DPSS will exhibit good spectral
    # concentration
    # [see http://en.wikipedia.org/wiki/Spectral_concentration_problem]

    # Here I set up an alternative symmetric tri-diagonal eigenvalue
    # problem such that
    # (B - (l2)I)v = 0, and v are our DPSS (but eigenvalues l2 != l1)
    # the main diagonal = ([N-1-2*t]/2)**2 cos(2PIW), t=[0,1,2,...,N-1]
    # and the first off-diagonal = t(N-t)/2, t=[1,2,...,N-1]
    # [see Percival and Walden, 1993]
    nidx = np.arange(N, dtype='d')
    W = float(half_nbw) / N
    diagonal = ((N - 1 - 2 * nidx) / 2.)**2 * np.cos(2 * np.pi * W)
    off_diag = np.zeros_like(nidx)
    off_diag[:-1] = nidx[1:] * (N - nidx[1:]) / 2.
    # put the diagonals in LAPACK "packed" storage
    ab = np.zeros((2, N), 'd')
    ab[1] = diagonal
    ab[0, 1:] = off_diag[:-1]
    # only calculate the highest Kmax eigenvalues
    w = linalg.eigvals_banded(ab, select='i', select_range=(N - Kmax, N - 1))
    w = w[::-1]

    # find the corresponding eigenvectors via inverse iteration
    t = np.linspace(0, np.pi, N)
    dpss = np.zeros((Kmax, N), 'd')
    for k in range(Kmax):
        dpss[k] = tridi_inverse_iteration(diagonal,
                                          off_diag,
                                          w[k],
                                          x0=np.sin((k + 1) * t))

    # By convention (Percival and Walden, 1993 pg 379)
    # * symmetric tapers (k=0,2,4,...) should have a positive average.
    # * antisymmetric tapers should begin with a positive lobe
    fix_symmetric = (dpss[0::2].sum(axis=1) < 0)
    for i, f in enumerate(fix_symmetric):
        if f:
            dpss[2 * i] *= -1
    # rather than test the sign of one point, test the sign of the
    # linear slope up to the first (largest) peak
    pk = np.argmax(np.abs(dpss[1::2, :N // 2]), axis=1)
    for i, p in enumerate(pk):
        if np.sum(dpss[2 * i + 1, :p]) < 0:
            dpss[2 * i + 1] *= -1

    return dpss
Beispiel #7
0
 def grid_guess(self):
     J = self.op['J']
     if self.symmetric:
         J_banded = sparse_symm_to_banded(J)
         self.grid = np.sort(linear.eigvals_banded(J_banded).real)
     else:
         J_dense = J.todense()
         self.grid = np.sort(linear.eigvals(J_dense).real)
     self.ngrid = len(self.grid)
Beispiel #8
0
def _dpss(N, half_nbw, Kmax):
    """Compute DPSS windows."""
    # here we want to set up an optimization problem to find a sequence
    # whose energy is maximally concentrated within band [-W,W].
    # Thus, the measure lambda(T,W) is the ratio between the energy within
    # that band, and the total energy. This leads to the eigen-system
    # (A - (l1)I)v = 0, where the eigenvector corresponding to the largest
    # eigenvalue is the sequence with maximally concentrated energy. The
    # collection of eigenvectors of this system are called Slepian
    # sequences, or discrete prolate spheroidal sequences (DPSS). Only the
    # first K, K = 2NW/dt orders of DPSS will exhibit good spectral
    # concentration
    # [see http://en.wikipedia.org/wiki/Spectral_concentration_problem]

    # Here I set up an alternative symmetric tri-diagonal eigenvalue
    # problem such that
    # (B - (l2)I)v = 0, and v are our DPSS (but eigenvalues l2 != l1)
    # the main diagonal = ([N-1-2*t]/2)**2 cos(2PIW), t=[0,1,2,...,N-1]
    # and the first off-diagonal = t(N-t)/2, t=[1,2,...,N-1]
    # [see Percival and Walden, 1993]
    nidx = np.arange(N, dtype='d')
    W = float(half_nbw) / N
    diagonal = ((N - 1 - 2 * nidx) / 2.) ** 2 * np.cos(2 * np.pi * W)
    off_diag = np.zeros_like(nidx)
    off_diag[:-1] = nidx[1:] * (N - nidx[1:]) / 2.
    # put the diagonals in LAPACK "packed" storage
    ab = np.zeros((2, N), 'd')
    ab[1] = diagonal
    ab[0, 1:] = off_diag[:-1]
    # only calculate the highest Kmax eigenvalues
    w = linalg.eigvals_banded(ab, select='i',
                              select_range=(N - Kmax, N - 1))
    w = w[::-1]

    # find the corresponding eigenvectors via inverse iteration
    t = np.linspace(0, np.pi, N)
    dpss = np.zeros((Kmax, N), 'd')
    for k in range(Kmax):
        dpss[k] = tridi_inverse_iteration(diagonal, off_diag, w[k],
                                          x0=np.sin((k + 1) * t))

    # By convention (Percival and Walden, 1993 pg 379)
    # * symmetric tapers (k=0,2,4,...) should have a positive average.
    # * antisymmetric tapers should begin with a positive lobe
    fix_symmetric = (dpss[0::2].sum(axis=1) < 0)
    for i, f in enumerate(fix_symmetric):
        if f:
            dpss[2 * i] *= -1
    # rather than test the sign of one point, test the sign of the
    # linear slope up to the first (largest) peak
    pk = np.argmax(np.abs(dpss[1::2, :N // 2]), axis=1)
    for i, p in enumerate(pk):
        if np.sum(dpss[2 * i + 1, :p]) < 0:
            dpss[2 * i + 1] *= -1

    return dpss
Beispiel #9
0
def ritz_values(Amul, b, nits):
    """
    Return all computed ritz values as a list of arrays, where the i-th array contains the ritz values at the i-th step
    """
    alpha, beta = lanczos(Amul, b, nits)
    rvals = []

    #This puts the diagonals into the appropriate form for eigvals_banded
    M = np.zeros((2, nits))
    M[0, 1:] = beta[:-1]
    M[1] = alpha

    for n in xrange(1, nits + 1):
        rvals.append(eigvals_banded(M[:, :n]))
    return rvals
Beispiel #10
0
def _find_tapers_from_optimization(n_time_samples_per_window, time_index,
                                   half_bandwidth, n_tapers):
    '''here we want to set up an optimization problem to find a sequence
    whose energy is maximally concentrated within band
    [-half_bandwidth, half_bandwidth]. Thus,
    the measure lambda(T, half_bandwidth) is the ratio between the
    energy within that band, and the total energy. This leads to the
    eigen-system (A - (l1)I)v = 0, where the eigenvector corresponding
    to the largest eigenvalue is the sequence with maximally
    concentrated energy. The collection of eigenvectors of this system
    are called Slepian sequences, or discrete prolate spheroidal
    sequences (DPSS). Only the first K, K = 2NW/dt orders of DPSS will
    exhibit good spectral concentration
    [see http://en.wikipedia.org/wiki/Spectral_concentration_problem]

    Here I set up an alternative symmetric tri-diagonal eigenvalue
    problem such that
    (B - (l2)I)v = 0, and v are our DPSS (but eigenvalues l2 != l1)
    the main diagonal = ([n_time_samples_per_window-1-2*t]/2)**2 cos(2PIW),
    t=[0,1,2,...,n_time_samples_per_window-1] and the first off-diagonal =
    t(n_time_samples_per_window-t)/2, t=[1,2,...,
    n_time_samples_per_window-1] [see Percival and Walden, 1993]'''
    diagonal = (
        ((n_time_samples_per_window - 1 - 2 * time_index) / 2.) ** 2
        * np.cos(2 * np.pi * half_bandwidth))
    off_diag = np.zeros_like(time_index)
    off_diag[:-1] = (
        time_index[1:] * (n_time_samples_per_window - time_index[1:]) / 2.)
    # put the diagonals in LAPACK 'packed' storage
    ab = np.zeros((2, n_time_samples_per_window), dtype='d')
    ab[1] = diagonal
    ab[0, 1:] = off_diag[:-1]
    # only calculate the highest n_tapers eigenvalues
    w = eigvals_banded(
        ab, select='i',
        select_range=(n_time_samples_per_window - n_tapers,
                      n_time_samples_per_window - 1))
    w = w[::-1]

    # find the corresponding eigenvectors via inverse iteration
    t = np.linspace(0, np.pi, n_time_samples_per_window)
    tapers = np.zeros((n_tapers, n_time_samples_per_window), dtype='d')
    for taper_ind in range(n_tapers):
        tapers[taper_ind, :] = tridi_inverse_iteration(
            diagonal, off_diag, w[taper_ind],
            x0=np.sin((taper_ind + 1) * t))
    return tapers
Beispiel #11
0
def grid_guess(Jacobi_matrix, symmetric=True):
    """Returns reasonable Gauss quadrature grid as the Jacobi matrix eigenvalues.
       For P(z) = [p_{0}(z),...,p_{N}(z)], J.P(z) = z P(z); or p_{N+1}(z) = 0.

       Parameters
       ----------
       Jacobi_matrix: square self-adjoint tri-diagonal matrix (arbitrary metric)
       symmetric: T/F
       A normalised metric implies a self-adjoint matrix is symmetric.

    """

    if symmetric:
        J_banded = sparse_symm_to_banded(Jacobi_matrix)
        return (np.sort(linear.eigvals_banded(J_banded).real)).astype(dtype)
    else:
        J_dense = Jacobi_matrix.todense()
        return (np.sort(linear.eigvals(J_dense).real)).astype(dtype)
Beispiel #12
0
def test_tridi_inverse_iteration():
    import scipy.linalg as la
    from scipy.sparse import spdiags
    # set up a spectral concentration eigenvalue problem for testing
    N = 2000
    NW = 4
    K = 8
    W = float(NW) / N
    nidx = np.arange(N, dtype='d')
    ab = np.zeros((2, N), 'd')
    # store this separately for tridisolve later
    sup_diag = np.zeros((N, ), 'd')
    sup_diag[:-1] = nidx[1:] * (N - nidx[1:]) / 2.
    ab[0, 1:] = sup_diag[:-1]
    ab[1] = ((N - 1 - 2 * nidx) / 2.)**2 * np.cos(2 * np.pi * W)
    # only calculate the highest Kmax-1 eigenvalues
    w = la.eigvals_banded(ab, select='i', select_range=(N - K, N - 1))
    w = w[::-1]
    E = np.zeros((K, N), 'd')
    t = np.linspace(0, np.pi, N)
    # make sparse tridiagonal matrix for eigenvector check
    sp_data = np.zeros((3, N), 'd')
    sp_data[0, :-1] = sup_diag[:-1]
    sp_data[1] = ab[1]
    sp_data[2, 1:] = sup_diag[:-1]
    A = spdiags(sp_data, [-1, 0, 1], N, N)
    E = np.zeros((K, N), 'd')
    for j in xrange(K):
        e = utils.tridi_inverse_iteration(ab[1],
                                          sup_diag,
                                          w[j],
                                          x0=np.sin((j + 1) * t))
        b = A * e
        nt.assert_true(
               np.linalg.norm(np.abs(b) - np.abs(w[j]*e)) < 1e-8,
               'Inverse iteration eigenvector solution is inconsistent with '\
               'given eigenvalue'
               )
        E[j] = e

    # also test orthonormality of the eigenvectors
    ident = np.dot(E, E.T)
    npt.assert_almost_equal(ident, np.eye(K))
Beispiel #13
0
def test_tridi_inverse_iteration():
    import scipy.linalg as la
    from scipy.sparse import spdiags
    # set up a spectral concentration eigenvalue problem for testing
    N = 2000
    NW = 4
    K = 8
    W = float(NW) / N
    nidx = np.arange(N, dtype='d')
    ab = np.zeros((2, N), 'd')
    # store this separately for tridisolve later
    sup_diag = np.zeros((N,), 'd')
    sup_diag[:-1] = nidx[1:] * (N - nidx[1:]) / 2.
    ab[0, 1:] = sup_diag[:-1]
    ab[1] = ((N - 1 - 2 * nidx) / 2.) ** 2 * np.cos(2 * np.pi * W)
    # only calculate the highest Kmax-1 eigenvalues
    w = la.eigvals_banded(ab, select='i', select_range=(N - K, N - 1))
    w = w[::-1]
    E = np.zeros((K, N), 'd')
    t = np.linspace(0, np.pi, N)
    # make sparse tridiagonal matrix for eigenvector check
    sp_data = np.zeros((3,N), 'd')
    sp_data[0, :-1] = sup_diag[:-1]
    sp_data[1] = ab[1]
    sp_data[2, 1:] = sup_diag[:-1]
    A = spdiags(sp_data, [-1, 0, 1], N, N)
    E = np.zeros((K,N), 'd')
    for j in xrange(K):
        e = utils.tridi_inverse_iteration(
            ab[1], sup_diag, w[j], x0=np.sin((j+1)*t)
            )
        b = A*e
        nt.assert_true(
               np.linalg.norm(np.abs(b) - np.abs(w[j]*e)) < 1e-8,
               'Inverse iteration eigenvector solution is inconsistent with '\
               'given eigenvalue'
               )
        E[j] = e

    # also test orthonormality of the eigenvectors
    ident = np.dot(E, E.T)
    npt.assert_almost_equal(ident, np.eye(K))
Beispiel #14
0
def _gen_roots_and_weights(n, mu0, an_func, bn_func, f, df, symmetrize, mu):
    """[x,w] = gen_roots_and_weights(n,an_func,sqrt_bn_func,mu)

    Returns the roots (x) of an nth order orthogonal polynomial,
    and weights (w) to use in appropriate Gaussian quadrature with that
    orthogonal polynomial.

    The polynomials have the recurrence relation
          P_n+1(x) = (x - A_n) P_n(x) - B_n P_n-1(x)

    an_func(n)          should return A_n
    sqrt_bn_func(n)     should return sqrt(B_n)
    mu ( = h_0 )        is the integral of the weight over the orthogonal
                        interval
    """
    k = np.arange(n, dtype='d')
    c = np.zeros((2, n))
    c[0,1:] = bn_func(k[1:])
    c[1,:] = an_func(k)
    x = linalg.eigvals_banded(c, overwrite_a_band=True)

    # improve roots by one application of Newton's method
    y = f(n, x)
    dy = df(n, x)
    x -= y/dy

    fm = f(n-1, x)
    fm /= np.abs(fm).max()
    dy /= np.abs(dy).max()
    w = 1.0 / (fm * dy)

    if symmetrize:
        w = (w + w[::-1]) / 2
        x = (x - x[::-1]) / 2

    w *= mu0 / w.sum()

    if mu:
        return x, w, mu0
    else:
        return x, w
Beispiel #15
0
    def test_eigvals_banded(self):
        """Compare eigenvalues of eigvals_banded with those of linalg.eig."""
        w_sym = eigvals_banded(self.bandmat_sym)
        w_sym = w_sym.real
        assert_array_almost_equal(sort(w_sym), self.w_sym_lin)

        w_herm = eigvals_banded(self.bandmat_herm)
        w_herm = w_herm.real
        assert_array_almost_equal(sort(w_herm), self.w_herm_lin)

        # extracting eigenvalues with respect to an index range
        ind1 = 2
        ind2 = 6
        w_sym_ind = eigvals_banded(self.bandmat_sym,
                                   select='i',
                                   select_range=(ind1, ind2))
        assert_array_almost_equal(sort(w_sym_ind),
                                  self.w_sym_lin[ind1:ind2 + 1])
        w_herm_ind = eigvals_banded(self.bandmat_herm,
                                    select='i',
                                    select_range=(ind1, ind2))
        assert_array_almost_equal(sort(w_herm_ind),
                                  self.w_herm_lin[ind1:ind2 + 1])

        # extracting eigenvalues with respect to a value range
        v_lower = self.w_sym_lin[ind1] - 1.0e-5
        v_upper = self.w_sym_lin[ind2] + 1.0e-5
        w_sym_val = eigvals_banded(self.bandmat_sym,
                                   select='v',
                                   select_range=(v_lower, v_upper))
        assert_array_almost_equal(sort(w_sym_val),
                                  self.w_sym_lin[ind1:ind2 + 1])

        v_lower = self.w_herm_lin[ind1] - 1.0e-5
        v_upper = self.w_herm_lin[ind2] + 1.0e-5
        w_herm_val = eigvals_banded(self.bandmat_herm,
                                    select='v',
                                    select_range=(v_lower, v_upper))
        assert_array_almost_equal(sort(w_herm_val),
                                  self.w_herm_lin[ind1:ind2 + 1])
    def test_eigvals_banded(self):
        """Compare eigenvalues of eigvals_banded with those of linalg.eig."""
        w_sym = eigvals_banded(self.bandmat_sym)
        w_sym = w_sym.real
        assert_array_almost_equal(sort(w_sym), self.w_sym_lin)

        w_herm = eigvals_banded(self.bandmat_herm)
        w_herm = w_herm.real
        assert_array_almost_equal(sort(w_herm), self.w_herm_lin)

        # extracting eigenvalues with respect to an index range
        ind1 = 2
        ind2 = 6
        w_sym_ind = eigvals_banded(self.bandmat_sym,
                                    select='i', select_range=(ind1, ind2) )
        assert_array_almost_equal(sort(w_sym_ind),
                                  self.w_sym_lin[ind1:ind2+1])
        w_herm_ind = eigvals_banded(self.bandmat_herm,
                                    select='i', select_range=(ind1, ind2) )
        assert_array_almost_equal(sort(w_herm_ind),
                                  self.w_herm_lin[ind1:ind2+1])

        # extracting eigenvalues with respect to a value range
        v_lower = self.w_sym_lin[ind1] - 1.0e-5
        v_upper = self.w_sym_lin[ind2] + 1.0e-5
        w_sym_val = eigvals_banded(self.bandmat_sym,
                                select='v', select_range=(v_lower, v_upper) )
        assert_array_almost_equal(sort(w_sym_val),
                                  self.w_sym_lin[ind1:ind2+1])

        v_lower = self.w_herm_lin[ind1] - 1.0e-5
        v_upper = self.w_herm_lin[ind2] + 1.0e-5
        w_herm_val = eigvals_banded(self.bandmat_herm,
                                select='v', select_range=(v_lower, v_upper) )
        assert_array_almost_equal(sort(w_herm_val),
                                  self.w_herm_lin[ind1:ind2+1])
Beispiel #17
0
def dpss_windows(N, half_nbw, Kmax, low_bias=True, interp_from=None,
                 interp_kind='linear'):
    """
    Returns the Discrete Prolate Spheroidal Sequences of orders [0,Kmax-1]
    for a given frequency-spacing multiple NW and sequence length N.

    Note: Copied from NiTime

    Parameters
    ----------
    N : int
        Sequence length
    half_nbw : float, unitless
        Standardized half bandwidth corresponding to 2 * half_bw = BW*f0
        = BW*N/dt but with dt taken as 1
    Kmax : int
        Number of DPSS windows to return is Kmax (orders 0 through Kmax-1)
    low_bias : Bool
        Keep only tapers with eigenvalues > 0.9
    interp_from : int (optional)
        The dpss can be calculated using interpolation from a set of dpss
        with the same NW and Kmax, but shorter N. This is the length of this
        shorter set of dpss windows.
    interp_kind : str (optional)
        This input variable is passed to scipy.interpolate.interp1d and
        specifies the kind of interpolation as a string ('linear', 'nearest',
        'zero', 'slinear', 'quadratic, 'cubic') or as an integer specifying the
        order of the spline interpolator to use.


    Returns
    -------
    v, e : tuple,
        v is an array of DPSS windows shaped (Kmax, N)
        e are the eigenvalues

    Notes
    -----
    Tridiagonal form of DPSS calculation from:

    Slepian, D. Prolate spheroidal wave functions, Fourier analysis, and
    uncertainty V: The discrete case. Bell System Technical Journal,
    Volume 57 (1978), 1371430
    """
    from scipy import interpolate
    Kmax = int(Kmax)
    W = float(half_nbw) / N
    nidx = np.arange(N, dtype='d')

    # In this case, we create the dpss windows of the smaller size
    # (interp_from) and then interpolate to the larger size (N)
    if interp_from is not None:
        if interp_from > N:
            e_s = 'In dpss_windows, interp_from is: %s ' % interp_from
            e_s += 'and N is: %s. ' % N
            e_s += 'Please enter interp_from smaller than N.'
            raise ValueError(e_s)
        dpss = []
        d, e = dpss_windows(interp_from, half_nbw, Kmax, low_bias=False)
        for this_d in d:
            x = np.arange(this_d.shape[-1])
            I = interpolate.interp1d(x, this_d, kind=interp_kind)
            d_temp = I(np.linspace(0, this_d.shape[-1] - 1, N, endpoint=False))

            # Rescale:
            d_temp = d_temp / np.sqrt(sum_squared(d_temp))

            dpss.append(d_temp)

        dpss = np.array(dpss)

    else:
        # here we want to set up an optimization problem to find a sequence
        # whose energy is maximally concentrated within band [-W,W].
        # Thus, the measure lambda(T,W) is the ratio between the energy within
        # that band, and the total energy. This leads to the eigen-system
        # (A - (l1)I)v = 0, where the eigenvector corresponding to the largest
        # eigenvalue is the sequence with maximally concentrated energy. The
        # collection of eigenvectors of this system are called Slepian
        # sequences, or discrete prolate spheroidal sequences (DPSS). Only the
        # first K, K = 2NW/dt orders of DPSS will exhibit good spectral
        # concentration
        # [see http://en.wikipedia.org/wiki/Spectral_concentration_problem]

        # Here I set up an alternative symmetric tri-diagonal eigenvalue
        # problem such that
        # (B - (l2)I)v = 0, and v are our DPSS (but eigenvalues l2 != l1)
        # the main diagonal = ([N-1-2*t]/2)**2 cos(2PIW), t=[0,1,2,...,N-1]
        # and the first off-diagonal = t(N-t)/2, t=[1,2,...,N-1]
        # [see Percival and Walden, 1993]
        diagonal = ((N - 1 - 2 * nidx) / 2.) ** 2 * np.cos(2 * np.pi * W)
        off_diag = np.zeros_like(nidx)
        off_diag[:-1] = nidx[1:] * (N - nidx[1:]) / 2.
        # put the diagonals in LAPACK "packed" storage
        ab = np.zeros((2, N), 'd')
        ab[1] = diagonal
        ab[0, 1:] = off_diag[:-1]
        # only calculate the highest Kmax eigenvalues
        w = linalg.eigvals_banded(ab, select='i',
                                  select_range=(N - Kmax, N - 1))
        w = w[::-1]

        # find the corresponding eigenvectors via inverse iteration
        t = np.linspace(0, np.pi, N)
        dpss = np.zeros((Kmax, N), 'd')
        for k in range(Kmax):
            dpss[k] = tridi_inverse_iteration(diagonal, off_diag, w[k],
                                              x0=np.sin((k + 1) * t))

    # By convention (Percival and Walden, 1993 pg 379)
    # * symmetric tapers (k=0,2,4,...) should have a positive average.
    # * antisymmetric tapers should begin with a positive lobe
    fix_symmetric = (dpss[0::2].sum(axis=1) < 0)
    for i, f in enumerate(fix_symmetric):
        if f:
            dpss[2 * i] *= -1
    # rather than test the sign of one point, test the sign of the
    # linear slope up to the first (largest) peak
    pk = np.argmax(np.abs(dpss[1::2, :N // 2]), axis=1)
    for i, p in enumerate(pk):
        if np.sum(dpss[2 * i + 1, :p]) < 0:
            dpss[2 * i + 1] *= -1

    # Now find the eigenvalues of the original spectral concentration problem
    # Use the autocorr sequence technique from Percival and Walden, 1993 pg 390

    # compute autocorr using FFT (same as nitime.utils.autocorr(dpss) * N)
    rxx_size = 2 * N - 1
    n_fft = 2 ** int(np.ceil(np.log2(rxx_size)))
    dpss_fft = fftpack.fft(dpss, n_fft)
    dpss_rxx = np.real(fftpack.ifft(dpss_fft * dpss_fft.conj()))
    dpss_rxx = dpss_rxx[:, :N]

    r = 4 * W * np.sinc(2 * W * nidx)
    r[0] = 2 * W
    eigvals = np.dot(dpss_rxx, r)

    if low_bias:
        idx = (eigvals > 0.9)
        if not idx.any():
            warn('Could not properly use low_bias, keeping lowest-bias taper')
            idx = [np.argmax(eigvals)]
        dpss, eigvals = dpss[idx], eigvals[idx]
    assert len(dpss) > 0  # should never happen
    assert dpss.shape[1] == N  # old nitime bug
    return dpss, eigvals
Beispiel #18
0
def dpss_windows(N, NW, Kmax, interp_from=None, interp_kind='linear'):
    """
    Returns the Discrete Prolate Spheroidal Sequences of orders [0,Kmax-1]
    for a given frequency-spacing multiple NW and sequence length N.

    Paramters
    ---------
    N : int
        sequence length
    NW : float, unitless
        standardized half bandwidth corresponding to 2NW = BW*f0 = BW*N/dt
        but with dt taken as 1
    Kmax : int
        number of DPSS windows to return is Kmax (orders 0 through Kmax-1)
    interp_from: int (optional)
        The dpss will can calculated using interpolation from a set of dpss
        with the same NW and Kmax, but shorter N. This is the length of this
        shorter set of dpss windows.
    interp_kind: str (optional)
        This input variable is passed to scipy.interpolate.interp1d and
        specifies the kind of interpolation as a string ('linear', 'nearest',
        'zero', 'slinear', 'quadratic, 'cubic') or as an integer specifying the
        order of the spline interpolator to use.


    Returns
    -------
    v, e : tuple,
        v is an array of DPSS windows shaped (Kmax, N)
        e are the eigenvalues

    Notes
    -----
    Tridiagonal form of DPSS calculation from:

    Slepian, D. Prolate spheroidal wave functions, Fourier analysis, and
    uncertainty V: The discrete case. Bell System Technical Journal,
    Volume 57 (1978), 1371430
    """
    Kmax = int(Kmax)
    W = float(NW) / N
    nidx = np.arange(N, dtype='d')

    # In this case, we create the dpss windows of the smaller size
    # (interp_from) and then interpolate to the larger size (N)
    if interp_from is not None:
        if interp_from > N:
            e_s = 'In dpss_windows, interp_from is: %s ' % interp_from
            e_s += 'and N is: %s. ' % N
            e_s += 'Please enter interp_from smaller than N.'
            raise ValueError(e_s)
        dpss = []
        d, e = dpss_windows(interp_from, NW, Kmax)
        for this_d in d:
            x = np.arange(this_d.shape[-1])
            I = interpolate.interp1d(x, this_d, kind=interp_kind)
            d_temp = I(
                np.arange(0, this_d.shape[-1] - 1,
                          float(this_d.shape[-1] - 1) / N))

            # Rescale:
            d_temp = d_temp / np.sqrt(np.sum(d_temp**2))

            dpss.append(d_temp)

        dpss = np.array(dpss)

    else:
        # here we want to set up an optimization problem to find a sequence
        # whose energy is maximally concentrated within band [-W,W].
        # Thus, the measure lambda(T,W) is the ratio between the energy within
        # that band, and the total energy. This leads to the eigen-system
        # (A - (l1)I)v = 0, where the eigenvector corresponding to the largest
        # eigenvalue is the sequence with maximally concentrated energy. The
        # collection of eigenvectors of this system are called Slepian
        # sequences, or discrete prolate spheroidal sequences (DPSS). Only the
        # first K, K = 2NW/dt orders of DPSS will exhibit good spectral
        # concentration
        # [see http://en.wikipedia.org/wiki/Spectral_concentration_problem]

        # Here I set up an alternative symmetric tri-diagonal eigenvalue
        # problem such that
        # (B - (l2)I)v = 0, and v are our DPSS (but eigenvalues l2 != l1)
        # the main diagonal = ([N-1-2*t]/2)**2 cos(2PIW), t=[0,1,2,...,N-1]
        # and the first off-diagonal = t(N-t)/2, t=[1,2,...,N-1]
        # [see Percival and Walden, 1993]
        diagonal = ((N - 1 - 2 * nidx) / 2.)**2 * np.cos(2 * np.pi * W)
        off_diag = np.zeros_like(nidx)
        off_diag[:-1] = nidx[1:] * (N - nidx[1:]) / 2.
        # put the diagonals in LAPACK "packed" storage
        ab = np.zeros((2, N), 'd')
        ab[1] = diagonal
        ab[0, 1:] = off_diag[:-1]
        # only calculate the highest Kmax eigenvalues
        w = linalg.eigvals_banded(ab,
                                  select='i',
                                  select_range=(N - Kmax, N - 1))
        w = w[::-1]

        # find the corresponding eigenvectors via inverse iteration
        t = np.linspace(0, np.pi, N)
        dpss = np.zeros((Kmax, N), 'd')
        for k in xrange(Kmax):
            dpss[k] = utils.tridi_inverse_iteration(diagonal,
                                                    off_diag,
                                                    w[k],
                                                    x0=np.sin((k + 1) * t))

    # By convention (Percival and Walden, 1993 pg 379)
    # * symmetric tapers (k=0,2,4,...) should have a positive average.
    # * antisymmetric tapers should begin with a positive lobe
    fix_symmetric = (dpss[0::2].sum(axis=1) < 0)
    for i, f in enumerate(fix_symmetric):
        if f:
            dpss[2 * i] *= -1
    fix_skew = (dpss[1::2, 1] < 0)
    for i, f in enumerate(fix_skew):
        if f:
            dpss[2 * i + 1] *= -1

    # Now find the eigenvalues of the original spectral concentration problem
    # Use the autocorr sequence technique from Percival and Walden, 1993 pg 390
    dpss_rxx = utils.autocorr(dpss) * N
    r = 4 * W * np.sinc(2 * W * nidx)
    r[0] = 2 * W
    eigvals = np.dot(dpss_rxx, r)

    return dpss, eigvals
Beispiel #19
0
def dpss_windows(N,
                 half_nbw,
                 Kmax,
                 low_bias=True,
                 interp_from=None,
                 interp_kind='linear'):
    """Compute Discrete Prolate Spheroidal Sequences.

    Will give of orders [0,Kmax-1] for a given frequency-spacing multiple
    NW and sequence length N.

    Note: Copied from NiTime

    Parameters
    ----------
    N : int
        Sequence length
    half_nbw : float, unitless
        Standardized half bandwidth corresponding to 2 * half_bw = BW*f0
        = BW*N/dt but with dt taken as 1
    Kmax : int
        Number of DPSS windows to return is Kmax (orders 0 through Kmax-1)
    low_bias : Bool
        Keep only tapers with eigenvalues > 0.9
    interp_from : int (optional)
        The dpss can be calculated using interpolation from a set of dpss
        with the same NW and Kmax, but shorter N. This is the length of this
        shorter set of dpss windows.
    interp_kind : str (optional)
        This input variable is passed to scipy.interpolate.interp1d and
        specifies the kind of interpolation as a string ('linear', 'nearest',
        'zero', 'slinear', 'quadratic, 'cubic') or as an integer specifying the
        order of the spline interpolator to use.


    Returns
    -------
    v, e : tuple,
        v is an array of DPSS windows shaped (Kmax, N)
        e are the eigenvalues

    Notes
    -----
    Tridiagonal form of DPSS calculation from:

    Slepian, D. Prolate spheroidal wave functions, Fourier analysis, and
    uncertainty V: The discrete case. Bell System Technical Journal,
    Volume 57 (1978), 1371430
    """
    from scipy import interpolate
    Kmax = int(Kmax)
    W = float(half_nbw) / N
    nidx = np.arange(N, dtype='d')

    # In this case, we create the dpss windows of the smaller size
    # (interp_from) and then interpolate to the larger size (N)
    if interp_from is not None:
        if interp_from > N:
            e_s = 'In dpss_windows, interp_from is: %s ' % interp_from
            e_s += 'and N is: %s. ' % N
            e_s += 'Please enter interp_from smaller than N.'
            raise ValueError(e_s)
        dpss = []
        d, e = dpss_windows(interp_from, half_nbw, Kmax, low_bias=False)
        for this_d in d:
            x = np.arange(this_d.shape[-1])
            I = interpolate.interp1d(x, this_d, kind=interp_kind)
            d_temp = I(np.linspace(0, this_d.shape[-1] - 1, N, endpoint=False))

            # Rescale:
            d_temp = d_temp / np.sqrt(sum_squared(d_temp))

            dpss.append(d_temp)

        dpss = np.array(dpss)

    else:
        # here we want to set up an optimization problem to find a sequence
        # whose energy is maximally concentrated within band [-W,W].
        # Thus, the measure lambda(T,W) is the ratio between the energy within
        # that band, and the total energy. This leads to the eigen-system
        # (A - (l1)I)v = 0, where the eigenvector corresponding to the largest
        # eigenvalue is the sequence with maximally concentrated energy. The
        # collection of eigenvectors of this system are called Slepian
        # sequences, or discrete prolate spheroidal sequences (DPSS). Only the
        # first K, K = 2NW/dt orders of DPSS will exhibit good spectral
        # concentration
        # [see http://en.wikipedia.org/wiki/Spectral_concentration_problem]

        # Here I set up an alternative symmetric tri-diagonal eigenvalue
        # problem such that
        # (B - (l2)I)v = 0, and v are our DPSS (but eigenvalues l2 != l1)
        # the main diagonal = ([N-1-2*t]/2)**2 cos(2PIW), t=[0,1,2,...,N-1]
        # and the first off-diagonal = t(N-t)/2, t=[1,2,...,N-1]
        # [see Percival and Walden, 1993]
        diagonal = ((N - 1 - 2 * nidx) / 2.)**2 * np.cos(2 * np.pi * W)
        off_diag = np.zeros_like(nidx)
        off_diag[:-1] = nidx[1:] * (N - nidx[1:]) / 2.
        # put the diagonals in LAPACK "packed" storage
        ab = np.zeros((2, N), 'd')
        ab[1] = diagonal
        ab[0, 1:] = off_diag[:-1]
        # only calculate the highest Kmax eigenvalues
        w = linalg.eigvals_banded(ab,
                                  select='i',
                                  select_range=(N - Kmax, N - 1))
        w = w[::-1]

        # find the corresponding eigenvectors via inverse iteration
        t = np.linspace(0, np.pi, N)
        dpss = np.zeros((Kmax, N), 'd')
        for k in range(Kmax):
            dpss[k] = tridi_inverse_iteration(diagonal,
                                              off_diag,
                                              w[k],
                                              x0=np.sin((k + 1) * t))

    # By convention (Percival and Walden, 1993 pg 379)
    # * symmetric tapers (k=0,2,4,...) should have a positive average.
    # * antisymmetric tapers should begin with a positive lobe
    fix_symmetric = (dpss[0::2].sum(axis=1) < 0)
    for i, f in enumerate(fix_symmetric):
        if f:
            dpss[2 * i] *= -1
    # rather than test the sign of one point, test the sign of the
    # linear slope up to the first (largest) peak
    pk = np.argmax(np.abs(dpss[1::2, :N // 2]), axis=1)
    for i, p in enumerate(pk):
        if np.sum(dpss[2 * i + 1, :p]) < 0:
            dpss[2 * i + 1] *= -1

    # Now find the eigenvalues of the original spectral concentration problem
    # Use the autocorr sequence technique from Percival and Walden, 1993 pg 390

    # compute autocorr using FFT (same as nitime.utils.autocorr(dpss) * N)
    rxx_size = 2 * N - 1
    n_fft = 2**int(np.ceil(np.log2(rxx_size)))
    dpss_fft = fftpack.fft(dpss, n_fft)
    dpss_rxx = np.real(fftpack.ifft(dpss_fft * dpss_fft.conj()))
    dpss_rxx = dpss_rxx[:, :N]

    r = 4 * W * np.sinc(2 * W * nidx)
    r[0] = 2 * W
    eigvals = np.dot(dpss_rxx, r)

    if low_bias:
        idx = (eigvals > 0.9)
        if not idx.any():
            warn('Could not properly use low_bias, keeping lowest-bias taper')
            idx = [np.argmax(eigvals)]
        dpss, eigvals = dpss[idx], eigvals[idx]
    assert len(dpss) > 0  # should never happen
    assert dpss.shape[1] == N  # old nitime bug
    return dpss, eigvals
Beispiel #20
0
def dpss_windows(N, NW, Kmax, interp_from=None, interp_kind='linear'):
    """
    Returns the Discrete Prolate Spheroidal Sequences of orders [0,Kmax-1]
    for a given frequency-spacing multiple NW and sequence length N.

    Paramters
    ---------
    N : int
        sequence length
    NW : float, unitless
        standardized half bandwidth corresponding to 2NW = BW*f0 = BW*N/dt
        but with dt taken as 1
    Kmax : int
        number of DPSS windows to return is Kmax (orders 0 through Kmax-1)
    interp_from: int (optional)
        The dpss will can calculated using interpolation from a set of dpss
        with the same NW and Kmax, but shorter N. This is the length of this
        shorter set of dpss windows.
    interp_kind: str (optional)
        This input variable is passed to scipy.interpolate.interp1d and
        specifies the kind of interpolation as a string ('linear', 'nearest',
        'zero', 'slinear', 'quadratic, 'cubic') or as an integer specifying the
        order of the spline interpolator to use.


    Returns
    -------
    v, e : tuple,
        v is an array of DPSS windows shaped (Kmax, N)
        e are the eigenvalues

    Notes
    -----
    Tridiagonal form of DPSS calculation from:

    Slepian, D. Prolate spheroidal wave functions, Fourier analysis, and
    uncertainty V: The discrete case. Bell System Technical Journal,
    Volume 57 (1978), 1371430
    """
    Kmax = int(Kmax)
    W = float(NW) / N
    nidx = np.arange(N, dtype='d')

    # In this case, we create the dpss windows of the smaller size
    # (interp_from) and then interpolate to the larger size (N)
    if interp_from is not None:
        if interp_from>N:
            e_s = 'In dpss_windows, interp_from is: %s ' % interp_from
            e_s += 'and N is: %s. ' % N
            e_s += 'Please enter interp_from smaller than N.'
            raise ValueError(e_s)
        dpss = []
        d, e = dpss_windows(interp_from, NW, Kmax)
        for this_d in d:
            x = np.arange(this_d.shape[-1])
            I = interpolate.interp1d(x, this_d, kind=interp_kind)
            d_temp = I(np.arange(0, this_d.shape[-1] - 1,
                                 float(this_d.shape[-1] - 1) / N))

            # Rescale:
            d_temp = d_temp / np.sqrt(np.sum(d_temp ** 2))

            dpss.append(d_temp)

        dpss = np.array(dpss)

    else:
        # here we want to set up an optimization problem to find a sequence
        # whose energy is maximally concentrated within band [-W,W].
        # Thus, the measure lambda(T,W) is the ratio between the energy within
        # that band, and the total energy. This leads to the eigen-system
        # (A - (l1)I)v = 0, where the eigenvector corresponding to the largest
        # eigenvalue is the sequence with maximally concentrated energy. The
        # collection of eigenvectors of this system are called Slepian sequences,
        # or discrete prolate spheroidal sequences (DPSS). Only the first K,
        # K = 2NW/dt orders of DPSS will exhibit good spectral concentration
        # [see http://en.wikipedia.org/wiki/Spectral_concentration_problem]

        # Here I set up an alternative symmetric tri-diagonal eigenvalue problem
        # such that
        # (B - (l2)I)v = 0, and v are our DPSS (but eigenvalues l2 != l1)
        # the main diagonal = ([N-1-2*t]/2)**2 cos(2PIW), t=[0,1,2,...,N-1]
        # and the first off-diagonal = t(N-t)/2, t=[1,2,...,N-1]
        # [see Percival and Walden, 1993]
        diagonal = ((N - 1 - 2 * nidx) / 2.) ** 2 * np.cos(2 * np.pi * W)
        off_diag = np.zeros_like(nidx)
        off_diag[:-1] = nidx[1:] * (N - nidx[1:]) / 2.
        # put the diagonals in LAPACK "packed" storage
        ab = np.zeros((2, N), 'd')
        ab[1] = diagonal
        ab[0, 1:] = off_diag[:-1]
        # only calculate the highest Kmax eigenvalues
        w = linalg.eigvals_banded(ab, select='i', select_range=(N - Kmax, N - 1))
        w = w[::-1]

        # find the corresponding eigenvectors via inverse iteration
        t = np.linspace(0, np.pi, N)
        dpss = np.zeros((Kmax, N), 'd')
        for k in xrange(Kmax):
            dpss[k] = utils.tridi_inverse_iteration(
                diagonal, off_diag, w[k], x0=np.sin((k + 1) * t)
                )

    # By convention (Percival and Walden, 1993 pg 379)
    # * symmetric tapers (k=0,2,4,...) should have a positive average.
    # * antisymmetric tapers should begin with a positive lobe
    fix_symmetric = (dpss[0::2].sum(axis=1) < 0)
    for i, f in enumerate(fix_symmetric):
        if f:
            dpss[2 * i] *= -1
    fix_skew = (dpss[1::2, 1] < 0)
    for i, f in enumerate(fix_skew):
        if f:
            dpss[2 * i + 1] *= -1

    # Now find the eigenvalues of the original spectral concentration problem
    # Use the autocorr sequence technique from Percival and Walden, 1993 pg 390
    dpss_rxx = utils.autocorr(dpss) * N
    r = 4 * W * np.sinc(2 * W * nidx)
    r[0] = 2 * W
    eigvals = np.dot(dpss_rxx, r)

    return dpss, eigvals
Beispiel #21
0
        alpha_rational = approx2(alpha, maxd)
        p = np.float(alpha_rational.numerator)
        q = np.float(alpha_rational.denominator)
        #print str(alpha) + ', ' + str(p) + '/' + str(q)
        new_maxd = maxd
        while p < min_points:
            p += q * np.ceil((min_points - p) / q)
#            print str(p/q) + ', ' + str(alpha) + ': ' + str(p) + '/' + str(q)

        if p > 1:
            A = np.zeros([2, p], dtype=np.complex128)
            for n in range(np.int(p)):
                A[1, n] = 2.0 * V2 * np.cos(q * b * k[1] / p +
                                            2 * np.pi * np.float(n) * q / p)
                if n < (p - 1):
                    A[0,
                      n + 1] = V1 * np.exp(np.complex(0.0, q * a * k[0] / p))
            d = eigvals_banded(A)

            ds = np.sort(d)
            ax.plot(alpha * np.ones(p),
                    ds,
                    symbols[kidx],
                    linewidth=0.5,
                    markersize=1.0)

plt.xlabel(r'$\alpha$')
plt.ylabel(r'$E$')

fig.show()
Beispiel #22
0
ax = fig.add_subplot(1, 1, 1)
symbols = [".b", ".r"]

for kidx in range(len(ks)):
    k = ks[kidx]
    for alpha in np.arange(1.0 / steps, 1.0, 1.0 / steps):
        alpha_rational = approx2(alpha, maxd)
        p = np.float(alpha_rational.numerator)
        q = np.float(alpha_rational.denominator)
        # print str(alpha) + ', ' + str(p) + '/' + str(q)
        new_maxd = maxd
        while p < min_points:
            p += q * np.ceil((min_points - p) / q)
        #            print str(p/q) + ', ' + str(alpha) + ': ' + str(p) + '/' + str(q)

        if p > 1:
            A = np.zeros([2, p], dtype=np.complex128)
            for n in range(np.int(p)):
                A[1, n] = 2.0 * V2 * np.cos(q * b * k[1] / p + 2 * np.pi * np.float(n) * q / p)
                if n < (p - 1):
                    A[0, n + 1] = V1 * np.exp(np.complex(0.0, q * a * k[0] / p))
            d = eigvals_banded(A)

            ds = np.sort(d)
            ax.plot(alpha * np.ones(p), ds, symbols[kidx], linewidth=0.5, markersize=1.0)

plt.xlabel(r"$\alpha$")
plt.ylabel(r"$E$")

fig.show()
Beispiel #23
0
    return rvals


if __name__ == "__main__":
    n = 1000
    nits = 40
    #A = np.random.random((n,n))
    #A = A.dot(A.T)
    #Construct the matrix
    ds = [
        np.ones(n - 100),
        np.ones(n - 1),
        np.sqrt(np.arange(1, n + 1)),
        np.ones(n - 1),
        np.ones(n - 100)
    ]
    A = diags(ds, offsets=[-100, -1, 0, 1, 100])
    b = np.ones(n)
    Amul = lambda x: A.dot(x)
    rvals = ritz_values(Amul, b, nits)
    #Convert the matrix A into the wierd form required by eigvals_banded
    M = np.zeros((101, n))
    M[-1] = ds[2]
    M[-2, 1:] = ds[1]
    M[0, 100:] = ds[0]
    print "Eigenvalue of A from 36.3 obtained after {0} iterations: {1:.7f}".format(
        nits, rvals[-1][0])
    #This call will get only the smallest eigenvalue
    print "True smallest eigenvalue (according to scipy): {0:.7f}".format(
        eigvals_banded(M, select='i', select_range=(0, 0))[0])
Beispiel #24
0
    for n in xrange(1, nits + 1):
        rvals.append(eigvals_banded(M[:, :n]))
    return rvals


if __name__ == "__main__":
    n = 1000
    nits = 40
    #A = np.random.random((n,n))
    #A = A.dot(A.T)
    ds = [
        np.ones(n - 100),
        np.ones(n - 1),
        np.sqrt(np.arange(1, n + 1)),
        np.ones(n - 1),
        np.ones(n - 100)
    ]
    A = diags(ds, offsets=[-100, -1, 0, 1, 100])
    b = np.random.random(n)
    Amul = lambda x: A.dot(x)
    rvals = ritz_values(Amul, b, nits)
    M = np.zeros((101, n))
    M[-1] = ds[2]
    M[-2, 1:] = ds[1]
    M[0, 100:] = ds[0]
    print "Eigenvalue of A from 36.3 obtained after {} iterations: {}".format(
        nits, rvals[-1][0])
    print "True smallest eigenvalue (according to scipy): {}".format(
        eigvals_banded(M, select='v', select_range=(-1., 1.))[0])
def HH_HO_eigvals(NMax, K, D):
    from numpy import arange, sqrt, vstack
    from scipy.linalg import eigvals_banded
    nmax = (NMax-K) // 2
    n = arange(nmax+1)
    return eigvals_banded(vstack((2 * n + K + D / 2., sqrt((n + 1) * (n + K + D / 2.)))), lower=True)