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