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.
46 Return ``self`` raised to the power ``n``.
48 Jordan algebras are always power-associative; see for
49 example Faraut and Koranyi, Proposition II.1.2 (ii).
57 return A
.element_class(A
, self
.vector()*(self
.matrix()**(n
-1)))
60 def span_of_powers(self
):
62 Return the vector space spanned by successive powers of
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()) )
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).
82 sage: J.one().degree()
84 sage: e0,e1,e2,e3 = J.gens()
85 sage: (e0 - e1).degree()
89 return self
.span_of_powers().dimension()
92 def minimal_polynomial(self
):
93 return self
.matrix().minimal_polynomial()
95 def characteristic_polynomial(self
):
96 return self
.matrix().characteristic_polynomial()
99 def eja_rn(dimension
, field
=QQ
):
101 Return the Euclidean Jordan Algebra corresponding to the set
102 `R^n` under the Hadamard product.
106 This multiplication table can be verified by hand::
109 sage: e0,e1,e2 = J.gens()
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
) ]
132 return FiniteDimensionalEuclideanJordanAlgebra(field
,Qs
)
135 def eja_ln(dimension
, field
=QQ
):
137 Return the Jordan algebra corresponding to the Lorentz "ice cream"
138 cone of the given ``dimension``.
142 This multiplication table can be verified by hand::
145 sage: e0,e1,e2,e3 = J.gens()
161 In one dimension, this is the reals under multiplication::
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
)
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)
182 return FiniteDimensionalEuclideanJordanAlgebra(field
,Qs
)