B
    ²ô`zO  ã               @   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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gZejdejde  ej¡j!dej"dej"de  ej"¡j!dej#dej#de  ej#¡j!di	Z$G dd„ dej%ƒZ&dd„ Z'dd„ Z(dd„ Z)dd„ Z*d dd„Z+dS )!zThe Bates distribution class.é    )Úabsolute_import)Údivision)Úprint_functionN)Úv2)Ú_numpy)Úsigmoid)Údistribution)Úassert_util)Údistribution_util)Ú
dtype_util)Úprefer_static)Úreparameterization)Úsamplers)Útensor_utilÚBatesg     ÀR@g      9@g      @c                   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e	dd„ ƒZdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zd/dd„Zdd „ Zd!d"„ Zd#d$„ Ze d%¡d&d'„ ƒZd(d)„ Zd*d+„ Zd,d-„ Z‡  ZS )0r   aÐ  Bates distribution.

  The Bates distribution is the distribution of the average of `total_count`
  independent samples from `Uniform(low, high)`. It is parameterized by the
  interval bounds `low` and `high`, and `total_count`, the number of samples.

  Although some care has been taken to avoid numerical issues, the `pdf`, `cdf`,
  and log versions thereof may still exhibit numerical instability. They are
  relatively stable near the tails; however near the mode they are unstable if
  `total_count` is greater than about `75` for `tf.float64`, `25` for
  `tf.float32`, and `7` for `tf.float16`. Beyond these limits a warning will be
  shown if `validate_args=False`; otherwise an exception is thrown. For high
  `total_count`, consider using a `Normal` approximation.

  #### Mathematical Details

  The probability density function (pdf) is supported in the interval
  `[low, high]`. If `[low, high]` is the unit interval `[0, 1]`, the pdf
  is,

  ```none
  pdf(x; n, 0, 1) =
    ((n / (n-1)!) sum_{k=0}^j (-1)^k (n choose k) (nx - k)^{n-1}
  ```

  where
  * `total_count = n`,
  * `j = floor(nx)`
  * `n!` is the factorial of `n`,
  * `(n choose k)` is the binomial coefficient `n! / (k!(n - k)!),

  For arbitrary intervals `[low, high]`, the pdf is,

  ```none
  pdf(x; n, low, high) = pdf((x - low) / (high - low); n, 0, 1) / (high - low)
  ```

  #### Examples

  Create a single distribution for the mean of 5 uniform random variables on the
  interval `[-10, 5]`.

  ```python
  dist = tfd.Bates(total_count=5., low=-10., high=5.)
  ```

  Create a 3-batch of distributions with varying total counts and intervals.

  ```python
  counts = [1., 2., 5.]
  # high will be broadcast to [100., 100., 100.]
  dist = tfd.Bates(total_count=counts, low=[0., 5., 10.], high=100.)
  ```

  Compute some values for the pdf.

  ```python
  dist.probs(50.).eval()    # shape: [3]
  x = [[50., 50., 50.],
       [5., 10., 20.]]      # shape: [2, 3]
  dist.probs(x).eval()      # shape: [2]
  ```
  ç        ç      ð?FTc       	   	      s¤   t tƒ ƒ}t |¡†}tj||gtjd}|tjtjfksBtdƒ‚t	j
|d|d| _t	j
||dd| _t	j
||dd| _tt| ƒj|tj||||d W d	Q R X d	S )
a‡  Construct a Bates distribution.

    Args:
      total_count: Non-negative integer-valued `Tensor` with shape broadcastable
        to the batch shape `[N1,..., Nm]`, `m >= 0`. This controls the number of
        samples of `Uniform(low, high)` to take the mean of.
      low: Floating point `Tensor` representing the lower bounds of the support.
        Should be broadcastable to `[N1,..., Nm]` with `m >= 0`, the same dtype
        as `total_count`, and `low < high` component-wise, after broadcasting.
        Defaults to `0`.
      high: Floating point `Tensor` representing the upper bounds of the
        support.  Should be broadcastable to `[N1,..., Nm]` with `m >= 0`, the
        same dtype as `total_count`, and `low < high` component-wise, after
        broadcasting.  Defaults to `1`.
      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.
    )Ú
dtype_hintz2`Bates` only supports `tf.float32` or `tf.float64`Útotal_count)Únamer   Úlow)Údtyper   Úhigh)r   Zreparameterization_typeÚvalidate_argsÚallow_nan_statsÚ
parametersr   N)ÚdictÚlocalsÚtfZ
name_scoper   Zcommon_dtypeÚfloat32Úfloat64ÚAssertionErrorr   Zconvert_nonref_to_tensorÚ_total_countÚ_lowÚ_highÚsuperr   Ú__init__r   ZNOT_REPARAMETERIZED)	Úselfr   r   r   r   r   r   r   r   )Ú	__class__© úg/home/dcms/DCMS/lib/python3.7/site-packages/tensorflow_probability/python/distributions/_numpy/bates.pyr&   ~   s$    

