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 superalgebra
= elt
.parent()
105 # First compute the vector subspace spanned by the powers of
107 V
= superalgebra
.vector_space()
108 superalgebra_basis
= [superalgebra
.one()]
109 # If our superalgebra is a subalgebra of something else, then
110 # superalgebra.one().to_vector() won't have the right
111 # coordinates unless we use V.from_vector() below.
112 basis_vectors
= [V
.from_vector(superalgebra
.one().to_vector())]
113 W
= V
.span_of_basis(basis_vectors
)
114 for exponent
in range(1, V
.dimension()):
115 new_power
= elt
**exponent
116 basis_vectors
.append( V
.from_vector(new_power
.to_vector()) )
118 W
= V
.span_of_basis(basis_vectors
)
119 superalgebra_basis
.append( new_power
)
121 # Vectors weren't independent; bail and keep the
122 # last subspace that worked.
125 # Make the basis hashable for UniqueRepresentation.
126 superalgebra_basis
= tuple(superalgebra_basis
)
128 # Now figure out the entries of the right-multiplication
129 # matrix for the successive basis elements b0, b1,... of
131 field
= superalgebra
.base_ring()
132 n
= len(superalgebra_basis
)
133 mult_table
= [[W
.zero() for i
in range(n
)] for j
in range(n
)]
136 product
= superalgebra_basis
[i
]*superalgebra_basis
[j
]
137 # product.to_vector() might live in a vector subspace
138 # if our parent algebra is already a subalgebra. We
139 # use V.from_vector() to make it "the right size" in
141 product_vector
= V
.from_vector(product
.to_vector())
142 mult_table
[i
][j
] = W
.coordinate_vector(product_vector
)
144 # A half-assed attempt to ensure that we don't collide with
145 # the superalgebra's prefix (ignoring the fact that there
146 # could be super-superelgrbas in scope). If possible, we
147 # try to "increment" the parent algebra's prefix, although
148 # this idea goes out the window fast because some prefixen
150 prefixen
= [ 'f', 'g', 'h', 'a', 'b', 'c', 'd' ]
152 prefix
= prefixen
[prefixen
.index(superalgebra
.prefix()) + 1]
156 # The rank is the highest possible degree of a minimal
157 # polynomial, and is bounded above by the dimension. We know
158 # in this case that there's an element whose minimal
159 # polynomial has the same degree as the space's dimension
160 # (remember how we constructed the space?), so that must be
164 category
= superalgebra
.category().Associative()
165 natural_basis
= tuple( b
.natural_representation()
166 for b
in superalgebra_basis
)
168 self
._superalgebra
= superalgebra
169 self
._vector
_space
= W
170 self
._superalgebra
_basis
= superalgebra_basis
173 fdeja
= super(FiniteDimensionalEuclideanJordanElementSubalgebra
, self
)
174 return fdeja
.__init
__(field
,
179 natural_basis
=natural_basis
)
182 def _element_constructor_(self
, elt
):
184 Construct an element of this subalgebra from the given one.
185 The only valid arguments are elements of the parent algebra
186 that happen to live in this subalgebra.
190 sage: from mjo.eja.eja_algebra import RealSymmetricEJA
191 sage: from mjo.eja.eja_subalgebra import FiniteDimensionalEuclideanJordanElementSubalgebra
195 sage: J = RealSymmetricEJA(3)
196 sage: x = sum( i*J.gens()[i] for i in range(6) )
197 sage: K = FiniteDimensionalEuclideanJordanElementSubalgebra(x)
198 sage: [ K(x^k) for k in range(J.rank()) ]
205 # Just as in the superalgebra class, we need to hack
206 # this special case to ensure that random_element() can
207 # coerce a ring zero into the algebra.
210 if elt
in self
.superalgebra():
211 coords
= self
.vector_space().coordinate_vector(elt
.to_vector())
212 return self
.from_vector(coords
)
217 Return the basis-element-index of this algebra's unit element.
224 Return the multiplicative identity element of this algebra.
226 The superclass method computes the identity element, which is
227 beyond overkill in this case: the algebra identity should be our
228 first basis element. We implement this via :meth:`one_basis`
229 because that method can optionally be used by other parts of the
234 sage: from mjo.eja.eja_algebra import (RealCartesianProductEJA,
239 sage: J = RealCartesianProductEJA(5)
241 e0 + e1 + e2 + e3 + e4
242 sage: x = sum(J.gens())
243 sage: A = x.subalgebra_generated_by()
246 sage: A.one().superalgebra_element()
247 e0 + e1 + e2 + e3 + e4
251 The identity element acts like the identity::
253 sage: set_random_seed()
254 sage: J = random_eja().random_element().subalgebra_generated_by()
255 sage: x = J.random_element()
256 sage: J.one()*x == x and x*J.one() == x
259 The matrix of the unit element's operator is the identity::
261 sage: set_random_seed()
262 sage: J = random_eja().random_element().subalgebra_generated_by()
263 sage: actual = J.one().operator().matrix()
264 sage: expected = matrix.identity(J.base_ring(), J.dimension())
265 sage: actual == expected
268 return self
.monomial(self
.one_basis())
271 def superalgebra(self
):
273 Return the superalgebra that this algebra was generated from.
275 return self
._superalgebra
278 def vector_space(self
):
282 sage: from mjo.eja.eja_algebra import RealSymmetricEJA
283 sage: from mjo.eja.eja_subalgebra import FiniteDimensionalEuclideanJordanElementSubalgebra
287 sage: J = RealSymmetricEJA(3)
288 sage: x = sum( i*J.gens()[i] for i in range(6) )
289 sage: K = FiniteDimensionalEuclideanJordanElementSubalgebra(x)
290 sage: K.vector_space()
291 Vector space of degree 6 and dimension 3 over Rational Field
296 sage: (x^0).to_vector()
298 sage: (x^1).to_vector()
300 sage: (x^2).to_vector()
301 (10, 14, 21, 19, 31, 50)
304 return self
._vector
_space
307 Element
= FiniteDimensionalEuclideanJordanElementSubalgebraElement