B
    `1F                 @   s2  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dde	jddfddZdde	jddfddZe	jdddde	jddfddZG dd dejZe	jdfddZ e	jdfddZ!dS )zThe Poisson distribution class.    )absolute_import)division)print_functionN)v2)distribution)assert_util)batched_rejection_sampler)distribution_util)
dtype_util)implementation_selection)reparameterization)samplers)tensor_utilPoissonc          	   C   sZ   t |p
dB |dkr$t j|}t j| t |gdd} t jj| |||dS Q R X dS )z2Sample using *fast* `tf.random.stateless_poisson`.Zpoisson_cpuNr   )axis)shapeseedZlamdtype)tf
name_scopemathexpconcatr   randomZstateless_poisson)r   rates	log_ratesoutput_dtyper   name r   i/home/dcms/DCMS/lib/python3.7/site-packages/tensorflow_probability/python/distributions/_numpy/poisson.py_random_poisson_cpu'   s    r    c          	   C   s
  t |p
d |dkr$t j|}t j| t |gdd} t j| }t j}t	|\}}	||t
dk@ }
t ||}t |
|d}t| |||	d}t ||}||
 @ }t |t j|d}t| |||d	}t ||}t |t |
||t
j}W dQ R X |S )
z9Sample using XLA-friendly python-based rejection sampler.Zpoisson_noncpuNr   )r   g      $@g      Y@)log_rateinternal_dtyper   gh㈵>)rater"   r   )r   r   r   logr   r   is_nanfloat64r   
split_seednpcastwhere_random_poisson_high_rater   _random_poisson_low_ratenan)r   r   r   r   r   r   Zgood_params_maskr"   Zseed_loZseed_hiZhigh_params_maskZcast_log_ratesZsafe_log_ratesZhigh_rate_samplesZlow_params_maskZ	safe_rateZlow_rate_samplessamplesr   r   r   _random_poisson_noncpu7   s2    
r/   F)Z	autographc          	   C   sd   t |p
dL t|}t j| t jdd} t| |||||d}tjdt	t
d}|f |S Q R X dS )a*  Sample a poisson, CPU specialized to stateless_poisson.

  Args:
    shape: Shape of the full sample output. Trailing dims should match the
      broadcast shape of `counts` with `probs|logits`.
    rates: Batch of rates for Poisson distribution.
    log_rates: Batch of log rates for Poisson distribution.
    output_dtype: DType of samples.
    seed: int or Tensor seed.
    name: Optional name for related ops.

  Returns:
    samples: Samples from poisson distributions.
    runtime_used_for_sampling: One of `implementation_selection._RUNTIME_*`.
  Zrandom_poissonr   )
dtype_hintr   )r   r   r   r   r   r   Zpoisson)fn_nameZ
default_fnZcpu_fnN)r   r   r   sanitize_seedconvert_to_tensorint32dictr   Zimplementation_selectingr/   r    )r   r   r   r   r   r   paramsZsampler_implr   r   r   _random_poissonf   s    
r7   c                   s  e Zd ZdZd8 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dd Zdd  Zd!d" Zd#d$ Zed%d&d' Zd9d(d)Zd:d*d+Zd,d- Zd;d.d/Zd0d1 Zd2d3 Zd4d5 Zd6d7 Z   Z!S )<r   a=  Poisson distribution.

  The Poisson distribution is parameterized by an event `rate` parameter.

  #### Mathematical Details

  The probability mass function (pmf) is,

  ```none
  pmf(k; lambda, k >= 0) = (lambda^k / k!) / Z
  Z = exp(lambda).
  ```

  where `rate = lambda` and `Z` is the normalizing constant.

  NTFc       	   	      s   t t }|dk|dkkr"tdt|}tj||gtjd}t|s`t	d
