]> gitweb.michael.orlitzky.com - sage.d.git/blob - mjo/eja/eja_subalgebra.py
eja: drop redundant vector->superalgebra-element conversion.
[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 sage: B = y.subalgebra_generated_by()
82 sage: B(y).superalgebra_element() == y
83 True
84
85 """
86 W = self.parent().vector_space()
87 V = self.parent().superalgebra().vector_space()
88 A = W.basis_matrix().transpose()
89 W_coords = A*self.to_vector()
90 V_coords = V.coordinate_vector(W_coords)
91 return self.parent().superalgebra().from_vector(V_coords)
92
93
94
95
96 class FiniteDimensionalEuclideanJordanSubalgebra(FiniteDimensionalEuclideanJordanAlgebra):
97 """
98 A subalgebra of an EJA with a given basis.
99
100 SETUP::
101
102 sage: from mjo.eja.eja_algebra import (ComplexHermitianEJA,
103 ....: JordanSpinEJA,
104 ....: RealSymmetricEJA)
105 sage: from mjo.eja.eja_subalgebra import FiniteDimensionalEuclideanJordanSubalgebra
106
107 EXAMPLES:
108
109 The following Peirce subalgebras of the 2-by-2 real symmetric
110 matrices do not contain the superalgebra's identity element::
111
112 sage: J = RealSymmetricEJA(2)
113 sage: E11 = matrix(AA, [ [1,0],
114 ....: [0,0] ])
115 sage: E22 = matrix(AA, [ [0,0],
116 ....: [0,1] ])
117 sage: K1 = FiniteDimensionalEuclideanJordanSubalgebra(J, (J(E11),))
118 sage: K1.one().natural_representation()
119 [1 0]
120 [0 0]
121 sage: K2 = FiniteDimensionalEuclideanJordanSubalgebra(J, (J(E22),))
122 sage: K2.one().natural_representation()
123 [0 0]
124 [0 1]
125
126 TESTS:
127
128 Ensure that our generator names don't conflict with the superalgebra::
129
130 sage: J = JordanSpinEJA(3)
131 sage: J.one().subalgebra_generated_by().gens()
132 (f0,)
133 sage: J = JordanSpinEJA(3, prefix='f')
134 sage: J.one().subalgebra_generated_by().gens()
135 (g0,)
136 sage: J = JordanSpinEJA(3, prefix='b')
137 sage: J.one().subalgebra_generated_by().gens()
138 (c0,)
139
140 Ensure that we can find subalgebras of subalgebras::
141
142 sage: A = ComplexHermitianEJA(3).one().subalgebra_generated_by()
143 sage: B = A.one().subalgebra_generated_by()
144 sage: B.dimension()
145 1
146
147 """
148 def __init__(self, superalgebra, basis, category=None, check_axioms=True):
149 self._superalgebra = superalgebra
150 V = self._superalgebra.vector_space()
151 field = self._superalgebra.base_ring()
152 if category is None:
153 category = self._superalgebra.category()
154
155 # A half-assed attempt to ensure that we don't collide with
156 # the superalgebra's prefix (ignoring the fact that there
157 # could be super-superelgrbas in scope). If possible, we
158 # try to "increment" the parent algebra's prefix, although
159 # this idea goes out the window fast because some prefixen
160 # are off-limits.
161 prefixen = [ 'f', 'g', 'h', 'a', 'b', 'c', 'd' ]
162 try:
163 prefix = prefixen[prefixen.index(self._superalgebra.prefix()) + 1]
164 except ValueError:
165 prefix = prefixen[0]
166
167 basis_vectors = [ b.to_vector() for b in basis ]
168
169 # If our superalgebra is a subalgebra of something else, then
170 # these vectors won't have the right coordinates for
171 # V.span_of_basis() unless we use V.from_vector() on them.
172 W = V.span_of_basis( V.from_vector(v) for v in basis_vectors )
173
174 n = len(basis)
175 mult_table = [[W.zero() for i in range(n)] for j in range(n)]
176 for i in range(n):
177 for j in range(n):
178 product = basis[i]*basis[j]
179 # product.to_vector() might live in a vector subspace
180 # if our parent algebra is already a subalgebra. We
181 # use V.from_vector() to make it "the right size" in
182 # that case.
183 product_vector = V.from_vector(product.to_vector())
184 mult_table[i][j] = W.coordinate_vector(product_vector)
185
186 natural_basis = tuple( b.natural_representation() for b in 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