# Path: morph_net/framework/op_handler.py
# class OpHandler(object):
#   def is_source_op(self):
#   def is_passthrough(self):
#   def assign_grouping(self, op, op_reg_manager):
#   def create_regularizer(self, op_slice):
# 
# Path: morph_net/framework/op_handler_util.py
# OP_TYPES_WITH_MULTIPLE_OUTPUTS = ('SplitV',)
# WEIGHTS_INDEX_DICT = {
#     'Conv2D': 1,
#     'Conv2DBackpropInput': 1,
#     'DepthwiseConv2dNative': 1,
#     'MatMul': 1
# }
# def get_input_ops(op, op_reg_manager, whitelist_indices=None):
#   def is_const(tensor):
#   def is_weight_tensor(i, op_type):
# def get_output_ops(op, op_reg_manager):
# def get_ops_without_groups(ops, op_reg_manager):
# def remove_non_passthrough_ops(ops, op_reg_manager):
# def group_op_with_inputs_and_outputs(op, input_op_slices, output_op_slices,
#                                      aligned_op_slice_sizes, op_reg_manager):
# def get_concat_input_op_slices(concat_ops, op_reg_manager):
# def get_op_slices(ops, op_reg_manager):
# def get_op_slice_sizes(op_slices):
# def get_aligned_op_slice_sizes(op_slices, input_op_slices, output_op_slices):
# def get_aligned_sizes(op_slice_sizes):
# def _get_num_slices(op_slice_sizes):
# def reslice_concat_ops(concat_ops, aligned_op_slice_sizes, op_reg_manager):
# def get_total_slice_size(op_slice_sizes, index, slice_count):
# def reslice_ops(ops, aligned_op_slice_sizes, op_reg_manager):
# def _get_source_op_slices(op_slices, op_reg_manager):
# def group_aligned_input_output_slices(
#     op, input_ops_to_process, output_ops_to_process, input_op_slices,
#     output_op_slices, aligned_op_slice_sizes, op_reg_manager):
# def get_op_size(op):
# def separate_same_size_ops(reference_op, ops):
# def group_match(regex, op_slices):
# 
# Path: morph_net/framework/tpu_util.py
# def run_on_cpu():
# def is_on_cpu():
# def get_variable_name(read_variable_op):
# def maybe_convert_to_variable(tensor):
# def write_to_variable(tensor, fail_if_exists=True):
# def read_from_variable(tensor):
# def is_intermediate_var(v):
# 
# Path: morph_net/op_regularizers/group_lasso_regularizer.py
# class GroupLassoRegularizer(generic_regularizers.OpRegularizer):
#   def __init__(self, weight_tensor, reduce_dims, threshold, l1_fraction=0.0):
#   def regularization_vector(self):
#   def alive_vector(self):


import abc
from morph_net.framework import op_handler
from morph_net.framework import op_handler_util
from morph_net.framework import tpu_util
from morph_net.op_regularizers import group_lasso_regularizer

  @abc.abstractmethod
  def _reduce_dims(self, op):
    # Reduction dimensions for Group Lasso.
    pass

  @property
  def is_source_op(self):
    return True

  @property
  def is_passthrough(self):
    return False

  def assign_grouping(self, op, op_reg_manager):
    """Assign grouping to the given op and updates the manager.

    Args:
      op: tf.Operation to assign grouping to.
      op_reg_manager: OpRegularizerManager to keep track of the grouping.
    """
    # This is a source op so begin by getting the OpGroup or creating one.
    op_slices = op_reg_manager.get_op_slices(op)
    for op_slice in op_slices:
      op_group = op_reg_manager.get_op_group(op_slice)
      if op_group is None:
        op_reg_manager.create_op_group_for_op_slice(op_slice)

    # Check if all input ops have groups, or tell the manager to process them.
    input_ops = op_handler_util.get_input_ops(op, op_reg_manager)

