o
    5ήc5                     @   s   d dl Z d dlZddlmZ ddlmZ d dlmZ d dl	m
Z
mZ d dlmZ e jdr7d d	lmZ d
ZndZd dlmZ ejjjZdgZdd Zdd Z		
	dddZdS )    N   )_arpack)eigsh)check_random_state)LinearOperatoraslinearoperator)lobpcgSCIPY_USE_PROPACK)_svdpTF)svdsvdsc                 C   s
   | j  S N)Tconjx r   G/tmp/pip-target-vg8gfxp4/lib/python/scipy/sparse/linalg/_eigen/_svds.py_herm   s   
r   c
              
   C   sr  t | }h d}
||
vrtd|
 dt| } t| jtjs0t| jtjs0d}t|t	| j
dkr>d}t||dkrGt| j
nt| j
d }t||ks_d|  k r^|ksen d	}t|t|}|d
kr|d urt||ks||  k rt| j
k sn d}t|t|}|dk st|sd}t|t|}t | }ddh}||vrtd| d|d urt|}t|jtjst|jtjsd}t||dkr| j
d fnt| j
f}|j
|krd| d}t||d urt||ks|dkrd}t||d urt|n|}h d}||vr)td| dt|	}	| |||||||||	f
S )N>   arpackr   propackzsolver must be one of .z6`A` must be of floating or complex floating data type.r   z`A` must not be empty.r   r   z9`k` must be an integer satisfying `0 < k < min(A.shape)`.r   z=`ncv` must be an integer satisfying `k < ncv < min(A.shape)`.z2`tol` must be a non-negative floating point value.LMSMz`which` must be in z7`v0` must be of floating or complex floating data type.z`v0` must have shape z%`maxiter` must be a positive integer.>   FTuvhz%`return_singular_vectors` must be in )strlower
ValueErrorr   np
issubdtypedtypecomplexfloatingfloatingprodshapeminintisfinitefloatupper
atleast_1dr   )Akncvtolwhichv0maxiterreturn_singularsolverrandom_statesolversmessagekmaxwhichsr%   
rs_optionsr   r   r   _iv   sj    "(
 
