o
    Me)                     @   s   d dl Z d dlZd dlZd dlmZmZ d dlmZ d dl	m
Z
 d dlmZmZmZmZ d dlmZmZ d dlmZmZmZmZmZmZmZmZ G dd	 d	ejZdS )
    N)_C_ops_legacy_C_ops)distribution)core)check_dtype
check_typecheck_variable_and_dtypeconvert_dtype)_non_static_modein_dygraph_mode)control_flowelementwise_addelementwise_divelementwise_mulelementwise_subnnopstensorc                       sL   e Zd ZdZd fdd	ZdddZdd	 Zd
d Zdd Zdd Z	  Z
S )Normala  The Normal distribution with location `loc` and `scale` parameters.

    Mathematical details

    The probability density function (pdf) is

    .. math::

        pdf(x; \mu, \sigma) = \frac{1}{Z}e^{\frac {-0.5 (x - \mu)^2}  {\sigma^2} }

    .. math::

        Z = (2 \pi \sigma^2)^{0.5}

    In the above equation:

    * :math:`loc = \mu`: is the mean.
    * :math:`scale = \sigma`: is the std.
    * :math:`Z`: is the normalization constant.

    Args:
        loc(int|float|list|tuple|numpy.ndarray|Tensor): The mean of normal distribution.The data type is float32 and float64.
        scale(int|float|list|tuple|numpy.ndarray|Tensor): The std of normal distribution.The data type is float32 and float64.
        name(str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.

    Examples:
        .. code-block:: python

            import paddle
            from paddle.distribution import Normal

            # Define a single scalar Normal distribution.
            dist = Normal(loc=0., scale=3.)
            # Define a batch of two scalar valued Normals.
            # The first has mean 1 and standard deviation 11, the second 2 and 22.
            dist = Normal(loc=[1., 2.], scale=[11., 22.])
            # Get 3 samples, returning a 3 x 2 tensor.
            dist.sample([3])

            # Define a batch of two scalar valued Normals.
            # Both have mean 1, but different standard deviations.
            dist = Normal(loc=1., scale=[11., 22.])

            # Complete example
            value_tensor = paddle.to_tensor([0.8], dtype="float32")

            normal_a = Normal([0.], [1.])
            normal_b = Normal([0.5], [2.])
            sample = normal_a.sample([2])
            # a random tensor created by normal distribution with shape: [2, 1]
            entropy = normal_a.entropy()
            # [1.4189385] with shape: [1]
            lp = normal_a.log_prob(value_tensor)
            # [-1.2389386] with shape: [1]
            p = normal_a.probs(value_tensor)
            # [0.28969154] with shape: [1]
            kl = normal_a.kl_divergence(normal_b)
            # [0.34939718] with shape: [1]
    Nc              	      s|  t  s!t|dtttjtjtt	fd t|dtttjtjtt	fd d| _
d| _|d ur-|nd| _d| _t|tr<t|}t|trEt|}| ||r[d| _
|| _|| _t|j| _nWt|trht|trhd| _t|tjrzt|jdv rz|j| _nt|tjrt|jdv r|j| _| ||\| _| _| jt| jjkrtj| j| jd| _tj| j| jd| _tt| | jj d S )	Nlocr   scaleFfloat32T)r   Zfloat64dtype)r
   r   intfloatnpZndarrayr   Variablelisttuplebatch_size_unknownall_arg_is_floatnamer   
isinstanceZ_validate_argsr   r   r	   strZ
_to_tensorcastsuperr   __init__shape)selfr   r   r"   	__class__ JD:\Projects\ConvertPro\env\Lib\site-packages\paddle/distribution/normal.pyr'   f   sJ   


