o
    .wi=                     @   s  d dl mZmZ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mZmZ d dlmZ G d	d
 d
eZG dd deZdededeeef fddZdedededefddZdededefddZdedededefddZdededefddZdGdededefdd Zdedeeeef fd!d"Zdeded#edeeeee ee ee ee ee ee ef	 fd$d%Zdeded&ed'ed(ed)ed*ee d+ee d#edefd,d-Zd.edefd/d0Z d(ed)ed*ee d1ee d2ee d+ee d3ee d4ee d#ed5ee defd6d7Z!			8dHdeded9eee  d:eee  d;edeee ee f fd<d=Z"	dIdeded#ed5ee deeee f f
d>d?Z#	@		AdJdeded#edB dCed5eedD  deeeeef f fdEdFZ$dS )K    )ListOptionalUnionN)Tensor)Literal) _check_data_shape_to_num_outputs)_check_same_shape)	_bincount_cumsumdim_zero_cat)EnumStrc                   @   .   e Zd ZdZdZdZdZedefddZ	dS )	_MetricVariantzEnumerate for metric variants.abcreturnc                   C      dS )Nvariant r   r   r   g/home/ubuntu/sommelier/.venv/lib/python3.10/site-packages/torchmetrics/functional/regression/kendall.py_name!      z_MetricVariant._nameN)
__name__
__module____qualname____doc__ABCstaticmethodstrr   r   r   r   r   r          r   c                   @   r   )	_TestAlternativez'Enumerate for test alternative options.	two-sidedlessgreaterr   c                   C   r   )Nalternativer   r   r   r   r   r   -   r   z_TestAlternative._nameN)
r   r   r   r   	TWO_SIDEDLESSGREATERr    r!   r   r   r   r   r   r#   &   r"   r#   xyr   c                 C   sX   t |}| j|j} }|  \} }t| jd D ]}|| ||  ||< q| j|jfS )zBSort sequences in an ascent order according to the sequence ``x``.r   )torchcloneTsortrangeshape)r+   r,   permir   r   r   _sort_on_first_sequence2   s   
r5   r4   c                 C   s@   t | | | |d d k || ||d d k ddS )z>Count a total number of concordant pairs in a single sequence.   Nr   )r-   logical_andsum	unsqueezer+   r,   r4   r   r   r   _concordant_element_sum=   s   @r;   predstargetc                    *   t  fddt jd D dS )z<Count a total number of concordant pairs in given sequences.c                       g | ]}t  |qS r   )r;   .0r4   r<   r=   r   r   
<listcomp>D       z+_count_concordant_pairs.<locals>.<listcomp>r   r-   catr1   r2   r8   rB   r   rB   r   _count_concordant_pairsB      *rG   c              
   C   sx   t t | | | |d d k|| ||d d k t | | | |d d k || ||d d kddS )z?Count a total number of discordant pairs in a single sequences.r6   Nr   )r-   
logical_orr7   r8   r9   r:   r   r   r   _discordant_element_sumG   s   22rJ   c                    r>   )z<Count a total number of discordant pairs in given sequences.c                    r?   r   )rJ   r@   rB   r   r   rC   U   rD   z+_count_discordant_pairs.<locals>.<listcomp>r   rE   rB   r   rB   r   _count_discordant_pairsS   rH   rK   Fr0   c                 C   s`   |r	| j ddj} tjd| jd tj| jd}ttj|| dd | dd k	 gddddS )z&Convert a sequence to the rank tensor.r   )dimr6   dtypedeviceN)
r0   valuesr-   zerosr2   int32rO   r
   rF   int)r+   r0   _onesr   r   r   _convert_sequence_to_dense_rankX   s   2rV   c                 C   s   t j| jd | j| jd}t j| jd | j| jd}t j| jd | j| jd}t| jd D ]<}t| dd|f }||dk }||d  d  ||< ||d  |d   ||< ||d  d| d   ||< q.|||fS )zWGet a total number of ties and staistics for p-value calculation for  a given sequence.r6   rM   N         ?   )r-   rR   r2   rN   rO   r1   r	   r8   )r+   tiesties_p1ties_p2rL   n_tiesr   r   r   	_get_tiesa   s   "
r^   r   c              	   C   s   t | |\} }t| |}t| |}tj| jd | jd}d }}d } }	 }
}|tjkrEt	| } t	|dd}t
| \}}}	t
|\}}
}|||||	||
||f	S )z,Obtain statistics to calculate metric value.r   )rO   NT)r0   )r5   rG   rK   r-   tensorr2   rO   r   r   rV   r^   )r<   r=   r   concordant_pairsdiscordant_pairsn_total
preds_tiestarget_tiespreds_ties_p1preds_ties_p2target_ties_p1target_ties_p2r   r   r   _get_metric_metadatap   s*   


ri   r`   ra   con_min_dis_pairsrb   rc   rd   c	                 C   s   |t jkr|||  S |t jkrC||d  d }	|du r&tjd|	j|	jd}|du r4tjd|	j|	jd}|	| |	|  }
|t|
 S tjdd | jD | j| jd}tjdd |jD |j|jd}t	||}d| |d | |d   S )	z-Calculate Kendall's tau from metric metadata.r6   rW   N        rM   c                 S      g | ]}t | qS r   lenunique)rA   pr   r   r   rC      rD   z"_calculate_tau.<locals>.<listcomp>c                 S   rl   r   rm   )rA   tr   r   r   rC      rD   )
