o
    .wi                     @   s   d dl Z d dl mZ d dlmZ d dlmZ ddededed	eeef fd
dZdeded	efddZ	ddededed	efddZ
dS )    N)Tensor)_check_same_shape)_safe_xlogy        predstargetspowerreturnc           
      C   s2  t | | tj| j| jd}d|  k rdk r"n ntd| d|dkr0tj||  dd}n|dkrXt| dksBt|dk rJtd| d	dt|||  |  |  }n|dkrt| dksjt|dkrrtd| d
dt	| | ||   d  }n|dk rt| dkrtd| dn9d|  k rdk rn nt| dkst|dk rtd| dnt| dkst|dkrtd| d
tt
||d| d| d|   }|t| d|  d|  }t| d| d|  }d|| |  }t|}tjt|| jd}	||	fS )a  Update and returns variables required to compute Deviance Score for the given power.

    Check for same shape of input tensors.

    Args:
        preds: Predicted tensor
        targets: Ground truth tensor
        power: see :func:`tweedie_deviance_score`

    Example:
        >>> targets = torch.tensor([1.0, 2.0, 3.0, 4.0])
        >>> preds = torch.tensor([4.0, 3.0, 2.0, 1.0])
        >>> _tweedie_deviance_score_update(preds, targets, power=2)
        (tensor(4.8333), tensor(4))

    )devicer      z(Deviance Score is not defined for power=.   )exponentz
For power=zG, 'preds' has to be strictly positive and 'targets' cannot be negative.z:, both 'preds' and 'targets' have to be strictly positive.z&, 'preds' has to be strictly positive.zG, 'targets' has to be strictly positive and 'preds' cannot be negative.)r   torchzerosshaper
   
ValueErrorpowanyr   logmaxsumtensornumel)
r   r   r   zero_tensordeviance_scoreterm_1term_2term_3sum_deviance_scorenum_observations r!   p/home/ubuntu/sommelier/.venv/lib/python3.10/site-packages/torchmetrics/functional/regression/tweedie_deviance.py_tweedie_deviance_score_update   sF   

 
(
r#   r   r    c                 C   s   | | S )a  Compute Deviance Score.

    Args:
        sum_deviance_score: Sum of deviance scores accumulated until now.
        num_observations: Number of observations encountered until now.

    Example:
        >>> targets = torch.tensor([1.0, 2.0, 3.0, 4.0])
        >>> preds = torch.tensor([4.0, 3.0, 2.0, 1.0])
        >>> sum_deviance_score, num_observations = _tweedie_deviance_score_update(preds, targets, power=2)
        >>> _tweedie_deviance_score_compute(sum_deviance_score, num_observations)
        tensor(1.2083)

    r!   )r   r    r!   r!   r"   _tweedie_deviance_score_computeV   s   r$   c                 C   s   t | ||d\}}t||S )a  Compute the `Tweedie Deviance Score`_.

    .. math::
        deviance\_score(\hat{y},y) =
        \begin{cases}
        (\hat{y} - y)^2, & \text{for }p=0\\
        2 * (y * log(\frac{y}{\hat{y}}) + \hat{y} - y),  & \text{for }p=1\\
        2 * (log(\frac{\hat{y}}{y}) + \frac{y}{\hat{y}} - 1),  & \text{for }p=2\\
        2 * (\frac{(max(y,0))^{2 - p}}{(1 - p)(2 - p)} - \frac{y(\hat{y})^{1 - p}}{1 - p} + \frac{(
            \hat{y})^{2 - p}}{2 - p}), & \text{otherwise}
        \end{cases}

    where :math:`y` is a tensor of targets values, :math:`\hat{y}` is a tensor of predictions, and
    :math:`p` is the `power`.

    Args:
        preds: Predicted tensor with shape ``(N,...)``
        targets: Ground truth tensor with shape ``(N,...)``
        power:
            - `power < 0` : Extreme stable distribution. (Requires: preds > 0.)
            - `power = 0` : Normal distribution. (Requires: targets and preds can be any real numbers.)
            - `power = 1` : Poisson distribution. (Requires: targets >= 0 and y_pred > 0.)
            - `1 < p < 2` : Compound Poisson distribution. (Requires: targets >= 0 and preds > 0.)
            - `power = 2` : Gamma distribution. (Requires: targets > 0 and preds > 0.)
            - `power = 3` : Inverse Gaussian distribution. (Requires: targets > 0 and preds > 0.)
            - `otherwise` : Positive stable distribution. (Requires: targets > 0 and preds > 0.)

    Example:
        >>> from torchmetrics.functional.regression import tweedie_deviance_score
        >>> targets = torch.tensor([1.0, 2.0, 3.0, 4.0])
        >>> preds = torch.tensor([4.0, 3.0, 2.0, 1.0])
        >>> tweedie_deviance_score(preds, targets, power=2)
        tensor(1.2083)

    )r   )r#   r$   )r   r   r   r   r    r!   r!   r"   tweedie_deviance_scoreh   s   $
r%   )r   )r   r   torchmetrics.utilities.checksr   torchmetrics.utilities.computer   floattupler#   r$   r%   r!   r!   r!   r"   <module>   s   $@ 