]> gitweb.michael.orlitzky.com - sage.d.git/blob - mjo/eja/eja_subalgebra.py
eja: add subalgebra() method for algebras.
[sage.d.git] / mjo / eja / eja_subalgebra.py
1 from sage.matrix.constructor import matrix
2
3 from sage.combinat.free_module import CombinatorialFreeModule_CartesianProduct
4
5 from mjo.eja.eja_algebra import (CartesianProductEJA,
6 FiniteDimensionalEJA)
7 from mjo.eja.eja_element import (CartesianProductEJAElement,
8 FiniteDimensionalEJAElement)
9
10 class FiniteDimensionalEJASubalgebraElement(FiniteDimensionalEJAElement):
11 """
12 SETUP::
13
14 sage: from mjo.eja.eja_algebra import random_eja
15
16 TESTS::
17
18 The matrix representation of an element in the subalgebra is
19 the same as its matrix representation in the superalgebra::
20
21 sage: set_random_seed()
22 sage: x = random_eja(field=QQ,orthonormalize=False).random_element()
23 sage: A = x.subalgebra_generated_by(orthonormalize=False)
24 sage: y = A.random_element()
25 sage: actual = y.to_matrix()
26 sage: expected = y.superalgebra_element().to_matrix()
27 sage: actual == expected
28 True
29
30 The left-multiplication-by operator for elements in the subalgebra
31 works like it does in the superalgebra, even if we orthonormalize
32 our basis::
33
34 sage: set_random_seed()
35 sage: x = random_eja(field=AA).random_element()
36 sage: A = x.subalgebra_generated_by(orthonormalize=True)
37 sage: y = A.random_element()
38 sage: y.operator()(A.one()) == y
39 True
40
41 """
42
43 def superalgebra_element(self):
44 """
45 Return the object in our algebra's superalgebra that corresponds
46 to myself.
47
48 SETUP::
49
50 sage: from mjo.eja.eja_algebra import (RealSymmetricEJA,
51 ....: random_eja)
52
53 EXAMPLES::
54
55 sage: J = RealSymmetricEJA(3)
56 sage: x = sum(J.gens())
57 sage: x
58 e0 + e1 + e2 + e3 + e4 + e5
59 sage: A = x.subalgebra_generated_by(orthonormalize=False)
60 sage: A(x)
61 f1
62 sage: A(x).superalgebra_element()
63 e0 + e1 + e2 + e3 + e4 + e5
64 sage: y = sum(A.gens())
65 sage: y
66 f0 + f1
67 sage: B = y.subalgebra_generated_by(orthonormalize=False)
68 sage: B(y)
69 g1
70 sage: B(y).superalgebra_element()
71 f0 + f1
72
73 TESTS:
74
75 We can convert back and forth faithfully::
76
77 sage: set_random_seed()
78 sage: J = random_eja()
79 sage: x = J.random_element()
80 sage: A = x.subalgebra_generated_by()
81 sage: A(x).superalgebra_element() == x
82 True
83 sage: y = A.random_element()
84 sage: A(y.superalgebra_element()) == y
85 True
86 sage: B = y.subalgebra_generated_by()
87 sage: B(y).superalgebra_element() == y
88 True
89
90 """
91 return self.parent().superalgebra()(self.to_matrix())
92
93
94
95
96 class FiniteDimensionalEJASubalgebra(FiniteDimensionalEJA):
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 FiniteDimensionalEJASubalgebra
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 = FiniteDimensionalEJASubalgebra(J, (J(E11),))
118 sage: K1.one().to_matrix()
119 [1 0]
120 [0 0]
121 sage: K2 = FiniteDimensionalEJASubalgebra(J, (J(E22),))
122 sage: K2.one().to_matrix()
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, **kwargs):
149 self._superalgebra = superalgebra
150 V = self._superalgebra.vector_space()
151 field = self._superalgebra.base_ring()
152
153 # A half-assed attempt to ensure that we don't collide with
154 # the superalgebra's prefix (ignoring the fact that there
155 # could be super-superelgrbas in scope). If possible, we
156 # try to "increment" the parent algebra's prefix, although
157 # this idea goes out the window fast because some prefixen
158 # are off-limits.
159 prefixen = [ 'f', 'g', 'h', 'a', 'b', 'c', 'd' ]
160 try:
161 prefix = prefixen[prefixen.index(self._superalgebra.prefix()) + 1]
162 except ValueError:
163 prefix = prefixen[0]
164
165 # The superalgebra constructor expects these to be in original matrix
166 # form, not algebra-element form.
167 matrix_basis = tuple( b.to_matrix() for b in basis )
168 def jordan_product(x,y):
169 return (self._superalgebra(x)*self._superalgebra(y)).to_matrix()
170
171 def inner_product(x,y):
172 return self._superalgebra(x).inner_product(self._superalgebra(y))
173
174 super().__init__(matrix_basis,
175 jordan_product,
176 inner_product,
177 prefix=prefix,
178 **kwargs)
179
180
181
182 def _element_constructor_(self, elt):
183 """
184 Construct an element of this subalgebra from the given one.
185 The only valid arguments are elements of the parent algebra
186 that happen to live in this subalgebra.
187
188 SETUP::
189
190 sage: from mjo.eja.eja_algebra import RealSymmetricEJA
191 sage: from mjo.eja.eja_subalgebra import FiniteDimensionalEJASubalgebra
192
193 EXAMPLES::
194
195 sage: J = RealSymmetricEJA(3)
196 sage: X = matrix(AA, [ [0,0,1],
197 ....: [0,1,0],
198 ....: [1,0,0] ])
199 sage: x = J(X)
200 sage: basis = ( x, x^2 ) # x^2 is the identity matrix
201 sage: K = FiniteDimensionalEJASubalgebra(J, basis, orthonormalize=False)
202 sage: K(J.one())
203 f1
204 sage: K(J.one() + x)
205 f0 + f1
206
207 ::
208
209 """
210 if elt in self.superalgebra():
211 return super()._element_constructor_(elt.to_matrix())
212 else:
213 return super()._element_constructor_(elt)
214
215
216
217 def matrix_space(self):
218 """
219 Return the matrix space of this algebra, which is identical to
220 that of its superalgebra.
221
222 This is correct "by definition," and avoids a mismatch when
223 the subalgebra is trivial (with no matrix basis elements to
224 infer anything from) and the parent is not.
225 """
226 return self.superalgebra().matrix_space()
227
228
229 def superalgebra(self):
230 """
231 Return the superalgebra that this algebra was generated from.
232 """
233 return self._superalgebra
234
235
236 Element = FiniteDimensionalEJASubalgebraElement
237
238
239
240 class CartesianProductEJASubalgebraElement(CartesianProductEJAElement,
241 FiniteDimensionalEJASubalgebraElement):
242 pass
243
244 class CartesianProductEJASubalgebra(CartesianProductEJA,
245 FiniteDimensionalEJASubalgebra):
246
247 def __init__(self, superalgebra, basis, **kwargs):
248 CombinatorialFreeModule_CartesianProduct.__init__(self,
249 superalgebra.cartesian_factors())
250 FiniteDimensionalEJASubalgebra.__init__(self,
251 superalgebra,
252 basis,
253 cartesian_product=True,
254 **kwargs)
255
256
257 Element = CartesianProductEJASubalgebraElement