zBates.__init__c             C   s    t tdtj| tjdgd ƒƒS )N)r   r   r   )r   é   )r   Úzipr   Úconvert_to_tensorÚint32)Zsample_shaper)   r)   r*   Ú_param_shapes±   s    zBates._param_shapesc             C   s   t ddddS )Nr   )r   r   r   )r   )Úclsr)   r)   r*   Ú_params_event_ndims·   s    zBates._params_event_ndimsc             C   s   | j S )z6Number of `Uniform` trials used to construct a sample.)r"   )r'   r)   r)   r*   r   »   s    zBates.total_countc             C   s   | j S )zLower bound of the support.)r#   )r'   r)   r)   r*   r   À   s    z	Bates.lowc             C   s   | j S )zUpper bound of the support.)r$   )r'   r)   r)   r*   r   Å   s    z
Bates.highc             C   s   d| j fd| jfd| jfgS )Nr   r   r   )r"   r#   r$   )r'   r)   r)   r*   Ú_params_listÊ   s    zBates._params_listc             C   s   t  tjdd„ |  ¡ D ƒ¡S )Nc             S   s   g | ]\}}t  |¡‘qS r)   )ÚpsÚshape)Ú.0Ú_Úparamr)   r)   r*   ú
<listcomp>Ò   s    z-Bates._batch_shape_tensor.<locals>.<listcomp>)Ú	functoolsÚreducer3   Úbroadcast_shaper2   )r'   r)   r)   r*   Ú_batch_shape_tensorÏ   s    zBates._batch_shape_tensorc             C   s   t  tjdd„ |  ¡ D ƒ¡S )Nc             S   s   g | ]\}}|j ‘qS r)   )r4   )r5   r6   r7   r)   r)   r*   r8   ×   s    z&Bates._batch_shape.<locals>.<listcomp>)r9   r:   r   Zbroadcast_static_shaper2   )r'   r)   r)   r*   Ú_batch_shapeÔ   s    zBates._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Bates._event_shape_tensorc             C   s
   t  g ¡S )N)r   ZTensorShape)r'   r)   r)   r*   Ú_event_shapeÜ   s    zBates._event_shapeNc             C   sF   t  | jt j¡}t  | j¡}t  | j¡}tt 	||  
¡ ¡||||dS )N)Úseed)r   Úcastr   r.   r-   r   r   Ú_sample_batesr3   Úbroadcast_tor<   )r'   Únr@   r   r   r   r)   r)   r*   Ú	_sample_nß   s    zBates._sample_nc             C   s   t | j| j| j| j|ƒS )N)Ú
_bates_pdfr   r   r   r   )r'   Úvaluer)   r)   r*   Ú_probç   s    zBates._probc             C   s   t | j| j| j| j|ƒS )N)Ú
_bates_cdfr   r   r   r   )r'   rG   r)   r)   r*   Ú_cdfê   s    z
Bates._cdfc             C   s   | j | j d S )Ng       @)r   r   )r'   r)   r)   r*   Ú_meaní   s    zBates._meanzGFor `n = 1`, any value in `(low, high)` is a mode; this gives the mean.c             C   s   |   ¡ S )N)rK   )r'   r)   r)   r*   Ú_modeð   s    zBates._modec             C   s(   t j | j| j ¡dt  | j| j¡  S )Ng      (@)r   ÚmathZsquarer   r   rA   r   r   )r'   r)   r)   r*   Ú	_varianceõ   s    zBates._variancec             C   s   t j| j| j| jdS )N)r   r   r   )Úsigmoid_bijectorZSigmoidr   r   r   )r'   r)   r)   r*   Ú_default_event_space_bijectorù   s    z#Bates._default_event_space_bijectorc             C   s
  | j s
g S |rZy|  ¡  W n> tk
rX   td t | j¡t | j¡t | j¡¡ƒ‚Y nX g }|t	 
| j¡krÎt | j¡}t| j }| tj|ddtj|ddtjt || j¡t || j¡d |¡dg¡ |t	 
| j¡pæt	 
| j¡kr| tj| j| jdd¡ |S )NzyArguments `total_count`, `low` and `high` must have compatible shapes; total_count.shape={}, low.shape={}, high.shape={}.z`total_count` must be positive.)Úmessagez%`total_count` must be integer-valued.z+`total_count` > {} is numerically unstable.z`low` must be less than `high`.)r   r=   Ú
ValueErrorÚformatr   r4   r   r   r   r   Zis_refr-   Ú"BATES_TOTAL_COUNT_STABILITY_LIMITSr   Úextendr	   Zassert_positiver
   Zassert_integer_formZassert_less_equalrA   ÚappendZassert_less)r'   Zis_initZ
