class_docstr: The MatMulHandler is a node handler which handles the sharding strategy generation for the matmul operation.
  According to https://pytorch.org/docs/stable/generated/torch.matmul.html, the operations will vary depending on
  the operands.
class_docstr_tok: ["The","MatMulHandler","is","a","node","handler","which","handles","the","sharding","strategy","generation","for","the","matmul","operation",".","According","to","https",":","\/\/pytorch.org\/docs\/stable\/generated\/torch.matmul.html",",","the","operations","will","vary","depending","on","the","operands","."]
code: def post_process(
      self, strategy: ShardingStrategy
  ) -> Union[ShardingStrategy, List[ShardingStrategy]]:
      if self.matmul_type in [MatMulType.DOT, MatMulType.MV]:
          return strategy
      elif self.matmul_type == MatMulType.MM:
          if self.input_meta_data.dim() == 1:
              # if a 1 is prepended to the input shape (this occurs when input is a 1D tensor)
              # we need to remove that dim
              input_sharding_spec = strategy.get_sharding_spec_by_name(
                  str(self.node.args[0])
              )
              input_physical_shape = self.node.args[0]._meta_data.shape
              dim_partition_dict = (
                  input_sharding_spec.dim_partition_dict
              )
  
              # remove the partitioning in the dim 0
              if 0 in dim_partition_dict:
                  dim_partition_dict.pop(0, None)
  
              # move the partitioning in dim 1 to dim 0
              if -1 in dim_partition_dict:
                  shard = dim_partition_dict.pop(-1)
                  dim_partition_dict[0] = shard
              if 1 in dim_partition_dict:
                  shard = dim_partition_dict.pop(1)
                  dim_partition_dict[0] = shard
  
              # re-init the sharding spec
              input_sharding_spec.__init__(
                  input_sharding_spec.device_mesh,
                  entire_shape=input_physical_shape,
                  dim_partition_dict=dim_partition_dict,
              )
              return strategy
          else:
              return strategy
      elif self.matmul_type == MatMulType.BMM:
          op_data_mapping = self.get_operation_data_mapping()
  
          strategies = [strategy]
          # recover the physical sharding spec
          for transform in self.transforms[::-1]:
              recovered_stragies = []
              for strategy_ in strategies:
                  output = transform.recover(op_data_mapping, strategy_)
                  if isinstance(output, ShardingStrategy):
                      recovered_stragies.append(output)
                  elif isinstance(output, (list, tuple)):
                      recovered_stragies.extend(output)
                  else:
                      raise TypeError(
                          f"Found unexpected output type {type(output)} from the recover method of BmmTransform"
                      )
              strategies = recovered_stragies
          for index, strategies in enumerate(strategies):
              strategies.name = f"{strategies.name}_{index}"
          return strategies
  
imports: import operator
  from abc import ABC, abstractmethod
  from copy import deepcopy
  from enum import Enum
  from functools import reduce
  from typing import Dict, List, Union
  import torch
  from colossalai.auto_parallel.tensor_shard.utils.broadcast import BroadcastType, get_broadcast_dim_info, get_broadcast_shape
  from colossalai.tensor.sharding_spec import ShardingSpecException
  from ..sharding_strategy import OperationData, OperationDataType, ShardingStrategy
  from ..utils import recover_sharding_spec_for_broadcast_shape
  from .node_handler import MetaInfoNodeHandler
  from .registry import operator_registry
  from .strategy import BatchedMatMulStrategyGenerator, DotProductStrategyGenerator, LinearProjectionStrategyGenerator, MatVecStrategyGenerator, StrategyGenerator
label_desc: Use image node_id 9 for calling the MatMulHandler obj's underlying member method code with example usage: obj.post_process(strategy) and returns: strategy, strategy, strategy, strategies