]> gitweb.michael.orlitzky.com - sage.d.git/blobdiff - mjo/eja/eja_element.py
eja: work towards fixing element subalgebras.
[sage.d.git] / mjo / eja / eja_element.py
index 6181f032e644423989cf135cd65eeafcb943585f..f0f6da756e841e65b7d9272f5feb09404c9f1a09 100644 (file)
@@ -830,10 +830,7 @@ class FiniteDimensionalEJAElement(IndexedFreeModuleElement):
 
         ALGORITHM:
 
-        For now, we skip the messy minimal polynomial computation
-        and instead return the dimension of the vector space spanned
-        by the powers of this element. The latter is a bit more
-        straightforward to compute.
+        .........
 
         SETUP::
 
@@ -881,12 +878,59 @@ class FiniteDimensionalEJAElement(IndexedFreeModuleElement):
             True
 
         """
-        if self.is_zero() and not self.parent().is_trivial():
+        n = self.parent().dimension()
+
+        if n == 0:
+            # The minimal polynomial is an empty product, i.e. the
+            # constant polynomial "1" having degree zero.
+            return 0
+        elif self.is_zero():
             # The minimal polynomial of zero in a nontrivial algebra
-            # is "t"; in a trivial algebra it's "1" by convention
-            # (it's an empty product).
+            # is "t", and is of degree one.
+            return 1
+        elif n == 1:
+            # If this is a nonzero element of a nontrivial algebra, it
+            # has degree at least one. It follows that, in an algebra
+            # of dimension one, the degree must be actually one.
             return 1
-        return self.subalgebra_generated_by().dimension()
+
+        # BEWARE: The subalgebra_generated_by() method uses the result
+        # of this method to construct a basis for the subalgebra. That
+        # means, in particular, that we cannot implement this method
+        # as ``self.subalgebra_generated_by().dimension()``.
+
+        # Algorithm: keep appending (vector representations of) powers
+        # self as rows to a matrix and echelonizing it. When its rank
+        # stops increasing, we've reached a redundancy.
+
+        # Given the special cases above, we can assume that "self" is
+        # nonzero, the algebra is nontrivial, and that its dimension
+        # is at least two.
+        M = matrix([(self.parent().one()).to_vector()])
+        old_rank = 1
+
+        # Specifying the row-reduction algorithm can e.g.  help over
+        # AA because it avoids the RecursionError that gets thrown
+        # when we have to look too hard for a root.
+        #
+        # Beware: QQ supports an entirely different set of "algorithm"
+        # keywords than do AA and RR.
+        algo = None
+        from sage.rings.all import QQ
+        if self.parent().base_ring() is not QQ:
+            algo = "scaled_partial_pivoting"
+
+        for d in range(1,n):
+            M = matrix(M.rows() + [(self**d).to_vector()])
+            M.echelonize(algo)
+            new_rank = M.rank()
+            if new_rank == old_rank:
+                return new_rank
+            else:
+                old_rank = new_rank
+
+        return n
+
 
 
     def left_matrix(self):
@@ -1320,7 +1364,7 @@ class FiniteDimensionalEJAElement(IndexedFreeModuleElement):
             result.append( (evalue, proj(A.one()).superalgebra_element()) )
         return result
 
-    def subalgebra_generated_by(self, orthonormalize_basis=False):
+    def subalgebra_generated_by(self, **kwargs):
         """
         Return the associative subalgebra of the parent EJA generated
         by this element.
@@ -1368,7 +1412,7 @@ class FiniteDimensionalEJAElement(IndexedFreeModuleElement):
 
         """
         from mjo.eja.eja_element_subalgebra import FiniteDimensionalEJAElementSubalgebra
-        return FiniteDimensionalEJAElementSubalgebra(self, orthonormalize_basis)
+        return FiniteDimensionalEJAElementSubalgebra(self, **kwargs)
 
 
     def subalgebra_idempotent(self):