from sage.categories.map import Map
class FiniteDimensionalEuclideanJordanAlgebraOperator(Map):
+ r"""
+ An operator between two finite-dimensional Euclidean Jordan algebras.
+
+ SETUP::
+
+ sage: from mjo.eja.eja_algebra import HadamardEJA
+ sage: from mjo.eja.eja_operator import FiniteDimensionalEuclideanJordanAlgebraOperator
+
+ EXAMPLES:
+
+ The domain and codomain must be finite-dimensional Euclidean
+ Jordan algebras; if either is not, then an error is raised::
+
+ sage: J = HadamardEJA(3)
+ sage: V = VectorSpace(J.base_ring(), 3)
+ sage: M = matrix.identity(J.base_ring(), 3)
+ sage: FiniteDimensionalEuclideanJordanAlgebraOperator(V,J,M)
+ Traceback (most recent call last):
+ ...
+ TypeError: domain must be a finite-dimensional Euclidean
+ Jordan algebra
+ sage: FiniteDimensionalEuclideanJordanAlgebraOperator(J,V,M)
+ Traceback (most recent call last):
+ ...
+ TypeError: codomain must be a finite-dimensional Euclidean
+ Jordan algebra
+
+ """
+
def __init__(self, domain_eja, codomain_eja, mat):
- # if not (
- # isinstance(domain_eja, FiniteDimensionalEuclideanJordanAlgebra) and
- # isinstance(codomain_eja, FiniteDimensionalEuclideanJordanAlgebra) ):
- # raise ValueError('(co)domains must be finite-dimensional Euclidean '
- # 'Jordan algebras')
+ from mjo.eja.eja_algebra import FiniteDimensionalEuclideanJordanAlgebra
+
+ # I guess we should check this, because otherwise you could
+ # pass in pretty much anything algebraish.
+ if not isinstance(domain_eja,
+ FiniteDimensionalEuclideanJordanAlgebra):
+ raise TypeError('domain must be a finite-dimensional '
+ 'Euclidean Jordan algebra')
+ if not isinstance(codomain_eja,
+ FiniteDimensionalEuclideanJordanAlgebra):
+ raise TypeError('codomain must be a finite-dimensional '
+ 'Euclidean Jordan algebra')
F = domain_eja.base_ring()
if not (F == codomain_eja.base_ring()):
sage: from mjo.eja.eja_operator import FiniteDimensionalEuclideanJordanAlgebraOperator
sage: from mjo.eja.eja_algebra import (
....: JordanSpinEJA,
- ....: RealCartesianProductEJA,
+ ....: HadamardEJA,
....: RealSymmetricEJA)
EXAMPLES::
sage: J1 = JordanSpinEJA(3)
- sage: J2 = RealCartesianProductEJA(2)
+ sage: J2 = HadamardEJA(2)
sage: J3 = RealSymmetricEJA(1)
- sage: mat1 = matrix(QQ, [[1,2,3],
+ sage: mat1 = matrix(AA, [[1,2,3],
....: [4,5,6]])
- sage: mat2 = matrix(QQ, [[7,8]])
+ sage: mat2 = matrix(AA, [[7,8]])
sage: g = FiniteDimensionalEuclideanJordanAlgebraOperator(J1,
....: J2,
....: mat1)
algebras represented by the matrix:
[39 54 69]
Domain: Euclidean Jordan algebra of dimension 3 over
- Rational Field
+ Algebraic Real Field
Codomain: Euclidean Jordan algebra of dimension 1 over
- Rational Field
+ Algebraic Real Field
"""
return FiniteDimensionalEuclideanJordanAlgebraOperator(
[1 0]
[0 1]
Domain: Euclidean Jordan algebra of dimension 2 over
- Rational Field
+ Algebraic Real Field
Codomain: Euclidean Jordan algebra of dimension 2 over
- Rational Field
+ Algebraic Real Field
"""
msg = ("Linear operator between finite-dimensional Euclidean Jordan "
return (self + (-other))
+ def is_self_adjoint(self):
+ r"""
+ Return whether or not this operator is self-adjoint.
+
+ At least in Sage, the fact that the base field is real means
+ that the algebra elements have to be real as well (this is why
+ we embed the complex numbers and quaternions). As a result, the
+ matrix of this operator will contain only real entries, and it
+ suffices to check only symmetry, not conjugate symmetry.
+
+ SETUP::
+
+ sage: from mjo.eja.eja_algebra import (JordanSpinEJA)
+
+ EXAMPLES::
+
+ sage: J = JordanSpinEJA(4)
+ sage: J.one().operator().is_self_adjoint()
+ True
+
+ """
+ return self.matrix().is_symmetric()
+
+
+ def is_zero(self):
+ r"""
+ Return whether or not this map is the zero operator.
+
+ SETUP::
+
+ sage: from mjo.eja.eja_operator import FiniteDimensionalEuclideanJordanAlgebraOperator
+ sage: from mjo.eja.eja_algebra import (random_eja,
+ ....: JordanSpinEJA,
+ ....: RealSymmetricEJA)
+
+ EXAMPLES::
+
+ sage: J1 = JordanSpinEJA(2)
+ sage: J2 = RealSymmetricEJA(2)
+ sage: R = J1.base_ring()
+ sage: M = matrix(R, [ [0, 0],
+ ....: [0, 0],
+ ....: [0, 0] ])
+ sage: L = FiniteDimensionalEuclideanJordanAlgebraOperator(J1,J2,M)
+ sage: L.is_zero()
+ True
+ sage: M = matrix(R, [ [0, 0],
+ ....: [0, 1],
+ ....: [0, 0] ])
+ sage: L = FiniteDimensionalEuclideanJordanAlgebraOperator(J1,J2,M)
+ sage: L.is_zero()
+ False
+
+ TESTS:
+
+ The left-multiplication-by-zero operation on a given algebra
+ is its zero map::
+
+ sage: set_random_seed()
+ sage: J = random_eja()
+ sage: J.zero().operator().is_zero()
+ True
+
+ """
+ return self.matrix().is_zero()
+
+
def inverse(self):
"""
Return the inverse of this operator, if it exists.
sage: idJ.inverse() == idJ
True
- The zero operator is never invertible::
+ The inverse of the inverse is the operator we started with::
sage: set_random_seed()
- sage: J = random_eja()
- sage: J.zero().operator().inverse()
- Traceback (most recent call last):
- ...
- ZeroDivisionError: input matrix must be nonsingular
+ sage: x = random_eja().random_element()
+ sage: L = x.operator()
+ sage: not L.is_invertible() or (L.inverse().inverse() == L)
+ True
"""
return ~self
SETUP::
- sage: from mjo.eja.eja_algebra import RealSymmetricEJA, random_eja
+ sage: from mjo.eja.eja_algebra import (RealSymmetricEJA,
+ ....: TrivialEJA,
+ ....: random_eja)
EXAMPLES::
sage: x.operator().is_invertible()
True
+ The zero operator is invertible in a trivial algebra::
+
+ sage: J = TrivialEJA()
+ sage: J.zero().operator().is_invertible()
+ True
+
TESTS:
The identity operator is always invertible::
sage: J.one().operator().is_invertible()
True
- The zero operator is never invertible::
+ The zero operator is never invertible in a nontrivial algebra::
sage: set_random_seed()
sage: J = random_eja()
- sage: J.zero().operator().is_invertible()
+ sage: not J.is_trivial() and J.zero().operator().is_invertible()
False
"""
EXAMPLES::
- sage: J = RealSymmetricEJA(4,AA)
+ sage: J = RealSymmetricEJA(4)
sage: x = sum(J.gens())
sage: A = x.subalgebra_generated_by(orthonormalize_basis=True)
sage: L0x = A(x).operator()
self.codomain(),
mat)
projectors.append(Pi)
- return zip(eigenvalues, projectors)
+ return list(zip(eigenvalues, projectors))