|
""" |
|
This module implements Pauli algebra by subclassing Symbol. Only algebraic |
|
properties of Pauli matrices are used (we do not use the Matrix class). |
|
|
|
See the documentation to the class Pauli for examples. |
|
|
|
References |
|
========== |
|
|
|
.. [1] https://en.wikipedia.org/wiki/Pauli_matrices |
|
""" |
|
|
|
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.symbol import Symbol |
|
from sympy.physics.quantum import TensorProduct |
|
|
|
__all__ = ['evaluate_pauli_product'] |
|
|
|
|
|
def delta(i, j): |
|
""" |
|
Returns 1 if ``i == j``, else 0. |
|
|
|
This is used in the multiplication of Pauli matrices. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.physics.paulialgebra import delta |
|
>>> delta(1, 1) |
|
1 |
|
>>> delta(2, 3) |
|
0 |
|
""" |
|
if i == j: |
|
return 1 |
|
else: |
|
return 0 |
|
|
|
|
|
def epsilon(i, j, k): |
|
""" |
|
Return 1 if i,j,k is equal to (1,2,3), (2,3,1), or (3,1,2); |
|
-1 if ``i``,``j``,``k`` is equal to (1,3,2), (3,2,1), or (2,1,3); |
|
else return 0. |
|
|
|
This is used in the multiplication of Pauli matrices. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.physics.paulialgebra import epsilon |
|
>>> epsilon(1, 2, 3) |
|
1 |
|
>>> epsilon(1, 3, 2) |
|
-1 |
|
""" |
|
if (i, j, k) in ((1, 2, 3), (2, 3, 1), (3, 1, 2)): |
|
return 1 |
|
elif (i, j, k) in ((1, 3, 2), (3, 2, 1), (2, 1, 3)): |
|
return -1 |
|
else: |
|
return 0 |
|
|
|
|
|
class Pauli(Symbol): |
|
""" |
|
The class representing algebraic properties of Pauli matrices. |
|
|
|
Explanation |
|
=========== |
|
|
|
The symbol used to display the Pauli matrices can be changed with an |
|
optional parameter ``label="sigma"``. Pauli matrices with different |
|
``label`` attributes cannot multiply together. |
|
|
|
If the left multiplication of symbol or number with Pauli matrix is needed, |
|
please use parentheses to separate Pauli and symbolic multiplication |
|
(for example: 2*I*(Pauli(3)*Pauli(2))). |
|
|
|
Another variant is to use evaluate_pauli_product function to evaluate |
|
the product of Pauli matrices and other symbols (with commutative |
|
multiply rules). |
|
|
|
See Also |
|
======== |
|
|
|
evaluate_pauli_product |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.physics.paulialgebra import Pauli |
|
>>> Pauli(1) |
|
sigma1 |
|
>>> Pauli(1)*Pauli(2) |
|
I*sigma3 |
|
>>> Pauli(1)*Pauli(1) |
|
1 |
|
>>> Pauli(3)**4 |
|
1 |
|
>>> Pauli(1)*Pauli(2)*Pauli(3) |
|
I |
|
|
|
>>> from sympy.physics.paulialgebra import Pauli |
|
>>> Pauli(1, label="tau") |
|
tau1 |
|
>>> Pauli(1)*Pauli(2, label="tau") |
|
sigma1*tau2 |
|
>>> Pauli(1, label="tau")*Pauli(2, label="tau") |
|
I*tau3 |
|
|
|
>>> from sympy import I |
|
>>> I*(Pauli(2)*Pauli(3)) |
|
-sigma1 |
|
|
|
>>> from sympy.physics.paulialgebra import evaluate_pauli_product |
|
>>> f = I*Pauli(2)*Pauli(3) |
|
>>> f |
|
I*sigma2*sigma3 |
|
>>> evaluate_pauli_product(f) |
|
-sigma1 |
|
""" |
|
|
|
__slots__ = ("i", "label") |
|
|
|
def __new__(cls, i, label="sigma"): |
|
if i not in [1, 2, 3]: |
|
raise IndexError("Invalid Pauli index") |
|
obj = Symbol.__new__(cls, "%s%d" %(label,i), commutative=False, hermitian=True) |
|
obj.i = i |
|
obj.label = label |
|
return obj |
|
|
|
def __getnewargs_ex__(self): |
|
return (self.i, self.label), {} |
|
|
|
def _hashable_content(self): |
|
return (self.i, self.label) |
|
|
|
|
|
def __mul__(self, other): |
|
if isinstance(other, Pauli): |
|
j = self.i |
|
k = other.i |
|
jlab = self.label |
|
klab = other.label |
|
|
|
if jlab == klab: |
|
return delta(j, k) \ |
|
+ I*epsilon(j, k, 1)*Pauli(1,jlab) \ |
|
+ I*epsilon(j, k, 2)*Pauli(2,jlab) \ |
|
+ I*epsilon(j, k, 3)*Pauli(3,jlab) |
|
return super().__mul__(other) |
|
|
|
def _eval_power(b, e): |
|
if e.is_Integer and e.is_positive: |
|
return super().__pow__(int(e) % 2) |
|
|
|
|
|
def evaluate_pauli_product(arg): |
|
'''Help function to evaluate Pauli matrices product |
|
with symbolic objects. |
|
|
|
Parameters |
|
========== |
|
|
|
arg: symbolic expression that contains Paulimatrices |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.physics.paulialgebra import Pauli, evaluate_pauli_product |
|
>>> from sympy import I |
|
>>> evaluate_pauli_product(I*Pauli(1)*Pauli(2)) |
|
-sigma3 |
|
|
|
>>> from sympy.abc import x |
|
>>> evaluate_pauli_product(x**2*Pauli(2)*Pauli(1)) |
|
-I*x**2*sigma3 |
|
''' |
|
start = arg |
|
end = arg |
|
|
|
if isinstance(arg, Pow) and isinstance(arg.args[0], Pauli): |
|
if arg.args[1].is_odd: |
|
return arg.args[0] |
|
else: |
|
return 1 |
|
|
|
if isinstance(arg, Add): |
|
return Add(*[evaluate_pauli_product(part) for part in arg.args]) |
|
|
|
if isinstance(arg, TensorProduct): |
|
return TensorProduct(*[evaluate_pauli_product(part) for part in arg.args]) |
|
|
|
elif not(isinstance(arg, Mul)): |
|
return arg |
|
|
|
while not start == end or start == arg and end == arg: |
|
start = end |
|
|
|
tmp = start.as_coeff_mul() |
|
sigma_product = 1 |
|
com_product = 1 |
|
keeper = 1 |
|
|
|
for el in tmp[1]: |
|
if isinstance(el, Pauli): |
|
sigma_product *= el |
|
elif not el.is_commutative: |
|
if isinstance(el, Pow) and isinstance(el.args[0], Pauli): |
|
if el.args[1].is_odd: |
|
sigma_product *= el.args[0] |
|
elif isinstance(el, TensorProduct): |
|
keeper = keeper*sigma_product*\ |
|
TensorProduct( |
|
*[evaluate_pauli_product(part) for part in el.args] |
|
) |
|
sigma_product = 1 |
|
else: |
|
keeper = keeper*sigma_product*el |
|
sigma_product = 1 |
|
else: |
|
com_product *= el |
|
end = tmp[0]*keeper*sigma_product*com_product |
|
if end == arg: break |
|
return end |
|
|