Traktor/myenv/Lib/site-packages/sympy/physics/quantum/boson.py
2024-05-26 05:12:46 +02:00

260 lines
6.2 KiB
Python

"""Bosonic quantum operators."""
from sympy.core.mul import Mul
from sympy.core.numbers import Integer
from sympy.core.singleton import S
from sympy.functions.elementary.complexes import conjugate
from sympy.functions.elementary.exponential import exp
from sympy.functions.elementary.miscellaneous import sqrt
from sympy.physics.quantum import Operator
from sympy.physics.quantum import HilbertSpace, FockSpace, Ket, Bra, IdentityOperator
from sympy.functions.special.tensor_functions import KroneckerDelta
__all__ = [
'BosonOp',
'BosonFockKet',
'BosonFockBra',
'BosonCoherentKet',
'BosonCoherentBra'
]
class BosonOp(Operator):
"""A bosonic operator that satisfies [a, Dagger(a)] == 1.
Parameters
==========
name : str
A string that labels the bosonic mode.
annihilation : bool
A bool that indicates if the bosonic operator is an annihilation (True,
default value) or creation operator (False)
Examples
========
>>> from sympy.physics.quantum import Dagger, Commutator
>>> from sympy.physics.quantum.boson import BosonOp
>>> a = BosonOp("a")
>>> Commutator(a, Dagger(a)).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 ("a", 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_BosonOp(self, other, **hints):
if self.name == other.name:
# [a^\dagger, a] = -1
if not self.is_annihilation and other.is_annihilation:
return S.NegativeOne
elif 'independent' in hints and hints['independent']:
# [a, b] = 0
return S.Zero
return None
def _eval_commutator_FermionOp(self, other, **hints):
return S.Zero
def _eval_anticommutator_BosonOp(self, other, **hints):
if 'independent' in hints and hints['independent']:
# {a, b} = 2 * a * b, because [a, b] = 0
return 2 * self * other
return None
def _eval_adjoint(self):
return BosonOp(str(self.name), not self.is_annihilation)
def __mul__(self, other):
if other == IdentityOperator(2):
return self
if isinstance(other, Mul):
args1 = tuple(arg for arg in other.args if arg.is_commutative)
args2 = tuple(arg for arg in other.args if not arg.is_commutative)
x = self
for y in args2:
x = x * y
return Mul(*args1) * x
return Mul(self, other)
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 BosonFockKet(Ket):
"""Fock state ket for a bosonic mode.
Parameters
==========
n : Number
The Fock state number.
"""
def __new__(cls, n):
return Ket.__new__(cls, n)
@property
def n(self):
return self.label[0]
@classmethod
def dual_class(self):
return BosonFockBra
@classmethod
def _eval_hilbert_space(cls, label):
return FockSpace()
def _eval_innerproduct_BosonFockBra(self, bra, **hints):
return KroneckerDelta(self.n, bra.n)
def _apply_from_right_to_BosonOp(self, op, **options):
if op.is_annihilation:
return sqrt(self.n) * BosonFockKet(self.n - 1)
else:
return sqrt(self.n + 1) * BosonFockKet(self.n + 1)
class BosonFockBra(Bra):
"""Fock state bra for a bosonic mode.
Parameters
==========
n : Number
The Fock state number.
"""
def __new__(cls, n):
return Bra.__new__(cls, n)
@property
def n(self):
return self.label[0]
@classmethod
def dual_class(self):
return BosonFockKet
@classmethod
def _eval_hilbert_space(cls, label):
return FockSpace()
class BosonCoherentKet(Ket):
"""Coherent state ket for a bosonic mode.
Parameters
==========
alpha : Number, Symbol
The complex amplitude of the coherent state.
"""
def __new__(cls, alpha):
return Ket.__new__(cls, alpha)
@property
def alpha(self):
return self.label[0]
@classmethod
def dual_class(self):
return BosonCoherentBra
@classmethod
def _eval_hilbert_space(cls, label):
return HilbertSpace()
def _eval_innerproduct_BosonCoherentBra(self, bra, **hints):
if self.alpha == bra.alpha:
return S.One
else:
return exp(-(abs(self.alpha)**2 + abs(bra.alpha)**2 - 2 * conjugate(bra.alpha) * self.alpha)/2)
def _apply_from_right_to_BosonOp(self, op, **options):
if op.is_annihilation:
return self.alpha * self
else:
return None
class BosonCoherentBra(Bra):
"""Coherent state bra for a bosonic mode.
Parameters
==========
alpha : Number, Symbol
The complex amplitude of the coherent state.
"""
def __new__(cls, alpha):
return Bra.__new__(cls, alpha)
@property
def alpha(self):
return self.label[0]
@classmethod
def dual_class(self):
return BosonCoherentKet
def _apply_operator_BosonOp(self, op, **options):
if not op.is_annihilation:
return self.alpha * self
else:
return None