1 from sage
.matrix
.constructor
import matrix
3 from mjo
.eja
.eja_subalgebra
import FiniteDimensionalEuclideanJordanSubalgebra
6 class FiniteDimensionalEuclideanJordanElementSubalgebra(FiniteDimensionalEuclideanJordanSubalgebra
):
7 def __init__(self
, elt
, orthonormalize_basis
):
8 self
._superalgebra
= elt
.parent()
9 category
= self
._superalgebra
.category().Associative()
10 V
= self
._superalgebra
.vector_space()
11 field
= self
._superalgebra
.base_ring()
13 # This list is guaranteed to contain all independent powers,
14 # because it's the maximal set of powers that could possibly
15 # be independent (by a dimension argument).
16 powers
= [ elt
**k
for k
in range(V
.dimension()) ]
17 power_vectors
= [ p
.to_vector() for p
in powers
]
18 P
= matrix(field
, power_vectors
)
20 if orthonormalize_basis
== False:
21 # In this case, we just need to figure out which elements
22 # of the "powers" list are redundant... First compute the
23 # vector subspace spanned by the powers of the given
26 # Figure out which powers form a linearly-independent set.
27 ind_rows
= P
.pivot_rows()
29 # Pick those out of the list of all powers.
30 superalgebra_basis
= tuple(map(powers
.__getitem
__, ind_rows
))
31 basis_vectors
= map(power_vectors
.__getitem
__, ind_rows
)
33 # If we're going to orthonormalize the basis anyway, we
34 # might as well just do Gram-Schmidt on the whole list of
35 # powers. The redundant ones will get zero'd out. If this
36 # looks like a roundabout way to orthonormalize, it is.
37 # But converting everything from algebra elements to vectors
38 # to matrices and then back again turns out to be about
39 # as fast as reimplementing our own Gram-Schmidt that
41 G
,_
= P
.gram_schmidt(orthonormal
=True)
42 basis_vectors
= [ g
for g
in G
.rows() if not g
.is_zero() ]
43 superalgebra_basis
= [ self
._superalgebra
.from_vector(b
)
44 for b
in basis_vectors
]
46 fdeja
= super(FiniteDimensionalEuclideanJordanElementSubalgebra
, self
)
47 fdeja
.__init
__(self
._superalgebra
,
52 # The rank is the highest possible degree of a minimal
53 # polynomial, and is bounded above by the dimension. We know
54 # in this case that there's an element whose minimal
55 # polynomial has the same degree as the space's dimension
56 # (remember how we constructed the space?), so that must be
58 self
.rank
.set_cache(self
.dimension())
63 Return the multiplicative identity element of this algebra.
65 The superclass method computes the identity element, which is
66 beyond overkill in this case: the superalgebra identity
67 restricted to this algebra is its identity. Note that we can't
68 count on the first basis element being the identity -- it migth
69 have been scaled if we orthonormalized the basis.
73 sage: from mjo.eja.eja_algebra import (HadamardEJA,
78 sage: J = HadamardEJA(5)
80 e0 + e1 + e2 + e3 + e4
81 sage: x = sum(J.gens())
82 sage: A = x.subalgebra_generated_by()
85 sage: A.one().superalgebra_element()
86 e0 + e1 + e2 + e3 + e4
90 The identity element acts like the identity over the rationals::
92 sage: set_random_seed()
93 sage: x = random_eja(field=QQ).random_element()
94 sage: A = x.subalgebra_generated_by()
95 sage: x = A.random_element()
96 sage: A.one()*x == x and x*A.one() == x
99 The identity element acts like the identity over the algebraic
100 reals with an orthonormal basis::
102 sage: set_random_seed()
103 sage: x = random_eja().random_element()
104 sage: A = x.subalgebra_generated_by(orthonormalize_basis=True)
105 sage: x = A.random_element()
106 sage: A.one()*x == x and x*A.one() == x
109 The matrix of the unit element's operator is the identity over
112 sage: set_random_seed()
113 sage: x = random_eja(field=QQ).random_element()
114 sage: A = x.subalgebra_generated_by()
115 sage: actual = A.one().operator().matrix()
116 sage: expected = matrix.identity(A.base_ring(), A.dimension())
117 sage: actual == expected
120 The matrix of the unit element's operator is the identity over
121 the algebraic reals with an orthonormal basis::
123 sage: set_random_seed()
124 sage: x = random_eja().random_element()
125 sage: A = x.subalgebra_generated_by(orthonormalize_basis=True)
126 sage: actual = A.one().operator().matrix()
127 sage: expected = matrix.identity(A.base_ring(), A.dimension())
128 sage: actual == expected
132 if self
.dimension() == 0:
135 sa_one
= self
.superalgebra().one().to_vector()
136 # The extra hackery is because foo.to_vector() might not
137 # live in foo.parent().vector_space()!
138 coords
= sum( a
*b
for (a
,b
)
140 self
.superalgebra().vector_space().basis()) )
141 return self
.from_vector(self
.vector_space().coordinate_vector(coords
))