]> gitweb.michael.orlitzky.com - sage.d.git/blob - mjo/eja/eja_subalgebra.py
eja: split "check" args into check_field and check_axioms.
[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_axioms=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_field=False,
184 check_axioms=check_axioms)
185
186
187
188 def _element_constructor_(self, elt):
189 """
190 Construct an element of this subalgebra from the given one.
191 The only valid arguments are elements of the parent algebra
192 that happen to live in this subalgebra.
193
194 SETUP::
195
196 sage: from mjo.eja.eja_algebra import RealSymmetricEJA
197 sage: from mjo.eja.eja_subalgebra import FiniteDimensionalEuclideanJordanSubalgebra
198
199 EXAMPLES::
200
201 sage: J = RealSymmetricEJA(3)
202 sage: X = matrix(AA, [ [0,0,1],
203 ....: [0,1,0],
204 ....: [1,0,0] ])
205 sage: x = J(X)
206 sage: basis = ( x, x^2 ) # x^2 is the identity matrix
207 sage: K = FiniteDimensionalEuclideanJordanSubalgebra(J, basis)
208 sage: K(J.one())
209 f1
210 sage: K(J.one() + x)
211 f0 + f1
212
213 ::
214
215 """
216 if elt not in self.superalgebra():
217 raise ValueError("not an element of this subalgebra")
218
219 # The extra hackery is because foo.to_vector() might not
220 # live in foo.parent().vector_space()!
221 coords = sum( a*b for (a,b)
222 in zip(elt.to_vector(),
223 self.superalgebra().vector_space().basis()) )
224 return self.from_vector(self.vector_space().coordinate_vector(coords))
225
226
227
228 def natural_basis_space(self):
229 """
230 Return the natural basis space of this algebra, which is identical
231 to that of its superalgebra.
232
233 This is correct "by definition," and avoids a mismatch when the
234 subalgebra is trivial (with no natural basis to infer anything
235 from) and the parent is not.
236 """
237 return self.superalgebra().natural_basis_space()
238
239
240 def superalgebra(self):
241 """
242 Return the superalgebra that this algebra was generated from.
243 """
244 return self._superalgebra
245
246
247 def vector_space(self):
248 """
249 SETUP::
250
251 sage: from mjo.eja.eja_algebra import RealSymmetricEJA
252 sage: from mjo.eja.eja_subalgebra import FiniteDimensionalEuclideanJordanSubalgebra
253
254 EXAMPLES::
255
256 sage: J = RealSymmetricEJA(3)
257 sage: E11 = matrix(ZZ, [ [1,0,0],
258 ....: [0,0,0],
259 ....: [0,0,0] ])
260 sage: E22 = matrix(ZZ, [ [0,0,0],
261 ....: [0,1,0],
262 ....: [0,0,0] ])
263 sage: b1 = J(E11)
264 sage: b2 = J(E22)
265 sage: basis = (b1, b2)
266 sage: K = FiniteDimensionalEuclideanJordanSubalgebra(J,basis)
267 sage: K.vector_space()
268 Vector space of degree 6 and dimension 2 over...
269 User basis matrix:
270 [1 0 0 0 0 0]
271 [0 0 1 0 0 0]
272 sage: b1.to_vector()
273 (1, 0, 0, 0, 0, 0)
274 sage: b2.to_vector()
275 (0, 0, 1, 0, 0, 0)
276
277 """
278 return self._vector_space
279
280
281 Element = FiniteDimensionalEuclideanJordanSubalgebraElement