o
    "jw                     @   s  d dl Z d dl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 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 d dlmZ d dlmZ d dlmZ ddgZi Zdd Zdd Z dd Z!e j"G dd dZ#e eedd Z$e eedd Z%e eedd Z&e eedd Z'e e
e
dd  Z(e eed!d" Z)e eed#d$ Z*e eed%d& Z+e eed'd( Z,e eed)d* Z-e eed+d, Z.d-d. Z/dS )/    N)	Bernoulli)Beta)Categorical)Cauchy)	Dirichlet)Distribution)ExponentialFamily)	Geometric)Laplace)	LogNormal)Normal)Uniform)in_dynamic_moderegister_klkl_divergencec                 C   s   t t| t|| |S )a-  
    Kullback-Leibler divergence between distribution p and q.

    .. math::

        KL(p||q) = \int p(x)log\frac{p(x)}{q(x)} \mathrm{d}x

    Args:
        p (Distribution): ``Distribution`` object. Inherits from the Distribution Base class.
        q (Distribution): ``Distribution`` object. Inherits from the Distribution Base class.

    Returns:
        Tensor, Batchwise KL-divergence between distribution p and q.

    Examples:

        .. code-block:: python

            >>> import paddle

            >>> p = paddle.distribution.Beta(alpha=0.5, beta=0.5)
            >>> q = paddle.distribution.Beta(alpha=0.3, beta=0.7)

            >>> print(paddle.distribution.kl_divergence(p, q))
            Tensor(shape=[], dtype=float32, place=Place(cpu), stop_gradient=True,
                0.21193528)

    )	_dispatchtypepq r   W/var/www/html/Deteccion_Ine/venv/lib/python3.10/site-packages/paddle/distribution/kl.pyr   %   s   c                    s.   t  tr
t tstd fdd}|S )a  Decorator for register a KL divergence implemention function.

    The ``kl_divergence(p, q)`` function will search concrete implemention
    functions registered by ``register_kl``, according to multi-dispatch pattern.
    If an implemention function is found, it will return the result, otherwise,
    it will raise ``NotImplementError`` exception. Users can register
    implemention function by the decorator.

    Args:
        cls_p (Distribution): The Distribution type of Instance p. Subclass derived from ``Distribution``.
        cls_q (Distribution): The Distribution type of Instance q. Subclass derived from ``Distribution``.

    Examples:
        .. code-block:: python

            >>> import paddle

            >>> @paddle.distribution.register_kl(paddle.distribution.Beta, paddle.distribution.Beta)
            >>> def kl_beta_beta():
            ...     pass # insert implementation here
    z0cls_p and cls_q must be subclass of Distributionc                    s   | t  f< | S N)_REGISTER_TABLE)fcls_pcls_qr   r   	decorator`   s   zregister_kl.<locals>.decorator)
issubclassr   	TypeError)r   r   r   r   r   r   r   E   s   c                    s    fddt D }|sttdd |D j\}}tdd |D j\}}t ||f t ||f urBtd jj|j|jt t ||f S )z3Multiple dispatch into concrete implement function.c                    s,   g | ]\}}t  |rt |r||fqS r   )r   ).0Zsuper_pZsuper_qr   r   r   
<listcomp>k   s    z_dispatch.<locals>.<listcomp>c                 s   s    | ]}t | V  qd S r   )_Comparer!   mr   r   r   	<genexpr>s   s    z_dispatch.<locals>.<genexpr>c                 s   s    | ]	}t t| V  qd S r   )r#   reversedr$   r   r   r   r&   t   s    z;Ambiguous kl_divergence({}, {}). Please register_kl({}, {}))	r   NotImplementedErrorminclasseswarningswarnformat__name__RuntimeWarning)r   r   ZmatchsZleft_pZleft_qZright_pZright_qr   r   r   r   g   s$   
r   c                   @   s$   e Zd Zdd Zdd Zdd ZdS )r#   c                 G   s
   || _ d S r   r*   )selfr*   r   r   r   __init__   s   
z_Compare.__init__c                 C   s   | j |j kS r   r0   )r1   otherr   r   r   __eq__   s   z_Compare.__eq__c                 C   s:   t | j|jD ]\}}t||s dS ||ur dS qdS )NFT)zipr*   r   )r1   r3   Zcls_xZcls_yr   r   r   __le__   s   
z_Compare.__le__N)r.   
__module____qualname__r2   r4   r6   r   r   r   r   r#      s    r#   c                 C   
   |  |S r   r   r   r   r   r   _kl_bernoulli_bernoulli      
r;   c                 C   s   |j  |j  | j | j   | j  | j  |j |j    | j |j  | j    | j|j | j   |j |j | j | j  | j | j    S r   )alphalgammabetadigammar   r   r   r   _kl_beta_beta   s   ""rA   c                 C   sl   | j d |j d  | j  |j   d | j |j  | j  | j d d  d S )N)Zconcentrationsumr>   r@   Z	unsqueezer   r   r   r   _kl_dirichlet_dirichlet   s   
rD   c                 C   r9   r   r:   r   r   r   r   _kl_categorical_categorical   r<   rE   c                 C   r9   r   r:   r   r   r   r   _kl_cauchy_cauchy   r<   rF   c                 C   r9   r   r:   r   r   r   r   _kl_normal_normal   r<   rG   c                 C   r9   r   r:   r   r   r   r   _kl_uniform_uniform   r<   rH   c                 C   r9   r   r:   r   r   r   r   _kl_laplace_laplace   r<   rI   c                 C   r9   r   r:   r   r   r   r   _kl_geometric_geometric   r<   rJ   c              
   C   s   t | t |ks
tg }| jD ]}| }d|_|| q|j}| j| }zt r3tj	||dd}ntj
||}W n tyW } ztdjt | jt |jd|d}~ww |j| | }t|||D ]\}	}
}|
|	 | }|t|t|j8 }qe|S )zuCompute kl-divergence using `Bregman divergences <https://www.lix.polytechnique.fr/~nielsen/EntropyEF-ICIP2010.pdf>`_FT)Zcreate_graphzlCann't compute kl_divergence({cls_p}, {cls_q}) use bregman divergence. Please register_kl({cls_p}, {cls_q}).r   N)r   r(   Z_natural_parametersdetachZstop_gradientappendZ_log_normalizerr   paddleZgradZstaticZ	gradientsRuntimeErrorr    r-   r.   r5   _sum_rightmostlenZevent_shape)r   r   Zp_natural_paramsparamZq_natural_paramsZ
p_log_normZp_gradseklZp_paramZq_paramZp_gradtermr   r   r   _kl_expfamily_expfamily   sB   

rU   c                 C   s   | j |j S r   )Z_baser   r   r   r   r   _kl_lognormal_lognormal   s   rV   c                 C   s"   |dkr|  tt| dS | S )Nr   )rC   listrange)valuenr   r   r   rO     s   "rO   )0	functoolsr+   rM   Zpaddle.distribution.bernoullir   Zpaddle.distribution.betar   Zpaddle.distribution.categoricalr   Zpaddle.distribution.cauchyr   Zpaddle.distribution.dirichletr   Z paddle.distribution.distributionr   Z&paddle.distribution.exponential_familyr   Zpaddle.distribution.geometricr	   Zpaddle.distribution.laplacer
   Zpaddle.distribution.lognormalr   Zpaddle.distribution.normalr   Zpaddle.distribution.uniformr   Zpaddle.frameworkr   __all__r   r   r   r   total_orderingr#   r;   rA   rD   rE   rF   rG   rH   rI   rJ   rU   rV   rO   r   r   r   r   <module>   s\    "









'
