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 Moyal distribution class.    )absolute_import)division)print_functionN)v2)identity)invert)	moyal_cdf)kullback_leibler)transformed_distribution)uniform)distribution_util)
dtype_util)tensor_utilMoyalc                   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 )r   ak  The Moyal distribution with location `loc` and `scale` parameters.

  #### Mathematical details

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

  ```none
  pdf(x; mu, sigma) = exp(- 1/2 * ((x - mu) / sigma + exp(-(x - mu) / sigma))) /
    (sigma * sqrt(2 pi))
  ```

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

  The cumulative density function of this distribution is,

  ```cdf(x; mu, sigma) = erfc(exp(- 1/2 * (x - mu) / sigma) / sqrt(2))```

  The Moyal 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 ~ Moyal(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 Moyal distribution.
  dist = tfd.Moyal(loc=0., scale=3.)

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

  # Define a batch of two scalar valued Moyals.
  # The first has mean 1 and scale 11, the second 2 and 22.
  dist = tfd.Moyal(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.Moyal(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 )aQ  Construct Moyal 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: `'Moyal'`.

    Raises:
      TypeError: if loc and scale are different dtypes.


    #### References

    [1] J.E. Moyal, "XXX. Theory of ionization fluctuations",
       The London, Edinburgh, and Dublin Philosophical Magazine
       and Journal of Science.
       https://www.tandfonline.com/doi/abs/10.1080/14786440308521076
    [2] G. Cordeiro, J. Nobre, R. Pescim, E. Ortega,
        "The beta Moyal: a useful skew distribution",
        https://www.arpapress.com/Volumes/Vol10Issue2/IJRRAS_10_2_02.pdf
    )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moyal_cdf_bijectorZMoyalCDF_moyal_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__ g/home/dcms/DCMS/lib/python3.7/site-packages/tensorflow_probability/python/distributions/_numpy/moyal.pyr"   j   s(    *


zMoyal.__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Moyal._param_shapesc             C   s   t dddS )Nr   )r   r   )r   )clsr'   r'   r(   _params_event_ndims   s    zMoyal._params_event_ndimsc             C   s   | j jS )z(Distribution parameter for the location.)r    r   )r%   r'   r'   r(   r      s    z	Moyal.locc             C   s   | j jS )z!Distribution parameter for scale.)r    r   )r%   r'   r'   r(   r      s    zMoyal.scalec             C   s@   | j t| j }dddtj|  tj tdtj   S )Ng      ?g      ?r)   g      @)	r   r   	ones_liker   mathlogr#   euler_gammapi)r%   r   r'   r'   r(   _entropy   s    zMoyal._entropyc             C   sN   t | j}|| j | }d|t |   dtdtj   t j| S )Ng      g      ?g       @)	r   r+   r   r   expr#   r2   r4   r1   )r%   xr   zr'   r'   r(   	_log_prob   s    zMoyal._log_probc             C   s   | j | jtjtd   S )Ng       @)r   r   r#   r3   r2   )r%   r'   r'   r(   _mean   s    zMoyal._meanc             C   s"   | j t| j tj td S )Ng       @)r   r   r0   r   r#   r4   sqrt)r%   r'   r'   r(   _stddev   s    zMoyal._stddevc             C   s   | j t| j S )N)r   r   r0   r   )r%   r'   r'   r(   _mode   s    zMoyal._modec             C   s   t j| jdS )N)r   )identity_bijectorZIdentityr   )r%   r'   r'   r(   _default_event_space_bijector   s    z#Moyal._default_event_space_bijectorc             C   s   | j |S )N)r    _parameter_control_dependencies)r%   Zis_initr'   r'   r(   r@      s    z%Moyal._parameter_control_dependencies)FTr   )__name__
__module____qualname____doc__r"   staticmethodr-   classmethodr/   propertyr   r   r5   r9   r:   r<   r=   r?   r@   __classcell__r'   r'   )r&   r(   r   (   s   @  Dc          	   C   s   t |p
d t | j}t |j}t | j}t |j}t j|td | || |  t j	d||   dttj
  }d||| |  d || d tjtd   dt j||    S Q R X dS )a/  Calculate the batched KL divergence KL(a || b) with a and b Moyal.

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

  Returns:
    Batchwise KL(a || b)
  Zkl_moyal_moyalg       @g      ?   r)   N)r   r   r+   r   r   r1   r6   r#   r2   lgammar4   r3   )abr   Za_locZb_locZa_scaleZb_scaleZexp_termr'   r'   r(   _kl_moyal_moyal   s    D.rM   )N)rD   
__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   __all__ZTransformedDistributionr   Z
RegisterKLrM   r'   r'   r'   r(   <module>   s&    >
