B
    `4                 @   s   d 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d ZG dd de	jZdS )z!The Empirical distribution class.    )absolute_import)division)print_function)v2)distribution)assert_util)distribution_util)
dtype_util)prefer_static)reparameterization)samplers)tensor_util)tensorshape_util	Empiricalc             C   s   t jt |d| d  t |t || d gdd}| t j|| jd } t j| | d d} |t j| |jd }| |fS )z Broadcasts the event or samples.N   r   )axis)dtype)tfconcatshaperankZonesr   expand_dimsZ	ones_like)eventsamplesevent_ndimssamples_shape r   k/home/dcms/DCMS/lib/python3.7/site-packages/tensorflow_probability/python/distributions/_numpy/empirical.py_broadcast_event_and_samples&   s    r   c                   s   e Zd ZdZd, fdd	Zedd Zd	d
 Zedd Z	dd Z
dd Zd-ddZdd Zd.ddZdd Zd/ddZdd Zd0ddZd1d d!Zd"d# Zd$d% Zd&d' Zd(d) Zd*d+ Z  ZS )2r   a9  Empirical distribution.

  The Empirical distribution is parameterized by a [batch] multiset of samples.
  It describes the empirical measure (observations) of a variable.

  Note: some methods (log_prob, prob, cdf, mode, entropy) are not differentiable
  with regard to samples.

  #### Mathematical Details

  The probability mass function (pmf) and cumulative distribution function (cdf)
  are

  ```none
  pmf(k; s1, ..., sn) = sum_i I(k)^{k == si} / n
  I(k)^{k == si} == 1, if k == si, else 0.
  cdf(k; s1, ..., sn) = sum_i I(k)^{k >= si} / n
  I(k)^{k >= si} == 1, if k >= si, else 0.
  ```

  #### Examples

  ```python

  # Initialize a empirical distribution with 4 scalar samples.
  dist = Empirical(samples=[0., 1., 1., 2.])
  dist.cdf(1.)
  ==> 0.75
  dist.prob([0., 1.])
  ==> [0.25, 0.5] # samples will be broadcast to
                    [[0., 1., 1., 2.], [0., 1., 1., 2.]] to match event.

  # Initialize a empirical distribution with a [2] batch of scalar samples.
  dist = Empirical(samples=[[0., 1.], [1., 2.]])
  dist.cdf([0., 2.])
  ==> [0.5, 1.]
  dist.prob(0.)
  ==> [0.5, 0] # event will be broadcast to [0., 0.] to match samples.

  # Initialize a empirical distribution with 4 vector-like samples.
  dist = Empirical(samples=[[0., 0.], [0., 1.], [0., 1.], [1., 2.]],
                   event_ndims=1)
  dist.cdf([0., 1.])
  ==> 0.75
  dist.prob([[0., 1.], [1., 2.]])
  ==> [0.5, 0.25] # samples will be broadcast to shape [2, 4, 2] to match event.

  # Initialize a empirical distribution with a [2] batch of vector samples.
  dist = Empirical(samples=[[[0., 0.], [0., 1.]], [[0., 1.], [1., 2.]]],
                   event_ndims=1)
  dist.cdf([[0., 0.], [0., 1.]])
  ==> [0.5, 0.5]
  dist.prob([0., 1.])
  ==> [0.5, 1.] # event will be broadcast to shape [[0., 1.], [0., 1.]]
                  to match samples.
  ```

  r   FTc       	   	      s   t t }t|h t|| _tj| jg| jj	d}|| _
t| j}|| j
 d | _tt| j|tj||||d W dQ R X dS )a  Initialize `Empirical` distributions.

    Args:
      samples: Numeric `Tensor` of shape [B1, ..., Bk, S, E1, ..., En]`,
        `k, n >= 0`. Samples or batches of samples on which the distribution
        is based. The first `k` dimensions index into a batch of independent
        distributions. Length of `S` dimension determines number of samples
        in each multiset. The last `n` dimension represents samples for each
        distribution. n is specified by argument event_ndims.
      event_ndims: Python `int32`, default `0`. number of dimensions for each
        event. When `0` this distribution has scalar samples. When `1` this
        distribution has vector-like samples.
      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:
      ValueError: if the rank of `samples` is statically known and less than
        event_ndims + 1.
    )
dtype_hintr   )r   Zreparameterization_typevalidate_argsallow_nan_stats
parametersnameN)dictlocalsr   Z
name_scoper   Zconvert_nonref_to_tensor_samplesr	   Zcommon_dtyper   _event_ndimsr
   r   r   _samples_axissuperr   __init__r   ZFULLY_REPARAMETERIZED)	selfr   r   r    r!   r#   r"   r   samples_rank)	__class__r   r   r*   u   s    !

zEmpirical.__init__c             C   s   dt j| t jdiS )Nr   )r   )r   convert_to_tensorint32)Zsample_shaper   r   r   _param_shapes   s    zEmpirical._param_shapesc             C   s   t | jd dS )Nr   )r   )r$   r'   )r+   r   r   r   _params_event_ndims   s    zEmpirical._params_event_ndimsc             C   s   | j S )zDistribution parameter.)r&   )r+   r   r   r   r      s    zEmpirical.samplesc          	   C   s"   |  d | | jS Q R X dS )aC  Compute and return the number of values in `self.samples`.

    Returns:
      num_samples: int32 `Tensor` containing the number of entries in
        `self.samples`. If `self.samples` has shape `[..., S, E1, ..., Ee]`
        where the `E`'s are event dims, this method returns a `Tensor` whose
        values is `S`.
    compute_num_samplesN)Z_name_and_control_scope_compute_num_samplesr   )r+   r   r   r   r2      s    	zEmpirical.compute_num_samplesc             C   s"   t |}tj|| j tjddS )Nnum_samples)r   r#   )r   Zprefer_static_shaper   r.   r(   r/   )r+   r   r   r   r   r   r3      s
    
