o
    &?e~w                     @   s8  d Z g dZddlZddlm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 dd
lmZ dddddZdZdZdd Zdd Zd4ddZedddde d5dd Zed!d"d#de d5d$d%Zed&d'd(de d5d)d*Zed+d,d-de d5d.d/Ze 		d6d0d1Ze 		d7d2d3ZdS )8z,Iterative methods for solving linear systems)bicgbicgstabcgcgsgmresqmr    N)dedent   )
_iterative)LinearOperator)make_system)_aligned_zeros)non_reentrantsdcz)fr   FDzC
Parameters
----------
A : {sparse matrix, ndarray, LinearOperator}aX  b : ndarray
    Right hand side of the linear system. Has shape (N,) or (N,1).

Returns
-------
x : ndarray
    The converged solution.
info : integer
    Provides convergence information:
        0  : successful exit
        >0 : convergence to tolerance not achieved, number of iterations
        <0 : illegal input or breakdown

Other Parameters
----------------
x0 : ndarray
    Starting guess for the solution.
tol, atol : float, optional
    Tolerances for convergence, ``norm(residual) <= max(tol*norm(b), atol)``.
    The default for ``atol`` is ``'legacy'``, which emulates
    a different legacy behavior.

    .. warning::

       The default value for `atol` will be changed in a future release.
       For future compatibility, specify `atol` explicitly.
maxiter : integer
    Maximum number of iterations.  Iteration will stop after maxiter
    steps even if the specified tolerance has not been achieved.
M : {sparse matrix, ndarray, LinearOperator}
    Preconditioner for A.  The preconditioner should approximate the
    inverse of A.  Effective preconditioning dramatically improves the
    rate of convergence, which implies that fewer iterations are needed
    to reach a given error tolerance.
callback : function
    User-supplied function to call after each iteration.  It is called
    as callback(xk), where xk is the current solution vector.
c                 C   s$   t j| }||kr|dfS |dfS )z;
    Successful termination condition for the solvers.
    r	   r   nplinalgnorm)Zresidualatolresid r   f/home/www/facesmatcher.com/pyenv/lib/python3.10/site-packages/scipy/sparse/linalg/_isolve/iterative.py	_stoptestC   s   r   c                 C   st   |du rt jdj|dtdd d}t| } |dkr/| }|| kr#dS |dkr)| S | t| S tt|| t| S )	a  
    Parse arguments for absolute tolerance in termination condition.

    Parameters
    ----------
    tol, atol : object
        The arguments passed into the solver routine by user.
    bnrm2 : float
        2-norm of the rhs vector.
    get_residual : callable
        Callable ``get_residual()`` that returns the initial value of
        the residual.
    routine_name : str
        Name of the routine.
    Na	  scipy.sparse.linalg.{name} called without specifying `atol`. The default value will be changed in a future release. For compatibility, specify a value for `atol` explicitly, e.g., ``{name}(..., atol=0)``, or to retain the old behavior ``{name}(..., atol='legacy')``)name   category
stacklevellegacyexitr   )warningswarnformatDeprecationWarningfloatmax)tolr   bnrm2get_residualZroutine_namer   r   r   r   	_get_atolN   s    r/    0c                    s    fdd}|S )Nc              	      s*   d td dd ttf| _| S )N
z    z
    )joincommon_doc1replacecommon_doc2r   __doc__)fnAinfofooterheaderr   r   combinex   s
   zset_docstring.<locals>.combiner   )r<   r:   r;   Zatol_defaultr=   r   r9   r   set_docstringw   s   r>   z7Use BIConjugate Gradient iteration to solve ``Ax = b``.zThe real or complex N-by-N matrix of the linear system.
Alternatively, ``A`` can be a linear operator which can
produce ``Ax`` and ``A^T x`` using, e.g.,
``scipy.sparse.linalg.LinearOperator``.a1                 Examples
               --------
               >>> import numpy as np
               >>> from scipy.sparse import csc_matrix
               >>> from scipy.sparse.linalg import bicg
               >>> A = csc_matrix([[3, 2, 0], [1, -1, 0], [0, 5, 1]], dtype=float)
               >>> b = np.array([2, 4, -1], dtype=float)
               >>> x, exitCode = bicg(A, b)
               >>> print(exitCode)            # 0 indicates successful convergence
               0
               >>> np.allclose(A.dot(x), b)
               True

               )r;   h㈵>c              
      s  t | || \} } }t }	|d u r|	d }| j| j}
