]> gitweb.michael.orlitzky.com - sage.d.git/blobdiff - mjo/eja/eja_algebra.py
eja: let random_eja() return zero-dimensional algebras of all types.
[sage.d.git] / mjo / eja / eja_algebra.py
index fc64510dde701f7f820456d9972691fe07f71178..4e66b2db251274d3091875a20056692f33849513 100644 (file)
@@ -438,8 +438,15 @@ class FiniteDimensionalEuclideanJordanAlgebra(CombinatorialFreeModule):
         """
         Return the matrix space in which this algebra's natural basis
         elements live.
+
+        Generally this will be an `n`-by-`1` column-vector space,
+        except when the algebra is trivial. There it's `n`-by-`n`
+        (where `n` is zero), to ensure that two elements of the
+        natural basis space (empty matrices) can be multiplied.
         """
-        if self._natural_basis is None or len(self._natural_basis) == 0:
+        if self.is_trivial():
+            return MatrixSpace(self.base_ring(), 0)
+        elif self._natural_basis is None or len(self._natural_basis) == 0:
             return MatrixSpace(self.base_ring(), self.dimension(), 1)
         else:
             return self._natural_basis[0].matrix_space()
@@ -666,7 +673,7 @@ class FiniteDimensionalEuclideanJordanAlgebra(CombinatorialFreeModule):
             # there's only one.
             return cls(field)
 
-        n = ZZ.random_element(cls._max_test_case_size()) + 1
+        n = ZZ.random_element(cls._max_test_case_size() + 1)
         return cls(n, field, **kwargs)
 
     @cached_method
@@ -688,6 +695,14 @@ class FiniteDimensionalEuclideanJordanAlgebra(CombinatorialFreeModule):
                         for k in range(n) )
 
         L_x = matrix(F, n, n, L_x_i_j)
+
+        r = None
+        if self.rank.is_in_cache():
+            r = self.rank()
+            # There's no need to pad the system with redundant
+            # columns if we *know* they'll be redundant.
+            n = r
+
         # Compute an extra power in case the rank is equal to
         # the dimension (otherwise, we would stop at x^(r-1)).
         x_powers = [ (L_x**k)*self.one().to_vector()
@@ -696,7 +711,8 @@ class FiniteDimensionalEuclideanJordanAlgebra(CombinatorialFreeModule):
         AE = A.extended_echelon_form()
         E = AE[:,n:]
         A_rref = AE[:,:n]
-        r = A_rref.rank()
+        if r is None:
+            r = A_rref.rank()
         b = x_powers[r]
 
         # The theory says that only the first "r" coefficients are
@@ -894,7 +910,7 @@ class HadamardEJA(FiniteDimensionalEuclideanJordanAlgebra):
         return x.to_vector().inner_product(y.to_vector())
 
 
-def random_eja(field=AA, nontrivial=False):
+def random_eja(field=AA):
     """
     Return a "random" finite-dimensional Euclidean Jordan Algebra.
 
@@ -908,21 +924,17 @@ def random_eja(field=AA, nontrivial=False):
         Euclidean Jordan algebra of dimension...
 
     """
-    eja_classes = [HadamardEJA,
-                   JordanSpinEJA,
-                   RealSymmetricEJA,
-                   ComplexHermitianEJA,
-                   QuaternionHermitianEJA]
-    if not nontrivial:
-        eja_classes.append(TrivialEJA)
-    classname = choice(eja_classes)
+    classname = choice([TrivialEJA,
+                        HadamardEJA,
+                        JordanSpinEJA,
+                        RealSymmetricEJA,
+                        ComplexHermitianEJA,
+                        QuaternionHermitianEJA])
     return classname.random_instance(field=field)
 
 
 
 
-
-
 class MatrixEuclideanJordanAlgebra(FiniteDimensionalEuclideanJordanAlgebra):
     @staticmethod
     def _max_test_case_size():
@@ -984,7 +996,26 @@ class MatrixEuclideanJordanAlgebra(FiniteDimensionalEuclideanJordanAlgebra):
             J = MatrixEuclideanJordanAlgebra(QQ,
                                              basis,
                                              normalize_basis=False)
-            return J._charpoly_coefficients()
+            a = J._charpoly_coefficients()
+
+            # Unfortunately, changing the basis does change the
+            # coefficients of the characteristic polynomial, but since
+            # these are really the coefficients of the "characteristic
+            # polynomial of" function, everything is still nice and
+            # unevaluated. It's therefore "obvious" how scaling the
+            # basis affects the coordinate variables X1, X2, et
+            # cetera. Scaling the first basis vector up by "n" adds a
+            # factor of 1/n into every "X1" term, for example. So here
+            # we simply undo the basis_normalizer scaling that we
+            # performed earlier.
+            #
+            # The a[0] access here is safe because trivial algebras
+            # won't have any basis normalizers and therefore won't
+            # make it to this "else" branch.
+            XS = a[0].parent().gens()
+            subs_dict = { XS[i]: self._basis_normalizers[i]*XS[i]
+                          for i in range(len(XS)) }
+            return tuple( a_i.subs(subs_dict) for a_i in a )
 
 
     @staticmethod
@@ -1002,6 +1033,9 @@ class MatrixEuclideanJordanAlgebra(FiniteDimensionalEuclideanJordanAlgebra):
         # is supposed to hold the entire long vector, and the subspace W
         # of V will be spanned by the vectors that arise from symmetric
         # matrices. Thus for S^2, dim(V) == 4 and dim(W) == 3.
+        if len(basis) == 0:
+            return []
+
         field = basis[0].base_ring()
         dimension = basis[0].nrows()
 
@@ -1159,6 +1193,11 @@ class RealSymmetricEJA(RealMatrixEuclideanJordanAlgebra):
         sage: x.operator().matrix().is_symmetric()
         True
 
+    We can construct the (trivial) algebra of rank zero::
+
+        sage: RealSymmetricEJA(0)
+        Euclidean Jordan algebra of dimension 0 over Algebraic Real Field
+
     """
     @classmethod
     def _denormalized_basis(cls, n, field):
@@ -1432,6 +1471,11 @@ class ComplexHermitianEJA(ComplexMatrixEuclideanJordanAlgebra):
         sage: x.operator().matrix().is_symmetric()
         True
 
+    We can construct the (trivial) algebra of rank zero::
+
+        sage: ComplexHermitianEJA(0)
+        Euclidean Jordan algebra of dimension 0 over Algebraic Real Field
+
     """
 
     @classmethod
@@ -1727,6 +1771,11 @@ class QuaternionHermitianEJA(QuaternionMatrixEuclideanJordanAlgebra):
         sage: x.operator().matrix().is_symmetric()
         True
 
+    We can construct the (trivial) algebra of rank zero::
+
+        sage: QuaternionHermitianEJA(0)
+        Euclidean Jordan algebra of dimension 0 over Algebraic Real Field
+
     """
     @classmethod
     def _denormalized_basis(cls, n, field):