boson.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. """Bosonic quantum operators."""
  2. from sympy.core.numbers import Integer
  3. from sympy.core.singleton import S
  4. from sympy.functions.elementary.complexes import conjugate
  5. from sympy.functions.elementary.exponential import exp
  6. from sympy.functions.elementary.miscellaneous import sqrt
  7. from sympy.physics.quantum import Operator
  8. from sympy.physics.quantum import HilbertSpace, FockSpace, Ket, Bra
  9. from sympy.functions.special.tensor_functions import KroneckerDelta
  10. __all__ = [
  11. 'BosonOp',
  12. 'BosonFockKet',
  13. 'BosonFockBra',
  14. 'BosonCoherentKet',
  15. 'BosonCoherentBra'
  16. ]
  17. class BosonOp(Operator):
  18. """A bosonic operator that satisfies [a, Dagger(a)] == 1.
  19. Parameters
  20. ==========
  21. name : str
  22. A string that labels the bosonic mode.
  23. annihilation : bool
  24. A bool that indicates if the bosonic operator is an annihilation (True,
  25. default value) or creation operator (False)
  26. Examples
  27. ========
  28. >>> from sympy.physics.quantum import Dagger, Commutator
  29. >>> from sympy.physics.quantum.boson import BosonOp
  30. >>> a = BosonOp("a")
  31. >>> Commutator(a, Dagger(a)).doit()
  32. 1
  33. """
  34. @property
  35. def name(self):
  36. return self.args[0]
  37. @property
  38. def is_annihilation(self):
  39. return bool(self.args[1])
  40. @classmethod
  41. def default_args(self):
  42. return ("a", True)
  43. def __new__(cls, *args, **hints):
  44. if not len(args) in [1, 2]:
  45. raise ValueError('1 or 2 parameters expected, got %s' % args)
  46. if len(args) == 1:
  47. args = (args[0], S.One)
  48. if len(args) == 2:
  49. args = (args[0], Integer(args[1]))
  50. return Operator.__new__(cls, *args)
  51. def _eval_commutator_BosonOp(self, other, **hints):
  52. if self.name == other.name:
  53. # [a^\dagger, a] = -1
  54. if not self.is_annihilation and other.is_annihilation:
  55. return S.NegativeOne
  56. elif 'independent' in hints and hints['independent']:
  57. # [a, b] = 0
  58. return S.Zero
  59. return None
  60. def _eval_commutator_FermionOp(self, other, **hints):
  61. return S.Zero
  62. def _eval_anticommutator_BosonOp(self, other, **hints):
  63. if 'independent' in hints and hints['independent']:
  64. # {a, b} = 2 * a * b, because [a, b] = 0
  65. return 2 * self * other
  66. return None
  67. def _eval_adjoint(self):
  68. return BosonOp(str(self.name), not self.is_annihilation)
  69. def _print_contents_latex(self, printer, *args):
  70. if self.is_annihilation:
  71. return r'{%s}' % str(self.name)
  72. else:
  73. return r'{{%s}^\dagger}' % str(self.name)
  74. def _print_contents(self, printer, *args):
  75. if self.is_annihilation:
  76. return r'%s' % str(self.name)
  77. else:
  78. return r'Dagger(%s)' % str(self.name)
  79. def _print_contents_pretty(self, printer, *args):
  80. from sympy.printing.pretty.stringpict import prettyForm
  81. pform = printer._print(self.args[0], *args)
  82. if self.is_annihilation:
  83. return pform
  84. else:
  85. return pform**prettyForm('\N{DAGGER}')
  86. class BosonFockKet(Ket):
  87. """Fock state ket for a bosonic mode.
  88. Parameters
  89. ==========
  90. n : Number
  91. The Fock state number.
  92. """
  93. def __new__(cls, n):
  94. return Ket.__new__(cls, n)
  95. @property
  96. def n(self):
  97. return self.label[0]
  98. @classmethod
  99. def dual_class(self):
  100. return BosonFockBra
  101. @classmethod
  102. def _eval_hilbert_space(cls, label):
  103. return FockSpace()
  104. def _eval_innerproduct_BosonFockBra(self, bra, **hints):
  105. return KroneckerDelta(self.n, bra.n)
  106. def _apply_from_right_to_BosonOp(self, op, **options):
  107. if op.is_annihilation:
  108. return sqrt(self.n) * BosonFockKet(self.n - 1)
  109. else:
  110. return sqrt(self.n + 1) * BosonFockKet(self.n + 1)
  111. class BosonFockBra(Bra):
  112. """Fock state bra for a bosonic mode.
  113. Parameters
  114. ==========
  115. n : Number
  116. The Fock state number.
  117. """
  118. def __new__(cls, n):
  119. return Bra.__new__(cls, n)
  120. @property
  121. def n(self):
  122. return self.label[0]
  123. @classmethod
  124. def dual_class(self):
  125. return BosonFockKet
  126. @classmethod
  127. def _eval_hilbert_space(cls, label):
  128. return FockSpace()
  129. class BosonCoherentKet(Ket):
  130. """Coherent state ket for a bosonic mode.
  131. Parameters
  132. ==========
  133. alpha : Number, Symbol
  134. The complex amplitude of the coherent state.
  135. """
  136. def __new__(cls, alpha):
  137. return Ket.__new__(cls, alpha)
  138. @property
  139. def alpha(self):
  140. return self.label[0]
  141. @classmethod
  142. def dual_class(self):
  143. return BosonCoherentBra
  144. @classmethod
  145. def _eval_hilbert_space(cls, label):
  146. return HilbertSpace()
  147. def _eval_innerproduct_BosonCoherentBra(self, bra, **hints):
  148. if self.alpha == bra.alpha:
  149. return S.One
  150. else:
  151. return exp(-(abs(self.alpha)**2 + abs(bra.alpha)**2 - 2 * conjugate(bra.alpha) * self.alpha)/2)
  152. def _apply_from_right_to_BosonOp(self, op, **options):
  153. if op.is_annihilation:
  154. return self.alpha * self
  155. else:
  156. return None
  157. class BosonCoherentBra(Bra):
  158. """Coherent state bra for a bosonic mode.
  159. Parameters
  160. ==========
  161. alpha : Number, Symbol
  162. The complex amplitude of the coherent state.
  163. """
  164. def __new__(cls, alpha):
  165. return Bra.__new__(cls, alpha)
  166. @property
  167. def alpha(self):
  168. return self.label[0]
  169. @classmethod
  170. def dual_class(self):
  171. return BosonCoherentKet
  172. def _apply_operator_BosonOp(self, op, **options):
  173. if not op.is_annihilation:
  174. return self.alpha * self
  175. else:
  176. return None