]> gitweb.michael.orlitzky.com - sage.d.git/blob - mjo/eja/eja_subalgebra.py
eja: add superalgebra_embedding() for subalgebras.
[sage.d.git] / mjo / eja / eja_subalgebra.py
1 from sage.matrix.constructor import matrix
2 from sage.misc.cachefunc import cached_method
3
4 from mjo.eja.eja_algebra import FiniteDimensionalEJA
5 from mjo.eja.eja_element import FiniteDimensionalEJAElement
6
7 class FiniteDimensionalEJASubalgebraElement(FiniteDimensionalEJAElement):
8 """
9 SETUP::
10
11 sage: from mjo.eja.eja_algebra import random_eja
12
13 TESTS::
14
15 The matrix representation of an element in the subalgebra is
16 the same as its matrix representation in the superalgebra::
17
18 sage: set_random_seed()
19 sage: x = random_eja(field=QQ,orthonormalize=False).random_element()
20 sage: A = x.subalgebra_generated_by(orthonormalize=False)
21 sage: y = A.random_element()
22 sage: actual = y.to_matrix()
23 sage: expected = y.superalgebra_element().to_matrix()
24 sage: actual == expected
25 True
26
27 The left-multiplication-by operator for elements in the subalgebra
28 works like it does in the superalgebra, even if we orthonormalize
29 our basis::
30
31 sage: set_random_seed()
32 sage: x = random_eja(field=AA).random_element()
33 sage: A = x.subalgebra_generated_by(orthonormalize=True)
34 sage: y = A.random_element()
35 sage: y.operator()(A.one()) == y
36 True
37
38 """
39
40 def superalgebra_element(self):
41 """
42 Return the object in our algebra's superalgebra that corresponds
43 to myself.
44
45 SETUP::
46
47 sage: from mjo.eja.eja_algebra import (RealSymmetricEJA,
48 ....: random_eja)
49
50 EXAMPLES::
51
52 sage: J = RealSymmetricEJA(3)
53 sage: x = sum(J.gens())
54 sage: x
55 b0 + b1 + b2 + b3 + b4 + b5
56 sage: A = x.subalgebra_generated_by(orthonormalize=False)
57 sage: A(x)
58 c1
59 sage: A(x).superalgebra_element()
60 b0 + b1 + b2 + b3 + b4 + b5
61 sage: y = sum(A.gens())
62 sage: y
63 c0 + c1
64 sage: B = y.subalgebra_generated_by(orthonormalize=False)
65 sage: B(y)
66 d1
67 sage: B(y).superalgebra_element()
68 c0 + c1
69
70 TESTS:
71
72 We can convert back and forth faithfully::
73
74 sage: set_random_seed()
75 sage: J = random_eja(field=QQ, orthonormalize=False)
76 sage: x = J.random_element()
77 sage: A = x.subalgebra_generated_by(orthonormalize=False)
78 sage: A(x).superalgebra_element() == x
79 True
80 sage: y = A.random_element()
81 sage: A(y.superalgebra_element()) == y
82 True
83 sage: B = y.subalgebra_generated_by(orthonormalize=False)
84 sage: B(y).superalgebra_element() == y
85 True
86
87 """
88 return self.parent().superalgebra_embedding()(self)
89
90
91
92
93 class FiniteDimensionalEJASubalgebra(FiniteDimensionalEJA):
94 """
95 A subalgebra of an EJA with a given basis.
96
97 SETUP::
98
99 sage: from mjo.eja.eja_algebra import (ComplexHermitianEJA,
100 ....: JordanSpinEJA,
101 ....: RealSymmetricEJA)
102 sage: from mjo.eja.eja_subalgebra import FiniteDimensionalEJASubalgebra
103
104 EXAMPLES:
105
106 The following Peirce subalgebras of the 2-by-2 real symmetric
107 matrices do not contain the superalgebra's identity element::
108
109 sage: J = RealSymmetricEJA(2)
110 sage: E11 = matrix(AA, [ [1,0],
111 ....: [0,0] ])
112 sage: E22 = matrix(AA, [ [0,0],
113 ....: [0,1] ])
114 sage: K1 = FiniteDimensionalEJASubalgebra(J, (J(E11),), associative=True)
115 sage: K1.one().to_matrix()
116 [1 0]
117 [0 0]
118 sage: K2 = FiniteDimensionalEJASubalgebra(J, (J(E22),), associative=True)
119 sage: K2.one().to_matrix()
120 [0 0]
121 [0 1]
122
123 TESTS:
124
125 Ensure that our generator names don't conflict with the
126 superalgebra::
127
128 sage: J = JordanSpinEJA(3)
129 sage: J.one().subalgebra_generated_by().gens()
130 (c0,)
131 sage: J = JordanSpinEJA(3, prefix='f')
132 sage: J.one().subalgebra_generated_by().gens()
133 (g0,)
134 sage: J = JordanSpinEJA(3, prefix='a')
135 sage: J.one().subalgebra_generated_by().gens()
136 (b0,)
137
138 Ensure that we can find subalgebras of subalgebras::
139
140 sage: A = ComplexHermitianEJA(3).one().subalgebra_generated_by()
141 sage: B = A.one().subalgebra_generated_by()
142 sage: B.dimension()
143 1
144 """
145 def __init__(self, superalgebra, basis, **kwargs):
146 self._superalgebra = superalgebra
147 V = self._superalgebra.vector_space()
148 field = self._superalgebra.base_ring()
149
150 # A half-assed attempt to ensure that we don't collide with
151 # the superalgebra's prefix (ignoring the fact that there
152 # could be super-superelgrbas in scope). If possible, we
153 # try to "increment" the parent algebra's prefix, although
154 # this idea goes out the window fast because some prefixen
155 # are off-limits.
156 prefixen = ["b","c","d","e","f","g","h","l","m"]
157 try:
158 prefix = prefixen[prefixen.index(self._superalgebra.prefix()) + 1]
159 except ValueError:
160 prefix = prefixen[0]
161
162 # The superalgebra constructor expects these to be in original matrix
163 # form, not algebra-element form.
164 matrix_basis = tuple( b.to_matrix() for b in basis )
165 def jordan_product(x,y):
166 return (self._superalgebra(x)*self._superalgebra(y)).to_matrix()
167
168 def inner_product(x,y):
169 return self._superalgebra(x).inner_product(self._superalgebra(y))
170
171 super().__init__(matrix_basis,
172 jordan_product,
173 inner_product,
174 field=field,
175 matrix_space=superalgebra.matrix_space(),
176 prefix=prefix,
177 **kwargs)
178
179
180
181 def _element_constructor_(self, elt):
182 """
183 Construct an element of this subalgebra from the given one.
184 The only valid arguments are elements of the parent algebra
185 that happen to live in this subalgebra.
186
187 SETUP::
188
189 sage: from mjo.eja.eja_algebra import RealSymmetricEJA
190 sage: from mjo.eja.eja_subalgebra import FiniteDimensionalEJASubalgebra
191
192 EXAMPLES::
193
194 sage: J = RealSymmetricEJA(3)
195 sage: X = matrix(AA, [ [0,0,1],
196 ....: [0,1,0],
197 ....: [1,0,0] ])
198 sage: x = J(X)
199 sage: basis = ( x, x^2 ) # x^2 is the identity matrix
200 sage: K = FiniteDimensionalEJASubalgebra(J,
201 ....: basis,
202 ....: associative=True,
203 ....: orthonormalize=False)
204 sage: K(J.one())
205 c1
206 sage: K(J.one() + x)
207 c0 + c1
208
209 ::
210
211 """
212 if elt in self.superalgebra():
213 return super()._element_constructor_(elt.to_matrix())
214 else:
215 return super()._element_constructor_(elt)
216
217
218 def superalgebra(self):
219 """
220 Return the superalgebra that this algebra was generated from.
221 """
222 return self._superalgebra
223
224
225 @cached_method
226 def superalgebra_embedding(self):
227 r"""
228 Return the embedding from this subalgebra into the superalgebra.
229
230 EXAMPLES::
231
232 sage: J = HadamardEJA(4)
233 sage: A = J.one().subalgebra_generated_by()
234 sage: iota = A.superalgebra_embedding()
235 sage: iota
236 Linear operator between finite-dimensional Euclidean Jordan algebras represented by the matrix:
237 [1/2]
238 [1/2]
239 [1/2]
240 [1/2]
241 Domain: Euclidean Jordan algebra of dimension 1 over Algebraic Real Field
242 Codomain: Euclidean Jordan algebra of dimension 4 over Algebraic Real Field
243 sage: iota(A.one()) == J.one()
244 True
245
246 """
247 from mjo.eja.eja_operator import FiniteDimensionalEJAOperator
248 mm = self._module_morphism(lambda j: self.superalgebra()(self.monomial(j).to_matrix()),
249 codomain=self.superalgebra())
250 return FiniteDimensionalEJAOperator(self,
251 self.superalgebra(),
252 mm.matrix())
253
254
255
256 Element = FiniteDimensionalEJASubalgebraElement