B
    `L;                 @   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dlmZ ddlmZ dgZdZG dd dej Z!e"e!e!dddZ#dS )zThe Beta distribution class.    )absolute_import)division)print_functionN)v2)_numpy)sigmoid)distribution)kullback_leibler)assert_util)distribution_util)
dtype_util)prefer_static)reparameterization)samplers)tensor_util)deprecationBetazuNote: `x` must have dtype `self.dtype` and be in
`[0, 1].` It must have a shape compatible with `self.batch_shape()`.c                   s4  e Zd ZdZd9 fdd	Zedd Zedd	 Ze	d
d Z
e	dd Ze	ejdddddd Zd:ddZdd Zdd Zdd Zd;ddZeedd Zeed d! Zeed"d# Zeed$d% Zd&d' Zd(d) Zd*d+ Zd,d- Zd.d/ Zed0d1d2 Z d3d4 Z!d5d6 Z"d7d8 Z#  Z$S )<r   a  Beta distribution.

  The Beta distribution is defined over the `(0, 1)` interval using parameters
  `concentration1` (aka 'alpha') and `concentration0` (aka 'beta').

  #### Mathematical Details

  The probability density function (pdf) is,

  ```none
  pdf(x; alpha, beta) = x**(alpha - 1) (1 - x)**(beta - 1) / Z
  Z = Gamma(alpha) Gamma(beta) / Gamma(alpha + beta)
  ```

  where:

  * `concentration1 = alpha`,
  * `concentration0 = beta`,
  * `Z` is the normalization constant, and,
  * `Gamma` is the [gamma function](
    https://en.wikipedia.org/wiki/Gamma_function).

  The concentration parameters represent mean total counts of a `1` or a `0`,
  i.e.,

  ```none
  concentration1 = alpha = mean * total_concentration
  concentration0 = beta  = (1. - mean) * total_concentration
  ```

  where `mean` in `(0, 1)` and `total_concentration` is a positive real number
  representing a mean `total_count = concentration1 + concentration0`.

  Distribution parameters are automatically broadcast in all functions; see
  examples for details.

  Warning: The samples can be zero due to finite precision.
  This happens more often when some of the concentrations are very small.
  Make sure to round the samples to `np.finfo(dtype).tiny` before computing the
  density.

  Samples of this distribution are reparameterized (pathwise differentiable).
  The derivatives are computed using the approach described in the paper

  [Michael Figurnov, Shakir Mohamed, Andriy Mnih.
  Implicit Reparameterization Gradients, 2018](https://arxiv.org/abs/1805.08498)

  #### Examples

  ```python
  import tensorflow_probability as tfp; tfp = tfp.experimental.substrates.numpy
  tfd = tfp.distributions

  # Create a batch of three Beta distributions.
  alpha = [1, 2, 3]
  beta = [1, 2, 3]
  dist = tfd.Beta(alpha, beta)

  dist.sample([4, 5])  # Shape [4, 5, 3]

  # `x` has three batch entries, each with two samples.
  x = [[.1, .4, .5],
       [.2, .3, .5]]
  # Calculate the probability of each pair of samples under the corresponding
  # distribution in `dist`.
  dist.prob(x)         # Shape [2, 3]
  ```

  ```python
  # Create batch_shape=[2, 3] via parameter broadcast:
  alpha = [[1.], [2]]      # Shape [2, 1]
  beta = [3., 4, 5]        # Shape [3]
  dist = tfd.Beta(alpha, beta)

  # alpha broadcast as: [[1., 1, 1,],
  #                      [2, 2, 2]]
  # beta broadcast as:  [[3., 4, 5],
  #                      [3, 4, 5]]
  # batch_Shape [2, 3]
  dist.sample([4, 5])  # Shape [4, 5, 2, 3]

  x = [.2, .3, .5]
  # x will be broadcast as [[.2, .3, .5],
  #                         [.2, .3, .5]],
  # thus matching batch_shape [2, 3].
  dist.prob(x)         # Shape [2, 3]
  ```

  Compute the gradients of samples w.r.t. the parameters:

  ```python
  alpha = tf.constant(1.0)
  beta = tf.constant(2.0)
  dist = tfd.Beta(alpha, beta)
  samples = dist.sample(5)  # Shape [5]
  loss = tf.reduce_mean(tf.square(samples))  # Arbitrary loss function
  # Unbiased stochastic gradients of the loss function
  grads = tf.gradients(loss, [alpha, beta])
  ```

  FTc          	      sz   t t }t|\}tj||gtjd}tj||dd| _	tj||dd| _
tt| j|||tj||d W dQ R X dS )a}  Initialize a batch of Beta distributions.

    Args:
      concentration1: Positive floating-point `Tensor` indicating mean
        number of successes; aka 'alpha'.
      concentration0: Positive floating-point `Tensor` indicating mean
        number of failures; aka 'beta'.
      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.
    )Z
dtype_hintconcentration1)dtypenameconcentration0)r   validate_argsallow_nan_statsZreparameterization_type
parametersr   N)dictlocalstf
name_scoper   Zcommon_dtypefloat32r   Zconvert_nonref_to_tensor_concentration1_concentration0superr   __init__r   ZFULLY_REPARAMETERIZED)selfr   r   r   r   r   r   r   )	__class__ f/home/dcms/DCMS/lib/python3.7/site-packages/tensorflow_probability/python/distributions/_numpy/beta.pyr"      s    



zBeta.__init__c             C   s   t j| t jd}t||dS )N)r   )r   r   )r   convert_to_tensorint32r   )Zsample_shapesr%   r%   r&   _param_shapes   s    zBeta._param_shapesc             C   s   t dddS )Nr   )r   r   )r   )clsr%   r%   r&   _params_event_ndims   s    zBeta._params_event_ndimsc             C   s   | j S )z6Concentration parameter associated with a `1` outcome.)r   )r#   r%   r%   r&   r      s    zBeta.concentration1c             C   s   | j S )z6Concentration parameter associated with a `0` outcome.)r    )r#   r%   r%   r&   r      s    zBeta.concentration0z
2019-10-01zjThe `total_concentration` property is deprecated; instead use `dist.concentration1 + dist.concentration0`.)Z	warn_oncec          	   C   s"   |  d | j| j S Q R X dS )z Sum of concentration parameters.total_concentrationN)Z_name_and_control_scoper   r   )r#   r%   r%   r&   r-      s    zBeta.total_concentrationNc             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Beta._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Beta._batch_shapec             C   s   t jg t jdS )N)r   )r   Zconstantr(   )r#   r%   r%   r&   _event_shape_tensor   s    zBeta._event_shape_tensorc             C   s
   t g S )N)r   ZTensorShape)r#   r%   r%   r&   _event_shape   s    zBeta._event_shapec             C   s   t j|dd\}}t| j}t| j}| ||}t||}t||}	t j|g|| j	|d}
t j|g|	| j	|d}|
|
|  }|S )Nbeta)Zsalt)r.   alphar   seed)
r   Z
split_seedr   r'   r   r   r/   broadcast_togammar   )r#   nr5   Zseed1Zseed2r   r   r.   Zexpanded_concentration1Zexpanded_concentration0Zgamma1_sampleZgamma2_sampleZbeta_sampler%   r%   r&   	_sample_n   s    zBeta._sample_nc             C   s2   t | j}t | j}| |||| || S )N)r   r'   r   r   _log_unnormalized_prob_log_normalization)r#   xr   r   r%   r%   r&   	_log_prob   s    zBeta._log_probc             C   s   t | |S )N)r   expr=   )r#   r<   r%   r%   r&   _prob  s    z
Beta._probc             C   s   t j| |S )N)r   mathlog_cdf)r#   r<   r%   r%   r&   _log_cdf  s    zBeta._log_cdfc             C   sL   t | j}t | j}| ||}t ||}t ||}t j|||S )N)r   r'   r   r   r/   r6   r@   Zbetainc)r#   r<   r   r   r.   r%   r%   r&   rB   	  s    z	Beta._cdfc             C   s&   t j|d |t j|d |  S )Ng      ?)r   r@   ZxlogyZxlog1py)r#   r<   r   r   r%   r%   r&   r:     s    zBeta._log_unnormalized_probc             C   s   t ||S )N)tfp_mathZlbeta)r#   r   r   r%   r%   r&   r;     s    zBeta._log_normalizationc             C   sh   t | j}t | j}|| }| |||d t j|  |d t j|  |d t j|  S )Ng      ?g       @)r   r'   r   r   r;   r@   digamma)r#   r   r   r-   r%   r%   r&   _entropy  s
    2zBeta._entropyc             C   s   t | j}||| j  S )N)r   r'   r   r   )r#   r   r%   r%   r&   _mean"  s    z
Beta._meanc             C   s8   t | j}t | j}|| }|| |d |d   S )N   g      ?)r   r'   r   r   )r#   r   r   r-   r%   r%   r&   	_variance&  s
    zBeta._variancea  Note: The mode is undefined when `concentration1 <= 1` or
      `concentration0 <= 1`. If `self.allow_nan_stats` is `True`, `NaN`
      is used for undefined modes. If `self.allow_nan_stats` is `False` an
      exception is raised when one or more modes are undefined.c          	   C   s   t | j}t | j}|d || d  }t | jr:g n6tjt jg | j	d|ddtjt jg | j	d|ddg* t 
|dk|dk@ |t| j	tjS Q R X d S )Ng      ?g       @)r   z'Mode undefined for concentration1 <= 1.)messagez'Mode undefined for concentration0 <= 1.)r   r'   r   r   Zcontrol_dependenciesr   r
   Zassert_lessonesr   wherer   Zas_numpy_dtypenpnan)r#   r   r   moder%   r%   r&   _mode-  s     z
Beta._modec             C   s   t j| jdS )N)r   )sigmoid_bijectorZSigmoidr   )r#   r%   r%   r&   _default_event_space_bijectorE  s    z"Beta._default_event_space_bijectorc             C   sF   g }| j s|S |tj|dd |tj|tg |jdd |S )z Checks the validity of a sample.zSample must be non-negative.)rJ   z)Sample must be less than or equal to `1`.)r   appendr
   Zassert_non_negativeZassert_less_equalr   rK   r   )r#   r<   
assertionsr%   r%   r&   _sample_control_dependenciesH  s    
z!Beta._sample_control_dependenciesc             C   sJ   | j s
g S g }x6| j| jgD ]&}|t|kr|tj|dd qW |S )Nz)Concentration parameter must be positive.)rJ   )r   r   r   r   Zis_refrS   r
   Zassert_positive)r#   Zis_initrT   Zconcentrationr%   r%   r&   _parameter_control_dependenciesT  s    z$Beta._parameter_control_dependencies)FTr   )NN)N)%__name__
__module____qualname____doc__r"   staticmethodr*   classmethodr,   propertyr   r   r   
deprecatedr-   r/   r0   r1   r2   r9   r   ZAppendDocstring_beta_sample_noter=   r?   rC   rB   r:   r;   rF   rG   rI   rP   rR   rU   rV   __classcell__r%   r%   )r$   r&   r   /   s@   e  "

		c          	   C   s   t |p
d t | j}t | j}t |j}t |j}|| }|| }| ||}	|||}
|
|	 t j|||   t j|||   t j|||   S Q R X dS )a4  Calculate the batchwise KL divergence KL(d1 || d2) with d1 and d2 Beta.

  Args:
    d1: instance of a Beta distribution object.
    d2: instance of a Beta distribution object.
    name: (optional) Name to use for created operations.
      default is 'kl_beta_beta'.

  Returns:
    Batchwise KL(d1 || d2)
  Zkl_beta_betaN)r   r   r'   r   r   r;   r@   rE   )d1Zd2r   Zd1_concentration1Zd1_concentration0Zd2_concentration1Zd2_concentration0Zd1_total_concentrationZd2_total_concentrationZd1_log_normalizationZd2_log_normalizationr%   r%   r&   _kl_beta_beta`  s    .
rb   )N)$rZ   
__future__r   r   r   numpyrM   Z;tensorflow_probability.python.internal.backend.numpy.compatr   r   Z"tensorflow_probability.python.mathr   rD   Z.tensorflow_probability.python.bijectors._numpyr   rQ   Z2tensorflow_probability.python.distributions._numpyr   r	   Z-tensorflow_probability.python.internal._numpyr
   r   r   r   Z&tensorflow_probability.python.internalr   r   r   Z4tensorflow_probability.python.internal.backend.numpyr   __all__r_   Distributionr   Z
RegisterKLrb   r%   r%   r%   r&   <module>   s0     3
