# Path: tf_slim/ops/arg_scope.py
# def add_arg_scope(func):
#   """Decorates a function with args so it can be used within an arg_scope.
# 
#   Args:
#     func: function to decorate.
# 
#   Returns:
#     A tuple with the decorated function func_with_args().
#   """
# 
#   def func_with_args(*args, **kwargs):
#     current_scope = current_arg_scope()
#     current_args = kwargs
#     key_func = arg_scope_func_key(func)
#     if key_func in current_scope:
#       current_args = current_scope[key_func].copy()
#       current_args.update(kwargs)
#     return func(*args, **current_args)
# 
#   _add_op(func)
#   setattr(func_with_args, '_key_op', arg_scope_func_key(func))
#   return tf_decorator.make_decorator(func, func_with_args)


from tf_slim.ops.arg_scope import add_arg_scope
from tensorflow.python.framework import dtypes
from tensorflow.python.framework import ops
from tensorflow.python.ops import array_ops
from tensorflow.python.ops import math_ops
from tensorflow.python.ops import nn
from tensorflow.python.ops import nn_ops
from tensorflow.python.util.deprecation import deprecated
from tensorflow.python.util.deprecation import deprecated_args
from tensorflow.python.util.deprecation import deprecated_argument_lookup
  if weights.get_shape().ndims == 0:
    batch_size = array_ops.reshape(
        array_ops.slice(array_ops.shape(losses), [0], [1]), [])
    num_per_batch = math_ops.div(
        math_ops.cast(array_ops.size(losses), dtypes.float32),
        math_ops.cast(batch_size, dtypes.float32))
    num_per_batch = array_ops.where(
        math_ops.equal(weights, 0), 0.0, num_per_batch)
    num_per_batch = math_ops.multiply(
        array_ops.ones(array_ops.reshape(batch_size, [1])), num_per_batch)
    return num_per_batch if per_batch else math_ops.reduce_sum(num_per_batch)

  # First, count the number of nonzero weights:
  if weights.get_shape().ndims >= 1:
    axis = list(range(1, weights.get_shape().ndims))
    num_nonzero_per_batch = math_ops.reduce_sum(
        math_ops.cast(math_ops.not_equal(weights, 0), dtypes.float32),
        axis=axis)

  # Next, determine the number of elements that weights would broadcast to:
  broadcast_dims = array_ops.slice(
      array_ops.shape(losses), [weights.get_shape().ndims], [-1])
  num_to_broadcast = math_ops.cast(math_ops.reduce_prod(broadcast_dims),
                                   dtypes.float32)

  num_per_batch = math_ops.multiply(num_nonzero_per_batch, num_to_broadcast)
  return num_per_batch if per_batch else math_ops.reduce_sum(num_per_batch)


@deprecated("2016-12-30", "Use tf.losses.add_loss instead.")

# Path: tf_slim/ops/arg_scope.py
# def add_arg_scope(func):
#   """Decorates a function with args so it can be used within an arg_scope.
# 
#   Args:
#     func: function to decorate.
# 
#   Returns:
#     A tuple with the decorated function func_with_args().
#   """
# 
#   def func_with_args(*args, **kwargs):
#     current_scope = current_arg_scope()
#     current_args = kwargs
#     key_func = arg_scope_func_key(func)
#     if key_func in current_scope:
#       current_args = current_scope[key_func].copy()
#       current_args.update(kwargs)
#     return func(*args, **current_args)
# 
#   _add_op(func)
#   setattr(func_with_args, '_key_op', arg_scope_func_key(func))
#   return tf_decorator.make_decorator(func, func_with_args)


# Path: tf_slim/losses/loss_ops.py
from tf_slim.ops.arg_scope import add_arg_scope
from tensorflow.python.framework import dtypes
from tensorflow.python.framework import ops
from tensorflow.python.ops import array_ops
from tensorflow.python.ops import math_ops
from tensorflow.python.ops import nn
from tensorflow.python.ops import nn_ops
from tensorflow.python.util.deprecation import deprecated
from tensorflow.python.util.deprecation import deprecated_args
from tensorflow.python.util.deprecation import deprecated_argument_lookup

  if weights.get_shape().ndims == 0:
    batch_size = array_ops.reshape(
        array_ops.slice(array_ops.shape(losses), [0], [1]), [])
    num_per_batch = math_ops.div(
        math_ops.cast(array_ops.size(losses), dtypes.float32),
        math_ops.cast(batch_size, dtypes.float32))
    num_per_batch = array_ops.where(
        math_ops.equal(weights, 0), 0.0, num_per_batch)
    num_per_batch = math_ops.multiply(
        array_ops.ones(array_ops.reshape(batch_size, [1])), num_per_batch)
    return num_per_batch if per_batch else math_ops.reduce_sum(num_per_batch)

  # First, count the number of nonzero weights:
  if weights.get_shape().ndims >= 1:
    axis = list(range(1, weights.get_shape().ndims))
    num_nonzero_per_batch = math_ops.reduce_sum(
        math_ops.cast(math_ops.not_equal(weights, 0), dtypes.float32),
        axis=axis)

  # Next, determine the number of elements that weights would broadcast to:
  broadcast_dims = array_ops.slice(
      array_ops.shape(losses), [weights.get_shape().ndims], [-1])
  num_to_broadcast = math_ops.cast(math_ops.reduce_prod(broadcast_dims),
                                   dtypes.float32)

  num_per_batch = math_ops.multiply(num_nonzero_per_batch, num_to_broadcast)
  return num_per_batch if per_batch else math_ops.reduce_sum(num_per_batch)


@deprecated("2016-12-30", "Use tf.losses.add_loss instead.")

@add_arg_scope