X-Git-Url: http://gitweb.michael.orlitzky.com/?a=blobdiff_plain;f=mjo%2Feja%2Feja_algebra.py;h=081abd303c32d35c9376ad99ecf2732a14ea3e9b;hb=95ae8e7b0ddca840da9631603a2f37cca888468b;hp=ea62da8ca796031bd99382c5886bb1091d145b78;hpb=de451def1161cc9dfefcfc125523029881cb160a;p=sage.d.git diff --git a/mjo/eja/eja_algebra.py b/mjo/eja/eja_algebra.py index ea62da8..081abd3 100644 --- a/mjo/eja/eja_algebra.py +++ b/mjo/eja/eja_algebra.py @@ -1187,9 +1187,7 @@ class RationalBasisEJA(FiniteDimensionalEJA): jordan_product, inner_product, field=AA, - orthonormalize=True, check_field=True, - check_axioms=True, **kwargs): if check_field: @@ -1212,15 +1210,13 @@ class RationalBasisEJA(FiniteDimensionalEJA): field=QQ, orthonormalize=False, check_field=False, - check_axioms=False, - **kwargs) + check_axioms=False) super().__init__(basis, jordan_product, inner_product, field=field, check_field=check_field, - check_axioms=check_axioms, **kwargs) @cached_method @@ -2317,25 +2313,25 @@ class BilinearFormEJA(ConcreteEJA): raise ValueError("bilinear form is not positive-definite") def inner_product(x,y): - return (B*x).inner_product(y) + return (y.T*B*x)[0,0] def jordan_product(x,y): P = x.parent() - x0 = x[0] - xbar = x[1:] - y0 = y[0] - ybar = y[1:] - z0 = inner_product(x,y) + x0 = x[0,0] + xbar = x[1:,0] + y0 = y[0,0] + ybar = y[1:,0] + z0 = (y.T*x)[0,0] zbar = y0*xbar + x0*ybar - return P((z0,) + tuple(zbar)) + return P([0] + zbar.list()) # We know this is a valid EJA, but will double-check # if the user passes check_axioms=True. if "check_axioms" not in kwargs: kwargs["check_axioms"] = False n = B.nrows() - standard_basis = FreeModule(ZZ, n).basis() - super(BilinearFormEJA, self).__init__(standard_basis, + column_basis = tuple( b.column() for b in FreeModule(ZZ, n).basis() ) + super(BilinearFormEJA, self).__init__(column_basis, jordan_product, inner_product, **kwargs) @@ -2516,243 +2512,243 @@ class TrivialEJA(ConcreteEJA): # inappropriate for us. return cls(**kwargs) -class DirectSumEJA(ConcreteEJA): - r""" - The external (orthogonal) direct sum of two other Euclidean Jordan - algebras. Essentially the Cartesian product of its two factors. - Every Euclidean Jordan algebra decomposes into an orthogonal - direct sum of simple Euclidean Jordan algebras, so no generality - is lost by providing only this construction. - - SETUP:: - - sage: from mjo.eja.eja_algebra import (random_eja, - ....: HadamardEJA, - ....: RealSymmetricEJA, - ....: DirectSumEJA) - - EXAMPLES:: - - sage: J1 = HadamardEJA(2) - sage: J2 = RealSymmetricEJA(3) - sage: J = DirectSumEJA(J1,J2) - sage: J.dimension() - 8 - sage: J.rank() - 5 - - TESTS: - - The external direct sum construction is only valid when the two factors - have the same base ring; an error is raised otherwise:: - - sage: set_random_seed() - sage: J1 = random_eja(field=AA) - sage: J2 = random_eja(field=QQ,orthonormalize=False) - sage: J = DirectSumEJA(J1,J2) - Traceback (most recent call last): - ... - ValueError: algebras must share the same base field - - """ - def __init__(self, J1, J2, **kwargs): - if J1.base_ring() != J2.base_ring(): - raise ValueError("algebras must share the same base field") - field = J1.base_ring() - - self._factors = (J1, J2) - n1 = J1.dimension() - n2 = J2.dimension() - n = n1+n2 - V = VectorSpace(field, n) - mult_table = [ [ V.zero() for j in range(i+1) ] - for i in range(n) ] - for i in range(n1): - for j in range(i+1): - p = (J1.monomial(i)*J1.monomial(j)).to_vector() - mult_table[i][j] = V(p.list() + [field.zero()]*n2) - - for i in range(n2): - for j in range(i+1): - p = (J2.monomial(i)*J2.monomial(j)).to_vector() - mult_table[n1+i][n1+j] = V([field.zero()]*n1 + p.list()) - - # TODO: build the IP table here from the two constituent IP - # matrices (it'll be block diagonal, I think). - ip_table = [ [ field.zero() for j in range(i+1) ] - for i in range(n) ] - super(DirectSumEJA, self).__init__(field, - mult_table, - ip_table, - check_axioms=False, - **kwargs) - self.rank.set_cache(J1.rank() + J2.rank()) - - - def factors(self): - r""" - Return the pair of this algebra's factors. - - SETUP:: - - sage: from mjo.eja.eja_algebra import (HadamardEJA, - ....: JordanSpinEJA, - ....: DirectSumEJA) - - EXAMPLES:: - - sage: J1 = HadamardEJA(2, field=QQ) - sage: J2 = JordanSpinEJA(3, field=QQ) - sage: J = DirectSumEJA(J1,J2) - sage: J.factors() - (Euclidean Jordan algebra of dimension 2 over Rational Field, - Euclidean Jordan algebra of dimension 3 over Rational Field) - - """ - return self._factors - - def projections(self): - r""" - Return a pair of projections onto this algebra's factors. - - SETUP:: - - sage: from mjo.eja.eja_algebra import (JordanSpinEJA, - ....: ComplexHermitianEJA, - ....: DirectSumEJA) - - EXAMPLES:: - - sage: J1 = JordanSpinEJA(2) - sage: J2 = ComplexHermitianEJA(2) - sage: J = DirectSumEJA(J1,J2) - sage: (pi_left, pi_right) = J.projections() - sage: J.one().to_vector() - (1, 0, 1, 0, 0, 1) - sage: pi_left(J.one()).to_vector() - (1, 0) - sage: pi_right(J.one()).to_vector() - (1, 0, 0, 1) - - """ - (J1,J2) = self.factors() - m = J1.dimension() - n = J2.dimension() - V_basis = self.vector_space().basis() - # Need to specify the dimensions explicitly so that we don't - # wind up with a zero-by-zero matrix when we want e.g. a - # zero-by-two matrix (important for composing things). - P1 = matrix(self.base_ring(), m, m+n, V_basis[:m]) - P2 = matrix(self.base_ring(), n, m+n, V_basis[m:]) - pi_left = FiniteDimensionalEJAOperator(self,J1,P1) - pi_right = FiniteDimensionalEJAOperator(self,J2,P2) - return (pi_left, pi_right) - - def inclusions(self): - r""" - Return the pair of inclusion maps from our factors into us. - - SETUP:: - - sage: from mjo.eja.eja_algebra import (random_eja, - ....: JordanSpinEJA, - ....: RealSymmetricEJA, - ....: DirectSumEJA) - - EXAMPLES:: - - sage: J1 = JordanSpinEJA(3) - sage: J2 = RealSymmetricEJA(2) - sage: J = DirectSumEJA(J1,J2) - sage: (iota_left, iota_right) = J.inclusions() - sage: iota_left(J1.zero()) == J.zero() - True - sage: iota_right(J2.zero()) == J.zero() - True - sage: J1.one().to_vector() - (1, 0, 0) - sage: iota_left(J1.one()).to_vector() - (1, 0, 0, 0, 0, 0) - sage: J2.one().to_vector() - (1, 0, 1) - sage: iota_right(J2.one()).to_vector() - (0, 0, 0, 1, 0, 1) - sage: J.one().to_vector() - (1, 0, 0, 1, 0, 1) - - TESTS: - - Composing a projection with the corresponding inclusion should - produce the identity map, and mismatching them should produce - the zero map:: - - sage: set_random_seed() - sage: J1 = random_eja() - sage: J2 = random_eja() - sage: J = DirectSumEJA(J1,J2) - sage: (iota_left, iota_right) = J.inclusions() - sage: (pi_left, pi_right) = J.projections() - sage: pi_left*iota_left == J1.one().operator() - True - sage: pi_right*iota_right == J2.one().operator() - True - sage: (pi_left*iota_right).is_zero() - True - sage: (pi_right*iota_left).is_zero() - True - - """ - (J1,J2) = self.factors() - m = J1.dimension() - n = J2.dimension() - V_basis = self.vector_space().basis() - # Need to specify the dimensions explicitly so that we don't - # wind up with a zero-by-zero matrix when we want e.g. a - # two-by-zero matrix (important for composing things). - I1 = matrix.column(self.base_ring(), m, m+n, V_basis[:m]) - I2 = matrix.column(self.base_ring(), n, m+n, V_basis[m:]) - iota_left = FiniteDimensionalEJAOperator(J1,self,I1) - iota_right = FiniteDimensionalEJAOperator(J2,self,I2) - return (iota_left, iota_right) - - def inner_product(self, x, y): - r""" - The standard Cartesian inner-product. - - We project ``x`` and ``y`` onto our factors, and add up the - inner-products from the subalgebras. - - SETUP:: - - - sage: from mjo.eja.eja_algebra import (HadamardEJA, - ....: QuaternionHermitianEJA, - ....: DirectSumEJA) - - EXAMPLE:: - - sage: J1 = HadamardEJA(3,field=QQ) - sage: J2 = QuaternionHermitianEJA(2,field=QQ,orthonormalize=False) - sage: J = DirectSumEJA(J1,J2) - sage: x1 = J1.one() - sage: x2 = x1 - sage: y1 = J2.one() - sage: y2 = y1 - sage: x1.inner_product(x2) - 3 - sage: y1.inner_product(y2) - 2 - sage: J.one().inner_product(J.one()) - 5 - - """ - (pi_left, pi_right) = self.projections() - x1 = pi_left(x) - x2 = pi_right(x) - y1 = pi_left(y) - y2 = pi_right(y) - - return (x1.inner_product(y1) + x2.inner_product(y2)) +# class DirectSumEJA(ConcreteEJA): +# r""" +# The external (orthogonal) direct sum of two other Euclidean Jordan +# algebras. Essentially the Cartesian product of its two factors. +# Every Euclidean Jordan algebra decomposes into an orthogonal +# direct sum of simple Euclidean Jordan algebras, so no generality +# is lost by providing only this construction. + +# SETUP:: + +# sage: from mjo.eja.eja_algebra import (random_eja, +# ....: HadamardEJA, +# ....: RealSymmetricEJA, +# ....: DirectSumEJA) + +# EXAMPLES:: + +# sage: J1 = HadamardEJA(2) +# sage: J2 = RealSymmetricEJA(3) +# sage: J = DirectSumEJA(J1,J2) +# sage: J.dimension() +# 8 +# sage: J.rank() +# 5 + +# TESTS: + +# The external direct sum construction is only valid when the two factors +# have the same base ring; an error is raised otherwise:: + +# sage: set_random_seed() +# sage: J1 = random_eja(field=AA) +# sage: J2 = random_eja(field=QQ,orthonormalize=False) +# sage: J = DirectSumEJA(J1,J2) +# Traceback (most recent call last): +# ... +# ValueError: algebras must share the same base field + +# """ +# def __init__(self, J1, J2, **kwargs): +# if J1.base_ring() != J2.base_ring(): +# raise ValueError("algebras must share the same base field") +# field = J1.base_ring() + +# self._factors = (J1, J2) +# n1 = J1.dimension() +# n2 = J2.dimension() +# n = n1+n2 +# V = VectorSpace(field, n) +# mult_table = [ [ V.zero() for j in range(i+1) ] +# for i in range(n) ] +# for i in range(n1): +# for j in range(i+1): +# p = (J1.monomial(i)*J1.monomial(j)).to_vector() +# mult_table[i][j] = V(p.list() + [field.zero()]*n2) + +# for i in range(n2): +# for j in range(i+1): +# p = (J2.monomial(i)*J2.monomial(j)).to_vector() +# mult_table[n1+i][n1+j] = V([field.zero()]*n1 + p.list()) + +# # TODO: build the IP table here from the two constituent IP +# # matrices (it'll be block diagonal, I think). +# ip_table = [ [ field.zero() for j in range(i+1) ] +# for i in range(n) ] +# super(DirectSumEJA, self).__init__(field, +# mult_table, +# ip_table, +# check_axioms=False, +# **kwargs) +# self.rank.set_cache(J1.rank() + J2.rank()) + + +# def factors(self): +# r""" +# Return the pair of this algebra's factors. + +# SETUP:: + +# sage: from mjo.eja.eja_algebra import (HadamardEJA, +# ....: JordanSpinEJA, +# ....: DirectSumEJA) + +# EXAMPLES:: + +# sage: J1 = HadamardEJA(2, field=QQ) +# sage: J2 = JordanSpinEJA(3, field=QQ) +# sage: J = DirectSumEJA(J1,J2) +# sage: J.factors() +# (Euclidean Jordan algebra of dimension 2 over Rational Field, +# Euclidean Jordan algebra of dimension 3 over Rational Field) + +# """ +# return self._factors + +# def projections(self): +# r""" +# Return a pair of projections onto this algebra's factors. + +# SETUP:: + +# sage: from mjo.eja.eja_algebra import (JordanSpinEJA, +# ....: ComplexHermitianEJA, +# ....: DirectSumEJA) + +# EXAMPLES:: + +# sage: J1 = JordanSpinEJA(2) +# sage: J2 = ComplexHermitianEJA(2) +# sage: J = DirectSumEJA(J1,J2) +# sage: (pi_left, pi_right) = J.projections() +# sage: J.one().to_vector() +# (1, 0, 1, 0, 0, 1) +# sage: pi_left(J.one()).to_vector() +# (1, 0) +# sage: pi_right(J.one()).to_vector() +# (1, 0, 0, 1) + +# """ +# (J1,J2) = self.factors() +# m = J1.dimension() +# n = J2.dimension() +# V_basis = self.vector_space().basis() +# # Need to specify the dimensions explicitly so that we don't +# # wind up with a zero-by-zero matrix when we want e.g. a +# # zero-by-two matrix (important for composing things). +# P1 = matrix(self.base_ring(), m, m+n, V_basis[:m]) +# P2 = matrix(self.base_ring(), n, m+n, V_basis[m:]) +# pi_left = FiniteDimensionalEJAOperator(self,J1,P1) +# pi_right = FiniteDimensionalEJAOperator(self,J2,P2) +# return (pi_left, pi_right) + +# def inclusions(self): +# r""" +# Return the pair of inclusion maps from our factors into us. + +# SETUP:: + +# sage: from mjo.eja.eja_algebra import (random_eja, +# ....: JordanSpinEJA, +# ....: RealSymmetricEJA, +# ....: DirectSumEJA) + +# EXAMPLES:: + +# sage: J1 = JordanSpinEJA(3) +# sage: J2 = RealSymmetricEJA(2) +# sage: J = DirectSumEJA(J1,J2) +# sage: (iota_left, iota_right) = J.inclusions() +# sage: iota_left(J1.zero()) == J.zero() +# True +# sage: iota_right(J2.zero()) == J.zero() +# True +# sage: J1.one().to_vector() +# (1, 0, 0) +# sage: iota_left(J1.one()).to_vector() +# (1, 0, 0, 0, 0, 0) +# sage: J2.one().to_vector() +# (1, 0, 1) +# sage: iota_right(J2.one()).to_vector() +# (0, 0, 0, 1, 0, 1) +# sage: J.one().to_vector() +# (1, 0, 0, 1, 0, 1) + +# TESTS: + +# Composing a projection with the corresponding inclusion should +# produce the identity map, and mismatching them should produce +# the zero map:: + +# sage: set_random_seed() +# sage: J1 = random_eja() +# sage: J2 = random_eja() +# sage: J = DirectSumEJA(J1,J2) +# sage: (iota_left, iota_right) = J.inclusions() +# sage: (pi_left, pi_right) = J.projections() +# sage: pi_left*iota_left == J1.one().operator() +# True +# sage: pi_right*iota_right == J2.one().operator() +# True +# sage: (pi_left*iota_right).is_zero() +# True +# sage: (pi_right*iota_left).is_zero() +# True + +# """ +# (J1,J2) = self.factors() +# m = J1.dimension() +# n = J2.dimension() +# V_basis = self.vector_space().basis() +# # Need to specify the dimensions explicitly so that we don't +# # wind up with a zero-by-zero matrix when we want e.g. a +# # two-by-zero matrix (important for composing things). +# I1 = matrix.column(self.base_ring(), m, m+n, V_basis[:m]) +# I2 = matrix.column(self.base_ring(), n, m+n, V_basis[m:]) +# iota_left = FiniteDimensionalEJAOperator(J1,self,I1) +# iota_right = FiniteDimensionalEJAOperator(J2,self,I2) +# return (iota_left, iota_right) + +# def inner_product(self, x, y): +# r""" +# The standard Cartesian inner-product. + +# We project ``x`` and ``y`` onto our factors, and add up the +# inner-products from the subalgebras. + +# SETUP:: + + +# sage: from mjo.eja.eja_algebra import (HadamardEJA, +# ....: QuaternionHermitianEJA, +# ....: DirectSumEJA) + +# EXAMPLE:: + +# sage: J1 = HadamardEJA(3,field=QQ) +# sage: J2 = QuaternionHermitianEJA(2,field=QQ,orthonormalize=False) +# sage: J = DirectSumEJA(J1,J2) +# sage: x1 = J1.one() +# sage: x2 = x1 +# sage: y1 = J2.one() +# sage: y2 = y1 +# sage: x1.inner_product(x2) +# 3 +# sage: y1.inner_product(y2) +# 2 +# sage: J.one().inner_product(J.one()) +# 5 + +# """ +# (pi_left, pi_right) = self.projections() +# x1 = pi_left(x) +# x2 = pi_right(x) +# y1 = pi_left(y) +# y2 = pi_right(y) + +# return (x1.inner_product(y1) + x2.inner_product(y2))