]> gitweb.michael.orlitzky.com - sage.d.git/blob - mjo/eja/eja_element_subalgebra.py
eja: begin major overhaul of class hierarchy and naming.
[sage.d.git] / mjo / eja / eja_element_subalgebra.py
1 from sage.matrix.constructor import matrix
2 from sage.misc.cachefunc import cached_method
3 from sage.rings.all import QQ
4
5 from mjo.eja.eja_subalgebra import FiniteDimensionalEJASubalgebra
6
7
8 class FiniteDimensionalEJAElementSubalgebra(FiniteDimensionalEJASubalgebra):
9 def __init__(self, elt, orthonormalize=True, **kwargs):
10 superalgebra = elt.parent()
11
12 powers = tuple( elt**k for k in range(superalgebra.dimension()) )
13 power_vectors = ( p.to_vector() for p in powers )
14 P = matrix(superalgebra.base_ring(), power_vectors)
15
16 if orthonormalize:
17 basis = powers # let god sort 'em out
18 else:
19 # Echelonize the matrix ourselves, because otherwise the
20 # call to P.pivot_rows() below can choose a non-optimal
21 # row-reduction algorithm. In particular, scaling can
22 # help over AA because it avoids the RecursionError that
23 # gets thrown when we have to look too hard for a root.
24 #
25 # Beware: QQ supports an entirely different set of "algorithm"
26 # keywords than do AA and RR.
27 algo = None
28 if superalgebra.base_ring() is not QQ:
29 algo = "scaled_partial_pivoting"
30 P.echelonize(algorithm=algo)
31
32 # In this case, we just need to figure out which elements
33 # of the "powers" list are redundant... First compute the
34 # vector subspace spanned by the powers of the given
35 # element.
36
37 # Figure out which powers form a linearly-independent set.
38 ind_rows = P.pivot_rows()
39
40 # Pick those out of the list of all powers.
41 basis = tuple(map(powers.__getitem__, ind_rows))
42
43
44 super().__init__(superalgebra,
45 basis,
46 associative=True,
47 **kwargs)
48
49 # The rank is the highest possible degree of a minimal
50 # polynomial, and is bounded above by the dimension. We know
51 # in this case that there's an element whose minimal
52 # polynomial has the same degree as the space's dimension
53 # (remember how we constructed the space?), so that must be
54 # its rank too.
55 self.rank.set_cache(self.dimension())
56
57
58 @cached_method
59 def one(self):
60 """
61 Return the multiplicative identity element of this algebra.
62
63 The superclass method computes the identity element, which is
64 beyond overkill in this case: the superalgebra identity
65 restricted to this algebra is its identity. Note that we can't
66 count on the first basis element being the identity -- it might
67 have been scaled if we orthonormalized the basis.
68
69 SETUP::
70
71 sage: from mjo.eja.eja_algebra import (HadamardEJA,
72 ....: random_eja)
73
74 EXAMPLES::
75
76 sage: J = HadamardEJA(5)
77 sage: J.one()
78 e0 + e1 + e2 + e3 + e4
79 sage: x = sum(J.gens())
80 sage: A = x.subalgebra_generated_by()
81 sage: A.one()
82 f0
83 sage: A.one().superalgebra_element()
84 e0 + e1 + e2 + e3 + e4
85
86 TESTS:
87
88 The identity element acts like the identity over the rationals::
89
90 sage: set_random_seed()
91 sage: x = random_eja(field=QQ,orthonormalize=False).random_element()
92 sage: A = x.subalgebra_generated_by()
93 sage: x = A.random_element()
94 sage: A.one()*x == x and x*A.one() == x
95 True
96
97 The identity element acts like the identity over the algebraic
98 reals with an orthonormal basis::
99
100 sage: set_random_seed()
101 sage: x = random_eja().random_element()
102 sage: A = x.subalgebra_generated_by(orthonormalize_basis=True)
103 sage: x = A.random_element()
104 sage: A.one()*x == x and x*A.one() == x
105 True
106
107 The matrix of the unit element's operator is the identity over
108 the rationals::
109
110 sage: set_random_seed()
111 sage: x = random_eja(field=QQ,orthonormalize=False).random_element()
112 sage: A = x.subalgebra_generated_by()
113 sage: actual = A.one().operator().matrix()
114 sage: expected = matrix.identity(A.base_ring(), A.dimension())
115 sage: actual == expected
116 True
117
118 The matrix of the unit element's operator is the identity over
119 the algebraic reals with an orthonormal basis::
120
121 sage: set_random_seed()
122 sage: x = random_eja().random_element()
123 sage: A = x.subalgebra_generated_by(orthonormalize_basis=True)
124 sage: actual = A.one().operator().matrix()
125 sage: expected = matrix.identity(A.base_ring(), A.dimension())
126 sage: actual == expected
127 True
128
129 """
130 if self.dimension() == 0:
131 return self.zero()
132
133 return self(self.superalgebra().one())
134