text: """Bosonic quantum operators."""
  
  from sympy.core.mul import Mul
  from sympy.core.numbers import Integer
  from sympy.core.singleton import S
  from sympy.functions.elementary.complexes import conjugate
  from sympy.functions.elementary.exponential import exp
  from sympy.functions.elementary.miscellaneous import sqrt
  from sympy.physics.quantum import Operator
  from sympy.physics.quantum import HilbertSpace, FockSpace, Ket, Bra, IdentityOperator
  from sympy.functions.special.tensor_functions import KroneckerDelta
  
  
  __all__ = [
      'BosonOp',
      'BosonFockKet',
      'BosonFockBra',
      'BosonCoherentKet',
      'BosonCoherentBra'
  ]
  
  
  class BosonOp(Operator):
      """A bosonic operator that satisfies [a, Dagger(a)] == 1.
  
      Parameters
      ==========
  
      name : str
          A string that labels the bosonic mode.
  
      annihilation : bool
          A bool that indicates if the bosonic operator is an annihilation (True,
          default value) or creation operator (False)
  
      Examples
      ========
  
      >>> from sympy.physics.quantum import Dagger, Commutator
      >>> from sympy.physics.quantum.boson import BosonOp
      >>> a = BosonOp("a")
      >>> Commutator(a, Dagger(a)).doit()
      1
      """
  
      @property
      def name(self):
          return self.args[0]
  
      @property
      def is_annihilation(self):
          return bool(self.args[1])
  
      @classmethod
      def default_args(self):
          return ("a", True)
  
      def __new__(cls, *args, **hints):
          if not len(args) in [1, 2]:
              raise ValueError('1 or 2 parameters expected, got %s' % args)
  
          if len(args) == 1:
              args = (args[0], S.One)
  
          if len(args) == 2:
              args = (args[0], Integer(args[1]))
  
          return Operator.__new__(cls, *args)
  
      def _eval_commutator_BosonOp(self, other, **hints):
          if self.name == other.name:
              # [a^\dagger, a] = -1
              if not self.is_annihilation and other.is_annihilation:
                  return S.NegativeOne
  
          elif 'independent' in hints and hints['independent']:
              # [a, b] = 0
              return S.Zero
  
          return None
  
      def _eval_commutator_FermionOp(self, other, **hints):
          return S.Zero
  
      def _eval_anticommutator_BosonOp(self, other, **hints):
          if 'independent' in hints and hints['independent']:
              # {a, b} = 2 * a * b, because [a, b] = 0
              return 2 * self * other
  
          return None
  
      def _eval_adjoint(self):
          return BosonOp(str(self.name), not self.is_annihilation)
  
      def __mul__(self, other):
  
          if other == IdentityOperator(2):
              return self
  
          if isinstance(other, Mul):
              args1 = tuple(arg for arg in other.args if arg.is_commutative)
              args2 = tuple(arg for arg in other.args if not arg.is_commutative)
              x = self
              for y in args2:
                  x = x * y
              return Mul(*args1) * x
  
          return Mul(self, other)
  
      def _print_contents_latex(self, printer, *args):
          if self.is_annihilation:
              return r'{%s}' % str(self.name)
          else:
              return r'{{%s}^\dagger}' % str(self.name)
  
      def _print_contents(self, printer, *args):
          if self.is_annihilation:
              return r'%s' % str(self.name)
          else:
              return r'Dagger(%s)' % str(self.name)
  
      def _print_contents_pretty(self, printer, *args):
          from sympy.printing.pretty.stringpict import prettyForm
          pform = printer._print(self.args[0], *args)
          if self.is_annihilation:
              return pform
          else:
              return pform**prettyForm('\N{DAGGER}')
  
  
  class BosonFockKet(Ket):
      """Fock state ket for a bosonic mode.
  
      Parameters
      ==========
  
      n : Number
          The Fock state number.
  
      """
  
      def __new__(cls, n):
          return Ket.__new__(cls, n)
  
      @property
      def n(self):
          return self.label[0]
  
      @classmethod
      def dual_class(self):
          return BosonFockBra
  
      @classmethod
      def _eval_hilbert_space(cls, label):
          return FockSpace()
  
      def _eval_innerproduct_BosonFockBra(self, bra, **hints):
          return KroneckerDelta(self.n, bra.n)
  
      def _apply_operator_BosonOp(self, op, **options):
          if op.is_annihilation:
              return sqrt(self.n) * BosonFockKet(self.n - 1)
          else:
              return sqrt(self.n + 1) * BosonFockKet(self.n + 1)
  
  
  class BosonFockBra(Bra):
      """Fock state bra for a bosonic mode.
  
      Parameters
      ==========
  
      n : Number
          The Fock state number.
  
      """
  
      def __new__(cls, n):
          return Bra.__new__(cls, n)
  
      @property
      def n(self):
          return self.label[0]
  
      @classmethod
      def dual_class(self):
          return BosonFockKet
  
      @classmethod
      def _eval_hilbert_space(cls, label):
          return FockSpace()
  
  
  class BosonCoherentKet(Ket):
      """Coherent state ket for a bosonic mode.
  
      Parameters
      ==========
  
      alpha : Number, Symbol
          The complex amplitude of the coherent state.
  
      """
  
      def __new__(cls, alpha):
          return Ket.__new__(cls, alpha)
  
      @property
      def alpha(self):
          return self.label[0]
  
      @classmethod
      def dual_class(self):
          return BosonCoherentBra
  
      @classmethod
      def _eval_hilbert_space(cls, label):
          return HilbertSpace()
  
      def _eval_innerproduct_BosonCoherentBra(self, bra, **hints):
          if self.alpha == bra.alpha:
              return S.One
          else:
              return exp(-(abs(self.alpha)**2 + abs(bra.alpha)**2 - 2 * conjugate(bra.alpha) * self.alpha)/2)
  
      def _apply_operator_BosonOp(self, op, **options):
          if op.is_annihilation:
              return self.alpha * self
          else:
              return None
  
  
  class BosonCoherentBra(Bra):
      """Coherent state bra for a bosonic mode.
  
      Parameters
      ==========
  
      alpha : Number, Symbol
          The complex amplitude of the coherent state.
  
      """
  
      def __new__(cls, alpha):
          return Bra.__new__(cls, alpha)
  
      @property
      def alpha(self):
          return self.label[0]
  
      @classmethod
      def dual_class(self):
          return BosonCoherentKet
  
      def _apply_operator_BosonOp(self, op, **options):
          if not op.is_annihilation:
              return self.alpha * self
          else:
              return None
  