1 from sage
.matrix
.constructor
import matrix
3 from mjo
.eja
.eja_algebra
import FiniteDimensionalEuclideanJordanAlgebra
4 from mjo
.eja
.eja_element
import FiniteDimensionalEuclideanJordanAlgebraElement
6 class FiniteDimensionalEuclideanJordanSubalgebraElement(FiniteDimensionalEuclideanJordanAlgebraElement
):
10 sage: from mjo.eja.eja_algebra import random_eja
14 The matrix representation of an element in the subalgebra is
15 the same as its matrix representation in the superalgebra::
17 sage: set_random_seed()
18 sage: A = random_eja().random_element().subalgebra_generated_by()
19 sage: y = A.random_element()
20 sage: actual = y.to_matrix()
21 sage: expected = y.superalgebra_element().to_matrix()
22 sage: actual == expected
25 The left-multiplication-by operator for elements in the subalgebra
26 works like it does in the superalgebra, even if we orthonormalize
29 sage: set_random_seed()
30 sage: x = random_eja(AA).random_element()
31 sage: A = x.subalgebra_generated_by(orthonormalize_basis=True)
32 sage: y = A.random_element()
33 sage: y.operator()(A.one()) == y
38 def superalgebra_element(self
):
40 Return the object in our algebra's superalgebra that corresponds
45 sage: from mjo.eja.eja_algebra import (RealSymmetricEJA,
50 sage: J = RealSymmetricEJA(3)
51 sage: x = sum(J.gens())
53 e0 + e1 + e2 + e3 + e4 + e5
54 sage: A = x.subalgebra_generated_by()
57 sage: A(x).superalgebra_element()
58 e0 + e1 + e2 + e3 + e4 + e5
59 sage: y = sum(A.gens())
62 sage: B = y.subalgebra_generated_by()
65 sage: B(y).superalgebra_element()
70 We can convert back and forth faithfully::
72 sage: set_random_seed()
73 sage: J = random_eja()
74 sage: x = J.random_element()
75 sage: A = x.subalgebra_generated_by()
76 sage: A(x).superalgebra_element() == x
78 sage: y = A.random_element()
79 sage: A(y.superalgebra_element()) == y
81 sage: B = y.subalgebra_generated_by()
82 sage: B(y).superalgebra_element() == y
86 # As with the _element_constructor_() method on the
87 # algebra... even in a subspace of a subspace, the basis
88 # elements belong to the ambient space. As a result, only one
89 # level of coordinate_vector() is needed, regardless of how
90 # deeply we're nested.
91 W
= self
.parent().vector_space()
92 V
= self
.parent().superalgebra().vector_space()
94 # Multiply on the left because basis_matrix() is row-wise.
95 ambient_coords
= self
.to_vector()*W
.basis_matrix()
96 V_coords
= V
.coordinate_vector(ambient_coords
)
97 return self
.parent().superalgebra().from_vector(V_coords
)
102 class FiniteDimensionalEuclideanJordanSubalgebra(FiniteDimensionalEuclideanJordanAlgebra
):
104 A subalgebra of an EJA with a given basis.
108 sage: from mjo.eja.eja_algebra import (ComplexHermitianEJA,
110 ....: RealSymmetricEJA)
111 sage: from mjo.eja.eja_subalgebra import FiniteDimensionalEuclideanJordanSubalgebra
115 The following Peirce subalgebras of the 2-by-2 real symmetric
116 matrices do not contain the superalgebra's identity element::
118 sage: J = RealSymmetricEJA(2)
119 sage: E11 = matrix(AA, [ [1,0],
121 sage: E22 = matrix(AA, [ [0,0],
123 sage: K1 = FiniteDimensionalEuclideanJordanSubalgebra(J, (J(E11),))
124 sage: K1.one().to_matrix()
127 sage: K2 = FiniteDimensionalEuclideanJordanSubalgebra(J, (J(E22),))
128 sage: K2.one().to_matrix()
134 Ensure that our generator names don't conflict with the superalgebra::
136 sage: J = JordanSpinEJA(3)
137 sage: J.one().subalgebra_generated_by().gens()
139 sage: J = JordanSpinEJA(3, prefix='f')
140 sage: J.one().subalgebra_generated_by().gens()
142 sage: J = JordanSpinEJA(3, prefix='b')
143 sage: J.one().subalgebra_generated_by().gens()
146 Ensure that we can find subalgebras of subalgebras::
148 sage: A = ComplexHermitianEJA(3).one().subalgebra_generated_by()
149 sage: B = A.one().subalgebra_generated_by()
154 def __init__(self
, superalgebra
, basis
, category
=None, check_axioms
=True):
155 self
._superalgebra
= superalgebra
156 V
= self
._superalgebra
.vector_space()
157 field
= self
._superalgebra
.base_ring()
159 category
= self
._superalgebra
.category()
161 # A half-assed attempt to ensure that we don't collide with
162 # the superalgebra's prefix (ignoring the fact that there
163 # could be super-superelgrbas in scope). If possible, we
164 # try to "increment" the parent algebra's prefix, although
165 # this idea goes out the window fast because some prefixen
167 prefixen
= [ 'f', 'g', 'h', 'a', 'b', 'c', 'd' ]
169 prefix
= prefixen
[prefixen
.index(self
._superalgebra
.prefix()) + 1]
173 # If our superalgebra is a subalgebra of something else, then
174 # these vectors won't have the right coordinates for
175 # V.span_of_basis() unless we use V.from_vector() on them.
176 W
= V
.span_of_basis( V
.from_vector(b
.to_vector()) for b
in basis
)
180 # The tables are square if we're verifying that they
182 mult_table
= [[W
.zero() for j
in range(n
)] for i
in range(n
)]
183 ip_table
= [ [ self
._superalgebra
.inner_product(basis
[i
],basis
[j
])
187 mult_table
= [[W
.zero() for j
in range(i
+1)] for i
in range(n
)]
188 ip_table
= [ [ self
._superalgebra
.inner_product(basis
[i
],basis
[j
])
189 for j
in range(i
+1) ]
194 product
= basis
[i
]*basis
[j
]
195 # product.to_vector() might live in a vector subspace
196 # if our parent algebra is already a subalgebra. We
197 # use V.from_vector() to make it "the right size" in
199 product_vector
= V
.from_vector(product
.to_vector())
200 mult_table
[i
][j
] = W
.coordinate_vector(product_vector
)
202 mult_table
[j
][i
] = mult_table
[i
][j
]
204 matrix_basis
= tuple( b
.to_matrix() for b
in basis
)
207 self
._vector
_space
= W
209 fdeja
= super(FiniteDimensionalEuclideanJordanSubalgebra
, self
)
210 fdeja
.__init
__(field
,
215 matrix_basis
=matrix_basis
,
217 check_axioms
=check_axioms
)
221 def _element_constructor_(self
, elt
):
223 Construct an element of this subalgebra from the given one.
224 The only valid arguments are elements of the parent algebra
225 that happen to live in this subalgebra.
229 sage: from mjo.eja.eja_algebra import RealSymmetricEJA
230 sage: from mjo.eja.eja_subalgebra import FiniteDimensionalEuclideanJordanSubalgebra
234 sage: J = RealSymmetricEJA(3)
235 sage: X = matrix(AA, [ [0,0,1],
239 sage: basis = ( x, x^2 ) # x^2 is the identity matrix
240 sage: K = FiniteDimensionalEuclideanJordanSubalgebra(J, basis)
249 if elt
not in self
.superalgebra():
250 raise ValueError("not an element of this subalgebra")
252 # The extra hackery is because foo.to_vector() might not live
253 # in foo.parent().vector_space()! Subspaces of subspaces still
254 # have user bases in the ambient space, though, so only one
255 # level of coordinate_vector() is needed. In other words, if V
256 # is itself a subspace, the basis elements for W will be of
257 # the same length as the basis elements for V -- namely
258 # whatever the dimension of the ambient (parent of V?) space is.
259 V
= self
.superalgebra().vector_space()
260 W
= self
.vector_space()
262 # Multiply on the left because basis_matrix() is row-wise.
263 ambient_coords
= elt
.to_vector()*V
.basis_matrix()
264 W_coords
= W
.coordinate_vector(ambient_coords
)
265 return self
.from_vector(W_coords
)
269 def matrix_space(self
):
271 Return the matrix space of this algebra, which is identical to
272 that of its superalgebra.
274 This is correct "by definition," and avoids a mismatch when
275 the subalgebra is trivial (with no matrix basis elements to
276 infer anything from) and the parent is not.
278 return self
.superalgebra().matrix_space()
281 def superalgebra(self
):
283 Return the superalgebra that this algebra was generated from.
285 return self
._superalgebra
288 def vector_space(self
):
292 sage: from mjo.eja.eja_algebra import RealSymmetricEJA
293 sage: from mjo.eja.eja_subalgebra import FiniteDimensionalEuclideanJordanSubalgebra
297 sage: J = RealSymmetricEJA(3)
298 sage: E11 = matrix(ZZ, [ [1,0,0],
301 sage: E22 = matrix(ZZ, [ [0,0,0],
306 sage: basis = (b1, b2)
307 sage: K = FiniteDimensionalEuclideanJordanSubalgebra(J,basis)
308 sage: K.vector_space()
309 Vector space of degree 6 and dimension 2 over...
319 return self
._vector
_space
322 Element
= FiniteDimensionalEuclideanJordanSubalgebraElement