X-Git-Url: http://gitweb.michael.orlitzky.com/?a=blobdiff_plain;f=mjo%2Feja%2Feja_element.py;h=47f6ff080c1d48a1a32b4903991aa0ec5bd0a502;hb=f0cabe7c6e37781e4f92c9ba0e0c7413a5f6b939;hp=52933e2decdcf3d9dc1218a568bf29bcff6cf5f1;hpb=827b203e50561de19857935f456509cf2392ee70;p=sage.d.git diff --git a/mjo/eja/eja_element.py b/mjo/eja/eja_element.py index 52933e2..47f6ff0 100644 --- a/mjo/eja/eja_element.py +++ b/mjo/eja/eja_element.py @@ -4,7 +4,8 @@ from sage.modules.free_module import VectorSpace 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): """ @@ -131,7 +132,8 @@ class FiniteDimensionalEJAElement(IndexedFreeModuleElement): SETUP:: - sage: from mjo.eja.eja_algebra import HadamardEJA + sage: from mjo.eja.eja_algebra import (random_eja, + ....: HadamardEJA) EXAMPLES: @@ -156,10 +158,10 @@ class FiniteDimensionalEJAElement(IndexedFreeModuleElement): 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:: @@ -167,8 +169,8 @@ class FiniteDimensionalEJAElement(IndexedFreeModuleElement): sage: J = HadamardEJA(3) sage: p1 = J.one().characteristic_polynomial() sage: q1 = J.zero().characteristic_polynomial() - sage: e0,e1,e2 = J.gens() - sage: A = (e0 + 2*e1 + 3*e2).subalgebra_generated_by() # dim 3 + sage: b0,b1,b2 = J.gens() + sage: A = (b0 + 2*b1 + 3*b2).subalgebra_generated_by() # dim 3 sage: p2 = A.one().characteristic_polynomial() sage: q2 = A.zero().characteristic_polynomial() sage: p1 == p2 @@ -348,7 +350,6 @@ class FiniteDimensionalEJAElement(IndexedFreeModuleElement): EXAMPLES:: sage: J = JordanSpinEJA(2) - sage: e0,e1 = J.gens() sage: x = sum( J.gens() ) sage: x.det() 0 @@ -356,7 +357,6 @@ class FiniteDimensionalEJAElement(IndexedFreeModuleElement): :: sage: J = JordanSpinEJA(3) - sage: e0,e1,e2 = J.gens() sage: x = sum( J.gens() ) sage: x.det() -1 @@ -391,7 +391,7 @@ class FiniteDimensionalEJAElement(IndexedFreeModuleElement): 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) @@ -406,21 +406,6 @@ class FiniteDimensionalEJAElement(IndexedFreeModuleElement): 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() @@ -793,7 +778,9 @@ class FiniteDimensionalEJAElement(IndexedFreeModuleElement): sage: J = JordanSpinEJA(5) sage: J.one().is_regular() False - sage: e0, e1, e2, e3, e4 = J.gens() # e0 is the identity + sage: b0, b1, b2, b3, b4 = J.gens() + sage: b0 == J.one() + True sage: for x in J.gens(): ....: (J.one() + x).is_regular() False @@ -843,8 +830,8 @@ class FiniteDimensionalEJAElement(IndexedFreeModuleElement): sage: J = JordanSpinEJA(4) sage: J.one().degree() 1 - sage: e0,e1,e2,e3 = J.gens() - sage: (e0 - e1).degree() + sage: b0,b1,b2,b3 = J.gens() + sage: (b0 - b1).degree() 2 In the spin factor algebra (of rank two), all elements that @@ -1008,8 +995,8 @@ class FiniteDimensionalEJAElement(IndexedFreeModuleElement): 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(): @@ -1034,8 +1021,9 @@ class FiniteDimensionalEJAElement(IndexedFreeModuleElement): 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) @@ -1096,29 +1084,27 @@ class FiniteDimensionalEJAElement(IndexedFreeModuleElement): sage: J = ComplexHermitianEJA(3) sage: J.one() - e0 + e3 + e8 + 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 = QuaternionHermitianEJA(2) sage: J.one() - e0 + e5 + 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:: @@ -1136,18 +1122,10 @@ class FiniteDimensionalEJAElement(IndexedFreeModuleElement): 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()) ) @@ -1355,11 +1333,11 @@ class FiniteDimensionalEJAElement(IndexedFreeModuleElement): sage: J = RealSymmetricEJA(3) sage: J.one() - e0 + e2 + e5 + b0 + b2 + b5 sage: J.one().spectral_decomposition() - [(1, e0 + e2 + e5)] + [(1, b0 + b2 + b5)] sage: J.zero().spectral_decomposition() - [(0, e0 + e2 + e5)] + [(0, b0 + b2 + b5)] TESTS:: @@ -1384,13 +1362,13 @@ class FiniteDimensionalEJAElement(IndexedFreeModuleElement): The spectral decomposition should work in subalgebras, too:: sage: J = RealSymmetricEJA(4) - sage: (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9) = J.gens() - sage: A = 2*e5 - 2*e8 + sage: (b0, b1, b2, b3, b4, b5, b6, b7, b8, b9) = J.gens() + sage: A = 2*b5 - 2*b8 sage: (lambda1, c1) = A.spectral_decomposition()[1] sage: (J0, J5, J1) = J.peirce_decomposition(c1) sage: (f0, f1, f2) = J1.gens() sage: f0.spectral_decomposition() - [(0, f2), (1, f0)] + [(0, 1.000000000000000?*c2), (1, 1.000000000000000?*c0)] """ A = self.subalgebra_generated_by(orthonormalize=True) @@ -1665,3 +1643,29 @@ class FiniteDimensionalEJAElement(IndexedFreeModuleElement): """ 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 )