class_docstr: Zipf distribution.
  
  The Zipf distribution is parameterized by a `power` parameter.
  
  #### Mathematical Details
  
  The probability mass function (pmf) is,
  
  ```none
  pmf(k; alpha, k >= 0) = (k^(-alpha)) / Z
  Z = zeta(alpha).
  ```
  
  where `power = alpha` and Z is the normalization constant.
  `zeta` is the [Riemann zeta function](
  https://en.wikipedia.org/wiki/Riemann_zeta_function).
  
  Note that gradients with respect to the `power` parameter are not
  supported in the current implementation.
class_docstr_tok: ["Zipf","distribution",".","The","Zipf","distribution","is","parameterized","by","a","`","power","`","parameter",".","#","#","#","#","Mathematical","Details","The","probability","mass","function","(","pmf",")","is",",","``","`","none","pmf","(","k",";","alpha",",","k",">","=","0",")","=","(","k^","(","-alpha",")",")","\/","Z","Z","=","zeta","(","alpha",")",".","``","`","where","`","power","=","alpha","`","and","Z","is","the","normalization","constant",".","`","zeta","`","is","the","[","Riemann","zeta","function","]","(","https",":","\/\/en.wikipedia.org\/wiki\/Riemann_zeta_function",")",".","Note","that","gradients","with","respect","to","the","`","power","`","parameter","are","not","supported","in","the","current","implementation","."]
code: def _sample_n(self, n, seed=None):
      power = tf.convert_to_tensor(self.power)
      shape = ps.concat([[n], ps.shape(power)], axis=0)
      numpy_dtype = dtype_util.as_numpy_dtype(power.dtype)
  
      seed = samplers.sanitize_seed(seed, salt="zipf")
  
      # Because `_hat_integral` is montonically decreasing, the bounds for u will
      # switch.
      # Compute the hat_integral explicitly here since we can calculate the log of
      # the inputs statically in float64 with numpy.
      maxval_u = (
          tf.math.exp(
              -(power - 1.0) * numpy_dtype(np.log1p(0.5))
              - tf.math.log(power - 1.0)
          )
          + 1.0
      )
      minval_u = tf.math.exp(
          -(power - 1.0)
          * numpy_dtype(np.log1p(dtype_util.max(self.dtype) - 0.5))
          - tf.math.log(power - 1.0)
      )
  
      def loop_body(should_continue, k, seed):
          """Resample the non-accepted points."""
          u_seed, next_seed = samplers.split_seed(seed)
          # Uniform variates must be sampled from the open-interval `(0, 1)` rather
          # than `[0, 1)`. To do so, we use
          # `np.finfo(dtype_util.as_numpy_dtype(self.dtype)).tiny`
          # because it is the smallest, positive, 'normal' number. A 'normal' number
          # is such that the mantissa has an implicit leading 1. Normal, positive
          # numbers x, y have the reasonable property that, `x + y >= max(x, y)`. In
          # this case, a subnormal number (i.e., np.nextafter) can cause us to
          # sample 0.
          u = samplers.uniform(
              shape,
              minval=np.finfo(
                  dtype_util.as_numpy_dtype(power.dtype)
              ).tiny,
              maxval=numpy_dtype(1.0),
              dtype=power.dtype,
              seed=u_seed,
          )
          # We use (1 - u) * maxval_u + u * minval_u rather than the other way
          # around, since we want to draw samples in (minval_u, maxval_u].
          u = maxval_u + (minval_u - maxval_u) * u
          # set_shape needed here because of b/139013403
          tensorshape_util.set_shape(u, should_continue.shape)
  
          # Sample the point X from the continuous density h(x) \propto x^(-power).
          x = self._hat_integral_inverse(u, power=power)
  
          # Rejection-inversion requires a `hat` function, h(x) such that
          # \int_{k - .5}^{k + .5} h(x) dx >= pmf(k + 1) for points k in the
          # support. A natural hat function for us is h(x) = x^(-power).
          #
          # After sampling X from h(x), suppose it lies in the interval
          # (K - .5, K + .5) for integer K. Then the corresponding K is accepted if
          # if lies to the left of x_K, where x_K is defined by:
          #   \int_{x_k}^{K + .5} h(x) dx = H(x_K) - H(K + .5) = pmf(K + 1),
          # where H(x) = \int_x^inf h(x) dx.
  
          # Solving for x_K, we find that x_K = H_inverse(H(K + .5) + pmf(K + 1)).
          # Or, the acceptance condition is X <= H_inverse(H(K + .5) + pmf(K + 1)).
          # Since X = H_inverse(U), this simplifies to U <= H(K + .5) + pmf(K + 1).
  
          # Update the non-accepted points.
          # Since X \in (K - .5, K + .5), the sample K is chosen as floor(X + 0.5).
          k = tf.where(should_continue, tf.floor(x + 0.5), k)
          accept = u <= self._hat_integral(
              k + 0.5, power=power
          ) + tf.exp(self._log_prob(k + 1, power=power))
  
          return [should_continue & (~accept), k, next_seed]
  
      should_continue, samples, _ = tf.while_loop(
          cond=lambda should_continue, *ignore: tf.reduce_any(
              should_continue
          ),
          body=loop_body,
          loop_vars=[
              tf.ones(shape, dtype=tf.bool),  # should_continue
              tf.zeros(shape, dtype=power.dtype),  # k
              seed,  # seed
          ],
          maximum_iterations=self.sample_maximum_iterations,
      )
      samples = samples + 1.0
  
      if self.validate_args and dtype_util.is_integer(self.dtype):
          samples = (
              distribution_util.embed_check_integer_casting_closed(
                  samples, target_dtype=self.dtype, assert_positive=True
              )
          )
  
      samples = tf.cast(samples, self.dtype)
  
      if self.validate_args:
          npdt = dtype_util.as_numpy_dtype(self.dtype)
          v = npdt(
              dtype_util.min(npdt)
              if dtype_util.is_integer(npdt)
              else np.nan
          )
          samples = tf.where(should_continue, v, samples)
  
      return samples
  
imports: import numpy
  import tensorflow.compat.v2
  from tensorflow_probability.python.bijectors import softplus
  from tensorflow_probability.python.distributions import distribution
  from tensorflow_probability.python.internal import assert_util
  from tensorflow_probability.python.internal import distribution_util
  from tensorflow_probability.python.internal import dtype_util
  from tensorflow_probability.python.internal import parameter_properties
  from tensorflow_probability.python.internal import prefer_static
  from tensorflow_probability.python.internal import reparameterization
  from tensorflow_probability.python.internal import samplers
  from tensorflow_probability.python.internal import tensor_util
  from tensorflow_probability.python.internal import tensorshape_util
label_desc: Use image node_id 13 for calling the Zipf obj's underlying member method code with example usage: obj._sample_n(n, seed) and returns: samples, list