1 from sage
.matrix
.constructor
import matrix
2 from sage
.misc
.cachefunc
import cached_method
4 from mjo
.eja
.eja_algebra
import EJA
5 from mjo
.eja
.eja_element
import (EJAElement
,
6 CartesianProductParentEJAElement
)
8 class EJASubalgebraElement(EJAElement
):
12 sage: from mjo.eja.eja_algebra import random_eja
16 The matrix representation of an element in the subalgebra is
17 the same as its matrix representation in the superalgebra::
19 sage: x = random_eja(field=QQ,orthonormalize=False).random_element()
20 sage: A = x.subalgebra_generated_by(orthonormalize=False)
21 sage: y = A.random_element()
22 sage: actual = y.to_matrix()
23 sage: expected = y.superalgebra_element().to_matrix()
24 sage: actual == expected
27 The left-multiplication-by operator for elements in the subalgebra
28 works like it does in the superalgebra, even if we orthonormalize
31 sage: x = random_eja(field=AA).random_element() # long time
32 sage: A = x.subalgebra_generated_by(orthonormalize=True) # long time
33 sage: y = A.random_element() # long time
34 sage: y.operator()(A.one()) == y # long time
39 def superalgebra_element(self
):
41 Return the object in our algebra's superalgebra that corresponds
46 sage: from mjo.eja.eja_algebra import (RealSymmetricEJA,
51 sage: J = RealSymmetricEJA(3)
52 sage: x = sum(J.gens())
54 b0 + b1 + b2 + b3 + b4 + b5
55 sage: A = x.subalgebra_generated_by(orthonormalize=False)
58 sage: A(x).superalgebra_element()
59 b0 + b1 + b2 + b3 + b4 + b5
60 sage: y = sum(A.gens())
63 sage: B = y.subalgebra_generated_by(orthonormalize=False)
66 sage: B(y).superalgebra_element()
71 We can convert back and forth faithfully::
73 sage: J = random_eja(field=QQ, orthonormalize=False)
74 sage: x = J.random_element()
75 sage: A = x.subalgebra_generated_by(orthonormalize=False)
76 sage: A(x).superalgebra_element() == x
78 sage: y = A.random_element()
79 sage: A(y.superalgebra_element()) == y
81 sage: B = y.subalgebra_generated_by(orthonormalize=False)
82 sage: B(y).superalgebra_element() == y
86 return self
.parent().superalgebra_embedding()(self
)
91 class EJASubalgebra(EJA
):
93 A subalgebra of an EJA with a given basis.
97 sage: from mjo.eja.eja_algebra import (ComplexHermitianEJA,
99 ....: RealSymmetricEJA)
100 sage: from mjo.eja.eja_subalgebra import EJASubalgebra
104 The following Peirce subalgebras of the 2-by-2 real symmetric
105 matrices do not contain the superalgebra's identity element::
107 sage: J = RealSymmetricEJA(2)
108 sage: E11 = matrix(AA, [ [1,0],
110 sage: E22 = matrix(AA, [ [0,0],
112 sage: K1 = EJASubalgebra(J, (J(E11),), associative=True)
113 sage: K1.one().to_matrix()
116 sage: K2 = EJASubalgebra(J, (J(E22),), associative=True)
117 sage: K2.one().to_matrix()
123 Ensure that our generator names don't conflict with the
126 sage: J = JordanSpinEJA(3)
127 sage: J.one().subalgebra_generated_by().gens()
129 sage: J = JordanSpinEJA(3, prefix='f')
130 sage: J.one().subalgebra_generated_by().gens()
132 sage: J = JordanSpinEJA(3, prefix='a')
133 sage: J.one().subalgebra_generated_by().gens()
136 Ensure that we can find subalgebras of subalgebras::
138 sage: A = ComplexHermitianEJA(3).one().subalgebra_generated_by()
139 sage: B = A.one().subalgebra_generated_by()
143 def __init__(self
, superalgebra
, basis
, **kwargs
):
144 self
._superalgebra
= superalgebra
145 V
= self
._superalgebra
.vector_space()
146 field
= self
._superalgebra
.base_ring()
148 # A half-assed attempt to ensure that we don't collide with
149 # the superalgebra's prefix (ignoring the fact that there
150 # could be super-superelgrbas in scope). If possible, we
151 # try to "increment" the parent algebra's prefix, although
152 # this idea goes out the window fast because some prefixen
154 prefixen
= ["b","c","d","e","f","g","h","l","m"]
156 prefix
= prefixen
[prefixen
.index(self
._superalgebra
.prefix()) + 1]
160 # The superalgebra constructor expects these to be in original matrix
161 # form, not algebra-element form.
162 matrix_basis
= tuple( b
.to_matrix() for b
in basis
)
163 def jordan_product(x
,y
):
164 return (self
._superalgebra
(x
)*self
._superalgebra
(y
)).to_matrix()
166 def inner_product(x
,y
):
167 return self
._superalgebra
(x
).inner_product(self
._superalgebra
(y
))
169 super().__init
__(matrix_basis
,
173 matrix_space
=superalgebra
.matrix_space(),
179 def _element_constructor_(self
, elt
):
181 Construct an element of this subalgebra from the given one.
182 The only valid arguments are elements of the parent algebra
183 that happen to live in this subalgebra.
187 sage: from mjo.eja.eja_algebra import RealSymmetricEJA
188 sage: from mjo.eja.eja_subalgebra import EJASubalgebra
192 sage: J = RealSymmetricEJA(3)
193 sage: X = matrix(AA, [ [0,0,1],
197 sage: basis = ( x, x^2 ) # x^2 is the identity matrix
198 sage: K = EJASubalgebra(J,
200 ....: associative=True,
201 ....: orthonormalize=False)
210 if elt
in self
.superalgebra():
211 # If the subalgebra is trivial, its _matrix_span will be empty
212 # but we still want to be able convert the superalgebra's zero()
213 # element into the subalgebra's zero() element. There's no great
214 # workaround for this because sage checks that your basis is
215 # linearly-independent everywhere, so we can't just give it a
216 # basis consisting of the zero element.
218 if self
.is_trivial() and m
.is_zero():
221 return super()._element
_constructor
_(m
)
223 return super()._element
_constructor
_(elt
)
226 def superalgebra(self
):
228 Return the superalgebra that this algebra was generated from.
230 return self
._superalgebra
234 def superalgebra_embedding(self
):
236 Return the embedding from this subalgebra into the superalgebra.
240 sage: from mjo.eja.eja_algebra import HadamardEJA
244 sage: J = HadamardEJA(4)
245 sage: A = J.one().subalgebra_generated_by()
246 sage: iota = A.superalgebra_embedding()
248 Linear operator between finite-dimensional Euclidean Jordan algebras represented by the matrix:
253 Domain: Euclidean Jordan algebra of dimension 1 over Algebraic Real Field
254 Codomain: Euclidean Jordan algebra of dimension 4 over Algebraic Real Field
255 sage: iota(A.one()) == J.one()
259 from mjo
.eja
.eja_operator
import EJAOperator
260 mm
= self
._module
_morphism
(lambda j
: self
.superalgebra()(self
.monomial(j
).to_matrix()),
261 codomain
=self
.superalgebra())
262 return EJAOperator(self
,
268 Element
= EJASubalgebraElement
272 class CartesianProductEJASubalgebraElement(EJASubalgebraElement
,
273 CartesianProductParentEJAElement
):
275 The class for elements that both belong to a subalgebra and
276 have a Cartesian product algebra as their parent. By inheriting
277 :class:`CartesianProductParentEJAElement` in addition to
278 :class:`EJASubalgebraElement`, we allow the
279 ``to_matrix()`` method to be overridden with the version that
280 works on Cartesian products.
284 sage: from mjo.eja.eja_algebra import (HadamardEJA,
285 ....: RealSymmetricEJA)
289 This used to fail when ``subalgebra_idempotent()`` tried to
290 embed the subalgebra element back into the original EJA::
292 sage: J1 = HadamardEJA(0, field=QQ, orthonormalize=False)
293 sage: J2 = RealSymmetricEJA(2, field=QQ, orthonormalize=False)
294 sage: J = cartesian_product([J1,J2])
295 sage: J.one().subalgebra_idempotent() == J.one()
301 class CartesianProductEJASubalgebra(EJASubalgebra
):
303 Subalgebras whose parents are Cartesian products. Exists only
304 to specify a special element class that will (in addition)
305 inherit from ``CartesianProductParentEJAElement``.
307 Element
= CartesianProductEJASubalgebraElement