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

  #### Mathematical details

  The probability density function (pdf) is,

  ```none
  pdf(x; loc, scale) = 1 / (pi scale (1 + z**2))
  z = (x - loc) / scale
  ```
  where `loc` is the location, and `scale` is the scale.

  The Cauchy distribution is a member of the [location-scale family](
  https://en.wikipedia.org/wiki/Location-scale_family), i.e.
  `Y ~ Cauchy(loc, scale)` is equivalent to,

  ```none
  X ~ Cauchy(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 Cauchy distribution.
  dist = tfd.Cauchy(loc=0., scale=3.)

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

  # Define a batch of two scalar valued Cauchy distributions.
  dist = tfd.Cauchy(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.
  # Define a batch of two scalar valued Cauchy distributions.
  # Both have median 1, but different scales.
  dist = tfd.Cauchy(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.)
  ```

  FTc          	      s   t t }t|p}t||gtj}tj|d|d| _	tj|d|d| _
t| j	| j
g tt| j| j
jtj||||d W dQ R X dS )a  Construct Cauchy distributions.

    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 modes of the distribution(s).
      scale: Floating point tensor; the locations of the distribution(s).
        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.
      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` have 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   r   ZFULLY_REPARAMETERIZED)selfr   r   r   r   r   r   r   )	__class__ h/home/dcms/DCMS/lib/python3.7/site-packages/tensorflow_probability/python/distributions/_numpy/cauchy.pyr   b   s    

zCauchy.__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Cauchy._param_shapesc             C   s   t dddS )Nr   )r   r   )r   )clsr"   r"   r#   _params_event_ndims   s    zCauchy._params_event_ndimsc             C   s   | j S )z(Distribution parameter for the location.)r   )r    r"   r"   r#   r      s    z
Cauchy.locc             C   s   | j S )z%Distribution parameter for the scale.)r   )r    r"   r"   r#   r      s    zCauchy.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Cauchy._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Cauchy._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Cauchy._event_shape_tensorc             C   s
   t g S )N)r   ZTensorShape)r    r"   r"   r#   _event_shape   s    zCauchy._event_shapec             C   s^   t | j}t | j}| j||d}t |g|gd}tj|dd| j|d}| j	|||dS )N)r   r   r   g        g      ?)r+   minvalmaxvalr   seed)
r   r&   r   r   r,   concatr   uniformr   	_quantile)r    nr2   r   r   Zbatch_shaper+   Zprobsr"   r"   r#   	_sample_n   s    zCauchy._sample_nc             C   sJ   t | j}t jt | j||d }ttj	t j| }|| S )N)r   )
r   r&   r   mathlog1psquare_znplogpi)r    xr   Zlog_unnormalized_probZlog_normalizationr"   r"   r#   	_log_prob   s    zCauchy._log_probc             C   s   t | |tj d S )Ng      ?)r   atanr;   r<   r>   )r    r?   r"   r"   r#   _cdf   s    zCauchy._cdfc             C   s,   t jdtj t | | td S )Nr$   )r   r8   r9   r<   r>   rA   r;   r=   )r    r?   r"   r"   r#   _log_cdf   s    zCauchy._log_cdfc             C   s.   t dt j tj| j }|t| j S )N   )r<   r=   r>   r   r8   r   	ones_liker   )r    hr"   r"   r#   _entropy   s    zCauchy._entropyc             C   sL   t |d kr| jn|}t |d kr*| jn|}||t tj|d    S )Ng      ?)r   r&   r   r   tanr<   r>   )r    pr   r   r"   r"   r#   r5      s    zCauchy._quantilec             C   s   | j t| j S )N)r   r   rE   r   )r    r"   r"   r#   _mode   s    zCauchy._modec          	   C   sR   t |dkr| jn|}t |dkr*| jn|}t d || | S Q R X dS )zStandardize input `x`.NZstandardize)r   r&   r   r   r   )r    r?   r   r   r"   r"   r#   r;      s    z	Cauchy._zc          	   C   s&   t d || j | j S Q R X dS )z4Reconstruct input `x` from a its normalized version.ZreconstructN)r   r   r   r   )r    zr"   r"   r#   _inv_z   s    zCauchy._inv_zc             C   s0   | j r$t|  t| jtjS t	dd S )Nz,`mean` is undefined for Cauchy distribution.)
r   r   fillbatch_shape_tensorr
   as_numpy_dtyper   r<   nan
ValueError)r    r"   r"   r#   _mean   s    
zCauchy._meanc             C   s0   | j r$t|  t| jtjS t	dd S )Nz.`stddev` is undefined for Cauchy distribution.)
r   r   rM   rN   r
   rO   r   r<   rP   rQ   )r    r"   r"   r#   _stddev   s    
zCauchy._stddevc             C   s   t j| jdS )N)r   )identity_bijectorZIdentityr   )r    r"   r"   r#   _default_event_space_bijector   s    z$Cauchy._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&Cauchy._parameter_control_dependencies)FTr   )NN)N)NN)NN)__name__
__module____qualname____doc__r   staticmethodr(   classmethodr*   propertyr   r   r,   r-   r.   r/   r7   r@   rB   rC   rG   r5   rJ   r;   rL   rR   rS   rU   rX   __classcell__r"   r"   )r!   r#   r   )   s2   7  '

	

c          	   C   s   t |p
dx t | j}t |j}t |j}t j|| }t j| j|}t j|| t	d t j| t j| S Q R X dS )a?  Calculate the batched KL divergence KL(a || b) with a and b Cauchy.

  Note that this KL divergence is symmetric in its arguments.

  Args:
    a: instance of a Cauchy distribution object.
    b: instance of a Cauchy distribution object.
    name: Name to use for created operations.
      Default value: `None` (i.e., `'kl_cauchy_cauchy'`).

  Returns:
    kl_div: Batchwise KL(a || b)

  #### References

  [1] Frederic Chyzak and Frank Nielsen. A closed-form formula for the
  Kullback-Leibler divergence between Cauchy distributions.
  https://arxiv.org/abs/1905.10965
  Zkl_cauchy_cauchyg      @N)
r   r   r&   r   r   r8   r:   Zsquared_differencer=   r<   )abr   Za_scaleZb_scaleZb_locZscale_sum_squareZloc_diff_squarer"   r"   r#   _kl_cauchy_cauchy   s    rc   )N)r\   
__future__r   r   r   numpyr<   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   __all__Distributionr   Z
RegisterKLrc   r"   r"   r"   r#   <module>   s&    R
