code: def qapply_Mul(e, **options):
      ip_doit = options.get("ip_doit", True)
  
      args = list(e.args)
  
      # If we only have 0 or 1 args, we have nothing to do and return.
      if len(args) <= 1 or not isinstance(e, Mul):
          return e
      rhs = args.pop()
      lhs = args.pop()
  
      # Make sure we have two non-commutative objects before proceeding.
      if (
          not isinstance(rhs, Wavefunction)
          and sympify(rhs).is_commutative
      ) or (
          not isinstance(lhs, Wavefunction)
          and sympify(lhs).is_commutative
      ):
          return e
  
      # For a Pow with an integer exponent, apply one of them and reduce the
      # exponent by one.
      if isinstance(lhs, Pow) and lhs.exp.is_Integer:
          args.append(lhs.base ** (lhs.exp - 1))
          lhs = lhs.base
  
      # Pull OuterProduct apart
      if isinstance(lhs, OuterProduct):
          args.append(lhs.ket)
          lhs = lhs.bra
  
      # Call .doit() on Commutator/AntiCommutator.
      if isinstance(lhs, (Commutator, AntiCommutator)):
          comm = lhs.doit()
          if isinstance(comm, Add):
              return qapply(
                  e.func(*(args + [comm.args[0], rhs]))
                  + e.func(*(args + [comm.args[1], rhs])),
                  **options,
              )
          else:
              return qapply(e.func(*args) * comm * rhs, **options)
  
      # Apply tensor products of operators to states
      if (
          isinstance(lhs, TensorProduct)
          and all(
              isinstance(arg, (Operator, State, Mul, Pow)) or arg == 1
              for arg in lhs.args
          )
          and isinstance(rhs, TensorProduct)
          and all(
              isinstance(arg, (Operator, State, Mul, Pow)) or arg == 1
              for arg in rhs.args
          )
          and len(lhs.args) == len(rhs.args)
      ):
          result = TensorProduct(
              *[
                  qapply(lhs.args[n] * rhs.args[n], **options)
                  for n in range(len(lhs.args))
              ]
          ).expand(tensorproduct=True)
          return qapply_Mul(e.func(*args), **options) * result
  
      # Now try to actually apply the operator and build an inner product.
      try:
          result = lhs._apply_operator(rhs, **options)
      except NotImplementedError:
          result = None
  
      if result is None:
          _apply_right = getattr(rhs, "_apply_from_right_to", None)
          if _apply_right is not None:
              try:
                  result = _apply_right(lhs, **options)
              except NotImplementedError:
                  result = None
  
      if result is None:
          if isinstance(lhs, BraBase) and isinstance(rhs, KetBase):
              result = InnerProduct(lhs, rhs)
              if ip_doit:
                  result = result.doit()
  
      # TODO: I may need to expand before returning the final result.
      if result == 0:
          return S.Zero
      elif result is None:
          if len(args) == 0:
              # We had two args to begin with so args=[].
              return e
          else:
              return (
                  qapply_Mul(e.func(*(args + [lhs])), **options) * rhs
              )
      elif isinstance(result, InnerProduct):
          return result * qapply_Mul(e.func(*args), **options)
      else:  # result is a scalar times a Mul, Add or TensorProduct
          return qapply(e.func(*args) * result, **options)
  
file_path: sympy/sympy/physics/quantum/qapply.py
imports: from sympy.core.add import Add
  from sympy.core.mul import Mul
  from sympy.core.power import Pow
  from sympy.core.singleton import S
  from sympy.core.sympify import sympify
  from sympy.physics.quantum.anticommutator import AntiCommutator
  from sympy.physics.quantum.commutator import Commutator
  from sympy.physics.quantum.dagger import Dagger
  from sympy.physics.quantum.innerproduct import InnerProduct
  from sympy.physics.quantum.operator import OuterProduct, Operator
  from sympy.physics.quantum.state import State, KetBase, BraBase, Wavefunction
  from sympy.physics.quantum.tensorproduct import TensorProduct
label_desc: Use image node_id 2 for calling a global function with example usage: qapply_Mul(e) and returns: e, e, unknown, S, qapply, qapply, e, unknown, unknown, qapply