123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675 |
- """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"""
- @property
- def name(self):
- return self.args[0]
- @property
- def use_name(self):
- return bool(self.args[0]) is not False
- @classmethod
- 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)
- @property
- def n(self):
- return self.label[0]
- @classmethod
- def dual_class(self):
- return SigmaZBra
- @classmethod
- def _eval_hilbert_space(cls, label):
- return ComplexSpace(2)
- def _eval_innerproduct_SigmaZBra(self, bra, **hints):
- return KroneckerDelta(self.n, bra.n)
- def _apply_operator_SigmaZ(self, op, **options):
- if self.n == 0:
- return self
- else:
- return S.NegativeOne * self
- def _apply_operator_SigmaX(self, op, **options):
- return SigmaZKet(1) if self.n == 0 else SigmaZKet(0)
- def _apply_operator_SigmaY(self, op, **options):
- return I * SigmaZKet(1) if self.n == 0 else (-I) * SigmaZKet(0)
- def _apply_operator_SigmaMinus(self, op, **options):
- if self.n == 0:
- return SigmaZKet(1)
- else:
- return S.Zero
- def _apply_operator_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)
- @property
- def n(self):
- return self.label[0]
- @classmethod
- 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
|