]> gitweb.michael.orlitzky.com - sage.d.git/blob - mjo/eja/eja_subalgebra.py
eja: add more "# long time" markers.
[sage.d.git] / mjo / eja / eja_subalgebra.py
1 from sage.matrix.constructor import matrix
2 from sage.misc.cachefunc import cached_method
3
4 from mjo.eja.eja_algebra import FiniteDimensionalEJA
5 from mjo.eja.eja_element import FiniteDimensionalEJAElement
6
7 class FiniteDimensionalEJASubalgebraElement(FiniteDimensionalEJAElement):
8 """
9 SETUP::
10
11 sage: from mjo.eja.eja_algebra import random_eja
12
13 TESTS::
14
15 The matrix representation of an element in the subalgebra is
16 the same as its matrix representation in the superalgebra::
17
18 sage: x = random_eja(field=QQ,orthonormalize=False).random_element()
19 sage: A = x.subalgebra_generated_by(orthonormalize=False)
20 sage: y = A.random_element()
21 sage: actual = y.to_matrix()
22 sage: expected = y.superalgebra_element().to_matrix()
23 sage: actual == expected
24 True
25
26 The left-multiplication-by operator for elements in the subalgebra
27 works like it does in the superalgebra, even if we orthonormalize
28 our basis::
29
30 sage: x = random_eja(field=AA).random_element() # long time
31 sage: A = x.subalgebra_generated_by(orthonormalize=True) # long time
32 sage: y = A.random_element() # long time
33 sage: y.operator()(A.one()) == y # long time
34 True
35
36 """
37
38 def superalgebra_element(self):
39 """
40 Return the object in our algebra's superalgebra that corresponds
41 to myself.
42
43 SETUP::
44
45 sage: from mjo.eja.eja_algebra import (RealSymmetricEJA,
46 ....: random_eja)
47
48 EXAMPLES::
49
50 sage: J = RealSymmetricEJA(3)
51 sage: x = sum(J.gens())
52 sage: x
53 b0 + b1 + b2 + b3 + b4 + b5
54 sage: A = x.subalgebra_generated_by(orthonormalize=False)
55 sage: A(x)
56 c1
57 sage: A(x).superalgebra_element()
58 b0 + b1 + b2 + b3 + b4 + b5
59 sage: y = sum(A.gens())
60 sage: y
61 c0 + c1
62 sage: B = y.subalgebra_generated_by(orthonormalize=False)
63 sage: B(y)
64 d1
65 sage: B(y).superalgebra_element()
66 c0 + c1
67
68 TESTS:
69
70 We can convert back and forth faithfully::
71
72 sage: J = random_eja(field=QQ, orthonormalize=False)
73 sage: x = J.random_element()
74 sage: A = x.subalgebra_generated_by(orthonormalize=False)
75 sage: A(x).superalgebra_element() == x
76 True
77 sage: y = A.random_element()
78 sage: A(y.superalgebra_element()) == y
79 True
80 sage: B = y.subalgebra_generated_by(orthonormalize=False)
81 sage: B(y).superalgebra_element() == y
82 True
83
84 """
85 return self.parent().superalgebra_embedding()(self)
86
87
88
89
90 class FiniteDimensionalEJASubalgebra(FiniteDimensionalEJA):
91 """
92 A subalgebra of an EJA with a given basis.
93
94 SETUP::
95
96 sage: from mjo.eja.eja_algebra import (ComplexHermitianEJA,
97 ....: JordanSpinEJA,
98 ....: RealSymmetricEJA)
99 sage: from mjo.eja.eja_subalgebra import FiniteDimensionalEJASubalgebra
100
101 EXAMPLES:
102
103 The following Peirce subalgebras of the 2-by-2 real symmetric
104 matrices do not contain the superalgebra's identity element::
105
106 sage: J = RealSymmetricEJA(2)
107 sage: E11 = matrix(AA, [ [1,0],
108 ....: [0,0] ])
109 sage: E22 = matrix(AA, [ [0,0],
110 ....: [0,1] ])
111 sage: K1 = FiniteDimensionalEJASubalgebra(J, (J(E11),), associative=True)
112 sage: K1.one().to_matrix()
113 [1 0]
114 [0 0]
115 sage: K2 = FiniteDimensionalEJASubalgebra(J, (J(E22),), associative=True)
116 sage: K2.one().to_matrix()
117 [0 0]
118 [0 1]
119
120 TESTS:
121
122 Ensure that our generator names don't conflict with the
123 superalgebra::
124
125 sage: J = JordanSpinEJA(3)
126 sage: J.one().subalgebra_generated_by().gens()
127 (c0,)
128 sage: J = JordanSpinEJA(3, prefix='f')
129 sage: J.one().subalgebra_generated_by().gens()
130 (g0,)
131 sage: J = JordanSpinEJA(3, prefix='a')
132 sage: J.one().subalgebra_generated_by().gens()
133 (b0,)
134
135 Ensure that we can find subalgebras of subalgebras::
136
137 sage: A = ComplexHermitianEJA(3).one().subalgebra_generated_by()
138 sage: B = A.one().subalgebra_generated_by()
139 sage: B.dimension()
140 1
141 """
142 def __init__(self, superalgebra, basis, **kwargs):
143 self._superalgebra = superalgebra
144 V = self._superalgebra.vector_space()
145 field = self._superalgebra.base_ring()
146
147 # A half-assed attempt to ensure that we don't collide with
148 # the superalgebra's prefix (ignoring the fact that there
149 # could be super-superelgrbas in scope). If possible, we
150 # try to "increment" the parent algebra's prefix, although
151 # this idea goes out the window fast because some prefixen
152 # are off-limits.
153 prefixen = ["b","c","d","e","f","g","h","l","m"]
154 try:
155 prefix = prefixen[prefixen.index(self._superalgebra.prefix()) + 1]
156 except ValueError:
157 prefix = prefixen[0]
158
159 # The superalgebra constructor expects these to be in original matrix
160 # form, not algebra-element form.
161 matrix_basis = tuple( b.to_matrix() for b in basis )
162 def jordan_product(x,y):
163 return (self._superalgebra(x)*self._superalgebra(y)).to_matrix()
164
165 def inner_product(x,y):
166 return self._superalgebra(x).inner_product(self._superalgebra(y))
167
168 super().__init__(matrix_basis,
169 jordan_product,
170 inner_product,
171 field=field,
172 matrix_space=superalgebra.matrix_space(),
173 prefix=prefix,
174 **kwargs)
175
176
177
178 def _element_constructor_(self, elt):
179 """
180 Construct an element of this subalgebra from the given one.
181 The only valid arguments are elements of the parent algebra
182 that happen to live in this subalgebra.
183
184 SETUP::
185
186 sage: from mjo.eja.eja_algebra import RealSymmetricEJA
187 sage: from mjo.eja.eja_subalgebra import FiniteDimensionalEJASubalgebra
188
189 EXAMPLES::
190
191 sage: J = RealSymmetricEJA(3)
192 sage: X = matrix(AA, [ [0,0,1],
193 ....: [0,1,0],
194 ....: [1,0,0] ])
195 sage: x = J(X)
196 sage: basis = ( x, x^2 ) # x^2 is the identity matrix
197 sage: K = FiniteDimensionalEJASubalgebra(J,
198 ....: basis,
199 ....: associative=True,
200 ....: orthonormalize=False)
201 sage: K(J.one())
202 c1
203 sage: K(J.one() + x)
204 c0 + c1
205
206 ::
207
208 """
209 if elt in self.superalgebra():
210 # If the subalgebra is trivial, its _matrix_span will be empty
211 # but we still want to be able convert the superalgebra's zero()
212 # element into the subalgebra's zero() element. There's no great
213 # workaround for this because sage checks that your basis is
214 # linearly-independent everywhere, so we can't just give it a
215 # basis consisting of the zero element.
216 m = elt.to_matrix()
217 if self.is_trivial() and m.is_zero():
218 return self.zero()
219 else:
220 return super()._element_constructor_(m)
221 else:
222 return super()._element_constructor_(elt)
223
224
225 def superalgebra(self):
226 """
227 Return the superalgebra that this algebra was generated from.
228 """
229 return self._superalgebra
230
231
232 @cached_method
233 def superalgebra_embedding(self):
234 r"""
235 Return the embedding from this subalgebra into the superalgebra.
236
237 SETUP::
238
239 sage: from mjo.eja.eja_algebra import HadamardEJA
240
241 EXAMPLES::
242
243 sage: J = HadamardEJA(4)
244 sage: A = J.one().subalgebra_generated_by()
245 sage: iota = A.superalgebra_embedding()
246 sage: iota
247 Linear operator between finite-dimensional Euclidean Jordan algebras represented by the matrix:
248 [1/2]
249 [1/2]
250 [1/2]
251 [1/2]
252 Domain: Euclidean Jordan algebra of dimension 1 over Algebraic Real Field
253 Codomain: Euclidean Jordan algebra of dimension 4 over Algebraic Real Field
254 sage: iota(A.one()) == J.one()
255 True
256
257 """
258 from mjo.eja.eja_operator import FiniteDimensionalEJAOperator
259 mm = self._module_morphism(lambda j: self.superalgebra()(self.monomial(j).to_matrix()),
260 codomain=self.superalgebra())
261 return FiniteDimensionalEJAOperator(self,
262 self.superalgebra(),
263 mm.matrix())
264
265
266
267 Element = FiniteDimensionalEJASubalgebraElement