]> gitweb.michael.orlitzky.com - sage.d.git/blobdiff - mjo/eja/eja_element.py
eja: make AA the default field because everything cool requires it.
[sage.d.git] / mjo / eja / eja_element.py
index 3491b69230b0d430fdfa936b3399ebfc88259988..0f6a47cd4f10efbcb0298725c4ae26537eae6372 100644 (file)
@@ -1,7 +1,5 @@
 # -*- coding: utf-8 -*-
 
-from itertools import izip
-
 from sage.matrix.constructor import matrix
 from sage.modules.free_module import VectorSpace
 from sage.modules.with_basis.indexed_element import IndexedFreeModuleElement
@@ -98,7 +96,7 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(IndexedFreeModuleElement):
 
         SETUP::
 
-            sage: from mjo.eja.eja_algebra import (RealCartesianProductEJA,
+            sage: from mjo.eja.eja_algebra import (HadamardEJA,
             ....:                                  random_eja)
 
         EXAMPLES::
@@ -106,7 +104,7 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(IndexedFreeModuleElement):
             sage: R = PolynomialRing(QQ, 't')
             sage: t = R.gen(0)
             sage: p = t^4 - t^3 + 5*t - 2
-            sage: J = RealCartesianProductEJA(5)
+            sage: J = HadamardEJA(5)
             sage: J.one().apply_univariate_polynomial(p) == 3*J.one()
             True
 
@@ -115,7 +113,7 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(IndexedFreeModuleElement):
         We should always get back an element of the algebra::
 
             sage: set_random_seed()
-            sage: p = PolynomialRing(QQ, 't').random_element()
+            sage: p = PolynomialRing(AA, 't').random_element()
             sage: J = random_eja()
             sage: x = J.random_element()
             sage: x.apply_univariate_polynomial(p) in J
@@ -139,7 +137,7 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(IndexedFreeModuleElement):
 
         SETUP::
 
-            sage: from mjo.eja.eja_algebra import RealCartesianProductEJA
+            sage: from mjo.eja.eja_algebra import HadamardEJA
 
         EXAMPLES:
 
@@ -147,14 +145,14 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(IndexedFreeModuleElement):
         the identity element is `(t-1)` from which it follows that
         the characteristic polynomial should be `(t-1)^3`::
 
-            sage: J = RealCartesianProductEJA(3)
+            sage: J = HadamardEJA(3)
             sage: J.one().characteristic_polynomial()
             t^3 - 3*t^2 + 3*t - 1
 
         Likewise, the characteristic of the zero element in the
         rank-three algebra `R^{n}` should be `t^{3}`::
 
-            sage: J = RealCartesianProductEJA(3)
+            sage: J = HadamardEJA(3)
             sage: J.zero().characteristic_polynomial()
             t^3
 
@@ -164,7 +162,7 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(IndexedFreeModuleElement):
         to zero on that element::
 
             sage: set_random_seed()
-            sage: x = RealCartesianProductEJA(3).random_element()
+            sage: x = HadamardEJA(3).random_element()
             sage: p = x.characteristic_polynomial()
             sage: x.apply_univariate_polynomial(p)
             0
@@ -172,7 +170,7 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(IndexedFreeModuleElement):
         The characteristic polynomials of the zero and unit elements
         should be what we think they are in a subalgebra, too::
 
-            sage: J = RealCartesianProductEJA(3)
+            sage: J = HadamardEJA(3)
             sage: p1 = J.one().characteristic_polynomial()
             sage: q1 = J.zero().characteristic_polynomial()
             sage: e0,e1,e2 = J.gens()
@@ -546,10 +544,15 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(IndexedFreeModuleElement):
         return not (p(zero) == zero)
 
 
-    def is_minimal_idempotent(self):
+    def is_primitive_idempotent(self):
         """
-        Return whether or not this element is a minimal idempotent.
+        Return whether or not this element is a primitive (or minimal)
+        idempotent.
 
+        A primitive idempotent is a non-zero idempotent that is not
+        the sum of two other non-zero idempotents. Remark 2.7.15 in
+        Baes shows that this is what he refers to as a "minimal
+        idempotent."
 
         An element of a Euclidean Jordan algebra is a minimal idempotent
         if it :meth:`is_idempotent` and if its Peirce subalgebra
@@ -560,6 +563,7 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(IndexedFreeModuleElement):
 
             sage: from mjo.eja.eja_algebra import (JordanSpinEJA,
             ....:                                  RealSymmetricEJA,
+            ....:                                  TrivialEJA,
             ....:                                  random_eja)
 
         WARNING::
@@ -571,22 +575,22 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(IndexedFreeModuleElement):
         The spectral decomposition of a non-regular element should always
         contain at least one non-minimal idempotent::
 
-            sage: J = RealSymmetricEJA(3, AA)
+            sage: J = RealSymmetricEJA(3)
             sage: x = sum(J.gens())
             sage: x.is_regular()
             False
-            sage: [ c.is_minimal_idempotent()
+            sage: [ c.is_primitive_idempotent()
             ....:   for (l,c) in x.spectral_decomposition() ]
             [False, True]
 
         On the other hand, the spectral decomposition of a regular
         element should always be in terms of minimal idempotents::
 
-            sage: J = JordanSpinEJA(4, AA)
+            sage: J = JordanSpinEJA(4)
             sage: x = sum( i*J.gens()[i] for i in range(len(J.gens())) )
             sage: x.is_regular()
             True
-            sage: [ c.is_minimal_idempotent()
+            sage: [ c.is_primitive_idempotent()
             ....:   for (l,c) in x.spectral_decomposition() ]
             [True, True]
 
@@ -596,7 +600,7 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(IndexedFreeModuleElement):
 
             sage: set_random_seed()
             sage: J = random_eja()
-            sage: J.rank() == 1 or not J.one().is_minimal_idempotent()
+            sage: J.rank() == 1 or not J.one().is_primitive_idempotent()
             True
 
         A non-idempotent cannot be a minimal idempotent::
@@ -604,7 +608,7 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(IndexedFreeModuleElement):
             sage: set_random_seed()
             sage: J = JordanSpinEJA(4)
             sage: x = J.random_element()
-            sage: (not x.is_idempotent()) and x.is_minimal_idempotent()
+            sage: (not x.is_idempotent()) and x.is_primitive_idempotent()
             False
 
         Proposition 2.7.19 in Baes says that an element is a minimal
@@ -615,24 +619,37 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(IndexedFreeModuleElement):
             sage: J = JordanSpinEJA(4)
             sage: x = J.random_element()
             sage: expected = (x.is_idempotent() and x.trace() == 1)
-            sage: actual = x.is_minimal_idempotent()
+            sage: actual = x.is_primitive_idempotent()
             sage: actual == expected
             True
 
+        Primitive idempotents must be non-zero::
+
+            sage: set_random_seed()
+            sage: J = random_eja()
+            sage: J.zero().is_idempotent()
+            True
+            sage: J.zero().is_primitive_idempotent()
+            False
+
+        As a consequence of the fact that primitive idempotents must
+        be non-zero, there are no primitive idempotents in a trivial
+        Euclidean Jordan algebra::
+
+            sage: J = TrivialEJA()
+            sage: J.one().is_idempotent()
+            True
+            sage: J.one().is_primitive_idempotent()
+            False
+
         """
-        # TODO: when the Peirce decomposition is implemented for real,
-        # we can use that instead of finding this eigenspace manually.
-        #
-        # Trivial eigenspaces don't appear in the list, so we default to the
-        # trivial one and override it if there's a nontrivial space in the
-        # list.
         if not self.is_idempotent():
             return False
 
-        J1 = VectorSpace(self.parent().base_ring(), 0)
-        for (eigval, eigspace) in self.operator().matrix().left_eigenspaces():
-            if eigval == 1:
-                J1 = eigspace
+        if self.is_zero():
+            return False
+
+        (_,_,J1) = self.parent().peirce_decomposition(self)
         return (J1.dimension() == 1)
 
 
@@ -892,9 +909,9 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(IndexedFreeModuleElement):
             sage: set_random_seed()
             sage: n_max = RealSymmetricEJA._max_test_case_size()
             sage: n = ZZ.random_element(1, n_max)
-            sage: J1 = RealSymmetricEJA(n,QQ)
-            sage: J2 = RealSymmetricEJA(n,QQ,normalize_basis=False)
-            sage: X = random_matrix(QQ,n)
+            sage: J1 = RealSymmetricEJA(n)
+            sage: J2 = RealSymmetricEJA(n,normalize_basis=False)
+            sage: X = random_matrix(AA,n)
             sage: X = X*X.transpose()
             sage: x1 = J1(X)
             sage: x2 = J2(X)
@@ -969,7 +986,7 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(IndexedFreeModuleElement):
         """
         B = self.parent().natural_basis()
         W = self.parent().natural_basis_space()
-        return W.linear_combination(izip(B,self.to_vector()))
+        return W.linear_combination(zip(B,self.to_vector()))
 
 
     def norm(self):
@@ -979,14 +996,14 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(IndexedFreeModuleElement):
         SETUP::
 
             sage: from mjo.eja.eja_algebra import (JordanSpinEJA,
-            ....:                                  RealCartesianProductEJA)
+            ....:                                  HadamardEJA)
 
         EXAMPLES::
 
-            sage: J = RealCartesianProductEJA(2)
+            sage: J = HadamardEJA(2)
             sage: x = sum(J.gens())
             sage: x.norm()
-            sqrt(2)
+            1.414213562373095?
 
         ::
 
@@ -1048,10 +1065,10 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(IndexedFreeModuleElement):
             sage: n = x_vec.degree()
             sage: x0 = x_vec[0]
             sage: x_bar = x_vec[1:]
-            sage: A = matrix(QQ, 1, [x_vec.inner_product(x_vec)])
+            sage: A = matrix(AA, 1, [x_vec.inner_product(x_vec)])
             sage: B = 2*x0*x_bar.row()
             sage: C = 2*x0*x_bar.column()
-            sage: D = matrix.identity(QQ, n-1)
+            sage: D = matrix.identity(AA, n-1)
             sage: D = (x0^2 - x_bar.inner_product(x_bar))*D
             sage: D = D + 2*x_bar.tensor_product(x_bar)
             sage: Q = matrix.block(2,2,[A,B,C,D])
@@ -1175,7 +1192,7 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(IndexedFreeModuleElement):
         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,AA)
+            sage: J = RealSymmetricEJA(3)
             sage: J.one()
             e0 + e2 + e5
             sage: J.one().spectral_decomposition()
@@ -1185,7 +1202,7 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(IndexedFreeModuleElement):
 
         TESTS::
 
-            sage: J = RealSymmetricEJA(4,AA)
+            sage: J = RealSymmetricEJA(4)
             sage: x = sum(J.gens())
             sage: sd = x.spectral_decomposition()
             sage: l0 = sd[0][0]
@@ -1285,6 +1302,9 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(IndexedFreeModuleElement):
             True
 
         """
+        if self.parent().is_trivial():
+            return self
+
         if self.is_nilpotent():
             raise ValueError("this only works with non-nilpotent elements!")
 
@@ -1295,7 +1315,7 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(IndexedFreeModuleElement):
         # will be minimal for some natural number s...
         s = 0
         minimal_dim = J.dimension()
-        for i in xrange(1, minimal_dim):
+        for i in range(1, minimal_dim):
             this_dim = (u**i).operator().matrix().image().dimension()
             if this_dim < minimal_dim:
                 minimal_dim = this_dim
@@ -1330,7 +1350,7 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(IndexedFreeModuleElement):
         SETUP::
 
             sage: from mjo.eja.eja_algebra import (JordanSpinEJA,
-            ....:                                  RealCartesianProductEJA,
+            ....:                                  HadamardEJA,
             ....:                                  TrivialEJA,
             ....:                                  random_eja)
 
@@ -1348,7 +1368,7 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(IndexedFreeModuleElement):
 
         ::
 
-            sage: J = RealCartesianProductEJA(5)
+            sage: J = HadamardEJA(5)
             sage: J.one().trace()
             5
 
@@ -1426,21 +1446,21 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(IndexedFreeModuleElement):
         SETUP::
 
             sage: from mjo.eja.eja_algebra import (JordanSpinEJA,
-            ....:                                  RealCartesianProductEJA)
+            ....:                                  HadamardEJA)
 
         EXAMPLES::
 
-            sage: J = RealCartesianProductEJA(2)
+            sage: J = HadamardEJA(2)
             sage: x = sum(J.gens())
             sage: x.trace_norm()
-            sqrt(2)
+            1.414213562373095?
 
         ::
 
             sage: J = JordanSpinEJA(4)
             sage: x = sum(J.gens())
             sage: x.trace_norm()
-            2*sqrt(2)
+            2.828427124746190?
 
         """
         return self.trace_inner_product(self).sqrt()