]> gitweb.michael.orlitzky.com - sage.d.git/blobdiff - mjo/eja/eja_algebra.py
eja: use now somewhat-proven and fast rank computation.
[sage.d.git] / mjo / eja / eja_algebra.py
index 0ef8bef1ab06bdb7dc08dd5785642f3c46b23369..7436ed36ce676dd9bbf0eda9922ac2aecacc6e6e 100644 (file)
@@ -794,6 +794,72 @@ class FiniteDimensionalEuclideanJordanAlgebra(CombinatorialFreeModule):
         return  tuple( self.random_element() for idx in range(count) )
 
 
+    def _rank_computation(self):
+        r"""
+        Compute the rank of this algebra.
+
+        SETUP::
+
+            sage: from mjo.eja.eja_algebra import (HadamardEJA,
+            ....:                                  JordanSpinEJA,
+            ....:                                  RealSymmetricEJA,
+            ....:                                  ComplexHermitianEJA,
+            ....:                                  QuaternionHermitianEJA)
+
+        EXAMPLES::
+
+            sage: J = HadamardEJA(4)
+            sage: J._rank_computation() == J.rank()
+            True
+            sage: J = JordanSpinEJA(4)
+            sage: J._rank_computation() == J.rank()
+            True
+            sage: J = RealSymmetricEJA(3)
+            sage: J._rank_computation() == J.rank()
+            True
+            sage: J = ComplexHermitianEJA(2)
+            sage: J._rank_computation() == J.rank()
+            True
+            sage: J = QuaternionHermitianEJA(2)
+            sage: J._rank_computation() == J.rank()
+            True
+
+        """
+        n = self.dimension()
+        if n == 0:
+            return 0
+        elif n == 1:
+            return 1
+
+        var_names = [ "X" + str(z) for z in range(1,n+1) ]
+        R = PolynomialRing(self.base_ring(), var_names)
+        vars = R.gens()
+
+        def L_x_i_j(i,j):
+            # From a result in my book, these are the entries of the
+            # basis representation of L_x.
+            return sum( vars[k]*self.monomial(k).operator().matrix()[i,j]
+                        for k in range(n) )
+
+        L_x = matrix(R, n, n, L_x_i_j)
+        x_powers = [ vars[k]*(L_x**k)*self.one().to_vector()
+                     for k in range(n) ]
+
+        # Can assume n >= 2
+        M = matrix([x_powers[0]])
+        old_rank = 1
+
+        for d in range(1,n):
+            M = matrix(M.rows() + [x_powers[d]])
+            M.echelonize()
+            new_rank = M.rank()
+            if new_rank == old_rank:
+                return new_rank
+            else:
+                old_rank = new_rank
+
+        return n
+
     def rank(self):
         """
         Return the rank of this EJA.
@@ -1069,6 +1135,28 @@ class MatrixEuclideanJordanAlgebra(FiniteDimensionalEuclideanJordanAlgebra):
                               **kwargs)
 
 
+    def _rank_computation(self):
+        r"""
+        Override the parent method with something that tries to compute
+        over a faster (non-extension) field.
+        """
+        if self._basis_normalizers is None:
+            # We didn't normalize, so assume that the basis we started
+            # with had entries in a nice field.
+            return super(MatrixEuclideanJordanAlgebra, self)._rank_computation()
+        else:
+            basis = ( (b/n) for (b,n) in zip(self.natural_basis(),
+                                             self._basis_normalizers) )
+
+            # Do this over the rationals and convert back at the end.
+            # Only works because we know the entries of the basis are
+            # integers.
+            J = MatrixEuclideanJordanAlgebra(QQ,
+                                             basis,
+                                             self.rank(),
+                                             normalize_basis=False)
+            return J._rank_computation()
+
     @cached_method
     def _charpoly_coeff(self, i):
         """