Spaces:
Sleeping
Sleeping
File size: 4,983 Bytes
6a86ad5 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 |
"""Fermionic quantum operators."""
from sympy.core.numbers import Integer
from sympy.core.singleton import S
from sympy.physics.quantum import Operator
from sympy.physics.quantum import HilbertSpace, Ket, Bra
from sympy.functions.special.tensor_functions import KroneckerDelta
__all__ = [
'FermionOp',
'FermionFockKet',
'FermionFockBra'
]
class FermionOp(Operator):
"""A fermionic operator that satisfies {c, Dagger(c)} == 1.
Parameters
==========
name : str
A string that labels the fermionic mode.
annihilation : bool
A bool that indicates if the fermionic operator is an annihilation
(True, default value) or creation operator (False)
Examples
========
>>> from sympy.physics.quantum import Dagger, AntiCommutator
>>> from sympy.physics.quantum.fermion import FermionOp
>>> c = FermionOp("c")
>>> AntiCommutator(c, Dagger(c)).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 ("c", 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_FermionOp(self, other, **hints):
if 'independent' in hints and hints['independent']:
# [c, d] = 0
return S.Zero
return None
def _eval_anticommutator_FermionOp(self, other, **hints):
if self.name == other.name:
# {a^\dagger, a} = 1
if not self.is_annihilation and other.is_annihilation:
return S.One
elif 'independent' in hints and hints['independent']:
# {c, d} = 2 * c * d, because [c, d] = 0 for independent operators
return 2 * self * other
return None
def _eval_anticommutator_BosonOp(self, other, **hints):
# because fermions and bosons commute
return 2 * self * other
def _eval_commutator_BosonOp(self, other, **hints):
return S.Zero
def _eval_adjoint(self):
return FermionOp(str(self.name), not self.is_annihilation)
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}')
def _eval_power(self, exp):
from sympy.core.singleton import S
if exp == 0:
return S.One
elif exp == 1:
return self
elif (exp > 1) == True and exp.is_integer == True:
return S.Zero
elif (exp < 0) == True or exp.is_integer == False:
raise ValueError("Fermionic operators can only be raised to a"
" positive integer power")
return Operator._eval_power(self, exp)
class FermionFockKet(Ket):
"""Fock state ket for a fermionic mode.
Parameters
==========
n : Number
The Fock state number.
"""
def __new__(cls, n):
if n not in (0, 1):
raise ValueError("n must be 0 or 1")
return Ket.__new__(cls, n)
@property
def n(self):
return self.label[0]
@classmethod
def dual_class(self):
return FermionFockBra
@classmethod
def _eval_hilbert_space(cls, label):
return HilbertSpace()
def _eval_innerproduct_FermionFockBra(self, bra, **hints):
return KroneckerDelta(self.n, bra.n)
def _apply_from_right_to_FermionOp(self, op, **options):
if op.is_annihilation:
if self.n == 1:
return FermionFockKet(0)
else:
return S.Zero
else:
if self.n == 0:
return FermionFockKet(1)
else:
return S.Zero
class FermionFockBra(Bra):
"""Fock state bra for a fermionic mode.
Parameters
==========
n : Number
The Fock state number.
"""
def __new__(cls, n):
if n not in (0, 1):
raise ValueError("n must be 0 or 1")
return Bra.__new__(cls, n)
@property
def n(self):
return self.label[0]
@classmethod
def dual_class(self):
return FermionFockKet
|