class_docstr: A graph optimization pass on PyMIL to detect and fuse several variants of ``layer_norm`` or
  ``instance_norm``. Pattern 1 corresponds to either ``layer_norm`` or ``instance_norm``. Patterns 2-4
  are ``instance_norm``. Pattern 5 is ``layer_norm``. You can find these patterns in the methods for
  this class in the source code. To quickly view the source code, click the **[source]** button at
  the end of the class definition.
docstr: Insert instance_norm / layer_norm and delete all ops.
  
  :param reduce_op: Start operation of the pattern.
  :param block: Block
  :param gamma_var: Gamma variable.
  :param beta_var: Beta variable.
  :param epsilon_var: Epsilon variable.
  :param end_op: End operation of the pattern.
  :param ops_to_remove: Operations to remove.
docstr_tok: ["Insert","instance_norm","\/","layer_norm","and","delete","all","ops",".",":","param","reduce_op",":","Start","operation","of","the","pattern",".",":","param","block",":","Block",":","param","gamma_var",":","Gamma","variable",".",":","param","beta_var",":","Beta","variable",".",":","param","epsilon_var",":","Epsilon","variable",".",":","param","end_op",":","End","operation","of","the","pattern",".",":","param","ops_to_remove",":","Operations","to","remove","."]
code: def _try_apply_transform(
      reduce_op: Operation,
      block: Block,
      gamma_var: Var,
      beta_var: Var,
      epsilon_var: Var,
      end_op: Operation,
      ops_to_remove: List[Operation],
  ) -> bool:
      """
      Insert instance_norm / layer_norm and delete all ops.
  
      :param reduce_op: Start operation of the pattern.
      :param block: Block
      :param gamma_var: Gamma variable.
      :param beta_var: Beta variable.
      :param epsilon_var: Epsilon variable.
      :param end_op: End operation of the pattern.
      :param ops_to_remove: Operations to remove.
      """
      if not _check_no_output_connection(block, ops_to_remove):
          return False
  
      axes = reduce_op.axes.val
      rank = len(reduce_op.x.shape)
  
      # check whether the pattern is instance_norm or layer_norm
      is_layernorm = False
      is_instancenorm = False
      is_require_rank4_transpose = False
  
      negative_axes = [a - rank if a >= 0 else a for a in axes]
      negative_axes.sort()
  
      gamma_rank = gamma_var.rank if gamma_var is not None else -1
      beta_rank = beta_var.rank if beta_var is not None else -1
  
      if gamma_rank == len(axes) and beta_rank == len(axes):
          # axes for layer_norm must be [-1] or [-1, -2] or [-1, -2, -3] and so on
          if negative_axes == list(range(-len(negative_axes), 0)):
              is_layernorm = True
  
      if rank == 4 and negative_axes == [-3]:
          is_layernorm = (gamma_var is None and beta_var is None) or (
              gamma_rank == 1 and beta_rank == 1
          )
          gamma_var = gamma_var.val if gamma_var else None
          beta_var = beta_var.val if beta_var else None
  
      if rank == 4 and (
          negative_axes == [-2, -1] or negative_axes == [-3, -2]
      ):
          if (
              len(np.squeeze(gamma_var.val).shape) == 1
              and len(np.squeeze(beta_var.val).shape) == 1
          ):
              is_instancenorm = True
          if negative_axes == [-3, -2]:
              is_require_rank4_transpose = True
  
      if not (is_instancenorm or is_layernorm):
          return False
  
      # remove all the ops, and replace with a layer_norm or instance_norm op
      out_name = end_op.outputs[0].name
  
      if is_require_rank4_transpose:
          x = mb.transpose(
              x=reduce_op.x,
              perm=[0, 3, 1, 2],
              name=out_name + "_transpose_nhwc_nchw",
              before_op=end_op,
          )
      if is_instancenorm:
          x = mb.instance_norm(
              x=x if is_require_rank4_transpose else reduce_op.x,
              gamma=np.squeeze(gamma_var.val),
              beta=np.squeeze(beta_var.val),
              epsilon=epsilon_var,
              name=out_name + "_instancenorm"
              if is_require_rank4_transpose
              else out_name,
              before_op=end_op,
          )
      else:  # is_layernorm
          x = mb.layer_norm(
              x=x if is_require_rank4_transpose else reduce_op.x,
              axes=axes,
              gamma=gamma_var,
              beta=beta_var,
              epsilon=epsilon_var,
              name=out_name + "_layernorm"
              if is_require_rank4_transpose
              else out_name,
              before_op=end_op,
          )
      if is_require_rank4_transpose:
          x = mb.transpose(
              x=x,
              perm=[0, 2, 3, 1],
              name=out_name + "_transpose_nchw_nhwc",
              before_op=end_op,
          )
  
      end_op.enclosing_block.replace_uses_of_var_after_op(
          anchor_op=end_op, old_var=end_op.outputs[0], new_var=x
      )
      # Remove all the ops at once
      block.remove_ops(ops_to_remove)
      return True
  
imports: from typing import List, Optional
  import numpy
  from coremltools import _logger
  from coremltools.converters.mil.mil import Block
  from coremltools.converters.mil.mil import Builder
  from coremltools.converters.mil.mil import Operation, Program, Var
  from coremltools.converters.mil.mil.passes.graph_pass import AbstractGraphPass
  from coremltools.converters.mil.mil.passes.helper import _check_no_output_connection, block_context_manager
  from coremltools.converters.mil.mil.passes.pass_registry import register_pass
label_desc: Use image node_id 5 for calling the fuse_layernorm_or_instancenorm obj's underlying member method code with example usage: obj._try_apply_transform(reduce_op, block, gamma_var, beta_var, epsilon_var, end_op, ops_to_remove) and returns: True, False, False