# Ticket #11595: trac_11595-exact-eigenspaces-format-v1.patch

File trac_11595-exact-eigenspaces-format-v1.patch, 11.9 KB (added by rbeezer, 11 years ago)
• ## doc/en/constructions/linear_algebra.rst

# HG changeset patch
# User Rob Beezer <beezer@ups.edu>
# Date 1313813339 25200
# Node ID 39d1899c4cf98c7353d0d3bae9cc98a84f334fe7
# Parent  2cb5efc74bed3d837ab725f7dd152e67fd4eabc7
11595: output format behavior for exact eigenspaces

diff -r 2cb5efc74bed -r 39d1899c4cf9 doc/en/constructions/linear_algebra.rst
 a sage: A*P == P*D True A word of caution - if the eigenvalues are not in the fraction field of the base ring of the matrix space (the eigenvalues below are :math:\pm \sqrt{3}) then the output of eigenspaces_right and code{eigenspaces_left only lists a single eigenspace for each irreducible factor of the characteristic polynomial. For eigenvalues outside the fraction field of the base ring of the matrix, you can choose to have all the eigenspaces output when the algebraic closure of the field is implemented, such as the algebraic numbers, QQbar.  Or you may request just a single eigenspace for each irreducible factor of the characteristic polynomial, since the others may be formed through Galois conjugation.  The eigenvalues of the matrix below are $\pm\sqrt{3}$ and we exhibit each possible output. Also, currently Sage does not implement multiprecision numerical eigenvalues/eigenvectors, so calling the eigen functions on a matrix from CC or RR will probably give inaccurate and nonsensical results (a warning is also printed).  Matrices over CDF and RDF should work, though. :: Also, currently Sage does not implement multiprecision numerical eigenvalues and eigenvectors, so calling the eigen functions on a matrix from CC or RR will probably give inaccurate and nonsensical results (a warning is also printed).  Eigenvalues and eigenvectors of matrices with floating point entries (over CDF and RDF) can be obtained with the "eigenmatrix" commands.  :: sage: MS = MatrixSpace(QQ, 2, 2) sage: A = MS([1,-4,1, -1]) sage: A.eigenspaces_left() sage: A.eigenspaces_left(format='all') [ (-1.732050807568878?*I, Vector space of degree 2 and dimension 1 over Algebraic Field User basis matrix: [                        1 -1 - 1.732050807568878?*I]), (1.732050807568878?*I, Vector space of degree 2 and dimension 1 over Algebraic Field User basis matrix: [                        1 -1 + 1.732050807568878?*I]) ] sage: A.eigenspaces_left(format='galois') [ (a0, Vector space of degree 2 and dimension 1 over Number Field in a0 with defining polynomial x^2 + 3 User basis matrix: [     1 a0 - 1]) ] sage: MS = MatrixSpace(CC, 2, 2) sage: A = MS([1,-4,1, -1]) sage: A.eigenspaces() # random output [ (1.73205080756888*I, [ ]), (-1.73205080756888*I, [ ]) ] Another approach is to use the interface with Maxima:
• ## sage/matrix/matrix2.pyx

diff -r 2cb5efc74bed -r 39d1899c4cf9 sage/matrix/matrix2.pyx
 a # Deprecated Aug 2008 Trac #3794 # Removed July 2011 # def eigenspaces(self, var='a', even_if_inexact=None): def _eigenspace_format(self, format): r""" Helper method to control output format for eigenspaces. INPUT: - format - None, 'all' or 'galois' OUTPUT: Any format except None is just passed through.  When the format is None a choice is made about the style of the output. If there is an algebraically closed field that will contain the possible eigenvalues, then 'all" of the eigenspaces are given. However if this is not the case, then only one eigenspace is output for each irreducible factor of the characteristic polynomial. EXAMPLES: Pass-through first.  :: sage: A = matrix(QQ, 2, range(4)) sage: A._eigenspace_format('all') == 'all' True sage: A._eigenspace_format('galois') == 'galois' True The algebraic closure of the rationals, the field of algebraic numbers, (aka QQbar) is implemented, while in general the algebraic closure of a finite field is not implemented.  :: sage: A = matrix(QQ, 2, range(4)) sage: A._eigenspace_format(None) == 'all' True sage: B = matrix(GF(13), 2, range(4)) sage: B._eigenspace_format(None) == 'galois' True Subrings are promoted to fraction fields and then checked for the existence of algebraic closures.  :: sage: A = matrix(ZZ, 2, range(4)) sage: A._eigenspace_format(None) == 'all' True """ if not format in [None, 'all', 'galois']: msg = "format keyword must be None, 'all' or 'galois', not {0}" raise ValueError(msg.format(format)) # For subrings of implemented algebraically closed fields we #   default to all eigenspaces in the absence of a format keyword # Add newly implemented algebraically closed fields to list below #   and implement the determintion of the actual eigenvalues #   in the eigenspace_left() routine if format is None: R = self.base_ring() from sage.rings.qqbar import QQbar try: if R.fraction_field().algebraic_closure() in [QQbar]: return 'all' else: return 'galois' except (NotImplementedError, AttributeError): return 'galois' else: return format def eigenspaces_left(self, format='all', var='a', algebraic_multiplicity=False): r""" - self - a square matrix over an exact field.  For inexact matrices consult the numerical or symbolic matrix classes. - format - default: 'all' - 'all' - attempts to create every eigenspace.  This will - format - default: None - 'all' - attempts to create every eigenspace.  This will always be possible for matrices with rational entries. - 'galois' - for each irreducible factor of the characteristic - 'galois' - for each irreducible factor of the characteristic polynomial, a single eigenspace will be output for a single root/eigenvalue for the irreducible factor. - None - Uses the 'all' format if the base ring is contained in an algebraically closed field which is implemented. Otherwise, uses the 'galois' format. - var - default: 'a' - variable name used to represent elements of the root field of each sage: B.eigenspaces_left(format='junk') Traceback (most recent call last): ... ValueError: format keyword must be 'all' or 'galois', not junk ValueError: format keyword must be None, 'all' or 'galois', not junk sage: B.eigenspaces_left(algebraic_multiplicity='garbage') Traceback (most recent call last): ... ValueError: algebraic_multiplicity keyword must be True or False """ if not format in ['all', 'galois']: raise ValueError("format keyword must be 'all' or 'galois', not {0}".format(format)) """ if not algebraic_multiplicity in [True, False]: raise ValueError('algebraic_multiplicity keyword must be True or False'.format(algebraic_multiplicity)) msg = 'algebraic_multiplicity keyword must be True or False' raise ValueError(msg.format(algebraic_multiplicity)) if not self.is_square(): raise TypeError('matrix must be square, not {0} x {1}'.format(self.nrows(), self.ncols())) msg = 'matrix must be square, not {0} x {1}' raise TypeError(msg.format(self.nrows(), self.ncols())) if not self.base_ring().is_exact(): msg = ("eigenspaces cannot be computed reliably for inexact rings such as {0},\n", "consult numerical or symbolic matrix classes for other options") raise NotImplementedError(''.join(msg).format(self.base_ring())) format = self._eigenspace_format(format) key = 'eigenspaces_left_' + format + '{0}'.format(var) x = self.fetch(key) if not x is None: # use minpoly when algebraic_multiplicity=False # as of 2007-03-25 minpoly is unreliable via linbox import sage.categories.homset import sage.rings.qqbar import sage.categories.homset G = self.fcp()   # factored characteristic polynomial V = [] i = -1 # variable name index, increments for each eigenvalue - self - a square matrix over an exact field.  For inexact matrices consult the numerical or symbolic matrix classes. - format - default: 'all' - 'all' - attempts to create every eigenspace.  This will - format - default: None - 'all' - attempts to create every eigenspace.  This will always be possible for matrices with rational entries. - 'galois' - for each irreducible factor of the characteristic - 'galois' - for each irreducible factor of the characteristic polynomial, a single eigenspace will be output for a single root/eigenvalue for the irreducible factor. - None - Uses the 'all' format if the base ring is contained in an algebraically closed field which is implemented. Otherwise, uses the 'galois' format. - var - default: 'a' - variable name used to represent elements of the root field of each sage: B.eigenspaces_right(format='junk') Traceback (most recent call last): ... ValueError: format keyword must be 'all' or 'galois', not junk ValueError: format keyword must be None, 'all' or 'galois', not junk sage: B.eigenspaces_right(algebraic_multiplicity='garbage') Traceback (most recent call last): ... ValueError: algebraic_multiplicity keyword must be True or False """ if not format in ['all', 'galois']: raise ValueError("format keyword must be 'all' or 'galois', not {0}".format(format)) if not algebraic_multiplicity in [True, False]: raise ValueError('algebraic_multiplicity keyword must be True or False'.format(algebraic_multiplicity)) msg = 'algebraic_multiplicity keyword must be True or False' raise ValueError(msg.format(algebraic_multiplicity)) if not self.is_square(): raise TypeError('matrix must be square, not {0} x {1}'.format(self.nrows(), self.ncols())) msg = 'matrix must be square, not {0} x {1}' raise TypeError(msg.format(self.nrows(), self.ncols())) if not self.base_ring().is_exact(): msg = ("eigenspaces cannot be computed reliably for inexact rings such as {0},\n", "consult numerical or symbolic matrix classes for other options") raise NotImplementedError(''.join(msg).format(self.base_ring())) format = self._eigenspace_format(format) key = 'eigenspaces_right_' + format + '{0}'.format(var) x = self.fetch(key)