]> gitweb.michael.orlitzky.com - sage.d.git/blob - mjo/eja/eja_subalgebra.py
eja: enable consistency checks by default in (non-element) 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
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(AA, [ [1,0],
99 ....: [0,0] ])
100 sage: E22 = matrix(AA, [ [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, category=None, check=True):
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 fdeja.__init__(field,
179 mult_table,
180 prefix=prefix,
181 category=category,
182 natural_basis=natural_basis,
183 check=check)
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(AA, [ [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 # The extra hackery is because foo.to_vector() might not
219 # live in foo.parent().vector_space()!
220 coords = sum( a*b for (a,b)
221 in zip(elt.to_vector(),
222 self.superalgebra().vector_space().basis()) )
223 return self.from_vector(self.vector_space().coordinate_vector(coords))
224
225
226
227 def natural_basis_space(self):
228 """
229 Return the natural basis space of this algebra, which is identical
230 to that of its superalgebra.
231
232 This is correct "by definition," and avoids a mismatch when the
233 subalgebra is trivial (with no natural basis to infer anything
234 from) and the parent is not.
235 """
236 return self.superalgebra().natural_basis_space()
237
238
239 def superalgebra(self):
240 """
241 Return the superalgebra that this algebra was generated from.
242 """
243 return self._superalgebra
244
245
246 def vector_space(self):
247 """
248 SETUP::
249
250 sage: from mjo.eja.eja_algebra import RealSymmetricEJA
251 sage: from mjo.eja.eja_subalgebra import FiniteDimensionalEuclideanJordanSubalgebra
252
253 EXAMPLES::
254
255 sage: J = RealSymmetricEJA(3)
256 sage: E11 = matrix(ZZ, [ [1,0,0],
257 ....: [0,0,0],
258 ....: [0,0,0] ])
259 sage: E22 = matrix(ZZ, [ [0,0,0],
260 ....: [0,1,0],
261 ....: [0,0,0] ])
262 sage: b1 = J(E11)
263 sage: b2 = J(E22)
264 sage: basis = (b1, b2)
265 sage: K = FiniteDimensionalEuclideanJordanSubalgebra(J,basis)
266 sage: K.vector_space()
267 Vector space of degree 6 and dimension 2 over...
268 User basis matrix:
269 [1 0 0 0 0 0]
270 [0 0 1 0 0 0]
271 sage: b1.to_vector()
272 (1, 0, 0, 0, 0, 0)
273 sage: b2.to_vector()
274 (0, 0, 1, 0, 0, 0)
275
276 """
277 return self._vector_space
278
279
280 Element = FiniteDimensionalEuclideanJordanSubalgebraElement