]> gitweb.michael.orlitzky.com - sage.d.git/blobdiff - mjo/eja/eja_operator.py
eja: get a rudimentary spectral decomposition for operators working.
[sage.d.git] / mjo / eja / eja_operator.py
index 7c3b2a6a4721848caaaf4d30cecbb08d0eab587f..c32ff1ed7c2ba0aa87c842e5545f9bf204f43fac 100644 (file)
@@ -13,6 +13,8 @@ class FiniteDimensionalEuclideanJordanAlgebraOperator(Map):
         F = domain_eja.base_ring()
         if not (F == codomain_eja.base_ring()):
             raise ValueError("domain and codomain must have the same base ring")
+        if not (F == mat.base_ring()):
+            raise ValueError("domain and matrix must have the same base ring")
 
         # We need to supply something here to avoid getting the
         # default Homset of the parent FiniteDimensionalAlgebra class,
@@ -81,19 +83,18 @@ class FiniteDimensionalEuclideanJordanAlgebraOperator(Map):
             [2 0 0]
             [0 2 0]
             [0 0 2]
-            Domain: Euclidean Jordan algebra of dimension 3 over
-            Rational Field
-            Codomain: Euclidean Jordan algebra of dimension 3 over
-            Rational Field
+            Domain: Euclidean Jordan algebra of dimension 3 over...
+            Codomain: Euclidean Jordan algebra of dimension 3 over...
 
         If you try to add two identical vector space operators but on
         different EJAs, that should blow up::
 
             sage: J1 = RealSymmetricEJA(2)
+            sage: id1 = identity_matrix(J1.base_ring(), 3)
             sage: J2 = JordanSpinEJA(3)
-            sage: id = identity_matrix(QQ, 3)
-            sage: f = FiniteDimensionalEuclideanJordanAlgebraOperator(J1,J1,id)
-            sage: g = FiniteDimensionalEuclideanJordanAlgebraOperator(J2,J2,id)
+            sage: id2 = identity_matrix(J2.base_ring(), 3)
+            sage: f = FiniteDimensionalEuclideanJordanAlgebraOperator(J1,J1,id1)
+            sage: g = FiniteDimensionalEuclideanJordanAlgebraOperator(J2,J2,id2)
             sage: f + g
             Traceback (most recent call last):
             ...
@@ -179,10 +180,8 @@ class FiniteDimensionalEuclideanJordanAlgebraOperator(Map):
             [1 0 0]
             [0 1 0]
             [0 0 1]
-            Domain: Euclidean Jordan algebra of dimension 3 over
-            Rational Field
-            Codomain: Euclidean Jordan algebra of dimension 3 over
-            Rational Field
+            Domain: Euclidean Jordan algebra of dimension 3 over...
+            Codomain: Euclidean Jordan algebra of dimension 3 over...
 
         """
         return FiniteDimensionalEuclideanJordanAlgebraOperator(
@@ -215,30 +214,31 @@ class FiniteDimensionalEuclideanJordanAlgebraOperator(Map):
             sage: x.operator()
             Linear operator between finite-dimensional Euclidean Jordan algebras
             represented by the matrix:
-            [ 2  4  0]
+            [ 2  2  0]
             [ 2  9  2]
-            [ 0  4 16]
-            Domain: Euclidean Jordan algebra of dimension 3 over
-            Rational Field
-            Codomain: Euclidean Jordan algebra of dimension 3 over
-            Rational Field
+            [ 0  2 16]
+            Domain: Euclidean Jordan algebra of dimension 3 over...
+            Codomain: Euclidean Jordan algebra of dimension 3 over...
             sage: x.operator()*(1/2)
             Linear operator between finite-dimensional Euclidean Jordan algebras
             represented by the matrix:
-            [  1   2   0]
+            [  1   1   0]
             [  1 9/2   1]
-            [  0   2   8]
-            Domain: Euclidean Jordan algebra of dimension 3 over
-            Rational Field
-            Codomain: Euclidean Jordan algebra of dimension 3 over
-            Rational Field
+            [  0   1   8]
+            Domain: Euclidean Jordan algebra of dimension 3 over...
+            Codomain: Euclidean Jordan algebra of dimension 3 over...
 
         """
