fermion.py 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. """Fermionic quantum operators."""
  2. from sympy.core.numbers import Integer
  3. from sympy.core.singleton import S
  4. from sympy.physics.quantum import Operator
  5. from sympy.physics.quantum import HilbertSpace, Ket, Bra
  6. from sympy.functions.special.tensor_functions import KroneckerDelta
  7. __all__ = [
  8. 'FermionOp',
  9. 'FermionFockKet',
  10. 'FermionFockBra'
  11. ]
  12. class FermionOp(Operator):
  13. """A fermionic operator that satisfies {c, Dagger(c)} == 1.
  14. Parameters
  15. ==========
  16. name : str
  17. A string that labels the fermionic mode.
  18. annihilation : bool
  19. A bool that indicates if the fermionic operator is an annihilation
  20. (True, default value) or creation operator (False)
  21. Examples
  22. ========
  23. >>> from sympy.physics.quantum import Dagger, AntiCommutator
  24. >>> from sympy.physics.quantum.fermion import FermionOp
  25. >>> c = FermionOp("c")
  26. >>> AntiCommutator(c, Dagger(c)).doit()
  27. 1
  28. """
  29. @property
  30. def name(self):
  31. return self.args[0]
  32. @property
  33. def is_annihilation(self):
  34. return bool(self.args[1])
  35. @classmethod
  36. def default_args(self):
  37. return ("c", True)
  38. def __new__(cls, *args, **hints):
  39. if not len(args) in [1, 2]:
  40. raise ValueError('1 or 2 parameters expected, got %s' % args)
  41. if len(args) == 1:
  42. args = (args[0], S.One)
  43. if len(args) == 2:
  44. args = (args[0], Integer(args[1]))
  45. return Operator.__new__(cls, *args)
  46. def _eval_commutator_FermionOp(self, other, **hints):
  47. if 'independent' in hints and hints['independent']:
  48. # [c, d] = 0
  49. return S.Zero
  50. return None
  51. def _eval_anticommutator_FermionOp(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.One
  56. elif 'independent' in hints and hints['independent']:
  57. # {c, d} = 2 * c * d, because [c, d] = 0 for independent operators
  58. return 2 * self * other
  59. return None
  60. def _eval_anticommutator_BosonOp(self, other, **hints):
  61. # because fermions and bosons commute
  62. return 2 * self * other
  63. def _eval_commutator_BosonOp(self, other, **hints):
  64. return S.Zero
  65. def _eval_adjoint(self):
  66. return FermionOp(str(self.name), not self.is_annihilation)
  67. def _print_contents_latex(self, printer, *args):
  68. if self.is_annihilation:
  69. return r'{%s}' % str(self.name)
  70. else:
  71. return r'{{%s}^\dagger}' % str(self.name)
  72. def _print_contents(self, printer, *args):
  73. if self.is_annihilation:
  74. return r'%s' % str(self.name)
  75. else:
  76. return r'Dagger(%s)' % str(self.name)
  77. def _print_contents_pretty(self, printer, *args):
  78. from sympy.printing.pretty.stringpict import prettyForm
  79. pform = printer._print(self.args[0], *args)
  80. if self.is_annihilation:
  81. return pform
  82. else:
  83. return pform**prettyForm('\N{DAGGER}')
  84. def _eval_power(self, exp):
  85. from sympy.core.singleton import S
  86. if exp == 0:
  87. return S.One
  88. elif exp == 1:
  89. return self
  90. elif (exp > 1) == True and exp.is_integer == True:
  91. return S.Zero
  92. elif (exp < 0) == True or exp.is_integer == False:
  93. raise ValueError("Fermionic operators can only be raised to a"
  94. " positive integer power")
  95. return Operator._eval_power(self, exp)
  96. class FermionFockKet(Ket):
  97. """Fock state ket for a fermionic mode.
  98. Parameters
  99. ==========
  100. n : Number
  101. The Fock state number.
  102. """
  103. def __new__(cls, n):
  104. if n not in (0, 1):
  105. raise ValueError("n must be 0 or 1")
  106. return Ket.__new__(cls, n)
  107. @property
  108. def n(self):
  109. return self.label[0]
  110. @classmethod
  111. def dual_class(self):
  112. return FermionFockBra
  113. @classmethod
  114. def _eval_hilbert_space(cls, label):
  115. return HilbertSpace()
  116. def _eval_innerproduct_FermionFockBra(self, bra, **hints):
  117. return KroneckerDelta(self.n, bra.n)
  118. def _apply_from_right_to_FermionOp(self, op, **options):
  119. if op.is_annihilation:
  120. if self.n == 1:
  121. return FermionFockKet(0)
  122. else:
  123. return S.Zero
  124. else:
  125. if self.n == 0:
  126. return FermionFockKet(1)
  127. else:
  128. return S.Zero
  129. class FermionFockBra(Bra):
  130. """Fock state bra for a fermionic mode.
  131. Parameters
  132. ==========
  133. n : Number
  134. The Fock state number.
  135. """
  136. def __new__(cls, n):
  137. if n not in (0, 1):
  138. raise ValueError("n must be 0 or 1")
  139. return Bra.__new__(cls, n)
  140. @property
  141. def n(self):
  142. return self.label[0]
  143. @classmethod
  144. def dual_class(self):
  145. return FermionFockKet