]> gitweb.michael.orlitzky.com - sage.d.git/blobdiff - mjo/eja/euclidean_jordan_algebra.py
eja: replace eja_ln() and eja_sn() with their new names.
[sage.d.git] / mjo / eja / euclidean_jordan_algebra.py
index fdaccba58a8b99a2f5222054358969ce3e731882..0a53667c36284d3a07a218f30e37fae8334861a9 100644 (file)
@@ -133,12 +133,12 @@ class FiniteDimensionalEuclideanJordanAlgebra(FiniteDimensionalAlgebra):
 
             EXAMPLES::
 
-                sage: J = eja_ln(2)
+                sage: J = JordanSpinSimpleEJA(2)
                 sage: e0,e1 = J.gens()
                 sage: x = e0 + e1
                 sage: x.det()
                 0
-                sage: J = eja_ln(3)
+                sage: J = JordanSpinSimpleEJA(3)
                 sage: e0,e1,e2 = J.gens()
                 sage: x = e0 + e1 + e2
                 sage: x.det()
@@ -207,7 +207,7 @@ class FiniteDimensionalEuclideanJordanAlgebra(FiniteDimensionalAlgebra):
             The identity element always has degree one, but any element
             linearly-independent from it is regular::
 
-                sage: J = eja_ln(5)
+                sage: J = JordanSpinSimpleEJA(5)
                 sage: J.one().is_regular()
                 False
                 sage: e0, e1, e2, e3, e4 = J.gens() # e0 is the identity
@@ -232,7 +232,7 @@ class FiniteDimensionalEuclideanJordanAlgebra(FiniteDimensionalAlgebra):
 
             EXAMPLES::
 
-                sage: J = eja_ln(4)
+                sage: J = JordanSpinSimpleEJA(4)
                 sage: J.one().degree()
                 1
                 sage: e0,e1,e2,e3 = J.gens()
@@ -244,7 +244,7 @@ class FiniteDimensionalEuclideanJordanAlgebra(FiniteDimensionalAlgebra):
 
                 sage: set_random_seed()
                 sage: n = ZZ.random_element(1,10).abs()
-                sage: J = eja_ln(n)
+                sage: J = JordanSpinSimpleEJA(n)
                 sage: x = J.random_element()
                 sage: x == x.coefficient(0)*J.one() or x.degree() == 2
                 True
@@ -289,7 +289,7 @@ class FiniteDimensionalEuclideanJordanAlgebra(FiniteDimensionalAlgebra):
 
                 sage: set_random_seed()
                 sage: n = ZZ.random_element(2,10).abs()
-                sage: J = eja_ln(n)
+                sage: J = JordanSpinSimpleEJA(n)
                 sage: y = J.random_element()
                 sage: while y == y.coefficient(0)*J.one():
                 ....:     y = J.random_element()
@@ -333,7 +333,7 @@ class FiniteDimensionalEuclideanJordanAlgebra(FiniteDimensionalAlgebra):
             Alizadeh's Example 11.12::
 
                 sage: n = ZZ.random_element(1,10).abs()
-                sage: J = eja_ln(n)
+                sage: J = JordanSpinSimpleEJA(n)
                 sage: x = J.random_element()
                 sage: x_vec = x.vector()
                 sage: x0 = x_vec[0]
@@ -433,7 +433,7 @@ class FiniteDimensionalEuclideanJordanAlgebra(FiniteDimensionalAlgebra):
                 sage: c = J.random_element().subalgebra_idempotent()
                 sage: c^2 == c
                 True
-                sage: J = eja_ln(5)
+                sage: J = JordanSpinSimpleEJA(5)
                 sage: c = J.random_element().subalgebra_idempotent()
                 sage: c^2 == c
                 True
@@ -489,7 +489,7 @@ class FiniteDimensionalEuclideanJordanAlgebra(FiniteDimensionalAlgebra):
 
             EXAMPLES::
 
-                sage: J = eja_ln(3)
+                sage: J = JordanSpinSimpleEJA(3)
                 sage: e0,e1,e2 = J.gens()
                 sage: x = e0 + e1 + e2
                 sage: x.trace()
@@ -549,82 +549,6 @@ def eja_rn(dimension, field=QQ):
     return FiniteDimensionalEuclideanJordanAlgebra(field,Qs,rank=dimension)
 
 
