B
    `q#                 @   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 G dd dejZeeedddZdS )zThe Gumbel distribution class.    )absolute_import)division)print_functionN)v2)
gumbel_cdf)identity)invert)kullback_leibler)transformed_distribution)uniform)distribution_util)
dtype_util)tensor_utilc                   s   e Zd ZdZd fdd	Zedd Zedd	 Ze	d
d Z
e	dd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Z  ZS )GumbelaM  The scalar Gumbel 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 - exp(-(x - mu) / sigma)) / sigma
  ```

  where `loc = mu` and `scale = sigma`.

  The cumulative density function of this distribution is,

  ```cdf(x; mu, sigma) = exp(-exp(-(x - mu) / sigma))```

  The Gumbel 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 ~ Gumbel(loc=0, scale=1)
  Y = loc + scale * X
  ```

  #### Examples

  Examples of initialization of one or a batch of distributions.

  ```python
  tfd = tfp.distributions

  # Define a single scalar Gumbel distribution.
  dist = tfd.Gumbel(loc=0., scale=3.)

  # Evaluate the cdf at 1, returning a scalar.
  dist.cdf(1.)

  # Define a batch of two scalar valued Gumbels.
  # The first has mean 1 and scale 11, the second 2 and 22.
  dist = tfd.Gumbel(loc=[1, 2.], scale=[11, 22.])

  # Evaluate the pdf of the first distribution on 0, and the second on 1.5,
  # returning a length two tensor.
  dist.prob([0, 1.5])

  # Get 3 samples, returning a 3 x 2 tensor.
  dist.sample([3])
  ```

  Arguments are broadcast when possible.

  ```python
  # Define a batch of two scalar valued Logistics.
  # Both have mean 1, but different scales.
  dist = tfd.Gumbel(loc=1., scale=[11, 22.])

  # Evaluate the pdf of both distributions on the same point, 3.0,
  # returning a length 2 tensor.
  dist.prob(3.0)
  ```

  FTc       	   	      s   t t }t|}tj||gtjd}tj|d|d}tj|d|d}t	||g t
j|||d| _t||}tt| jtjtt|jtj||d|dtj| j|d||d	 W d
Q R X d
S )a  Construct Gumbel distributions with location and scale `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, the means of the distribution(s).
      scale: Floating point tensor, the scales of the distribution(s).
        scale must contain only positive values.
      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.
        Default value: `False`.
      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.
        Default value: `True`.
      name: Python `str` name prefixed to Ops created by this class.
        Default value: `'Gumbel'`.

    Raises:
      TypeError: if loc and scale are different dtypes.
    )Z
dtype_hintloc)namedtypescale)r   r   validate_args)r   )lowhighallow_nan_stats)r   )distributionZbijector
parametersr   N)dictlocalstf
name_scoper   Zcommon_dtypefloat32r   Zconvert_nonref_to_tensorZassert_same_float_dtypegumbel_cdf_bijectorZ	GumbelCDF_gumbel_bijectorr   Zget_broadcast_shapesuperr   __init__r   ZUniformnpZfinfoZas_numpy_dtypeZtinyZonesinvert_bijectorZInvert)	selfr   r   r   r   r   r   r   Zbatch_shape)	__class__ h/home/dcms/DCMS/lib/python3.7/site-packages/tensorflow_probability/python/distributions/_numpy/gumbel.pyr"   e   s(    


zGumbel.__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_shapes   s    zGumbel._param_shapesc             C   s   t dddS )Nr   )r   r   )r   )clsr'   r'   r(   _params_event_ndims   s    zGumbel._params_event_ndimsc             C   s   | j jS )z(Distribution parameter for the location.)r    r   )r%   r'   r'   r(   r      s    z
Gumbel.locc             C   s   | j jS )z!Distribution parameter for scale.)r    r   )r%   r'   r'   r(   r      s    zGumbel.scalec             C   s(   | j t| j }dtj| tj S )Ng      ?)r   r   	ones_liker   mathlogr#   euler_gamma)r%   r   r'   r'   r(   _entropy   s    zGumbel._entropyc             C   s8   t | j}|| j | }|t |   t j| S )N)r   r+   r   r   expr1   r2   )r%   xr   zr'   r'   r(   	_log_prob   s    zGumbel._log_probc             C   s   | j | jtj  S )N)r   r   r#   r3   )r%   r'   r'   r(   _mean   s    zGumbel._meanc             C   s"   | j t| j tj td S )N   )r   r   r0   r   r#   pisqrt)r%   r'   r'   r(   _stddev   s    zGumbel._stddevc             C   s   | j t| j S )N)r   r   r0   r   )r%   r'   r'   r(   _mode   s    zGumbel._modec             C   s   t j| jdS )N)r   )identity_bijectorZIdentityr   )r%   r'   r'   r(   _default_event_space_bijector   s    z$Gumbel._default_event_space_bijectorc             C   s   | j |S )N)r    _parameter_control_dependencies)r%   Zis_initr'   r'   r(   rA      s    z&Gumbel._parameter_control_dependencies)FTr   )__name__
__module____qualname____doc__r"   staticmethodr-   classmethodr/   propertyr   r   r4   r8   r9   r=   r>   r@   rA   __classcell__r'   r'   )r&   r(   r   $   s   ?  9r   c          	   C   s   t |p
d t | j}t |j}t | j}t |j}t j|t j| tj|| d   t j	|| | t j
|| d   || |  S Q R X dS )a4  Calculate the batched KL divergence KL(a || b) with a and b Gumbel.

  Args:
    a: instance of a Gumbel distribution object.
    b: instance of a Gumbel distribution object.
    name: (optional) Name to use for created operations.
      default is 'kl_gumbel_gumbel'.

  Returns:
    Batchwise KL(a || b)
  Zkl_gumbel_gumbelg      ?N)r   r   r+   r   r   r1   r2   r#   r3   expm1lgamma)abr   Za_locZb_locZa_scaleZb_scaler'   r'   r(   _kl_gumbel_gumbel   s    PrN   )N)rE   
__future__r   r   r   numpyr#   Z;tensorflow_probability.python.internal.backend.numpy.compatr   r   Z.tensorflow_probability.python.bijectors._numpyr   r   r   r?   r   r$   Z2tensorflow_probability.python.distributions._numpyr	   r
   r   Z-tensorflow_probability.python.internal._numpyr   r   r   ZTransformedDistributionr   Z
RegisterKLrN   r'   r'   r'   r(   <module>   s$    0
