# Path: t3f/ops.py
# def full(tt, name='t3f_full'):
# def _full_tt(tt):
# def _full_tt_batch(tt):
# def tt_tt_matmul(tt_matrix_a, tt_matrix_b):
# def tt_dense_matmul(tt_matrix_a, matrix_b):
# def dense_tt_matmul(matrix_a, tt_matrix_b):
# def sparse_tt_matmul(sparse_matrix_a, tt_matrix_b):
# def tt_sparse_matmul(tt_matrix_a, sparse_matrix_b):
# def matmul(a, b, name='t3f_matmul'):
# def tt_tt_flat_inner(tt_a, tt_b):
# def tt_dense_flat_inner(tt_a, dense_b):
# def tt_sparse_flat_inner(tt_a, sparse_b):
# def dense_tt_flat_inner(dense_a, tt_b):
# def sparse_tt_flat_inner(sparse_a, tt_b):
# def flat_inner(a, b, name='t3f_flat_inner'):
# def _add_tensor_cores(tt_a, tt_b):
# def _add_batch_tensor_cores(tt_a, tt_b):
# def _add_matrix_cores(tt_a, tt_b):
# def _add_batch_matrix_cores(tt_a, tt_b):
# def add(tt_a, tt_b, name='t3f_add'):
# def multiply(tt_left, right, name='t3f_multiply'):
# def frobenius_norm_squared(tt, differentiable=False,
#                            name='t3f_frobenius_norm_squared'):
# def frobenius_norm(tt, epsilon=1e-5, differentiable=False,
#                    name='t3f_frobenius_norm'):
# def transpose(tt_matrix, name='t3f_transpose'):
# def quadratic_form(A, b, c, name='t3f_bilinear_form'):
# def bilinear_form(A, b, c, name='t3f_bilinear_form'):
# def bilinear_form_two_mat(x, A, B, y, name='t3f_bilinear_xaby'):
# def cast(tt, dtype, name='t3f_cast'):
# def gather_nd(tt, indices, name='t3f_gather_nd'):
# def renormalize_tt_cores(tt, epsilon=1e-8, name='t3f_renormalize_tt_cores'):


import numbers
import tensorflow as tf
from t3f import ops



def l2_regularizer(scale, scope=None):
  """Returns a function that applies L2 regularization to TensorTrain weights.

  Args:
    scale: A scalar multiplier `Tensor`. 0.0 disables the regularizer.
    scope: An optional scope name.

  Returns:
    A function with signature `l2(tt)` that applies L2 regularization.

  Raises:
    ValueError: If scale is negative or if scale is not a float.
  """
  if isinstance(scale, numbers.Integral):
    raise ValueError('scale cannot be an integer: %s' % (scale,))
  if isinstance(scale, numbers.Real):
    if scale < 0.:
      raise ValueError('Setting a scale less than 0 on a regularizer: %g.' %
                       scale)
    if scale == 0.:
      tf.logging.info('Scale of 0 disables regularizer.')
      return lambda _: None

  def l2(tt):
    """Applies l2 regularization to TensorTrain object."""
    with tf.name_scope(scope, 'l2_regularizer') as name:
      my_scale = tf.convert_to_tensor(scale, dtype=tt.dtype, name='scale')

# Path: t3f/ops.py
# def full(tt, name='t3f_full'):
# def _full_tt(tt):
# def _full_tt_batch(tt):
# def tt_tt_matmul(tt_matrix_a, tt_matrix_b):
# def tt_dense_matmul(tt_matrix_a, matrix_b):
# def dense_tt_matmul(matrix_a, tt_matrix_b):
# def sparse_tt_matmul(sparse_matrix_a, tt_matrix_b):
# def tt_sparse_matmul(tt_matrix_a, sparse_matrix_b):
# def matmul(a, b, name='t3f_matmul'):
# def tt_tt_flat_inner(tt_a, tt_b):
# def tt_dense_flat_inner(tt_a, dense_b):
# def tt_sparse_flat_inner(tt_a, sparse_b):
# def dense_tt_flat_inner(dense_a, tt_b):
# def sparse_tt_flat_inner(sparse_a, tt_b):
# def flat_inner(a, b, name='t3f_flat_inner'):
# def _add_tensor_cores(tt_a, tt_b):
# def _add_batch_tensor_cores(tt_a, tt_b):
# def _add_matrix_cores(tt_a, tt_b):
# def _add_batch_matrix_cores(tt_a, tt_b):
# def add(tt_a, tt_b, name='t3f_add'):
# def multiply(tt_left, right, name='t3f_multiply'):
# def frobenius_norm_squared(tt, differentiable=False,
#                            name='t3f_frobenius_norm_squared'):
# def frobenius_norm(tt, epsilon=1e-5, differentiable=False,
#                    name='t3f_frobenius_norm'):
# def transpose(tt_matrix, name='t3f_transpose'):
# def quadratic_form(A, b, c, name='t3f_bilinear_form'):
# def bilinear_form(A, b, c, name='t3f_bilinear_form'):
# def bilinear_form_two_mat(x, A, B, y, name='t3f_bilinear_xaby'):
# def cast(tt, dtype, name='t3f_cast'):
# def gather_nd(tt, indices, name='t3f_gather_nd'):
# def renormalize_tt_cores(tt, epsilon=1e-8, name='t3f_renormalize_tt_cores'):


# Path: t3f/regularizers.py
import numbers
import tensorflow as tf
from t3f import ops




def l2_regularizer(scale, scope=None):
  """Returns a function that applies L2 regularization to TensorTrain weights.

  Args:
    scale: A scalar multiplier `Tensor`. 0.0 disables the regularizer.
    scope: An optional scope name.

  Returns:
    A function with signature `l2(tt)` that applies L2 regularization.

  Raises:
    ValueError: If scale is negative or if scale is not a float.
  """
  if isinstance(scale, numbers.Integral):
    raise ValueError('scale cannot be an integer: %s' % (scale,))
  if isinstance(scale, numbers.Real):
    if scale < 0.:
      raise ValueError('Setting a scale less than 0 on a regularizer: %g.' %
                       scale)
    if scale == 0.:
      tf.logging.info('Scale of 0 disables regularizer.')
      return lambda _: None

  def l2(tt):
    """Applies l2 regularization to TensorTrain object."""
    with tf.name_scope(scope, 'l2_regularizer') as name:
      my_scale = tf.convert_to_tensor(scale, dtype=tt.dtype, name='scale')

      return tf.multiply(my_scale, ops.frobenius_norm_squared(tt), name=name)