-def eja_ln(dimension, field=QQ):
-    """
-    Return the Jordan algebra corresponding to the Lorentz "ice cream"
-    cone of the given ``dimension``.
-
-    EXAMPLES:
-
-    This multiplication table can be verified by hand::
-
-        sage: J = eja_ln(4)
-        sage: e0,e1,e2,e3 = J.gens()
-        sage: e0*e0
-        e0
-        sage: e0*e1
-        e1
-        sage: e0*e2
-        e2
-        sage: e0*e3
-        e3
-        sage: e1*e2
-        0
-        sage: e1*e3
-        0
-        sage: e2*e3
-        0
-
-    In one dimension, this is the reals under multiplication::
-
-      sage: J1 = eja_ln(1)
-      sage: J2 = eja_rn(1)
-      sage: J1 == J2
-      True
-
-    """
-    Qs = []
-    id_matrix = identity_matrix(field,dimension)
-    for i in xrange(dimension):
-        ei = id_matrix.column(i)
-        Qi = zero_matrix(field,dimension)
-        Qi.set_row(0, ei)
-        Qi.set_column(0, ei)
-        Qi += diagonal_matrix(dimension, [ei[0]]*dimension)
-        # The addition of the diagonal matrix adds an extra ei[0] in the
-        # upper-left corner of the matrix.
-        Qi[0,0] = Qi[0,0] * ~field(2)
-        Qs.append(Qi)
-
-    # The rank of the spin factor algebra is two, UNLESS we're in a
-    # one-dimensional ambient space (the rank is bounded by the
-    # ambient dimension).
-    rank = min(dimension,2)
-    return FiniteDimensionalEuclideanJordanAlgebra(field,Qs,rank=rank)
-
-
-def eja_sn(dimension, field=QQ):
-    """
-    Return the simple Jordan algebra of ``dimension``-by-``dimension``
-    symmetric matrices over ``field``.
-
-    EXAMPLES::
-
-        sage: J = eja_sn(2)
-        sage: e0, e1, e2 = J.gens()
-        sage: e0*e0
-        e0
-        sage: e1*e1
-        e0 + e2
-        sage: e2*e2
-        e2
-
-    """
-    S = _real_symmetric_basis(dimension, field=field)
-    Qs = _multiplication_table_from_matrix_basis(S)
-
-    return FiniteDimensionalEuclideanJordanAlgebra(field,Qs,rank=dimension)
-
 
 def random_eja():
     """
@@ -652,9 +576,12 @@ def random_eja():
         Euclidean Jordan algebra of degree...
 
     """
-    n = ZZ.random_element(1,10).abs()
-    constructor = choice([eja_rn, eja_ln, eja_sn])
-    return constructor(dimension=n, field=QQ)
+    n = ZZ.random_element(1,5).abs()
+    constructor = choice([eja_rn,
+                          JordanSpinSimpleEJA,
+                          RealSymmetricSimpleEJA,
+                          ComplexHermitianSimpleEJA])
+    return constructor(n, field=QQ)
 
 
 
@@ -709,7 +636,7 @@ def _multiplication_table_from_matrix_basis(basis):
     S = [ vec2mat(b) for b in W.basis() ]
 
     Qs = []
-    for s in basis:
+    for s in S:
         # Brute force the multiplication-by-s matrix by looping
         # through all elements of the basis and doing the computation
         # to find out what the corresponding row should be. BEWARE:
@@ -718,10 +645,10 @@ def _multiplication_table_from_matrix_basis(basis):
         # constructor uses ROW vectors and not COLUMN vectors. That's
         # why we're computing rows here and not columns.
         Q_rows = []
-        for t in basis:
+        for t in S:
             this_row = mat2vec((s*t + t*s)/2)
             Q_rows.append(W.coordinates(this_row))
-        Q = matrix(field,Q_rows)
+        Q = matrix(field, W.dimension(), Q_rows)
         Qs.append(Q)
 
     return Qs
@@ -758,25 +685,90 @@ def _embed_complex_matrix(M):
         a = z.real()
         b = z.imag()
         blocks.append(matrix(field, 2, [[a,-b],[b,a]]))
-    return block_matrix(field, n, blocks)
 