|j|j}}tjj }tt|d } fdd}t	||t
j |d}|dkrQ|dfS |}d}d	}td
|	 jd}d}d}d}|}	 |}| |||||||	\	}}}}}}}}|d ur||kr| t|d |d |	 }t|d |d |	 }|d	kr|d ur| q3|dkr||  |9  < ||  |||  7  < ne|dkr||  |9  < ||  ||
||  7  < nJ|dkr||| ||< n=|dkr||| ||< n/|dkr||  |9  < ||  | 7  < n|d
kr0|r'd	}d}t|| |\}}d}qi|dkrD||krD||ksD|}||fS )N
   Z
bicgrevcomc                         t j  S Nr   r   bmatvecxr   r   r.         zbicg.<locals>.get_residualr   r%   r   r	      dtypeT      r       F)r   lenrE   rmatvec
_type_convrK   chargetattrr
   r/   r   r   r   r   slicer   )ArD   x0r,   maxiterMcallbackr   postprocessnrP   psolverpsolveltrrevcomr.   r   ndx1ndx2workijobinfoftflagiter_olditersclr1sclr2slice1slice2r   rC   r   r      sn   


 r   zBUse BIConjugate Gradient STABilized iteration to solve ``Ax = b``.zThe real or complex N-by-N matrix of the linear system.
Alternatively, ``A`` can be a linear operator which can
produce ``Ax`` using, e.g.,
``scipy.sparse.linalg.LinearOperator``.a                 Examples
               --------
               >>> import numpy as np
               >>> from scipy.sparse import csc_matrix
               >>> from scipy.sparse.linalg import bicgstab
               >>> R = np.array([[4, 2, 0, 1],
               ...               [3, 0, 0, 2],
               ...               [0, 1, 1, 1],
               ...               [0, 2, 1, 0]])
               >>> A = csc_matrix(R)
               >>> b = np.array([-1, -0.5, -1, 2])
               >>> x, exit_code = bicgstab(A, b)
               >>> print(exit_code)  # 0 indicates successful convergence
               0
               >>> np.allclose(A.dot(x), b)
               True
               c              
      s*  t | || \} } }t }	|d u r|	d }| j|j}
tjj }tt|d } fdd}t||t	j
 |d}|dkrI|dfS |}d}d	}td
