1 from sage
.matrix
.constructor
import matrix
3 from mjo
.eja
.eja_algebra
import FiniteDimensionalEuclideanJordanAlgebra
4 from mjo
.eja
.eja_element
import FiniteDimensionalEuclideanJordanAlgebraElement
7 class FiniteDimensionalEuclideanJordanElementSubalgebraElement(FiniteDimensionalEuclideanJordanAlgebraElement
):
11 sage: from mjo.eja.eja_algebra import random_eja
15 The natural representation of an element in the subalgebra is
16 the same as its natural representation in the superalgebra::
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
28 def superalgebra_element(self
):
30 Return the object in our algebra's superalgebra that corresponds
35 sage: from mjo.eja.eja_algebra import (RealSymmetricEJA,
40 sage: J = RealSymmetricEJA(3)
41 sage: x = sum(J.gens())
43 e0 + e1 + e2 + e3 + e4 + e5
44 sage: A = x.subalgebra_generated_by()
47 sage: A(x).superalgebra_element()
48 e0 + e1 + e2 + e3 + e4 + e5
52 We can convert back and forth faithfully::
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
60 sage: y = A.random_element()
61 sage: A(y.superalgebra_element()) == y
65 return self
.parent().superalgebra().linear_combination(
66 zip(self
.parent()._superalgebra
_basis
, self
.to_vector()) )
71 class FiniteDimensionalEuclideanJordanElementSubalgebra(FiniteDimensionalEuclideanJordanAlgebra
):
73 The subalgebra of an EJA generated by a single element.
77 sage: from mjo.eja.eja_algebra import (ComplexHermitianEJA,
82 Ensure that our generator names don't conflict with the superalgebra::
84 sage: J = JordanSpinEJA(3)
85 sage: J.one().subalgebra_generated_by().gens()
87 sage: J = JordanSpinEJA(3, prefix='f')
88 sage: J.one().subalgebra_generated_by().gens()
90 sage: J = JordanSpinEJA(3, prefix='b')
91 sage: J.one().subalgebra_generated_by().gens()
94 Ensure that we can find subalgebras of subalgebras::
96 sage: A = ComplexHermitianEJA(3).one().subalgebra_generated_by()
97 sage: B = A.one().subalgebra_generated_by()
102 def __init__(self
, elt
):
103 self
._superalgebra
= elt
.parent()
104 category
= self
._superalgebra
.category().Associative()
105 V
= self
._superalgebra
.vector_space()
106 field
= self
._superalgebra
.base_ring()
108 # A half-assed attempt to ensure that we don't collide with
109 # the superalgebra's prefix (ignoring the fact that there
110 # could be super-superelgrbas in scope). If possible, we
111 # try to "increment" the parent algebra's prefix, although
112 # this idea goes out the window fast because some prefixen
114 prefixen
= [ 'f', 'g', 'h', 'a', 'b', 'c', 'd' ]
116 prefix
= prefixen
[prefixen
.index(self
._superalgebra
.prefix()) + 1]
121 # Short circuit because 0^0 == 1 is going to make us
122 # think we have a one-dimensional algebra otherwise.
123 natural_basis
= tuple()
126 self
._vector
_space
= V
.zero_subspace()
127 self
._superalgebra
_basis
= []
128 fdeja
= super(FiniteDimensionalEuclideanJordanElementSubalgebra
,
130 return fdeja
.__init
__(field
,
135 natural_basis
=natural_basis
)
138 # First compute the vector subspace spanned by the powers of
140 powers
= [ elt
**k
for k
in range(V
.dimension()) ]
141 power_vectors
= [ p
.to_vector() for p
in powers
]
143 # Figure out which powers form a linearly-independent set.
144 ind_rows
= matrix(field
, power_vectors
).pivot_rows()
146 # Pick those out of the list of all powers.
147 superalgebra_basis
= tuple(map(powers
.__getitem
__, ind_rows
))
149 # If our superalgebra is a subalgebra of something else, then
150 # these vectors won't have the right coordinates for
151 # V.span_of_basis() unless we use V.from_vector() on them.
152 basis_vectors
= map(power_vectors
.__getitem
__, ind_rows
)
153 W
= V
.span_of_basis( V
.from_vector(v
) for v
in basis_vectors
)
155 # Now figure out the entries of the right-multiplication
156 # matrix for the successive basis elements b0, b1,... of
158 n
= len(superalgebra_basis
)
159 mult_table
= [[W
.zero() for i
in range(n
)] for j
in range(n
)]
162 product
= superalgebra_basis
[i
]*superalgebra_basis
[j
]
163 # product.to_vector() might live in a vector subspace
164 # if our parent algebra is already a subalgebra. We
165 # use V.from_vector() to make it "the right size" in
167 product_vector
= V
.from_vector(product
.to_vector())
168 mult_table
[i
][j
] = W
.coordinate_vector(product_vector
)
170 # The rank is the highest possible degree of a minimal
171 # polynomial, and is bounded above by the dimension. We know
172 # in this case that there's an element whose minimal
173 # polynomial has the same degree as the space's dimension
174 # (remember how we constructed the space?), so that must be
178 natural_basis
= tuple( b
.natural_representation()
179 for b
in superalgebra_basis
)
182 self
._vector
_space
= W
183 self
._superalgebra
_basis
= superalgebra_basis
186 fdeja
= super(FiniteDimensionalEuclideanJordanElementSubalgebra
, self
)
187 return fdeja
.__init
__(field
,
192 natural_basis
=natural_basis
)
195 def _a_regular_element(self
):
197 Override the superalgebra method to return the one
198 regular element that is sure to exist in this
199 subalgebra, namely the element that generated it.
203 sage: from mjo.eja.eja_algebra import random_eja
207 sage: set_random_seed()
208 sage: J = random_eja().random_element().subalgebra_generated_by()
209 sage: J._a_regular_element().is_regular()
213 if self
.dimension() == 0:
216 return self
.monomial(1)
219 def _element_constructor_(self
, elt
):
221 Construct an element of this subalgebra from the given one.
222 The only valid arguments are elements of the parent algebra
223 that happen to live in this subalgebra.
227 sage: from mjo.eja.eja_algebra import RealSymmetricEJA
228 sage: from mjo.eja.eja_subalgebra import FiniteDimensionalEuclideanJordanElementSubalgebra
232 sage: J = RealSymmetricEJA(3)
233 sage: x = sum( i*J.gens()[i] for i in range(6) )
234 sage: K = FiniteDimensionalEuclideanJordanElementSubalgebra(x)
235 sage: [ K(x^k) for k in range(J.rank()) ]
242 # Just as in the superalgebra class, we need to hack
243 # this special case to ensure that random_element() can
244 # coerce a ring zero into the algebra.
247 if elt
in self
.superalgebra():
248 coords
= self
.vector_space().coordinate_vector(elt
.to_vector())
249 return self
.from_vector(coords
)
254 Return the basis-element-index of this algebra's unit element.
261 Return the multiplicative identity element of this algebra.
263 The superclass method computes the identity element, which is
264 beyond overkill in this case: the algebra identity should be our
265 first basis element. We implement this via :meth:`one_basis`
266 because that method can optionally be used by other parts of the
271 sage: from mjo.eja.eja_algebra import (RealCartesianProductEJA,
276 sage: J = RealCartesianProductEJA(5)
278 e0 + e1 + e2 + e3 + e4
279 sage: x = sum(J.gens())
280 sage: A = x.subalgebra_generated_by()
283 sage: A.one().superalgebra_element()
284 e0 + e1 + e2 + e3 + e4
288 The identity element acts like the identity::
290 sage: set_random_seed()
291 sage: J = random_eja().random_element().subalgebra_generated_by()
292 sage: x = J.random_element()
293 sage: J.one()*x == x and x*J.one() == x
296 The matrix of the unit element's operator is the identity::
298 sage: set_random_seed()
299 sage: J = random_eja().random_element().subalgebra_generated_by()
300 sage: actual = J.one().operator().matrix()
301 sage: expected = matrix.identity(J.base_ring(), J.dimension())
302 sage: actual == expected
305 if self
.dimension() == 0:
308 return self
.monomial(self
.one_basis())
311 def natural_basis_space(self
):
313 Return the natural basis space of this algebra, which is identical
314 to that of its superalgebra.
316 This is correct "by definition," and avoids a mismatch when the
317 subalgebra is trivial (with no natural basis to infer anything
318 from) and the parent is not.
320 return self
.superalgebra().natural_basis_space()
323 def superalgebra(self
):
325 Return the superalgebra that this algebra was generated from.
327 return self
._superalgebra
330 def vector_space(self
):
334 sage: from mjo.eja.eja_algebra import RealSymmetricEJA
335 sage: from mjo.eja.eja_subalgebra import FiniteDimensionalEuclideanJordanElementSubalgebra
339 sage: J = RealSymmetricEJA(3)
340 sage: x = J.monomial(0) + 2*J.monomial(2) + 5*J.monomial(5)
341 sage: K = FiniteDimensionalEuclideanJordanElementSubalgebra(x)
342 sage: K.vector_space()
343 Vector space of degree 6 and dimension 3 over...
348 sage: (x^0).to_vector()
350 sage: (x^1).to_vector()
352 sage: (x^2).to_vector()
356 return self
._vector
_space
359 Element
= FiniteDimensionalEuclideanJordanElementSubalgebraElement