code: def local_dimshuffle_subtensor(fgraph, node):
      """If a subtensor is inside a dimshuffle which only drop
      broadcastable dimensions, scrap the dimshuffle and index the
      subtensor in a way that avoids the degenerate dimension
  
      x[i:j, :, k:l].dimshuffle(0, 2) =>
          x[i:j, 0, k:l] if x.broadcastable == (False, True, False)
  
      x[i:j, k:l, :].dimshuffle(0, 2) => x[i:j, k, :]
      x[i:j, k:, :].dimshuffle(0, 2) => x[i:j, k, :]
      x[i:j, :l, :].dimshuffle(0, 2) => x[i:j, 0, :]
  
      """
      if isinstance(node.op, DimShuffle) and node.inputs[0].owner:
          # the dimshuffle can only drop dimensions (cannot reshape nor add 'x')
          if "x" in node.op.new_order:
              return False
          new_order = node.op.new_order
          # new order could be empty
          # Verif that we don't change dimensions order.
          if len(new_order) > 1:
              past_dim = new_order[0]
              for dim in new_order[1:]:
                  if not dim > past_dim:
                      return False
                  else:
                      past_dim = dim
  
          input_ = node.inputs[0]
          if isinstance(input_.owner.op, Subtensor):
              # the arguments missing from the dimshuffles must be dims
              # that are broadcastable
              broadcastable = input_.broadcastable
  
              missing_dims = list(range(input_.ndim))
              for dim in new_order:
                  missing_dims.remove(dim)
  
              if not all(broadcastable[i] for i in missing_dims):
                  return False
  
              # create a new idx_list for a new Subtensor object
              # have to loop on idx_list and inputs
              # inputs has the length of sum of non None elements of idx_list
              # (check in slice!).
              # len(missing_dims) can be < len(idx_list), this happens if
              # tensor was indexed such as x[scalar, :, :], check that as well
              new_idx_list = list(input_.owner.op.idx_list)
              new_inputs = [input_.owner.inputs[0]]
              zero = constant(0)
              j = 0
              slice_i = -1
              subtensor_removed_dims = 0
              for i, idx in enumerate(input_.owner.op.idx_list):
                  if isinstance(idx, slice):
                      slice_i += 1
                      if slice_i in missing_dims:
                          # Missing dim is a slice(None), remove by indexing by 0
                          if idx == slice(None):
                              new_idx_list[i] = zero
                              new_inputs += [zero]
                          # Missing dim is an ordinary slice with known output dim length of 1
                          # Remove by indexing by start
                          else:
                              if idx.start is None:
                                  start = zero
                              else:
                                  start = input_.owner.inputs[1 + j]
                                  j += 1
                              new_idx_list[i] = start
                              new_inputs += [start]
  
                              # Ignore useless stop and step input if there is one
                              for slice_attr in ("stop", "step"):
                                  if (
                                      getattr(idx, slice_attr)
                                      is not None
                                  ):
                                      j += 1
  
                      # Keep non-dropped slice inputs
                      else:
                          for slice_attr in ("start", "stop", "step"):
                              if getattr(idx, slice_attr) is not None:
                                  new_inputs += [
                                      input_.owner.inputs[1 + j]
                                  ]
                                  j += 1
                  # Keep non-dropped non-slice inputs
                  else:
                      new_inputs += [input_.owner.inputs[1 + j]]
                      j += 1
                      subtensor_removed_dims += 1
              # Verify the trailing dimensions the subtensor didn't look at.
              for idx in range(
                  len(input_.owner.op.idx_list), new_inputs[0].ndim
              ):
                  if (idx - subtensor_removed_dims) in missing_dims:
                      while len(new_idx_list) < idx:
                          new_idx_list.append(slice(None))
  
                      new_idx_list.append(zero)
                      new_inputs.append(zero)
              return [Subtensor(new_idx_list)(*new_inputs)]
      return False
  
file_path: pytensor/pytensor/tensor/rewriting/uncanonicalize.py
imports: from pytensor import scalar
  from pytensor.graph.rewriting.basic import copy_stack_trace, node_rewriter
  from pytensor.tensor.basic import Alloc, alloc, constant
  from pytensor.tensor.elemwise import CAReduce, DimShuffle
  from pytensor.tensor.math import Argmax, Max, MaxAndArgmax, Min, neg
  from pytensor.tensor.rewriting.basic import register_uncanonicalize
  from pytensor.tensor.shape import Reshape, reshape
  from pytensor.tensor.subtensor import Subtensor
label_desc: Use image node_id 6 for calling a global function with example usage: local_dimshuffle_subtensor(fgraph, node) and returns: False, False, list, False, False