from sage.modules.with_basis.indexed_element import IndexedFreeModuleElement
from mjo.eja.eja_operator import FiniteDimensionalEJAOperator
-from mjo.eja.eja_utils import _mat2vec, _scale
+from mjo.eja.eja_utils import _scale
+
class FiniteDimensionalEJAElement(IndexedFreeModuleElement):
"""
SETUP::
- sage: from mjo.eja.eja_algebra import HadamardEJA
+ sage: from mjo.eja.eja_algebra import (random_eja,
+ ....: HadamardEJA)
EXAMPLES:
to zero on that element::
sage: set_random_seed()
- sage: x = HadamardEJA(3).random_element()
+ sage: x = random_eja().random_element()
sage: p = x.characteristic_polynomial()
- sage: x.apply_univariate_polynomial(p)
- 0
+ sage: x.apply_univariate_polynomial(p).is_zero()
+ True
The characteristic polynomials of the zero and unit elements
should be what we think they are in a subalgebra, too::
sage: (x*y).det() == x.det()*y.det()
True
- The determinant in matrix algebras is just the usual determinant::
+ The determinant in real matrix algebras is the usual determinant::
sage: set_random_seed()
sage: X = matrix.random(QQ,3)
sage: actual2 == expected
True
- ::
-
- sage: set_random_seed()
- sage: J1 = ComplexHermitianEJA(2)
- sage: J2 = ComplexHermitianEJA(2,field=QQ,orthonormalize=False)
- sage: X = matrix.random(GaussianIntegers(), 2)
- sage: X = X + X.H
- sage: expected = AA(X.det())
- sage: actual1 = J1(J1.real_embed(X)).det()
- sage: actual2 = J2(J2.real_embed(X)).det()
- sage: expected == actual1
- True
- sage: expected == actual2
- True
-
"""
P = self.parent()
r = P.rank()
two here so that said elements actually exist::
sage: set_random_seed()
- sage: n_max = max(2, JordanSpinEJA._max_random_instance_size())
- sage: n = ZZ.random_element(2, n_max)
+ sage: d_max = JordanSpinEJA._max_random_instance_dimension()
+ sage: n = ZZ.random_element(2, max(2,d_max))
sage: J = JordanSpinEJA(n)
sage: y = J.random_element()
sage: while y == y.coefficient(0)*J.one():
and in particular, a re-scaling of the basis::
sage: set_random_seed()
- sage: n_max = RealSymmetricEJA._max_random_instance_size()
- sage: n = ZZ.random_element(1, n_max)
+ sage: d_max = RealSymmetricEJA._max_random_instance_dimension()
+ sage: d = ZZ.random_element(1, d_max)
+ sage: n = RealSymmetricEJA._max_random_instance_size(d)
sage: J1 = RealSymmetricEJA(n)
sage: J2 = RealSymmetricEJA(n,orthonormalize=False)
sage: X = random_matrix(AA,n)
sage: J.one()
b0 + b3 + b8
sage: J.one().to_matrix()
- [1 0 0 0 0 0]
- [0 1 0 0 0 0]
- [0 0 1 0 0 0]
- [0 0 0 1 0 0]
- [0 0 0 0 1 0]
- [0 0 0 0 0 1]
+ +---+---+---+
+ | 1 | 0 | 0 |
+ +---+---+---+
+ | 0 | 1 | 0 |
+ +---+---+---+
+ | 0 | 0 | 1 |
+ +---+---+---+
::
sage: J.one()
b0 + b5
sage: J.one().to_matrix()
- [1 0 0 0 0 0 0 0]
- [0 1 0 0 0 0 0 0]
- [0 0 1 0 0 0 0 0]
- [0 0 0 1 0 0 0 0]
- [0 0 0 0 1 0 0 0]
- [0 0 0 0 0 1 0 0]
- [0 0 0 0 0 0 1 0]
- [0 0 0 0 0 0 0 1]
+ +---+---+
+ | 1 | 0 |
+ +---+---+
+ | 0 | 1 |
+ +---+---+
This also works in Cartesian product algebras::
B = self.parent().matrix_basis()
W = self.parent().matrix_space()
- if hasattr(W, 'cartesian_factors'):
- # Aaaaand linear combinations don't work in Cartesian
- # product spaces, even though they provide a method with
- # that name. This is hidden behind an "if" because the
- # _scale() function is slow.
- pairs = zip(B, self.to_vector())
- return W.sum( _scale(b, alpha) for (b,alpha) in pairs )
- else:
- # This is just a manual "from_vector()", but of course
- # matrix spaces aren't vector spaces in sage, so they
- # don't have a from_vector() method.
- return W.linear_combination( zip(B, self.to_vector()) )
+ # This is just a manual "from_vector()", but of course
+ # matrix spaces aren't vector spaces in sage, so they
+ # don't have a from_vector() method.
+ return W.linear_combination( zip(B, self.to_vector()) )
sage: (J0, J5, J1) = J.peirce_decomposition(c1)
sage: (f0, f1, f2) = J1.gens()
sage: f0.spectral_decomposition()
- [(0, c2), (1, c0)]
+ [(0, 1.000000000000000?*c2), (1, 1.000000000000000?*c0)]
"""
A = self.subalgebra_generated_by(orthonormalize=True)
"""
return self.trace_inner_product(self).sqrt()
+
+
+class CartesianProductEJAElement(FiniteDimensionalEJAElement):
+ def det(self):
+ r"""
+ Compute the determinant of this product-element using the
+ determianants of its factors.
+
+ This result Follows from the spectral decomposition of (say)
+ the pair `(x,y)` in terms of the Jordan frame `\left\{ (c_1,
+ 0),(c_2, 0),...,(0,d_1),(0,d_2),... \right\}.
+ """
+ from sage.misc.misc_c import prod
+ return prod( f.det() for f in self.cartesian_factors() )
+
+ def to_matrix(self):
+ # An override is necessary to call our custom _scale().
+ B = self.parent().matrix_basis()
+ W = self.parent().matrix_space()
+
+ # Aaaaand linear combinations don't work in Cartesian
+ # product spaces, even though they provide a method with
+ # that name. This is hidden behind an "if" because the
+ # _scale() function is slow.
+ pairs = zip(B, self.to_vector())
+ return W.sum( _scale(b, alpha) for (b,alpha) in pairs )