class_docstr: Runs one step of the elliptic slice sampler.
  
  Elliptical Slice Sampling is a Markov Chain Monte Carlo (MCMC) algorithm
  based, as stated in [Murray, 2010][1].
  
  Given `log_likelihood_fn` and `normal_sampler_fn`, the goal of Elliptical
  Slice Sampling is to sample from:
  
  ```none
  p(f) = N(f; 0, Sigma)L(f) / Z
  ```
  
  where:
    * `L = log_likelihood_fn`
    * `Sigma` is a covariance matrix.
    * Samples from `normal_sampler_fn` are distributed as `N(f; 0, Sigma)`.
    * `Z` is a normalizing constant.
  
  In other words, sampling from a posterior distribution that is proportional
  to a multivariate gaussian prior multiplied by some likelihood function.
  
  The `one_step` function can update multiple chains in parallel. It assumes
  that all leftmost dimensions of `current_state` index independent chain states
  (and are therefore updated independently). The output of
  `log_likelihood_fn(*current_state)` should sum log-probabilities across all
  event dimensions. Slices along the rightmost dimensions may have different
  target distributions; for example, `current_state[0, :]` could have a
  different target distribution from `current_state[1, :]`.
  These semantics are governed both by `log_likelihood_fn(*current_state)` and
  `normal_sampler_fn`.
  
  Note that the sampler only supports states where all components have a common
  dtype.
  
  ### Examples:
  
  #### Simple chain with warm-up.
  
  In this example we have the following model.
  
  ```none
    p(loc | loc0, scale0) ~ N(loc0, scale0)
    p(x | loc, sigma) ~ N(mu, sigma)
  ```
  
  What we would like to do is sample from `p(loc | x, loc0, scale0)`. In other
  words, given some data, we would like to infer the posterior distribution
  of the mean that generated that data point.
  
  We can use elliptical slice sampling here.
  
  ```python
    import tensorflow as tf
    import tensorflow_probability as tfp
    import numpy as np
  
    tfd = tfp.distributions
  
    dtype = np.float64
  
    # loc0 = 0, scale0 = 1
    normal_sampler_fn = lambda seed: return tfd.Normal(
        loc=dtype(0), scale=dtype(1)).sample(seed=seed)
  
    # We saw the following data.
    data_points = np.random.randn(20)
  
    # scale = 2.
    log_likelihood_fn = lambda state: return tf.reduce_sum(
        tfd.Normal(state, dtype(2.)).log_prob(data_points))
  
    kernel = tfp.mcmc.EllipticalSliceSampler(
        normal_sampler_fn=normal_sampler_fn,
        log_likelihood_fn=log_likelihood_fn,
        seed=1234)
  
    samples = tfp.mcmc.sample_chain(
        num_results=int(3e5),
        current_state=dtype(1),
        kernel=kernel,
        num_burnin_steps=1000,
        trace_fn=None,
        parallel_iterations=1)  # For determinism.
  
    sample_mean = tf.reduce_mean(samples, axis=0)
    sample_std = tf.sqrt(
      tf.reduce_mean(tf.squared_difference(samples, sample_mean),
                     axis=0))
  
    with tf.Session() as sess:
      [sample_mean, sample_std] = sess.run([sample_mean, sample_std])
  
    print("Sample mean: ", sample_mean)
    print("Sample Std: ", sample_std)
  ```
  
  ### References
  
  [1]: Ian Murray, Ryan P. Adams, David J.C. MacKay. Elliptical slice sampling.
       proceedings.mlr.press/v9/murray10a/murray10a.pdf
