]> gitweb.michael.orlitzky.com - sage.d.git/blob - mjo/eja/eja_subalgebra.py
eja: choose subalgebra generator prefix smarter.
[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
7 class FiniteDimensionalEuclideanJordanElementSubalgebraElement(FiniteDimensionalEuclideanJordanAlgebraElement):
8 """
9 SETUP::
10
11 sage: from mjo.eja.eja_algebra import random_eja
12
13 TESTS::
14
15 The natural representation of an element in the subalgebra is
16 the same as its natural representation in the superalgebra::
17
18 sage: set_random_seed()
19 sage: A = random_eja().random_element().subalgebra_generated_by()
20 sage: y = A.random_element()
21 sage: actual = y.natural_representation()
22 sage: expected = y.superalgebra_element().natural_representation()
23 sage: actual == expected
24 True
25
26 """
27
28 def superalgebra_element(self):
29 """
30 Return the object in our algebra's superalgebra that corresponds
31 to myself.
32
33 SETUP::
34
35 sage: from mjo.eja.eja_algebra import (RealSymmetricEJA,
36 ....: random_eja)
37
38 EXAMPLES::
39
40 sage: J = RealSymmetricEJA(3)
41 sage: x = sum(J.gens())
42 sage: x
43 e0 + e1 + e2 + e3 + e4 + e5
44 sage: A = x.subalgebra_generated_by()
45 sage: A(x)
46 f1
47 sage: A(x).superalgebra_element()
48 e0 + e1 + e2 + e3 + e4 + e5
49
50 TESTS:
51
52 We can convert back and forth faithfully::
53
54 sage: set_random_seed()
55 sage: J = random_eja()
56 sage: x = J.random_element()
57 sage: A = x.subalgebra_generated_by()
58 sage: A(x).superalgebra_element() == x
59 True
60 sage: y = A.random_element()
61 sage: A(y.superalgebra_element()) == y
62 True
63
64 """
65 return self.parent().superalgebra().linear_combination(
66 zip(self.parent()._superalgebra_basis, self.to_vector()) )
67
68
69
70
71 class FiniteDimensionalEuclideanJordanElementSubalgebra(FiniteDimensionalEuclideanJordanAlgebra):
72 """
73 The subalgebra of an EJA generated by a single element.
74
75 SETUP::
76
77 sage: from mjo.eja.eja_algebra import JordanSpinEJA
78
79 TESTS:
80
81 Ensure that our generator names don't conflict with the superalgebra::
82
83 sage: J = JordanSpinEJA(3)
84 sage: J.one().subalgebra_generated_by().gens()
85 (f0,)
86 sage: J = JordanSpinEJA(3, prefix='f')
87 sage: J.one().subalgebra_generated_by().gens()
88 (g0,)
89 sage: J = JordanSpinEJA(3, prefix='b')
90 sage: J.one().subalgebra_generated_by().gens()
91 (c0,)
92
93 """
94 def __init__(self, elt):
95 superalgebra = elt.parent()
96
97 # First compute the vector subspace spanned by the powers of
98 # the given element.
99 V = superalgebra.vector_space()
100 superalgebra_basis = [superalgebra.one()]
101 basis_vectors = [superalgebra.one().to_vector()]
102 W = V.span_of_basis(basis_vectors)
103 for exponent in range(1, V.dimension()):
104 new_power = elt**exponent
105 basis_vectors.append( new_power.to_vector() )
106 try:
107 W = V.span_of_basis(basis_vectors)
108 superalgebra_basis.append( new_power )
109 except ValueError:
110 # Vectors weren't independent; bail and keep the
111 # last subspace that worked.
112 break
113
114 # Make the basis hashable for UniqueRepresentation.
115 superalgebra_basis = tuple(superalgebra_basis)
116
117 # Now figure out the entries of the right-multiplication
118 # matrix for the successive basis elements b0, b1,... of
119 # that subspace.
120 field = superalgebra.base_ring()
121 n = len(superalgebra_basis)
122 mult_table = [[W.zero() for i in range(n)] for j in range(n)]
123 for i in range(n):
124 for j in range(n):
125 product = superalgebra_basis[i]*superalgebra_basis[j]
126 mult_table[i][j] = W.coordinate_vector(product.to_vector())
127
128 # A half-assed attempt to ensure that we don't collide with
129 # the superalgebra's prefix (ignoring the fact that there
130 # could be super-superelgrbas in scope). If possible, we
131 # try to "increment" the parent algebra's prefix, although
132 # this idea goes out the window fast because some prefixen
133 # are off-limits.
134 prefixen = [ 'f', 'g', 'h', 'a', 'b', 'c', 'd' ]
135 try:
136 prefix = prefixen[prefixen.index(superalgebra.prefix()) + 1]
137 except ValueError:
138 prefix = prefixen[0]
139
140 # The rank is the highest possible degree of a minimal
141 # polynomial, and is bounded above by the dimension. We know
142 # in this case that there's an element whose minimal
143 # polynomial has the same degree as the space's dimension
144 # (remember how we constructed the space?), so that must be
145 # its rank too.
146 rank = W.dimension()
147
148 category = superalgebra.category().Associative()
149 natural_basis = tuple( b.natural_representation()
150 for b in superalgebra_basis )
151
152 self._superalgebra = superalgebra
153 self._vector_space = W
154 self._superalgebra_basis = superalgebra_basis
155
156
157 fdeja = super(FiniteDimensionalEuclideanJordanElementSubalgebra, self)
158 return fdeja.__init__(field,
159 mult_table,
160 rank,
161 prefix=prefix,
162 category=category,
163 natural_basis=natural_basis)
164
165
166 def _element_constructor_(self, elt):
167 """
168 Construct an element of this subalgebra from the given one.
169 The only valid arguments are elements of the parent algebra
170 that happen to live in this subalgebra.
171
172 SETUP::
173
174 sage: from mjo.eja.eja_algebra import RealSymmetricEJA
175 sage: from mjo.eja.eja_subalgebra import FiniteDimensionalEuclideanJordanElementSubalgebra
176
177 EXAMPLES::
178
179 sage: J = RealSymmetricEJA(3)
180 sage: x = sum( i*J.gens()[i] for i in range(6) )
181 sage: K = FiniteDimensionalEuclideanJordanElementSubalgebra(x)
182 sage: [ K(x^k) for k in range(J.rank()) ]
183 [f0, f1, f2]
184
185 ::
186
187 """
188 if elt == 0:
189 # Just as in the superalgebra class, we need to hack
190 # this special case to ensure that random_element() can
191 # coerce a ring zero into the algebra.
192 return self.zero()
193
194 if elt in self.superalgebra():
195 coords = self.vector_space().coordinate_vector(elt.to_vector())
196 return self.from_vector(coords)
197
198
199 def one_basis(self):
200 """
201 Return the basis-element-index of this algebra's unit element.
202 """
203 return 0
204
205
206 def one(self):
207 """
208 Return the multiplicative identity element of this algebra.
209
210 The superclass method computes the identity element, which is
211 beyond overkill in this case: the algebra identity should be our
212 first basis element. We implement this via :meth:`one_basis`
213 because that method can optionally be used by other parts of the
214 category framework.
215
216 SETUP::
217
218 sage: from mjo.eja.eja_algebra import (RealCartesianProductEJA,
219 ....: random_eja)
220
221 EXAMPLES::
222
223 sage: J = RealCartesianProductEJA(5)
224 sage: J.one()
225 e0 + e1 + e2 + e3 + e4
226 sage: x = sum(J.gens())
227 sage: A = x.subalgebra_generated_by()
228 sage: A.one()
229 f0
230 sage: A.one().superalgebra_element()
231 e0 + e1 + e2 + e3 + e4
232
233 TESTS:
234
235 The identity element acts like the identity::
236
237 sage: set_random_seed()
238 sage: J = random_eja().random_element().subalgebra_generated_by()
239 sage: x = J.random_element()
240 sage: J.one()*x == x and x*J.one() == x
241 True
242
243 The matrix of the unit element's operator is the identity::
244
245 sage: set_random_seed()
246 sage: J = random_eja().random_element().subalgebra_generated_by()
247 sage: actual = J.one().operator().matrix()
248 sage: expected = matrix.identity(J.base_ring(), J.dimension())
249 sage: actual == expected
250 True
251 """
252 return self.monomial(self.one_basis())
253
254
255 def superalgebra(self):
256 """
257 Return the superalgebra that this algebra was generated from.
258 """
259 return self._superalgebra
260
261
262 def vector_space(self):
263 """
264 SETUP::
265
266 sage: from mjo.eja.eja_algebra import RealSymmetricEJA
267 sage: from mjo.eja.eja_subalgebra import FiniteDimensionalEuclideanJordanElementSubalgebra
268
269 EXAMPLES::
270
271 sage: J = RealSymmetricEJA(3)
272 sage: x = sum( i*J.gens()[i] for i in range(6) )
273 sage: K = FiniteDimensionalEuclideanJordanElementSubalgebra(x)
274 sage: K.vector_space()
275 Vector space of degree 6 and dimension 3 over Rational Field
276 User basis matrix:
277 [ 1 0 1 0 0 1]
278 [ 0 1 2 3 4 5]
279 [10 14 21 19 31 50]
280 sage: (x^0).to_vector()
281 (1, 0, 1, 0, 0, 1)
282 sage: (x^1).to_vector()
283 (0, 1, 2, 3, 4, 5)
284 sage: (x^2).to_vector()
285 (10, 14, 21, 19, 31, 50)
286
287 """
288 return self._vector_space
289
290
291 Element = FiniteDimensionalEuclideanJordanElementSubalgebraElement