From 2a0cca4f62e8335db7069e04f0837a96b331614a Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Sat, 20 Jul 2019 11:18:22 -0400 Subject: [PATCH] eja: get the quaternions working. --- mjo/eja/euclidean_jordan_algebra.py | 126 +++++++++++++++++++++++++++- 1 file changed, 123 insertions(+), 3 deletions(-) diff --git a/mjo/eja/euclidean_jordan_algebra.py b/mjo/eja/euclidean_jordan_algebra.py index 204c608..b8c7a91 100644 --- a/mjo/eja/euclidean_jordan_algebra.py +++ b/mjo/eja/euclidean_jordan_algebra.py @@ -321,6 +321,12 @@ class FiniteDimensionalEuclideanJordanAlgebra(FiniteDimensionalAlgebra): sage: J.one().inner_product(J.one()) 3 + Ditto for the quaternions:: + + sage: J = QuaternionHermitianSimpleEJA(3) + sage: J.one().inner_product(J.one()) + 3 + TESTS: Ensure that we can always compute an inner product, and that @@ -674,6 +680,25 @@ class FiniteDimensionalEuclideanJordanAlgebra(FiniteDimensionalAlgebra): [0 0 0 0 1 0] [0 0 0 0 0 1] + :: + + sage: J = QuaternionHermitianSimpleEJA(3) + sage: J.one() + e0 + e9 + e14 + sage: J.one().natural_representation() + [1 0 0 0 0 0 0 0 0 0 0 0] + [0 1 0 0 0 0 0 0 0 0 0 0] + [0 0 1 0 0 0 0 0 0 0 0 0] + [0 0 0 1 0 0 0 0 0 0 0 0] + [0 0 0 0 1 0 0 0 0 0 0 0] + [0 0 0 0 0 1 0 0 0 0 0 0] + [0 0 0 0 0 0 1 0 0 0 0 0] + [0 0 0 0 0 0 0 1 0 0 0 0] + [0 0 0 0 0 0 0 0 1 0 0 0] + [0 0 0 0 0 0 0 0 0 1 0 0] + [0 0 0 0 0 0 0 0 0 0 1 0] + [0 0 0 0 0 0 0 0 0 0 0 1] + """ B = self.parent().natural_basis() W = B[0].matrix_space() @@ -1042,6 +1067,12 @@ def random_eja(): * The ``n``-by-``n`` rational symmetric matrices with the symmetric product. + * The ``n``-by-``n`` complex-rational Hermitian matrices embedded + in the space of ``2n``-by-``2n`` real symmetric matrices. + + * The ``n``-by-``n`` quaternion-rational Hermitian matrices embedded + in the space of ``4n``-by-``4n`` real symmetric matrices. + Later this might be extended to return Cartesian products of the EJAs above. @@ -1055,7 +1086,8 @@ def random_eja(): constructor = choice([eja_rn, JordanSpinSimpleEJA, RealSymmetricSimpleEJA, - ComplexHermitianSimpleEJA]) + ComplexHermitianSimpleEJA, + QuaternionHermitianSimpleEJA]) return constructor(n, field=QQ) @@ -1116,6 +1148,48 @@ def _complex_hermitian_basis(n, field=QQ): return tuple(S) +def _quaternion_hermitian_basis(n, field=QQ): + """ + Returns a basis for the space of quaternion Hermitian n-by-n matrices. + + TESTS:: + + sage: set_random_seed() + sage: n = ZZ.random_element(1,5) + sage: all( M.is_symmetric() for M in _quaternion_hermitian_basis(n) ) + True + + """ + Q = QuaternionAlgebra(QQ,-1,-1) + I,J,K = Q.gens() + + # This is like the symmetric case, but we need to be careful: + # + # * We want conjugate-symmetry, not just symmetry. + # * The diagonal will (as a result) be real. + # + S = [] + for i in xrange(n): + for j in xrange(i+1): + Eij = matrix(Q, n, lambda k,l: k==i and l==j) + if i == j: + Sij = _embed_quaternion_matrix(Eij) + S.append(Sij) + else: + # Beware, orthogonal but not normalized! The second, + # third, and fourth ones have a minus because they're + # conjugated. + Sij_real = _embed_quaternion_matrix(Eij + Eij.transpose()) + S.append(Sij_real) + Sij_I = _embed_quaternion_matrix(I*Eij - I*Eij.transpose()) + S.append(Sij_I) + Sij_J = _embed_quaternion_matrix(J*Eij - J*Eij.transpose()) + S.append(Sij_J) + Sij_K = _embed_quaternion_matrix(K*Eij - K*Eij.transpose()) + S.append(Sij_K) + return tuple(S) + + def _mat2vec(m): return vector(m.base_ring(), m.list()) @@ -1467,14 +1541,60 @@ def ComplexHermitianSimpleEJA(n, field=QQ): inner_product=ip) -def QuaternionHermitianSimpleEJA(n): +def QuaternionHermitianSimpleEJA(n, field=QQ): """ The rank-n simple EJA consisting of self-adjoint n-by-n quaternion matrices, the usual symmetric Jordan product, and the real-part-of-trace inner product. It has dimension `2n^2 - n` over the reals. + + TESTS: + + The degree of this algebra is `n^2`:: + + sage: set_random_seed() + sage: n = ZZ.random_element(1,5) + sage: J = QuaternionHermitianSimpleEJA(n) + sage: J.degree() == 2*(n^2) - n + True + + The Jordan multiplication is what we think it is:: + + sage: set_random_seed() + sage: n = ZZ.random_element(1,5) + sage: J = QuaternionHermitianSimpleEJA(n) + sage: x = J.random_element() + sage: y = J.random_element() + sage: actual = (x*y).natural_representation() + sage: X = x.natural_representation() + sage: Y = y.natural_representation() + sage: expected = (X*Y + Y*X)/2 + sage: actual == expected + True + sage: J(expected) == x*y + True + """ - pass + S = _quaternion_hermitian_basis(n) + (Qs, T) = _multiplication_table_from_matrix_basis(S) + + # Since a+bi+cj+dk on the diagonal is represented as + # + # a + bi +cj + dk = [ a b c d] + # [ -b a -d c] + # [ -c d a -b] + # [ -d -c b a], + # + # we'll quadruple-count the "a" entries if we take the trace of + # the embedding. + ip = lambda X,Y: _matrix_ip(X,Y)/4 + + return FiniteDimensionalEuclideanJordanAlgebra(field, + Qs, + rank=n, + natural_basis=T, + inner_product=ip) + def OctonionHermitianSimpleEJA(n): """ -- 2.44.2