]> gitweb.michael.orlitzky.com - sage.d.git/commitdiff
eja: fix random_eja() dimension bounds, for real.
authorMichael Orlitzky <michael@orlitzky.com>
Fri, 12 Mar 2021 02:37:08 +0000 (21:37 -0500)
committerMichael Orlitzky <michael@orlitzky.com>
Fri, 12 Mar 2021 02:37:08 +0000 (21:37 -0500)
mjo/eja/TODO
mjo/eja/eja_algebra.py
mjo/eja/eja_element.py

index 38cff88c1584b5be8c6a6ce7e90a47b8350adce3..5bb85879e781286ca67df0a37a856c7db0a7885d 100644 (file)
@@ -6,3 +6,6 @@
    could easily cache the identity and charpoly coefficients using
    the nontrivial factor. On the other hand, it's nice that we can
    test out some alternate code paths...
    could easily cache the identity and charpoly coefficients using
    the nontrivial factor. On the other hand, it's nice that we can
    test out some alternate code paths...
+
+4. Can we hit "x" with the deortho matrix and delegate to the
+   _rational_algebra to speed up minimal_polynomial?
index e28ec6b9466fc69385eeb6cca44c0b8053155629..ee2b52665e8a7d73b50fb4e159430627bcf8b36b 100644 (file)
@@ -1827,11 +1827,36 @@ class ConcreteEJA(FiniteDimensionalEJA):
     def random_instance(cls, max_dimension=None, *args, **kwargs):
         """
         Return a random instance of this type of algebra whose dimension
     def random_instance(cls, max_dimension=None, *args, **kwargs):
         """
         Return a random instance of this type of algebra whose dimension
-        is less than or equal to ``max_dimension``. If the dimension bound
-        is omitted, then the ``_max_random_instance_dimension()`` is used
-        to get a suitable bound.
+        is less than or equal to the lesser of ``max_dimension`` and
+        the value returned by ``_max_random_instance_dimension()``. If
+        the dimension bound is omitted, then only the
+        ``_max_random_instance_dimension()`` is used as a bound.
 
         This method should be implemented in each subclass.
 
         This method should be implemented in each subclass.
+
+        SETUP::
+
+            sage: from mjo.eja.eja_algebra import ConcreteEJA
+
+        TESTS:
+
+        Both the class bound and the ``max_dimension`` argument are upper
+        bounds on the dimension of the algebra returned::
+
+            sage: from sage.misc.prandom import choice
+            sage: eja_class = choice(ConcreteEJA.__subclasses__())
+            sage: class_max_d = eja_class._max_random_instance_dimension()
+            sage: J = eja_class.random_instance(max_dimension=20,
+            ....:                               field=QQ,
+            ....:                               orthonormalize=False)
+            sage: J.dimension() <= class_max_d
+            True
+            sage: J = eja_class.random_instance(max_dimension=2,
+            ....:                               field=QQ,
+            ....:                               orthonormalize=False)
+            sage: J.dimension() <= 2
+            True
+
         """
         from sage.misc.prandom import choice
         eja_class = choice(cls.__subclasses__())
         """
         from sage.misc.prandom import choice
         eja_class = choice(cls.__subclasses__())
@@ -1839,7 +1864,7 @@ class ConcreteEJA(FiniteDimensionalEJA):
         # These all bubble up to the RationalBasisEJA superclass
         # constructor, so any (kw)args valid there are also valid
         # here.
         # These all bubble up to the RationalBasisEJA superclass
         # constructor, so any (kw)args valid there are also valid
         # here.
-        return eja_class.random_instance(*args, **kwargs)
+        return eja_class.random_instance(max_dimension, *args, **kwargs)
 
 
 class MatrixEJA(FiniteDimensionalEJA):
 
 
 class MatrixEJA(FiniteDimensionalEJA):
