Esempio n. 1
0
    def eigs(self,
             neigs=None,
             symmetric=False,
             niter=None,
             uselobpcg=False,
             **kwargs_eig):
        r"""Most significant eigenvalues of linear operator.

        Return an estimate of the most significant eigenvalues
        of the linear operator. If the operator has rectangular
        shape (``shape[0]!=shape[1]``), eigenvalues are first
        computed for the square operator :math:`\mathbf{A^H}\mathbf{A}`
        and the square-root values are returned.

        Parameters
        ----------
        neigs : :obj:`int`
            Number of eigenvalues to compute (if ``None``, return all). Note
            that for ``explicit=False``, only :math:`N-1` eigenvalues can be
            computed where :math:`N` is the size of the operator in the
            model space
        symmetric : :obj:`bool`, optional
            Operator is symmetric (``True``) or not (``False``). User should
            set this parameter to ``True`` only when it is guaranteed that the
            operator is real-symmetric or complex-hermitian matrices
        niter : :obj:`int`, optional
            Number of iterations for eigenvalue estimation
        uselobpcg : :obj:`bool`, optional
            Use :func:`scipy.sparse.linalg.lobpcg`
        **kwargs_eig
            Arbitrary keyword arguments for :func:`scipy.sparse.linalg.eigs`,
            :func:`scipy.sparse.linalg.eigsh`, or
            :func:`scipy.sparse.linalg.lobpcg`

        Returns
        -------
        eigenvalues : :obj:`numpy.ndarray`
            Operator eigenvalues.

        Raises
        -------
        ValueError
            If ``uselobpcg=True`` for a non-symmetric square matrix with
            complex type

        Notes
        -----
        Depending on the size of the operator, whether it is explicit or not
        and the number of eigenvalues requested, different algorithms are
        used by this routine.

        More precisely, when only a limited number of eigenvalues is requested
        the :func:`scipy.sparse.linalg.eigsh` method is used in case of
        ``symmetric=True`` and the :func:`scipy.sparse.linalg.eigs` method
        is used ``symmetric=False``. However, when the matrix is represented
        explicitly within the linear operator (``explicit=True``) and all the
        eigenvalues are requested the :func:`scipy.linalg.eigvals` is used
        instead.

        Finally, when only a limited number of eigenvalues is required,
        it is also possible to explicitly choose to use the
        ``scipy.sparse.linalg.lobpcg`` method via the ``uselobpcg`` input
        parameter flag.

        Most of these algorithms are a port of ARPACK [1]_, a Fortran package
        which provides routines for quickly finding eigenvalues/eigenvectors
        of a matrix. As ARPACK requires only left-multiplication
        by the matrix in question, eigenvalues/eigenvectors can also be
        estimated for linear operators when the dense matrix is not available.

        .. [1] http://www.caam.rice.edu/software/ARPACK/

        """
        if self.explicit and isinstance(self.A, np.ndarray):
            if self.shape[0] == self.shape[1]:
                if neigs is None or neigs == self.shape[1]:
                    eigenvalues = eigvals(self.A)
                else:
                    if not symmetric and np.iscomplexobj(self) and uselobpcg:
                        raise ValueError(
                            'cannot use scipy.sparse.linalg.lobpcg '
                            'for non-symmetric square matrices of '
                            'complex type...')
                    if symmetric and uselobpcg:
                        X = np.random.rand(self.shape[0], neigs)
                        eigenvalues = \
                            sp_lobpcg(self.A, X=X, maxiter=niter,
                                      **kwargs_eig)[0]
                    elif symmetric:
                        eigenvalues = sp_eigsh(self.A,
                                               k=neigs,
                                               maxiter=niter,
                                               **kwargs_eig)[0]
                    else:
                        eigenvalues = sp_eigs(self.A,
                                              k=neigs,
                                              maxiter=niter,
                                              **kwargs_eig)[0]

            else:
                if neigs is None or neigs == self.shape[1]:
                    eigenvalues = np.sqrt(
                        eigvals(np.dot(np.conj(self.A.T), self.A)))
                else:
                    if uselobpcg:
                        X = np.random.rand(self.shape[1], neigs)
                        eigenvalues = np.sqrt(
                            sp_lobpcg(np.dot(np.conj(self.A.T), self.A),
                                      X=X,
                                      maxiter=niter,
                                      **kwargs_eig)[0])
                    else:
                        eigenvalues = np.sqrt(
                            sp_eigsh(np.dot(np.conj(self.A.T), self.A),
                                     k=neigs,
                                     maxiter=niter,
                                     **kwargs_eig)[0])
        else:
            if neigs is None or neigs >= self.shape[1]:
                neigs = self.shape[1] - 2
            if self.shape[0] == self.shape[1]:
                if not symmetric and np.iscomplexobj(self) and uselobpcg:
                    raise ValueError(
                        'cannot use scipy.sparse.linalg.lobpcg for '
                        'non symmetric square matrices of '
                        'complex type...')
                if symmetric and uselobpcg:
                    X = np.random.rand(self.shape[0], neigs)
                    eigenvalues = \
                        sp_lobpcg(self, X=X, maxiter=niter, **kwargs_eig)[0]
                elif symmetric:
                    eigenvalues = sp_eigsh(self,
                                           k=neigs,
                                           maxiter=niter,
                                           **kwargs_eig)[0]
                else:
                    eigenvalues = sp_eigs(self,
                                          k=neigs,
                                          maxiter=niter,
                                          **kwargs_eig)[0]
            else:
                if uselobpcg:
                    X = np.random.rand(self.shape[1], neigs)
                    eigenvalues = np.sqrt(
                        sp_lobpcg(self.H * self,
                                  X=X,
                                  maxiter=niter,
                                  **kwargs_eig)[0])
                else:
                    eigenvalues = np.sqrt(
                        sp_eigs(self.H * self,
                                k=neigs,
                                maxiter=niter,
                                **kwargs_eig)[0])
        return -np.sort(-eigenvalues)
