def __classcall_private__(cls,
field,
mult_table,
+ rank,
names='e',
assume_associative=False,
category=None,
- rank=None,
natural_basis=None):
n = len(mult_table)
mult_table = [b.base_extend(field) for b in mult_table]
return fda.__classcall__(cls,
field,
mult_table,
+ rank=rank,
assume_associative=assume_associative,
names=names,
category=cat,
- rank=rank,
natural_basis=natural_basis)
def __init__(self,
field,
mult_table,
+ rank,
names='e',
assume_associative=False,
category=None,
- rank=None,
natural_basis=None):
"""
SETUP::
def rank(self):
"""
Return the rank of this EJA.
+
+ ALGORITHM:
+
+ The author knows of no algorithm to compute the rank of an EJA
+ where only the multiplication table is known. In lieu of one, we
+ require the rank to be specified when the algebra is created,
+ and simply pass along that number here.
+
+ SETUP::
+
+ sage: from mjo.eja.eja_algebra import (JordanSpinEJA,
+ ....: RealSymmetricEJA,
+ ....: ComplexHermitianEJA,
+ ....: QuaternionHermitianEJA,
+ ....: random_eja)
+
+ EXAMPLES:
+
+ The rank of the Jordan spin algebra is always two::
+
+ sage: JordanSpinEJA(2).rank()
+ 2
+ sage: JordanSpinEJA(3).rank()
+ 2
+ sage: JordanSpinEJA(4).rank()
+ 2
+
+ The rank of the `n`-by-`n` Hermitian real, complex, or
+ quaternion matrices is `n`::
+
+ sage: RealSymmetricEJA(2).rank()
+ 2
+ sage: ComplexHermitianEJA(2).rank()
+ 2
+ sage: QuaternionHermitianEJA(2).rank()
+ 2
+ sage: RealSymmetricEJA(5).rank()
+ 5
+ sage: ComplexHermitianEJA(5).rank()
+ 5
+ sage: QuaternionHermitianEJA(5).rank()
+ 5
+
+ TESTS:
+
+ Ensure that every EJA that we know how to construct has a
+ positive integer rank::
+
+ sage: set_random_seed()
+ sage: r = random_eja().rank()
+ sage: r in ZZ and r > 0
+ True
+
"""
- if self._rank is None:
- raise ValueError("no rank specified at genesis")
- else:
- return self._rank
+ return self._rank
def vector_space(self):
SETUP::
- sage: from mjo.eja.eja_algebra import RealSymmetricEJA
+ sage: from mjo.eja.eja_algebra import (RealSymmetricEJA,
+ ....: random_eja)
EXAMPLES:
...
ArithmeticError: vector is not in free module
+ TESTS:
+
+ Ensure that we can convert any element of the parent's
+ underlying vector space back into an algebra element whose
+ vector representation is what we started with::
+
+ sage: set_random_seed()
+ sage: J = random_eja()
+ sage: v = J.vector_space().random_element()
+ sage: J(v).vector() == v
+ True
+
"""
# Goal: if we're given a matrix, and if it lives in our
# parent algebra's "natural ambient space," convert it
Jordan algebras are always power-associative; see for
example Faraut and Koranyi, Proposition II.1.2 (ii).
- .. WARNING:
-
- We have to override this because our superclass uses row vectors
- instead of column vectors! We, on the other hand, assume column
- vectors everywhere.
+ We have to override this because our superclass uses row
+ vectors instead of column vectors! We, on the other hand,
+ assume column vectors everywhere.
SETUP::
sage: from mjo.eja.eja_algebra import random_eja
- EXAMPLES::
+ TESTS:
+
+ The definition of `x^2` is the unambiguous `x*x`::
sage: set_random_seed()
sage: x = random_eja().random_element()
- sage: x.operator()(x) == (x^2)
+ sage: x*x == (x^2)
True
A few examples of power-associativity::
sage: J.zero().characteristic_polynomial()
t^3
+ TESTS:
+
The characteristic polynomial of an element should evaluate
to zero on that element::
sage: lhs == rhs
True
- Test the first polarization identity from my notes, Koecher Chapter
- III, or from Baes (2.3)::
+ Test the first polarization identity from my notes, Koecher
+ Chapter III, or from Baes (2.3)::
sage: set_random_seed()
sage: J = random_eja()
"""
Return whether or not this element is invertible.
- We can't use the superclass method because it relies on
- the algebra being associative.
-
ALGORITHM:
The usual way to do this is to check if the determinant is
whether or not the paren't algebra's zero element is a root
of this element's minimal polynomial.
+ Beware that we can't use the superclass method, because it
+ relies on the algebra being associative.
+
SETUP::
sage: from mjo.eja.eja_algebra import random_eja
"""
Return whether or not some power of this element is zero.
- The superclass method won't work unless we're in an
- associative algebra, and we aren't. However, we generate
- an assocoative subalgebra and we're nilpotent there if and
- only if we're nilpotent here (probably).
+ ALGORITHM:
+
+ We use Theorem 5 in Chapter III of Koecher, which says that
+ an element ``x`` is nilpotent if and only if ``x.operator()``
+ is nilpotent. And it is a basic fact of linear algebra that
+ an operator on an `n`-dimensional space is nilpotent if and
+ only if, when raised to the `n`th power, it equals the zero
+ operator (for example, see Axler Corollary 8.8).
SETUP::
- sage: from mjo.eja.eja_algebra import random_eja
+ sage: from mjo.eja.eja_algebra import (JordanSpinEJA,
+ ....: random_eja)
+
+ EXAMPLES::
+
+ sage: J = JordanSpinEJA(3)
+ sage: x = sum(J.gens())
+ sage: x.is_nilpotent()
+ False
TESTS:
True
"""
- # The element we're going to call "is_nilpotent()" on.
- # Either myself, interpreted as an element of a finite-
- # dimensional algebra, or an element of an associative
- # subalgebra.
- elt = None
-
- if self.parent().is_associative():
- elt = FiniteDimensionalAlgebraElement(self.parent(), self)
- else:
- V = self.span_of_powers()
- assoc_subalg = self.subalgebra_generated_by()
- # Mis-design warning: the basis used for span_of_powers()
- # and subalgebra_generated_by() must be the same, and in
- # the same order!
- elt = assoc_subalg(V.coordinates(self.vector()))
-
- # Recursive call, but should work since elt lives in an
- # associative algebra.
- return elt.is_nilpotent()
+ P = self.parent()
+ zero_operator = P.zero().operator()
+ return self.operator()**P.dimension() == zero_operator
def is_regular(self):
# are power-associative.
#
# TODO: choose generator names intelligently.
- return FiniteDimensionalEuclideanJordanAlgebra(F, mats, assume_associative=True, names='f')
+ #
+ # The rank is the highest possible degree of a minimal polynomial,
+ # and is bounded above by the dimension. We know in this case that
+ # there's an element whose minimal polynomial has the same degree
+ # as the space's dimension, so that must be its rank too.
+ return FiniteDimensionalEuclideanJordanAlgebra(
+ F,
+ mats,
+ V.dimension(),
+ assume_associative=True,
+ names='f')
def subalgebra_idempotent(self):