code: def identify_removable_identity_matrices(expr):
      editor = _EditArrayContraction(expr)
  
      flag = True
      while flag:
          flag = False
          for arg_with_ind in editor.args_with_ind:
              if isinstance(arg_with_ind.element, Identity):
                  k = arg_with_ind.element.shape[0]
                  # Candidate for removal:
                  if arg_with_ind.indices == [None, None]:
                      # Free identity matrix, will be cleared by _remove_trivial_dims:
                      continue
                  elif None in arg_with_ind.indices:
                      ind = [
                          j
                          for j in arg_with_ind.indices
                          if j is not None
                      ][0]
                      counted = editor.count_args_with_index(ind)
                      if counted == 1:
                          # Identity matrix contracted only on one index with itself,
                          # transform to a OneArray(k) element:
                          editor.insert_after(arg_with_ind, OneArray(k))
                          editor.args_with_ind.remove(arg_with_ind)
                          flag = True
                          break
                      elif counted > 2:
                          # Case counted = 2 is a matrix multiplication by identity matrix, skip it.
                          # Case counted > 2 is a multiple contraction,
                          # this is a case where the contraction becomes a diagonalization if the
                          # identity matrix is dropped.
                          continue
                  elif (
                      arg_with_ind.indices[0] == arg_with_ind.indices[1]
                  ):
                      ind = arg_with_ind.indices[0]
                      counted = editor.count_args_with_index(ind)
                      if counted > 1:
                          editor.args_with_ind.remove(arg_with_ind)
                          flag = True
                          break
                      else:
                          # This is a trace, skip it as it will be recognized somewhere else:
                          pass
              elif ask(Q.diagonal(arg_with_ind.element)):
                  if arg_with_ind.indices == [None, None]:
                      continue
                  elif None in arg_with_ind.indices:
                      pass
                  elif (
                      arg_with_ind.indices[0] == arg_with_ind.indices[1]
                  ):
                      ind = arg_with_ind.indices[0]
                      counted = editor.count_args_with_index(ind)
                      if counted == 3:
                          # A_ai B_bi D_ii ==> A_ai D_ij B_bj
                          ind_new = editor.get_new_contraction_index()
                          other_args = [
                              j
                              for j in editor.args_with_ind
                              if j != arg_with_ind
                          ]
                          other_args[1].indices = [
                              ind_new if j == ind else j
                              for j in other_args[1].indices
                          ]
                          arg_with_ind.indices = [ind, ind_new]
                          flag = True
                          break
  
      return editor.to_array_contraction()
  
imports: import itertools
  from collections import defaultdict
  from typing import Tuple, Union, FrozenSet, Dict, List, Optional
  from functools import singledispatch
  from itertools import accumulate
  from sympy import MatMul, Basic, Wild, KroneckerProduct
  from sympy.assumptions.ask import Q, ask
  from sympy.core.mul import Mul
  from sympy.core.singleton import S
  from sympy.matrices.expressions.diagonal import DiagMatrix
  from sympy.matrices.expressions.hadamard import hadamard_product, HadamardPower
  from sympy.matrices.expressions.matexpr import MatrixExpr
  from sympy.matrices.expressions.special import Identity, ZeroMatrix, OneMatrix
  from sympy.matrices.expressions.trace import Trace
  from sympy.matrices.expressions.transpose import Transpose
  from sympy.combinatorics.permutations import _af_invert, Permutation
  from sympy.matrices.matrixbase import MatrixBase
  from sympy.matrices.expressions.applyfunc import ElementwiseApplyFunction
  from sympy.matrices.expressions.matexpr import MatrixElement
  from sympy.tensor.array.expressions.array_expressions import PermuteDims, ArrayDiagonal, ArrayTensorProduct, OneArray, get_rank, _get_subrank, ZeroArray, ArrayContraction, ArrayAdd, _CodegenArrayAbstract, get_shape, ArrayElementwiseApplyFunc, _ArrayExpr, _EditArrayContraction, _ArgE, ArrayElement, _array_tensor_product, _array_contraction, _array_diagonal, _array_add, _permute_dims
  from sympy.tensor.array.expressions.utils import _get_mapping_from_subranks
label_desc: Use image node_id 32 for calling a global function with example usage: identify_removable_identity_matrices(expr) and returns: editor