+ Since the eigenvalues are required to be distinct, we take
+ the spectral decomposition of the zero element to be zero
+ times the identity element of the algebra (which is idempotent,
+ obviously).
+
+ SETUP::
+
+ sage: from mjo.eja.eja_algebra import RealSymmetricEJA
+
+ EXAMPLES:
+
+ The spectral decomposition of the identity is ``1`` times itself,
+ and the spectral decomposition of zero is ``0`` times the identity::
+
+ sage: J = RealSymmetricEJA(3)
+ sage: J.one()
+ e0 + e2 + e5
+ sage: J.one().spectral_decomposition()
+ [(1, e0 + e2 + e5)]
+ sage: J.zero().spectral_decomposition()
+ [(0, e0 + e2 + e5)]
+
+ TESTS::
+
+ sage: J = RealSymmetricEJA(4)
+ sage: x = sum(J.gens())
+ sage: sd = x.spectral_decomposition()
+ sage: l0 = sd[0][0]
+ sage: l1 = sd[1][0]
+ sage: c0 = sd[0][1]
+ sage: c1 = sd[1][1]
+ sage: c0.inner_product(c1) == 0
+ True
+ sage: c0.is_idempotent()
+ True
+ sage: c1.is_idempotent()
+ True
+ sage: c0 + c1 == J.one()
+ True
+ sage: l0*c0 + l1*c1 == x
+ True
+
+ The spectral decomposition should work in subalgebras, too::
+
+ sage: J = RealSymmetricEJA(4)
+ sage: (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9) = J.gens()
+ sage: A = 2*e5 - 2*e8
+ sage: (lambda1, c1) = A.spectral_decomposition()[1]
+ sage: (J0, J5, J1) = J.peirce_decomposition(c1)
+ sage: (f0, f1, f2) = J1.gens()
+ sage: f0.spectral_decomposition()
+ [(0, 1.000000000000000?*f2), (1, 1.000000000000000?*f0)]
+
+ """
+ A = self.subalgebra_generated_by(orthonormalize_basis=True)
+ result = []
+ for (evalue, proj) in A(self).operator().spectral_decomposition():
+ result.append( (evalue, proj(A.one()).superalgebra_element()) )
+ return result
+
+ def full_spectral_decomposition(self):
+ if self.is_zero():
+ # Following the convention that the empty sum is the
+ # algebra's additive identity.
+ return []
+
+ A = self.subalgebra_generated_by(orthonormalize_basis=True)
+ if A.dimension() == 1:
+ # I'm a scalar multiple of the identity element
+ s = self.norm() / A.one().norm()
+ return [(s, self * ~s)]
+
+ result = []
+ for (evalue, proj) in A(self).operator().spectral_decomposition():
+ c = proj(A.one()).superalgebra_element()
+
+ # We know that "c" here is idempotent, so the only question is
+ # whether or not it can be decomposed further.
+ if c.is_primitive_idempotent():
+ result.append( (evalue, c) )
+ else:
+ for b in A.gens():
+ b_decomp = b.full_spectral_decomposition()
+ if len(b_decomp) > 1:
+ for (a,y) in b_decomp:
+ y_sup = y.superalgebra_element()
+ eigenvecs = [ r[1] for r in result ]
+ if not y_sup in eigenvecs:
+ result.append( ( evalue*a, y_sup) )
+ return result
+
+ def subalgebra_generated_by(self, orthonormalize_basis=False):