123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179 |
- """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
|