code: def _conv_general_permutations(self, dimension_numbers):
      
      lhs_spec, rhs_spec, out_spec = dimension_numbers
      lhs_char, rhs_char, out_char = ('N', 'C'), ('O', 'I'), ('N', 'C')
      charpairs = (lhs_char, rhs_char, out_char)
      for i, (a, b) in enumerate(charpairs):
        if not (dimension_numbers[i].count(a) == 1 and
                dimension_numbers[i].count(b) == 1):
          msg = ('convolution dimension_numbers[{}] must contain the characters '
                 '"{}" and "{}" exatly once, got {}.')
          raise TypeError(msg.format(i, a, b, dimension_numbers[i]))
        if len(dimension_numbers[i]) != len(set(dimension_numbers[i])):
          msg = ('convolution dimension_numbers[{}] cannot have duplicate '
                 'characters, got {}.')
          raise TypeError(msg.format(i, dimension_numbers[i]))
      if not (set(lhs_spec) - set(lhs_char) == set(rhs_spec) - set(rhs_char) ==
              set(out_spec) - set(out_char)):
        msg = ('convolution dimension_numbers elements must each have the same '
               'set of spatial characters, got {}.')
        raise TypeError(msg.format(dimension_numbers))
  
      def getperm(spec, charpair):
        spatial = (i for i, c in enumerate(spec) if c not in charpair)
        if spec is not rhs_spec:
          spatial = sorted(spatial, key=lambda i: rhs_spec.index(spec[i]))
        return (spec.index(charpair[0]), spec.index(charpair[1])) + tuple(spatial)
  
      lhs_perm, rhs_perm, out_perm = map(getperm, dimension_numbers, charpairs)
      return lhs_perm, rhs_perm, out_perm
docs: Utility for convolution dimension permutations relative to Conv HLO.