r   r   r   r-   r_   rN   rO   sqrtr/   minimum)r<   r=   r`   ra   rj   rb   rc   rd   r   total_combinationsdenominatorpreds_uniquetarget_uniquemin_classesr   r   r   _calculate_tau   s   

  ry   t_valuec                 C   sl   | }t jjt dg|t dg|}|  }|  } || }|	| t jt
d|j|jdS )zObtain p-value for a given Tensor of t-values. Handle ``nan`` which cannot be passed into torch distributions.

    When t-value is ``nan``, a resulted p-value should be alson ``nan``.

    rk   rX   nanrM   )r-   distributionsnormalNormalr_   toisnan
nan_to_numcdfwherefloatrN   rO   )rz   rO   normal_distis_nanp_valuer   r   r   "_get_p_value_for_t_value_from_dist   s   ,
"r   re   rf   rg   rh   r'   c
                 C   s&  ||d  d| d  }
|t jkrd|  t|
d  }nQ||d  }|
|dur*|nd |dur2|nd d }|d|dur?|nd |durG|nd | 7 }||durT|nd|dur[|nd d| |d   7 }| t| }|	tjkrxt|}|	tjtjfv r|d	9 }t|}|	tjkr|d9 }|S )
z9Calculate p-value for Kendall's tau from metric metadata.r6   rW   rY      Nr      	   rP   )	r   r   r-   rr   r#   r(   absr*   r   )rj   rb   rc   re   rf   rd   rg   rh   r   r'   t_value_denominator_baserz   mt_value_denominatorr   r   r   r   _calculate_p_value   s>   
"


r   r6   concat_predsconcat_targetnum_outputsc                 C   s^   |pg }|pg }t | | t| || |dkr!| d} |d}||  || ||fS )a  Update variables required to compute Kendall rank correlation coefficient.

    Args:
        preds: Sequence of data
        target: Sequence of data
        concat_preds: List of batches of preds sequence to be concatenated
        concat_target: List of batches of target sequence to be concatenated
        num_outputs: Number of outputs in multioutput setting

    Raises:
        RuntimeError: If ``preds`` and ``target`` do not have the same shape

    r6   )r   r   r9   append)r<   r=   r   r   r   r   r   r   _kendall_corrcoef_update   s   




r   c                 C   s   t | ||\	}}}}}}	}
}}|| }t| |||||||	|	}|r.t||||||	|
|||
nd}|jd dkrE| }|durC| nd}|dd|fS )a/  Compute Kendall rank correlation coefficient, and optionally p-value of corresponding statistical test.

    Args:
        Args:
        preds: Sequence of data
        target: Sequence of data
        variant: Indication of which variant of Kendall's tau to be used
        alternative: Alternative hypothesis for for t-test. Possible values:
            - 'two-sided': the rank correlation is nonzero
            - 'less': the rank correlation is negative (less than zero)
            - 'greater':  the rank correlation is positive (greater than zero)

    Nr   r6   rP   )ri   ry   r   r2   squeezeclamp)r<   r=   r   r'   r`   ra   rc   re   rf   rd   rg   rh   rb   rj   taur   r   r   r   _kendall_corrcoef_compute  sD   
