code: def qapply(e, **options):
      """Apply operators to states in a quantum expression.
  
      Parameters
      ==========
  
      e : Expr
          The expression containing operators and states. This expression tree
          will be walked to find operators acting on states symbolically.
      options : dict
          A dict of key/value pairs that determine how the operator actions
          are carried out.
  
          The following options are valid:
  
          * ``dagger``: try to apply Dagger operators to the left
            (default: False).
          * ``ip_doit``: call ``.doit()`` in inner products when they are
            encountered (default: True).
  
      Returns
      =======
  
      e : Expr
          The original expression, but with the operators applied to states.
  
      Examples
      ========
  
          >>> from sympy.physics.quantum import qapply, Ket, Bra
          >>> b = Bra('b')
          >>> k = Ket('k')
          >>> A = k * b
          >>> A
          |k><b|
          >>> qapply(A * b.dual / (b * b.dual))
          |k>
          >>> qapply(k.dual * A / (k.dual * k), dagger=True)
          <b|
          >>> qapply(k.dual * A / (k.dual * k))
          <k|*|k><b|/<k|k>
      """
      from sympy.physics.quantum.density import Density
  
      dagger = options.get("dagger", False)
  
      if e == 0:
          return S.Zero
  
      # This may be a bit aggressive but ensures that everything gets expanded
      # to its simplest form before trying to apply operators. This includes
      # things like (A+B+C)*|a> and A*(|a>+|b>) and all Commutators and
      # TensorProducts. The only problem with this is that if we can't apply
      # all the Operators, we have just expanded everything.
      # TODO: don't expand the scalars in front of each Mul.
      e = e.expand(commutator=True, tensorproduct=True)
  
      # If we just have a raw ket, return it.
      if isinstance(e, KetBase):
          return e
  
      # We have an Add(a, b, c, ...) and compute
      # Add(qapply(a), qapply(b), ...)
      elif isinstance(e, Add):
          result = 0
          for arg in e.args:
              result += qapply(arg, **options)
          return result.expand()
  
      # For a Density operator call qapply on its state
      elif isinstance(e, Density):
          new_args = [
              (qapply(state, **options), prob)
              for (state, prob) in e.args
          ]
          return Density(*new_args)
  
      # For a raw TensorProduct, call qapply on its args.
      elif isinstance(e, TensorProduct):
          return TensorProduct(*[qapply(t, **options) for t in e.args])
  
      # For a Pow, call qapply on its base.
      elif isinstance(e, Pow):
          return qapply(e.base, **options) ** e.exp
  
      # We have a Mul where there might be actual operators to apply to kets.
      elif isinstance(e, Mul):
          c_part, nc_part = e.args_cnc()
          c_mul = Mul(*c_part)
          nc_mul = Mul(*nc_part)
          if isinstance(nc_mul, Mul):
              result = c_mul * qapply_Mul(nc_mul, **options)
          else:
              result = c_mul * qapply(nc_mul, **options)
          if result == e and dagger:
              return Dagger(qapply_Mul(Dagger(e), **options))
          else:
              return result
  
      # In all other cases (State, Operator, Pow, Commutator, InnerProduct,
      # OuterProduct) we won't ever have operators to apply to kets.
      else:
          return e
  
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 1 for calling a global function with example usage: qapply(e) and returns: S, e, result, Density, TensorProduct, unknown, e, Dagger, result