]> 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...
+
+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
-        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.
+
+        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__())
@@ -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.
-        return eja_class.random_instance(*args, **kwargs)
+        return eja_class.random_instance(max_dimension, *args, **kwargs)
 
 
 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
-    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.
         """
-        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):
@@ -2195,13 +2221,15 @@ class ComplexHermitianEJA(MatrixEJA, RationalBasisEJA, ConcreteEJA):
         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.
         """
-        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)
 
 
@@ -2291,13 +2319,15 @@ class QuaternionHermitianEJA(MatrixEJA, RationalBasisEJA, ConcreteEJA):
         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.
         """
-        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):
@@ -2404,13 +2434,15 @@ class OctonionHermitianEJA(MatrixEJA, RationalBasisEJA, ConcreteEJA):
             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.
         """
-        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):
@@ -2546,13 +2578,15 @@ class HadamardEJA(RationalBasisEJA, ConcreteEJA):
         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.
         """
-        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)
 
 
@@ -2707,13 +2741,16 @@ class BilinearFormEJA(RationalBasisEJA, ConcreteEJA):
         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.
         """
-        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)
@@ -2724,6 +2761,7 @@ class BilinearFormEJA(RationalBasisEJA, ConcreteEJA):
         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
@@ -2797,15 +2835,17 @@ class JordanSpinEJA(BilinearFormEJA):
         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``.
         """
-        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)
 
 
@@ -2862,9 +2902,12 @@ class TrivialEJA(RationalBasisEJA, ConcreteEJA):
         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
-        # 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)
 
 
@@ -3417,6 +3460,21 @@ class RationalBasisCartesianProductEJA(CartesianProductEJA,
 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:
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: 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)