]> gitweb.michael.orlitzky.com - sage.d.git/blob - mjo/eja/eja_subalgebra.py
eja: drop cached superalgebra basis from subalgebras.
[sage.d.git] / mjo / eja / eja_subalgebra.py
1 from sage.matrix.constructor import matrix
2
3 from mjo.eja.eja_algebra import FiniteDimensionalEuclideanJordanAlgebra
4 from mjo.eja.eja_element import FiniteDimensionalEuclideanJordanAlgebraElement
5
6 class FiniteDimensionalEuclideanJordanSubalgebraElement(FiniteDimensionalEuclideanJordanAlgebraElement):
7 """
8 SETUP::
9
10 sage: from mjo.eja.eja_algebra import random_eja
11
12 TESTS::
13
14 The natural representation of an element in the subalgebra is
15 the same as its natural representation in the superalgebra::
16
17 sage: set_random_seed()
18 sage: A = random_eja().random_element().subalgebra_generated_by()
19 sage: y = A.random_element()
20 sage: actual = y.natural_representation()
21 sage: expected = y.superalgebra_element().natural_representation()
22 sage: actual == expected
23 True
24
25 The left-multiplication-by operator for elements in the subalgebra
26 works like it does in the superalgebra, even if we orthonormalize
27 our basis::
28
29 sage: set_random_seed()
30 sage: x = random_eja(AA).random_element()
31 sage: A = x.subalgebra_generated_by(orthonormalize_basis=True)
32 sage: y = A.random_element()
33 sage: y.operator()(A.one()) == y
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 e0 + e1 + e2 + e3 + e4 + e5
54 sage: A = x.subalgebra_generated_by()
55 sage: A(x)
56 f1
57 sage: A(x).superalgebra_element()
58 e0 + e1 + e2 + e3 + e4 + e5
59 sage: y = sum(A.gens())
60 sage: y
61 f0 + f1
62 sage: B = y.subalgebra_generated_by()
63 sage: B(y)
64 g1
65 sage: B(y).superalgebra_element()
66 f0 + f1
67
68 TESTS:
69
70 We can convert back and forth faithfully::
71
72 sage: set_random_seed()
73 sage: J = random_eja()
74 sage: x = J.random_element()
75 sage: A = x.subalgebra_generated_by()
76 sage: A(x).superalgebra_element() == x
77 True
78 sage: y = A.random_element()
79 sage: A(y.superalgebra_element()) == y
80 True
81
82 """
83 W = self.parent().vector_space()
84 V = self.parent().superalgebra().vector_space()
85 A = W.basis_matrix().transpose()
86 W_coords = A*self.to_vector()
87 V_coords = V.coordinate_vector(W_coords)
88 return self.parent().superalgebra().from_vector(V_coords)
89
90
91
92
93 class FiniteDimensionalEuclideanJordanSubalgebra(FiniteDimensionalEuclideanJordanAlgebra):
94 """
95 A subalgebra of an EJA with a given basis.
96
97 SETUP::
98
99 sage: from mjo.eja.eja_algebra import (ComplexHermitianEJA,
100 ....: JordanSpinEJA,
101 ....: RealSymmetricEJA)
102 sage: from mjo.eja.eja_subalgebra import FiniteDimensionalEuclideanJordanSubalgebra
103
104 EXAMPLES:
105
106 The following Peirce subalgebras of the 2-by-2 real symmetric
107 matrices do not contain the superalgebra's identity element::
108
109 sage: J = RealSymmetricEJA(2)
110 sage: E11 = matrix(AA, [ [1,0],
111 ....: [0,0] ])
112 sage: E22 = matrix(AA, [ [0,0],
113 ....: [0,1] ])
114 sage: K1 = FiniteDimensionalEuclideanJordanSubalgebra(J, (J(E11),))
115 sage: K1.one().natural_representation()
116 [1 0]
117 [0 0]
118 sage: K2 = FiniteDimensionalEuclideanJordanSubalgebra(J, (J(E22),))
119 sage: K2.one().natural_representation()
120 [0 0]
121 [0 1]
122
123 TESTS:
124
125 Ensure that our generator names don't conflict with the superalgebra::
126
127 sage: J = JordanSpinEJA(3)
128 sage: J.one().subalgebra_generated_by().gens()
129 (f0,)
130 sage: J = JordanSpinEJA(3, prefix='f')
131 sage: J.one().subalgebra_generated_by().gens()
132 (g0,)
133 sage: J = JordanSpinEJA(3, prefix='b')
134 sage: J.one().subalgebra_generated_by().gens()
135 (c0,)
136
137 Ensure that we can find subalgebras of subalgebras::
138
139 sage: A = ComplexHermitianEJA(3).one().subalgebra_generated_by()
140 sage: B = A.one().subalgebra_generated_by()
141 sage: B.dimension()
142 1
143
144 """
145 def __init__(self, superalgebra, basis, category=None, check_axioms=True):
146 self._superalgebra = superalgebra
147 V = self._superalgebra.vector_space()
148 field = self._superalgebra.base_ring()
149 if category is None:
150 category = self._superalgebra.category()
151
152 # A half-assed attempt to ensure that we don't collide with
153 # the superalgebra's prefix (ignoring the fact that there
154 # could be super-superelgrbas in scope). If possible, we
155 # try to "increment" the parent algebra's prefix, although
156 # this idea goes out the window fast because some prefixen
157 # are off-limits.
158 prefixen = [ 'f', 'g', 'h', 'a', 'b', 'c', 'd' ]
159 try:
160 prefix = prefixen[prefixen.index(self._superalgebra.prefix()) + 1]
161 except ValueError:
162 prefix = prefixen[0]
163
164 basis_vectors = [ b.to_vector() for b in basis ]
165 superalgebra_basis = [ self._superalgebra.from_vector(b)
166 for b in basis_vectors ]
167
168 # If our superalgebra is a subalgebra of something else, then
169 # these vectors won't have the right coordinates for
170 # V.span_of_basis() unless we use V.from_vector() on them.
171 W = V.span_of_basis( V.from_vector(v) for v in basis_vectors )
172
173 n = len(superalgebra_basis)
174 mult_table = [[W.zero() for i in range(n)] for j in range(n)]
175 for i in range(n):
176 for j in range(n):
177 product = superalgebra_basis[i]*superalgebra_basis[j]
178 # product.to_vector() might live in a vector subspace
179 # if our parent algebra is already a subalgebra. We
180 # use V.from_vector() to make it "the right size" in
181 # that case.
182 product_vector = V.from_vector(product.to_vector())
183 mult_table[i][j] = W.coordinate_vector(product_vector)
184
185 natural_basis = tuple( b.natural_representation()
186 for b in superalgebra_basis )
187
188
189 self._vector_space = W
190
191 fdeja = super(FiniteDimensionalEuclideanJordanSubalgebra, self)
192 fdeja.__init__(field,
193 mult_table,
194 prefix=prefix,
195 category=category,
196 natural_basis=natural_basis,
197 check_field=False,
198 check_axioms=check_axioms)
199
200
201
202 def _element_constructor_(self, elt):
203 """
204 Construct an element of this subalgebra from the given one.
205 The only valid arguments are elements of the parent algebra
206 that happen to live in this subalgebra.
207
208 SETUP::
209
210 sage: from mjo.eja.eja_algebra import RealSymmetricEJA
211 sage: from mjo.eja.eja_subalgebra import FiniteDimensionalEuclideanJordanSubalgebra
212
213 EXAMPLES::
214
215 sage: J = RealSymmetricEJA(3)
216 sage: X = matrix(AA, [ [0,0,1],
217 ....: [0,1,0],
218 ....: [1,0,0] ])
219 sage: x = J(X)
220 sage: basis = ( x, x^2 ) # x^2 is the identity matrix
221 sage: K = FiniteDimensionalEuclideanJordanSubalgebra(J, basis)
222 sage: K(J.one())
223 f1
224 sage: K(J.one() + x)
225 f0 + f1
226
227 ::
228
229 """
230 if elt not in self.superalgebra():
231 raise ValueError("not an element of this subalgebra")
232
233 # The extra hackery is because foo.to_vector() might not
234 # live in foo.parent().vector_space()!
235 coords = sum( a*b for (a,b)
236 in zip(elt.to_vector(),
237 self.superalgebra().vector_space().basis()) )
238 return self.from_vector(self.vector_space().coordinate_vector(coords))
239
240
241
242 def natural_basis_space(self):
243 """
244 Return the natural basis space of this algebra, which is identical
245 to that of its superalgebra.
246
247 This is correct "by definition," and avoids a mismatch when the
248 subalgebra is trivial (with no natural basis to infer anything
249 from) and the parent is not.
250 """
251 return self.superalgebra().natural_basis_space()
252
253
254 def superalgebra(self):
255 """
256 Return the superalgebra that this algebra was generated from.
257 """
258 return self._superalgebra
259
260
261 def vector_space(self):
262 """
263 SETUP::
264
265 sage: from mjo.eja.eja_algebra import RealSymmetricEJA
266 sage: from mjo.eja.eja_subalgebra import FiniteDimensionalEuclideanJordanSubalgebra
267
268 EXAMPLES::
269
270 sage: J = RealSymmetricEJA(3)
271 sage: E11 = matrix(ZZ, [ [1,0,0],
272 ....: [0,0,0],
273 ....: [0,0,0] ])
274 sage: E22 = matrix(ZZ, [ [0,0,0],
275 ....: [0,1,0],
276 ....: [0,0,0] ])
277 sage: b1 = J(E11)
278 sage: b2 = J(E22)
279 sage: basis = (b1, b2)
280 sage: K = FiniteDimensionalEuclideanJordanSubalgebra(J,basis)
281 sage: K.vector_space()
282 Vector space of degree 6 and dimension 2 over...
283 User basis matrix:
284 [1 0 0 0 0 0]
285 [0 0 1 0 0 0]
286 sage: b1.to_vector()
287 (1, 0, 0, 0, 0, 0)
288 sage: b2.to_vector()
289 (0, 0, 1, 0, 0, 0)
290
291 """
292 return self._vector_space
293
294
295 Element = FiniteDimensionalEuclideanJordanSubalgebraElement