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()
98 return self
.span_of_powers().dimension()
101 def minimal_polynomial(self
):
102 return self
.matrix().minimal_polynomial()
104 def characteristic_polynomial(self
):
105 return self
.matrix().characteristic_polynomial()
108 def eja_rn(dimension
, field
=QQ
):
110 Return the Euclidean Jordan Algebra corresponding to the set
111 `R^n` under the Hadamard product.
115 This multiplication table can be verified by hand::
118 sage: e0,e1,e2 = J.gens()
133 # The FiniteDimensionalAlgebra constructor takes a list of
134 # matrices, the ith representing right multiplication by the ith
135 # basis element in the vector space. So if e_1 = (1,0,0), then
136 # right (Hadamard) multiplication of x by e_1 picks out the first
137 # component of x; and likewise for the ith basis element e_i.
138 Qs
= [ matrix(field
, dimension
, dimension
, lambda k
,j
: 1*(k
== j
== i
))
139 for i
in xrange(dimension
) ]
141 return FiniteDimensionalEuclideanJordanAlgebra(field
,Qs
)
144 def eja_ln(dimension
, field
=QQ
):
146 Return the Jordan algebra corresponding to the Lorentz "ice cream"
147 cone of the given ``dimension``.
151 This multiplication table can be verified by hand::
154 sage: e0,e1,e2,e3 = J.gens()
170 In one dimension, this is the reals under multiplication::
179 id_matrix
= identity_matrix(field
,dimension
)
180 for i
in xrange(dimension
):
181 ei
= id_matrix
.column(i
)
182 Qi
= zero_matrix(field
,dimension
)
185 Qi
+= diagonal_matrix(dimension
, [ei
[0]]*dimension
)
186 # The addition of the diagonal matrix adds an extra ei[0] in the
187 # upper-left corner of the matrix.
188 Qi
[0,0] = Qi
[0,0] * ~
field(2)
191 return FiniteDimensionalEuclideanJordanAlgebra(field
,Qs
)