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``.
+ (<Bx,y>,y_bar>, x0*y_bar + y0*x_bar)`` where `B = 1 \times B22` is
+ a symmetric positive-definite "bilinear form" matrix. Its
+ dimension is the size of `B`, and it has rank two in dimensions
+ larger than two. It reduces to the ``JordanSpinEJA`` when `B` is
+ the identity matrix of order ``n``.
+
+ We insist that the one-by-one upper-left identity block of `B` be
+ passed in as well so that we can be passed a matrix of size zero
+ to construct a trivial algebra.
SETUP::
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: B = matrix.identity(AA,3)
+ sage: J0 = BilinearFormEJA(B)
sage: J1 = JordanSpinEJA(3)
sage: J0.multiplication_table() == J0.multiplication_table()
True
We can create a zero-dimensional algebra::
- sage: J = BilinearFormEJA(0)
+ sage: B = matrix.identity(AA,0)
+ sage: J = BilinearFormEJA(B)
sage: J.basis()
Finite family {}
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: B11 = matrix.identity(QQ,1)
+ sage: B22 = M.transpose()*M
+ sage: B = block_matrix(2,2,[ [B11,0 ],
+ ....: [0, B22 ] ])
+ sage: J = BilinearFormEJA(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()))
sage: actual == expected
True
"""
- def __init__(self, n, field=AA, B=None, **kwargs):
- if B is None:
- self._B = matrix.identity(field, max(0,n-1))
- else:
- self._B = B
+ def __init__(self, B, field=AA, **kwargs):
+ self._B = B
+ n = B.nrows()
+
+ if not B.is_positive_definite():
+ raise TypeError("matrix B is not positive-definite")
V = VectorSpace(field, n)
mult_table = [[V.zero() for j in range(n)] for i in range(n)]
xbar = x[1:]
y0 = y[0]
ybar = y[1:]
- z0 = x0*y0 + (self._B*xbar).inner_product(ybar)
+ z0 = (B*x).inner_product(y)
zbar = y0*xbar + x0*ybar
z = V([z0] + zbar.list())
mult_table[i][j] = z
sage: set_random_seed()
sage: n = ZZ.random_element(2,5)
sage: M = matrix.random(QQ, max(0,n-1), algorithm='unimodular')
- sage: B = M.transpose()*M
- sage: J = BilinearFormEJA(n, B=B)
+ sage: B11 = matrix.identity(QQ,1)
+ sage: B22 = M.transpose()*M
+ sage: B = block_matrix(2,2,[ [B11,0 ],
+ ....: [0, B22 ] ])
+ sage: J = BilinearFormEJA(B)
sage: x = J.random_element()
sage: y = J.random_element()
sage: x.inner_product(y) == (x*y).trace()/2
True
"""
- 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)
+ return (self._B*x.to_vector()).inner_product(y.to_vector())
class JordanSpinEJA(BilinearFormEJA):
def __init__(self, n, field=AA, **kwargs):
# This is a special case of the BilinearFormEJA with the identity
# matrix as its bilinear form.
- super(JordanSpinEJA, self).__init__(n, field, **kwargs)
+ B = matrix.identity(field, n)
+ super(JordanSpinEJA, self).__init__(B, field, **kwargs)
class TrivialEJA(FiniteDimensionalEuclideanJordanAlgebra):