]> gitweb.michael.orlitzky.com - sage.d.git/blobdiff - mjo/eja/eja_algebra.py
eja: use custom gram-schmidt in the new constructor.
[sage.d.git] / mjo / eja / eja_algebra.py
index 9d53bc5fdfd8fca177e43e49a187387fbe5a6085..05b9a5a4191bffa74f3680df50d0327cf12b1d1e 100644 (file)
@@ -134,10 +134,15 @@ class FiniteDimensionalEuclideanJordanAlgebra(CombinatorialFreeModule):
         # long run to have the multiplication table be in terms of
         # algebra elements. We do this after calling the superclass
         # constructor so that from_vector() knows what to do.
-        self._multiplication_table = [
-            list(map(lambda x: self.from_vector(x), ls))
-            for ls in mult_table
-        ]
+        self._multiplication_table = [ [ self.vector_space().zero()
+                                         for i in range(n) ]
+                                       for j in range(n) ]
+        # take advantage of symmetry
+        for i in range(n):
+            for j in range(i+1):
+                elt = self.from_vector(mult_table[i][j])
+                self._multiplication_table[i][j] = elt
+                self._multiplication_table[j][i] = elt
 
         if check_axioms:
             if not self._is_commutative():
@@ -989,38 +994,13 @@ class FiniteDimensionalEuclideanJordanAlgebra(CombinatorialFreeModule):
         Ensure that computing the rank actually works, since the ranks
         of all simple algebras are known and will be cached by default::
 
-            sage: J = HadamardEJA(4)
-            sage: J.rank.clear_cache()
-            sage: J.rank()
-            4
-
-        ::
-
-            sage: J = JordanSpinEJA(4)
-            sage: J.rank.clear_cache()
-            sage: J.rank()
-            2
-
-        ::
-
-            sage: J = RealSymmetricEJA(3)
-            sage: J.rank.clear_cache()
-            sage: J.rank()
-            3
-
-        ::
-
-            sage: J = ComplexHermitianEJA(2)
-            sage: J.rank.clear_cache()
-            sage: J.rank()
-            2
-
-        ::
+            sage: set_random_seed()    # long time
+            sage: J = random_eja()     # long time
+            sage: caches = J.rank()    # long time
+            sage: J.rank.clear_cache() # long time
+            sage: J.rank() == cached   # long time
+            True
 
-            sage: J = QuaternionHermitianEJA(2)
-            sage: J.rank.clear_cache()
-            sage: J.rank()
-            2
         """
         return len(self._charpoly_coefficients())
 
@@ -1045,6 +1025,81 @@ class FiniteDimensionalEuclideanJordanAlgebra(CombinatorialFreeModule):
 
     Element = FiniteDimensionalEuclideanJordanAlgebraElement
 
+class RationalBasisEuclideanJordanAlgebraNg(FiniteDimensionalEuclideanJordanAlgebra):
+    def __init__(self,
+                 field,
+                 basis,
+                 jordan_product,
+                 inner_product,
+                 orthonormalize=True,
+                 prefix='e',
+                 category=None,
+                 check_field=True,
+                 check_axioms=True):
+
+        n = len(basis)
+        vector_basis = basis
+
+        from sage.structure.element import is_Matrix
+        basis_is_matrices = False
+
+        degree = 0
+        if n > 0:
+            if is_Matrix(basis[0]):
+                basis_is_matrices = True
+                vector_basis = tuple( map(_mat2vec,basis) )
+                degree = basis[0].nrows()**2
+            else:
+                degree = basis[0].degree()
+
+        V = VectorSpace(field, degree)
+
+        # Compute this from "Q" (obtained from Gram-Schmidt) below as
+        # R = Q.solve_right(A), where the rows of "Q" are the
+        # orthonormalized vector_basis and and the rows of "A" are the
+        # original vector_basis.
+        self._deorthonormalization_matrix = None
+
+        if orthonormalize:
+            from mjo.eja.eja_utils import gram_schmidt
+            vector_basis = gram_schmidt(vector_basis, inner_product)
+            W = V.span_of_basis( vector_basis )
+            if basis_is_matrices:
+                from mjo.eja.eja_utils import _vec2mat
+                basis = tuple( map(_vec2mat,vector_basis) )
+
+        W = V.span_of_basis( vector_basis )
+
+        mult_table = [ [0 for i in range(n)] for j in range(n) ]
+        ip_table = [ [0 for i in range(n)] for j in range(n) ]
+
+        for i in range(n):
+            for j in range(i+1):
+                # do another mat2vec because the multiplication
+                # table is in terms of vectors
+                elt = _mat2vec(jordan_product(basis[i],basis[j]))
+                elt = W.coordinate_vector(elt)
+                mult_table[i][j] = elt
+                mult_table[j][i] = elt
+                ip = inner_product(basis[i],basis[j])
+                ip_table[i][j] = ip
+                ip_table[j][i] = ip
+
+        self._inner_product_matrix = matrix(field,ip_table)
+
+        if basis_is_matrices:
+            for m in basis:
+                m.set_immutable()
+        else:
+            basis = tuple( x.column() for x in basis )
+
+        super().__init__(field,
+                         mult_table,
+                         prefix,
+                         category,
+                         basis, # matrix basis
+                         check_field,
+                         check_axioms)
 
 class RationalBasisEuclideanJordanAlgebra(FiniteDimensionalEuclideanJordanAlgebra):
     r"""
@@ -1090,7 +1145,7 @@ class RationalBasisEuclideanJordanAlgebra(FiniteDimensionalEuclideanJordanAlgebr
             return superclass._charpoly_coefficients()
 
         mult_table = tuple(
-            map(lambda x: x.to_vector(), ls)
+            tuple(map(lambda x: x.to_vector(), ls))
             for ls in self._multiplication_table
         )