]> gitweb.michael.orlitzky.com - sage.d.git/commitdiff
eja: speed up det() for Cartesian product elements.
authorMichael Orlitzky <michael@orlitzky.com>
Sun, 14 Mar 2021 01:46:54 +0000 (20:46 -0500)
committerMichael Orlitzky <michael@orlitzky.com>
Sun, 14 Mar 2021 01:46:54 +0000 (20:46 -0500)
mjo/eja/TODO
mjo/eja/eja_algebra.py
mjo/eja/eja_element.py

index 82c49d53d883d40712b66897c115ed1e58fa430f..9cee421b4f5cacee4e623a6b4d1099c191eeaf72 100644 (file)
@@ -7,9 +7,5 @@
    the nontrivial factor. On the other hand, it's nice that we can
    test out some alternate code paths...
 
-4. Conjecture: if x = (x1,x2), then det(x) = det(x1)det(x2). This
-   should be used to fix the fact that det(x) is monstrously slow in
-   Cartesian product algebras, and thus randomly in the doctests.
-
-5. Add dimension bounds on any tests over AA that compute element
+4. Add dimension bounds on any tests over AA that compute element
    subalgebras.
index 907f40d72135df42d211cdd9bb8923df6bf462e6..2bad32c2f500193e4126b7c5e209c0acb3116ede 100644 (file)
@@ -166,7 +166,8 @@ from sage.modules.free_module import FreeModule, VectorSpace
 from sage.rings.all import (ZZ, QQ, AA, QQbar, RR, RLF, CLF,
                             PolynomialRing,
                             QuadraticField)
-from mjo.eja.eja_element import FiniteDimensionalEJAElement
+from mjo.eja.eja_element import (CartesianProductEJAElement,
+                                 FiniteDimensionalEJAElement)
 from mjo.eja.eja_operator import FiniteDimensionalEJAOperator
 from mjo.eja.eja_utils import _all2list
 
@@ -3089,6 +3090,7 @@ class CartesianProductEJA(FiniteDimensionalEJA):
         sage: actual == expected             # long time
         True
     """
+    Element = CartesianProductEJAElement
     def __init__(self, factors, **kwargs):
         m = len(factors)
         if m == 0:
index 693e8e2d03c0e2aadeb5cf52034fa112a2208f4b..47f6ff080c1d48a1a32b4903991aa0ec5bd0a502 100644 (file)
@@ -6,6 +6,7 @@ from sage.modules.with_basis.indexed_element import IndexedFreeModuleElement
 from mjo.eja.eja_operator import FiniteDimensionalEJAOperator
 from mjo.eja.eja_utils import _scale
 
+
 class FiniteDimensionalEJAElement(IndexedFreeModuleElement):
     """
     An element of a Euclidean Jordan algebra.
@@ -1121,18 +1122,10 @@ class FiniteDimensionalEJAElement(IndexedFreeModuleElement):
         B = self.parent().matrix_basis()
         W = self.parent().matrix_space()
 
-        if hasattr(W, 'cartesian_factors'):
-            # Aaaaand linear combinations don't work in Cartesian
-            # product spaces, even though they provide a method with
-            # that name. This is hidden behind an "if" because the
-            # _scale() function is slow.
-            pairs = zip(B, self.to_vector())
-            return W.sum( _scale(b, alpha) for (b,alpha) in pairs )
-        else:
-            # This is just a manual "from_vector()", but of course
-            # matrix spaces aren't vector spaces in sage, so they
-            # don't have a from_vector() method.
-            return W.linear_combination( zip(B, self.to_vector()) )
+        # This is just a manual "from_vector()", but of course
+        # matrix spaces aren't vector spaces in sage, so they
+        # don't have a from_vector() method.
+        return W.linear_combination( zip(B, self.to_vector()) )
 
 
 
@@ -1650,3 +1643,29 @@ class FiniteDimensionalEJAElement(IndexedFreeModuleElement):
 
         """
         return self.trace_inner_product(self).sqrt()
+
+
+class CartesianProductEJAElement(FiniteDimensionalEJAElement):
+    def det(self):
+        r"""
+        Compute the determinant of this product-element using the
+        determianants of its factors.
+
+        This result Follows from the spectral decomposition of (say)
+        the pair `(x,y)` in terms of the Jordan frame `\left\{ (c_1,
+        0),(c_2, 0),...,(0,d_1),(0,d_2),... \right\}.
+        """
+        from sage.misc.misc_c import prod
+        return prod( f.det() for f in self.cartesian_factors() )
+
+    def to_matrix(self):
+        # An override is necessary to call our custom _scale().
+        B = self.parent().matrix_basis()
+        W = self.parent().matrix_space()
+
+        # Aaaaand linear combinations don't work in Cartesian
+        # product spaces, even though they provide a method with
+        # that name. This is hidden behind an "if" because the
+        # _scale() function is slow.
+        pairs = zip(B, self.to_vector())
+        return W.sum( _scale(b, alpha) for (b,alpha) in pairs )