vector representations) back and forth faithfully::
sage: set_random_seed()
- sage: J = RealCartesianProductEJA(5)
+ sage: J = RealCartesianProductEJA.random_instance()
sage: x = J.random_element()
sage: J(x.to_vector().column()) == x
True
- sage: J = JordanSpinEJA(5)
+ sage: J = JordanSpinEJA.random_instance()
sage: x = J.random_element()
sage: J(x.to_vector().column()) == x
True
return self.from_vector(coords)
+ @staticmethod
+ def _max_test_case_size():
+ """
+ Return an integer "size" that is an upper bound on the size of
+ this algebra when it is used in a random test
+ case. Unfortunately, the term "size" is quite vague -- when
+ dealing with `R^n` under either the Hadamard or Jordan spin
+ product, the "size" refers to the dimension `n`. When dealing
+ with a matrix algebra (real symmetric or complex/quaternion
+ Hermitian), it refers to the size of the matrix, which is
+ far less than the dimension of the underlying vector space.
+
+ We default to five in this class, which is safe in `R^n`. The
+ matrix algebra subclasses (or any class where the "size" is
+ interpreted to be far less than the dimension) should override
+ with a smaller number.
+ """
+ return 5
+
+
def _repr_(self):
"""
Return a string representation of ``self``.
"""
X = x.natural_representation()
Y = y.natural_representation()
- return self.__class__.natural_inner_product(X,Y)
+ return self.natural_inner_product(X,Y)
def is_trivial(self):
return s.random_element()
+ @classmethod
+ def random_instance(cls, field=QQ, **kwargs):
+ """
+ Return a random instance of this type of algebra.
+
+ In subclasses for algebras that we know how to construct, this
+ is a shortcut for constructing test cases and examples.
+ """
+ if cls is FiniteDimensionalEuclideanJordanAlgebra:
+ # Red flag! But in theory we could do this I guess. The
+ # only finite-dimensional exceptional EJA is the
+ # octononions. So, we could just create an EJA from an
+ # associative matrix algebra (generated by a subset of
+ # elements) with the symmetric product. Or, we could punt
+ # to random_eja() here, override it in our subclasses, and
+ # not worry about it.
+ raise NotImplementedError
+
+ n = ZZ.random_element(1, cls._max_test_case_size())
+ return cls(n, field, **kwargs)
+
+
def rank(self):
"""
Return the rank of this EJA.
Our inner product satisfies the Jordan axiom::
sage: set_random_seed()
- sage: n = ZZ.random_element(1,5)
- sage: J = RealCartesianProductEJA(n)
+ sage: J = RealCartesianProductEJA.random_instance()
sage: x = J.random_element()
sage: y = J.random_element()
sage: z = J.random_element()
over `R^n`::
sage: set_random_seed()
- sage: n = ZZ.random_element(1,5)
- sage: J = RealCartesianProductEJA(n)
+ sage: J = RealCartesianProductEJA.random_instance()
sage: x = J.random_element()
sage: y = J.random_element()
sage: X = x.natural_representation()
sage: Y = y.natural_representation()
- sage: x.inner_product(y) == J.__class__.natural_inner_product(X,Y)
+ sage: x.inner_product(y) == J.natural_inner_product(X,Y)
True
"""
Euclidean Jordan algebra of dimension...
"""
-
- # The max_n component lets us choose different upper bounds on the
- # value "n" that gets passed to the constructor. This is needed
- # because e.g. R^{10} is reasonable to test, while the Hermitian
- # 10-by-10 quaternion matrices are not.
- (constructor, max_n) = choice([(RealCartesianProductEJA, 6),
- (JordanSpinEJA, 6),
- (RealSymmetricEJA, 5),
- (ComplexHermitianEJA, 4),
- (QuaternionHermitianEJA, 3)])
- n = ZZ.random_element(1, max_n)
- return constructor(n, field=QQ)
+ classname = choice([RealCartesianProductEJA,
+ JordanSpinEJA,
+ RealSymmetricEJA,
+ ComplexHermitianEJA,
+ QuaternionHermitianEJA])
+ return classname.random_instance()
SETUP::
- sage: from mjo.eja.eja_algebra import _embed_complex_matrix
+ sage: from mjo.eja.eja_algebra import (_embed_complex_matrix,
+ ....: ComplexHermitianEJA)
EXAMPLES::
Embedding is a homomorphism (isomorphism, in fact)::
sage: set_random_seed()
- sage: n = ZZ.random_element(5)
+ sage: n_max = ComplexHermitianEJA._max_test_case_size()
+ sage: n = ZZ.random_element(n_max)
sage: F = QuadraticField(-1, 'i')
sage: X = random_matrix(F, n)
sage: Y = random_matrix(F, n)
SETUP::
- sage: from mjo.eja.eja_algebra import _embed_quaternion_matrix
+ sage: from mjo.eja.eja_algebra import (_embed_quaternion_matrix,
+ ....: QuaternionHermitianEJA)
EXAMPLES::
Embedding is a homomorphism (isomorphism, in fact)::
sage: set_random_seed()
- sage: n = ZZ.random_element(5)
+ sage: n_max = QuaternionHermitianEJA._max_test_case_size()
+ sage: n = ZZ.random_element(n_max)
sage: Q = QuaternionAlgebra(QQ,-1,-1)
sage: X = random_matrix(Q, n)
sage: Y = random_matrix(Q, n)
return matrix(Q, n/4, elements)
-# The inner product used for the real symmetric simple EJA.
-# We keep it as a separate function because e.g. the complex
-# algebra uses the same inner product, except divided by 2.
-def _matrix_ip(X,Y):
- X_mat = X.natural_representation()
- Y_mat = Y.natural_representation()
- return (X_mat*Y_mat).trace()
-
class RealSymmetricEJA(FiniteDimensionalEuclideanJordanAlgebra):
"""
The dimension of this algebra is `(n^2 + n) / 2`::
sage: set_random_seed()
- sage: n = ZZ.random_element(1,5)
+ sage: n_max = RealSymmetricEJA._max_test_case_size()
+ sage: n = ZZ.random_element(1, n_max)
sage: J = RealSymmetricEJA(n)
sage: J.dimension() == (n^2 + n)/2
True
The Jordan multiplication is what we think it is::
sage: set_random_seed()
- sage: n = ZZ.random_element(1,5)
- sage: J = RealSymmetricEJA(n)
+ sage: J = RealSymmetricEJA.random_instance()
sage: x = J.random_element()
sage: y = J.random_element()
sage: actual = (x*y).natural_representation()
Our inner product satisfies the Jordan axiom::
sage: set_random_seed()
- sage: n = ZZ.random_element(1,5)
- sage: J = RealSymmetricEJA(n)
+ sage: J = RealSymmetricEJA.random_instance()
sage: x = J.random_element()
sage: y = J.random_element()
sage: z = J.random_element()
product unless we specify otherwise::
sage: set_random_seed()
- sage: n = ZZ.random_element(1,5)
- sage: J = RealSymmetricEJA(n)
+ sage: J = RealSymmetricEJA.random_instance()
sage: all( b.norm() == 1 for b in J.gens() )
True
the operator is self-adjoint by the Jordan axiom::
sage: set_random_seed()
- sage: n = ZZ.random_element(1,5)
- sage: x = RealSymmetricEJA(n).random_element()
+ sage: x = RealSymmetricEJA.random_instance().random_element()
sage: x.operator().matrix().is_symmetric()
True
field = NumberField(p, 'sqrt2', embedding=RLF(2).sqrt())
S = [ s.change_ring(field) for s in S ]
self._basis_normalizers = tuple(
- ~(self.__class__.natural_inner_product(s,s).sqrt())
- for s in S )
+ ~(self.natural_inner_product(s,s).sqrt()) for s in S )
S = tuple( s*c for (s,c) in zip(S,self._basis_normalizers) )
Qs = _multiplication_table_from_matrix_basis(S)
natural_basis=S,
**kwargs)
+ @staticmethod
+ def _max_test_case_size():
+ return 5
class ComplexHermitianEJA(FiniteDimensionalEuclideanJordanAlgebra):
The dimension of this algebra is `n^2`::
sage: set_random_seed()
- sage: n = ZZ.random_element(1,5)
+ sage: n_max = ComplexHermitianEJA._max_test_case_size()
+ sage: n = ZZ.random_element(1, n_max)
sage: J = ComplexHermitianEJA(n)
sage: J.dimension() == n^2
True
The Jordan multiplication is what we think it is::
sage: set_random_seed()
- sage: n = ZZ.random_element(1,5)
- sage: J = ComplexHermitianEJA(n)
+ sage: J = ComplexHermitianEJA.random_instance()
sage: x = J.random_element()
sage: y = J.random_element()
sage: actual = (x*y).natural_representation()
Our inner product satisfies the Jordan axiom::
sage: set_random_seed()
- sage: n = ZZ.random_element(1,5)
- sage: J = ComplexHermitianEJA(n)
+ sage: J = ComplexHermitianEJA.random_instance()
sage: x = J.random_element()
sage: y = J.random_element()
sage: z = J.random_element()
product unless we specify otherwise::
sage: set_random_seed()
- sage: n = ZZ.random_element(1,4)
- sage: J = ComplexHermitianEJA(n)
+ sage: J = ComplexHermitianEJA.random_instance()
sage: all( b.norm() == 1 for b in J.gens() )
True
the operator is self-adjoint by the Jordan axiom::
sage: set_random_seed()
- sage: n = ZZ.random_element(1,5)
- sage: x = ComplexHermitianEJA(n).random_element()
+ sage: x = ComplexHermitianEJA.random_instance().random_element()
sage: x.operator().matrix().is_symmetric()
True
field = NumberField(p, 'sqrt2', embedding=RLF(2).sqrt())
S = [ s.change_ring(field) for s in S ]
self._basis_normalizers = tuple(
- ~(self.__class__.natural_inner_product(s,s).sqrt())
- for s in S )
+ ~(self.natural_inner_product(s,s).sqrt()) for s in S )
S = tuple( s*c for (s,c) in zip(S,self._basis_normalizers) )
Qs = _multiplication_table_from_matrix_basis(S)
**kwargs)
+ @staticmethod
+ def _max_test_case_size():
+ return 4
+
@staticmethod
def natural_inner_product(X,Y):
Xu = _unembed_complex_matrix(X)
TESTS:
- The dimension of this algebra is `n^2`::
+ The dimension of this algebra is `2*n^2 - n`::
sage: set_random_seed()
- sage: n = ZZ.random_element(1,4)
+ sage: n_max = QuaternionHermitianEJA._max_test_case_size()
+ sage: n = ZZ.random_element(1, n_max)
sage: J = QuaternionHermitianEJA(n)
sage: J.dimension() == 2*(n^2) - n
True
The Jordan multiplication is what we think it is::
sage: set_random_seed()
- sage: n = ZZ.random_element(1,4)
- sage: J = QuaternionHermitianEJA(n)
+ sage: J = QuaternionHermitianEJA.random_instance()
sage: x = J.random_element()
sage: y = J.random_element()
sage: actual = (x*y).natural_representation()
Our inner product satisfies the Jordan axiom::
sage: set_random_seed()
- sage: n = ZZ.random_element(1,4)
- sage: J = QuaternionHermitianEJA(n)
+ sage: J = QuaternionHermitianEJA.random_instance()
sage: x = J.random_element()
sage: y = J.random_element()
sage: z = J.random_element()
product unless we specify otherwise::
sage: set_random_seed()
- sage: n = ZZ.random_element(1,4)
- sage: J = QuaternionHermitianEJA(n)
+ sage: J = QuaternionHermitianEJA.random_instance()
sage: all( b.norm() == 1 for b in J.gens() )
True
the operator is self-adjoint by the Jordan axiom::
sage: set_random_seed()
- sage: n = ZZ.random_element(1,5)
- sage: x = QuaternionHermitianEJA(n).random_element()
+ sage: x = QuaternionHermitianEJA.random_instance().random_element()
sage: x.operator().matrix().is_symmetric()
True
field = NumberField(p, 'sqrt2', embedding=RLF(2).sqrt())
S = [ s.change_ring(field) for s in S ]
self._basis_normalizers = tuple(
- ~(self.__class__.natural_inner_product(s,s).sqrt())
- for s in S )
+ ~(self.natural_inner_product(s,s).sqrt()) for s in S )
S = tuple( s*c for (s,c) in zip(S,self._basis_normalizers) )
Qs = _multiplication_table_from_matrix_basis(S)
natural_basis=S,
**kwargs)
+ @staticmethod
+ def _max_test_case_size():
+ return 3
+
@staticmethod
def natural_inner_product(X,Y):
Xu = _unembed_quaternion_matrix(X)
Our inner product satisfies the Jordan axiom::
sage: set_random_seed()
- sage: n = ZZ.random_element(1,5)
- sage: J = JordanSpinEJA(n)
+ sage: J = JordanSpinEJA.random_instance()
sage: x = J.random_element()
sage: y = J.random_element()
sage: z = J.random_element()
over `R^n`::
sage: set_random_seed()
- sage: n = ZZ.random_element(1,5)
- sage: J = JordanSpinEJA(n)
+ sage: J = JordanSpinEJA.random_instance()
sage: x = J.random_element()
sage: y = J.random_element()
sage: X = x.natural_representation()
sage: Y = y.natural_representation()
- sage: x.inner_product(y) == J.__class__.natural_inner_product(X,Y)
+ sage: x.inner_product(y) == J.natural_inner_product(X,Y)
True
"""