assertionsr   Úlimitr)   r)   r*   Ú_parameter_control_dependenciesý   s@    


z%Bates._parameter_control_dependencies)r   r   FTr   )N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r&   Ústaticmethodr/   Úclassmethodr1   Úpropertyr   r   r   r2   r<   r=   r>   r?   rE   rH   rJ   rK   r
   ZAppendDocstringrL   rN   rP   rX   Ú__classcell__r)   r)   )r(   r*   r   =   s2   ?    -
c             C   sö  t  | |¡} t  |¡}t  |¡}t  t| |ƒg¡¸ || }|| | }t  |dd¡}t  |dk |d| ¡}t  t j |¡||¡}t	 
t	 |¡t	 | ¡¡}t	 | |¡}	| | }
t  |	dg¡}t  |
dg¡}t jt j |d ¡t jd}t  t|ƒ|¡}t  ||¡}t  ||¡}t  d|¡| d|d t j t || d |d ¡¡   || |d   }t  t  t  |¡¡|¡}t j ||¡}t  ||¡}||	 |t j t j |	¡¡  }t  |dk |dkB t  d|¡|¡}t  t j |¡|tj¡}|S Q R X dS )	aè  Compute the Bates pdf.

  Internally, the (standard, unnormalized) pdf is computed by the formula

  ```none
  pdf = sum_{k=0}^j (-1)^k (n choose k) (nx - k)^{n - 1}
  ```

  where
  * `n = total_count`,
  * `x = value` the value to compute the probability of, and
  * `j = floor(nx)`.

  This is shifted to `[low, high]` and normalized. Since the pdf is symmetric,
  we only compute the left half, which keeps the number of terms lower.

  Computation is batched, using `tf.math.segment_sum()`. For this reason this is
  not compatible with `tf.vectorized_map()`.

  All input parameters should have compatible dtypes and shapes.

  Args:
    total_count: `Tensor` with integer values, as given to the `Bates`
      constructor.
    low: Float `Tensor`, as given to the `Bates` constructor.
    high: Float `Tensor`, as given to the `Bates` constructor.
    dtype: The dtype of the output.
    value: Float `Tensor`. Input value to `prob()`.
  Returns:
    pdf: Float `Tensor`. See above formula.
  g        g      ð?g      à?éÿÿÿÿé   )r   g      ð¿N)r   rA   r-   Úcontrol_dependenciesÚ_stability_limit_tensorÚclip_by_valueÚwhererM   Ú	is_finiter3   r;   r4   rC   ÚreshapeÚfloorr.   Ú_segmented_rangeÚrepeatÚexpÚtfp_mathÚlbetaÚrangeÚsizeÚsegment_sumÚlgammaÚnpÚnan)r   r   r   r   rG   Zrange_Úvalue_centeredÚ	value_adjr4   Útotal_count_bÚtotal_count_x_value_adj_bÚtotal_count_fÚtotal_count_x_value_adj_fÚnum_terms_fÚ
term_idx_sÚtotal_count_sÚtotal_count_x_value_adj_sÚtermsÚsegment_idsZpdf_sZpdfr)   r)   r*   rF   )  s<     