|	 jd}d}d}d}|}	 |}| |||||||	\	}}}}}}}}|d ur||kr| t|d |d |	 }t|d |d |	 }|d	kr|d ur| q|dkr||  |9  < ||  |||  7  < n9|dkr|
|| ||< n,|dkr||  |9  < ||  | 7  < n|dkr|rd	}d}t|| |\}}d}qa|dkr||kr||ks|}||fS )Nr@   Zbicgstabrevcomc                      rA   rB   r   r   rC   r   r   r.      rG   zbicgstab.<locals>.get_residualr   r%   r   r	   rH      rJ   TrL   rM   r    Fr   rO   rE   rQ   rK   rR   rS   r
   r/   r   r   r   r   rT   r   rU   rD   rV   r,   rW   rX   rY   r   rZ   r[   r\   r^   r_   r.   r   r`   ra   rb   rc   rd   re   rf   rg   rh   ri   rj   rk   r   rC   r   r      sd   r   z5Use Conjugate Gradient iteration to solve ``Ax = b``.zThe real or complex N-by-N matrix of the linear system.
``A`` must represent a hermitian, positive definite matrix.
Alternatively, ``A`` can be a linear operator which can
produce ``Ax`` using, e.g.,
``scipy.sparse.linalg.LinearOperator``.a                 Examples
               --------
               >>> import numpy as np
               >>> from scipy.sparse import csc_matrix
               >>> from scipy.sparse.linalg import cg
               >>> P = np.array([[4, 0, 1, 0],
               ...               [0, 5, 0, 0],
               ...               [1, 0, 3, 2],
               ...               [0, 0, 2, 4]])
               >>> A = csc_matrix(P)
               >>> b = np.array([-1, -0.5, -1, 2])
               >>> x, exit_code = cg(A, b)
               >>> print(exit_code)    # 0 indicates successful convergence
               0
               >>> np.allclose(A.dot(x), b)
               True

               c              
      sd  t | || \} } }t }	|d u r|	d }| j|j}
tjj }tt|d } fdd}t||t	j
 |d}|dkrI|dfS |}d}d	}td
|	 jd}d}d}d}|}	 |}| |||||||	\	}}}}}}}}|d ur||kr| t|d |d |	 }t|d |d |	 }|d	kr|d ur| q|dkr||  |9  < ||  |||  7  < nU|dkr|
|| ||< nH|dkr||  |9  < ||  | 7  < n/|d
kr|rd	}d}t|| |\}}|dkr|dkr  ||< t|| |\}}d}qa|dkr,||kr,||ks,|}||fS )Nr@   Zcgrevcomc                      rA   rB   r   r   rC   r   r   r.   T  rG   zcg.<locals>.get_residualr   r%   r   r	   rH   r    rJ   TrL   rM   Frm   rn   r   rC   r   r   .  sj   
 r   z=Use Conjugate Gradient Squared iteration to solve ``Ax = b``.zThe real-valued N-by-N matrix of the linear system.
Alternatively, ``A`` can be a linear operator which can
produce ``Ax`` using, e.g.,
``scipy.sparse.linalg.LinearOperator``.a                 Examples
               --------
               >>> import numpy as np
               >>> from scipy.sparse import csc_matrix
               >>> from scipy.sparse.linalg import cgs
               >>> R = np.array([[4, 2, 0, 1],
               ...               [3, 0, 0, 2],
               ...               [0, 1, 1, 1],
               ...               [0, 2, 1, 0]])
               >>> A = csc_matrix(R)
               >>> b = np.array([-1, -0.5, -1, 2])
               >>> x, exit_code = cgs(A, b)
               >>> print(exit_code)  # 0 indicates successful convergence
               0
               >>> np.allclose(A.dot(x), b)
               True
               c              
      s  t | || \} } }t }	|d u r|	d }| j|j}
tjj }tt|d } fdd}t||t	j
 |d}|dkrI|dfS |}d}d	}td
|	 jd}d}d}d}|}	 |}| |||||||	\	}}}}}}}}|d ur||kr| t|d |d |	 }t|d |d |	 }|d	kr|d ur| q|dkr||  |9  < ||  |||  7  < nU|dkr|
|| ||< nH|dkr||  |9  < ||  | 7  < n/|dkr|rd	}d}t|| |\}}|dkr|dkr  ||< t|| |\}}d}qa|dkr0t  |\}}|r0d}|dkrA||krA||ksA|}||fS )Nr@   Z	cgsrevcomc                      rA   rB   r   r   rC   r   r   r.     rG   zcgs.<locals>.get_residualr   r%   r   r	   rH   rl   rJ   TrL   rM   r    Firm   )rU   rD   rV   r,   rW   rX   rY   r   rZ   r[   r\   r^   r_   r.   r   r`   ra   rb   rc   rd   re   rf   rg   rh   ri   rj   rk   okr   rC   r   r     sr   

 r   c           )         s  |du r|}n|durt dd}tj|tdd |dur)|
du r)tjdtdd |
du r/d	}
|
d
vr:t d|
|du r@d}
t| || \} } }t }|du rX|d }|du r^d}t||}| j|j}tj	j
 }tt|d }tj }tj| } fdd}t||	||d}	|	dkr|dfS |dkr| dfS d}|t||	|  }tj}tj}d}d}td| | j	d}t|d d| d  j	d}d}d}d}|}|} d}!d}"d}#	 |}$| ||||||||||\	}}}}}}%}&}|