zNormal.__init__r   c                 C   s  t  st|dtd t|dtd t| j| j j}| jd }| jr\|| }t	
| j| j || | jd}t||}t|}tj|dd|| jd}	|	|| j  }
t|
| j|d}
|
S || }tj|dd|| jdt	j|| jd	| j  }
t|
| j|d}
| jrtj|
||dS |
S )
a  Generate samples of the specified shape.

        Args:
            shape (list): 1D `int32`. Shape of the generated samples.
            seed (int): Python integer number.

        Returns:
            Tensor, A tensor with prepended dimensions shape.The data type is float32.

        r(   sampleseedZ_sample              ?)meanZstdr/   r   r"   r   )r
   r   r   r   r   r   r(   r"   r    r   fill_constant_batch_size_liker   r   ZreshapeZgaussian_randomr   Zzerosr!   )r)   r(   r/   batch_shaper"   Zoutput_shapezero_tmpZzero_tmp_reshapeZzero_tmp_shapeZnormal_random_tmpoutputr,   r,   r-   r.      s8   

zNormal.samplec                 C   sh   | j d }t| j| j j}t| j| j || jd}td| dt	
dt	j  t
| j|  |dS )a>  Shannon entropy in nats.

        The entropy is

        .. math::

            entropy(\sigma) = 0.5 \log (2 \pi e \sigma^2)

        In the above equation:

        * :math:`scale = \sigma`: is the std.

        Returns:
            Tensor, Shannon entropy of normal distribution.The data type is float32.

        Z_entropyr0         ?   r3   )r"   r   r   r   r(   r   r4   r   r   mathlogpir   )r)   r"   r5   r6   r,   r,   r-   entropy   s   
"zNormal.entropyc              	   C   sp   | j d }| | j|}| j| j }t| j}td|| j || j   d|  |ttdtj	  |dS )zLog probability density/mass function.

        Args:
          value (Tensor): The input tensor.

        Returns:
          Tensor: log probability.The data type is same with value.

        Z	_log_prob             @r3   )
r"   _check_values_dtype_in_probsr   r   r   r;   r   r:   sqrtr<   )r)   valuer"   varZ	log_scaler,   r,   r-   log_prob   s   

zNormal.log_probc                 C   sf   | j d }| | j|}| j| j }ttd|| j || j   d|  tdtj	 | j |dS )zProbability density/mass function.

        Args:
            value (Tensor): The input tensor.

        Returns:
            Tensor, probability. The data type is same with value.

        Z_probsr>   r?   r9   r3   )
r"   r@   r   r   r   r   expr:   rA   r<   )r)   rB   r"   rC   r,   r,   r-   probs   s   

zNormal.probsc                 C   sp   t  s
t|dtd | jd }| j|j }|| }| j|j |j }|| }td| d|d t|  |dS )a  The KL-divergence between two normal distributions.

        The probability density function (pdf) is

        .. math::

            KL\_divergence(\mu_0, \sigma_0; \mu_1, \sigma_1) = 0.5 (ratio^2 + (\frac{diff}{\sigma_1})^2 - 1 - 2 \ln {ratio})

        .. math::

            ratio = \frac{\sigma_0}{\sigma_1}

        .. math::

            diff = \mu_1 - \mu_0

        In the above equation:

        * :math:`loc = \mu_0`: is the mean of current Normal distribution.
        * :math:`scale = \sigma_0`: is the std of current Normal distribution.
        * :math:`loc = \mu_1`: is the mean of other Normal distribution.
        * :math:`scale = \sigma_1`: is the std of other Normal distribution.
        * :math:`ratio`: is the ratio of scales.
        * :math:`diff`: is the difference between means.

        Args:
            other (Normal): instance of Normal.

        Returns:
            Tensor, kl-divergence between two normal distributions.The data type is float32.

        otherkl_divergenceZ_kl_divergencer8   r1   r3   )	r
   r   r   r"   r   r   r   r   r;   )r)   rG   r"   Z	var_ratiot1r,   r,   r-   rH   	  s   !
zNormal.kl_divergence)N)r   )__name__
__module____qualname____doc__r'   r.   r=   rD   rF   rH   __classcell__r,   r,   r*   r-   r   )   s    <
2*r   )r:   warningsnumpyr   Zpaddler   r   Zpaddle.distributionr   Zpaddle.fluidr   Zpaddle.fluid.data_feederr   r   r   r	   Zpaddle.fluid.frameworkr
   r   Zpaddle.fluid.layersr   r   r   r   r   r   r   r   Distributionr   r,   r,   r,   r-   <module>   s   (