@@ -2071,14 +2096,15 @@ class RealSymmetricEJA(MatrixEJA, RationalBasisEJA, ConcreteEJA):
         return ZZ(int(ZZ(8*max_dimension + 1).sqrt()/2 - 1/2))
 
     @classmethod
         return ZZ(int(ZZ(8*max_dimension + 1).sqrt()/2 - 1/2))
 
     @classmethod
-    def random_instance(cls, max_dimension=None, **kwargs):
+    def random_instance(cls, max_dimension=None, *args, **kwargs):
         """
         Return a random instance of this type of algebra.
         """
         """
         Return a random instance of this type of algebra.
         """
-        if max_dimension is None:
-            max_dimension = cls._max_random_instance_dimension()
-        max_size = cls._max_random_instance_size(max_dimension) + 1
-        n = ZZ.random_element(max_size)
+        class_max_d = cls._max_random_instance_dimension()
+        if (max_dimension is None or max_dimension > class_max_d):
+            max_dimension = class_max_d
+        max_size = cls._max_random_instance_size(max_dimension)
+        n = ZZ.random_element(max_size + 1)
         return cls(n, **kwargs)
 
     def __init__(self, n, field=AA, **kwargs):
         return cls(n, **kwargs)
 
     def __init__(self, n, field=AA, **kwargs):
@@ -2195,13 +2221,15 @@ class ComplexHermitianEJA(MatrixEJA, RationalBasisEJA, ConcreteEJA):
         return ZZ(int(ZZ(max_dimension).sqrt()))
 
     @classmethod
         return ZZ(int(ZZ(max_dimension).sqrt()))
 
     @classmethod
-    def random_instance(cls, max_dimension=None, **kwargs):
+    def random_instance(cls, max_dimension=None, *args, **kwargs):
         """
         Return a random instance of this type of algebra.
         """
         """
         Return a random instance of this type of algebra.
         """
-        if max_dimension is None:
-            max_dimension = cls._max_random_instance_dimension()
-        n = ZZ.random_element(cls._max_random_instance_size(max_dimension) + 1)
+        class_max_d = cls._max_random_instance_dimension()
+        if (max_dimension is None or max_dimension > class_max_d):
+            max_dimension = class_max_d
+        max_size = cls._max_random_instance_size(max_dimension)
+        n = ZZ.random_element(max_size + 1)
         return cls(n, **kwargs)
 
 
         return cls(n, **kwargs)
 
 
@@ -2291,13 +2319,15 @@ class QuaternionHermitianEJA(MatrixEJA, RationalBasisEJA, ConcreteEJA):
         return ZZ(int(ZZ(8*max_dimension + 1).sqrt()/4 + 1/4))
 
     @classmethod
         return ZZ(int(ZZ(8*max_dimension + 1).sqrt()/4 + 1/4))
 
     @classmethod
-    def random_instance(cls, max_dimension=None, **kwargs):
+    def random_instance(cls, max_dimension=None, *args, **kwargs):
         """
         Return a random instance of this type of algebra.
         """
         """
         Return a random instance of this type of algebra.
         """
-        if max_dimension is None:
-            max_dimension = cls._max_random_instance_dimension()
-        n = ZZ.random_element(cls._max_random_instance_size(max_dimension) + 1)
+        class_max_d = cls._max_random_instance_dimension()
+        if (max_dimension is None or max_dimension > class_max_d):
+            max_dimension = class_max_d
+        max_size = cls._max_random_instance_size(max_dimension)
+        n = ZZ.random_element(max_size + 1)
         return cls(n, **kwargs)
 
 class OctonionHermitianEJA(MatrixEJA, RationalBasisEJA, ConcreteEJA):
         return cls(n, **kwargs)
 
 class OctonionHermitianEJA(MatrixEJA, RationalBasisEJA, ConcreteEJA):
@@ -2404,13 +2434,15 @@ class OctonionHermitianEJA(MatrixEJA, RationalBasisEJA, ConcreteEJA):
             return 0
 
     @classmethod
             return 0
 
     @classmethod
