|
"""The anti-commutator: ``{A,B} = A*B + B*A``.""" |
|
|
|
from sympy.core.expr import Expr |
|
from sympy.core.kind import KindDispatcher |
|
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.dagger import Dagger |
|
from sympy.physics.quantum.kind import _OperatorKind, OperatorKind |
|
|
|
__all__ = [ |
|
'AntiCommutator' |
|
] |
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
|
|
|
_kind_dispatcher = KindDispatcher("AntiCommutator_kind_dispatcher", commutative=True) |
|
|
|
@property |
|
def kind(self): |
|
arg_kinds = (a.kind for a in self.args) |
|
return self._kind_dispatcher(*arg_kinds) |
|
|
|
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 |
|
|
|
|
|
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))) |
|
|
|
|
|
|
|
if a.compare(b) == 1: |
|
return cls(b, a) |
|
|
|
def doit(self, **hints): |
|
""" Evaluate anticommutator """ |
|
|
|
|
|
from sympy.physics.quantum.operator import Operator |
|
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]) |
|
|
|
|
|
@AntiCommutator._kind_dispatcher.register(_OperatorKind, _OperatorKind) |
|
def find_op_kind(e1, e2): |
|
"""Find the kind of an anticommutator of two OperatorKinds.""" |
|
return OperatorKind |
|
|