t|tj|d|d| _tj|d|d| _|| _tt| j|tj||||d W dQ R X dS )	a4  Initialize a batch of Poisson distributions.

    Args:
      rate: Floating point tensor, the rate parameter. `rate` must be positive.
        Must specify exactly one of `rate` and `log_rate`.
      log_rate: Floating point tensor, the log of the rate parameter.
        Must specify exactly one of `rate` and `log_rate`.
      interpolate_nondiscrete: Python `bool`. When `False`,
        `log_prob` returns `-inf` (and `prob` returns `0`) for non-integer
        inputs. When `True`, `log_prob` evaluates the continuous function
        `k * log_rate - lgamma(k+1) - rate`, which matches the Poisson pmf
        at integer arguments `k` (note that this function is not itself
        a normalized probability log-density).
        Default value: `True`.
      validate_args: Python `bool`. 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`. 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.

    Raises:
      ValueError: if none or both of `rate`, `log_rate` are specified.
      TypeError: if `rate` is not a float-type.
      TypeError: if `log_rate` is not a float-type.
    Nz2Must specify exactly one of `rate` and `log_rate`.)r0   z,[log_]rate.dtype ({}) is a not a float-type.r#   )r   r   r!   )r   Zreparameterization_typevalidate_argsallow_nan_stats
parametersr   )r5   locals
ValueErrorr   r   r
   Zcommon_dtypefloat32Zis_floating	TypeErrorformatr   r   Zconvert_nonref_to_tensor_rate	_log_rate_interpolate_nondiscretesuperr   __init__r   ZNOT_REPARAMETERIZED)	selfr#   r!   interpolate_nondiscreter8   r9   r   r:   r   )	__class__r   r   rD      s(    &


zPoisson.__init__c             C   s   t dddS )Nr   )r#   r!   )r5   )clsr   r   r   _params_event_ndims   s    zPoisson._params_event_ndimsc             C   s   | j S )zRate parameter.)r@   )rE   r   r   r   r#      s    zPoisson.ratec             C   s   | j S )zLog rate parameter.)rA   )rE   r   r   r   r!      s    zPoisson.log_ratec             C   s   | j S )z.Interpolate (log) probs on non-integer inputs.)rB   )rE   r   r   r   rF      s    zPoisson.interpolate_nondiscretec             C   s    | j d kr| jn| j }t|S )N)rA   r@   r   r   )rE   xr   r   r   _batch_shape_tensor   s    zPoisson._batch_shape_tensorc             C   s   | j d kr| jn| j }|jS )N)rA   r@   r   )rE   rJ   r   r   r   _batch_shape   s    zPoisson._batch_shapec             C   s   t jg t jdS )N)r   )r   Zconstantr4   )rE   r   r   r   _event_shape_tensor   s    zPoisson._event_shape_tensorc             C   s
   t g S )N)r   ZTensorShape)rE   r   r   r   _event_shape   s    zPoisson._event_shapec             C   sN   |   }| ||| | }| jsJttj|t	|j
tj |}|S )N)_log_rate_parameter_no_checks_log_unnormalized_prob_log_normalizationrF   r   r*   r   Zis_infr
   as_numpy_dtyper   r(   inf)rE   rJ   r!   Z	log_probsr   r   r   	_log_prob   s    

zPoisson._log_probc             C   s   t j| |S )N)r   r   r$   cdf)rE   rJ   r   r   r   _log_cdf  s    zPoisson._log_cdfc             C   sJ   t | jr|nt |d}t jd| |  }t |dk t ||S )Ng        g      ?)	r   maximumrF   floorr   Zigammac_rate_parameter_no_checksr*   Z
zeros_like)rE   rJ   safe_xrU   r   r   r   _cdf  s    zPoisson._cdfc             C   s
   t |S )N)r   r   )rE   r!   r   r   r   rQ     s    zPoisson._log_normalizationc             C   s`   t | jr|nt |d}t j||t jd|  }t t |||t	
|jtj S )Ng        g      ?)r   rW   rF   rX   r   Zmultiply_no_nanlgammar*   equalr
   rR   r   r(   rS   )rE   rJ   r!   rZ   yr   r   r   rP     s    zPoisson._log_unnormalized_probc             C   s   |   S )N)rY   )rE   r   r   r   _mean  s    zPoisson._meanc             C   s   |   S )N)rY   )rE   r   r   r   	_variance  s    zPoisson._variancezNote: when `rate` is an integer, there are actually two modes: `rate`
      and `rate - 1`. In this case we return the larger, i.e., `rate`.c             C   s   t |  S )N)r   rX   rY   )rE   r   r   r   _mode!  s    zPoisson._modec             C   sV   t |}tt|g| jd kr$d n
t| j| jd kr<d n
t| j| j|dd S )N)r   r   r   r   r   r   )r   r2   r7   r   r3   r@   rA   r   )rE   nr   r   r   r   	_sample_n'  s    



zPoisson._sample_nc          	   C   s"   |  |p
d
 |  S Q R X dS )zCRate vec computed from non-`None` input arg (`rate` or `log_rate`).rate_parameterN)_name_and_control_scoperY   )rE   r   r   r   r   rd   2  s    zPoisson.rate_parameterc             C   s"   | j d krt| jS t| j S )N)r@   r   r   rA   identity)rE   r   r   r   rY   7  s    
z!Poisson._rate_parameter_no_checksc          	   C   s"   |  |p
d
 |  S Q R X dS )zELog-rate vec computed from non-`None` input arg (`rate`, `log_rate`).log_rate_parameterN)re   rO   )rE   r   r   r   r   rg   <  s    zPoisson.log_rate_parameterc             C   s$   | j d krtj| jS t| j S )N)rA   r   r   r$   r@   rf   )rE   r   r   r   rO   A  s    
z%Poisson._log_rate_parameter_no_checksc             C   s   d S )Nr   )rE   r   r   r   _default_event_space_bijectorF  s    z%Poisson._default_event_space_bijectorc             C   sB   | j s
g S g }| jd k	r>|t| jkr>|tj| jdd |S )Nz%Argument `rate` must be non-negative.)message)r8   r@   r   Zis_refappendr   Zassert_non_negative)rE   Zis_init
assertionsr   r   r   _parameter_control_dependenciesI  s    

z'Poisson._parameter_control_dependenciesc             C   s"   g }| j s|S |t| |S )N)r8   extendr	   Zassert_nonnegative_integer_form)rE   rJ   rk   r   r   r   _sample_control_dependenciesT  s
    z$Poisson._sample_control_dependencies)NNTFTr   )N)N)N)"__name__
