]> gitweb.michael.orlitzky.com - sage.d.git/blob - mjo/eja/eja_subalgebra.py
eja: fix construction of subalgebra elements from superalgebra ones.
[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 def __init__(self, elt):
76 superalgebra = elt.parent()
77
78 # First compute the vector subspace spanned by the powers of
79 # the given element.
80 V = superalgebra.vector_space()
81 superalgebra_basis = [superalgebra.one()]
82 basis_vectors = [superalgebra.one().to_vector()]
83 W = V.span_of_basis(basis_vectors)
84 for exponent in range(1, V.dimension()):
85 new_power = elt**exponent
86 basis_vectors.append( new_power.to_vector() )
87 try:
88 W = V.span_of_basis(basis_vectors)
89 superalgebra_basis.append( new_power )
90 except ValueError:
91 # Vectors weren't independent; bail and keep the
92 # last subspace that worked.
93 break
94
95 # Make the basis hashable for UniqueRepresentation.
96 superalgebra_basis = tuple(superalgebra_basis)
97
98 # Now figure out the entries of the right-multiplication
99 # matrix for the successive basis elements b0, b1,... of
100 # that subspace.
101 field = superalgebra.base_ring()
102 mult_table = []
103 for b_right in superalgebra_basis:
104 b_right_rows = []
105 # The first row of the right-multiplication matrix by
106 # b1 is what we get if we apply that matrix to b1. The
107 # second row of the right multiplication matrix by b1
108 # is what we get when we apply that matrix to b2...
109 #
110 # IMPORTANT: this assumes that all vectors are COLUMN
111 # vectors, unlike our superclass (which uses row vectors).
112 for b_left in superalgebra_basis:
113 # Multiply in the original EJA, but then get the
114 # coordinates from the subalgebra in terms of its
115 # basis.
116 this_row = W.coordinates((b_left*b_right).to_vector())
117 b_right_rows.append(this_row)
118 b_right_matrix = matrix(field, b_right_rows)
119 mult_table.append(b_right_matrix)
120
121 for m in mult_table:
122 m.set_immutable()
123 mult_table = tuple(mult_table)
124
125 # TODO: We'll have to redo this and make it unique again...
126 prefix = 'f'
127
128 # The rank is the highest possible degree of a minimal
129 # polynomial, and is bounded above by the dimension. We know
130 # in this case that there's an element whose minimal
131 # polynomial has the same degree as the space's dimension
132 # (remember how we constructed the space?), so that must be
133 # its rank too.
134 rank = W.dimension()
135
136 category = superalgebra.category().Associative()
137 natural_basis = tuple( b.natural_representation()
138 for b in superalgebra_basis )
139
140 self._superalgebra = superalgebra
141 self._vector_space = W
142 self._superalgebra_basis = superalgebra_basis
143
144
145 fdeja = super(FiniteDimensionalEuclideanJordanElementSubalgebra, self)
146 return fdeja.__init__(field,
147 mult_table,
148 rank,
149 prefix=prefix,
150 category=category,
151 natural_basis=natural_basis)
152
153
154 def _element_constructor_(self, elt):
155 """
156 Construct an element of this subalgebra from the given one.
157 The only valid arguments are elements of the parent algebra
158 that happen to live in this subalgebra.
159
160 SETUP::
161
162 sage: from mjo.eja.eja_algebra import RealSymmetricEJA
163 sage: from mjo.eja.eja_subalgebra import FiniteDimensionalEuclideanJordanElementSubalgebra
164
165 EXAMPLES::
166
167 sage: J = RealSymmetricEJA(3)
168 sage: x = sum( i*J.gens()[i] for i in range(6) )
169 sage: K = FiniteDimensionalEuclideanJordanElementSubalgebra(x)
170 sage: [ K(x^k) for k in range(J.rank()) ]
171 [f0, f1, f2]
172
173 ::
174
175 """
176 if elt in self.superalgebra():
177 coords = self.vector_space().coordinate_vector(elt.to_vector())
178 return self.from_vector(coords)
179
180
181 def superalgebra(self):
182 """
183 Return the superalgebra that this algebra was generated from.
184 """
185 return self._superalgebra
186
187
188 def vector_space(self):
189 """
190 SETUP::
191
192 sage: from mjo.eja.eja_algebra import RealSymmetricEJA
193 sage: from mjo.eja.eja_subalgebra import FiniteDimensionalEuclideanJordanElementSubalgebra
194
195 EXAMPLES::
196
197 sage: J = RealSymmetricEJA(3)
198 sage: x = sum( i*J.gens()[i] for i in range(6) )
199 sage: K = FiniteDimensionalEuclideanJordanElementSubalgebra(x)
200 sage: K.vector_space()
201 Vector space of degree 6 and dimension 3 over Rational Field
202 User basis matrix:
203 [ 1 0 1 0 0 1]
204 [ 0 1 2 3 4 5]
205 [10 14 21 19 31 50]
206 sage: (x^0).to_vector()
207 (1, 0, 1, 0, 0, 1)
208 sage: (x^1).to_vector()
209 (0, 1, 2, 3, 4, 5)
210 sage: (x^2).to_vector()
211 (10, 14, 21, 19, 31, 50)
212
213 """
214 return self._vector_space
215
216
217 Element = FiniteDimensionalEuclideanJordanElementSubalgebraElement