/
anticommutator.py
149 lines (116 loc) · 4.34 KB
/
anticommutator.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
"""The anti-commutator: ``{A,B} = A*B + B*A``."""
from sympy.core.expr import Expr
from sympy.core.mul import Mul
from sympy.core.numbers import Integer
from sympy.core.singleton import S
from sympy.printing.pretty.stringpict import prettyForm
from sympy.physics.quantum.operator import Operator
from sympy.physics.quantum.dagger import Dagger
__all__ = [
'AntiCommutator'
]
#-----------------------------------------------------------------------------
# Anti-commutator
#-----------------------------------------------------------------------------
class AntiCommutator(Expr):
"""The standard anticommutator, in an unevaluated state.
Explanation
===========
Evaluating an anticommutator is defined [1]_ as: ``{A, B} = A*B + B*A``.
This class returns the anticommutator in an unevaluated form. To evaluate
the anticommutator, use the ``.doit()`` method.
Canonical ordering of an anticommutator is ``{A, B}`` for ``A < B``. The
arguments of the anticommutator are put into canonical order using
``__cmp__``. If ``B < A``, then ``{A, B}`` is returned as ``{B, A}``.
Parameters
==========
A : Expr
The first argument of the anticommutator {A,B}.
B : Expr
The second argument of the anticommutator {A,B}.
Examples
========
>>> from sympy import symbols
>>> from sympy.physics.quantum import AntiCommutator
>>> from sympy.physics.quantum import Operator, Dagger
>>> x, y = symbols('x,y')
>>> A = Operator('A')
>>> B = Operator('B')
Create an anticommutator and use ``doit()`` to multiply them out.
>>> ac = AntiCommutator(A,B); ac
{A,B}
>>> ac.doit()
A*B + B*A
The commutator orders it arguments in canonical order:
>>> ac = AntiCommutator(B,A); ac
{A,B}
Commutative constants are factored out:
>>> AntiCommutator(3*x*A,x*y*B)
3*x**2*y*{A,B}
Adjoint operations applied to the anticommutator are properly applied to
the arguments:
>>> Dagger(AntiCommutator(A,B))
{Dagger(A),Dagger(B)}
References
==========
.. [1] https://en.wikipedia.org/wiki/Commutator
"""
is_commutative = False
def __new__(cls, A, B):
r = cls.eval(A, B)
if r is not None:
return r
obj = Expr.__new__(cls, A, B)
return obj
@classmethod
def eval(cls, a, b):
if not (a and b):
return S.Zero
if a == b:
return Integer(2)*a**2
if a.is_commutative or b.is_commutative:
return Integer(2)*a*b
# [xA,yB] -> xy*[A,B]
ca, nca = a.args_cnc()
cb, ncb = b.args_cnc()
c_part = ca + cb
if c_part:
return Mul(Mul(*c_part), cls(Mul._from_args(nca), Mul._from_args(ncb)))
# Canonical ordering of arguments
#The Commutator [A,B] is on canonical form if A < B.
if a.compare(b) == 1:
return cls(b, a)
def doit(self, **hints):
""" Evaluate anticommutator """
A = self.args[0]
B = self.args[1]
if isinstance(A, Operator) and isinstance(B, Operator):
try:
comm = A._eval_anticommutator(B, **hints)
except NotImplementedError:
try:
comm = B._eval_anticommutator(A, **hints)
except NotImplementedError:
comm = None
if comm is not None:
return comm.doit(**hints)
return (A*B + B*A).doit(**hints)
def _eval_adjoint(self):
return AntiCommutator(Dagger(self.args[0]), Dagger(self.args[1]))
def _sympyrepr(self, printer, *args):
return "%s(%s,%s)" % (
self.__class__.__name__, printer._print(
self.args[0]), printer._print(self.args[1])
)
def _sympystr(self, printer, *args):
return "{%s,%s}" % (
printer._print(self.args[0]), printer._print(self.args[1]))
def _pretty(self, printer, *args):
pform = printer._print(self.args[0], *args)
pform = prettyForm(*pform.right(prettyForm(',')))
pform = prettyForm(*pform.right(printer._print(self.args[1], *args)))
pform = prettyForm(*pform.parens(left='{', right='}'))
return pform
def _latex(self, printer, *args):
return "\\left\\{%s,%s\\right\\}" % tuple([
printer._print(arg, *args) for arg in self.args])