__module____qualname____doc__rD   classmethodrI   propertyr#   r!   rF   rK   rL   rM   rN   rT   rV   r[   rQ   rP   r_   r`   r	   ZAppendDocstringra   rc   rd   rY   rg   rO   rh   rl   rn   __classcell__r   r   )rG   r   r      s@        6	


c                sn   t jddt jd   dd   ddd    fd	d
}tj||dd }|S )a  Samples from the Poisson distribution using transformed rejection sampling.

  Given a CDF F(x), and G(x), a dominating distribution chosen such that it is
  close to the inverse CDF F^-1(x), compute the following steps:

  1) Generate U and V, two independent random variates. Set U = U - 0.5 (this
  step isn't strictly necessary, but is done to make some calculations symmetric
  and convenient. Henceforth, G is defined on [-0.5, 0.5]).

  2) If V <= alpha * F'(G(U)) * G'(U), return floor(G(U)), else return to
  step 1. alpha is the acceptance probability of the rejection algorithm.
  The dominating distribution in this case:
    G(u) = (2 * a / (2 - |u|) + b) * u + c

  For more details on transformed rejection, see [1].

  Args:
    sample_shape: The output sample shape. Must broadcast with `log_rate`.
    log_rate: Floating point tensor, log rate.
    internal_dtype: dtype to use for internal computations.
    seed: (optional) The random seed.

  Returns:
    Samples from the poisson distribution using transformed rejection.

  #### References

  [1]: W. Hormann, G. Derflinger, The Transformed Rejection Method For
  Generating Random Variables, An Alternative To The Ratio Of Uniforms Method
  (1994), Manuskript, Institut f. Statistik, Wirtschaftsuniversitat
  gn?g=
ףp=@g      ?gh|?5g[	m?g$~?gr?g333333@c       
         s   t | \}}t j|d}|d }dtj| }t j|d}tjd  |  |  d }|dk|ddd   k@ }tj|  tj|   } |  tj	|d  }	|||	kB }||d	k@ |d
k||kB @ }||fS )zGenerate and test samples.)r   r   g      ?g       @gQ?gQ?gr鷯?gB>٬@   r   g9v?)
r   r'   uniformr   r   absrX   r$   Zsquarer\   )
r   u_seedZv_seeduZ	u_shiftedvkZgood_sample_maskst)abr"   inverse_alphar!   r#   sample_shaper   r   generate_and_test_samples  s    $$z<_random_poisson_high_rate.<locals>.generate_and_test_samples)r   r   )r   r   r   brsZbatched_las_vegas_algorithm)r   r!   r"   r   r   r.   r   )r   r   r"   r   r!   r#   r   r   r+   \  s    #r+   c          
      sz   t j|   fdd}t jdd |t jt jdt jt jdt jdt jg t jd|gdd\}}}}}|S )a  Samples from the Poisson distribution using Knuth's algorithm.

  We use an algorithm attributed to Knuth: Seminumerical Algorithms. Art of
  Computer Programming, Volume 2. This algorithm runs in O(rate) time, and
  requires O(rate) uniform variates. This algorithm is performant for rate ~<10.

  Given a Poisson process, the time between events is exponentially distributed.
  If we have a Poisson process with rate lambda, then, the time between events
  is distributed as Exp(lambda). If X ~ Uniform(0, 1), then Y ~ Exp(lambda)
  where Y = -log(X) / lambda. Thus, to simulate a Poisson draw, we can sample
  X_i ~ Exp(lambda), and we will haver N ~ Poisson(lambda), where N is the
  smallest number such that sum_i^N X_i > 1.

  Args:
    sample_shape: The output sample shape. Must broadcast with `rate`.
    rate: Floating point tensor, rate.
    internal_dtype: (optional) dtype to use for internal computations.
    seed: (optional) The random seed.

  Returns:
    Samples from the poisson distribution.
  c                sT   t |\}}|t j|d }| | k@ }t|||}| | @ |||d |gS )N)r   r   rv   )r   r'   rw   r   r*   )should_continuer.   prodZ	num_itersr   ry   Z	next_seedaccept)exp_neg_rater"   r   r   r   	loop_body  s    z+_random_poisson_low_rate.<locals>.loop_bodyc             W   s
   t | S )N)r   Z
reduce_any)r   ignorer   r   r   <lambda>      z*_random_poisson_low_rate.<locals>.<lambda>)r      )ZcondbodyZ	loop_varsZmaximum_iterations)r   r   r   Z
while_loopZonesboolzerosr4   )r   r#   r"   r   r   _r.   r   )r   r"   r   r   r,     s    
r,   )"rr   
__future__r   r   r   numpyr(   Z;tensorflow_probability.python.internal.backend.numpy.compatr   r   Z2tensorflow_probability.python.distributions._numpyr   Z-tensorflow_probability.python.internal._numpyr   r   r   r	   r
   r   Z&tensorflow_probability.python.internalr   r   r   __all__r=   r    r/   functionr7   Distributionr   r&   r+   r,   r   r   r   r   <module>   sJ   )
 VE