-    def random_instance(cls, max_dimension=None, **kwargs):
+    def random_instance(cls, max_dimension=None, *args, **kwargs):
         """
         Return a random instance of this type of algebra.
         """
         """
         Return a random instance of this type of algebra.
         """
-        if max_dimension is None:
-            max_dimension = cls._max_random_instance_dimension()
-        n = ZZ.random_element(cls._max_random_instance_size(max_dimension) + 1)
+        class_max_d = cls._max_random_instance_dimension()
+        if (max_dimension is None or max_dimension > class_max_d):
+            max_dimension = class_max_d
+        max_size = cls._max_random_instance_size(max_dimension)
+        n = ZZ.random_element(max_size + 1)
         return cls(n, **kwargs)
 
     def __init__(self, n, field=AA, **kwargs):
         return cls(n, **kwargs)
 
     def __init__(self, n, field=AA, **kwargs):
@@ -2546,13 +2578,15 @@ class HadamardEJA(RationalBasisEJA, ConcreteEJA):
         return max_dimension
 
     @classmethod
         return max_dimension
 
     @classmethod
-    def random_instance(cls, max_dimension=None, **kwargs):
+    def random_instance(cls, max_dimension=None, *args, **kwargs):
         """
         Return a random instance of this type of algebra.
         """
         """
         Return a random instance of this type of algebra.
         """
-        if max_dimension is None:
-            max_dimension = cls._max_random_instance_dimension()
-        n = ZZ.random_element(cls._max_random_instance_size(max_dimension) + 1)
+        class_max_d = cls._max_random_instance_dimension()
+        if (max_dimension is None or max_dimension > class_max_d):
+            max_dimension = class_max_d
+        max_size = cls._max_random_instance_size(max_dimension)
+        n = ZZ.random_element(max_size + 1)
         return cls(n, **kwargs)
 
 
         return cls(n, **kwargs)
 
 
@@ -2707,13 +2741,16 @@ class BilinearFormEJA(RationalBasisEJA, ConcreteEJA):
         return max_dimension
 
     @classmethod
         return max_dimension
 
     @classmethod
-    def random_instance(cls, max_dimension=None, **kwargs):
+    def random_instance(cls, max_dimension=None, *args, **kwargs):
         """
         Return a random instance of this algebra.
         """
         """
         Return a random instance of this algebra.
         """
-        if max_dimension is None:
-            max_dimension = cls._max_random_instance_dimension()
-        n = ZZ.random_element(cls._max_random_instance_size(max_dimension) + 1)
+        class_max_d = cls._max_random_instance_dimension()
+        if (max_dimension is None or max_dimension > class_max_d):
+            max_dimension = class_max_d
+        max_size = cls._max_random_instance_size(max_dimension)
+        n = ZZ.random_element(max_size + 1)
+
         if n.is_zero():
             B = matrix.identity(ZZ, n)
             return cls(B, **kwargs)
         if n.is_zero():
             B = matrix.identity(ZZ, n)
             return cls(B, **kwargs)
@@ -2724,6 +2761,7 @@ class BilinearFormEJA(RationalBasisEJA, ConcreteEJA):
         alpha = ZZ.zero()
         while alpha.is_zero():
             alpha = ZZ.random_element().abs()
         alpha = ZZ.zero()
         while alpha.is_zero():
             alpha = ZZ.random_element().abs()
+
         B22 = M.transpose()*M + alpha*I
 
         from sage.matrix.special import block_matrix
         B22 = M.transpose()*M + alpha*I
 
         from sage.matrix.special import block_matrix
@@ -2797,15 +2835,17 @@ class JordanSpinEJA(BilinearFormEJA):
         super().__init__(B, *args, **kwargs)
 
     @classmethod
         super().__init__(B, *args, **kwargs)
 
     @classmethod
