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 b  
    238238    sage: A*P == P*D
    239239    True
    240240
    241 A word of caution - if the eigenvalues are not in the fraction field
    242 of the base ring of the matrix space (the eigenvalues below are
    243 :math:`\pm \sqrt{3}`) then the output of ``eigenspaces_right`` and
    244 ``code{eigenspaces_left`` only lists a single eigenspace for each
    245 irreducible factor of the characteristic polynomial.
     241For eigenvalues outside the fraction field of the base ring of the matrix,
     242you can choose to have all the eigenspaces output when the algebraic closure
     243of the field is implemented, such as the algebraic numbers, ``QQbar``.  Or you
     244may request just a single eigenspace for each irreducible factor of the
     245characteristic polynomial, since the others may be formed through Galois
     246conjugation.  The eigenvalues of the matrix below are $\pm\sqrt{3}$ and
     247we exhibit each possible output.
    246248
    247 Also, currently Sage does not implement multiprecision numerical
    248 eigenvalues/eigenvectors, so calling the eigen functions on a matrix
    249 from ``CC`` or ``RR`` will probably give inaccurate and
    250 nonsensical results (a warning is also printed).  Matrices over
    251 ``CDF`` and ``RDF`` should work, though.
    252 
    253 ::
     249Also, currently Sage does not implement multiprecision numerical eigenvalues
     250and eigenvectors, so calling the eigen functions on a matrix from
     251``CC`` or ``RR`` will probably give inaccurate and nonsensical results
     252(a warning is also printed).  Eigenvalues and eigenvectors of matrices with
     253floating point entries (over ``CDF`` and ``RDF``) can be obtained with the
     254"eigenmatrix" commands.  ::
    254255
    255256    sage: MS = MatrixSpace(QQ, 2, 2)
    256257    sage: A = MS([1,-4,1, -1])
    257     sage: A.eigenspaces_left()
     258    sage: A.eigenspaces_left(format='all')
     259    [
     260    (-1.732050807568878?*I, Vector space of degree 2 and dimension 1 over Algebraic Field
     261    User basis matrix:
     262    [                        1 -1 - 1.732050807568878?*I]),
     263    (1.732050807568878?*I, Vector space of degree 2 and dimension 1 over Algebraic Field
     264    User basis matrix:
     265    [                        1 -1 + 1.732050807568878?*I])
     266    ]
     267    sage: A.eigenspaces_left(format='galois')
    258268    [
    259269    (a0, Vector space of degree 2 and dimension 1 over Number Field in a0 with defining polynomial x^2 + 3
    260270    User basis matrix:
    261271    [     1 a0 - 1])
    262272    ]
    263     sage: MS = MatrixSpace(CC, 2, 2)
    264     sage: A = MS([1,-4,1, -1])
    265     sage: A.eigenspaces() # random output
    266     [                             
    267     (1.73205080756888*I, [               
    268     ]),
    269     (-1.73205080756888*I, [
    270     ])
    271     ]
    272273
    273274Another approach is to use the interface with Maxima:
    274275
  • sage/matrix/matrix2.pyx

    diff -r 2cb5efc74bed -r 39d1899c4cf9 sage/matrix/matrix2.pyx
    a b  
    43654365    # Deprecated Aug 2008 Trac #3794
    43664366    # Removed July 2011
    43674367    # def eigenspaces(self, var='a', even_if_inexact=None):
     4368   
     4369    def _eigenspace_format(self, format):
     4370        r"""
     4371        Helper method to control output format for eigenspaces.
     4372       
     4373        INPUT:
     4374       
     4375        - ``format`` - ``None``, ``'all'`` or ``'galois'``
     4376       
     4377        OUTPUT:
     4378       
     4379        Any format except ``None`` is just passed through.  When the
     4380        format is ``None`` a choice is made about the style of the output.
     4381        If there is an algebraically closed field that will contain the
     4382        possible eigenvalues, then 'all" of the eigenspaces are given.
     4383       
     4384        However if this is not the case, then only one eigenspace is output
     4385        for each irreducible factor of the characteristic polynomial.
     4386       
     4387        EXAMPLES:
     4388       
     4389        Pass-through first.  ::
     4390       
     4391            sage: A = matrix(QQ, 2, range(4))
     4392            sage: A._eigenspace_format('all') == 'all'
     4393            True
     4394            sage: A._eigenspace_format('galois') == 'galois'
     4395            True
     4396 
     4397        The algebraic closure of the rationals, the field of algebraic numbers,
     4398        (aka ``QQbar``) is implemented, while in general the algebraic closure
     4399        of a finite field is not implemented.  ::
     4400       
     4401            sage: A = matrix(QQ, 2, range(4))
     4402            sage: A._eigenspace_format(None) == 'all'
     4403            True
     4404            sage: B = matrix(GF(13), 2, range(4))
     4405            sage: B._eigenspace_format(None) == 'galois'
     4406            True
     4407       
     4408        Subrings are promoted to fraction fields and then checked for the
     4409        existence of algebraic closures.  ::
     4410
     4411            sage: A = matrix(ZZ, 2, range(4))
     4412            sage: A._eigenspace_format(None) == 'all'
     4413            True
     4414        """
     4415        if not format in [None, 'all', 'galois']:
     4416            msg = "format keyword must be None, 'all' or 'galois', not {0}"
     4417            raise ValueError(msg.format(format))
     4418
     4419        # For subrings of implemented algebraically closed fields we
     4420        #   default to all eigenspaces in the absence of a format keyword
     4421        # Add newly implemented algebraically closed fields to list below
     4422        #   and implement the determintion of the actual eigenvalues
     4423        #   in the eigenspace_left() routine
     4424        if format is None:
     4425            R = self.base_ring()
     4426            from sage.rings.qqbar import QQbar
     4427            try:
     4428                if R.fraction_field().algebraic_closure() in [QQbar]:
     4429                    return 'all'
     4430                else:
     4431                    return 'galois'
     4432            except (NotImplementedError, AttributeError):
     4433                return 'galois'
     4434        else:
     4435            return format
    43684436
    43694437    def eigenspaces_left(self, format='all', var='a', algebraic_multiplicity=False):
    43704438        r"""
     
    43794447        - ``self`` - a square matrix over an exact field.  For inexact
    43804448          matrices consult the numerical or symbolic matrix classes.
    43814449
    4382         - ``format`` - default: 'all'
    4383           - 'all' - attempts to create every eigenspace.  This will
     4450        - ``format`` - default: ``None``
     4451       
     4452          - ``'all'`` - attempts to create every eigenspace.  This will
    43844453            always be possible for matrices with rational entries.
    4385           - 'galois' - for each irreducible factor of the characteristic
     4454          - ``'galois'`` - for each irreducible factor of the characteristic
    43864455            polynomial, a single eigenspace will be output for a
    43874456            single root/eigenvalue for the irreducible factor.
     4457          - ``None`` - Uses the 'all' format if the base ring is contained
     4458            in an algebraically closed field which is implemented. 
     4459            Otherwise, uses the 'galois' format.
    43884460
    43894461        - ``var`` - default: 'a' - variable name used to
    43904462          represent elements of the root field of each
     
    46194691            sage: B.eigenspaces_left(format='junk')
    46204692            Traceback (most recent call last):
    46214693            ...
    4622             ValueError: format keyword must be 'all' or 'galois', not junk
     4694            ValueError: format keyword must be None, 'all' or 'galois', not junk
    46234695
    46244696            sage: B.eigenspaces_left(algebraic_multiplicity='garbage')
    46254697            Traceback (most recent call last):
    46264698            ...
    46274699            ValueError: algebraic_multiplicity keyword must be True or False
    4628 
    4629         """
    4630         if not format in ['all', 'galois']:
    4631             raise ValueError("format keyword must be 'all' or 'galois', not {0}".format(format))
     4700        """
    46324701        if not algebraic_multiplicity in [True, False]:
    4633             raise ValueError('algebraic_multiplicity keyword must be True or False'.format(algebraic_multiplicity))
     4702            msg = 'algebraic_multiplicity keyword must be True or False'
     4703            raise ValueError(msg.format(algebraic_multiplicity))
    46344704        if not self.is_square():
    4635             raise TypeError('matrix must be square, not {0} x {1}'.format(self.nrows(), self.ncols()))
     4705            msg = 'matrix must be square, not {0} x {1}'
     4706            raise TypeError(msg.format(self.nrows(), self.ncols()))
    46364707        if not self.base_ring().is_exact():
    46374708            msg = ("eigenspaces cannot be computed reliably for inexact rings such as {0},\n",
    46384709                   "consult numerical or symbolic matrix classes for other options")
    46394710            raise NotImplementedError(''.join(msg).format(self.base_ring()))
    46404711
     4712        format = self._eigenspace_format(format)
     4713       
    46414714        key = 'eigenspaces_left_' + format + '{0}'.format(var)
    46424715        x = self.fetch(key)
    46434716        if not x is None:
     
    46514724        # use minpoly when algebraic_multiplicity=False
    46524725        # as of 2007-03-25 minpoly is unreliable via linbox
    46534726
     4727        import sage.categories.homset
    46544728        import sage.rings.qqbar
    4655         import sage.categories.homset
     4729       
    46564730        G = self.fcp()   # factored characteristic polynomial
    46574731        V = []
    46584732        i = -1 # variable name index, increments for each eigenvalue
     
    47084782        - ``self`` - a square matrix over an exact field.  For inexact
    47094783          matrices consult the numerical or symbolic matrix classes.
    47104784
    4711         - ``format`` - default: 'all'
    4712           - 'all' - attempts to create every eigenspace.  This will
     4785        - ``format`` - default: ``None``
     4786       
     4787          - ``'all'`` - attempts to create every eigenspace.  This will
    47134788            always be possible for matrices with rational entries.
    4714           - 'galois' - for each irreducible factor of the characteristic
     4789          - ``'galois'`` - for each irreducible factor of the characteristic
    47154790            polynomial, a single eigenspace will be output for a
    47164791            single root/eigenvalue for the irreducible factor.
     4792          - ``None`` - Uses the 'all' format if the base ring is contained
     4793            in an algebraically closed field which is implemented. 
     4794            Otherwise, uses the 'galois' format.
    47174795
    47184796        - ``var`` - default: 'a' - variable name used to
    47194797          represent elements of the root field of each
     
    48534931            sage: B.eigenspaces_right(format='junk')
    48544932            Traceback (most recent call last):
    48554933            ...
    4856             ValueError: format keyword must be 'all' or 'galois', not junk
     4934            ValueError: format keyword must be None, 'all' or 'galois', not junk
    48574935
    48584936            sage: B.eigenspaces_right(algebraic_multiplicity='garbage')
    48594937            Traceback (most recent call last):
    48604938            ...
    48614939            ValueError: algebraic_multiplicity keyword must be True or False
    48624940        """
    4863         if not format in ['all', 'galois']:
    4864             raise ValueError("format keyword must be 'all' or 'galois', not {0}".format(format))
    48654941        if not algebraic_multiplicity in [True, False]:
    4866             raise ValueError('algebraic_multiplicity keyword must be True or False'.format(algebraic_multiplicity))
     4942            msg = 'algebraic_multiplicity keyword must be True or False'
     4943            raise ValueError(msg.format(algebraic_multiplicity))
    48674944        if not self.is_square():
    4868             raise TypeError('matrix must be square, not {0} x {1}'.format(self.nrows(), self.ncols()))
     4945            msg = 'matrix must be square, not {0} x {1}'
     4946            raise TypeError(msg.format(self.nrows(), self.ncols()))
    48694947        if not self.base_ring().is_exact():
    48704948            msg = ("eigenspaces cannot be computed reliably for inexact rings such as {0},\n",
    48714949                   "consult numerical or symbolic matrix classes for other options")
    48724950            raise NotImplementedError(''.join(msg).format(self.base_ring()))
     4951       
     4952        format = self._eigenspace_format(format)
    48734953
    48744954        key = 'eigenspaces_right_' + format + '{0}'.format(var)
    48754955        x = self.fetch(key)