]> gitweb.michael.orlitzky.com - sage.d.git/commitdiff
eja: new half-baked BilinearFormEJA class.
authorMichael Orlitzky <michael@orlitzky.com>
Mon, 8 Jun 2020 23:16:52 +0000 (19:16 -0400)
committerMichael Orlitzky <michael@orlitzky.com>
Mon, 8 Jun 2020 23:16:52 +0000 (19:16 -0400)
mjo/eja/all.py
mjo/eja/eja_algebra.py

index b3b95e2026a2cd4e771aa82e21b9f78c327b825c..a3b524b509646ae3d0f482fa5f77abe407b3418a 100644 (file)
@@ -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,
index cf541b1b24efe18571ff9132ee8337fbbfe5a6f3..26b72480ffd6d18c1bb8ca43ae3358afda951996 100644 (file)
@@ -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 + <B*x_bar,y_bar>, 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)``