tensorflow_probability/python/optimizer/linesearch/internal/hager_zhang_lib.py
def _bisect(value_and_gradients_function, initial_args, f_lim):
  """Actual implementation of bisect given initial_args in a _BracketResult."""
  def _loop_cond(curr):
    # TODO(b/112524024): Also take into account max_iterations.
    return ~tf.reduce_all(input_tensor=curr.stopped)

  def _loop_body(curr):
    """Narrow down interval to satisfy opposite slope conditions."""
    mid = value_and_gradients_function((curr.left.x + curr.right.x) / 2)

    # Fail if function values at mid point are no longer finite; or left/right
    # points are so close to it that we can't distinguish them any more.
    failed = (curr.failed | ~is_finite(mid) |
              tf.equal(mid.x, curr.left.x) | tf.equal(mid.x, curr.right.x))

    # If mid point has a negative slope and the function value at that point is
    # small enough, we can use it as a new left end point to narrow down the
    # interval. If mid point has a positive slope, then we have found a suitable
    # right end point to bracket a minima within opposite slopes. Otherwise, the
    # mid point has a negative slope but the function value at that point is too
    # high to work as left end point, we are in the same situation in which we
    # started the loop so we just update the right end point and continue.
    to_update = ~(curr.stopped | failed)
    update_left = (mid.df < 0) & (mid.f <= f_lim)
    left = val_where(to_update & update_left, mid, curr.left)
    right = val_where(to_update & ~update_left, mid, curr.right)

    # We're done when the right end point has a positive slope.
    stopped = curr.stopped | failed | (right.df >= 0)

    return [_IntermediateResult(
        iteration=curr.iteration,
        stopped=stopped,
        failed=failed,
        num_evals=curr.num_evals + 1,
        left=left,
        right=right)]

  # The interval needs updating if the right end point has a negative slope and
  # the value of the function at that point is too high. It is not a valid left
  # end point but along with the current left end point, it encloses another
  # minima. The loop above tries to narrow the interval so that it satisfies the
  # opposite slope conditions.
  return tf.while_loop(
      cond=_loop_cond, body=_loop_body, loop_vars=[initial_args])[0]
def _bisect(value_and_gradients_function, initial_args, f_lim):
  def _loop_cond(curr):
    # TODO(b/112524024): Also take into account max_iterations.
    return ~tf.reduce_all(input_tensor=curr.stopped)

  def _loop_body(curr):
    """Narrow down interval to satisfy opposite slope conditions."""
    mid = value_and_gradients_function((curr.left.x + curr.right.x) / 2)

    # Fail if function values at mid point are no longer finite; or left/right
    # points are so close to it that we can't distinguish them any more.
    failed = (curr.failed | ~is_finite(mid) |
              tf.equal(mid.x, curr.left.x) | tf.equal(mid.x, curr.right.x))

    # If mid point has a negative slope and the function value at that point is
    # small enough, we can use it as a new left end point to narrow down the
    # interval. If mid point has a positive slope, then we have found a suitable
    # right end point to bracket a minima within opposite slopes. Otherwise, the
    # mid point has a negative slope but the function value at that point is too
    # high to work as left end point, we are in the same situation in which we
    # started the loop so we just update the right end point and continue.
    to_update = ~(curr.stopped | failed)
    update_left = (mid.df < 0) & (mid.f <= f_lim)
    left = val_where(to_update & update_left, mid, curr.left)
    right = val_where(to_update & ~update_left, mid, curr.right)

    # We're done when the right end point has a positive slope.
    stopped = curr.stopped | failed | (right.df >= 0)

    return [_IntermediateResult(
        iteration=curr.iteration,
        stopped=stopped,
        failed=failed,
        num_evals=curr.num_evals + 1,
        left=left,
        right=right)]

  # The interval needs updating if the right end point has a negative slope and
  # the value of the function at that point is too high. It is not a valid left
  # end point but along with the current left end point, it encloses another
  # minima. The loop above tries to narrow the interval so that it satisfies the
  # opposite slope conditions.
  return tf.while_loop(
      cond=_loop_cond, body=_loop_body, loop_vars=[initial_args])[0]
def _bisect ( value_and_gradients_function , initial_args , f_lim ) : def _loop_cond ( curr ) : # TODO(b/112524024): Also take into account max_iterations. return ~ tf . reduce_all ( input_tensor = curr . stopped ) def _loop_body ( curr ) : """Narrow down interval to satisfy opposite slope conditions.""" mid = value_and_gradients_function ( ( curr . left . x + curr . right . x ) / 2 ) # Fail if function values at mid point are no longer finite; or left/right # points are so close to it that we can't distinguish them any more. failed = ( curr . failed | ~ is_finite ( mid ) | tf . equal ( mid . x , curr . left . x ) | tf . equal ( mid . x , curr . right . x ) ) # If mid point has a negative slope and the function value at that point is # small enough, we can use it as a new left end point to narrow down the # interval. If mid point has a positive slope, then we have found a suitable # right end point to bracket a minima within opposite slopes. Otherwise, the # mid point has a negative slope but the function value at that point is too # high to work as left end point, we are in the same situation in which we # started the loop so we just update the right end point and continue. to_update = ~ ( curr . stopped | failed ) update_left = ( mid . df < 0 ) & ( mid . f <= f_lim ) left = val_where ( to_update & update_left , mid , curr . left ) right = val_where ( to_update & ~ update_left , mid , curr . right ) # We're done when the right end point has a positive slope. stopped = curr . stopped | failed | ( right . df >= 0 ) return [ _IntermediateResult ( iteration = curr . iteration , stopped = stopped , failed = failed , num_evals = curr . num_evals + 1 , left = left , right = right ) ] # The interval needs updating if the right end point has a negative slope and # the value of the function at that point is too high. It is not a valid left # end point but along with the current left end point, it encloses another # minima. The loop above tries to narrow the interval so that it satisfies the # opposite slope conditions. return tf . while_loop ( cond = _loop_cond , body = _loop_body , loop_vars = [ initial_args ] ) [ 0 ]
Actual implementation of bisect given initial_args in a _BracketResult.
Actual implementation of bisect given initial_args in a _BracketResult .