-    def random_instance(cls, max_dimension=None, **kwargs):
+    def random_instance(cls, max_dimension=None, *args, **kwargs):
         """
         Return a random instance of this type of algebra.
 
         Needed here to override the implementation for ``BilinearFormEJA``.
         """
         """
         Return a random instance of this type of algebra.
 
         Needed here to override the implementation for ``BilinearFormEJA``.
         """
-        if max_dimension is None:
-            max_dimension = cls._max_random_instance_dimension()
-        n = ZZ.random_element(cls._max_random_instance_size(max_dimension) + 1)
+        class_max_d = cls._max_random_instance_dimension()
+        if (max_dimension is None or max_dimension > class_max_d):
+            max_dimension = class_max_d
+        max_size = cls._max_random_instance_size(max_dimension)
+        n = ZZ.random_element(max_size + 1)
         return cls(n, **kwargs)
 
 
         return cls(n, **kwargs)
 
 
@@ -2862,9 +2902,12 @@ class TrivialEJA(RationalBasisEJA, ConcreteEJA):
         self.one.set_cache( self.zero() )
 
     @classmethod
         self.one.set_cache( self.zero() )
 
     @classmethod
-    def random_instance(cls, **kwargs):
+    def random_instance(cls, max_dimension=None, *args, **kwargs):
         # We don't take a "size" argument so the superclass method is
         # We don't take a "size" argument so the superclass method is
-        # inappropriate for us.
+        # inappropriate for us. The ``max_dimension`` argument is
+        # included so that if this method is called generically with a
+        # ``max_dimension=<whatever>`` argument, we don't try to pass
+        # it on to the algebra constructor.
         return cls(**kwargs)
 
 
         return cls(**kwargs)
 
 
@@ -3417,6 +3460,21 @@ class RationalBasisCartesianProductEJA(CartesianProductEJA,
 RationalBasisEJA.CartesianProduct = RationalBasisCartesianProductEJA
 
 def random_eja(max_dimension=None, *args, **kwargs):
 RationalBasisEJA.CartesianProduct = RationalBasisCartesianProductEJA
 
 def random_eja(max_dimension=None, *args, **kwargs):
+    r"""
+
+    SETUP::
+
+        sage: from mjo.eja.eja_algebra import random_eja
+
+    TESTS::
+
+        sage: set_random_seed()
+        sage: n = ZZ.random_element(1,5)
+        sage: J = random_eja(max_dimension=n, field=QQ, orthonormalize=False)
+        sage: J.dimension() <= n
+        True
+
+    """
     # Use the ConcreteEJA default as the total upper bound (regardless
     # of any whether or not any individual factors set a lower limit).
     if max_dimension is None:
     # Use the ConcreteEJA default as the total upper bound (regardless
     # of any whether or not any individual factors set a lower limit).
     if max_dimension is None:
index 14bc8cb742cc7cc95f6c55895c1e4946b95cb6ac..614c399c926e6ccaf822ad39e2e438880c66c783 100644 (file)
@@ -1021,7 +1021,8 @@ class FiniteDimensionalEJAElement(IndexedFreeModuleElement):
 
             sage: set_random_seed()
             sage: d_max = RealSymmetricEJA._max_random_instance_dimension()
 
             sage: set_random_seed()
             sage: d_max = RealSymmetricEJA._max_random_instance_dimension()
-            sage: n = ZZ.random_element(1, d_max)
+            sage: d = ZZ.random_element(1, d_max)
+            sage: n = RealSymmetricEJA._max_random_instance_size(d)
             sage: J1 = RealSymmetricEJA(n)
             sage: J2 = RealSymmetricEJA(n,orthonormalize=False)
             sage: X = random_matrix(AA,n)
             sage: J1 = RealSymmetricEJA(n)
             sage: J2 = RealSymmetricEJA(n,orthonormalize=False)
             sage: X = random_matrix(AA,n)