B
    `v#                 @   s   d Z ddlmZ ddlmZ 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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gZG dd dejZeeedddZdS )zThe Laplace distribution class.    )absolute_import)division)print_functionN)v2)identity)distribution)kullback_leibler)assert_util)
dtype_util)prefer_static)reparameterization)samplers)special_math)tensor_utilLaplacec                   s   e Zd ZdZd3 fdd	Zedd Zedd	 Ze	d
d Z
e	dd Zd4ddZdd Zdd Zdd Zd5ddZdd Zdd Zdd Zdd  Zd!d" Zd#d$ Zd%d& Zd'd( Zd)d* Zd+d, Zd-d. Zd/d0 Zd1d2 Z  ZS )6r   a  The Laplace distribution with location `loc` and `scale` parameters.

  #### Mathematical details

  The probability density function (pdf) of this distribution is,

  ```none
  pdf(x; mu, sigma) = exp(-|x - mu| / sigma) / Z
  Z = 2 sigma
  ```

  where `loc = mu`, `scale = sigma`, and `Z` is the normalization constant.

  Note that the Laplace distribution can be thought of two exponential
  distributions spliced together 'back-to-back.'

  The Laplace distribution is a member of the [location-scale family](
  https://en.wikipedia.org/wiki/Location-scale_family), i.e., it can be
  constructed as,

  ```none
  X ~ Laplace(loc=0, scale=1)
  Y = loc + scale * X
  ```

  FTc          	      s   t t }t|l}t||gtj}tj|d|d| _	tj|d|d| _
t| j	| j
g tt| j|tj||||d W dQ R X dS )aY  Construct Laplace distribution with parameters `loc` and `scale`.

    The parameters `loc` and `scale` must be shaped in a way that supports
    broadcasting (e.g., `loc / scale` is a valid operation).

    Args:
      loc: Floating point tensor which characterizes the location (center)
        of the distribution.
      scale: Positive floating point tensor which characterizes the spread of
        the distribution.
      validate_args: Python `bool`, default `False`. When `True` distribution
        parameters are checked for validity despite possibly degrading runtime
        performance. When `False` invalid inputs may silently render incorrect
        outputs.
      allow_nan_stats: Python `bool`, default `True`. When `True`,
        statistics (e.g., mean, mode, variance) use the value '`NaN`' to
        indicate the result is undefined. When `False`, an exception is raised
        if one or more of the statistic's batch members are undefined.
      name: Python `str` name prefixed to Ops created by this class.

    Raises:
      TypeError: if `loc` and `scale` are of different dtype.
    loc)namedtypescale)r   Zreparameterization_typevalidate_argsallow_nan_stats
parametersr   N)dictlocalstf
name_scoper
   Zcommon_dtypefloat32r   Zconvert_nonref_to_tensor_loc_scaleZassert_same_float_dtypesuperr   __init__r   ZFULLY_REPARAMETERIZED)selfr   r   r   r   r   r   r   )	__class__ i/home/dcms/DCMS/lib/python3.7/site-packages/tensorflow_probability/python/distributions/_numpy/laplace.pyr    F   s    

zLaplace.__init__c             C   s    t tdtj| tjdgd S )N)r   r   )r      )r   zipr   convert_to_tensorint32)Zsample_shaper#   r#   r$   _param_shapess   s    zLaplace._param_shapesc             C   s   t dddS )Nr   )r   r   )r   )clsr#   r#   r$   _params_event_ndimsy   s    zLaplace._params_event_ndimsc             C   s   | j S )z(Distribution parameter for the location.)r   )r!   r#   r#   r$   r   }   s    zLaplace.locc             C   s   | j S )z!Distribution parameter for scale.)r   )r!   r#   r#   r$   r      s    zLaplace.scaleNc             C   s4   t t |d kr| jn|t |d kr,| jn|S )N)r   Zbroadcast_shapeshaper   r   )r!   r   r   r#   r#   r$   _batch_shape_tensor   s    zLaplace._batch_shape_tensorc             C   s   t | jj| jjS )N)r   Zbroadcast_static_shaper   r,   r   )r!   r#   r#   r$   _batch_shape   s    zLaplace._batch_shapec             C   s   t jg t jdS )N)r   )r   constantr(   )r!   r#   r#   r$   _event_shape_tensor   s    zLaplace._event_shape_tensorc             C   s
   t g S )N)r   ZTensorShape)r!   r#   r#   r$   _event_shape   s    zLaplace._event_shapec             C   s   t | j}t | j}t |g| j||dgd}t| j}t	j
|t|d|dd| j|d}||t | t jt |   S )N)r   r   r   g      g      ?)r,   minvalmaxvalr   seed)r   r'   r   r   concatr-   r
   Zas_numpy_dtyper   r   uniformnpZ	nextaftersignmathlog1pabs)r!   nr4   r   r   r,   dtZuniform_samplesr#   r#   r$   	_sample_n   s    zLaplace._sample_nc             C   sF   t | j}t | j}|| | }t | td t j| S )Ng       @)r   r'   r   r   r;   r7   logr9   )r!   xr   r   zr#   r#   r$   	_log_prob   s    zLaplace._log_probc             C   s   t | |S )N)r   log_cdf_laplace_z)r!   r@   r#   r#   r$   _log_cdf   s    zLaplace._log_cdfc             C   s   t | | S )N)r   rC   rD   )r!   r@   r#   r#   r$   _log_survival_function   s    zLaplace._log_survival_functionc             C   s0   |  |}ddt| tjt|   S )Ng      ?)rD   r   r8   r9   expm1r;   )r!   r@   rA   r#   r#   r$   _cdf   s    
zLaplace._cdfc             C   s6   t | j}t tdd t j| | j|dS )Ng       @   )r   )r   r'   r   broadcast_tor7   r?   r9   r-   )r!   r   r#   r#   r$   _entropy   s    zLaplace._entropyc             C   s    t | j}t || j|dS )N)r   )r   r'   r   rJ   r-   )r!   r   r#   r#   r$   _mean   s    zLaplace._meanc             C   s*   t | j}t td| | j|dS )Ng       @)r   )r   r'   r   rJ   r7   sqrtr-   )r!   r   r#   r#   r$   _stddev   s    zLaplace._stddevc             C   s   |   S )N)rL   )r!   r#   r#   r$   _median   s    zLaplace._medianc             C   s   |   S )N)rL   )r!   r#   r#   r$   _mode   s    zLaplace._modec          
   C   sf   t | j}t | j}t |dk||t jtd|jdt j	
|    ||t j	d|   S )Ng      ?r%   )r   )r   r'   r   r   wherer/   r7   r?   r   r9   r:   )r!   pr   r   r#   r#   r$   	_quantile   s    
zLaplace._quantilec             C   s   || j  | j S )N)r   r   )r!   r@   r#   r#   r$   rD      s    z
Laplace._zc             C   s   t j| jdS )N)r   )identity_bijectorZIdentityr   )r!   r#   r#   r$   _default_event_space_bijector   s    z%Laplace._default_event_space_bijectorc             C   s8   | j s
g S g }|t| jkr4|tj| jdd |S )Nz"Argument `scale` must be positive.)message)r   r   Zis_refr   appendr	   Zassert_positive)r!   Zis_initZ
assertionsr#   r#   r$   _parameter_control_dependencies   s    z'Laplace._parameter_control_dependencies)FTr   )NN)N)__name__
__module____qualname____doc__r    staticmethodr)   classmethodr+   propertyr   r   r-   r.   r0   r1   r>   rB   rE   rF   rH   rK   rL   rN   rO   rP   rS   rD   rU   rX   __classcell__r#   r#   )r"   r$   r   *   s4     (

	c          	   C   s   t |p
dj t | j|j }t | j}t |j}t j|t j| }| ||  d t | | |  S Q R X dS )aX  Calculate the batched KL divergence KL(a || b) with a and b Laplace.

  Args:
    a: instance of a Laplace distribution object.
    b: instance of a Laplace distribution object.
    name: Python `str` name to use for created operations.
      Default value: `None` (i.e., `'kl_laplace_laplace'`).

  Returns:
    kl_div: Batchwise KL(a || b)
  Zkl_laplace_laplaceg      ?N)	r   r   r;   r   r'   r   r9   r?   exp)abr   ZdistanceZa_scaleZb_scaleZdelta_log_scaler#   r#   r$   _kl_laplace_laplace   s    rd   )N)r\   
__future__r   r   r   numpyr7   Z;tensorflow_probability.python.internal.backend.numpy.compatr   r   Z.tensorflow_probability.python.bijectors._numpyr   rT   Z2tensorflow_probability.python.distributions._numpyr   r   Z-tensorflow_probability.python.internal._numpyr	   r
   r   Z&tensorflow_probability.python.internalr   r   r   r   __all__Distributionr   Z
RegisterKLrd   r#   r#   r#   r$   <module>   s(    >