r   r   r$   )r   r   r   t_test)r$   r%   r&   c                 C   s   t |tstdt| d|r|du rtdtt|}|r)tt|nd}t| |g g | j	dkr7dn| j
d d\}}tt|t|||\}	}
|
durU|	|
fS |	S )a  Compute `Kendall Rank Correlation Coefficient`_.

    .. math::
        tau_a = \frac{C - D}{C + D}

    where :math:`C` represents concordant pairs, :math:`D` stands for discordant pairs.

    .. math::
        tau_b = \frac{C - D}{\sqrt{(C + D + T_{preds}) * (C + D + T_{target})}}

    where :math:`C` represents concordant pairs, :math:`D` stands for discordant pairs and :math:`T` represents
    a total number of ties.

    .. math::
        tau_c = 2 * \frac{C - D}{n^2 * \frac{m - 1}{m}}

    where :math:`C` represents concordant pairs, :math:`D` stands for discordant pairs, :math:`n` is a total number
    of observations and :math:`m` is a ``min`` of unique values in ``preds`` and ``target`` sequence.

    Definitions according to Definition according to `The Treatment of Ties in Ranking Problems`_.

    Args:
        preds: Sequence of data of either shape ``(N,)`` or ``(N,d)``
        target: Sequence of data of either shape ``(N,)`` or ``(N,d)``
        variant: Indication of which variant of Kendall's tau to be used
        t_test: Indication whether to run t-test
        alternative: Alternative hypothesis for t-test. Possible values:
            - 'two-sided': the rank correlation is nonzero
            - 'less': the rank correlation is negative (less than zero)
            - 'greater':  the rank correlation is positive (greater than zero)

    Return:
        Correlation tau statistic
        (Optional) p-value of corresponding statistical test (asymptotic)

    Raises:
        ValueError: If ``t_test`` is not of a type bool
        ValueError: If ``t_test=True`` and ``alternative=None``

    Example (single output regression):
        >>> from torchmetrics.functional.regression import kendall_rank_corrcoef
        >>> preds = torch.tensor([2.5, 0.0, 2, 8])
        >>> target = torch.tensor([3, -0.5, 2, 1])
        >>> kendall_rank_corrcoef(preds, target)
        tensor(0.3333)

    Example (multi output regression):
        >>> from torchmetrics.functional.regression import kendall_rank_corrcoef
        >>> preds = torch.tensor([[2.5, 0.0], [2, 8]])
        >>> target = torch.tensor([[3, -0.5], [2, 1]])
        >>> kendall_rank_corrcoef(preds, target)
        tensor([1., 1.])

    Example (single output regression with t-test)
        >>> from torchmetrics.functional.regression import kendall_rank_corrcoef
        >>> preds = torch.tensor([2.5, 0.0, 2, 8])
        >>> target = torch.tensor([3, -0.5, 2, 1])
        >>> kendall_rank_corrcoef(preds, target, t_test=True, alternative='two-sided')
        (tensor(0.3333), tensor(0.4969))

    Example (multi output regression with t-test):
        >>> from torchmetrics.functional.regression import kendall_rank_corrcoef
        >>> preds = torch.tensor([[2.5, 0.0], [2, 8]])
        >>> target = torch.tensor([[3, -0.5], [2, 1]])
        >>> kendall_rank_corrcoef(preds, target, t_test=True, alternative='two-sided')
            (tensor([1., 1.]), tensor([nan, nan]))

    z>Argument `t_test` is expected to be of a type `bool`, but got .NzCArgument `alternative` is required if `t_test=True` but got `None`.r6   rP   )r   )
isinstancebool
ValueErrortyper   from_strr!   r#   r   ndimr2   r   r   )r<   r=   r   r   r'   _variant_alternative_preds_targetr   r   r   r   r   kendall_rank_corrcoefO  s$   
K
r   )F)NNr6   )N)r   Fr$   )%typingr   r   r   r-   r   typing_extensionsr   (torchmetrics.functional.regression.utilsr   torchmetrics.utilities.checksr   torchmetrics.utilities.datar	   r
   r   torchmetrics.utilities.enumsr   r   r#   tupler5   rT   r;   rG   rJ   rK   r   rV   r^   ri   ry   r   r   r   r   r   r   r   r   r   <module>   s   	
(	

	

.


(
?