zEmpirical._compute_num_samplesNc             C   s(   |d krt | j}t |d | j S )N)r   r.   r   r   r(   )r+   r   r   r   r   _batch_shape_tensor   s    zEmpirical._batch_shape_tensorc             C   s.   t | jjd krtd S | jjd | j S )N)r   r   r   r   r   TensorShaper(   )r+   r   r   r   _batch_shape   s    
zEmpirical._batch_shapec             C   s,   |d krt | j}t || jd d  S )Nr   )r   r.   r   r   r(   )r+   r   r   r   r   _event_shape_tensor   s    zEmpirical._event_shape_tensorc             C   s2   t | jjd krtd S | jj| jd d  S )Nr   )r   r   r   r   r   r6   r(   )r+   r   r   r   _event_shape   s    
zEmpirical._event_shapec             C   s$   |d krt | j}t j|| jdS )N)r   )r   r.   r&   reduce_meanr(   )r+   r   r   r   r   _mean   s    zEmpirical._meanc             C   sH   t | j}| j}|t j| ||d }t jt ||d}t |S )N)r   )	r   r.   r&   r(   r   r;   r:   Zsquaresqrt)r+   r   r   rvarr   r   r   _stddev   s
    zEmpirical._stddevc             C   s   t | j}tj|g| |t j|d}t j||| jd}t j	| jgt j
| jt jdt j
| jt jd| j d gdd}t j||d}|S )N)maxvalr   seed)r   )r   r   r   )aZperm)r   r.   r&   r   uniformr3   r/   Zgatherr(   r   ranger'   Z	transpose)r+   nrA   r   indicesZdrawsZaxesr   r   r   	_sample_n   s    zEmpirical._sample_nc       
      C   s   dd }|d krt | j}| |}| jdkrLt |d|g}| |}n@t | |}t j	| || |gdd}t |d||g}t j
||t jd}t jt t |d t |t jgdd}t ||}	t |	|S )Nc             S   s   t jj| dgdj}t |S )Nr   )xr   )r   raw_opsUniqueWithCountsV2countZargmax)r   rK   r   r   r   	_get_mode   s    z"Empirical._mode.<locals>._get_moder   )r   )Zfn_output_signaturer   )r   r.   r&   r3   r'   reshaper5   reduce_prodr8   r   map_fnint64stackrD   r   castr/   Z	gather_nd)
r+   r   rL   r4   Zflattened_samplesZ
mode_shape
event_sizerF   Zfull_indicesmoder   r   r   _mode   s*    



zEmpirical._modec                s   t j}| |}jdkr<t |d g}n t  }t |d |g} fdd}t j	||j
d}t ||S )Nr   rM   c                sD   t jj| dgdj}t j|  jd}t | t j| }|S )Nr   )rH   r   )r   )	r   rI   rJ   rK   rS   r   
reduce_summathlog)r   rK   probentropy)r4   r+   r   r   _get_entropy%  s    z(Empirical._entropy.<locals>._get_entropy)r   )r   r.   r   r3   r5   r'   rN   rO   Zevent_shape_tensorrP   r   )r+   r   Zentropy_shaperT   r\   r[   r   )r4   r+   r   _entropy  s    


zEmpirical._entropyc             C   s   t | j}| |}t j|d| jd}t||| jd\}}t jt jt j	||kt 
| j ddt jddd| }t| jrt || j}|S )Nr   )r#   r   )r   r   )r   )r   rM   )r   r.   r&   r3   r   r   r'   rW   rS   
reduce_allrD   r/   r	   is_floating)r+   r   r   r4   Zcdfr   r   r   _cdf.  s    
zEmpirical._cdfc             C   s   t | j}| |}t j|d| jd}t||| jd\}}t jt jt j	t 
||t | j ddt jddd| }t| jrt || j}|S )Nr   )r#   r   )r   r   )r   )r   rM   )r   r.   r&   r3   r   r   r'   rW   rS   r^   equalrD   r/   r	   r_   )r+   r   r   r4   rZ   r   r   r   _prob>  s    
zEmpirical._probc             C   s   d S )Nr   )r+   r   r   r   _default_event_space_bijectorN  s    z'Empirical._default_event_space_bijectorc             C   st   g }d}|r^t | jj}|d k	r:|| jd k r^t|n$| jr^|tj	| j
| jd |d | jsp|rltg S |S )Nz5Rank of `samples` must be at least `event_ndims + 1`.r   )message)r   r   r   r   r'   
ValueErrorZ_validate_argsappendr   Zassert_rank_at_leastr&   AssertionError)r+   Zis_initZ
assertionsrd   r,   r   r   r   _parameter_control_dependenciesQ  s    
z)Empirical._parameter_control_dependencies)r   FTr   )N)N)N)N)N)__name__
__module____qualname____doc__r*   staticmethodr0   r1   propertyr   r2   r3   r5   r7   r8   r9   r;   r?   rG   rV   r]   r`   rb   rc   rh   __classcell__r   r   )r-   r   r   9   s.   :   1




!N)rl   
__future__r   r   r   Z;tensorflow_probability.python.internal.backend.numpy.compatr   r   Z2tensorflow_probability.python.distributions._numpyr   Z-tensorflow_probability.python.internal._numpyr   r   r	   r
   Z&tensorflow_probability.python.internalr   r   r   r   __all__r   Distributionr   r   r   r   r   <module>   s    