parameters: (operands)
return_statement: return (input_subscripts, output_subscript, operands)
docstring: A reproduction of einsum c side einsum parsing in python.
  
      Returns
      -------
      input_strings : str
          Parsed input strings
      output_string : str
          Parsed output string
      operands : list of array_like
          The operands to use in the numpy contraction
  
      Examples
      --------
      The operand list is simplified to reduce printing:
  
      >>> np.random.seed(123)
      >>> a = np.random.rand(4, 4)
      >>> b = np.random.rand(4, 4, 4)
      >>> _parse_einsum_input(('...a,...a->...', a, b))
      ('za,xza', 'xz', [a, b]) # may vary
  
      >>> _parse_einsum_input((a, [Ellipsis, 0], b, [Ellipsis, 0]))
      ('za,xza', 'xz', [a, b]) # may vary
docstring_summary: A reproduction of einsum c side einsum parsing in python.
docstring_tokens: A reproduction of einsum c side einsum parsing in python .
function: def _parse_einsum_input(operands):
      """
      A reproduction of einsum c side einsum parsing in python.
  
      Returns
      -------
      input_strings : str
          Parsed input strings
      output_string : str
          Parsed output string
      operands : list of array_like
          The operands to use in the numpy contraction
  
      Examples
      --------
      The operand list is simplified to reduce printing:
  
      >>> np.random.seed(123)
      >>> a = np.random.rand(4, 4)
      >>> b = np.random.rand(4, 4, 4)
      >>> _parse_einsum_input(('...a,...a->...', a, b))
      ('za,xza', 'xz', [a, b]) # may vary
  
      >>> _parse_einsum_input((a, [Ellipsis, 0], b, [Ellipsis, 0]))
      ('za,xza', 'xz', [a, b]) # may vary
      """
  
      if len(operands) == 0:
          raise ValueError("No input operands")
  
      if isinstance(operands[0], str):
          subscripts = operands[0].replace(" ", "")
          operands = [asanyarray(v) for v in operands[1:]]
  
          # Ensure all characters are valid
          for s in subscripts:
              if s in '.,->':
                  continue
              if s not in einsum_symbols:
                  raise ValueError("Character %s is not a valid symbol." % s)
  
      else:
          tmp_operands = list(operands)
          operand_list = []
          subscript_list = []
          for p in range(len(operands) // 2):
              operand_list.append(tmp_operands.pop(0))
              subscript_list.append(tmp_operands.pop(0))
  
          output_list = tmp_operands[-1] if len(tmp_operands) else None
          operands = [asanyarray(v) for v in operand_list]
          subscripts = ""
          last = len(subscript_list) - 1
          for num, sub in enumerate(subscript_list):
              for s in sub:
                  if s is Ellipsis:
                      subscripts += "..."
                  else:
                      try:
                          s = operator.index(s)
                      except TypeError as e:
                          raise TypeError("For this input type lists must contain "
                                          "either int or Ellipsis") from e
                      subscripts += einsum_symbols[s]
              if num != last:
                  subscripts += ","
  
          if output_list is not None:
              subscripts += "->"
              for s in output_list:
                  if s is Ellipsis:
                      subscripts += "..."
                  else:
                      try:
                          s = operator.index(s)
                      except TypeError as e:
                          raise TypeError("For this input type lists must contain "
                                          "either int or Ellipsis") from e
                      subscripts += einsum_symbols[s]
      # Check for proper "->"
      if ("-" in subscripts) or (">" in subscripts):
          invalid = (subscripts.count("-") > 1) or (subscripts.count(">") > 1)
          if invalid or (subscripts.count("->") != 1):
              raise ValueError("Subscripts can only contain one '->'.")
  
      # Parse ellipses
      if "." in subscripts:
          used = subscripts.replace(".", "").replace(",", "").replace("->", "")
          unused = list(einsum_symbols_set - set(used))
          ellipse_inds = "".join(unused)
          longest = 0
  
          if "->" in subscripts:
              input_tmp, output_sub = subscripts.split("->")
              split_subscripts = input_tmp.split(",")
              out_sub = True
          else:
              split_subscripts = subscripts.split(',')
              out_sub = False
  
          for num, sub in enumerate(split_subscripts):
              if "." in sub:
                  if (sub.count(".") != 3) or (sub.count("...") != 1):
                      raise ValueError("Invalid Ellipses.")
  
                  # Take into account numerical values
                  if operands[num].shape == ():
                      ellipse_count = 0
                  else:
                      ellipse_count = max(operands[num].ndim, 1)
                      ellipse_count -= (len(sub) - 3)
  
                  if ellipse_count > longest:
                      longest = ellipse_count
  
                  if ellipse_count < 0:
                      raise ValueError("Ellipses lengths do not match.")
                  elif ellipse_count == 0:
                      split_subscripts[num] = sub.replace('...', '')
                  else:
                      rep_inds = ellipse_inds[-ellipse_count:]
                      split_subscripts[num] = sub.replace('...', rep_inds)
  
          subscripts = ",".join(split_subscripts)
          if longest == 0:
              out_ellipse = ""
          else:
              out_ellipse = ellipse_inds[-longest:]
  
          if out_sub:
              subscripts += "->" + output_sub.replace("...", out_ellipse)
          else:
              # Special care for outputless ellipses
              output_subscript = ""
              tmp_subscripts = subscripts.replace(",", "")
              for s in sorted(set(tmp_subscripts)):
                  if s not in (einsum_symbols):
                      raise ValueError("Character %s is not a valid symbol." % s)
                  if tmp_subscripts.count(s) == 1:
                      output_subscript += s
              normal_inds = ''.join(sorted(set(output_subscript) -
                                           set(out_ellipse)))
  
              subscripts += "->" + out_ellipse + normal_inds
  
      # Build output string if does not exist
      if "->" in subscripts:
          input_subscripts, output_subscript = subscripts.split("->")
      else:
          input_subscripts = subscripts
          # Build output subscripts
          tmp_subscripts = subscripts.replace(",", "")
          output_subscript = ""
          for s in sorted(set(tmp_subscripts)):
              if s not in einsum_symbols:
                  raise ValueError("Character %s is not a valid symbol." % s)
              if tmp_subscripts.count(s) == 1:
                  output_subscript += s
  
      # Make sure output subscripts are in the input
      for char in output_subscript:
          if char not in input_subscripts:
              raise ValueError("Output character %s did not appear in the input"
                               % char)
  
      # Make sure number operands is equivalent to the number of terms
      if len(input_subscripts.split(',')) != len(operands):
          raise ValueError("Number of einsum subscripts must be equal to the "
                           "number of operands.")
  
      return (input_subscripts, output_subscript, operands)
function_tokens: def _parse_einsum_input ( operands ) : if len ( operands ) == 0 : raise ValueError ( "No input operands" ) if isinstance ( operands [ 0 ] , str ) : subscripts = operands [ 0 ] . replace ( " " , "" ) operands = [ asanyarray ( v ) for v in operands [ 1 : ] ] # Ensure all characters are valid for s in subscripts : if s in '.,->' : continue if s not in einsum_symbols : raise ValueError ( "Character %s is not a valid symbol." % s ) else : tmp_operands = list ( operands ) operand_list = [ ] subscript_list = [ ] for p in range ( len ( operands ) // 2 ) : operand_list . append ( tmp_operands . pop ( 0 ) ) subscript_list . append ( tmp_operands . pop ( 0 ) ) output_list = tmp_operands [ - 1 ] if len ( tmp_operands ) else None operands = [ asanyarray ( v ) for v in operand_list ] subscripts = "" last = len ( subscript_list ) - 1 for num , sub in enumerate ( subscript_list ) : for s in sub : if s is Ellipsis : subscripts += "..." else : try : s = operator . index ( s ) except TypeError as e : raise TypeError ( "For this input type lists must contain " "either int or Ellipsis" ) from e subscripts += einsum_symbols [ s ] if num != last : subscripts += "," if output_list is not None : subscripts += "->" for s in output_list : if s is Ellipsis : subscripts += "..." else : try : s = operator . index ( s ) except TypeError as e : raise TypeError ( "For this input type lists must contain " "either int or Ellipsis" ) from e subscripts += einsum_symbols [ s ] # Check for proper "->" if ( "-" in subscripts ) or ( ">" in subscripts ) : invalid = ( subscripts . count ( "-" ) > 1 ) or ( subscripts . count ( ">" ) > 1 ) if invalid or ( subscripts . count ( "->" ) != 1 ) : raise ValueError ( "Subscripts can only contain one '->'." ) # Parse ellipses if "." in subscripts : used = subscripts . replace ( "." , "" ) . replace ( "," , "" ) . replace ( "->" , "" ) unused = list ( einsum_symbols_set - set ( used ) ) ellipse_inds = "" . join ( unused ) longest = 0 if "->" in subscripts : input_tmp , output_sub = subscripts . split ( "->" ) split_subscripts = input_tmp . split ( "," ) out_sub = True else : split_subscripts = subscripts . split ( ',' ) out_sub = False for num , sub in enumerate ( split_subscripts ) : if "." in sub : if ( sub . count ( "." ) != 3 ) or ( sub . count ( "..." ) != 1 ) : raise ValueError ( "Invalid Ellipses." ) # Take into account numerical values if operands [ num ] . shape == ( ) : ellipse_count = 0 else : ellipse_count = max ( operands [ num ] . ndim , 1 ) ellipse_count -= ( len ( sub ) - 3 ) if ellipse_count > longest : longest = ellipse_count if ellipse_count < 0 : raise ValueError ( "Ellipses lengths do not match." ) elif ellipse_count == 0 : split_subscripts [ num ] = sub . replace ( '...' , '' ) else : rep_inds = ellipse_inds [ - ellipse_count : ] split_subscripts [ num ] = sub . replace ( '...' , rep_inds ) subscripts = "," . join ( split_subscripts ) if longest == 0 : out_ellipse = "" else : out_ellipse = ellipse_inds [ - longest : ] if out_sub : subscripts += "->" + output_sub . replace ( "..." , out_ellipse ) else : # Special care for outputless ellipses output_subscript = "" tmp_subscripts = subscripts . replace ( "," , "" ) for s in sorted ( set ( tmp_subscripts ) ) : if s not in ( einsum_symbols ) : raise ValueError ( "Character %s is not a valid symbol." % s ) if tmp_subscripts . count ( s ) == 1 : output_subscript += s normal_inds = '' . join ( sorted ( set ( output_subscript ) - set ( out_ellipse ) ) ) subscripts += "->" + out_ellipse + normal_inds # Build output string if does not exist if "->" in subscripts : input_subscripts , output_subscript = subscripts . split ( "->" ) else : input_subscripts = subscripts # Build output subscripts tmp_subscripts = subscripts . replace ( "," , "" ) output_subscript = "" for s in sorted ( set ( tmp_subscripts ) ) : if s not in einsum_symbols : raise ValueError ( "Character %s is not a valid symbol." % s ) if tmp_subscripts . count ( s ) == 1 : output_subscript += s # Make sure output subscripts are in the input for char in output_subscript : if char not in input_subscripts : raise ValueError ( "Output character %s did not appear in the input" % char ) # Make sure number operands is equivalent to the number of terms if len ( input_subscripts . split ( ',' ) ) != len ( operands ) : raise ValueError ( "Number of einsum subscripts must be equal to the " "number of operands." ) return ( input_subscripts , output_subscript , operands )