Esempio n. 2
0
    def eigs(self, neigs=None, symmetric=False, niter=None, **kwargs_eig):
        r"""Most significant eigenvalues of linear operator.

        Return an estimate of the most significant eigenvalues
        of the linear operator. If the operator has rectangular
        shape (``shape[0]!=shape[1]``), eigenvalues are first
        computed for the square operator :math:`\mathbf{A^H}\mathbf{A}`
        and the square-root values are returned.

        Parameters
        ----------
        neigs : :obj:`int`
            Number of eigenvalues to compute (if ``None``, return all). Note
            that for ``explicit=False``, only :math:`N-1` eigenvalues can be
            computed where :math:`N` is the size of the operator in the
            model space
        symmetric : :obj:`bool`, optional
            Operator is symmetric (``True``) or not (``False``). User should
            set this parameter to ``True`` only when it is guaranteed that the
            operator is real-symmetric or complex-hermitian matrices
        niter : :obj:`int`, optional
            Number of iterations for eigenvalue estimation
        **kwargs_eig
            Arbitrary keyword arguments for
            :func:`scipy.sparse.linalg.eigs` or
            :func:`scipy.sparse.linalg.eigsh`

        Returns
        -------
        eigenvalues : :obj:`numpy.ndarray`
            Operator eigenvalues.

        Notes
        -----
        Eigenvalues are estimated using :func:`scipy.sparse.linalg.eigs`
        (``explicit=True``) or :func:`scipy.sparse.linalg.eigsh`
        (``explicit=False``).

        This is a port of ARPACK [1]_, a Fortran package which provides
        routines for quickly finding eigenvalues/eigenvectors
        of a matrix. As ARPACK requires only left-multiplication
        by the matrix in question, eigenvalues/eigenvectors can also be
        estimated for linear operators when the dense matrix is not available.

        .. [1] http://www.caam.rice.edu/software/ARPACK/

        """
        if self.explicit and isinstance(self.A, np.ndarray):
            if self.shape[0] == self.shape[1]:
                if neigs is None or neigs == self.shape[1]:
                    eigenvalues = eigvals(self.A)
                else:
                    if symmetric:
                        eigenvalues = sp_eigsh(self.A,
                                               k=neigs,
                                               maxiter=niter,
                                               **kwargs_eig)[0]
                    else:
                        eigenvalues = sp_eigs(self.A,
                                              k=neigs,
                                              maxiter=niter,
                                              **kwargs_eig)[0]

            else:
                if neigs is None or neigs == self.shape[1]:
                    eigenvalues = np.sqrt(
                        eigvals(np.dot(np.conj(self.A.T), self.A)))
                else:
                    eigenvalues = np.sqrt(
                        sp_eigsh(np.dot(np.conj(self.A.T), self.A),
                                 k=neigs,
                                 maxiter=niter,
                                 **kwargs_eig)[0])
        else:
            if neigs is None or neigs >= self.shape[1]:
                neigs = self.shape[1] - 2
            if self.shape[0] == self.shape[1]:
                if symmetric:
                    eigenvalues = sp_eigsh(self,
                                           k=neigs,
                                           maxiter=niter,
                                           **kwargs_eig)[0]
                else:
                    eigenvalues = sp_eigs(self,
                                          k=neigs,
                                          maxiter=niter,
                                          **kwargs_eig)[0]
            else:
                eigenvalues = np.sqrt(
                    sp_eigs(self.H * self,
                            k=neigs,
                            maxiter=niter,
                            **kwargs_eig)[0])
        return -np.sort(-eigenvalues)