o
    .wi                     @   s   d dl 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eded	e
d
eeef fddZ	ddedeeef ded d
efddZ	ddeded	e
ded d
ef
ddZdS )    )UnionN)Tensor)Literal)kl_divergence)_check_same_shapepqlog_probreturnc                 C   s   t | | | jdks|jdkrtd| j d|j d| jd }|rOtjt| |gddttd }dt	| ||d	d
 dt	|||d	d
  }||fS | | j
ddd } ||j
ddd }| | d }dt	| ||d	d
 dt	|||d	d
  }||fS )a  Update and returns jensen-shannon divergence scores for each observation and the total number of observations.

    Args:
        p: data distribution with shape ``[N, d]``
        q: prior or approximate distribution with shape ``[N, d]``
        log_prob: bool indicating if input is log-probabilities or probabilities. If given as probabilities,
            will normalize to make sure the distributes sum to 1

       z4Expected both p and q distribution to be 2D but got z and z respectivelyr   )dimg       @g      ?N)r	   	reductionT)axiskeepdim)r   ndim
ValueErrorshapetorch	logsumexpstacklogtensorr   sum)r   r   r	   totalmeanmeasures r   m/home/ubuntu/sommelier/.venv/lib/python3.10/site-packages/torchmetrics/functional/regression/js_divergence.py_jsd_update   s"   


(


r   r   r   r   r   )r   r   noneNc                 C   s@   |dkr|   S |dkr|   | S |du s|dkr| S | | S )zPCompute and reduce the Jensen-Shannon divergence based on the type of reduction.r   r   Nr    )r   )r   r   r   r   r   r   _jsd_compute7   s   r!   Fc                 C   s   t | ||\}}t|||S )a*  Compute `Jensen-Shannon divergence`_.

    .. math::
        D_{JS}(P||Q) = \frac{1}{2} D_{KL}(P||M) + \frac{1}{2} D_{KL}(Q||M)

    Where :math:`P` and :math:`Q` are probability distributions where :math:`P` usually represents a distribution
    over data and :math:`Q` is often a prior or approximation of :math:`P`. :math:`D_{KL}` is the `KL divergence`_ and
    :math:`M` is the average of the two distributions. It should be noted that the Jensen-Shannon divergence is a
    symmetrical metric i.e. :math:`D_{JS}(P||Q) = D_{JS}(Q||P)`.

    Args:
        p: data distribution with shape ``[N, d]``
        q: prior or approximate distribution with shape ``[N, d]``
        log_prob: bool indicating if input is log-probabilities or probabilities. If given as probabilities,
            will normalize to make sure the distributes sum to 1
        reduction:
            Determines how to reduce over the ``N``/batch dimension:

            - ``'mean'`` [default]: Averages score across samples
            - ``'sum'``: Sum score across samples
            - ``'none'`` or ``None``: Returns score per sample

    Example:
        >>> from torch import tensor
        >>> p = tensor([[0.36, 0.48, 0.16]])
        >>> q = tensor([[1/3, 1/3, 1/3]])
        >>> jensen_shannon_divergence(p, q)
        tensor(0.0225)

    )r   r!   )r   r   r	   r   r   r   r   r   r   jensen_shannon_divergenceD   s   !r"   )r   )Fr   )typingr   r   r   typing_extensionsr   0torchmetrics.functional.regression.kl_divergencer   torchmetrics.utilities.checksr   booltupleintr   r!   r"   r   r   r   r   <module>   s:   "

