code: def boundary_numerator(
      tau_grid: types.FloatTensor,
      b: Callable[[types.FloatTensor], types.FloatTensor],
      k: types.FloatTensor,
      r: types.FloatTensor,
      q: types.FloatTensor,
      sigma: types.FloatTensor,
      integration_num_points: int = 32,
      dtype: Optional[tf.DType] = None,
  ) -> types.FloatTensor:
      """Calculates the numerator of the exercise boundary function of an American option.
  
      Calculates the numerator part of the calculation required to get the exercise
      boundary function of an American option. This corresponds to `N` in formula
      (3.7) in the paper [1].
  
      #### References
      [1] Leif Andersen, Mark Lake and Dimitri Offengenden. High-performance
      American option pricing. 2015
      https://engineering.nyu.edu/sites/default/files/2019-03/Carr-adjusting-exponential-levy-models.pdf#page=54
  
      #### Example
      ```python
        dtype = tf.float64
        tau_grid = tf.constant([[0., 0.5, 1.], [0., 1., 2.],  [0., 3., 6.]],
                               dtype=dtype)
        k = tf.constant([1, 2, 2], dtype=dtype)
        r = tf.constant([0.01, 0.02, 0.04], dtype=dtype)
        q = tf.constant([0.01, 0.02, 0.0], dtype=dtype)
        sigma = tf.constant([0.1, 0.15, 0.05], dtype=dtype)
        k_exp = k[:, tf.newaxis, tf.newaxis]
        r_exp = r[:, tf.newaxis, tf.newaxis]
        q_exp = q[:, tf.newaxis, tf.newaxis]
        epsilon = machine_eps(dtype)
        def b_0(tau_grid_exp):
          one = tf.constant(1.0, dtype=dtype)
          return tf.ones_like(tau_grid_exp) * k_exp_exp * tf.where(
              tf.math.abs(q_exp_exp) < epsilon, one,
              tf.math.minimum(one, r_exp_exp / q_exp_exp))
        integration_num_points = 32
        boundary_numerator(tau_grid, b_0, k, r, q, sigma, integration_num_points)
        # Returns a tensor of shape [3, 3].
      ```
  
      Args:
        tau_grid: Grid of values of shape `[num_options, grid_num_points]`
          indicating the time left until option maturity.
        b: Represents the exercise boundary function for the option. Receives
          `Tensor` of rank `tau_grid.rank + 1` and returns a `Tensor` of same shape.
        k: Same dtype as `tau_grid` with shape `num_options` representing the strike
          price of the option.
        r: Same shape and dtype as `k` representing the annualized risk-free
          interest rate, continuously compounded.
        q: Same shape and dtype as `k` representing the dividend rate.
        sigma: Same shape and dtype as `k` representing the volatility of the
          option's returns.
        integration_num_points: The number of points used in the integration
          approximation method.
          Default value: 32.
        dtype: If supplied, the dtype for all input tensors. Result will have the
          same dtype.
          Default value: None which maps to dtype of `tau_grid`.
  
      Returns:
        `Tensor` of shape `[num_options, grid_num_points]`, containing a partial
        result for calculating the exercise boundary.
      """
      with tf.name_scope("calculate_N"):
          # Shape [num_options, grid_num_points]
          tau_grid = tf.convert_to_tensor(tau_grid, dtype=dtype)
          dtype = tau_grid.dtype
          # Shape [num_options]
          k = tf.convert_to_tensor(k, dtype=dtype)
          r = tf.convert_to_tensor(r, dtype=dtype)
          q = tf.convert_to_tensor(q, dtype=dtype)
          sigma = tf.convert_to_tensor(sigma, dtype=dtype)
          # Shape [num_options, 1, 1]
          k_exp = k[:, tf.newaxis, tf.newaxis]
          r_simple_exp = r[:, tf.newaxis]
          r_exp = r_simple_exp[:, tf.newaxis]
          q_exp = q[:, tf.newaxis, tf.newaxis]
          sigma_exp = sigma[:, tf.newaxis, tf.newaxis]
          # Shape [num_options, grid_num_points, 1]
          tau_grid_exp = tf.expand_dims(tau_grid, axis=-1)
          term1 = standard_normal_cdf(
              d_minus(
                  tau_grid_exp,
                  b(tau_grid_exp) / k_exp,
                  r_exp,
                  q_exp,
                  sigma_exp,
              )
          )
          # Shape [num_options, grid_num_points]
          term1 = tf.squeeze(term1, axis=-1)
  
          def func(u):
              # Shape [num_options, grid_num_points, integration_num_points]
              ratio = divide_with_positive_denominator(
                  b(tau_grid_exp), b(u)
              )
              norm = standard_normal_cdf(
                  d_minus(
                      tau_grid_exp - u, ratio, r_exp, q_exp, sigma_exp
                  )
              )
              return tf.math.exp(r_exp * u) * norm
  
          # Shape [num_options, grid_num_points]
          term2 = r_simple_exp * gauss_legendre(
              func=func,
              lower=tf.zeros_like(tau_grid),
              upper=tau_grid,
              num_points=integration_num_points,
              dtype=dtype,
          )
          return term1 + term2
  
file_path: tf-quant-finance/tf_quant_finance/experimental/american_option_pricing/exercise_boundary.py
imports: from typing import Callable, Optional
  import tensorflow.compat.v2
  from tf_quant_finance import types
  from tf_quant_finance import utils
  from tf_quant_finance.experimental.american_option_pricing import common
  from tf_quant_finance.math.integration import gauss_legendre
  from tf_quant_finance.math.interpolation.cubic import cubic_interpolation
label_desc: Use image node_id 1 for calling a global function with example usage: boundary_numerator(tau_grid, b, k, r, q, sigma, integration_num_points, dtype) and returns: unknown, unknown