product. This will be applied to ``basis`` to compute an
inner-product table (basically a matrix) for this algebra.
+ - ``matrix_space`` -- the space that your matrix basis lives in,
+ or ``None`` (the default). So long as your basis does not have
+ length zero you can omit this. But in trivial algebras, it is
+ required.
+
- ``field`` -- a subfield of the reals (default: ``AA``); the scalar
field for the algebra.
sage: basis = tuple(b.superalgebra_element() for b in A.basis())
sage: J.subalgebra(basis, orthonormalize=False).is_associative()
True
-
"""
Element = FiniteDimensionalEJAElement
jordan_product,
inner_product,
field=AA,
+ matrix_space=None,
orthonormalize=True,
associative=None,
cartesian_product=False,
basis = tuple(gram_schmidt(basis, inner_product))
# Save the (possibly orthonormalized) matrix basis for
- # later...
+ # later, as well as the space that its elements live in.
+ # In most cases we can deduce the matrix space, but when
+ # n == 0 (that is, there are no basis elements) we cannot.
self._matrix_basis = basis
+ if matrix_space is None:
+ self._matrix_space = self._matrix_basis[0].parent()
+ else:
+ self._matrix_space = matrix_space
# Now create the vector space for the algebra, which will have
# its own set of non-ambient coordinates (in terms of the
the scalar ring Rational Field
"""
- if self.is_trivial():
- return MatrixSpace(self.base_ring(), 0)
- else:
- return self.matrix_basis()[0].parent()
+ return self._matrix_space
@cached_method
jordan_product,
inner_product,
field=QQ,
+ matrix_space=self.matrix_space(),
associative=self.is_associative(),
orthonormalize=False,
check_field=False,
self.jordan_product,
self.trace_inner_product,
field=field,
+ matrix_space=A,
**kwargs)
# TODO: this could be factored out somehow, but is left here
# because the MatrixEJA is not presently a subclass of the
# FDEJA class that defines rank() and one().
self.rank.set_cache(n)
- if n == 0:
- self.one.set_cache( self.zero() )
- else:
- self.one.set_cache(self(A.one()))
+ self.one.set_cache( self(A.one()) )
EXAMPLES:
- In theory, our "field" can be any subfield of the reals::
+ In theory, our "field" can be any subfield of the reals, but we
+ can't use inexact real fields at the moment because SageMath
+ doesn't know how to convert their elements into complex numbers,
+ or even into algebraic reals::
- sage: ComplexHermitianEJA(2, field=RDF, check_axioms=True)
- Euclidean Jordan algebra of dimension 4 over Real Double Field
- sage: ComplexHermitianEJA(2, field=RR, check_axioms=True)
- Euclidean Jordan algebra of dimension 4 over Real Field with
- 53 bits of precision
+ sage: QQbar(RDF(1))
+ Traceback (most recent call last):
+ ...
+ TypeError: Illegal initializer for algebraic number
+ sage: AA(RR(1))
+ Traceback (most recent call last):
+ ...
+ TypeError: Illegal initializer for algebraic number
+
+ This causes the following error when we try to scale a matrix of
+ complex numbers by an inexact real number::
+
+ sage: ComplexHermitianEJA(2,field=RR)
+ Traceback (most recent call last):
+ ...
+ TypeError: Unable to coerce entries (=(1.00000000000000,
+ -0.000000000000000)) to coefficients in Algebraic Real Field
TESTS:
sage: ComplexHermitianEJA(0)
Euclidean Jordan algebra of dimension 0 over Algebraic Real Field
-
"""
def __init__(self, n, field=AA, **kwargs):
# We know this is a valid EJA, but will double-check
self.jordan_product,
self.trace_inner_product,
field=field,
+ matrix_space=A,
**kwargs)
# TODO: this could be factored out somehow, but is left here
# because the MatrixEJA is not presently a subclass of the
# FDEJA class that defines rank() and one().
self.rank.set_cache(n)
- if n == 0:
- self.one.set_cache( self.zero() )
- else:
- self.one.set_cache(self(A.one()))
+ self.one.set_cache( self(A.one()) )
+
@staticmethod
def _max_random_instance_size():
self.jordan_product,
self.trace_inner_product,
field=field,
+ matrix_space=A,
**kwargs)
# TODO: this could be factored out somehow, but is left here
# because the MatrixEJA is not presently a subclass of the
# FDEJA class that defines rank() and one().
self.rank.set_cache(n)
- if n == 0:
- self.one.set_cache( self.zero() )
- else:
- self.one.set_cache(self(A.one()))
+ self.one.set_cache( self(A.one()) )
@staticmethod
self.jordan_product,
self.trace_inner_product,
field=field,
+ matrix_space=A,
**kwargs)
# TODO: this could be factored out somehow, but is left here
# because the MatrixEJA is not presently a subclass of the
# FDEJA class that defines rank() and one().
self.rank.set_cache(n)
- if n == 0:
- self.one.set_cache( self.zero() )
- else:
- self.one.set_cache(self(A.one()))
+ self.one.set_cache( self(A.one()) )
class AlbertEJA(OctonionHermitianEJA):
(r0, r1, r2)
"""
def __init__(self, n, field=AA, **kwargs):
+ MS = MatrixSpace(field, n, 1)
+
if n == 0:
jordan_product = lambda x,y: x
inner_product = lambda x,y: x
else:
def jordan_product(x,y):
- P = x.parent()
- return P( xi*yi for (xi,yi) in zip(x,y) )
+ return MS( xi*yi for (xi,yi) in zip(x,y) )
def inner_product(x,y):
return (x.T*y)[0,0]
if "orthonormalize" not in kwargs: kwargs["orthonormalize"] = False
if "check_axioms" not in kwargs: kwargs["check_axioms"] = False
- column_basis = tuple( b.column()
- for b in FreeModule(field, n).basis() )
+ column_basis = tuple( MS(b) for b in FreeModule(field, n).basis() )
super().__init__(column_basis,
jordan_product,
inner_product,
field=field,
+ matrix_space=MS,
associative=True,
**kwargs)
self.rank.set_cache(n)
- if n == 0:
- self.one.set_cache( self.zero() )
- else:
- self.one.set_cache( sum(self.gens()) )
+ self.one.set_cache( self.sum(self.gens()) )
@staticmethod
def _max_random_instance_size():
# verify things, we'll skip the rest of the checks.
if "check_axioms" not in kwargs: kwargs["check_axioms"] = False
+ n = B.nrows()
+ MS = MatrixSpace(field, n, 1)
+
def inner_product(x,y):
return (y.T*B*x)[0,0]
def jordan_product(x,y):
- P = x.parent()
x0 = x[0,0]
xbar = x[1:,0]
y0 = y[0,0]
ybar = y[1:,0]
z0 = inner_product(y,x)
zbar = y0*xbar + x0*ybar
- return P([z0] + zbar.list())
+ return MS([z0] + zbar.list())
- n = B.nrows()
- column_basis = tuple( b.column()
- for b in FreeModule(field, n).basis() )
+ column_basis = tuple( MS(b) for b in FreeModule(field, n).basis() )
# TODO: I haven't actually checked this, but it seems legit.
associative = False
jordan_product,
inner_product,
field=field,
+ matrix_space=MS,
associative=associative,
**kwargs)
# one-dimensional ambient space (because the rank is bounded
# by the ambient dimension).
self.rank.set_cache(min(n,2))
-
if n == 0:
self.one.set_cache( self.zero() )
else:
0
"""
- def __init__(self, **kwargs):
+ def __init__(self, field=AA, **kwargs):
jordan_product = lambda x,y: x
- inner_product = lambda x,y: 0
+ inner_product = lambda x,y: field.zero()
basis = ()
+ MS = MatrixSpace(field,0)
# New defaults for keyword arguments
if "orthonormalize" not in kwargs: kwargs["orthonormalize"] = False
jordan_product,
inner_product,
associative=True,
+ field=field,
+ matrix_space=MS,
**kwargs)
# The rank is zero using my definition, namely the dimension of the
associative = all( f.is_associative() for f in factors )
- MS = self.matrix_space()
+ # Compute my matrix space. This category isn't perfect, but
+ # is good enough for what we need to do.
+ MS_cat = MagmaticAlgebras(field).FiniteDimensional().WithBasis()
+ MS_cat = MS_cat.Unital().CartesianProducts()
+ MS_factors = tuple( J.matrix_space() for J in factors )
+ from sage.sets.cartesian_product import CartesianProduct
+ MS = CartesianProduct(MS_factors, MS_cat)
+
basis = []
zero = MS.zero()
for i in range(m):
jordan_product,
inner_product,
field=field,
+ matrix_space=MS,
orthonormalize=False,
associative=associative,
cartesian_product=True,
check_field=False,
check_axioms=False)
+ self.rank.set_cache(sum(J.rank() for J in factors))
ones = tuple(J.one().to_matrix() for J in factors)
self.one.set_cache(self(ones))
- self.rank.set_cache(sum(J.rank() for J in factors))
def cartesian_factors(self):
# Copy/pasted from CombinatorialFreeModule_CartesianProduct.
+----+
"""
- scalars = self.cartesian_factor(0).base_ring()
-
- # This category isn't perfect, but is good enough for what we
- # need to do.
- cat = MagmaticAlgebras(scalars).FiniteDimensional().WithBasis()
- cat = cat.Unital().CartesianProducts()
- factors = tuple( J.matrix_space() for J in self.cartesian_factors() )
-
- from sage.sets.cartesian_product import CartesianProduct
- return CartesianProduct(factors, cat)
+ return super().matrix_space()
@cached_method