Ticket #13678: 13678-matrix-methods.v3.patch

File 13678-matrix-methods.v3.patch, 10.4 KB (added by robertwb, 9 years ago)

More improvements.

  • sage/matrix/constructor.py

    # HG changeset patch
    # User Robert Bradshaw <robertwb@math.washington.edu>
    # Date 1351720134 25200
    # Node ID 0562e3dce8aa122cc4a806b79a2c28a1ab15beed
    # Parent  95e14084836ba7484596fbb93880154e02883bc1
    Add identity, random, etc. methods to matrix constructor object.
    
    diff --git a/sage/matrix/constructor.py b/sage/matrix/constructor.py
    a b  
    3131
    3232import sage.categories.pushout
    3333
    34 def matrix(*args, **kwds):
     34def matrix_method(func=None, name=None):
    3535    """
    36     Create a matrix.
    37    
    38     INPUT: The matrix command takes the entries of a matrix, optionally
     36    Allows a function to be tab-completed on the global matrix
     37    constructor object.
     38
     39    INPUT:
     40
     41    - ``*function`` -- a single argument. The function that is being
     42      decorated.
     43
     44    - ``**kwds`` -- a single optional keyword argument
     45      ``name=<string>``. The name of the corresponding method in the
     46      global matrix constructor object. If not given, it is derived
     47      from the function name.
     48
     49    EXAMPLES::
     50
     51        sage: from sage.matrix.constructor import matrix_method
     52        sage: def foo_matrix(n): return matrix.diagonal(range(n))
     53        sage: matrix_method(foo_matrix)
     54        <function foo_matrix at ...>
     55        sage: matrix.foo(5)
     56        [0 0 0 0 0]
     57        [0 1 0 0 0]
     58        [0 0 2 0 0]
     59        [0 0 0 3 0]
     60        [0 0 0 0 4]
     61        sage: matrix_method(foo_matrix, name='bar')
     62        <function foo_matrix at ...>
     63        sage: matrix.bar(3)
     64        [0 0 0]
     65        [0 1 0]
     66        [0 0 2]
     67    """
     68    if func is not None:
     69        if name is None:
     70            name = func.__name__.replace('matrix', '').strip('_')
     71        prefix = "    This function is available as %s(...) and matrix.%s(...)." % (
     72            func.__name__, name)
     73        func.__doc__ = "%s\n\n%s" % (prefix, func.__doc__)
     74        setattr(matrix, name, func)
     75        return func
     76    else:
     77        return lambda func: matrix_method(func, name=name)
     78
     79def _matrix_constructor(*args, **kwds):
     80    """
     81    Create a matrix. 
     82
     83    This implements the ``matrix`` constructor::
     84
     85        sage: matrix([[1,2],[3,4]])
     86        [1 2]
     87        [3 4]
     88
     89    It also contains methods to create special types of matrices, see
     90    ``matrix.[tab]`` for more options. For example::
     91
     92        sage: matrix.identity(2)
     93        [1 0]
     94        [0 1]
     95
     96    INPUT:
     97
     98    The matrix command takes the entries of a matrix, optionally
    3999    preceded by a ring and the dimensions of the matrix, and returns a
    40100    matrix.
    41101   
     
    668728    return matrix_space.MatrixSpace(ring, nrows, ncols, sparse=sparse)(entries)
    669729       
    670730
     731class MatrixFactory(object):
     732    """
     733    The class of the ``matrix`` object.
     734   
     735    See :func:`_matrix_constructor` for the implementation of the call
     736    interface.  Implemented as a class for nicer tab completion.
     737
     738    EXAMPLES::
     739       
     740        sage: from sage.misc.sageinspect import sage_getdoc, sage_getsource
     741        sage: sage_getdoc(matrix)       # used in output of matrix?
     742        '   Create a matrix.\n\n   This implements the "matrix" ...'
     743        sage: sage_getsource(matrix)    # used in output of matrix??
     744        'def _matrix_constructor(*args, **kwds):...'
     745    """
     746
     747    __doc__ = _matrix_constructor.__doc__
     748    __call__ = staticmethod(_matrix_constructor)
     749
     750    def _sage_src_(self):
     751        from sage.misc.sageinspect import sage_getsource
     752        return sage_getsource(_matrix_constructor)
     753
     754Matrix = matrix = MatrixFactory()
     755
    671756
    672757def prepare(w):
    673758    """
     
    799884        return 0
    800885    return max([0] + [ij[1] for ij in d.keys()]) + 1   
    801886
    802 Matrix = matrix
    803 
     887
     888@matrix_method
    804889def column_matrix(*args, **kwds):
    805890    r"""
    806891    Constructs a matrix, and then swaps rows for columns and columns for rows.
    807892
    808893    .. note::
    809894
    810         Linear algebra in Sage favors rows over columns.  So, generally,
    811         when creating a matrix, input vectors and lists are treated as rows.
    812         This function is a convenience that turns around this convention
    813         when creating a matrix.  If you are not familiar with the usual
    814         :func:`matrix` constructor, you might want to consider it first.
     895        Linear algebra in Sage favors rows over columns.  So,
     896        generally, when creating a matrix, input vectors and lists are
     897        treated as rows.  This function is a convenience that turns
     898        around this convention when creating a matrix.  If you are not
     899        familiar with the usual :class:`matrix <MatrixFactory>`
     900        constructor, you might want to consider it first.
    815901
    816902    INPUT:
    817903
    818     Inputs are almost exactly the same as for the :func:`matrix`
    819     constructor, which are documented there.  But see examples below
    820     for how dimensions are handled.
     904    Inputs are almost exactly the same as for the :class:`matrix
     905    <MatrixFactory>` constructor, which are documented there.  But see
     906    examples below for how dimensions are handled.
    821907
    822908    OUTPUT:
    823909
    824     Output is exactly the transpose of what the :func:`matrix`
    825     constructor would return.  In other words, the ``matrix``
    826     constructor builds a matrix and then this function exchanges
    827     rows for columns, and columns for rows.
     910    Output is exactly the transpose of what the :class:`matrix
     911    <MatrixFactory>` constructor would return.  In other words, the
     912    ``matrix`` constructor builds a matrix and then this function
     913    exchanges rows for columns, and columns for rows.
    828914
    829915    EXAMPLES:
    830916
    831     The most compelling use of this function is when you have
    832     a collection of lists or vectors that you would like to
    833     become the columns of a matrix. In almost any other
    834     situation, the :func:`matrix` constructor can probably do
    835     the job just as easily, or easier. ::
     917    The most compelling use of this function is when you have a
     918    collection of lists or vectors that you would like to become the
     919    columns of a matrix. In almost any other situation, the
     920    :class:`matrix <MatrixFactory>` constructor can probably do the
     921    job just as easily, or easier. ::
    836922
    837923        sage: col_1 = [1,2,3]
    838924        sage: col_2 = [4,5,6]
     
    886972    return matrix(*args, **kwds).transpose()
    887973
    888974
     975@matrix_method
    889976def random_matrix(ring, nrows, ncols=None, algorithm='randomize', *args, **kwds):
    890977    r"""
    891978    Return a random matrix with entries in a specified ring, and possibly with additional properties.
     
    12621349        raise ValueError('random matrix algorithm "%s" is not recognized' % algorithm)
    12631350
    12641351
     1352@matrix_method
    12651353def diagonal_matrix(arg0=None, arg1=None, arg2=None, sparse=True):
    12661354    r"""
    12671355    Return a square matrix with specified diagonal entries, and zeros elsewhere.
     
    14811569        return matrix(ring, nrows, nrows, w, sparse=sparse)
    14821570
    14831571
     1572@matrix_method
    14841573def identity_matrix(ring, n=0, sparse=False):
    14851574    r"""
    14861575    Return the `n \times n` identity matrix over the given
     
    15171606    return matrix_space.MatrixSpace(ring, n, n, sparse)(1)
    15181607
    15191608
     1609@matrix_method
    15201610def zero_matrix(ring, nrows, ncols=None, sparse=False):
    15211611    r"""
    15221612    Return the `nrows \times ncols` zero matrix over the given
     
    15521642        ring = rings.ZZ
    15531643    return matrix_space.MatrixSpace(ring, nrows, ncols, sparse)(0)
    15541644
     1645
     1646@matrix_method
    15551647def ones_matrix(ring, nrows=None, ncols=None, sparse=False):
    15561648    r"""
    15571649    Return a matrix with all entries equal to 1.
     
    16431735    one = ring(1)
    16441736    return matrix_space.MatrixSpace(ring, nrows, ncols, sparse).matrix([one]*nents)
    16451737
     1738
     1739@matrix_method
    16461740def elementary_matrix(arg0, arg1=None, **kwds):
    16471741    r"""
    16481742    Creates a square matrix that corresponds to a row operation or a column operation.
     
    22472341    # If we got this far, then everything fits
    22482342    return (row_heights, zero_widths, total_width)
    22492343
     2344
     2345@matrix_method
    22502346def block_matrix(*args, **kwds):
    22512347    r"""
    22522348    Returns a larger matrix made by concatenating submatrices
     
    26202716
    26212717    return big
    26222718
     2719
     2720@matrix_method
    26232721def block_diagonal_matrix(*sub_matrices, **kwds):
    26242722    """
    26252723    Create a block matrix whose diagonal block entries are given by
     
    26552753        entries[n*i+i] = sub_matrices[i]
    26562754    return block_matrix(n, n, entries, **kwds)
    26572755
     2756
     2757@matrix_method
    26582758def jordan_block(eigenvalue, size, sparse=False):
    26592759    r"""
    26602760    Returns the Jordan block for the given eigenvalue with given size.
     
    26972797        block[i,i+1]=1
    26982798    return block
    26992799
     2800
     2801@matrix_method
    27002802def companion_matrix(poly, format='right'):
    27012803    r"""
    27022804    Create a companion matrix from a monic polynomial.
     
    28932995        raise TypeError("unable to find common ring for coefficients from polynomial")
    28942996    return M
    28952997
     2998@matrix_method
    28962999def random_rref_matrix(parent, num_pivots):
    28973000    r"""
    28983001    Generate a matrix in reduced row-echelon form with a specified number of non-zero rows.
     
    30583161                    return_matrix[rest_entries,rest_non_pivot_column]=ring.random_element()
    30593162    return return_matrix
    30603163
     3164@matrix_method
    30613165def random_echelonizable_matrix(parent, rank, upper_bound=None):
    30623166    r"""
    30633167    Generate a matrix of a desired size and rank, over a desired ring, whose reduced
     
    32463350            matrix.add_multiple_of_row(0,randint(1,rows-1),ring.random_element())
    32473351    return matrix
    32483352
     3353@matrix_method
    32493354def random_subspaces_matrix(parent, rank=None):
    32503355    r"""
    32513356    Create a matrix of the designated size and rank whose right and
     
    34273532    # K matrix to the identity matrix.
    34283533    return J.inverse()*B
    34293534
     3535@matrix_method
    34303536def random_unimodular_matrix(parent, upper_bound=None):
    34313537    """
    34323538    Generate a random unimodular (determinant 1) matrix of a desired size over a desired ring.
     
    35263632        return random_matrix(ring, size,algorithm='echelonizable',rank=size, upper_bound=upper_bound)
    35273633
    35283634
     3635@matrix_method
    35293636def random_diagonalizable_matrix(parent,eigenvalues=None,dimensions=None):
    35303637    """
    35313638    Create a random matrix that diagonalizes nicely. 
     
    37723879            eigenvector_matrix.add_multiple_of_row(upper_row,row,randint(-4,4))
    37733880    return eigenvector_matrix*diagonal_matrix*(eigenvector_matrix.inverse())
    37743881
     3882
     3883@matrix_method
    37753884def vector_on_axis_rotation_matrix(v, i, ring=None):
    37763885    r"""
    37773886    Return a rotation matrix `M` such that `det(M)=1` sending the vector
     
    38453954        m = rot * m
    38463955    return m
    38473956
     3957
     3958@matrix_method
    38483959def ith_to_zero_rotation_matrix(v, i, ring=None):
    38493960    r"""
    38503961    Return a rotation matrix that sends the i-th coordinates of the