fermion.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  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. class FermionFockKet(Ket):
  85. """Fock state ket for a fermionic mode.
  86. Parameters
  87. ==========
  88. n : Number
  89. The Fock state number.
  90. """
  91. def __new__(cls, n):
  92. if n not in (0, 1):
  93. raise ValueError("n must be 0 or 1")
  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 FermionFockBra
  101. @classmethod
  102. def _eval_hilbert_space(cls, label):
  103. return HilbertSpace()
  104. def _eval_innerproduct_FermionFockBra(self, bra, **hints):
  105. return KroneckerDelta(self.n, bra.n)
  106. def _apply_operator_FermionOp(self, op, **options):
  107. if op.is_annihilation:
  108. if self.n == 1:
  109. return FermionFockKet(0)
  110. else:
  111. return S.Zero
  112. else:
  113. if self.n == 0:
  114. return FermionFockKet(1)
  115. else:
  116. return S.Zero
  117. class FermionFockBra(Bra):
  118. """Fock state bra for a fermionic mode.
  119. Parameters
  120. ==========
  121. n : Number
  122. The Fock state number.
  123. """
  124. def __new__(cls, n):
  125. if n not in (0, 1):
  126. raise ValueError("n must be 0 or 1")
  127. return Bra.__new__(cls, n)
  128. @property
  129. def n(self):
  130. return self.label[0]
  131. @classmethod
  132. def dual_class(self):
  133. return FermionFockKet