+    # We can drop the imaginaries here.
+    return block_matrix(field.base_ring(), n, blocks)
+
+
+def _unembed_complex_matrix(M):
+    """
+    The inverse of _embed_complex_matrix().
+
+    EXAMPLES::
 
-def RealSymmetricSimpleEJA(n):
+        sage: A = matrix(QQ,[ [ 1,  2,   3,  4],
+        ....:                 [-2,  1,  -4,  3],
+        ....:                 [ 9,  10, 11, 12],
+        ....:                 [-10, 9, -12, 11] ])
+        sage: _unembed_complex_matrix(A)
+        [  -2*i + 1   -4*i + 3]
+        [ -10*i + 9 -12*i + 11]
+    """
+    n = ZZ(M.nrows())
+    if M.ncols() != n:
+        raise ArgumentError("the matrix 'M' must be square")
+    if not n.mod(2).is_zero():
+        raise ArgumentError("the matrix 'M' must be a complex embedding")
+
+    F = QuadraticField(-1, 'i')
+    i = F.gen()
+
+    # Go top-left to bottom-right (reading order), converting every
+    # 2-by-2 block we see to a single complex element.
+    elements = []
+    for k in xrange(n/2):
+        for j in xrange(n/2):
+            submat = M[2*k:2*k+2,2*j:2*j+2]
+            if submat[0,0] != submat[1,1]:
+                raise ArgumentError('bad real submatrix')
+            if submat[0,1] != -submat[1,0]:
+                raise ArgumentError('bad imag submatrix')
+            z = submat[0,0] + submat[1,0]*i
+            elements.append(z)
+
+    return matrix(F, n/2, elements)
+
+
+def RealSymmetricSimpleEJA(n, field=QQ):
     """
     The rank-n simple EJA consisting of real symmetric n-by-n
     matrices, the usual symmetric Jordan product, and the trace inner
     product. It has dimension `(n^2 + n)/2` over the reals.
+
+    EXAMPLES::
+
+        sage: J = RealSymmetricSimpleEJA(2)
+        sage: e0, e1, e2 = J.gens()
+        sage: e0*e0
+        e0
+        sage: e1*e1
+        e0 + e2
+        sage: e2*e2
+        e2
     """
-    pass
+    S = _real_symmetric_basis(n, field=field)
+    Qs = _multiplication_table_from_matrix_basis(S)
 
-def ComplexHermitianSimpleEJA(n):
+    return FiniteDimensionalEuclideanJordanAlgebra(field,Qs,rank=n)
+
+
+def ComplexHermitianSimpleEJA(n, field=QQ):
     """
     The rank-n simple EJA consisting of complex Hermitian n-by-n
     matrices over the real numbers, the usual symmetric Jordan product,
     and the real-part-of-trace inner product. It has dimension `n^2 over
     the reals.
     """
-    pass
+    F = QuadraticField(-1, 'i')
+    i = F.gen()
+    S = _real_symmetric_basis(n, field=F)
+    T = []
+    for s in S:
+        T.append(s)
+        T.append(i*s)
+    embed_T = [ _embed_complex_matrix(t) for t in T ]
+    Qs = _multiplication_table_from_matrix_basis(embed_T)
+    return FiniteDimensionalEuclideanJordanAlgebra(field, Qs, rank=n)
 
 def QuaternionHermitianSimpleEJA(n):
     """
@@ -794,11 +786,56 @@ def OctonionHermitianSimpleEJA(n):
     n = 3
     pass
 
-def JordanSpinSimpleEJA(n):
+def JordanSpinSimpleEJA(n, field=QQ):
     """
     The rank-2 simple EJA consisting of real vectors ``x=(x0, x_bar)``
     with the usual inner product and jordan product ``x*y =
     (<x_bar,y_bar>, x0*y_bar + y0*x_bar)``. It has dimension `n` over
     the reals.
+
+    EXAMPLES:
+
+    This multiplication table can be verified by hand::
+
+        sage: J = JordanSpinSimpleEJA(4)
+        sage: e0,e1,e2,e3 = J.gens()
+        sage: e0*e0
+        e0
+        sage: e0*e1
+        e1
+        sage: e0*e2
+        e2
+        sage: e0*e3
+        e3
+        sage: e1*e2
+        0
+        sage: e1*e3
+        0
+        sage: e2*e3
+        0
+
+    In one dimension, this is the reals under multiplication::
+
+      sage: J1 = JordanSpinSimpleEJA(1)
+      sage: J2 = eja_rn(1)
+      sage: J1 == J2
+      True
+
     """
-    pass
+    Qs = []
+    id_matrix = identity_matrix(field, n)
+    for i in xrange(n):
+        ei = id_matrix.column(i)
+        Qi = zero_matrix(field, n)
+        Qi.set_row(0, ei)
+        Qi.set_column(0, ei)
+        Qi += diagonal_matrix(n, [ei[0]]*n)
+        # The addition of the diagonal matrix adds an extra ei[0] in the
+        # upper-left corner of the matrix.
+        Qi[0,0] = Qi[0,0] * ~field(2)
+        Qs.append(Qi)
+
+    # The rank of the spin factor algebra is two, UNLESS we're in a
+    # one-dimensional ambient space (the rank is bounded by the
+    # ambient dimension).
+    return FiniteDimensionalEuclideanJordanAlgebra(field, Qs, rank=min(n,2))