Spaces:
Sleeping
Sleeping
"""Pauli operators and states""" | |
from sympy.core.add import Add | |
from sympy.core.mul import Mul | |
from sympy.core.numbers import I | |
from sympy.core.power import Pow | |
from sympy.core.singleton import S | |
from sympy.functions.elementary.exponential import exp | |
from sympy.physics.quantum import Operator, Ket, Bra | |
from sympy.physics.quantum import ComplexSpace | |
from sympy.matrices import Matrix | |
from sympy.functions.special.tensor_functions import KroneckerDelta | |
__all__ = [ | |
'SigmaX', 'SigmaY', 'SigmaZ', 'SigmaMinus', 'SigmaPlus', 'SigmaZKet', | |
'SigmaZBra', 'qsimplify_pauli' | |
] | |
class SigmaOpBase(Operator): | |
"""Pauli sigma operator, base class""" | |
def name(self): | |
return self.args[0] | |
def use_name(self): | |
return bool(self.args[0]) is not False | |
def default_args(self): | |
return (False,) | |
def __new__(cls, *args, **hints): | |
return Operator.__new__(cls, *args, **hints) | |
def _eval_commutator_BosonOp(self, other, **hints): | |
return S.Zero | |
class SigmaX(SigmaOpBase): | |
"""Pauli sigma x operator | |
Parameters | |
========== | |
name : str | |
An optional string that labels the operator. Pauli operators with | |
different names commute. | |
Examples | |
======== | |
>>> from sympy.physics.quantum import represent | |
>>> from sympy.physics.quantum.pauli import SigmaX | |
>>> sx = SigmaX() | |
>>> sx | |
SigmaX() | |
>>> represent(sx) | |
Matrix([ | |
[0, 1], | |
[1, 0]]) | |
""" | |
def __new__(cls, *args, **hints): | |
return SigmaOpBase.__new__(cls, *args, **hints) | |
def _eval_commutator_SigmaY(self, other, **hints): | |
if self.name != other.name: | |
return S.Zero | |
else: | |
return 2 * I * SigmaZ(self.name) | |
def _eval_commutator_SigmaZ(self, other, **hints): | |
if self.name != other.name: | |
return S.Zero | |
else: | |
return - 2 * I * SigmaY(self.name) | |
def _eval_commutator_BosonOp(self, other, **hints): | |
return S.Zero | |
def _eval_anticommutator_SigmaY(self, other, **hints): | |
return S.Zero | |
def _eval_anticommutator_SigmaZ(self, other, **hints): | |
return S.Zero | |
def _eval_adjoint(self): | |
return self | |
def _print_contents_latex(self, printer, *args): | |
if self.use_name: | |
return r'{\sigma_x^{(%s)}}' % str(self.name) | |
else: | |
return r'{\sigma_x}' | |
def _print_contents(self, printer, *args): | |
return 'SigmaX()' | |
def _eval_power(self, e): | |
if e.is_Integer and e.is_positive: | |
return SigmaX(self.name).__pow__(int(e) % 2) | |
def _represent_default_basis(self, **options): | |
format = options.get('format', 'sympy') | |
if format == 'sympy': | |
return Matrix([[0, 1], [1, 0]]) | |
else: | |
raise NotImplementedError('Representation in format ' + | |
format + ' not implemented.') | |
class SigmaY(SigmaOpBase): | |
"""Pauli sigma y operator | |
Parameters | |
========== | |
name : str | |
An optional string that labels the operator. Pauli operators with | |
different names commute. | |
Examples | |
======== | |
>>> from sympy.physics.quantum import represent | |
>>> from sympy.physics.quantum.pauli import SigmaY | |
>>> sy = SigmaY() | |
>>> sy | |
SigmaY() | |
>>> represent(sy) | |
Matrix([ | |
[0, -I], | |
[I, 0]]) | |
""" | |
def __new__(cls, *args, **hints): | |
return SigmaOpBase.__new__(cls, *args) | |
def _eval_commutator_SigmaZ(self, other, **hints): | |
if self.name != other.name: | |
return S.Zero | |
else: | |
return 2 * I * SigmaX(self.name) | |
def _eval_commutator_SigmaX(self, other, **hints): | |
if self.name != other.name: | |
return S.Zero | |
else: | |
return - 2 * I * SigmaZ(self.name) | |
def _eval_anticommutator_SigmaX(self, other, **hints): | |
return S.Zero | |
def _eval_anticommutator_SigmaZ(self, other, **hints): | |
return S.Zero | |
def _eval_adjoint(self): | |
return self | |
def _print_contents_latex(self, printer, *args): | |
if self.use_name: | |
return r'{\sigma_y^{(%s)}}' % str(self.name) | |
else: | |
return r'{\sigma_y}' | |
def _print_contents(self, printer, *args): | |
return 'SigmaY()' | |
def _eval_power(self, e): | |
if e.is_Integer and e.is_positive: | |
return SigmaY(self.name).__pow__(int(e) % 2) | |
def _represent_default_basis(self, **options): | |
format = options.get('format', 'sympy') | |
if format == 'sympy': | |
return Matrix([[0, -I], [I, 0]]) | |
else: | |
raise NotImplementedError('Representation in format ' + | |
format + ' not implemented.') | |
class SigmaZ(SigmaOpBase): | |
"""Pauli sigma z operator | |
Parameters | |
========== | |
name : str | |
An optional string that labels the operator. Pauli operators with | |
different names commute. | |
Examples | |
======== | |
>>> from sympy.physics.quantum import represent | |
>>> from sympy.physics.quantum.pauli import SigmaZ | |
>>> sz = SigmaZ() | |
>>> sz ** 3 | |
SigmaZ() | |
>>> represent(sz) | |
Matrix([ | |
[1, 0], | |
[0, -1]]) | |
""" | |
def __new__(cls, *args, **hints): | |
return SigmaOpBase.__new__(cls, *args) | |
def _eval_commutator_SigmaX(self, other, **hints): | |
if self.name != other.name: | |
return S.Zero | |
else: | |
return 2 * I * SigmaY(self.name) | |
def _eval_commutator_SigmaY(self, other, **hints): | |
if self.name != other.name: | |
return S.Zero | |
else: | |
return - 2 * I * SigmaX(self.name) | |
def _eval_anticommutator_SigmaX(self, other, **hints): | |
return S.Zero | |
def _eval_anticommutator_SigmaY(self, other, **hints): | |
return S.Zero | |
def _eval_adjoint(self): | |
return self | |
def _print_contents_latex(self, printer, *args): | |
if self.use_name: | |
return r'{\sigma_z^{(%s)}}' % str(self.name) | |
else: | |
return r'{\sigma_z}' | |
def _print_contents(self, printer, *args): | |
return 'SigmaZ()' | |
def _eval_power(self, e): | |
if e.is_Integer and e.is_positive: | |
return SigmaZ(self.name).__pow__(int(e) % 2) | |
def _represent_default_basis(self, **options): | |
format = options.get('format', 'sympy') | |
if format == 'sympy': | |
return Matrix([[1, 0], [0, -1]]) | |
else: | |
raise NotImplementedError('Representation in format ' + | |
format + ' not implemented.') | |
class SigmaMinus(SigmaOpBase): | |
"""Pauli sigma minus operator | |
Parameters | |
========== | |
name : str | |
An optional string that labels the operator. Pauli operators with | |
different names commute. | |
Examples | |
======== | |
>>> from sympy.physics.quantum import represent, Dagger | |
>>> from sympy.physics.quantum.pauli import SigmaMinus | |
>>> sm = SigmaMinus() | |
>>> sm | |
SigmaMinus() | |
>>> Dagger(sm) | |
SigmaPlus() | |
>>> represent(sm) | |
Matrix([ | |
[0, 0], | |
[1, 0]]) | |
""" | |
def __new__(cls, *args, **hints): | |
return SigmaOpBase.__new__(cls, *args) | |
def _eval_commutator_SigmaX(self, other, **hints): | |
if self.name != other.name: | |
return S.Zero | |
else: | |
return -SigmaZ(self.name) | |
def _eval_commutator_SigmaY(self, other, **hints): | |
if self.name != other.name: | |
return S.Zero | |
else: | |
return I * SigmaZ(self.name) | |
def _eval_commutator_SigmaZ(self, other, **hints): | |
return 2 * self | |
def _eval_commutator_SigmaMinus(self, other, **hints): | |
return SigmaZ(self.name) | |
def _eval_anticommutator_SigmaZ(self, other, **hints): | |
return S.Zero | |
def _eval_anticommutator_SigmaX(self, other, **hints): | |
return S.One | |
def _eval_anticommutator_SigmaY(self, other, **hints): | |
return I * S.NegativeOne | |
def _eval_anticommutator_SigmaPlus(self, other, **hints): | |
return S.One | |
def _eval_adjoint(self): | |
return SigmaPlus(self.name) | |
def _eval_power(self, e): | |
if e.is_Integer and e.is_positive: | |
return S.Zero | |
def _print_contents_latex(self, printer, *args): | |
if self.use_name: | |
return r'{\sigma_-^{(%s)}}' % str(self.name) | |
else: | |
return r'{\sigma_-}' | |
def _print_contents(self, printer, *args): | |
return 'SigmaMinus()' | |
def _represent_default_basis(self, **options): | |
format = options.get('format', 'sympy') | |
if format == 'sympy': | |
return Matrix([[0, 0], [1, 0]]) | |
else: | |
raise NotImplementedError('Representation in format ' + | |
format + ' not implemented.') | |
class SigmaPlus(SigmaOpBase): | |
"""Pauli sigma plus operator | |
Parameters | |
========== | |
name : str | |
An optional string that labels the operator. Pauli operators with | |
different names commute. | |
Examples | |
======== | |
>>> from sympy.physics.quantum import represent, Dagger | |
>>> from sympy.physics.quantum.pauli import SigmaPlus | |
>>> sp = SigmaPlus() | |
>>> sp | |
SigmaPlus() | |
>>> Dagger(sp) | |
SigmaMinus() | |
>>> represent(sp) | |
Matrix([ | |
[0, 1], | |
[0, 0]]) | |
""" | |
def __new__(cls, *args, **hints): | |
return SigmaOpBase.__new__(cls, *args) | |
def _eval_commutator_SigmaX(self, other, **hints): | |
if self.name != other.name: | |
return S.Zero | |
else: | |
return SigmaZ(self.name) | |
def _eval_commutator_SigmaY(self, other, **hints): | |
if self.name != other.name: | |
return S.Zero | |
else: | |
return I * SigmaZ(self.name) | |
def _eval_commutator_SigmaZ(self, other, **hints): | |
if self.name != other.name: | |
return S.Zero | |
else: | |
return -2 * self | |
def _eval_commutator_SigmaMinus(self, other, **hints): | |
return SigmaZ(self.name) | |
def _eval_anticommutator_SigmaZ(self, other, **hints): | |
return S.Zero | |
def _eval_anticommutator_SigmaX(self, other, **hints): | |
return S.One | |
def _eval_anticommutator_SigmaY(self, other, **hints): | |
return I | |
def _eval_anticommutator_SigmaMinus(self, other, **hints): | |
return S.One | |
def _eval_adjoint(self): | |
return SigmaMinus(self.name) | |
def _eval_mul(self, other): | |
return self * other | |
def _eval_power(self, e): | |
if e.is_Integer and e.is_positive: | |
return S.Zero | |
def _print_contents_latex(self, printer, *args): | |
if self.use_name: | |
return r'{\sigma_+^{(%s)}}' % str(self.name) | |
else: | |
return r'{\sigma_+}' | |
def _print_contents(self, printer, *args): | |
return 'SigmaPlus()' | |
def _represent_default_basis(self, **options): | |
format = options.get('format', 'sympy') | |
if format == 'sympy': | |
return Matrix([[0, 1], [0, 0]]) | |
else: | |
raise NotImplementedError('Representation in format ' + | |
format + ' not implemented.') | |
class SigmaZKet(Ket): | |
"""Ket for a two-level system quantum system. | |
Parameters | |
========== | |
n : Number | |
The state number (0 or 1). | |
""" | |
def __new__(cls, n): | |
if n not in (0, 1): | |
raise ValueError("n must be 0 or 1") | |
return Ket.__new__(cls, n) | |
def n(self): | |
return self.label[0] | |
def dual_class(self): | |
return SigmaZBra | |
def _eval_hilbert_space(cls, label): | |
return ComplexSpace(2) | |
def _eval_innerproduct_SigmaZBra(self, bra, **hints): | |
return KroneckerDelta(self.n, bra.n) | |
def _apply_from_right_to_SigmaZ(self, op, **options): | |
if self.n == 0: | |
return self | |
else: | |
return S.NegativeOne * self | |
def _apply_from_right_to_SigmaX(self, op, **options): | |
return SigmaZKet(1) if self.n == 0 else SigmaZKet(0) | |
def _apply_from_right_to_SigmaY(self, op, **options): | |
return I * SigmaZKet(1) if self.n == 0 else (-I) * SigmaZKet(0) | |
def _apply_from_right_to_SigmaMinus(self, op, **options): | |
if self.n == 0: | |
return SigmaZKet(1) | |
else: | |
return S.Zero | |
def _apply_from_right_to_SigmaPlus(self, op, **options): | |
if self.n == 0: | |
return S.Zero | |
else: | |
return SigmaZKet(0) | |
def _represent_default_basis(self, **options): | |
format = options.get('format', 'sympy') | |
if format == 'sympy': | |
return Matrix([[1], [0]]) if self.n == 0 else Matrix([[0], [1]]) | |
else: | |
raise NotImplementedError('Representation in format ' + | |
format + ' not implemented.') | |
class SigmaZBra(Bra): | |
"""Bra for a two-level quantum system. | |
Parameters | |
========== | |
n : Number | |
The state number (0 or 1). | |
""" | |
def __new__(cls, n): | |
if n not in (0, 1): | |
raise ValueError("n must be 0 or 1") | |
return Bra.__new__(cls, n) | |
def n(self): | |
return self.label[0] | |
def dual_class(self): | |
return SigmaZKet | |
def _qsimplify_pauli_product(a, b): | |
""" | |
Internal helper function for simplifying products of Pauli operators. | |
""" | |
if not (isinstance(a, SigmaOpBase) and isinstance(b, SigmaOpBase)): | |
return Mul(a, b) | |
if a.name != b.name: | |
# Pauli matrices with different labels commute; sort by name | |
if a.name < b.name: | |
return Mul(a, b) | |
else: | |
return Mul(b, a) | |
elif isinstance(a, SigmaX): | |
if isinstance(b, SigmaX): | |
return S.One | |
if isinstance(b, SigmaY): | |
return I * SigmaZ(a.name) | |
if isinstance(b, SigmaZ): | |
return - I * SigmaY(a.name) | |
if isinstance(b, SigmaMinus): | |
return (S.Half + SigmaZ(a.name)/2) | |
if isinstance(b, SigmaPlus): | |
return (S.Half - SigmaZ(a.name)/2) | |
elif isinstance(a, SigmaY): | |
if isinstance(b, SigmaX): | |
return - I * SigmaZ(a.name) | |
if isinstance(b, SigmaY): | |
return S.One | |
if isinstance(b, SigmaZ): | |
return I * SigmaX(a.name) | |
if isinstance(b, SigmaMinus): | |
return -I * (S.One + SigmaZ(a.name))/2 | |
if isinstance(b, SigmaPlus): | |
return I * (S.One - SigmaZ(a.name))/2 | |
elif isinstance(a, SigmaZ): | |
if isinstance(b, SigmaX): | |
return I * SigmaY(a.name) | |
if isinstance(b, SigmaY): | |
return - I * SigmaX(a.name) | |
if isinstance(b, SigmaZ): | |
return S.One | |
if isinstance(b, SigmaMinus): | |
return - SigmaMinus(a.name) | |
if isinstance(b, SigmaPlus): | |
return SigmaPlus(a.name) | |
elif isinstance(a, SigmaMinus): | |
if isinstance(b, SigmaX): | |
return (S.One - SigmaZ(a.name))/2 | |
if isinstance(b, SigmaY): | |
return - I * (S.One - SigmaZ(a.name))/2 | |
if isinstance(b, SigmaZ): | |
# (SigmaX(a.name) - I * SigmaY(a.name))/2 | |
return SigmaMinus(b.name) | |
if isinstance(b, SigmaMinus): | |
return S.Zero | |
if isinstance(b, SigmaPlus): | |
return S.Half - SigmaZ(a.name)/2 | |
elif isinstance(a, SigmaPlus): | |
if isinstance(b, SigmaX): | |
return (S.One + SigmaZ(a.name))/2 | |
if isinstance(b, SigmaY): | |
return I * (S.One + SigmaZ(a.name))/2 | |
if isinstance(b, SigmaZ): | |
#-(SigmaX(a.name) + I * SigmaY(a.name))/2 | |
return -SigmaPlus(a.name) | |
if isinstance(b, SigmaMinus): | |
return (S.One + SigmaZ(a.name))/2 | |
if isinstance(b, SigmaPlus): | |
return S.Zero | |
else: | |
return a * b | |
def qsimplify_pauli(e): | |
""" | |
Simplify an expression that includes products of pauli operators. | |
Parameters | |
========== | |
e : expression | |
An expression that contains products of Pauli operators that is | |
to be simplified. | |
Examples | |
======== | |
>>> from sympy.physics.quantum.pauli import SigmaX, SigmaY | |
>>> from sympy.physics.quantum.pauli import qsimplify_pauli | |
>>> sx, sy = SigmaX(), SigmaY() | |
>>> sx * sy | |
SigmaX()*SigmaY() | |
>>> qsimplify_pauli(sx * sy) | |
I*SigmaZ() | |
""" | |
if isinstance(e, Operator): | |
return e | |
if isinstance(e, (Add, Pow, exp)): | |
t = type(e) | |
return t(*(qsimplify_pauli(arg) for arg in e.args)) | |
if isinstance(e, Mul): | |
c, nc = e.args_cnc() | |
nc_s = [] | |
while nc: | |
curr = nc.pop(0) | |
while (len(nc) and | |
isinstance(curr, SigmaOpBase) and | |
isinstance(nc[0], SigmaOpBase) and | |
curr.name == nc[0].name): | |
x = nc.pop(0) | |
y = _qsimplify_pauli_product(curr, x) | |
c1, nc1 = y.args_cnc() | |
curr = Mul(*nc1) | |
c = c + c1 | |
nc_s.append(curr) | |
return Mul(*c) * Mul(*nc_s) | |
return e | |