code: def _bracket_and_search(
      value_and_gradients_function,
      init_interval,
      f_lim,
      max_iterations,
      shrinkage_param,
      expansion_param,
      sufficient_decrease_param,
      curvature_param,
  ):
      """Brackets the minimum and performs a line search.
  
      Args:
        value_and_gradients_function: A Python callable that accepts a real scalar
          tensor and returns a namedtuple with the fields 'x', 'f', and 'df' that
          correspond to scalar tensors of real dtype containing the point at which
          the function was evaluated, the value of the function, and its
          derivative at that point. The other namedtuple fields, if present,
          should be tensors or sequences (possibly nested) of tensors.
          In usual optimization application, this function would be generated by
          projecting the multivariate objective function along some specific
          direction. The direction is determined by some other procedure but should
          be a descent direction (i.e. the derivative of the projected univariate
          function must be negative at 0.).
          Alternatively, the function may represent the batching of `n` such line
          functions (e.g. projecting a single multivariate objective function along
          `n` distinct directions at once) accepting n points as input, i.e. a
          tensor of shape [n], and the fields 'x', 'f' and 'df' in the returned
          namedtuple should each be a tensor of shape [n], with the corresponding
          input points, function values, and derivatives at those input points.
        init_interval: Instance of `HagerZhangLineSearchResults` containing
          the initial line search interval. The gradient of init_interval.left must
          be negative (i.e. must be a descent direction), while init_interval.right
          must be positive and finite.
        f_lim: Scalar `Tensor` of float dtype.
        max_iterations: Positive scalar `Tensor` of integral dtype. The maximum
          number of iterations to perform in the line search. The number of
          iterations used to bracket the minimum are also counted against this
          parameter.
        shrinkage_param: Scalar positive Tensor of real dtype. Must be less than
          `1.`. Corresponds to the parameter `gamma` in [Hager and Zhang (2006)][2].
        expansion_param: Scalar positive `Tensor` of real dtype. Must be greater
          than `1.`. Used to expand the initial interval in case it does not bracket
          a minimum. Corresponds to `rho` in [Hager and Zhang (2006)][2].
        sufficient_decrease_param: Positive scalar `Tensor` of real dtype.
          Bounded above by the curvature param. Corresponds to `delta` in the
          terminology of [Hager and Zhang (2006)][2].
        curvature_param: Positive scalar `Tensor` of real dtype. Bounded above
          by `1.`. Corresponds to 'sigma' in the terminology of
          [Hager and Zhang (2006)][2].
  
      Returns:
        A namedtuple containing the following fields.
          converged: Boolean `Tensor` of shape [n]. Whether a point satisfying
            Wolfe/Approx wolfe was found.
          failed: Boolean `Tensor` of shape [n]. Whether line search failed e.g.
            if either the objective function or the gradient are not finite at
            an evaluation point.
          iterations: int32 `Tensor` of shape [n]. Number of line search iterations.
          func_evals: Scalar int32 `Tensor`. Number of function evaluations made.
          left: A namedtuple, as returned by value_and_gradients_function,
            of the left end point of the updated bracketing interval.
          right: A namedtuple, as returned by value_and_gradients_function,
            of the right end point of the updated bracketing interval.
      """
      bracket_result = hzl.bracket(
          value_and_gradients_function,
          init_interval,
          f_lim,
          max_iterations,
          expansion_param,
      )
  
      converged = init_interval.converged | _very_close(
          bracket_result.left.x, bracket_result.right.x
      )
  
      # We fail if we have not yet converged but already exhausted all iterations.
      exhausted_iterations = ~converged & (
          bracket_result.iteration >= max_iterations
      )
  
      line_search_args = HagerZhangLineSearchResult(
          converged=converged,
          failed=bracket_result.failed | exhausted_iterations,
          iterations=bracket_result.iteration,
          func_evals=bracket_result.num_evals,
          left=bracket_result.left,
          right=bracket_result.right,
      )
  
      return _line_search_after_bracketing(
          value_and_gradients_function,
          line_search_args,
          init_interval.left,
          f_lim,
          max_iterations,
          sufficient_decrease_param,
          curvature_param,
          shrinkage_param,
      )
  
file_path: probability/tensorflow_probability/python/optimizer/linesearch/hager_zhang.py
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.optimizer.linesearch.internal import hager_zhang_lib
label_desc: Use image node_id 3 for calling a global function with example usage: _bracket_and_search(value_and_gradients_function, init_interval, f_lim, max_iterations, shrinkage_param, expansion_param, sufficient_decrease_param, curvature_param) and returns: _line_search_after_bracketing