]> gitweb.michael.orlitzky.com - sage.d.git/blob - mjo/eja/eja_subalgebra.py
eja: begin moving the associative subalgebra stuff into its own class.
[sage.d.git] / mjo / eja / eja_subalgebra.py
1 from sage.matrix.constructor import matrix
2 from sage.structure.category_object import normalize_names
3
4 from mjo.eja.eja_algebra import FiniteDimensionalEuclideanJordanAlgebra
5 from mjo.eja.eja_element import FiniteDimensionalEuclideanJordanAlgebraElement
6
7
8 class FiniteDimensionalEuclideanJordanElementSubalgebra(FiniteDimensionalEuclideanJordanAlgebra):
9 """
10 The subalgebra of an EJA generated by a single element.
11 """
12 @staticmethod
13 def __classcall_private__(cls, elt):
14 superalgebra = elt.parent()
15
16 # First compute the vector subspace spanned by the powers of
17 # the given element.
18 V = superalgebra.vector_space()
19 eja_basis = [superalgebra.one()]
20 basis_vectors = [superalgebra.one().vector()]
21 W = V.span_of_basis(basis_vectors)
22 for exponent in range(1, V.dimension()):
23 new_power = elt**exponent
24 basis_vectors.append( new_power.vector() )
25 try:
26 W = V.span_of_basis(basis_vectors)
27 eja_basis.append( new_power )
28 except ValueError:
29 # Vectors weren't independent; bail and keep the
30 # last subspace that worked.
31 break
32
33 # Make the basis hashable for UniqueRepresentation.
34 eja_basis = tuple(eja_basis)
35
36 # Now figure out the entries of the right-multiplication
37 # matrix for the successive basis elements b0, b1,... of
38 # that subspace.
39 F = superalgebra.base_ring()
40 mult_table = []
41 for b_right in eja_basis:
42 b_right_rows = []
43 # The first row of the right-multiplication matrix by
44 # b1 is what we get if we apply that matrix to b1. The
45 # second row of the right multiplication matrix by b1
46 # is what we get when we apply that matrix to b2...
47 #
48 # IMPORTANT: this assumes that all vectors are COLUMN
49 # vectors, unlike our superclass (which uses row vectors).
50 for b_left in eja_basis:
51 # Multiply in the original EJA, but then get the
52 # coordinates from the subalgebra in terms of its
53 # basis.
54 this_row = W.coordinates((b_left*b_right).vector())
55 b_right_rows.append(this_row)
56 b_right_matrix = matrix(F, b_right_rows)
57 mult_table.append(b_right_matrix)
58
59 for m in mult_table:
60 m.set_immutable()
61 mult_table = tuple(mult_table)
62
63 # The rank is the highest possible degree of a minimal
64 # polynomial, and is bounded above by the dimension. We know
65 # in this case that there's an element whose minimal
66 # polynomial has the same degree as the space's dimension
67 # (remember how we constructed the space?), so that must be
68 # its rank too.
69 rank = W.dimension()
70
71 # EJAs are power-associative, and this algebra is nothin but
72 # powers.
73 assume_associative=True
74
75 # TODO: Un-hard-code this. It should be possible to get the "next"
76 # name based on the parent's generator names.
77 names = 'f'
78 names = normalize_names(W.dimension(), names)
79
80 cat = superalgebra.category().Associative()
81
82 # TODO: compute this and actually specify it.
83 natural_basis = None
84
85 fdeja = super(FiniteDimensionalEuclideanJordanElementSubalgebra, cls)
86 return fdeja.__classcall__(cls,
87 F,
88 mult_table,
89 rank,
90 eja_basis,
91 W,
92 assume_associative=assume_associative,
93 names=names,
94 category=cat,
95 natural_basis=natural_basis)
96
97 def __init__(self,
98 field,
99 mult_table,
100 rank,
101 eja_basis,
102 vector_space,
103 assume_associative=True,
104 names='f',
105 category=None,
106 natural_basis=None):
107
108 self._superalgebra = eja_basis[0].parent()
109 self._vector_space = vector_space
110 self._eja_basis = eja_basis
111
112 fdeja = super(FiniteDimensionalEuclideanJordanElementSubalgebra, self)
113 fdeja.__init__(field,
114 mult_table,
115 rank,
116 assume_associative=assume_associative,
117 names=names,
118 category=category,
119 natural_basis=natural_basis)
120
121
122 def vector_space(self):
123 """
124 SETUP::
125
126 sage: from mjo.eja.eja_algebra import RealSymmetricEJA
127 sage: from mjo.eja.eja_subalgebra import FiniteDimensionalEuclideanJordanElementSubalgebra
128
129 EXAMPLES::
130
131 sage: J = RealSymmetricEJA(3)
132 sage: x = sum( i*J.gens()[i] for i in range(6) )
133 sage: K = FiniteDimensionalEuclideanJordanElementSubalgebra(x)
134 sage: K.vector_space()
135 Vector space of degree 6 and dimension 3 over Rational Field
136 User basis matrix:
137 [ 1 0 0 1 0 1]
138 [ 0 1 2 3 4 5]
139 [ 5 11 14 26 34 45]
140 sage: (x^0).vector()
141 (1, 0, 0, 1, 0, 1)
142 sage: (x^1).vector()
143 (0, 1, 2, 3, 4, 5)
144 sage: (x^2).vector()
145 (5, 11, 14, 26, 34, 45)
146
147 """
148 return self._vector_space
149
150
151 class Element(FiniteDimensionalEuclideanJordanAlgebraElement):
152 def __init__(self, A, elt=None):
153 """
154 SETUP::
155
156 sage: from mjo.eja.eja_algebra import RealSymmetricEJA
157 sage: from mjo.eja.eja_subalgebra import FiniteDimensionalEuclideanJordanElementSubalgebra
158
159 EXAMPLES::
160
161 sage: J = RealSymmetricEJA(3)
162 sage: x = sum( i*J.gens()[i] for i in range(6) )
163 sage: K = FiniteDimensionalEuclideanJordanElementSubalgebra(x)
164 sage: [ K(x^k) for k in range(J.rank()) ]
165 [f0, f1, f2]
166
167 ::
168
169 """
170 if elt in A._superalgebra:
171 # Try to convert a parent algebra element into a
172 # subalgebra element...
173 try:
174 coords = A.vector_space().coordinates(elt.vector())
175 elt = A(coords)
176 except AttributeError:
177 # Catches a missing method in elt.vector()
178 pass
179
180 FiniteDimensionalEuclideanJordanAlgebraElement.__init__(self,
181 A,
182 elt)