+ def spectral_decomposition(self):
+ """
+ Return the unique spectral decomposition of this element.
+
+ ALGORITHM:
+
+ Following Faraut and Korányi's Theorem III.1.1, we restrict this
+ element's left-multiplication-by operator to the subalgebra it
+ generates. We then compute the spectral decomposition of that
+ operator, and the spectral projectors we get back must be the
+ left-multiplication-by operators for the idempotents we
+ seek. Thus applying them to the identity element gives us those
+ idempotents.
+
+ 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()
+ b0 + b2 + b5
+ sage: J.one().spectral_decomposition()
+ [(1, b0 + b2 + b5)]
+ sage: J.zero().spectral_decomposition()
+ [(0, b0 + b2 + b5)]
+
+ 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: (b0, b1, b2, b3, b4, b5, b6, b7, b8, b9) = J.gens()
+ sage: A = 2*b5 - 2*b8
+ 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?*c2), (1, 1.000000000000000?*c0)]
+
+ """
+ A = self.subalgebra_generated_by(orthonormalize=True)
+ result = []
+ for (evalue, proj) in A(self).operator().spectral_decomposition():
+ result.append( (evalue, proj(A.one()).superalgebra_element()) )
+ return result