dkr||$kr| t|d |d | }'t|d |d | }(|dkrE|
dv r:|"r9|||  n	|
dkrC| q|dkr_||(  |&9  < ||(  |% 7  < n|dkry|||( ||'< |!sv| dkrvd}"d}!no|dkr||(  |&9  < ||(  |%||'  7  < |"r|
dv r|||  d}"|#d }#n?|dkr|rd}d}t||' |	\}}|s||krtdd| }ntd d!| }|dkr|t||	|  }n|| }|} d}|
d	kr|#|kr|}qq|dkr||	ks|}||fS )"aU  
    Use Generalized Minimal RESidual iteration to solve ``Ax = b``.

    Parameters
    ----------
    A : {sparse matrix, ndarray, LinearOperator}
        The real or complex N-by-N matrix of the linear system.
        Alternatively, ``A`` can be a linear operator which can
        produce ``Ax`` using, e.g.,
        ``scipy.sparse.linalg.LinearOperator``.
    b : ndarray
        Right hand side of the linear system. Has shape (N,) or (N,1).

    Returns
    -------
    x : ndarray
        The converged solution.
    info : int
        Provides convergence information:
          * 0  : successful exit
          * >0 : convergence to tolerance not achieved, number of iterations
          * <0 : illegal input or breakdown

    Other parameters
    ----------------
    x0 : ndarray
        Starting guess for the solution (a vector of zeros by default).
    tol, atol : float, optional
        Tolerances for convergence, ``norm(residual) <= max(tol*norm(b), atol)``.
        The default for ``atol`` is ``'legacy'``, which emulates
        a different legacy behavior.

        .. warning::

           The default value for `atol` will be changed in a future release.
           For future compatibility, specify `atol` explicitly.
    restart : int, optional
        Number of iterations between restarts. Larger values increase
        iteration cost, but may be necessary for convergence.
        Default is 20.
    maxiter : int, optional
        Maximum number of iterations (restart cycles).  Iteration will stop
        after maxiter steps even if the specified tolerance has not been
        achieved.
    M : {sparse matrix, ndarray, LinearOperator}
        Inverse of the preconditioner of A.  M should approximate the
        inverse of A and be easy to solve for (see Notes).  Effective
        preconditioning dramatically improves the rate of convergence,
        which implies that fewer iterations are needed to reach a given
        error tolerance.  By default, no preconditioner is used.
        In this implementation, left preconditioning is used,
        and the preconditioned residual is minimized.
    callback : function
        User-supplied function to call after each iteration.  It is called
        as `callback(args)`, where `args` are selected by `callback_type`.
    callback_type : {'x', 'pr_norm', 'legacy'}, optional
        Callback function argument requested:
          - ``x``: current iterate (ndarray), called on every restart
          - ``pr_norm``: relative (preconditioned) residual norm (float),
            called on every inner iteration
          - ``legacy`` (default): same as ``pr_norm``, but also changes the
            meaning of 'maxiter' to count inner iterations instead of restart
            cycles.
    restrt : int, optional, deprecated

        .. deprecated:: 0.11.0
           `gmres` keyword argument `restrt` is deprecated infavour of
           `restart` and will be removed in SciPy 1.12.0.

    See Also
    --------
    LinearOperator

    Notes
    -----
    A preconditioner, P, is chosen such that P is close to A but easy to solve
    for. The preconditioner parameter required by this routine is
    ``M = P^-1``. The inverse should preferably not be calculated
    explicitly.  Rather, use the following template to produce M::

      # Construct a linear operator that computes P^-1 @ x.
      import scipy.sparse.linalg as spla
      M_x = lambda x: spla.spsolve(P, x)
      M = spla.LinearOperator((n, n), M_x)

    Examples
    --------
    >>> import numpy as np
    >>> from scipy.sparse import csc_matrix
    >>> from scipy.sparse.linalg import gmres
    >>> A = csc_matrix([[3, 2, 0], [1, -1, 0], [0, 5, 1]], dtype=float)
    >>> b = np.array([2, 4, -1], dtype=float)
    >>> x, exitCode = gmres(A, b)
    >>> print(exitCode)            # 0 indicates successful convergence
    0
    >>> np.allclose(A.dot(x), b)
    True
    NzOCannot specify both restart and restrt keywords. Preferably use 'restart' only.zj'gmres' keyword argument 'restrt' is deprecated infavour of 'restart' and will be removed in SciPy 1.12.0.rL   )r#   a4  scipy.sparse.linalg.gmres called without specifying `callback_type`. The default value will be changed in a future release. For compatibility, specify a value for `callback_type` explicitly, e.g., ``{name}(..., callback_type='pr_norm')``, or to retain the old behavior ``{name}(..., callback_type='legacy')``rM   r!   r$   )rF   pr_normr$   zUnknown callback_type: noner@      Zgmresrevcomc                      rA   rB   r   r   rC   r   r   r.     rG   zgmres.<locals>.get_residualr   r%   r   g      ?r	   rH   rI   rJ   TFrF   )rp   r$   r    g      ?gؗҜ<g      ?)
ValueErrorr&   r'   r)   r   rO   minrE   rQ   rK   rR   rS   r
   r   r   r   r/   nanr   rT   r   r+   ))rU   rD   rV   r,   ZrestartrW   rX   rY   Zrestrtr   Zcallback_typemsgrZ   r[   r\   r^   r_   r-   ZMb_nrm2r.   Zptol_max_factorZptolr   Zpresidr`   ra   rb   Zwork2rc   rd   re   rf   Zold_ijobZ
first_passZresid_readyZiter_numrg   rh   ri   rj   rk   r   rC   r   r     s   g











<r   c	           !   
      sZ   t  d|\ }	}
|du rX|du rXtdrDfdd}fdd}fdd}fd	d
}t j||d}t j||d}ndd }t j||d}t j||d}t}|du rd|d }tjj }tt	|d } fdd}t
||tj|d}|dkr|
dfS |}d}d}td| j}d}d}d}|}	 |}||||||||	\	}}}}}}}}|dur||kr| t|d |d | }t|d |d | } |dkr|dur| q|dkr
||   |9  < ||   | ||  7  < n|dkr'||   |9  < ||   | ||  7  < nl|dkr6|||  ||< n]|dkrE|||  ||< nN|dkrT|||  ||< n?|dkrc|||  ||< n0|dkr~||   |9  < ||   |  7  < n|dkr|rd}d }t|| |\}}d}q|dkr||kr||ks|}|
|fS )!a	  Use Quasi-Minimal Residual iteration to solve ``Ax = b``.

    Parameters
    ----------
    A : {sparse matrix, ndarray, LinearOperator}
        The real-valued N-by-N matrix of the linear system.
        Alternatively, ``A`` can be a linear operator which can
        produce ``Ax`` and ``A^T x`` using, e.g.,
        ``scipy.sparse.linalg.LinearOperator``.
    b : ndarray
        Right hand side of the linear system. Has shape (N,) or (N,1).

    Returns
    -------
    x : ndarray
        The converged solution.
    info : integer
        Provides convergence information:
            0  : successful exit
            >0 : convergence to tolerance not achieved, number of iterations
            <0 : illegal input or breakdown

    Other Parameters
    ----------------
    x0 : ndarray
        Starting guess for the solution.
    tol, atol : float, optional
        Tolerances for convergence, ``norm(residual) <= max(tol*norm(b), atol)``.
        The default for ``atol`` is ``'legacy'``, which emulates
        a different legacy behavior.

        .. warning::

           The default value for `atol` will be changed in a future release.
           For future compatibility, specify `atol` explicitly.
    maxiter : integer
        Maximum number of iterations.  Iteration will stop after maxiter
        steps even if the specified tolerance has not been achieved.
    M1 : {sparse matrix, ndarray, LinearOperator}
        Left preconditioner for A.
    M2 : {sparse matrix, ndarray, LinearOperator}
        Right preconditioner for A. Used together with the left
        preconditioner M1.  The matrix M1@A@M2 should have better
        conditioned than A alone.
    callback : function
        User-supplied function to call after each iteration.  It is called
        as callback(xk), where xk is the current solution vector.

    See Also
    --------
    LinearOperator

    Examples
    --------
    >>> import numpy as np
    >>> from scipy.sparse import csc_matrix
    >>> from scipy.sparse.linalg import qmr
    >>> A = csc_matrix([[3, 2, 0], [1, -1, 0], [0, 5, 1]], dtype=float)
    >>> b = np.array([2, 4, -1], dtype=float)
    >>> x, exitCode = qmr(A, b)
    >>> print(exitCode)            # 0 indicates successful convergence
    0
    >>> np.allclose(A.dot(x), b)
    True
    Nr\   c                         | dS Nleftr\   rD   A_r   r   left_psolve(     zqmr.<locals>.left_psolvec                    rw   Nrightrz   r{   r|   r   r   right_psolve+  r   zqmr.<locals>.right_psolvec                    rw   rx   r]   r{   r|   r   r   left_rpsolve.  r   zqmr.<locals>.left_rpsolvec                    rw   r   r   r{   r|   r   r   right_rpsolve1  r   zqmr.<locals>.right_rpsolve)rE   rP   c                 S   s   | S rB   r   r{   r   r   r   id6  s   zqmr.<locals>.idr@   Z	qmrrevcomc                      s   t j  S rB   )r   r   r   rE   r   )rU   rD   rF   r   r   r.   B  s   zqmr.<locals>.get_residualr   r%   r   r	   rH      TrL   rM   r    rN   rI   rl      F)r   hasattrr   shaperO   rQ   rK   rR   rS   r
   r/   r   r   r   r   rT   rE   rP   r   )!rU   rD   rV   r,   rW   ZM1ZM2rY   r   rX   rZ   r~   r   r   r   r   r[   r^   r_   r.   r   r`   ra   rb   rc   rd   re   rf   rg   rh   ri   rj   rk   r   )rU   r}   rD   rF   r   r     s   D

 
 





$r   )r0   r1   )Nr?   NNNN)	Nr?   NNNNNNN)Nr?   NNNNN)r7   __all__r&   textwrapr   numpyr   r0   r
   Zscipy.sparse.linalg._interfacer   utilsr   Zscipy._lib._utilr   Zscipy._lib._threadsafetyr   rQ   r4   r6   r   r/   r>   r   r   r   r   r   r   r   r   r   r   <module>   sf    )
)	B=BH t