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 superalgebra_basis
= [self
._superalgebra
.one()]
141 # If our superalgebra is a subalgebra of something else, then
142 # superalgebra.one().to_vector() won't have the right
143 # coordinates unless we use V.from_vector() below.
144 basis_vectors
= [V
.from_vector(self
._superalgebra
.one().to_vector())]
145 W
= V
.span_of_basis(basis_vectors
)
146 for exponent
in range(1, V
.dimension()):
147 new_power
= elt
**exponent
148 basis_vectors
.append( V
.from_vector(new_power
.to_vector()) )
150 W
= V
.span_of_basis(basis_vectors
)
151 superalgebra_basis
.append( new_power
)
153 # Vectors weren't independent; bail and keep the
154 # last subspace that worked.
157 # Make the basis hashable for UniqueRepresentation.
158 superalgebra_basis
= tuple(superalgebra_basis
)
160 # Now figure out the entries of the right-multiplication
161 # matrix for the successive basis elements b0, b1,... of
163 n
= len(superalgebra_basis
)
164 mult_table
= [[W
.zero() for i
in range(n
)] for j
in range(n
)]
167 product
= superalgebra_basis
[i
]*superalgebra_basis
[j
]
168 # product.to_vector() might live in a vector subspace
169 # if our parent algebra is already a subalgebra. We
170 # use V.from_vector() to make it "the right size" in
172 product_vector
= V
.from_vector(product
.to_vector())
173 mult_table
[i
][j
] = W
.coordinate_vector(product_vector
)
175 # The rank is the highest possible degree of a minimal
176 # polynomial, and is bounded above by the dimension. We know
177 # in this case that there's an element whose minimal
178 # polynomial has the same degree as the space's dimension
179 # (remember how we constructed the space?), so that must be
183 natural_basis
= tuple( b
.natural_representation()
184 for b
in superalgebra_basis
)
187 self
._vector
_space
= W
188 self
._superalgebra
_basis
= superalgebra_basis
191 fdeja
= super(FiniteDimensionalEuclideanJordanElementSubalgebra
, self
)
192 return fdeja
.__init
__(field
,
197 natural_basis
=natural_basis
)
200 def _a_regular_element(self
):
202 Override the superalgebra method to return the one
203 regular element that is sure to exist in this
204 subalgebra, namely the element that generated it.
208 sage: from mjo.eja.eja_algebra import random_eja
212 sage: set_random_seed()
213 sage: J = random_eja().random_element().subalgebra_generated_by()
214 sage: J._a_regular_element().is_regular()
218 if self
.dimension() == 0:
221 return self
.monomial(1)
224 def _element_constructor_(self
, elt
):
226 Construct an element of this subalgebra from the given one.
227 The only valid arguments are elements of the parent algebra
228 that happen to live in this subalgebra.
232 sage: from mjo.eja.eja_algebra import RealSymmetricEJA
233 sage: from mjo.eja.eja_subalgebra import FiniteDimensionalEuclideanJordanElementSubalgebra
237 sage: J = RealSymmetricEJA(3)
238 sage: x = sum( i*J.gens()[i] for i in range(6) )
239 sage: K = FiniteDimensionalEuclideanJordanElementSubalgebra(x)
240 sage: [ K(x^k) for k in range(J.rank()) ]
247 # Just as in the superalgebra class, we need to hack
248 # this special case to ensure that random_element() can
249 # coerce a ring zero into the algebra.
252 if elt
in self
.superalgebra():
253 coords
= self
.vector_space().coordinate_vector(elt
.to_vector())
254 return self
.from_vector(coords
)
259 Return the basis-element-index of this algebra's unit element.
266 Return the multiplicative identity element of this algebra.
268 The superclass method computes the identity element, which is
269 beyond overkill in this case: the algebra identity should be our
270 first basis element. We implement this via :meth:`one_basis`
271 because that method can optionally be used by other parts of the
276 sage: from mjo.eja.eja_algebra import (RealCartesianProductEJA,
281 sage: J = RealCartesianProductEJA(5)
283 e0 + e1 + e2 + e3 + e4
284 sage: x = sum(J.gens())
285 sage: A = x.subalgebra_generated_by()
288 sage: A.one().superalgebra_element()
289 e0 + e1 + e2 + e3 + e4
293 The identity element acts like the identity::
295 sage: set_random_seed()
296 sage: J = random_eja().random_element().subalgebra_generated_by()
297 sage: x = J.random_element()
298 sage: J.one()*x == x and x*J.one() == x
301 The matrix of the unit element's operator is the identity::
303 sage: set_random_seed()
304 sage: J = random_eja().random_element().subalgebra_generated_by()
305 sage: actual = J.one().operator().matrix()
306 sage: expected = matrix.identity(J.base_ring(), J.dimension())
307 sage: actual == expected
310 if self
.dimension() == 0:
313 return self
.monomial(self
.one_basis())
316 def natural_basis_space(self
):
318 Return the natural basis space of this algebra, which is identical
319 to that of its superalgebra.
321 This is correct "by definition," and avoids a mismatch when the
322 subalgebra is trivial (with no natural basis to infer anything
323 from) and the parent is not.
325 return self
.superalgebra().natural_basis_space()
328 def superalgebra(self
):
330 Return the superalgebra that this algebra was generated from.
332 return self
._superalgebra
335 def vector_space(self
):
339 sage: from mjo.eja.eja_algebra import RealSymmetricEJA
340 sage: from mjo.eja.eja_subalgebra import FiniteDimensionalEuclideanJordanElementSubalgebra
344 sage: J = RealSymmetricEJA(3)
345 sage: x = J.monomial(0) + 2*J.monomial(2) + 5*J.monomial(5)
346 sage: K = FiniteDimensionalEuclideanJordanElementSubalgebra(x)
347 sage: K.vector_space()
348 Vector space of degree 6 and dimension 3 over...
353 sage: (x^0).to_vector()
355 sage: (x^1).to_vector()
357 sage: (x^2).to_vector()
361 return self
._vector
_space
364 Element
= FiniteDimensionalEuclideanJordanElementSubalgebraElement