]> gitweb.michael.orlitzky.com - sage.d.git/blob - mjo/eja/euclidean_jordan_algebra.py
eja: add span_of_powers() method.
[sage.d.git] / mjo / eja / euclidean_jordan_algebra.py
1 """
2 Euclidean Jordan Algebras. These are formally-real Jordan Algebras;
3 specifically those where u^2 + v^2 = 0 implies that u = v = 0. They
4 are used in optimization, and have some additional nice methods beyond
5 what can be supported in a general Jordan Algebra.
6 """
7
8 from sage.algebras.finite_dimensional_algebras.finite_dimensional_algebra import FiniteDimensionalAlgebra
9 from sage.algebras.finite_dimensional_algebras.finite_dimensional_algebra_element import FiniteDimensionalAlgebraElement
10
11 class FiniteDimensionalEuclideanJordanAlgebra(FiniteDimensionalAlgebra):
12 @staticmethod
13 def __classcall__(cls, field, mult_table, names='e', category=None):
14 fda = super(FiniteDimensionalEuclideanJordanAlgebra, cls)
15 return fda.__classcall_private__(cls,
16 field,
17 mult_table,
18 names,
19 category)
20
21 def __init__(self, field, mult_table, names='e', category=None):
22 fda = super(FiniteDimensionalEuclideanJordanAlgebra, self)
23 fda.__init__(field, mult_table, names, category)
24
25
26 def _repr_(self):
27 """
28 Return a string representation of ``self``.
29 """
30 return "Euclidean Jordan algebra of degree {} over {}".format(self.degree(), self.base_ring())
31
32 def rank(self):
33 """
34 Return the rank of this EJA.
35 """
36 raise NotImplementedError
37
38
39 class Element(FiniteDimensionalAlgebraElement):
40 """
41 An element of a Euclidean Jordan algebra.
42 """
43
44 def __pow__(self, n):
45 """
46 Return ``self`` raised to the power ``n``.
47
48 Jordan algebras are always power-associative; see for
49 example Faraut and Koranyi, Proposition II.1.2 (ii).
50 """
51 A = self.parent()
52 if n == 0:
53 return A.one()
54 elif n == 1:
55 return self
56 else:
57 return A.element_class(A, self.vector()*(self.matrix()**(n-1)))
58
59
60 def span_of_powers(self):
61 """
62 Return the vector space spanned by successive powers of
63 this element.
64 """
65 # The dimension of the subalgebra can't be greater than
66 # the big algebra, so just put everything into a list
67 # and let span() get rid of the excess.
68 V = self.vector().parent()
69 return V.span( (self**d).vector() for d in xrange(V.dimension()) )
70
71
72 def degree(self):
73 """
74 Compute the degree of this element the straightforward way
75 according to the definition; by appending powers to a list
76 and figuring out its dimension (that is, whether or not
77 they're linearly dependent).
78
79 EXAMPLES::
80
81 sage: J = eja_ln(4)
82 sage: J.one().degree()
83 1
84 sage: e0,e1,e2,e3 = J.gens()
85 sage: (e0 - e1).degree()
86 2
87
88 """
89 return self.span_of_powers().dimension()
90
91
92 def minimal_polynomial(self):
93 return self.matrix().minimal_polynomial()
94
95 def characteristic_polynomial(self):
96 return self.matrix().characteristic_polynomial()
97
98
99 def eja_rn(dimension, field=QQ):
100 """
101 Return the Euclidean Jordan Algebra corresponding to the set
102 `R^n` under the Hadamard product.
103
104 EXAMPLES:
105
106 This multiplication table can be verified by hand::
107
108 sage: J = eja_rn(3)
109 sage: e0,e1,e2 = J.gens()
110 sage: e0*e0
111 e0
112 sage: e0*e1
113 0
114 sage: e0*e2
115 0
116 sage: e1*e1
117 e1
118 sage: e1*e2
119 0
120 sage: e2*e2
121 e2
122
123 """
124 # The FiniteDimensionalAlgebra constructor takes a list of
125 # matrices, the ith representing right multiplication by the ith
126 # basis element in the vector space. So if e_1 = (1,0,0), then
127 # right (Hadamard) multiplication of x by e_1 picks out the first
128 # component of x; and likewise for the ith basis element e_i.
129 Qs = [ matrix(field, dimension, dimension, lambda k,j: 1*(k == j == i))
130 for i in xrange(dimension) ]
131
132 return FiniteDimensionalEuclideanJordanAlgebra(field,Qs)
133
134
135 def eja_ln(dimension, field=QQ):
136 """
137 Return the Jordan algebra corresponding to the Lorentz "ice cream"
138 cone of the given ``dimension``.
139
140 EXAMPLES:
141
142 This multiplication table can be verified by hand::
143
144 sage: J = eja_ln(4)
145 sage: e0,e1,e2,e3 = J.gens()
146 sage: e0*e0
147 e0
148 sage: e0*e1
149 e1
150 sage: e0*e2
151 e2
152 sage: e0*e3
153 e3
154 sage: e1*e2
155 0
156 sage: e1*e3
157 0
158 sage: e2*e3
159 0
160
161 In one dimension, this is the reals under multiplication::
162
163 sage: J1 = eja_ln(1)
164 sage: J2 = eja_rn(1)
165 sage: J1 == J2
166 True
167
168 """
169 Qs = []
170 id_matrix = identity_matrix(field,dimension)
171 for i in xrange(dimension):
172 ei = id_matrix.column(i)
173 Qi = zero_matrix(field,dimension)
174 Qi.set_row(0, ei)
175 Qi.set_column(0, ei)
176 Qi += diagonal_matrix(dimension, [ei[0]]*dimension)
177 # The addition of the diagonal matrix adds an extra ei[0] in the
178 # upper-left corner of the matrix.
179 Qi[0,0] = Qi[0,0] * ~field(2)
180 Qs.append(Qi)
181
182 return FiniteDimensionalEuclideanJordanAlgebra(field,Qs)