U
    “PÓh…  ã                   @  sd   d dl mZ d dlmZ d dlZd dlmZ ddddœdd„Zddd	œd
d„ZG dd„ dejƒZ	dS )é    )Úannotations)ÚCallableN)Únnútorch.Tensor)Úx1Úx2Úreturnc                 C  s@   t  | ¡r.t  |¡stdƒ‚t  |  ¡ | ¡S t  | | ¡S dS )zD
    Complex dot product between tensors x1 and x2: sum(x1.*x2)
    zx1 and x2 must both be complexN)ÚtorchÚ
is_complexÚAssertionErrorÚsumÚconj)r   r   © r   ú]/home/dell461/cl/sdc2/HISourceFinder-master-l/src/monai/networks/layers/conjugate_gradient.pyÚ_zdot   s    
r   )Úxr   c                 C  s"   t | | ƒ}t |¡r|jS |S dS )z9
    Complex dot product between tensor x and itself
    N)r   r	   r
   Úreal)r   Úresr   r   r   Ú_zdot_single   s    

r   c                      sP   e Zd ZdZdddœ‡ fdd„Zdddddd	œd
d„Zddddœdd„Z‡  ZS )ÚConjugateGradientaÍ  
    Congugate Gradient (CG) solver for linear systems Ax = y.

    For linear_op that is positive definite and self-adjoint, CG is
    guaranteed to converge CG is often used to solve linear systems of the form
    Ax = y, where A is too large to store explicitly, but can be computed via a
    linear operator.

    As a result, here we won't set A explicitly as a matrix, but rather as a
    linear operator. For example, A could be a FFT/IFFT operation
    r   Úint)Ú	linear_opÚnum_iterc                   s   t ƒ  ¡  || _|| _dS )zs
        Args:
            linear_op: Linear operator
            num_iter: Number of iterations to run CG
        N)ÚsuperÚ__init__r   r   )Úselfr   r   ©Ú	__class__r   r   r   7   s    
zConjugateGradient.__init__r   z=tuple[torch.Tensor, torch.Tensor, torch.Tensor, torch.Tensor])r   ÚpÚrÚrsoldr   c           
      C  s`   |   |¡}t||ƒ}|| }|||  }|||  }t|ƒ}|| }	|}|	| | }||||fS )a9  
        perform one iteration of the CG method. It takes the current solution x,
        the current search direction p, the current residual r, and the old
        residual norm rsold as inputs. Then it computes the new solution, search
        direction, residual, and residual norm, and returns them.
        )r   r   r   )
r   r   r   r   r    ÚdyZp_dot_dyÚalphaZrsnewÚbetar   r   r   ÚupdateB   s    


zConjugateGradient.update)r   Úyr   c                 C  sR   ||   |¡ }t|ƒ}|}t| jƒD ](}|  ||||¡\}}}}|dk r$ qNq$|S )a  
        run conjugate gradient for num_iter iterations to solve Ax = y

        Args:
            x: tensor (real or complex); Initial guess for linear system Ax = y.
            The size of x should be applicable to the linear operator. For
            example, if the linear operator is FFT, then x is HCHW; if the
            linear operator is a matrix multiplication, then x is a vector

            y: tensor (real or complex); Measurement. Same size as x

        Returns:
            x: Solution to Ax = y
        g»½×Ùß|Û=)r   r   Úranger   r$   )r   r   r%   r   r    r   Ú_ir   r   r   ÚforwardW   s    zConjugateGradient.forward)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r$   r(   Ú__classcell__r   r   r   r   r   *   s   r   )
Ú
__future__r   Útypingr   r	   r   r   r   ÚModuler   r   r   r   r   Ú<module>   s   