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.
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
11 class FiniteDimensionalEuclideanJordanAlgebra(FiniteDimensionalAlgebra
):
13 def __classcall__(cls
, field
, mult_table
, names
='e', category
=None):
14 fda
= super(FiniteDimensionalEuclideanJordanAlgebra
, cls
)
15 return fda
.__classcall
_private
__(cls
,
21 def __init__(self
, field
, mult_table
, names
='e', category
=None):
22 fda
= super(FiniteDimensionalEuclideanJordanAlgebra
, self
)
23 fda
.__init
__(field
, mult_table
, names
, category
)
28 Return a string representation of ``self``.
30 return "Euclidean Jordan algebra of degree {} over {}".format(self
.degree(), self
.base_ring())
34 Return the rank of this EJA.
36 raise NotImplementedError
39 class Element(FiniteDimensionalAlgebraElement
):
41 An element of a Euclidean Jordan algebra.
43 Since EJAs are commutative, the "right multiplication" matrix is
44 also the left multiplication matrix and must be symmetric::
46 sage: set_random_seed()
48 sage: J.random_element().matrix().is_symmetric()
55 Return ``self`` raised to the power ``n``.
57 Jordan algebras are always power-associative; see for
58 example Faraut and Koranyi, Proposition II.1.2 (ii).
66 return A
.element_class(A
, self
.vector()*(self
.matrix()**(n
-1)))
69 def span_of_powers(self
):
71 Return the vector space spanned by successive powers of
74 # The dimension of the subalgebra can't be greater than
75 # the big algebra, so just put everything into a list
76 # and let span() get rid of the excess.
77 V
= self
.vector().parent()
78 return V
.span( (self
**d
).vector() for d
in xrange(V
.dimension()) )
83 Compute the degree of this element the straightforward way
84 according to the definition; by appending powers to a list
85 and figuring out its dimension (that is, whether or not
86 they're linearly dependent).
91 sage: J.one().degree()
93 sage: e0,e1,e2,e3 = J.gens()
94 sage: (e0 - e1).degree()
97 In the spin factor algebra (of rank two), all elements that
98 aren't multiples of the identity are regular::
100 sage: set_random_seed()
101 sage: n = ZZ.random_element(1,10).abs()
103 sage: x = J.random_element()
104 sage: x == x.coefficient(0)*J.one() or x.degree() == 2
108 return self
.span_of_powers().dimension()
111 def subalgebra_generated_by(self
):
113 Return the subalgebra of the parent EJA generated by this element.
115 # First get the subspace spanned by the powers of myself...
116 V
= self
.span_of_powers()
119 # Now figure out the entries of the right-multiplication
120 # matrix for the successive basis elements b0, b1,... of
123 for b_right
in V
.basis():
124 eja_b_right
= self
.parent()(b_right
)
126 # The first row of the right-multiplication matrix by
127 # b1 is what we get if we apply that matrix to b1. The
128 # second row of the right multiplication matrix by b1
129 # is what we get when we apply that matrix to b2...
130 for b_left
in V
.basis():
131 eja_b_left
= self
.parent()(b_left
)
132 # Multiply in the original EJA, but then get the
133 # coordinates from the subalgebra in terms of its
135 this_row
= V
.coordinates((eja_b_left
*eja_b_right
).vector())
136 b_right_rows
.append(this_row
)
137 b_right_matrix
= matrix(F
, b_right_rows
)
138 mats
.append(b_right_matrix
)
140 return FiniteDimensionalEuclideanJordanAlgebra(F
, mats
)
143 def minimal_polynomial(self
):
144 return self
.matrix().minimal_polynomial()
146 def characteristic_polynomial(self
):
147 return self
.matrix().characteristic_polynomial()
150 def eja_rn(dimension
, field
=QQ
):
152 Return the Euclidean Jordan Algebra corresponding to the set
153 `R^n` under the Hadamard product.
157 This multiplication table can be verified by hand::
160 sage: e0,e1,e2 = J.gens()
175 # The FiniteDimensionalAlgebra constructor takes a list of
176 # matrices, the ith representing right multiplication by the ith
177 # basis element in the vector space. So if e_1 = (1,0,0), then
178 # right (Hadamard) multiplication of x by e_1 picks out the first
179 # component of x; and likewise for the ith basis element e_i.
180 Qs
= [ matrix(field
, dimension
, dimension
, lambda k
,j
: 1*(k
== j
== i
))
181 for i
in xrange(dimension
) ]
183 return FiniteDimensionalEuclideanJordanAlgebra(field
,Qs
)
186 def eja_ln(dimension
, field
=QQ
):
188 Return the Jordan algebra corresponding to the Lorentz "ice cream"
189 cone of the given ``dimension``.
193 This multiplication table can be verified by hand::
196 sage: e0,e1,e2,e3 = J.gens()
212 In one dimension, this is the reals under multiplication::
221 id_matrix
= identity_matrix(field
,dimension
)
222 for i
in xrange(dimension
):
223 ei
= id_matrix
.column(i
)
224 Qi
= zero_matrix(field
,dimension
)
227 Qi
+= diagonal_matrix(dimension
, [ei
[0]]*dimension
)
228 # The addition of the diagonal matrix adds an extra ei[0] in the
229 # upper-left corner of the matrix.
230 Qi
[0,0] = Qi
[0,0] * ~
field(2)
233 return FiniteDimensionalEuclideanJordanAlgebra(field
,Qs
)