-
-class FiniteDimensionalEuclideanJordanAlgebraOperator(Map):
- 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')
-
- F = domain_eja.base_ring()
- if not (F == codomain_eja.base_ring()):
- raise ValueError("domain and codomain must have the same base ring")
-
- # We need to supply something here to avoid getting the
- # default Homset of the parent FiniteDimensionalAlgebra class,
- # which messes up e.g. equality testing. We use FreeModules(F)
- # instead of VectorSpaces(F) because our characteristic polynomial
- # algorithm will need to F to be a polynomial ring at some point.
- # When F is a field, FreeModules(F) returns VectorSpaces(F) anyway.
- parent = Hom(domain_eja, codomain_eja, FreeModules(F))
-
- # The Map initializer will set our parent to a homset, which
- # is explicitly NOT what we want, because these ain't algebra
- # homomorphisms.
- super(FiniteDimensionalEuclideanJordanAlgebraOperator,self).__init__(parent)
-
- # Keep a matrix around to do all of the real work. It would
- # be nice if we could use a VectorSpaceMorphism instead, but
- # those use row vectors that we don't want to accidentally
- # expose to our users.
- self._matrix = mat
-
-
- def _call_(self, x):
- """
- Allow this operator to be called only on elements of an EJA.
-
- EXAMPLES::
-
- sage: J = JordanSpinEJA(3)
- sage: x = J.linear_combination(zip(range(len(J.gens())), J.gens()))
- sage: id = identity_matrix(J.base_ring(), J.dimension())
- sage: f = FiniteDimensionalEuclideanJordanAlgebraOperator(J,J,id)
- sage: f(x) == x
- True
-
- """
- return self.codomain()(self.matrix()*x.vector())
-
-
- def _add_(self, other):
- """
- Add the ``other`` EJA operator to this one.
-
- EXAMPLES:
-
- When we add two EJA operators, we get another one back::
-
- sage: J = RealSymmetricEJA(2)
- sage: id = identity_matrix(J.base_ring(), J.dimension())
- sage: f = FiniteDimensionalEuclideanJordanAlgebraOperator(J,J,id)
- sage: g = FiniteDimensionalEuclideanJordanAlgebraOperator(J,J,id)
- sage: f + g
- Linear operator between finite-dimensional Euclidean Jordan
- algebras represented by the matrix:
- [2 0 0]
- [0 2 0]
- [0 0 2]
- Domain: Euclidean Jordan algebra of degree 3 over Rational Field
- Codomain: Euclidean Jordan algebra of degree 3 over Rational Field
-
- If you try to add two identical vector space operators but on
- different EJAs, that should blow up::
-
- sage: J1 = RealSymmetricEJA(2)
- sage: J2 = JordanSpinEJA(3)
- sage: id = identity_matrix(QQ, 3)
- sage: f = FiniteDimensionalEuclideanJordanAlgebraOperator(J1,J1,id)
- sage: g = FiniteDimensionalEuclideanJordanAlgebraOperator(J2,J2,id)
- sage: f + g
- Traceback (most recent call last):
- ...
- TypeError: unsupported operand parent(s) for +: ...
-
- """
- return FiniteDimensionalEuclideanJordanAlgebraOperator(
- self.domain(),
- self.codomain(),
- self.matrix() + other.matrix())
-
-
- def _composition_(self, other, homset):
- """
- Compose two EJA operators to get another one (and NOT a formal
- composite object) back.
-
- EXAMPLES::
-
- sage: J1 = JordanSpinEJA(3)
- sage: J2 = RealCartesianProductEJA(2)
- sage: J3 = RealSymmetricEJA(1)
- sage: mat1 = matrix(QQ, [[1,2,3],
- ....: [4,5,6]])
- sage: mat2 = matrix(QQ, [[7,8]])
- sage: g = FiniteDimensionalEuclideanJordanAlgebraOperator(J1,
- ....: J2,
- ....: mat1)
- sage: f = FiniteDimensionalEuclideanJordanAlgebraOperator(J2,
- ....: J3,
- ....: mat2)
- sage: f*g
- Linear operator between finite-dimensional Euclidean Jordan
- algebras represented by the matrix:
- [39 54 69]
- Domain: Euclidean Jordan algebra of degree 3 over Rational Field
- Codomain: Euclidean Jordan algebra of degree 1 over Rational Field
-
- """
- return FiniteDimensionalEuclideanJordanAlgebraOperator(
- other.domain(),
- self.codomain(),
- self.matrix()*other.matrix())
-
-
- def __eq__(self, other):
- if self.domain() != other.domain():
- return False
- if self.codomain() != other.codomain():
- return False
- if self.matrix() != other.matrix():
- return False
- return True
-
-
- def __invert__(self):
- """
- Invert this EJA operator.
-
- EXAMPLES::
-
- sage: J = RealSymmetricEJA(2)
- sage: id = identity_matrix(J.base_ring(), J.dimension())
- sage: f = FiniteDimensionalEuclideanJordanAlgebraOperator(J,J,id)
- sage: ~f
- Linear operator between finite-dimensional Euclidean Jordan
- algebras represented by the matrix:
- [1 0 0]
- [0 1 0]
- [0 0 1]
- Domain: Euclidean Jordan algebra of degree 3 over Rational Field
- Codomain: Euclidean Jordan algebra of degree 3 over Rational Field
-
- """
- return FiniteDimensionalEuclideanJordanAlgebraOperator(
- self.codomain(),
- self.domain(),
- ~self.matrix())
-
-
- def __mul__(self, other):
- """
- Compose two EJA operators, or scale myself by an element of the
- ambient vector space.
-
- We need to override the real ``__mul__`` function to prevent the
- coercion framework from throwing an error when it fails to convert
- a base ring element into a morphism.
-
- EXAMPLES:
-
- We can scale an operator on a rational algebra by a rational number::
-
- sage: J = RealSymmetricEJA(2)
- sage: e0,e1,e2 = J.gens()
- sage: x = 2*e0 + 4*e1 + 16*e2
- sage: x.operator()
- Linear operator between finite-dimensional Euclidean Jordan algebras
- represented by the matrix:
- [ 2 4 0]
- [ 2 9 2]
- [ 0 4 16]
- Domain: Euclidean Jordan algebra of degree 3 over Rational Field
- Codomain: Euclidean Jordan algebra of degree 3 over Rational Field
- sage: x.operator()*(1/2)
- Linear operator between finite-dimensional Euclidean Jordan algebras
- represented by the matrix:
- [ 1 2 0]
- [ 1 9/2 1]
- [ 0 2 8]
- Domain: Euclidean Jordan algebra of degree 3 over Rational Field
- Codomain: Euclidean Jordan algebra of degree 3 over Rational Field
-
- """
- if other in self.codomain().base_ring():
- return FiniteDimensionalEuclideanJordanAlgebraOperator(
- self.domain(),
- self.codomain(),
- self.matrix()*other)
-
- # This should eventually delegate to _composition_ after performing
- # some sanity checks for us.
- mor = super(FiniteDimensionalEuclideanJordanAlgebraOperator,self)
- return mor.__mul__(other)
-
-
- def _neg_(self):
- """
- Negate this EJA operator.
-
- EXAMPLES::
-
- sage: J = RealSymmetricEJA(2)
- sage: id = identity_matrix(J.base_ring(), J.dimension())
- sage: f = FiniteDimensionalEuclideanJordanAlgebraOperator(J,J,id)
- sage: -f
- Linear operator between finite-dimensional Euclidean Jordan
- algebras represented by the matrix:
- [-1 0 0]
- [ 0 -1 0]
- [ 0 0 -1]
- Domain: Euclidean Jordan algebra of degree 3 over Rational Field
- Codomain: Euclidean Jordan algebra of degree 3 over Rational Field
-
- """
- return FiniteDimensionalEuclideanJordanAlgebraOperator(
- self.domain(),
- self.codomain(),
- -self.matrix())
-
-
- def __pow__(self, n):
- """
- Raise this EJA operator to the power ``n``.
-
- TESTS:
-
- Ensure that we get back another EJA operator that can be added,
- subtracted, et cetera::
-
- sage: J = RealSymmetricEJA(2)
- sage: id = identity_matrix(J.base_ring(), J.dimension())
- sage: f = FiniteDimensionalEuclideanJordanAlgebraOperator(J,J,id)
- sage: f^0 + f^1 + f^2
- Linear operator between finite-dimensional Euclidean Jordan
- algebras represented by the matrix:
- [3 0 0]
- [0 3 0]
- [0 0 3]
- Domain: Euclidean Jordan algebra of degree 3 over Rational Field
- Codomain: Euclidean Jordan algebra of degree 3 over Rational Field
-
- """
- if (n == 1):
- return self
- elif (n == 0):
- # Raising a vector space morphism to the zero power gives
- # you back a special IdentityMorphism that is useless to us.
- rows = self.codomain().dimension()
- cols = self.domain().dimension()
- mat = matrix.identity(self.base_ring(), rows, cols)
- else:
- mat = self.matrix()**n
-
- return FiniteDimensionalEuclideanJordanAlgebraOperator(
- self.domain(),
- self.codomain(),
- mat)
-
-
- def _repr_(self):
- r"""
-
- A text representation of this linear operator on a Euclidean
- Jordan Algebra.
-
- EXAMPLES::
-
- sage: J = JordanSpinEJA(2)
- sage: id = identity_matrix(J.base_ring(), J.dimension())
- sage: FiniteDimensionalEuclideanJordanAlgebraOperator(J,J,id)
- Linear operator between finite-dimensional Euclidean Jordan
- algebras represented by the matrix:
- [1 0]
- [0 1]
- Domain: Euclidean Jordan algebra of degree 2 over Rational Field
- Codomain: Euclidean Jordan algebra of degree 2 over Rational Field
-
- """
- msg = ("Linear operator between finite-dimensional Euclidean Jordan "
- "algebras represented by the matrix:\n",
- "{!r}\n",
- "Domain: {}\n",
- "Codomain: {}")
- return ''.join(msg).format(self.matrix(),
- self.domain(),
- self.codomain())
-
-
- def _sub_(self, other):
- """
- Subtract ``other`` from this EJA operator.
-
- EXAMPLES::
-
- sage: J = RealSymmetricEJA(2)
- sage: id = identity_matrix(J.base_ring(),J.dimension())
- sage: f = FiniteDimensionalEuclideanJordanAlgebraOperator(J,J,id)
- sage: f - (f*2)
- Linear operator between finite-dimensional Euclidean Jordan
- algebras represented by the matrix:
- [-1 0 0]
- [ 0 -1 0]
- [ 0 0 -1]
- Domain: Euclidean Jordan algebra of degree 3 over Rational Field
- Codomain: Euclidean Jordan algebra of degree 3 over Rational Field
-
- """
- return (self + (-other))
-
-
- def matrix(self):
- """
- Return the matrix representation of this operator with respect
- to the default bases of its (co)domain.
-
- EXAMPLES::
-
- sage: J = RealSymmetricEJA(2)
- sage: mat = matrix(J.base_ring(), J.dimension(), range(9))
- sage: f = FiniteDimensionalEuclideanJordanAlgebraOperator(J,J,mat)
- sage: f.matrix()
- [0 1 2]
- [3 4 5]
- [6 7 8]
-
- """
- return self._matrix
-
-
- def minimal_polynomial(self):
- """
- Return the minimal polynomial of this linear operator,
- in the variable ``t``.
-
- EXAMPLES::
-
- sage: J = RealSymmetricEJA(3)
- sage: J.one().operator().minimal_polynomial()
- t - 1
-
- """
- # The matrix method returns a polynomial in 'x' but want one in 't'.
- return self.matrix().minimal_polynomial().change_variable_name('t')