a
    dk                     @   sh   d dl Z d dlmZ d dlm  mZ d dlmZ d	e je je	e	e	e jdddZ
G dd dejZdS )
    N)one_hot:0yE>)inputtargetalphabetaepsreturnc                 C   s0  t | tjstdt|  t| jdks<td| j | jdd |jdd ksptd| j d| j | j|jkstd| j d|j t	j
| d	d
}t|| jd	 | j| jd}d}t|| |}t|| d  |}	t| d | |}
|}|||	  ||
  }|||  }t| d S )ud  Criterion that computes Tversky Coefficient loss.

    According to :cite:`salehi2017tversky`, we compute the Tversky Coefficient as follows:

    .. math::

        \text{S}(P, G, \alpha; \beta) =
          \frac{|PG|}{|PG| + \alpha |P \setminus G| + \beta |G \setminus P|}

    Where:
       - :math:`P` and :math:`G` are the predicted and ground truth binary
         labels.
       - :math:`\alpha` and :math:`\beta` control the magnitude of the
         penalties for FPs and FNs, respectively.

    Note:
       - :math:`\alpha = \beta = 0.5` => dice coeff
       - :math:`\alpha = \beta = 1` => tanimoto coeff
       - :math:`\alpha + \beta = 1` => F beta coeff

    Args:
        input: logits tensor with shape :math:`(N, C, H, W)` where C = number of classes.
        target: labels tensor with shape :math:`(N, H, W)` where each value
          is :math:`0 ≤ targets[i] ≤ C−1`.
        alpha: the first coefficient in the denominator.
        beta: the second coefficient in the denominator.
        eps: scalar for numerical stability.

    Return:
        the computed loss.

    Example:
        >>> N = 5  # num_classes
        >>> input = torch.randn(1, N, 3, 5, requires_grad=True)
        >>> target = torch.empty(1, 3, 5, dtype=torch.long).random_(N)
        >>> output = tversky_loss(input, target, alpha=0.5, beta=0.5)
        >>> output.backward()
    z&Input type is not a torch.Tensor. Got    z-Invalid input shape, we expect BxNxHxW. Got: Nz/input and target shapes must be the same. Got: z and z2input and target must be in the same device. Got:    )Zdim)Znum_classesdevicedtype)r         g      ?)
isinstancetorchTensor	TypeErrortypelenshape
ValueErrorr   FZsoftmaxr   r   summean)r   r   r   r   r   Z
input_softZtarget_one_hotdimsintersectionZfpsfns	numeratordenominatortversky_loss r"   ^/var/www/html/stable-diffusion-webui/venv/lib/python3.9/site-packages/kornia/losses/tversky.pyr!      s$    )r!   c                       sF   e Zd ZdZd
eeedd fddZejejejddd	Z  Z	S )TverskyLossu<  Criterion that computes Tversky Coefficient loss.

    According to :cite:`salehi2017tversky`, we compute the Tversky Coefficient as follows:

    .. math::

        \text{S}(P, G, \alpha; \beta) =
          \frac{|PG|}{|PG| + \alpha |P \setminus G| + \beta |G \setminus P|}

    Where:
       - :math:`P` and :math:`G` are the predicted and ground truth binary
         labels.
       - :math:`\alpha` and :math:`\beta` control the magnitude of the
         penalties for FPs and FNs, respectively.

    Note:
       - :math:`\alpha = \beta = 0.5` => dice coeff
       - :math:`\alpha = \beta = 1` => tanimoto coeff
       - :math:`\alpha + \beta = 1` => F beta coeff

    Args:
        alpha: the first coefficient in the denominator.
        beta: the second coefficient in the denominator.
        eps: scalar for numerical stability.

    Shape:
        - Input: :math:`(N, C, H, W)` where C = number of classes.
        - Target: :math:`(N, H, W)` where each value is
          :math:`0 ≤ targets[i] ≤ C−1`.

    Examples:
        >>> N = 5  # num_classes
        >>> criterion = TverskyLoss(alpha=0.5, beta=0.5)
        >>> input = torch.randn(1, N, 3, 5, requires_grad=True)
        >>> target = torch.empty(1, 3, 5, dtype=torch.long).random_(N)
        >>> output = criterion(input, target)
        >>> output.backward()
    r   N)r   r   r   r	   c                    s    t    || _|| _|| _d S N)super__init__r   r   r   )selfr   r   r   	__class__r"   r#   r'   {   s    
zTverskyLoss.__init__)r   r   r	   c                 C   s   t ||| j| j| jS r%   )r!   r   r   r   )r(   r   r   r"   r"   r#   forward   s    zTverskyLoss.forward)r   )
__name__
__module____qualname____doc__floatr'   r   r   r+   __classcell__r"   r"   r)   r#   r$   S   s   'r$   )r   )r   Ztorch.nnnnZtorch.nn.functionalZ
functionalr   Zkornia.utils.one_hotr   r   r0   r!   Moduler$   r"   r"   r"   r#   <module>   s    H