from sage.algebras.quatalg.quaternion_algebra import QuaternionAlgebra
from sage.categories.magmatic_algebras import MagmaticAlgebras
from sage.categories.sets_cat import cartesian_product
-from sage.combinat.free_module import (CombinatorialFreeModule,
- CombinatorialFreeModule_CartesianProduct)
+from sage.combinat.free_module import CombinatorialFreeModule
from sage.matrix.constructor import matrix
from sage.matrix.matrix_space import MatrixSpace
from sage.misc.cachefunc import cached_method
cartesian_product=False,
check_field=True,
check_axioms=True,
- prefix='e'):
+ prefix="b"):
n = len(basis)
# we've specified a real embedding.
raise ValueError("scalar field is not real")
- from mjo.eja.eja_utils import _change_ring
- # If the basis given to us wasn't over the field that it's
- # supposed to be over, fix that. Or, you know, crash.
- basis = tuple( _change_ring(b, field) for b in basis )
-
if check_axioms:
# Check commutativity of the Jordan and inner-products.
# This has to be done before we build the multiplication
# ambient vector space V that our (vectorized) basis lives in,
# as well as a subspace W of V spanned by those (vectorized)
# basis elements. The W-coordinates are the coefficients that
- # we see in things like x = 1*e1 + 2*e2.
+ # we see in things like x = 1*b1 + 2*b2.
vector_basis = basis
degree = 0
sage: set_random_seed()
sage: J = random_eja()
sage: n = J.dimension()
- sage: ei = J.zero()
- sage: ej = J.zero()
- sage: ei_ej = J.zero()*J.zero()
+ sage: bi = J.zero()
+ sage: bj = J.zero()
+ sage: bi_bj = J.zero()*J.zero()
sage: if n > 0:
....: i = ZZ.random_element(n)
....: j = ZZ.random_element(n)
- ....: ei = J.monomial(i)
- ....: ej = J.monomial(j)
- ....: ei_ej = J.product_on_basis(i,j)
- sage: ei*ej == ei_ej
+ ....: bi = J.monomial(i)
+ ....: bj = J.monomial(j)
+ ....: bi_bj = J.product_on_basis(i,j)
+ sage: bi*bj == bi_bj
True
"""
sage: J2 = RealSymmetricEJA(2)
sage: J = cartesian_product([J1,J2])
sage: J( (J1.matrix_basis()[1], J2.matrix_basis()[2]) )
- e1 + e5
+ b1 + b5
TESTS:
sage: J = JordanSpinEJA(4)
sage: J.multiplication_table()
+----++----+----+----+----+
- | * || e0 | e1 | e2 | e3 |
+ | * || b0 | b1 | b2 | b3 |
+====++====+====+====+====+
- | e0 || e0 | e1 | e2 | e3 |
+ | b0 || b0 | b1 | b2 | b3 |
+----++----+----+----+----+
- | e1 || e1 | e0 | 0 | 0 |
+ | b1 || b1 | b0 | 0 | 0 |
+----++----+----+----+----+
- | e2 || e2 | 0 | e0 | 0 |
+ | b2 || b2 | 0 | b0 | 0 |
+----++----+----+----+----+
- | e3 || e3 | 0 | 0 | e0 |
+ | b3 || b3 | 0 | 0 | b0 |
+----++----+----+----+----+
"""
sage: J = RealSymmetricEJA(2)
sage: J.basis()
- Finite family {0: e0, 1: e1, 2: e2}
+ Finite family {0: b0, 1: b1, 2: b2}
sage: J.matrix_basis()
(
[1 0] [ 0 0.7071067811865475?] [0 0]
sage: J = JordanSpinEJA(2)
sage: J.basis()
- Finite family {0: e0, 1: e1}
+ Finite family {0: b0, 1: b1}
sage: J.matrix_basis()
(
[1] [0]
sage: J = HadamardEJA(5)
sage: J.one()
- e0 + e1 + e2 + e3 + e4
+ b0 + b1 + b2 + b3 + b4
The unit element in the Hadamard EJA is inherited in the
subalgebras generated by its elements::
sage: J = HadamardEJA(5)
sage: J.one()
- e0 + e1 + e2 + e3 + e4
+ b0 + b1 + b2 + b3 + b4
sage: x = sum(J.gens())
sage: A = x.subalgebra_generated_by(orthonormalize=False)
sage: A.one()
- f0
+ c0
sage: A.one().superalgebra_element()
- e0 + e1 + e2 + e3 + e4
+ b0 + b1 + b2 + b3 + b4
TESTS:
EXAMPLES::
sage: J = RealSymmetricEJA(2)
- sage: e0, e1, e2 = J.gens()
- sage: e0*e0
- e0
- sage: e1*e1
- 1/2*e0 + 1/2*e2
- sage: e2*e2
- e2
+ sage: b0, b1, b2 = J.gens()
+ sage: b0*b0
+ b0
+ sage: b1*b1
+ 1/2*b0 + 1/2*b2
+ sage: b2*b2
+ b2
In theory, our "field" can be any subfield of the reals::
"""
@classmethod
- def _denormalized_basis(cls, n):
+ def _denormalized_basis(cls, n, field):
"""
Return a basis for the space of real symmetric n-by-n matrices.
sage: set_random_seed()
sage: n = ZZ.random_element(1,5)
- sage: B = RealSymmetricEJA._denormalized_basis(n)
+ sage: B = RealSymmetricEJA._denormalized_basis(n,ZZ)
sage: all( M.is_symmetric() for M in B)
True
S = []
for i in range(n):
for j in range(i+1):
- Eij = matrix(ZZ, n, lambda k,l: k==i and l==j)
+ Eij = matrix(field, n, lambda k,l: k==i and l==j)
if i == j:
Sij = Eij
else:
n = ZZ.random_element(cls._max_random_instance_size() + 1)
return cls(n, **kwargs)
- def __init__(self, n, **kwargs):
+ def __init__(self, n, field=AA, **kwargs):
# We know this is a valid EJA, but will double-check
# if the user passes check_axioms=True.
if "check_axioms" not in kwargs: kwargs["check_axioms"] = False
if n <= 1:
associative = True
- super().__init__(self._denormalized_basis(n),
+ super().__init__(self._denormalized_basis(n,field),
self.jordan_product,
self.trace_inner_product,
+ field=field,
associative=associative,
**kwargs)
"""
@classmethod
- def _denormalized_basis(cls, n):
+ def _denormalized_basis(cls, n, field):
"""
Returns a basis for the space of complex Hermitian n-by-n matrices.
sage: set_random_seed()
sage: n = ZZ.random_element(1,5)
- sage: B = ComplexHermitianEJA._denormalized_basis(n)
+ sage: B = ComplexHermitianEJA._denormalized_basis(n,ZZ)
sage: all( M.is_symmetric() for M in B)
True
"""
- field = ZZ
- R = PolynomialRing(field, 'z')
+ R = PolynomialRing(ZZ, 'z')
z = R.gen()
- F = field.extension(z**2 + 1, 'I')
+ F = ZZ.extension(z**2 + 1, 'I')
I = F.gen(1)
# This is like the symmetric case, but we need to be careful:
# "erase" E_ij
Eij[i,j] = 0
- # Since we embedded these, we can drop back to the "field" that we
- # started with instead of the complex extension "F".
+ # Since we embedded the entries, we can drop back to the
+ # desired real "field" instead of the extension "F".
return tuple( s.change_ring(field) for s in S )
- def __init__(self, n, **kwargs):
+ def __init__(self, n, field=AA, **kwargs):
# We know this is a valid EJA, but will double-check
# if the user passes check_axioms=True.
if "check_axioms" not in kwargs: kwargs["check_axioms"] = False
if n <= 1:
associative = True
- super().__init__(self._denormalized_basis(n),
+ super().__init__(self._denormalized_basis(n,field),
self.jordan_product,
self.trace_inner_product,
+ field=field,
associative=associative,
**kwargs)
# TODO: this could be factored out somehow, but is left here
"""
@classmethod
- def _denormalized_basis(cls, n):
+ def _denormalized_basis(cls, n, field):
"""
Returns a basis for the space of quaternion Hermitian n-by-n matrices.
sage: set_random_seed()
sage: n = ZZ.random_element(1,5)
- sage: B = QuaternionHermitianEJA._denormalized_basis(n)
+ sage: B = QuaternionHermitianEJA._denormalized_basis(n,ZZ)
sage: all( M.is_symmetric() for M in B )
True
"""
- field = ZZ
Q = QuaternionAlgebra(QQ,-1,-1)
I,J,K = Q.gens()
# "erase" E_ij
Eij[i,j] = 0
- # Since we embedded these, we can drop back to the "field" that we
- # started with instead of the quaternion algebra "Q".
+ # Since we embedded the entries, we can drop back to the
+ # desired real "field" instead of the quaternion algebra "Q".
return tuple( s.change_ring(field) for s in S )
- def __init__(self, n, **kwargs):
+ def __init__(self, n, field=AA, **kwargs):
# We know this is a valid EJA, but will double-check
# if the user passes check_axioms=True.
if "check_axioms" not in kwargs: kwargs["check_axioms"] = False
if n <= 1:
associative = True
- super().__init__(self._denormalized_basis(n),
+ super().__init__(self._denormalized_basis(n,field),
self.jordan_product,
self.trace_inner_product,
+ field=field,
associative=associative,
**kwargs)
This multiplication table can be verified by hand::
sage: J = HadamardEJA(3)
- sage: e0,e1,e2 = J.gens()
- sage: e0*e0
- e0
- sage: e0*e1
+ sage: b0,b1,b2 = J.gens()
+ sage: b0*b0
+ b0
+ sage: b0*b1
0
- sage: e0*e2
+ sage: b0*b2
0
- sage: e1*e1
- e1
- sage: e1*e2
+ sage: b1*b1
+ b1
+ sage: b1*b2
0
- sage: e2*e2
- e2
+ sage: b2*b2
+ b2
TESTS:
(r0, r1, r2)
"""
- def __init__(self, n, **kwargs):
+ def __init__(self, n, field=AA, **kwargs):
if n == 0:
jordan_product = lambda x,y: x
inner_product = lambda x,y: x
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(ZZ, n).basis() )
+ column_basis = tuple( b.column()
+ for b in FreeModule(field, n).basis() )
super().__init__(column_basis,
jordan_product,
inner_product,
+ field=field,
associative=True,
**kwargs)
self.rank.set_cache(n)
True
"""
- def __init__(self, B, **kwargs):
+ def __init__(self, B, field=AA, **kwargs):
# The matrix "B" is supplied by the user in most cases,
# so it makes sense to check whether or not its positive-
# definite unless we are specifically asked not to...
return P([z0] + zbar.list())
n = B.nrows()
- column_basis = tuple( b.column() for b in FreeModule(ZZ, n).basis() )
+ column_basis = tuple( b.column()
+ for b in FreeModule(field, n).basis() )
# TODO: I haven't actually checked this, but it seems legit.
associative = False
super().__init__(column_basis,
jordan_product,
inner_product,
+ field=field,
associative=associative,
**kwargs)
This multiplication table can be verified by hand::
sage: J = JordanSpinEJA(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
+ sage: b0,b1,b2,b3 = J.gens()
+ sage: b0*b0
+ b0
+ sage: b0*b1
+ b1
+ sage: b0*b2
+ b2
+ sage: b0*b3
+ b3
+ sage: b1*b2
0
- sage: e1*e3
+ sage: b1*b3
0
- sage: e2*e3
+ sage: b2*b3
0
We can change the generator prefix::
True
"""
- def __init__(self, n, **kwargs):
+ def __init__(self, n, *args, **kwargs):
# This is a special case of the BilinearFormEJA with the
# identity matrix as its bilinear form.
B = matrix.identity(ZZ, n)
# But also don't pass check_field=False here, because the user
# can pass in a field!
- super().__init__(B, **kwargs)
+ super().__init__(B, *args, **kwargs)
@staticmethod
def _max_random_instance_size():
sage: J = cartesian_product([J1,cartesian_product([J2,J3])])
sage: J.multiplication_table()
+----++----+----+----+
- | * || e0 | e1 | e2 |
+ | * || b0 | b1 | b2 |
+====++====+====+====+
- | e0 || e0 | 0 | 0 |
+ | b0 || b0 | 0 | 0 |
+----++----+----+----+
- | e1 || 0 | e1 | 0 |
+ | b1 || 0 | b1 | 0 |
+----++----+----+----+
- | e2 || 0 | 0 | e2 |
+ | b2 || 0 | 0 | b2 |
+----++----+----+----+
sage: HadamardEJA(3).multiplication_table()
+----++----+----+----+
- | * || e0 | e1 | e2 |
+ | * || b0 | b1 | b2 |
+====++====+====+====+
- | e0 || e0 | 0 | 0 |
+ | b0 || b0 | 0 | 0 |
+----++----+----+----+
- | e1 || 0 | e1 | 0 |
+ | b1 || 0 | b1 | 0 |
+----++----+----+----+
- | e2 || 0 | 0 | e2 |
+ | b2 || 0 | 0 | b2 |
+----++----+----+----+
TESTS: