|
|
"""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}')
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_operator_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
|