Ticket #10876: trac_10876-elementary-matrices.patch

File trac_10876-elementary-matrices.patch, 10.9 KB (added by rbeezer, 10 years ago)
  • sage/matrix/all.py

    # HG changeset patch
    # User Rob Beezer <beezer@ups.edu>
    # Date 1299281755 28800
    # Node ID 06a80d69c1bef4fbdefd36532d666ad5ae9b284b
    # Parent  8438b7c20d79c02a2ece3e1c3f7224a772ff8f07
    10876: constructor for elementary matrices
    
    diff -r 8438b7c20d79 -r 06a80d69c1be sage/matrix/all.py
    a b  
    11from matrix_space import MatrixSpace, is_MatrixSpace
    2 from constructor import matrix, Matrix, column_matrix, random_matrix, diagonal_matrix, identity_matrix, block_matrix, block_diagonal_matrix, jordan_block, zero_matrix, ones_matrix
     2from constructor import matrix, Matrix, column_matrix, random_matrix, diagonal_matrix, identity_matrix, block_matrix, block_diagonal_matrix, jordan_block, zero_matrix, ones_matrix, elementary_matrix
    33from matrix import is_Matrix
    44from berlekamp_massey import berlekamp_massey
    55
  • sage/matrix/constructor.py

    diff -r 8438b7c20d79 -r 06a80d69c1be sage/matrix/constructor.py
    a b  
    16411641    one = ring(1)
    16421642    return matrix_space.MatrixSpace(ring, nrows, ncols, sparse).matrix([one]*nents)
    16431643
     1644def elementary_matrix(arg0, arg1=None, row1=None, row2=None, scale=None):
     1645    r"""
     1646    Creates a square matrix that corresponds to a row operation.
     1647
     1648    FORMATS:
     1649
     1650    In each case, ``R`` is the base ring, and is optional (the default
     1651    is the integers). ``n`` is the size of the square matrix created.
     1652    We describe the matrices by their associated row operation, see
     1653    the output description for more.
     1654
     1655    - ``elementary_matrix(R, n, row1=i, row2=j)``
     1656
     1657      The matrix which swaps rows ``i`` and ``j``.
     1658
     1659    - ``elementary_matrix(R, n, row1=i, scale=s)``
     1660
     1661      The matrix which multiplies row ``i`` by ``s``.
     1662
     1663    - ``elementary_matrix(R, n, row1=i, row2=j, scale=s)``
     1664
     1665      The matrix which multiplies row ``j`` by ``s``
     1666      and adds it to row ``i``.
     1667
     1668    The following formats will work without keywords (with
     1669    one exception), provided the ring is included.
     1670
     1671    - ``elementary_matrix(R, n, i, j)`` - swap rows ``i`` and ``j``.
     1672    - ``elementary_matrix(R, n, i, scale=s)`` - multiply row ``i`` by ``s``.
     1673    - ``elementary_matrix(R, n, i, j, s)`` - multiply row ``j`` by ``s``
     1674      and add to row ``i``.
     1675
     1676    OUTPUT:
     1677
     1678    An elementary matrix is a square matrix that is very close to being
     1679    an identity matrix.  If ``E`` is an identity matrix and ``A`` is any
     1680    matrix with the same number of rows, then ``E*A`` is the result of
     1681    applying a row operation to ``A``.  This is how the three types
     1682    created by this function are described.
     1683
     1684    EXAMPLES:
     1685
     1686    Over the integers, with keywords. ::
     1687
     1688        sage: A = matrix(ZZ, 4, 10, range(40)); A
     1689        [ 0  1  2  3  4  5  6  7  8  9]
     1690        [10 11 12 13 14 15 16 17 18 19]
     1691        [20 21 22 23 24 25 26 27 28 29]
     1692        [30 31 32 33 34 35 36 37 38 39]
     1693
     1694        sage: E = elementary_matrix(4, row1=1, row2=3); E
     1695        [1 0 0 0]
     1696        [0 0 0 1]
     1697        [0 0 1 0]
     1698        [0 1 0 0]
     1699        sage: E*A
     1700        [ 0  1  2  3  4  5  6  7  8  9]
     1701        [30 31 32 33 34 35 36 37 38 39]
     1702        [20 21 22 23 24 25 26 27 28 29]
     1703        [10 11 12 13 14 15 16 17 18 19]
     1704
     1705        sage: E = elementary_matrix(4, row1=2, scale=10); E
     1706        [ 1  0  0  0]
     1707        [ 0  1  0  0]
     1708        [ 0  0 10  0]
     1709        [ 0  0  0  1]
     1710        sage: E*A
     1711        [  0   1   2   3   4   5   6   7   8   9]
     1712        [ 10  11  12  13  14  15  16  17  18  19]
     1713        [200 210 220 230 240 250 260 270 280 290]
     1714        [ 30  31  32  33  34  35  36  37  38  39]
     1715
     1716        sage: E = elementary_matrix(4, row1=2, row2=1, scale=10); E
     1717        [ 1  0  0  0]
     1718        [ 0  1  0  0]
     1719        [ 0 10  1  0]
     1720        [ 0  0  0  1]
     1721        sage: E*A
     1722        [  0   1   2   3   4   5   6   7   8   9]
     1723        [ 10  11  12  13  14  15  16  17  18  19]
     1724        [120 131 142 153 164 175 186 197 208 219]
     1725        [ 30  31  32  33  34  35  36  37  38  39]
     1726
     1727    Over the rationals, with minimal keywords. ::
     1728
     1729        sage: A = matrix(QQ, 4, 10, range(40)); A
     1730        [ 0  1  2  3  4  5  6  7  8  9]
     1731        [10 11 12 13 14 15 16 17 18 19]
     1732        [20 21 22 23 24 25 26 27 28 29]
     1733        [30 31 32 33 34 35 36 37 38 39]
     1734
     1735        sage: E = elementary_matrix(QQ, 4, 1, 3); E
     1736        [1 0 0 0]
     1737        [0 0 0 1]
     1738        [0 0 1 0]
     1739        [0 1 0 0]
     1740        sage: E*A
     1741        [ 0  1  2  3  4  5  6  7  8  9]
     1742        [30 31 32 33 34 35 36 37 38 39]
     1743        [20 21 22 23 24 25 26 27 28 29]
     1744        [10 11 12 13 14 15 16 17 18 19]
     1745
     1746        sage: E = elementary_matrix(QQ, 4, 2, scale=10); E
     1747        [ 1  0  0  0]
     1748        [ 0  1  0  0]
     1749        [ 0  0 10  0]
     1750        [ 0  0  0  1]
     1751        sage: E*A
     1752        [  0   1   2   3   4   5   6   7   8   9]
     1753        [ 10  11  12  13  14  15  16  17  18  19]
     1754        [200 210 220 230 240 250 260 270 280 290]
     1755        [ 30  31  32  33  34  35  36  37  38  39]
     1756
     1757        sage: E = elementary_matrix(QQ, 4, 2, 1, 10); E
     1758        [ 1  0  0  0]
     1759        [ 0  1  0  0]
     1760        [ 0 10  1  0]
     1761        [ 0  0  0  1]
     1762        sage: E*A
     1763        [  0   1   2   3   4   5   6   7   8   9]
     1764        [ 10  11  12  13  14  15  16  17  18  19]
     1765        [120 131 142 153 164 175 186 197 208 219]
     1766        [ 30  31  32  33  34  35  36  37  38  39]
     1767
     1768    An elementary matrix is always nonsingular.  Then repeated row
     1769    operations can be represented by products of elementary matrices,
     1770    and this product is again nonsingular.  If row operations are to
     1771    preserve fundamental properties of a matrix (like rank), we do not
     1772    allow scaling a row by zero.  Similarly, the corresponding elementary
     1773    matrix is not constructed.  ::
     1774
     1775        sage: A = matrix(QQ, 4, 10, range(40)); A
     1776        [ 0  1  2  3  4  5  6  7  8  9]
     1777        [10 11 12 13 14 15 16 17 18 19]
     1778        [20 21 22 23 24 25 26 27 28 29]
     1779        [30 31 32 33 34 35 36 37 38 39]
     1780
     1781        sage: E1 = elementary_matrix(QQ, 4, row1=0, row2=1)
     1782        sage: E2 = elementary_matrix(QQ, 4, row1=3, row2=0, scale=100)
     1783        sage: E = E2*E1
     1784        sage: E.is_singular()
     1785        False
     1786        sage: E*A
     1787        [  10   11   12   13   14   15   16   17   18   19]
     1788        [   0    1    2    3    4    5    6    7    8    9]
     1789        [  20   21   22   23   24   25   26   27   28   29]
     1790        [1030 1131 1232 1333 1434 1535 1636 1737 1838 1939]
     1791
     1792        sage: E3 = elementary_matrix(QQ, 4, row1=3, scale=0)
     1793        Traceback (most recent call last):
     1794        ...
     1795        ValueError: scale parameter of row of elementary matrix must be non-zero
     1796
     1797    And the ridiculously small cases.  The zero-row matrix fails
     1798    since there are no rows to manipulate. ::
     1799
     1800        sage: elementary_matrix(QQ, 1, 0, 0)
     1801        [1]
     1802        sage: elementary_matrix(QQ, 0, 0, 0)
     1803        Traceback (most recent call last):
     1804        ...
     1805        ValueError: row of elementary matrix must be positive and smaller than 0, not 0
     1806
     1807    TESTS::
     1808
     1809        sage: E = elementary_matrix(ZZ, 4/3, row1=3, row2=1, scale=12)
     1810        Traceback (most recent call last):
     1811        ...
     1812        TypeError: size of elementary matrix must be an integer, not 4/3
     1813
     1814        sage: E = elementary_matrix(ZZ, -3, row1=3, row2=1, scale=12)
     1815        Traceback (most recent call last):
     1816        ...
     1817        ValueError: size of elementary matrix must be positive, not -3
     1818
     1819        sage: E = elementary_matrix(ZZ, 5, row1=4/3, row2=1, scale=12)
     1820        Traceback (most recent call last):
     1821        ...
     1822        TypeError: row of elementary matrix must be an integer, not 4/3
     1823
     1824        sage: E = elementary_matrix(ZZ, 5, row1=5, row2=1, scale=12)
     1825        Traceback (most recent call last):
     1826        ...
     1827        ValueError: row of elementary matrix must be positive and smaller than 5, not 5
     1828
     1829        sage: E = elementary_matrix(ZZ, 5, row1=3, row2=4/3, scale=12)
     1830        Traceback (most recent call last):
     1831        ...
     1832        TypeError: row of elementary matrix must be an integer, not 4/3
     1833
     1834        sage: E = elementary_matrix(ZZ, 5, row1=3, row2=-1, scale=12)
     1835        Traceback (most recent call last):
     1836        ...
     1837        ValueError: row of elementary matrix must be positive and smaller than 5, not -1
     1838
     1839        sage: E = elementary_matrix(ZZ, 5, row1=3, row2=1, scale=4/3)
     1840        Traceback (most recent call last):
     1841        ...
     1842        TypeError: scale parameter of elementary matrix must an element of Integer Ring, not 4/3
     1843
     1844        sage: E = elementary_matrix(ZZ, 5, row1=3)
     1845        Traceback (most recent call last):
     1846        ...
     1847        ValueError: insufficient parameters provided to construct elementary matrix
     1848
     1849        sage: E = elementary_matrix(ZZ, 5, row1=3, scale=0)
     1850        Traceback (most recent call last):
     1851        ...
     1852        ValueError: scale parameter of row of elementary matrix must be non-zero
     1853
     1854    AUTHOR:
     1855
     1856    - Rob Beezer (2011-03-04)
     1857    """
     1858    # collect and sanitize arguments
     1859    if rings.is_Ring(arg0):
     1860        R = arg0
     1861        arg0 = arg1
     1862    else:
     1863        R = rings.ZZ
     1864    try:
     1865        n = rings.Integer(arg0)
     1866    except:
     1867        raise TypeError('size of elementary matrix must be an integer, not {0}'.format(arg1))
     1868    if n < 0:
     1869        raise ValueError('size of elementary matrix must be positive, not {0}'.format(n))
     1870    try:
     1871        row1 = rings.Integer(row1)
     1872    except:
     1873        raise TypeError('row of elementary matrix must be an integer, not {0}'.format(row1))
     1874    if row1 < 0 or row1 >= n :
     1875        raise ValueError('row of elementary matrix must be positive and smaller than {0}, not {1}'.format(n, row1))
     1876    if not row2 is None:
     1877        try:
     1878            row2 = rings.Integer(row2)
     1879        except:
     1880            raise TypeError('row of elementary matrix must be an integer, not {0}'.format(row2))
     1881        if row2 < 0 or row2 >= n :
     1882            raise ValueError('row of elementary matrix must be positive and smaller than {0}, not {1}'.format(n, row2))
     1883    if not scale is None:
     1884        try:
     1885            scale = R(scale)
     1886        except:
     1887            raise TypeError('scale parameter of elementary matrix must an element of {0}, not {1}'.format(R, scale))
     1888
     1889    # determine type of matrix and adjust an identity matrix
     1890    elem = identity_matrix(R, n)
     1891    if row2 is None and scale is None:
     1892        raise ValueError('insufficient parameters provided to construct elementary matrix')
     1893    if not row2 is None and not scale is None:
     1894        elem[row1, row2] = scale
     1895        return elem
     1896    if not row2 is None and scale is None:
     1897        elem[row1, row1] = 0
     1898        elem[row2, row2] = 0
     1899        elem[row1, row2] = 1
     1900        elem[row2, row1] = 1
     1901        return elem
     1902    if row2 is None and not scale is None:
     1903        if scale == 0:
     1904            raise ValueError('scale parameter of row of elementary matrix must be non-zero')
     1905        elem[row1, row1] = scale
     1906        return elem
     1907
    16441908def _determine_block_matrix_grid(sub_matrices):
    16451909    r"""
    16461910    For internal use. This tries to determine the dimensions