It turns out that the FiniteDimensionalAlgebrasWithBasis category
somehow has both the legacy Algebras() category and the newer
MagmaticAlgebras() category as super-categories. Problem is, the
legacy one is associative! To fix that, we now use MagmaticAlgebras
directly.
Of course, we have to reimplement some of the stuff that was done for
us before... and we have to add a bunch of hacks for parts of Sage
that break when you don't have a ring.... and we can't use a matrix
for our multiplication table any more. But it was all doable.
"""
from sage.algebras.quatalg.quaternion_algebra import QuaternionAlgebra
"""
from sage.algebras.quatalg.quaternion_algebra import QuaternionAlgebra
-from sage.categories.finite_dimensional_algebras_with_basis import FiniteDimensionalAlgebrasWithBasis
+from sage.categories.magmatic_algebras import MagmaticAlgebras
from sage.combinat.free_module import CombinatorialFreeModule
from sage.matrix.constructor import matrix
from sage.misc.cachefunc import cached_method
from sage.misc.prandom import choice
from sage.combinat.free_module import CombinatorialFreeModule
from sage.matrix.constructor import matrix
from sage.misc.cachefunc import cached_method
from sage.misc.prandom import choice
+from sage.misc.table import table
from sage.modules.free_module import VectorSpace
from sage.rings.integer_ring import ZZ
from sage.rings.number_field.number_field import QuadraticField
from sage.modules.free_module import VectorSpace
from sage.rings.integer_ring import ZZ
from sage.rings.number_field.number_field import QuadraticField
from mjo.eja.eja_utils import _mat2vec
class FiniteDimensionalEuclideanJordanAlgebra(CombinatorialFreeModule):
from mjo.eja.eja_utils import _mat2vec
class FiniteDimensionalEuclideanJordanAlgebra(CombinatorialFreeModule):
+ # This is an ugly hack needed to prevent the category framework
+ # from implementing a coercion from our base ring (e.g. the
+ # rationals) into the algebra. First of all -- such a coercion is
+ # nonsense to begin with. But more importantly, it tries to do so
+ # in the category of rings, and since our algebras aren't
+ # associative they generally won't be rings.
+ _no_generic_basering_coercion = True
+
def __init__(self,
field,
mult_table,
def __init__(self,
field,
mult_table,
self._natural_basis = natural_basis
if category is None:
self._natural_basis = natural_basis
if category is None:
- category = FiniteDimensionalAlgebrasWithBasis(field).Unital()
+ category = MagmaticAlgebras(field).FiniteDimensional()
+ category = category.WithBasis().Unital()
+
fda = super(FiniteDimensionalEuclideanJordanAlgebra, self)
fda.__init__(field,
range(len(mult_table)),
fda = super(FiniteDimensionalEuclideanJordanAlgebra, self)
fda.__init__(field,
range(len(mult_table)),
+ if elt == 0:
+ # The superclass implementation of random_element()
+ # needs to be able to coerce "0" into the algebra.
+ return self.zero()
+
natural_basis = self.natural_basis()
if elt not in natural_basis[0].matrix_space():
raise ValueError("not a naturally-represented algebra element")
natural_basis = self.natural_basis()
if elt not in natural_basis[0].matrix_space():
raise ValueError("not a naturally-represented algebra element")
def multiplication_table(self):
"""
def multiplication_table(self):
"""
- Return a readable matrix representation of this algebra's
- multiplication table. The (i,j)th entry in the matrix contains
- the product of the ith basis element with the jth.
-
- This is not extraordinarily useful, but it overrides a superclass
- method that would otherwise just crash and complain about the
- algebra being infinite.
+ Return a visual representation of this algebra's multiplication
+ table (on basis elements).
- sage: from mjo.eja.eja_algebra import (JordanSpinEJA,
- ....: RealCartesianProductEJA)
+ sage: from mjo.eja.eja_algebra import JordanSpinEJA
- sage: J = RealCartesianProductEJA(3)
- sage: J.multiplication_table()
- [e0 0 0]
- [ 0 e1 0]
- [ 0 0 e2]
-
- ::
-
- sage: J = JordanSpinEJA(3)
+ sage: J = JordanSpinEJA(4)
sage: J.multiplication_table()
sage: J.multiplication_table()
- [e0 e1 e2]
- [e1 e0 0]
- [e2 0 e0]
+ +----++----+----+----+----+
+ | * || e0 | e1 | e2 | e3 |
+ +====++====+====+====+====+
+ | e0 || e0 | e1 | e2 | e3 |
+ +----++----+----+----+----+
+ | e1 || e1 | e0 | 0 | 0 |
+ +----++----+----+----+----+
+ | e2 || e2 | 0 | e0 | 0 |
+ +----++----+----+----+----+
+ | e3 || e3 | 0 | 0 | e0 |
+ +----++----+----+----+----+
- return matrix(self._multiplication_table)
+ M = list(self._multiplication_table) # copy
+ for i in range(len(M)):
+ # M had better be "square"
+ M[i] = [self.monomial(i)] + M[i]
+ M = [["*"] + list(self.gens())] + M
+ return table(M, header_row=True, header_column=True, frame=True)
- zero = self.parent().zero()
+ # In fact, we only need to know if the constant term is non-zero,
+ # so we can pass in the field's zero element instead.
+ zero = self.base_ring().zero()
p = self.minimal_polynomial()
return not (p(zero) == zero)
p = self.minimal_polynomial()
return not (p(zero) == zero)
+ left_mult_by_self = lambda y: self*y
+ L = P.module_morphism(function=left_mult_by_self, codomain=P)
return FiniteDimensionalEuclideanJordanAlgebraOperator(
P,
P,
return FiniteDimensionalEuclideanJordanAlgebraOperator(
P,
P,
def quadratic_representation(self, other=None):
def quadratic_representation(self, other=None):
+ if elt == 0:
+ # Just as in the superalgebra class, we need to hack
+ # this special case to ensure that random_element() can
+ # coerce a ring zero into the algebra.
+ return self.zero()
+
if elt in self.superalgebra():
coords = self.vector_space().coordinate_vector(elt.to_vector())
return self.from_vector(coords)
if elt in self.superalgebra():
coords = self.vector_space().coordinate_vector(elt.to_vector())
return self.from_vector(coords)