# Path: tensorflow_model_remediation/common/docs.py
# def _no_op_decorator(obj):
# def _get_safe_decorator(decorator_name):
# 
# Path: tensorflow_model_remediation/common/types.py



import abc
import tensorflow as tf
from typing import Optional
from tensorflow_model_remediation.common import docs
from tensorflow_model_remediation.common import types
    tile_input: Boolean indicating whether to tile inputs before computing the
      kernel (see below for details).

  To be implemented by subclasses:

  - `call()`: contains the logic for the kernel tensor calculation.

  Example subclass Implementation:

  ```
  class GuassKernel(MinDiffKernel):

    def call(x, y):
      return tf.exp(-tf.reduce_sum(tf.square(x - y), axis=2) / 0.01)
  ```

  "Tiling" is a way of expanding the rank of the input tensors so that their
  dimensions work for the operations we need.

  If `x` and `y` are of rank `[N, D]` and `[M, D]` respectively, tiling expands
  them to be: `[N, ?, D]` and `[?, M, D]` where `tf` broadcasting will ensure
  that the operations between them work.
  """
  # pyformat: enable

  def __init__(self, tile_input: bool = True):
    self.tile_input = tile_input

  def __call__(self,
               x: types.TensorType,

# Path: tensorflow_model_remediation/common/docs.py
# def _no_op_decorator(obj):
# def _get_safe_decorator(decorator_name):
# 
# Path: tensorflow_model_remediation/common/types.py



# Path: tensorflow_model_remediation/min_diff/losses/kernels/base_kernel.py
import abc
import tensorflow as tf
from typing import Optional
from tensorflow_model_remediation.common import docs
from tensorflow_model_remediation.common import types

    tile_input: Boolean indicating whether to tile inputs before computing the
      kernel (see below for details).

  To be implemented by subclasses:

  - `call()`: contains the logic for the kernel tensor calculation.

  Example subclass Implementation:

  ```
  class GuassKernel(MinDiffKernel):

    def call(x, y):
      return tf.exp(-tf.reduce_sum(tf.square(x - y), axis=2) / 0.01)
  ```

  "Tiling" is a way of expanding the rank of the input tensors so that their
  dimensions work for the operations we need.

  If `x` and `y` are of rank `[N, D]` and `[M, D]` respectively, tiling expands
  them to be: `[N, ?, D]` and `[?, M, D]` where `tf` broadcasting will ensure
  that the operations between them work.
  """
  # pyformat: enable

  def __init__(self, tile_input: bool = True):
    self.tile_input = tile_input

  def __call__(self,
               x: types.TensorType,

               y: Optional[types.TensorType] = None) -> types.TensorType: