class_docstr: Perform tensor multiplication expressed according to the einsum notation.
  The mode/equation that is currently supported is multiplying matrices that are laid out on
  dimensions -1 and -3, treating all the other dimensions as batch. Broadcasting is supported along batch dimensions.
  In particular, the inputs must be of the following shapes:
  
  * Rank 4 input case:
      * Input 1: ``[B, C, H, W1]``.
      * Input 2: ``[B, W1, H, W2]``.
      * Output: ``[B, C, H, W2]``.
      * If, for one of the inputs, the dimensions ``"B"`` or ``"H"`` is 1, they are broadcast to match the other input.
  
  * Rank 3 input case:
      * Input 1: ``[C, H, W1]``.
      * Input 2: ``[W1, H, W2]``.
      * Output: ``[C, H, W2]``.
      * If, for one of the inputs, the dimension ``"H"`` is 1, it is broadcast to match the other input.
  
  Parameters
  ----------
  values : Tuple(tensor_1, tensor_2)
      * Where:
          * ``tensor_1``: ``tensor<[*D, C, H, W1], T>``.
          * Must be of rank 3 or 4.
          * ``tensor_2``: ``tensor<[*D, W1, H, W2], T>``.
          * Must be of rank 3 or 4.
  equation: const<str>
      * Supported equations are:
          * ``"nchw,nwhu->nchu"`` and its equivalent equation strings.
          * ``"chw,whr->chr"`` and its equivalent equation strings.
  
  Returns
  -------
  tensor<[\*D, C, H, W2], T>
      * Same ranks as the inputs.
  
  Attributes
  ----------
  T: fp16, fp32
class_docstr_tok: ["Perform","tensor","multiplication","expressed","according","to","the","einsum","notation",".","The","mode\/equation","that","is","currently","supported","is","multiplying","matrices","that","are","laid","out","on","dimensions","-1","and","-3",",","treating","all","the","other","dimensions","as","batch",".","Broadcasting","is","supported","along","batch","dimensions",".","In","particular",",","the","inputs","must","be","of","the","following","shapes",":","*","Rank","4","input","case",":","*","Input","1",":","``","[","B",",","C",",","H",",","W1","]","``",".","*","Input","2",":","``","[","B",",","W1",",","H",",","W2","]","``",".","*","Output",":","``","[","B",",","C",",","H",",","W2","]","``",".","*","If",",","for","one","of","the","inputs",",","the","dimensions","``","``","B","''","``","or","``","``","H","''","``","is","1",",","they","are","broadcast","to","match","the","other","input",".","*","Rank","3","input","case",":","*","Input","1",":","``","[","C",",","H",",","W1","]","``",".","*","Input","2",":","``","[","W1",",","H",",","W2","]","``",".","*","Output",":","``","[","C",",","H",",","W2","]","``",".","*","If",",","for","one","of","the","inputs",",","the","dimension","``","``","H","''","``","is","1",",","it","is","broadcast","to","match","the","other","input",".","Parameters","--","--","--","--","--","values",":","Tuple","(","tensor_1",",","tensor_2",")","*","Where",":","*","``","tensor_1","``",":","``","tensor","<","[","*","D",",","C",",","H",",","W1","]",",","T",">","``",".","*","Must","be","of","rank","3","or","4",".","*","``","tensor_2","``",":","``","tensor","<","[","*","D",",","W1",",","H",",","W2","]",",","T",">","``",".","*","Must","be","of","rank","3","or","4.","equation",":","const","<","str",">","*","Supported","equations","are",":","*","``","``","nchw",",","nwhu-",">","nchu","''","``","and","its","equivalent","equation","strings",".","*","``","``","chw",",","whr-",">","chr","''","``","and","its","equivalent","equation","strings",".","Returns","--","--","--","-","tensor","<","[","\\","*","D",",","C",",","H",",","W2","]",",","T",">","*","Same","ranks","as","the","inputs",".","Attributes","--","--","--","--","--","T",":","fp16",",","fp32"]
code: def value_inference(self):
      x = self.values[0]
      y = self.values[1]
      x_shape = x.val.shape
      y_shape = y.val.shape
      # broadcast dimensions -2 and -4, if required
      if len(x_shape) == 4:
          x_shape = (
              max(x_shape[0], y_shape[0]),
              x_shape[1],
              max(x_shape[2], y_shape[2]),
              x_shape[3],
          )
          y_shape = (
              max(x_shape[0], y_shape[0]),
              y_shape[1],
              max(x_shape[2], y_shape[2]),
              y_shape[3],
          )
      elif len(x_shape) == 3:
          x_shape = (
              x_shape[0],
              max(x_shape[1], y_shape[1]),
              x_shape[2],
          )
          y_shape = (
              y_shape[0],
              max(x_shape[1], y_shape[1]),
              y_shape[2],
          )
      else:
          raise ValueError("ranks of the input must be 3 or 4")
      res = np.einsum(
          self.equation.val,
          np.broadcast_to(x.val, x_shape),
          np.broadcast_to(y.val, y_shape),
      )
      return res
  
imports: import numpy
  from coremltools.converters.mil.mil import DefaultInputs, InputSpec, Operation, TensorInputType, TupleInputType, precondition, types
  from coremltools.converters.mil.mil.operation import VALUE
  from coremltools.converters.mil.mil.ops.defs._op_reqs import register_op
  from coremltools.converters.mil.mil.ops.defs._utils import broadcast_shapes, parse_einsum_equation
  from coremltools.converters.mil.mil.types import nptype_from_builtin
  from coremltools.converters.mil.mil.types.symbolic import is_symbolic
label_desc: Use image node_id 2 for calling the einsum obj's underlying member method code with example usage: obj.value_inference() and returns: res