commutator.py 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. """The commutator: [A,B] = A*B - B*A."""
  2. from sympy.core.add import Add
  3. from sympy.core.expr import Expr
  4. from sympy.core.kind import KindDispatcher
  5. from sympy.core.mul import Mul
  6. from sympy.core.power import Pow
  7. from sympy.core.singleton import S
  8. from sympy.printing.pretty.stringpict import prettyForm
  9. from sympy.physics.quantum.dagger import Dagger
  10. from sympy.physics.quantum.kind import _OperatorKind, OperatorKind
  11. __all__ = [
  12. 'Commutator'
  13. ]
  14. #-----------------------------------------------------------------------------
  15. # Commutator
  16. #-----------------------------------------------------------------------------
  17. class Commutator(Expr):
  18. """The standard commutator, in an unevaluated state.
  19. Explanation
  20. ===========
  21. Evaluating a commutator is defined [1]_ as: ``[A, B] = A*B - B*A``. This
  22. class returns the commutator in an unevaluated form. To evaluate the
  23. commutator, use the ``.doit()`` method.
  24. Canonical ordering of a commutator is ``[A, B]`` for ``A < B``. The
  25. arguments of the commutator are put into canonical order using ``__cmp__``.
  26. If ``B < A``, then ``[B, A]`` is returned as ``-[A, B]``.
  27. Parameters
  28. ==========
  29. A : Expr
  30. The first argument of the commutator [A,B].
  31. B : Expr
  32. The second argument of the commutator [A,B].
  33. Examples
  34. ========
  35. >>> from sympy.physics.quantum import Commutator, Dagger, Operator
  36. >>> from sympy.abc import x, y
  37. >>> A = Operator('A')
  38. >>> B = Operator('B')
  39. >>> C = Operator('C')
  40. Create a commutator and use ``.doit()`` to evaluate it:
  41. >>> comm = Commutator(A, B)
  42. >>> comm
  43. [A,B]
  44. >>> comm.doit()
  45. A*B - B*A
  46. The commutator orders it arguments in canonical order:
  47. >>> comm = Commutator(B, A); comm
  48. -[A,B]
  49. Commutative constants are factored out:
  50. >>> Commutator(3*x*A, x*y*B)
  51. 3*x**2*y*[A,B]
  52. Using ``.expand(commutator=True)``, the standard commutator expansion rules
  53. can be applied:
  54. >>> Commutator(A+B, C).expand(commutator=True)
  55. [A,C] + [B,C]
  56. >>> Commutator(A, B+C).expand(commutator=True)
  57. [A,B] + [A,C]
  58. >>> Commutator(A*B, C).expand(commutator=True)
  59. [A,C]*B + A*[B,C]
  60. >>> Commutator(A, B*C).expand(commutator=True)
  61. [A,B]*C + B*[A,C]
  62. Adjoint operations applied to the commutator are properly applied to the
  63. arguments:
  64. >>> Dagger(Commutator(A, B))
  65. -[Dagger(A),Dagger(B)]
  66. References
  67. ==========
  68. .. [1] https://en.wikipedia.org/wiki/Commutator
  69. """
  70. is_commutative = False
  71. _kind_dispatcher = KindDispatcher("Commutator_kind_dispatcher", commutative=True)
  72. @property
  73. def kind(self):
  74. arg_kinds = (a.kind for a in self.args)
  75. return self._kind_dispatcher(*arg_kinds)
  76. def __new__(cls, A, B):
  77. r = cls.eval(A, B)
  78. if r is not None:
  79. return r
  80. obj = Expr.__new__(cls, A, B)
  81. return obj
  82. @classmethod
  83. def eval(cls, a, b):
  84. if not (a and b):
  85. return S.Zero
  86. if a == b:
  87. return S.Zero
  88. if a.is_commutative or b.is_commutative:
  89. return S.Zero
  90. # [xA,yB] -> xy*[A,B]
  91. ca, nca = a.args_cnc()
  92. cb, ncb = b.args_cnc()
  93. c_part = ca + cb
  94. if c_part:
  95. return Mul(Mul(*c_part), cls(Mul._from_args(nca), Mul._from_args(ncb)))
  96. # Canonical ordering of arguments
  97. # The Commutator [A, B] is in canonical form if A < B.
  98. if a.compare(b) == 1:
  99. return S.NegativeOne*cls(b, a)
  100. def _expand_pow(self, A, B, sign):
  101. exp = A.exp
  102. if not exp.is_integer or not exp.is_constant() or abs(exp) <= 1:
  103. # nothing to do
  104. return self
  105. base = A.base
  106. if exp.is_negative:
  107. base = A.base**-1
  108. exp = -exp
  109. comm = Commutator(base, B).expand(commutator=True)
  110. result = base**(exp - 1) * comm
  111. for i in range(1, exp):
  112. result += base**(exp - 1 - i) * comm * base**i
  113. return sign*result.expand()
  114. def _eval_expand_commutator(self, **hints):
  115. A = self.args[0]
  116. B = self.args[1]
  117. if isinstance(A, Add):
  118. # [A + B, C] -> [A, C] + [B, C]
  119. sargs = []
  120. for term in A.args:
  121. comm = Commutator(term, B)
  122. if isinstance(comm, Commutator):
  123. comm = comm._eval_expand_commutator()
  124. sargs.append(comm)
  125. return Add(*sargs)
  126. elif isinstance(B, Add):
  127. # [A, B + C] -> [A, B] + [A, C]
  128. sargs = []
  129. for term in B.args:
  130. comm = Commutator(A, term)
  131. if isinstance(comm, Commutator):
  132. comm = comm._eval_expand_commutator()
  133. sargs.append(comm)
  134. return Add(*sargs)
  135. elif isinstance(A, Mul):
  136. # [A*B, C] -> A*[B, C] + [A, C]*B
  137. a = A.args[0]
  138. b = Mul(*A.args[1:])
  139. c = B
  140. comm1 = Commutator(b, c)
  141. comm2 = Commutator(a, c)
  142. if isinstance(comm1, Commutator):
  143. comm1 = comm1._eval_expand_commutator()
  144. if isinstance(comm2, Commutator):
  145. comm2 = comm2._eval_expand_commutator()
  146. first = Mul(a, comm1)
  147. second = Mul(comm2, b)
  148. return Add(first, second)
  149. elif isinstance(B, Mul):
  150. # [A, B*C] -> [A, B]*C + B*[A, C]
  151. a = A
  152. b = B.args[0]
  153. c = Mul(*B.args[1:])
  154. comm1 = Commutator(a, b)
  155. comm2 = Commutator(a, c)
  156. if isinstance(comm1, Commutator):
  157. comm1 = comm1._eval_expand_commutator()
  158. if isinstance(comm2, Commutator):
  159. comm2 = comm2._eval_expand_commutator()
  160. first = Mul(comm1, c)
  161. second = Mul(b, comm2)
  162. return Add(first, second)
  163. elif isinstance(A, Pow):
  164. # [A**n, C] -> A**(n - 1)*[A, C] + A**(n - 2)*[A, C]*A + ... + [A, C]*A**(n-1)
  165. return self._expand_pow(A, B, 1)
  166. elif isinstance(B, Pow):
  167. # [A, C**n] -> C**(n - 1)*[C, A] + C**(n - 2)*[C, A]*C + ... + [C, A]*C**(n-1)
  168. return self._expand_pow(B, A, -1)
  169. # No changes, so return self
  170. return self
  171. def doit(self, **hints):
  172. """ Evaluate commutator """
  173. # Keep the import of Operator here to avoid problems with
  174. # circular imports.
  175. from sympy.physics.quantum.operator import Operator
  176. A = self.args[0]
  177. B = self.args[1]
  178. if isinstance(A, Operator) and isinstance(B, Operator):
  179. try:
  180. comm = A._eval_commutator(B, **hints)
  181. except NotImplementedError:
  182. try:
  183. comm = -1*B._eval_commutator(A, **hints)
  184. except NotImplementedError:
  185. comm = None
  186. if comm is not None:
  187. return comm.doit(**hints)
  188. return (A*B - B*A).doit(**hints)
  189. def _eval_adjoint(self):
  190. return Commutator(Dagger(self.args[1]), Dagger(self.args[0]))
  191. def _sympyrepr(self, printer, *args):
  192. return "%s(%s,%s)" % (
  193. self.__class__.__name__, printer._print(
  194. self.args[0]), printer._print(self.args[1])
  195. )
  196. def _sympystr(self, printer, *args):
  197. return "[%s,%s]" % (
  198. printer._print(self.args[0]), printer._print(self.args[1]))
  199. def _pretty(self, printer, *args):
  200. pform = printer._print(self.args[0], *args)
  201. pform = prettyForm(*pform.right(prettyForm(',')))
  202. pform = prettyForm(*pform.right(printer._print(self.args[1], *args)))
  203. pform = prettyForm(*pform.parens(left='[', right=']'))
  204. return pform
  205. def _latex(self, printer, *args):
  206. return "\\left[%s,%s\\right]" % tuple([
  207. printer._print(arg, *args) for arg in self.args])
  208. @Commutator._kind_dispatcher.register(_OperatorKind, _OperatorKind)
  209. def find_op_kind(e1, e2):
  210. """Find the kind of an anticommutator of two OperatorKinds."""
  211. return OperatorKind