Permalink
Browse files

Implement adjoint(): Hermite conjugation.

- adjoint():   Hermite conjugation or conjugate transposition,
- transpose(): Linear map transposition.

>>> A = Symbol('A', hermitian=True)
>>> B = Symbol('B', antihermitian=True)
>>> C = Symbol('C')
>>> M = Matrix(3, 1, [1,I,3])
>>> adjoint(A)
A
>>> adjoint(B)
-B
>>> adjoint(A*B)
-A*B
>>> adjoint(B*B)
B**2
>>> adjoint(C)
conjugate(transpose(C))
>>> M.adjoint()
[1, -I, 3]
  • Loading branch information...
1 parent 4c0ac8a commit 04a297fe17802284e394ca6deff8054798e307ae @jrioux committed Mar 22, 2012
View
@@ -662,6 +662,12 @@ def _eval_as_leading_term(self, x):
def _eval_conjugate(self):
return Add(*[t.conjugate() for t in self.args])
+ def _eval_transpose(self):
+ return Add(*[t.transpose() for t in self.args])
+
+ def _eval_adjoint(self):
+ return Add(*[t.adjoint() for t in self.args])
+
def _eval_expand_basic(self, deep=True, **hints):
sargs, terms = self.args, []
for term in sargs:
View
@@ -640,6 +640,35 @@ def conjugate(self):
from sympy.functions.elementary.complexes import conjugate as c
return c(self)
+ def _eval_transpose(self):
+ from sympy.functions.elementary.complexes import conjugate
+ if self.is_complex:
+ return self
+ elif self.is_hermitian:
+ return conjugate(self)
+ elif self.is_antihermitian:
+ return -conjugate(self)
+
+ def transpose(self):
+ from sympy.functions.elementary.complexes import transpose
+ return transpose(self)
+
+ def _eval_adjoint(self):
+ from sympy.functions.elementary.complexes import conjugate, transpose
+ if self.is_hermitian:
+ return self
+ elif self.is_antihermitian:
+ return -self
+ obj = self._eval_conjugate()
+ if obj is not None:
+ return transpose(obj)
+ obj = self._eval_transpose()
+ if obj is not None:
+ return conjugate(obj)
+
+ def adjoint(self):
+ from sympy.functions.elementary.complexes import adjoint
+ return adjoint(self)
@classmethod
def _parse_order(cls, order):
View
@@ -1466,6 +1466,12 @@ def _eval_as_leading_term(self, x):
def _eval_conjugate(self):
return Mul(*[t.conjugate() for t in self.args])
+ def _eval_transpose(self):
+ return Mul(*[t.transpose() for t in self.args[::-1]])
+
+ def _eval_adjoint(self):
+ return Mul(*[t.adjoint() for t in self.args[::-1]])
+
def _sage_(self):
s = 1
for x in self.args:
View
@@ -278,6 +278,30 @@ def _eval_conjugate(self):
if expanded != self:
return c(expanded)
+ def _eval_transpose(self):
+ from sympy.functions.elementary.complexes import transpose
+ i, p = self.exp.is_integer, self.base.is_complex
+ if p:
+ return self.base**self.exp
+ if i:
+ return transpose(self.base)**self.exp
+ if i is False and p is False:
+ expanded = expand_complex(self)
+ if expanded != self:
+ return transpose(expanded)
+
+ def _eval_adjoint(self):
+ from sympy.functions.elementary.complexes import adjoint
+ i, p = self.exp.is_integer, self.base.is_positive
+ if i:
+ return adjoint(self.base)**self.exp
+ if p:
+ return self.base**adjoint(self.exp)
+ if i is False and p is False:
+ expanded = expand_complex(self)
+ if expanded != self:
+ return adjoint(expanded)
+
def _eval_expand_basic(self, deep=True, **hints):
sargs, terms = self.args, []
for term in sargs:
@@ -673,6 +673,10 @@ def test_sympy__functions__elementary__complexes__Abs():
from sympy.functions.elementary.complexes import Abs
assert _test_args(Abs(x))
+def test_sympy__functions__elementary__complexes__adjoint():
+ from sympy.functions.elementary.complexes import adjoint
+ assert _test_args(adjoint(x))
+
def test_sympy__functions__elementary__complexes__arg():
from sympy.functions.elementary.complexes import arg
assert _test_args(arg(x))
@@ -705,6 +709,10 @@ def test_sympy__functions__elementary__complexes__principal_branch():
from sympy.functions.elementary.complexes import principal_branch
assert _test_args(principal_branch(x, y))
+def test_sympy__functions__elementary__complexes__transpose():
+ from sympy.functions.elementary.complexes import transpose
+ assert _test_args(transpose(x))
+
def test_sympy__functions__elementary__exponential__LambertW():
from sympy.functions.elementary.exponential import LambertW
assert _test_args(LambertW(2))
@@ -22,7 +22,7 @@
from elementary.miscellaneous import sqrt, root, Min, Max, Id, real_root
from elementary.complexes import (re, im, sign, Abs, conjugate, arg,
polar_lift, periodic_argument, unbranched_argument,
- principal_branch)
+ principal_branch, transpose, adjoint)
from elementary.trigonometric import acot, cot, tan, cos, sin, asin, acos, atan, atan2
from elementary.exponential import exp_polar, exp, log, LambertW
from elementary.hyperbolic import sinh, cosh, tanh, coth, asinh, acosh, atanh, acoth
@@ -424,12 +424,68 @@ def eval(cls, arg):
if obj is not None:
return obj
+ def _eval_adjoint(self):
+ return transpose(self.args[0])
+
def _eval_conjugate(self):
return self.args[0]
def _eval_derivative(self, x):
return conjugate(Derivative(self.args[0], x, **{'evaluate': True}))
+ def _eval_transpose(self):
+ return conjugate(transpose(self.args[0]))
+
+class transpose(Function):
+ """
+ Linear map transposition.
+ """
+
+ nargs = 1
+
+ @classmethod
+ def eval(cls, arg):
+ obj = arg._eval_transpose()
+ if obj is not None:
+ return obj
+
+ def _eval_adjoint(self):
+ return conjugate(self.args[0])
+
+ def _eval_derivative(self, x):
+ return transpose(Derivative(self.args[0], x, **{'evaluate': True}))
+
+ def _eval_transpose(self):
+ return self.args[0]
+
+class adjoint(Function):
+ """
+ Conjugate transpose or Hermite conjugation.
+ """
+
+ nargs = 1
+
+ @classmethod
+ def eval(cls, arg):
+ obj = arg._eval_adjoint()
+ if obj is not None:
+ return obj
+ obj = arg._eval_transpose()
+ if obj is not None:
+ return conjugate(obj)
+
+ def _eval_adjoint(self):
+ return self.args[0]
+
+ def _eval_conjugate(self):
+ return transpose(self.args[0])
+
+ def _eval_derivative(self, x):
+ return adjoint(Derivative(self.args[0], x, **{'evaluate': True}))
+
+ def _eval_transpose(self):
+ return conjugate(self.args[0])
+
###############################################################################
############### HANDLING OF POLAR NUMBERS #####################################
###############################################################################
@@ -106,9 +106,21 @@ def eval_transpose(self):
def eval_inverse(self):
raise NotImplementedError()
+ def transpose(self):
+ if isinstance(self, Transpose):
+ return self.arg
+
+ if self.is_Mul:
+ return MatMul(*[Transpose(arg) for arg in self.args[::-1]])
+
+ if self.is_Add:
+ return MatAdd(*[Transpose(arg) for arg in self.args])
+
+ return Basic.__new__(Transpose, self)
+
@property
def T(self):
- return Transpose(self)
+ return self.transpose()
@property
def I(self):
@@ -21,21 +21,9 @@ class Transpose(MatrixExpr):
is_Transpose = True
def __new__(cls, mat):
- if not mat.is_Matrix:
- return mat
-
- if isinstance(mat, Transpose):
- return mat.arg
-
if hasattr(mat, 'transpose'):
return mat.transpose()
- if mat.is_Mul:
- return MatMul(*[Transpose(arg) for arg in mat.args[::-1]])
-
- if mat.is_Add:
- return MatAdd(*[Transpose(arg) for arg in mat.args])
-
return Basic.__new__(cls, mat)
@property
@@ -36,5 +36,8 @@ def __setitem__(self, *args):
as_mutable = MatrixBase.as_mutable
+ adjoint = MatrixBase.adjoint
+ conjugate = MatrixBase.conjugate
equals = MatrixBase.equals
is_Identity = MatrixBase.is_Identity
+ transpose = MatrixBase.transpose
@@ -214,6 +214,10 @@ def conjugate(self):
C = property(conjugate,None,None,"By-element conjugation.")
+ def adjoint(self):
+ """Conjugate transpose or Hermitian conjugation."""
+ return self.conjugate().transpose()
+
@property
def H(self):
"""

0 comments on commit 04a297f

Please sign in to comment.