docstr: Runs one iteration of the Elliptical Slice Sampler.
  
  Args:
    current_state: `Tensor` or Python `list` of `Tensor`s representing the
      current state(s) of the Markov chain(s). The first `r` dimensions
      index independent chains,
      `r = tf.rank(log_likelihood_fn(*normal_sampler_fn()))`.
    previous_kernel_results: `collections.namedtuple` containing `Tensor`s
      representing values from previous calls to this function (or from the
      `bootstrap_results` function.)
    seed: PRNG seed; see `tfp.random.sanitize_seed` for details.
  
  Returns:
    next_state: Tensor or Python list of `Tensor`s representing the state(s)
      of the Markov chain(s) after taking exactly one step. Has same type and
      shape as `current_state`.
    kernel_results: `collections.namedtuple` of internal calculations used to
      advance the chain.
  
  Raises:
    TypeError: if `log_likelihood.dtype` is not floating point.
docstr_tok: ["Runs","one","iteration","of","the","Elliptical","Slice","Sampler",".","Args",":","current_state",":","`","Tensor","`","or","Python","`","list","`","of","`","Tensor","`","s","representing","the","current","state","(","s",")","of","the","Markov","chain","(","s",")",".","The","first","`","r","`","dimensions","index","independent","chains",",","`","r","=","tf.rank","(","log_likelihood_fn","(","*","normal_sampler_fn","(",")",")",")","`",".","previous_kernel_results",":","`","collections.namedtuple","`","containing","`","Tensor","`","s","representing","values","from","previous","calls","to","this","function","(","or","from","the","`","bootstrap_results","`","function",".",")","seed",":","PRNG","seed",";","see","`","tfp.random.sanitize_seed","`","for","details",".","Returns",":","next_state",":","Tensor","or","Python","list","of","`","Tensor","`","s","representing","the","state","(","s",")","of","the","Markov","chain","(","s",")","after","taking","exactly","one","step",".","Has","same","type","and","shape","as","`","current_state","`",".","kernel_results",":","`","collections.namedtuple","`","of","internal","calculations","used","to","advance","the","chain",".","Raises",":","TypeError",":","if","`","log_likelihood.dtype","`","is","not","floating","point","."]
code: def one_step(self, current_state, previous_kernel_results, seed=None):
      """Runs one iteration of the Elliptical Slice Sampler.
  
      Args:
        current_state: `Tensor` or Python `list` of `Tensor`s representing the
          current state(s) of the Markov chain(s). The first `r` dimensions
          index independent chains,
          `r = tf.rank(log_likelihood_fn(*normal_sampler_fn()))`.
        previous_kernel_results: `collections.namedtuple` containing `Tensor`s
          representing values from previous calls to this function (or from the
          `bootstrap_results` function.)
        seed: PRNG seed; see `tfp.random.sanitize_seed` for details.
  
      Returns:
        next_state: Tensor or Python list of `Tensor`s representing the state(s)
          of the Markov chain(s) after taking exactly one step. Has same type and
          shape as `current_state`.
        kernel_results: `collections.namedtuple` of internal calculations used to
          advance the chain.
  
      Raises:
        TypeError: if `log_likelihood.dtype` is not floating point.
      """
      with tf.name_scope(
          mcmc_util.make_name(self.name, "elliptical_slice", "one_step")
      ):
          with tf.name_scope("initialize"):
              [init_state_parts, init_log_likelihood] = _prepare_args(
                  self.log_likelihood_fn,
                  current_state,
                  previous_kernel_results.log_likelihood,
              )
  
          seed = samplers.sanitize_seed(
              seed
          )  # Unsalted, for kernel results.
          (
              normal_seed,
              u_seed,
              angle_seed,
              loop_seed,
          ) = samplers.split_seed(
              seed, n=4, salt="elliptical_slice_sampler"
          )
          normal_samples = self.normal_sampler_fn(
              normal_seed
          )  # pylint: disable=not-callable
          normal_samples = (
              list(normal_samples)
              if mcmc_util.is_list_like(normal_samples)
              else [normal_samples]
          )
          u = samplers.uniform(
              shape=ps.shape(init_log_likelihood),
              seed=u_seed,
              dtype=dtype_util.base_dtype(init_log_likelihood.dtype),
          )
          threshold = init_log_likelihood + tf.math.log(u)
  
          starting_angle = samplers.uniform(
              shape=ps.shape(init_log_likelihood),
              minval=0.0,
              maxval=2 * np.pi,
              name="angle",
              seed=angle_seed,
              dtype=dtype_util.base_dtype(init_log_likelihood.dtype),
          )
          starting_angle_min = starting_angle - 2 * np.pi
          starting_angle_max = starting_angle
  
          starting_state_parts = _rotate_on_ellipse(
              init_state_parts, normal_samples, starting_angle
          )
          starting_log_likelihood = self.log_likelihood_fn(
              *starting_state_parts
          )  # pylint: disable=not-callable
  
          def chain_not_done(
              seed,
              angle,
              angle_min,
              angle_max,
              current_state_parts,
              current_log_likelihood,
          ):
              del seed, angle, angle_min, angle_max, current_state_parts
              return tf.reduce_any(current_log_likelihood < threshold)
  
          def sample_next_angle(
              seed,
              angle,
              angle_min,
              angle_max,
              current_state_parts,
              current_log_likelihood,
          ):
              """Slice sample a new angle, and rotate init_state by that amount."""
              angle_seed, next_seed = samplers.split_seed(seed)
              chain_not_done = current_log_likelihood < threshold
              # Box in on angle. Only update angles for which we haven't generated a
              # point that beats the threshold.
              angle_min = tf.where(
                  (angle < 0) & chain_not_done, angle, angle_min
              )
              angle_max = tf.where(
                  (angle >= 0) & chain_not_done, angle, angle_max
              )
              new_angle = samplers.uniform(
                  shape=ps.shape(current_log_likelihood),
                  minval=angle_min,
                  maxval=angle_max,
                  seed=angle_seed,
                  dtype=dtype_util.base_dtype(angle.dtype),
              )
              angle = tf.where(chain_not_done, new_angle, angle)
              next_state_parts = _rotate_on_ellipse(
                  init_state_parts, normal_samples, angle
              )
  
              new_state_parts = []
              for n_state, c_state in zip(
                  next_state_parts, current_state_parts
              ):
                  broadcasted_chain_not_done = _right_pad_with_ones(
                      chain_not_done, ps.rank(n_state)
                  )
                  new_state_part = tf.where(
                      broadcasted_chain_not_done, n_state, c_state
                  )
                  new_state_parts.append(new_state_part)
  
              return (
                  next_seed,
                  angle,
                  angle_min,
                  angle_max,
                  new_state_parts,
                  self.log_likelihood_fn(
                      *new_state_parts
                  ),  # pylint: disable=not-callable
              )
  
          [
              _,
              next_angle,
              _,
              _,
              next_state_parts,
              next_log_likelihood,
          ] = tf.while_loop(
              cond=chain_not_done,
              body=sample_next_angle,
              loop_vars=[
                  loop_seed,
                  starting_angle,
                  starting_angle_min,
                  starting_angle_max,
                  starting_state_parts,
                  starting_log_likelihood,
              ],
          )
  
          return [
              next_state_parts
              if mcmc_util.is_list_like(current_state)
              else next_state_parts[0],
              EllipticalSliceSamplerKernelResults(
                  log_likelihood=next_log_likelihood,
                  angle=next_angle,
                  normal_samples=normal_samples,
                  seed=seed,
              ),
          ]
  
imports: import collections
  import numpy
  import tensorflow.compat.v2
  from tensorflow_probability.python.internal import dtype_util
  from tensorflow_probability.python.internal import prefer_static
  from tensorflow_probability.python.internal import samplers
  from tensorflow_probability.python.mcmc import kernel
  from tensorflow_probability.python.mcmc.internal import util
label_desc: Use image node_id 7 for calling the EllipticalSliceSampler obj's underlying member method code with example usage: obj.one_step(current_state, previous_kernel_results, seed) and returns: list, tf, next_seed,  angle,  angle_min,  angle_max,  new_state_parts,  self