# Path: morph_net/framework/op_handler.py
# class OpHandler(object):
#   def is_source_op(self):
#   def is_passthrough(self):
#   def assign_grouping(self, op, op_reg_manager):
#   def create_regularizer(self, op_slice):
# 
# Path: morph_net/framework/op_handler_util.py
# OP_TYPES_WITH_MULTIPLE_OUTPUTS = ('SplitV',)
# WEIGHTS_INDEX_DICT = {
#     'Conv2D': 1,
#     'Conv2DBackpropInput': 1,
#     'DepthwiseConv2dNative': 1,
#     'MatMul': 1
# }
# def get_input_ops(op, op_reg_manager, whitelist_indices=None):
#   def is_const(tensor):
#   def is_weight_tensor(i, op_type):
# def get_output_ops(op, op_reg_manager):
# def get_ops_without_groups(ops, op_reg_manager):
# def remove_non_passthrough_ops(ops, op_reg_manager):
# def group_op_with_inputs_and_outputs(op, input_op_slices, output_op_slices,
#                                      aligned_op_slice_sizes, op_reg_manager):
# def get_concat_input_op_slices(concat_ops, op_reg_manager):
# def get_op_slices(ops, op_reg_manager):
# def get_op_slice_sizes(op_slices):
# def get_aligned_op_slice_sizes(op_slices, input_op_slices, output_op_slices):
# def get_aligned_sizes(op_slice_sizes):
# def _get_num_slices(op_slice_sizes):
# def reslice_concat_ops(concat_ops, aligned_op_slice_sizes, op_reg_manager):
# def get_total_slice_size(op_slice_sizes, index, slice_count):
# def reslice_ops(ops, aligned_op_slice_sizes, op_reg_manager):
# def _get_source_op_slices(op_slices, op_reg_manager):
# def group_aligned_input_output_slices(
#     op, input_ops_to_process, output_ops_to_process, input_op_slices,
#     output_op_slices, aligned_op_slice_sizes, op_reg_manager):
# def get_op_size(op):
# def separate_same_size_ops(reference_op, ops):
# def group_match(regex, op_slices):
# 
# Path: morph_net/framework/tpu_util.py
# def run_on_cpu():
# def is_on_cpu():
# def get_variable_name(read_variable_op):
# def maybe_convert_to_variable(tensor):
# def write_to_variable(tensor, fail_if_exists=True):
# def read_from_variable(tensor):
# def is_intermediate_var(v):
# 
# Path: morph_net/op_regularizers/group_lasso_regularizer.py
# class GroupLassoRegularizer(generic_regularizers.OpRegularizer):
#   def __init__(self, weight_tensor, reduce_dims, threshold, l1_fraction=0.0):
#   def regularization_vector(self):
#   def alive_vector(self):


# Path: morph_net/framework/group_lasso_base_op_handler.py
import abc
from morph_net.framework import op_handler
from morph_net.framework import op_handler_util
from morph_net.framework import tpu_util
from morph_net.op_regularizers import group_lasso_regularizer


  @abc.abstractmethod
  def _reduce_dims(self, op):
    # Reduction dimensions for Group Lasso.
    pass

  @property
  def is_source_op(self):
    return True

  @property
  def is_passthrough(self):
    return False

  def assign_grouping(self, op, op_reg_manager):
    """Assign grouping to the given op and updates the manager.

    Args:
      op: tf.Operation to assign grouping to.
      op_reg_manager: OpRegularizerManager to keep track of the grouping.
    """
    # This is a source op so begin by getting the OpGroup or creating one.
    op_slices = op_reg_manager.get_op_slices(op)
    for op_slice in op_slices:
      op_group = op_reg_manager.get_op_group(op_slice)
      if op_group is None:
        op_reg_manager.create_op_group_for_op_slice(op_slice)

    # Check if all input ops have groups, or tell the manager to process them.
    input_ops = op_handler_util.get_input_ops(op, op_reg_manager)

    input_ops_without_group = op_handler_util.get_ops_without_groups(