1 from sage
.matrix
.constructor
import matrix
2 from sage
.categories
.all
import FreeModules
3 from sage
.categories
.map import Map
5 class FiniteDimensionalEuclideanJordanAlgebraOperator(Map
):
6 def __init__(self
, domain_eja
, codomain_eja
, mat
):
8 # isinstance(domain_eja, FiniteDimensionalEuclideanJordanAlgebra) and
9 # isinstance(codomain_eja, FiniteDimensionalEuclideanJordanAlgebra) ):
10 # raise ValueError('(co)domains must be finite-dimensional Euclidean '
13 F
= domain_eja
.base_ring()
14 if not (F
== codomain_eja
.base_ring()):
15 raise ValueError("domain and codomain must have the same base ring")
17 # We need to supply something here to avoid getting the
18 # default Homset of the parent FiniteDimensionalAlgebra class,
19 # which messes up e.g. equality testing. We use FreeModules(F)
20 # instead of VectorSpaces(F) because our characteristic polynomial
21 # algorithm will need to F to be a polynomial ring at some point.
22 # When F is a field, FreeModules(F) returns VectorSpaces(F) anyway.
23 parent
= domain_eja
.Hom(codomain_eja
, FreeModules(F
))
25 # The Map initializer will set our parent to a homset, which
26 # is explicitly NOT what we want, because these ain't algebra
28 super(FiniteDimensionalEuclideanJordanAlgebraOperator
,self
).__init
__(parent
)
30 # Keep a matrix around to do all of the real work. It would
31 # be nice if we could use a VectorSpaceMorphism instead, but
32 # those use row vectors that we don't want to accidentally
33 # expose to our users.
39 Allow this operator to be called only on elements of an EJA.
43 sage: from mjo.eja.eja_operator import FiniteDimensionalEuclideanJordanAlgebraOperator
44 sage: from mjo.eja.eja_algebra import JordanSpinEJA
48 sage: J = JordanSpinEJA(3)
49 sage: x = J.linear_combination(zip(range(len(J.gens())), J.gens()))
50 sage: id = identity_matrix(J.base_ring(), J.dimension())
51 sage: f = FiniteDimensionalEuclideanJordanAlgebraOperator(J,J,id)
56 return self
.codomain()(self
.matrix()*x
.vector())
59 def _add_(self
, other
):
61 Add the ``other`` EJA operator to this one.
65 sage: from mjo.eja.eja_operator import FiniteDimensionalEuclideanJordanAlgebraOperator
66 sage: from mjo.eja.eja_algebra import (
68 ....: RealSymmetricEJA )
72 When we add two EJA operators, we get another one back::
74 sage: J = RealSymmetricEJA(2)
75 sage: id = identity_matrix(J.base_ring(), J.dimension())
76 sage: f = FiniteDimensionalEuclideanJordanAlgebraOperator(J,J,id)
77 sage: g = FiniteDimensionalEuclideanJordanAlgebraOperator(J,J,id)
79 Linear operator between finite-dimensional Euclidean Jordan
80 algebras represented by the matrix:
84 Domain: Euclidean Jordan algebra of degree 3 over Rational Field
85 Codomain: Euclidean Jordan algebra of degree 3 over Rational Field
87 If you try to add two identical vector space operators but on
88 different EJAs, that should blow up::
90 sage: J1 = RealSymmetricEJA(2)
91 sage: J2 = JordanSpinEJA(3)
92 sage: id = identity_matrix(QQ, 3)
93 sage: f = FiniteDimensionalEuclideanJordanAlgebraOperator(J1,J1,id)
94 sage: g = FiniteDimensionalEuclideanJordanAlgebraOperator(J2,J2,id)
96 Traceback (most recent call last):
98 TypeError: unsupported operand parent(s) for +: ...
101 return FiniteDimensionalEuclideanJordanAlgebraOperator(
104 self
.matrix() + other
.matrix())
107 def _composition_(self
, other
, homset
):
109 Compose two EJA operators to get another one (and NOT a formal
110 composite object) back.
114 sage: from mjo.eja.eja_operator import FiniteDimensionalEuclideanJordanAlgebraOperator
115 sage: from mjo.eja.eja_algebra import (
117 ....: RealCartesianProductEJA,
118 ....: RealSymmetricEJA)
122 sage: J1 = JordanSpinEJA(3)
123 sage: J2 = RealCartesianProductEJA(2)
124 sage: J3 = RealSymmetricEJA(1)
125 sage: mat1 = matrix(QQ, [[1,2,3],
127 sage: mat2 = matrix(QQ, [[7,8]])
128 sage: g = FiniteDimensionalEuclideanJordanAlgebraOperator(J1,
131 sage: f = FiniteDimensionalEuclideanJordanAlgebraOperator(J2,
135 Linear operator between finite-dimensional Euclidean Jordan
136 algebras represented by the matrix:
138 Domain: Euclidean Jordan algebra of degree 3 over Rational Field
139 Codomain: Euclidean Jordan algebra of degree 1 over Rational Field
142 return FiniteDimensionalEuclideanJordanAlgebraOperator(
145 self
.matrix()*other
.matrix())
148 def __eq__(self
, other
):
149 if self
.domain() != other
.domain():
151 if self
.codomain() != other
.codomain():
153 if self
.matrix() != other
.matrix():
158 def __invert__(self
):
160 Invert this EJA operator.
164 sage: from mjo.eja.eja_operator import FiniteDimensionalEuclideanJordanAlgebraOperator
165 sage: from mjo.eja.eja_algebra import RealSymmetricEJA
169 sage: J = RealSymmetricEJA(2)
170 sage: id = identity_matrix(J.base_ring(), J.dimension())
171 sage: f = FiniteDimensionalEuclideanJordanAlgebraOperator(J,J,id)
173 Linear operator between finite-dimensional Euclidean Jordan
174 algebras represented by the matrix:
178 Domain: Euclidean Jordan algebra of degree 3 over Rational Field
179 Codomain: Euclidean Jordan algebra of degree 3 over Rational Field
182 return FiniteDimensionalEuclideanJordanAlgebraOperator(
188 def __mul__(self
, other
):
190 Compose two EJA operators, or scale myself by an element of the
191 ambient vector space.
193 We need to override the real ``__mul__`` function to prevent the
194 coercion framework from throwing an error when it fails to convert
195 a base ring element into a morphism.
199 sage: from mjo.eja.eja_operator import FiniteDimensionalEuclideanJordanAlgebraOperator
200 sage: from mjo.eja.eja_algebra import RealSymmetricEJA
204 We can scale an operator on a rational algebra by a rational number::
206 sage: J = RealSymmetricEJA(2)
207 sage: e0,e1,e2 = J.gens()
208 sage: x = 2*e0 + 4*e1 + 16*e2
210 Linear operator between finite-dimensional Euclidean Jordan algebras
211 represented by the matrix:
215 Domain: Euclidean Jordan algebra of degree 3 over Rational Field
216 Codomain: Euclidean Jordan algebra of degree 3 over Rational Field
217 sage: x.operator()*(1/2)
218 Linear operator between finite-dimensional Euclidean Jordan algebras
219 represented by the matrix:
223 Domain: Euclidean Jordan algebra of degree 3 over Rational Field
224 Codomain: Euclidean Jordan algebra of degree 3 over Rational Field
227 if other
in self
.codomain().base_ring():
228 return FiniteDimensionalEuclideanJordanAlgebraOperator(
233 # This should eventually delegate to _composition_ after performing
234 # some sanity checks for us.
235 mor
= super(FiniteDimensionalEuclideanJordanAlgebraOperator
,self
)
236 return mor
.__mul
__(other
)
241 Negate this EJA operator.
245 sage: from mjo.eja.eja_operator import FiniteDimensionalEuclideanJordanAlgebraOperator
246 sage: from mjo.eja.eja_algebra import RealSymmetricEJA
250 sage: J = RealSymmetricEJA(2)
251 sage: id = identity_matrix(J.base_ring(), J.dimension())
252 sage: f = FiniteDimensionalEuclideanJordanAlgebraOperator(J,J,id)
254 Linear operator between finite-dimensional Euclidean Jordan
255 algebras represented by the matrix:
259 Domain: Euclidean Jordan algebra of degree 3 over Rational Field
260 Codomain: Euclidean Jordan algebra of degree 3 over Rational Field
263 return FiniteDimensionalEuclideanJordanAlgebraOperator(
269 def __pow__(self
, n
):
271 Raise this EJA operator to the power ``n``.
275 sage: from mjo.eja.eja_operator import FiniteDimensionalEuclideanJordanAlgebraOperator
276 sage: from mjo.eja.eja_algebra import RealSymmetricEJA
280 Ensure that we get back another EJA operator that can be added,
281 subtracted, et cetera::
283 sage: J = RealSymmetricEJA(2)
284 sage: id = identity_matrix(J.base_ring(), J.dimension())
285 sage: f = FiniteDimensionalEuclideanJordanAlgebraOperator(J,J,id)
286 sage: f^0 + f^1 + f^2
287 Linear operator between finite-dimensional Euclidean Jordan
288 algebras represented by the matrix:
292 Domain: Euclidean Jordan algebra of degree 3 over Rational Field
293 Codomain: Euclidean Jordan algebra of degree 3 over Rational Field
299 # Raising a vector space morphism to the zero power gives
300 # you back a special IdentityMorphism that is useless to us.
301 rows
= self
.codomain().dimension()
302 cols
= self
.domain().dimension()
303 mat
= matrix
.identity(self
.base_ring(), rows
, cols
)
305 mat
= self
.matrix()**n
307 return FiniteDimensionalEuclideanJordanAlgebraOperator(
316 A text representation of this linear operator on a Euclidean
321 sage: from mjo.eja.eja_operator import FiniteDimensionalEuclideanJordanAlgebraOperator
322 sage: from mjo.eja.eja_algebra import JordanSpinEJA
326 sage: J = JordanSpinEJA(2)
327 sage: id = identity_matrix(J.base_ring(), J.dimension())
328 sage: FiniteDimensionalEuclideanJordanAlgebraOperator(J,J,id)
329 Linear operator between finite-dimensional Euclidean Jordan
330 algebras represented by the matrix:
333 Domain: Euclidean Jordan algebra of degree 2 over Rational Field
334 Codomain: Euclidean Jordan algebra of degree 2 over Rational Field
337 msg
= ("Linear operator between finite-dimensional Euclidean Jordan "
338 "algebras represented by the matrix:\n",
342 return ''.join(msg
).format(self
.matrix(),
347 def _sub_(self
, other
):
349 Subtract ``other`` from this EJA operator.
353 sage: from mjo.eja.eja_operator import FiniteDimensionalEuclideanJordanAlgebraOperator
354 sage: from mjo.eja.eja_algebra import RealSymmetricEJA
358 sage: J = RealSymmetricEJA(2)
359 sage: id = identity_matrix(J.base_ring(),J.dimension())
360 sage: f = FiniteDimensionalEuclideanJordanAlgebraOperator(J,J,id)
362 Linear operator between finite-dimensional Euclidean Jordan
363 algebras represented by the matrix:
367 Domain: Euclidean Jordan algebra of degree 3 over Rational Field
368 Codomain: Euclidean Jordan algebra of degree 3 over Rational Field
371 return (self
+ (-other
))
376 Return the matrix representation of this operator with respect
377 to the default bases of its (co)domain.
381 sage: from mjo.eja.eja_operator import FiniteDimensionalEuclideanJordanAlgebraOperator
382 sage: from mjo.eja.eja_algebra import RealSymmetricEJA
386 sage: J = RealSymmetricEJA(2)
387 sage: mat = matrix(J.base_ring(), J.dimension(), range(9))
388 sage: f = FiniteDimensionalEuclideanJordanAlgebraOperator(J,J,mat)
398 def minimal_polynomial(self
):
400 Return the minimal polynomial of this linear operator,
401 in the variable ``t``.
405 sage: from mjo.eja.eja_operator import FiniteDimensionalEuclideanJordanAlgebraOperator
406 sage: from mjo.eja.eja_algebra import RealSymmetricEJA
410 sage: J = RealSymmetricEJA(3)
411 sage: J.one().operator().minimal_polynomial()
415 # The matrix method returns a polynomial in 'x' but want one in 't'.
416 return self
.matrix().minimal_polynomial().change_variable_name('t')