code: def slice_bounds_by_doubling(
      x_initial,
      target_log_prob,
      log_slice_heights,
      max_doublings,
      step_size,
      seed=None,
      name=None,
  ):
      """Returns the bounds of the slice at each stage of doubling procedure.
  
      Precomputes the x coordinates of the left (L) and right (R) endpoints of the
      interval `I` produced in the "doubling" algorithm [Neal 2003][1] P713. Note
      that we simultaneously compute all possible doubling values for each chain,
      for the reason that at small-medium densities, the gains from parallel
      evaluation might cause a speed-up, but this will be benchmarked against the
      while loop implementation.
  
      Args:
        x_initial: `tf.Tensor` of any shape and any real dtype consumable by
          `target_log_prob`. The initial points.
        target_log_prob: A callable taking a `tf.Tensor` of shape and dtype as
          `x_initial` and returning a tensor of the same shape. The log density of
          the target distribution.
        log_slice_heights: `tf.Tensor` with the same shape as `x_initial` and the
          same dtype as returned by `target_log_prob`. The log of the height of the
          slice for each chain. The values must be bounded above by
          `target_log_prob(x_initial)`.
        max_doublings: Scalar positive int32 `tf.Tensor`. The maximum number of
          doublings to consider.
        step_size: `tf.Tensor` with same dtype as and shape compatible with
          `x_initial`. The size of the initial interval.
        seed: (Optional) positive int or Tensor seed pair. The random seed.
        name: Python `str` name prefixed to Ops created by this function.
          Default value: `None` (i.e., 'find_slice_bounds').
  
      Returns:
        upper_bounds: A tensor of same shape and dtype as `x_initial`. Slice upper
          bounds for each chain.
        lower_bounds: A tensor of same shape and dtype as `x_initial`. Slice lower
          bounds for each chain.
        both_ok: A tensor of shape `x_initial` and boolean dtype. Indicates if both
          the chosen upper and lower bound lie outside of the slice.
  
      #### References
  
      [1]: Radford M. Neal. Slice Sampling. The Annals of Statistics. 2003, Vol 31,
           No. 3 , 705-767.
           https://projecteuclid.org/download/pdf_1/euclid.aos/1056562461
      """
      with tf.name_scope(name or "slice_bounds_by_doubling"):
          left_seed, increments_seed = samplers.split_seed(
              seed, salt="slice_bounds_by_doubling"
          )
          x_initial = tf.convert_to_tensor(value=x_initial)
          batch_shape = ps.shape(x_initial)
          dtype = dtype_util.base_dtype(step_size.dtype)
          left_endpoints = x_initial + step_size * samplers.uniform(
              batch_shape,
              minval=-1.0,
              maxval=0.0,
              dtype=dtype,
              seed=left_seed,
          )
  
          # Compute the increments by which we need to step the upper and lower bounds
          # part of the doubling procedure.
          left_increments, widths = _left_doubling_increments(
              batch_shape,
              max_doublings,
              step_size,
              seed=increments_seed,
          )
          # The left and right end points. Shape (max_doublings+1,) + batch_shape.
          left_endpoints = left_endpoints - left_increments
          right_endpoints = left_endpoints + widths
  
          # Test if these end points lie outside of the slice.
          # Checks if the end points of the slice are outside the graph of the pdf.
          left_ep_values = tf.map_fn(target_log_prob, left_endpoints)
          right_ep_values = tf.map_fn(target_log_prob, right_endpoints)
          left_ok = left_ep_values < log_slice_heights
          right_ok = right_ep_values < log_slice_heights
          both_ok = left_ok & right_ok
  
          both_ok_f = tf.reshape(both_ok, [max_doublings + 1, -1])
  
          best_interval_idx = _find_best_interval_idx(
              tf.cast(both_ok_f, dtype=tf.int32)
          )
  
          # Formats the above index as required to use with gather_nd.
          point_index_gather = tf.stack(
              [best_interval_idx, ps.range(ps.size(best_interval_idx))],
              axis=1,
              name="point_index_gather",
          )
          left_ep_f = tf.reshape(
              left_endpoints, [max_doublings + 1, -1]
          )
          right_ep_f = tf.reshape(
              right_endpoints, [max_doublings + 1, -1]
          )
          # The x values of the uppper and lower bounds of the slices for each chain.
          lower_bounds = tf.reshape(
              tf.gather_nd(left_ep_f, point_index_gather), batch_shape
          )
          upper_bounds = tf.reshape(
              tf.gather_nd(right_ep_f, point_index_gather), batch_shape
          )
          both_ok = tf.reduce_any(both_ok, axis=0)
          return upper_bounds, lower_bounds, both_ok
  
file_path: probability/tensorflow_probability/python/mcmc/internal/slice_sampler_utils.py
imports: import tensorflow.compat.v2
  from tensorflow_probability.python.distributions import bernoulli
  from tensorflow_probability.python.distributions import gamma
  from tensorflow_probability.python.internal import dtype_util
  from tensorflow_probability.python.internal import prefer_static
  from tensorflow_probability.python.internal import samplers
label_desc: Use image node_id 3 for calling a global function with example usage: slice_bounds_by_doubling(x_initial, target_log_prob, log_slice_heights, max_doublings, step_size, seed, name) and returns: upper_bounds,  lower_bounds,  both_ok