From 1846049dafeb625173550d00539989e14939544a Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Mon, 8 Jun 2020 19:16:52 -0400 Subject: [PATCH] eja: new half-baked BilinearFormEJA class. --- mjo/eja/all.py | 3 +- mjo/eja/eja_algebra.py | 119 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 121 insertions(+), 1 deletion(-) diff --git a/mjo/eja/all.py b/mjo/eja/all.py index b3b95e2..a3b524b 100644 --- a/mjo/eja/all.py +++ b/mjo/eja/all.py @@ -2,7 +2,8 @@ All imports from mjo.eja modules. """ -from mjo.eja.eja_algebra import (ComplexHermitianEJA, +from mjo.eja.eja_algebra import (BilinearFormEJA, + ComplexHermitianEJA, HadamardEJA, JordanSpinEJA, QuaternionHermitianEJA, diff --git a/mjo/eja/eja_algebra.py b/mjo/eja/eja_algebra.py index cf541b1..26b7248 100644 --- a/mjo/eja/eja_algebra.py +++ b/mjo/eja/eja_algebra.py @@ -1875,6 +1875,125 @@ class QuaternionHermitianEJA(QuaternionMatrixEuclideanJordanAlgebra, super(QuaternionHermitianEJA,self).__init__(field, basis, n, **kwargs) +class BilinearFormEJA(FiniteDimensionalEuclideanJordanAlgebra, KnownRankEJA): + r""" + The rank-2 simple EJA consisting of real vectors ``x=(x0, x_bar)`` + with the half-trace inner product and jordan product ``x*y = + (x0*y0 + , x0*y_bar + y0*x_bar)`` where ``B`` is a + symmetric positive-definite "bilinear form" matrix. It has + dimension `n` over the reals, and reduces to the ``JordanSpinEJA`` + when ``B`` is the identity matrix of order ``n-1``. + + SETUP:: + + sage: from mjo.eja.eja_algebra import BilinearFormEJA + + EXAMPLES: + + When no bilinear form is specified, the identity matrix is used, + and the resulting algebra is the Jordan spin algebra:: + + sage: J0 = BilinearFormEJA(3) + sage: J1 = JordanSpinEJA(3) + sage: J0.multiplication_table() == J0.multiplication_table() + True + + TESTS: + + We can create a zero-dimensional algebra:: + + sage: J = BilinearFormEJA(0) + sage: J.basis() + Finite family {} + + We can check the multiplication condition given in the Jordan, von + Neumann, and Wigner paper (and also discussed on my "On the + symmetry..." paper). Note that this relies heavily on the standard + choice of basis, as does anything utilizing the bilinear form matrix:: + + sage: set_random_seed() + sage: n = ZZ.random_element(5) + sage: M = matrix.random(QQ, max(0,n-1), algorithm='unimodular') + sage: B = M.transpose()*M + sage: J = BilinearFormEJA(n, B=B) + sage: eis = VectorSpace(M.base_ring(), M.ncols()).basis() + sage: V = J.vector_space() + sage: sis = [ J.from_vector(V([0] + (M.inverse()*ei).list())) + ....: for ei in eis ] + sage: actual = [ sis[i]*sis[j] + ....: for i in range(n-1) + ....: for j in range(n-1) ] + sage: expected = [ J.one() if i == j else J.zero() + ....: for i in range(n-1) + ....: for j in range(n-1) ] + sage: actual == expected + True + """ + def __init__(self, n, field=QQ, B=None, **kwargs): + if B is None: + self._B = matrix.identity(field, max(0,n-1)) + else: + self._B = B + + V = VectorSpace(field, n) + mult_table = [[V.zero() for j in range(n)] for i in range(n)] + for i in range(n): + for j in range(n): + x = V.gen(i) + y = V.gen(j) + x0 = x[0] + xbar = x[1:] + y0 = y[0] + ybar = y[1:] + z0 = x0*y0 + (self._B*xbar).inner_product(ybar) + zbar = y0*xbar + x0*ybar + z = V([z0] + zbar.list()) + mult_table[i][j] = z + + # The rank of this algebra is two, unless we're in a + # one-dimensional ambient space (because the rank is bounded + # by the ambient dimension). + fdeja = super(BilinearFormEJA, self) + return fdeja.__init__(field, mult_table, rank=min(n,2), **kwargs) + + def inner_product(self, x, y): + r""" + Half of the trace inner product. + + This is defined so that the special case of the Jordan spin + algebra gets the usual inner product. + + SETUP:: + + sage: from mjo.eja.eja_algebra import BilinearFormEJA + + TESTS: + + Ensure that this is one-half of the trace inner-product:: + + sage: set_random_seed() + sage: n = ZZ.random_element(5) + sage: M = matrix.random(QQ, n-1, algorithm='unimodular') + sage: B = M.transpose()*M + sage: J = BilinearFormEJA(n, B=B) + sage: eis = VectorSpace(M.base_ring(), M.ncols()).basis() + sage: V = J.vector_space() + sage: sis = [ J.from_vector(V([0] + (M.inverse()*ei).list())) + ....: for ei in eis ] + sage: actual = [ sis[i]*sis[j] + ....: for i in range(n-1) + ....: for j in range(n-1) ] + sage: expected = [ J.one() if i == j else J.zero() + ....: for i in range(n-1) + ....: for j in range(n-1) ] + + """ + xvec = x.to_vector() + xbar = xvec[1:] + yvec = y.to_vector() + ybar = yvec[1:] + return x[0]*y[0] + (self._B*xbar).inner_product(ybar) + class JordanSpinEJA(FiniteDimensionalEuclideanJordanAlgebra, KnownRankEJA): """ The rank-2 simple EJA consisting of real vectors ``x=(x0, x_bar)`` -- 2.43.2