"
r;      r   r   c           !         sp  |	du }t | |||||||||	
}|\
} }}}}}}}}}	|dk}| j\}}||kr9| j| j| j | jd}n#| j| j| j | jd}t| dd}|du r\| t	|dgj
} fdd}fd	d
}t|| j
|t| jt| jfd}|dkr|dkr|durt|d}n|rtjdt| j|}n|	jt| j|fd}t|||d ||d\}}tj|\}}n|dkrtstd|dv }|dv }|dk}t| ||d |d||||||	d}|\}}}}|ddd }|dddddf }|ddd }|r|nd}|r|nd}|r|||fS |S |dks(|du rI|du r:|s:|	jt| jfd}t|||d ||||d\}}|}|s^t|ddd}|ddd S t|ddd\}}}|dddddf }|ddd }|ddd }|dv }|dv }|r|r|t| nd} |rt|nd}| }n|sd}|r|t| nd}|||fS )a2  
    Partial singular value decomposition of a sparse matrix.

    Compute the largest or smallest `k` singular values and corresponding
    singular vectors of a sparse matrix `A`. The order in which the singular
    values are returned is not guaranteed.

    In the descriptions below, let ``M, N = A.shape``.

    Parameters
    ----------
    A : ndarray, sparse matrix, or LinearOperator
        Matrix to decompose of a floating point numeric dtype.
    k : int, default: 6
        Number of singular values and singular vectors to compute.
        Must satisfy ``1 <= k <= kmax``, where ``kmax=min(M, N)`` for
        ``solver='propack'`` and ``kmax=min(M, N) - 1`` otherwise.
    ncv : int, optional
        When ``solver='arpack'``, this is the number of Lanczos vectors
        generated. See :ref:`'arpack' <sparse.linalg.svds-arpack>` for details.
        When ``solver='lobpcg'`` or ``solver='propack'``, this parameter is
        ignored.
    tol : float, optional
        Tolerance for singular values. Zero (default) means machine precision.
    which : {'LM', 'SM'}
        Which `k` singular values to find: either the largest magnitude ('LM')
        or smallest magnitude ('SM') singular values.
    v0 : ndarray, optional
        The starting vector for iteration; see method-specific
        documentation (:ref:`'arpack' <sparse.linalg.svds-arpack>`,
        :ref:`'lobpcg' <sparse.linalg.svds-lobpcg>`), or
        :ref:`'propack' <sparse.linalg.svds-propack>` for details.
    maxiter : int, optional
        Maximum number of iterations; see method-specific
        documentation (:ref:`'arpack' <sparse.linalg.svds-arpack>`,
        :ref:`'lobpcg' <sparse.linalg.svds-lobpcg>`), or
        :ref:`'propack' <sparse.linalg.svds-propack>` for details.
    return_singular_vectors : {True, False, "u", "vh"}
        Singular values are always computed and returned; this parameter
        controls the computation and return of singular vectors.

        - ``True``: return singular vectors.
        - ``False``: do not return singular vectors.
        - ``"u"``: if ``M <= N``, compute only the left singular vectors and
          return ``None`` for the right singular vectors. Otherwise, compute
          all singular vectors.
        - ``"vh"``: if ``M > N``, compute only the right singular vectors and
          return ``None`` for the left singular vectors. Otherwise, compute
          all singular vectors.

        If ``solver='propack'``, the option is respected regardless of the
        matrix shape.

    solver :  {'arpack', 'propack', 'lobpcg'}, optional
            The solver used.
            :ref:`'arpack' <sparse.linalg.svds-arpack>`,
            :ref:`'lobpcg' <sparse.linalg.svds-lobpcg>`, and
            :ref:`'propack' <sparse.linalg.svds-propack>` are supported.
            Default: `'arpack'`.
    random_state : {None, int, `numpy.random.Generator`,
                    `numpy.random.RandomState`}, optional

        Pseudorandom number generator state used to generate resamples.

        If `random_state` is ``None`` (or `np.random`), the
        `numpy.random.RandomState` singleton is used.
        If `random_state` is an int, a new ``RandomState`` instance is used,
        seeded with `random_state`.
        If `random_state` is already a ``Generator`` or ``RandomState``
        instance then that instance is used.
    options : dict, optional
        A dictionary of solver-specific options. No solver-specific options
        are currently supported; this parameter is reserved for future use.

    Returns
    -------
    u : ndarray, shape=(M, k)
        Unitary matrix having left singular vectors as columns.
    s : ndarray, shape=(k,)
        The singular values.
    vh : ndarray, shape=(k, N)
        Unitary matrix having right singular vectors as rows.

    Notes
    -----
    This is a naive implementation using ARPACK or LOBPCG as an eigensolver
    on ``A.conj().T @ A`` or ``A @ A.conj().T``, depending on which one is more
    efficient, followed by the Rayleigh-Ritz method as postprocessing; see
    https://w.wiki/4zms

    Alternatively, the PROPACK solver can be called. ``form="array"``

    Choices of the input matrix ``A`` numeric dtype may be limited.
    Only ``solver="lobpcg"`` supports all floating point dtypes
    real: 'np.single', 'np.double', 'np.longdouble' and
    complex: 'np.csingle', 'np.cdouble', 'np.clongdouble'.
    The ``solver="arpack"`` supports only
    'np.single', 'np.double', and 'np.cdouble'.

    Examples
    --------
    Construct a matrix ``A`` from singular values and vectors.

    >>> from scipy.stats import ortho_group
    >>> from scipy.sparse import csc_matrix, diags
    >>> from scipy.sparse.linalg import svds
    >>> rng = np.random.default_rng()
    >>> orthogonal = csc_matrix(ortho_group.rvs(10, random_state=rng))
    >>> s = [0.0001, 0.001, 3, 4, 5]  # singular values
    >>> u = orthogonal[:, :5]         # left singular vectors
    >>> vT = orthogonal[:, 5:].T      # right singular vectors
    >>> A = u @ diags(s) @ vT

    With only three singular values/vectors, the SVD approximates the original
    matrix.

    >>> u2, s2, vT2 = svds(A, k=3)
    >>> A2 = u2 @ np.diag(s2) @ vT2
    >>> np.allclose(A2, A.toarray(), atol=1e-3)
    True

    With all five singular values/vectors, we can reproduce the original
    matrix.

    >>> u3, s3, vT3 = svds(A, k=5)
    >>> A3 = u3 @ np.diag(s3) @ vT3
    >>> np.allclose(A3, A.toarray())
    True

    The singular values match the expected singular values, and the singular
    vectors are as expected up to a difference in sign.

    >>> (np.allclose(s3, s) and
    ...  np.allclose(np.abs(u3), np.abs(u.toarray())) and
    ...  np.allclose(np.abs(vT3), np.abs(vT.toarray())))
    True

    The singular vectors are also orthogonal.
    >>> (np.allclose(u3.T @ u3, np.eye(5)) and
    ...  np.allclose(vT3 @ vT3.T, np.eye(5)))
    True

    Nr   FTr!   r   c                        | S r   r   r   )XH_dotX_dotr   r   matvec_XH_X     zsvds.<locals>.matvec_XH_Xc                    r=   r   r   r   )XH_matX_matmatr   r   matmat_XH_X  rA   zsvds.<locals>.matmat_XH_X)matvecr!   matmatr%   r   )r   4   )size   )r/   r2   largestr   z`solver='propack'` is opt-in due to potential issues on Windows, it can be enabled by setting the `SCIPY_USE_PROPACK` environment variable before importing scipy>   Tr   >   Tr   r   )
r-   r/   r0   r2   	compute_u	compute_virl_moder8   r1   r5   rG   r   )r-   r/   r2   r.   r0   r1   )
compute_uvoverwrite_a)full_matricesrP   )r;   r%   rE   rF   rmatvecrmatmatgetattrdotr   zerosr!   r   r&   reshaperandomRandomStaterandnuniformr   linalgqrHAS_PROPACKr   r
   r   r   r   )!r,   r-   r.   r/   r0   r1   r2   return_singular_vectorsr4   r5   optionsrs_was_NoneargsrK   nm	transposer!   r@   rD   XH_XX_eigvecjobujobvrN   resr   sr   Avu_tmpr   )r>   rB   r?   rC   r   r   h   s    





)
r<   Nr   r   NNTr   NN)osnumpyr   r   r    r   scipy._lib._utilr   scipy.sparse.linalg._interfacer   r   !scipy.sparse.linalg._eigen.lobpcgr   environgetscipy.sparse.linalg._svdpr
   r^   scipy.linalgr   timingnbxr!   
arpack_int__all__r   r;   r   r   r   r   r   <module>   s(    
O