# 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):


from morph_net.framework import op_handler
from morph_net.framework import op_handler_util

    Args:
      op: tf.Operation to assign grouping to.
      op_reg_manager: OpRegularizerManager to keep track of the grouping.
    """
    # Check if all output ops have groups, or tell the manager to process them.
    output_ops = op_handler_util.get_output_ops(op, op_reg_manager)
    output_ops_without_group = op_handler_util.get_ops_without_groups(
        output_ops, op_reg_manager)

    # Remove non-passthrough ops from outputs ops to group with.
    output_ops = op_handler_util.remove_non_passthrough_ops(
        output_ops, op_reg_manager)

    # Only group with ops that have the same size.  Process the ops that have
    # mismatched size.
    output_ops_to_group, output_ops_to_process = (
        op_handler_util.separate_same_size_ops(op, output_ops))

    # Also process ungrouped ops.
    for output_op_without_group in output_ops_without_group:
      if output_op_without_group not in output_ops_to_process:
        output_ops_to_process.append(output_op_without_group)

    # Align op slice sizes if needed.
    op_slices = op_reg_manager.get_op_slices(op)
    output_op_slices = op_handler_util.get_op_slices(
        output_ops_to_group, op_reg_manager)
    aligned_op_slice_sizes = op_handler_util.get_aligned_op_slice_sizes(
        op_slices, [], output_op_slices)

# 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/leaf_op_handler.py
from morph_net.framework import op_handler
from morph_net.framework import op_handler_util


    Args:
      op: tf.Operation to assign grouping to.
      op_reg_manager: OpRegularizerManager to keep track of the grouping.
    """
    # Check if all output ops have groups, or tell the manager to process them.
    output_ops = op_handler_util.get_output_ops(op, op_reg_manager)
    output_ops_without_group = op_handler_util.get_ops_without_groups(
        output_ops, op_reg_manager)

    # Remove non-passthrough ops from outputs ops to group with.
    output_ops = op_handler_util.remove_non_passthrough_ops(
        output_ops, op_reg_manager)

    # Only group with ops that have the same size.  Process the ops that have
    # mismatched size.
    output_ops_to_group, output_ops_to_process = (
        op_handler_util.separate_same_size_ops(op, output_ops))

    # Also process ungrouped ops.
    for output_op_without_group in output_ops_without_group:
      if output_op_without_group not in output_ops_to_process:
        output_ops_to_process.append(output_op_without_group)

    # Align op slice sizes if needed.
    op_slices = op_reg_manager.get_op_slices(op)
    output_op_slices = op_handler_util.get_op_slices(
        output_ops_to_group, op_reg_manager)
    aligned_op_slice_sizes = op_handler_util.get_aligned_op_slice_sizes(
        op_slices, [], output_op_slices)

    op_handler_util.reslice_ops([op] + output_ops_to_group,