-        if other in self.codomain().base_ring():
-            return FiniteDimensionalEuclideanJordanAlgebraOperator(
-                self.domain(),
-                self.codomain(),
-                self.matrix()*other)
+        try:
+            if other in self.codomain().base_ring():
+                return FiniteDimensionalEuclideanJordanAlgebraOperator(
+                    self.domain(),
+                    self.codomain(),
+                    self.matrix()*other)
+        except NotImplementedError:
+            # This can happen with certain arguments if the base_ring()
+            # is weird and doesn't know how to test membership.
+            pass
 
         # This should eventually delegate to _composition_ after performing
         # some sanity checks for us.
@@ -266,10 +266,8 @@ class FiniteDimensionalEuclideanJordanAlgebraOperator(Map):
             [-1  0  0]
             [ 0 -1  0]
             [ 0  0 -1]
-            Domain: Euclidean Jordan algebra of dimension 3 over
-            Rational Field
-            Codomain: Euclidean Jordan algebra of dimension 3 over
-            Rational Field
+            Domain: Euclidean Jordan algebra of dimension 3 over...
+            Codomain: Euclidean Jordan algebra of dimension 3 over...
 
         """
         return FiniteDimensionalEuclideanJordanAlgebraOperator(
@@ -301,10 +299,8 @@ class FiniteDimensionalEuclideanJordanAlgebraOperator(Map):
             [3 0 0]
             [0 3 0]
             [0 0 3]
-            Domain: Euclidean Jordan algebra of dimension 3 over
-            Rational Field
-            Codomain: Euclidean Jordan algebra of dimension 3 over
-            Rational Field
+            Domain: Euclidean Jordan algebra of dimension 3 over...
+            Codomain: Euclidean Jordan algebra of dimension 3 over...
 
         """
         if (n == 1):
@@ -380,10 +376,8 @@ class FiniteDimensionalEuclideanJordanAlgebraOperator(Map):
             [-1  0  0]
             [ 0 -1  0]
             [ 0  0 -1]
-            Domain: Euclidean Jordan algebra of dimension 3 over
-            Rational Field
-            Codomain: Euclidean Jordan algebra of dimension 3 over
-            Rational Field
+            Domain: Euclidean Jordan algebra of dimension 3 over...
+            Codomain: Euclidean Jordan algebra of dimension 3 over...
 
         """
         return (self + (-other))
@@ -432,3 +426,43 @@ class FiniteDimensionalEuclideanJordanAlgebraOperator(Map):
         """
         # The matrix method returns a polynomial in 'x' but want one in 't'.
         return self.matrix().minimal_polynomial().change_variable_name('t')
+
+
+    def spectral_decomposition(self):
+        """
+        Return the spectral decomposition of this operator as a list of
+        (eigenvalue, orthogonal projector) pairs.
+
+        SETUP::
+
+            sage: from mjo.eja.eja_algebra import RealSymmetricEJA
+
+        EXAMPLES::
+
+            sage: J = RealSymmetricEJA(4,AA)
+            sage: x = sum(J.gens())
+            sage: A = x.subalgebra_generated_by(orthonormalize_basis=True)
+            sage: L0x = A(x).operator()
+            sage: Ps = [ P*l for (l,P) in L0x.spectral_decomposition() ]
+            sage: Ps[0] + Ps[1] == L0x
+            True
+
+        """
+        if not self.matrix().is_symmetric():
+            raise ValueError('algebra basis is not orthonormal')
+
+        D,P = self.matrix().jordan_form(subdivide=False,transformation=True)
+        eigenvalues = D.diagonal()
+        us = P.columns()
+        projectors = []
+        for i in range(len(us)):
+            # they won't be normalized, but they have to be
+            # for the spectral theorem to work.
+            us[i] = us[i]/us[i].norm()
+            mat = us[i].column()*us[i].row()
+            Pi = FiniteDimensionalEuclideanJordanAlgebraOperator(
+                   self.domain(),
+                   self.codomain(),
+                   mat)
+            projectors.append(Pi)
+        return zip(eigenvalues, projectors)