LrF   c             C   s  t  | |¡} t  |¡}t  |¡}t  t| |ƒg¡Ü || ||  }t  |dd¡}t  |dk |d| ¡}t  t j |¡||¡}t	 
t	 |¡t	 | ¡¡}t	 | |¡}| | }	t  |dg¡}
t  |	dg¡}t jt j |d ¡t jd}t  t|ƒ|¡}t  |
|¡}t  ||¡}t  d|¡| d|d t j t || d |d ¡¡   || |  }t  t  t  |¡¡|¡}t j ||¡}t  ||¡}|t j t j |t  d|¡ ¡¡ }t  |dkd| |¡}t  |dk t  d|¡|¡}t  |dkt  d|¡|¡}t  t j |¡|tj¡}|S Q R X dS )	a$  Compute the Bates cdf.

  Internally, the (standard, unnormalized) cdf is computed by the formula

  ```none
  pdf = sum_{k=0}^j (-1)^k (n choose k) (nx - k)^n
  ```

  where
  * `n = total_count`,
  * `x = value` the value to compute the cumulative probability of, and
  * `j = floor(nx)`.

  This is shifted to `[low, high]` and normalized. Since the pdf is symmetric,
  we have `cdf(x) = 1 - cdf(1 - x)` for `x > .5`, hence we only compute the left
  half, which keeps the number of terms lower.

  Computation is batched, using `tf.math.segment_sum()`. For this reason this is
  not compatible with `tf.vectorized_map()`.

  All input parameters should have compatible dtypes and shapes.

  Args:
    total_count: `Tensor` with integer values, as given to the `Bates`
      constructor.
    low: Float `Tensor`, as given to the `Bates` constructor.
    high: Float `Tensor`, as given to the `Bates` constructor.
    dtype: The dtype of the output.
    value: Float `Tensor`. Input value to `cdf()`.
  Returns:
    cdf: Float `Tensor`. See above formula.
  g        g      ð?g      à?ra   rb   )r   g      ð¿N)r   rA   r-   rc   rd   re   rf   rM   rg   r3   r;   r4   rC   rh   ri   r.   rj   rk   rl   rm   rn   ro   rp   rq   rr   rs   rt   )r   r   r   r   rG   ru   rv   r4   rw   rx   ry   rz   r{   r|   r}   r~   r   r€   Zcdf_sZcdfr)   r)   r*   rI   {  s:    !


H$rI   c                s4   t  t| |¡‰ t  t j | ˆ k¡‡ fdd„t j¡S )Nc                  s   t jdˆ tjdS )Nz6WARNING: Bates PDF/CDF is unstable for `total_count` >)Zoutput_stream)r   ÚprintÚsysÚstderrr)   )rW   r)   r*   Ú<lambda>Ò  s   z)_stability_limit_tensor.<locals>.<lambda>)r   rA   rT   ZcondrM   Z
reduce_anyZno_op)r   r   r)   )rW   r*   rd   Í  s
    
rd   c          
   C   s:   t  t  | ¡¡t  t jdgt  | dd… ¡gdd| ¡ S )zàEquivalent to `tf.ragged.range(limits).flat_values`.

  Ragged Tensors are are not supported by numpy.

  Args:
    limits: Integer `Tensor` of sizes of each range.

  Returns:
    segments: 1D `Tensor` of segment ranges.
  r   Nra   )Úaxis)r   ro   Ú
reduce_sumrk   ÚconcatZcumsum)Zlimitsr)   r)   r*   rj   Ø  s    rj   c             C   sÄ   t jt  | ¡g|ggdd}tj|dd|j|d}t  | dg¡}t  t  t  	|¡¡|¡}t j
 ||¡}	t jt  | ¡|ggdd}
t  |	|
¡}t  t  |¡¡}t  |t j|ddd¡}||| |  S )	a:  Vectorized production of `Bates` samples.

  Args:
    total_count: (Batches of) counts of `Uniform`s to take means of.  Should
      have integer dtype and already be broadcasted to the batch shape.
    low: (Batches of) lower bounds of the `Uniform` variables to sample.  Should
      be the same floating dtype as `high` and broadcastable to the batch shape.
    high: (Batches of) upper bounds of the `Uniform` variables to sample. Should
      be the same floating dtype as `low` and broadcastable to the batch shape.
    n: `int32` number of samples to generate.
    seed: Random seed to pass to `Uniform` sampler.

  Returns:
    samples: Samples of (batches of) the `Bates` variable.  Will have same dtype
      as `low` and `high`. If the batch shape is `[B1,..., Bn]`, `samples` has
      shape `[n, B1,..., Bn]`.
  r   )r…   g        g      ð?)ÚminvalÚmaxvalr   r@   ra   rb   )Úshiftr…   )r   r‡   r†   r   Úuniformr   rh   rk   ro   rp   rM   Zsegment_meanr4   ZrankZ	transposeZroll)r   r   r   rD   r@   Zuniform_sample_shapeZuniform_samplesZsegment_lengthsr€   Z	flatmeansZoutshapeZtmeansZaxesZmeansr)   r)   r*   rB   è  s    rB   )N),r\   Ú
__future__r   r   r   r9   r‚   Únumpyrs   Z;tensorflow_probability.python.internal.backend.numpy.compatr   r   Z"tensorflow_probability.python.mathr   rm   Z.tensorflow_probability.python.bijectors._numpyr   rO   Z2tensorflow_probability.python.distributions._numpyr   Z-tensorflow_probability.python.internal._numpyr	   r
   r   r   r3   Z&tensorflow_probability.python.internalr   r   r   Ú__all__r    Zfinfor   r   Úfloat16rT   ÚDistributionr   rF   rI   rd   rj   rB   r)   r)   r)   r*   Ú<module>   sD    mRR