code: def test_exercise_boundary(
      self,
      k,
      tau,
      r,
      q,
      sigma,
      grid_num_points,
      max_iterations,
      tolerance,
      integration_num_points,
      convergence_atol,
      dtype,
      expected_shape,
  ):
      k = tf.constant(k, dtype=dtype)
      tau = tf.constant(tau, dtype=dtype)
      tau_grid = tf.linspace(
          tau / grid_num_points, tau, grid_num_points, axis=-1
      )
      r = tf.constant(r, dtype=dtype)
      q = tf.constant(q, dtype=dtype)
      sigma = tf.constant(sigma, dtype=dtype)
      k_exp = tf.expand_dims(k, axis=-1)
      r_exp = tf.expand_dims(r, axis=-1)
      q_exp = tf.expand_dims(q, axis=-1)
      # TODO(viktoriac): test against numpy results
      actual_boundary_function = exercise_boundary(
          tau_grid,
          k,
          r,
          q,
          sigma,
          max_iterations,
          tolerance,
          integration_num_points,
          dtype=dtype,
      )
      actual_boundary = actual_boundary_function(tau_grid)
  
      # Test if next iteration of the function gives same results
      def actual_boundary_fn_3d(tau_grid_exp):
          shape_1 = utils.get_shape(tau_grid_exp)[1]
          shape_2 = utils.get_shape(tau_grid_exp)[2]
          tau_grid_exp_reshape = tf.reshape(
              tau_grid_exp, [-1, shape_1 * shape_2]
          )
          interpolation = actual_boundary_function(tau_grid_exp_reshape)
          return tf.reshape(interpolation, [-1, shape_1, shape_2])
  
      numerator = boundary_numerator(
          tau_grid,
          actual_boundary_fn_3d,
          k,
          r,
          q,
          sigma,
          integration_num_points,
      )
      denominator = boundary_denominator(
          tau_grid,
          actual_boundary_fn_3d,
          k,
          r,
          q,
          sigma,
          integration_num_points,
      )
      next_boundary_points = divide_with_positive_denominator(
          k_exp * tf.math.exp(-(r_exp - q_exp) * tau_grid) * numerator,
          denominator,
      )
      actual_boundary = np.array(self.evaluate(actual_boundary))
      next_boundary_points = np.array(
          self.evaluate(next_boundary_points)
      )
      # Test results against next iteration of exercise boundary function
      np.testing.assert_allclose(
          actual_boundary, next_boundary_points, atol=convergence_atol
      )
      # Test shape of result
      self.assertEqual(actual_boundary.shape, expected_shape)
  
file_path: tf-quant-finance/tf_quant_finance/experimental/american_option_pricing/exercise_boundary_test.py
imports: from absl.testing import parameterized
  import numpy
  import tensorflow.compat.v2
  from tf_quant_finance import utils
  from tf_quant_finance.experimental.american_option_pricing import common
  from tf_quant_finance.experimental.american_option_pricing import exercise_boundary
  from tensorflow.python.framework import test_util
label_desc: Use image node_id 3 for calling the ExerciseBoundaryTest obj's underlying member method code with example usage: obj.test_exercise_boundary(k, tau, r, q, sigma, grid_num_points, max_iterations, tolerance, integration_num_points, convergence_atol, dtype, expected_shape) and returns: tf