U
    !?h                     @   s   d dl ZdddZdS )	    N        Hz>'  Fc	                    s   dkrdd }	nt  r  }	n fdd}	|dkr>t|n| }
tj|}t | rh|| |
 }n|| |
 }tj|}||k s||| k r|
S |	|}| }t||}t|D ]}| }t | r| |}n
| |}|t|| }|
|| 7 }
||| 8 }tj|}|dk	r6|| |
|||| ||k sN||| k rV|
  S |	|}|rt|| || }t||}nd| }t||}||9 }||9 }||7 }qt	d| dS )a  Solves a system of linear equations :math:`Ax=b` using conjugate gradient descent :cite:`hestenes1952methods`

    Parameters
    ----------
    A: scipy.sparse.csr_matrix
       Square matrix
    b: numpy.ndarray
       Vector describing the right-hand side of the system
    x0: numpy.ndarray
       Initialization, if `None` then :code:`x=np.zeros_like(b)`
    atol: float
       Absolute tolerance. The loop terminates if the :math:`||r||` is smaller than `atol`, where :math:`r` denotes the residual of the current iterate.
    rtol: float
       Relative tolerance. The loop terminates if :math:`{||r||}/{||b||}` is smaller than `rtol`, where :math:`r` denotes the residual of the current iterate.
    callback: function
       Function :code:`callback(A, x, b, norm_b, r, norm_r)` called after each iteration, defaults to `None`
    M: function or scipy.sparse.csr_matrix
       Function that applies the preconditioner to a vector. Alternatively, `M` can be a matrix describing the precondioner.
    reorthogonalize: boolean
        Whether to apply reorthogonalization of the residuals after each update, defaults to `False`


    Returns
    -------
    x: numpy.ndarray
        Solution of the system

    Example
    -------
    >>> from pymatting import *
    >>> import numpy as np
    >>> A = np.array([[3.0, 1.0], [1.0, 2.0]])
    >>> M = jacobi(A)
    >>> b = np.array([4.0, 3.0])
    >>> cg(A, b, M=M)
    array([1., 1.])
    Nc                 S   s   | S N xr   r   E/var/www/html/venv/lib/python3.8/site-packages/pymatting/solver/cg.pyprecondition6   s    zcg.<locals>.preconditionc                    s
     | S r   )dotr   Mr   r	   r
   =   s    g      ?z@Conjugate gradient descent did not converge within %d iterations)
callablenpZ
zeros_likecopyZlinalgZnormr   innerrange
ValueError)AbZx0ZatolZrtolmaxitercallbackr   Zreorthogonalizer
   r   Znorm_brZnorm_rzpZrz	iterationZr_oldZApalphabetar   r   r	   cg   sR    0




r   )Nr   r   r   NNF)numpyr   r   r   r   r   r	   <module>   s          