Ticket #13012: trac_13012_bug_with_zero_matrices.patch

File trac_13012_bug_with_zero_matrices.patch, 19.2 KB (added by Andrey Novoseltsev, 11 years ago)
  • sage/coding/linear_code.py

    # HG changeset patch
    # User Andrey Novoseltsev <novoselt@gmail.com>
    # Date 1338087477 25200
    # Node ID e56aebc14b4bdbe7c263b14fed7ec1b10c1ba091
    # Parent  4d86b7654555f68192569a1b3257a997012a833b
    Prevent MatrixSpace from constructing zero matrices from unsuitable data.
    
    diff --git a/sage/coding/linear_code.py b/sage/coding/linear_code.py
    a b  
    21352135            sage: C.punctured([1,2])
    21362136            Linear code of length 5, dimension 4 over Finite Field of size 2
    21372137        """
    2138         G = self.gen_mat()
    2139         F = self.base_ring()
    2140         nC = len(G.columns())
    2141         kC = len(G.rows())
    2142         nL = nC-len(L)
    2143         colsGnotL = [G.columns()[i] for i in range(nC) if not(i in L)]
    2144         MS1 = MatrixSpace(F, kC, nL)
    2145         GL1 = MS1(list(colsGnotL))
    2146         VnotL = GL1.row_space()
    2147         B = VnotL.basis()
    2148         k = len(list(B))
    2149         MS2 = MatrixSpace(F, k, nL)
    2150         GL2 = MS2(list(B))
    2151         return LinearCode(GL2)
     2138        G = self.gen_mat()       
     2139        GL = G.matrix_from_columns([i for i in range(G.ncols()) if i not in L])
     2140        return LinearCode(GL.row_space().basis_matrix())
    21522141
    21532142    def random_element(self, *args, **kwds):
    21542143        """
  • sage/matrix/constructor.py

    diff --git a/sage/matrix/constructor.py b/sage/matrix/constructor.py
    a b  
    288288        sage: m=matrix(QQ,5,[1,2,3,4,5,6]); m; m.parent()
    289289        Traceback (most recent call last):
    290290        ...
    291         TypeError: entries has the wrong length
     291        TypeError: cannot construct an element of
     292        Full MatrixSpace of 5 by 1 dense matrices over Rational Field
     293        from [1, 2, 3, 4, 5, 6]!
    292294        sage: m=matrix({(1,1): 2}); m; m.parent()
    293295        [0 0]
    294296        [0 2]
  • sage/matrix/matrix_integer_2x2.pyx

    diff --git a/sage/matrix/matrix_integer_2x2.pyx b/sage/matrix/matrix_integer_2x2.pyx
    a b  
    153153            sage: MS([11,3])
    154154            Traceback (most recent call last):
    155155            ...
    156             TypeError: entries has the wrong length
     156            TypeError: cannot construct an element of
     157            Space of 2x2 integer matrices from [11, 3]!
    157158        """
    158159        matrix.Matrix.__init__(self, parent)
    159160
  • sage/matrix/matrix_space.py

    diff --git a/sage/matrix/matrix_space.py b/sage/matrix/matrix_space.py
    a b  
    6767import sage.structure.coerce
    6868import sage.structure.parent_gens as parent_gens
    6969from sage.structure.unique_representation import UniqueRepresentation
     70from sage.rings.all import ZZ
    7071import sage.rings.ring as ring
    7172import sage.rings.rational_field as rational_field
    7273import sage.rings.integer_ring as integer_ring
     
    7879import sage.rings.finite_rings.integer_mod_ring
    7980import sage.rings.polynomial.multi_polynomial_ring_generic
    8081import sage.misc.latex as latex
     82from sage.misc.misc import deprecation
    8183import sage.misc.mrange
    8284import sage.modules.free_module_element
    8385import sage.modules.free_module
     
    407409            sage: M2 = MS(range(8)); M2
    408410            [0 1 2 3]
    409411            [4 5 6 7]
    410             sage: M2.columns()
    411             [(0, 4), (1, 5), (2, 6), (3, 7)]
    412             sage: MS(M2.columns())
    413             [0 1 2 3]
    414             [4 5 6 7]
    415             sage: M2 == MS(M2.columns())
    416             True
    417412            sage: M2 == MS(M2.rows())
    418413            True
    419414       
     
    423418            sage: M2 = MS(range(8)); M2
    424419            [0 1 2 3]
    425420            [4 5 6 7]
    426             sage: M2.columns()
    427             [(0, 4), (1, 5), (2, 6), (3, 7)]
    428             sage: MS(M2.columns())
    429             [0 1 2 3]
    430             [4 5 6 7]
    431             sage: M2 == MS(M2.columns())
    432             True
    433421            sage: M2 == MS(M2.rows())
    434422            True
    435423       
     
    440428            [1 2]
    441429            [3 4]
    442430            sage: MS([1,2,3,4], rows=True)
     431            doctest:...: DeprecationWarning: (Since Sage 5.1)
     432            'rows=True/False' parameter is deprecated!
    443433            [1 2]
    444434            [3 4]
    445435            sage: MS([1,2,3,4], rows=False)
     
    478468
    479469        TESTS:
    480470
    481         Ensure that trac 12020 is fixed::
     471        Ensure that :trac:`12020` is fixed::
    482472
    483473            sage: x = polygen(QQ)
    484             sage: for R in [ZZ, QQ, RealField(100), ComplexField(100), RDF, CDF, SR, GF(2), GF(11), GF(2^8,'a'), GF(3^19,'a'), NumberField(x^3+2,'a'), CyclotomicField(4), PolynomialRing(QQ,'x'), PolynomialRing(CC,2,'x')]:
     474            sage: for R in [ZZ, QQ, RealField(100), ComplexField(100), RDF, CDF,
     475            ...             SR, GF(2), GF(11), GF(2^8,'a'), GF(3^19,'a'),
     476            ...             NumberField(x^3+2,'a'), CyclotomicField(4),
     477            ...             PolynomialRing(QQ,'x'), PolynomialRing(CC,2,'x')]:
    485478            ...       A = MatrixSpace(R,60,30,sparse=False)(0)
    486479            ...       B = A.augment(A)
    487480            ...       A = MatrixSpace(R,60,30,sparse=True)(0)
    488481            ...       B = A.augment(A)
     482           
     483        Check that :trac:`13012` is fixed::
     484       
     485            sage: m = zero_matrix(2, 3)
     486            sage: m
     487            [0 0 0]
     488            [0 0 0]
     489            sage: M = MatrixSpace(ZZ, 3, 5)
     490            sage: M.zero()
     491            [0 0 0 0 0]
     492            [0 0 0 0 0]
     493            [0 0 0 0 0]
     494            sage: M(m)
     495            Traceback (most recent call last):
     496            ...
     497            ValueError: a matrix from
     498            Full MatrixSpace of 2 by 3 dense matrices over Integer Ring
     499            cannot be converted to a matrix in
     500            Full MatrixSpace of 3 by 5 dense matrices over Integer Ring!
     501            sage: M.matrix(m)
     502            Traceback (most recent call last):
     503            ...
     504            ValueError: a matrix from
     505            Full MatrixSpace of 2 by 3 dense matrices over Integer Ring
     506            cannot be converted to a matrix in
     507            Full MatrixSpace of 3 by 5 dense matrices over Integer Ring!
    489508        """
    490         if entries is None or entries == 0:
    491             if self._copy_zero: # faster to copy than to create a new one.
    492                 return self.zero_matrix().__copy__()
    493             else:
    494                 return self.__matrix_class(self, None, coerce=coerce, copy=copy)
    495 
    496         if isinstance(entries, (list, tuple)) and len(entries) > 0 and \
    497            sage.modules.free_module_element.is_FreeModuleElement(entries[0]):
    498             #Try to determine whether or not the entries should
    499             #be rows or columns
    500             if rows is None:
    501                 #If the matrix is square, default to rows
    502                 if self.__ncols == self.__nrows:
    503                     rows = True
    504                 elif len(entries[0]) == self.__ncols:
    505                     rows = True
    506                 elif len(entries[0]) == self.__nrows:
    507                     rows = False
    508                 else:
    509                     raise ValueError("incorrect dimensions")
    510            
    511             if self.__is_sparse:
    512                 e = {}
    513                 zero = self.base_ring()(0)
    514                 for i in xrange(len(entries)):
    515                     for j, x in entries[i].iteritems():
    516                         if x != zero:
    517                             if rows:
    518                                 e[(i,j)] = x
    519                             else:
    520                                 e[(j,i)] = x
    521                 entries = e
    522             else:
    523                 tmp=[]
    524                 for v in entries:
    525                     tmp.extend(v)
    526                 entries = tmp
    527 
    528         if rows is None:
    529             rows = True
    530 
    531         if not self.__is_sparse and isinstance(entries, dict):
    532             entries = dict_to_list(entries, self.__nrows, self.__ncols)
    533             coerce = True
    534             copy = False
    535         elif self.__is_sparse and isinstance(entries, (list, tuple)):
    536             entries = list_to_dict(entries, self.__nrows, self.__ncols, rows=rows)
    537             coerce = True
    538             copy = False
    539         elif sage.groups.matrix_gps.matrix_group_element.is_MatrixGroupElement(entries) \
    540              or isinstance(entries, sage.modular.arithgroup.arithgroup_element.ArithmeticSubgroupElement):
    541             return self(entries.matrix(), copy=False)
    542 
    543         return self.matrix(entries, copy=copy, coerce=coerce, rows=rows)
     509        if rows is not None:
     510            deprecation("'rows=True/False' parameter is deprecated!", "Sage 5.1")
     511            return self.matrix(entries, coerce, copy, rows)
     512        return self.matrix(entries, coerce, copy)
    544513
    545514    def change_ring(self, R):
    546515        """
     
    914883            weight = 0
    915884            while True:
    916885                for iv in sage.combinat.integer_vector.IntegerVectors(weight, number_of_entries):
    917                     yield self(entries=[base_elements[i] for i in iv], rows=True)       
    918                        
     886                    yield self(entries=[base_elements[i] for i in iv])
    919887                weight += 1
    920888                base_elements.append( base_iter.next() )
    921889        else:
     
    927895            base_elements = list(base_ring)
    928896            for weight in range((order-1)*number_of_entries+1):
    929897                for iv in sage.combinat.integer_vector.IntegerVectors(weight, number_of_entries, max_part=(order-1)):
    930                    yield self(entries=[base_elements[i] for i in iv], rows=True)
     898                   yield self(entries=[base_elements[i] for i in iv])
    931899
    932900    def _get_matrix_class(self):
    933901        r"""
     
    12051173        """
    12061174        return self.dimension()
    12071175
    1208     def matrix(self, x=0, coerce=True, copy=True, rows=True):
     1176    def matrix(self, x=0, coerce=True, copy=True, rows=None):
    12091177        r"""
    12101178        Create a matrix in ``self``.
    12111179       
     
    12161184         
    12171185          * 0, corresponding to the zero matrix;
    12181186         
    1219           * a matrix, whose dimension must match ``self`` and whose base ring
     1187          * 1, corresponding to the identity_matrix;
     1188         
     1189          * a matrix, whose dimensions must match ``self`` and whose base ring
    12201190            must be convertible to the base ring of ``self``;
    12211191           
    12221192          * a list of entries corresponding to all elements of the new matrix;
    12231193         
    1224           * a list of lists with each inner list being either a row or a column
    1225             of the new matrix.
     1194          * a list of rows with each row given as an iterable;
    12261195
    1227           * a list of vectors or matrices
    1228            
    12291196        - ``coerce`` -- (default: ``True``) whether to coerce ``x`` into self;
    12301197       
    12311198        - ``copy`` -- (default: ``True``) whether to copy ``x`` during
    12321199          construction (makes a difference only if ``x`` is a matrix in
    1233           ``self``);
    1234          
    1235         - ``rows`` -- (default: ``True``) whether entries are given row by row
    1236           or column by column.
     1200          ``self``).
    12371201         
    12381202        OUTPUT:
    12391203       
     
    12521216            [1 2]
    12531217            [3 4]
    12541218            sage: M.matrix([1,2,3,4],rows=False)
     1219            doctest:...: DeprecationWarning: (Since Sage 5.1)
     1220            'rows=True/False' parameter is deprecated!
    12551221            [1 3]
    12561222            [2 4]
    12571223           
     
    12851251            [0 0]
    12861252            [1 0]
    12871253
    1288         Trac ticket #10628 enables to provide the data be lists of matrices::
    1289 
    1290             sage: MS = MatrixSpace(ZZ,4,2)
    1291             sage: MS0 = MatrixSpace(ZZ,2)
    1292             sage: MS.matrix([MS0([1,2,3,4]), MS0([5,6,7,8])])
    1293             [1 2]
    1294             [3 4]
    1295             [5 6]
    1296             [7 8]
    1297 
    1298         A mixed list of matrices and vectors is allowed as well::
    1299 
    1300             sage: MS.matrix( [MS0([1,2,3,4])] + list(MS0([5,6,7,8])) )
    1301             [1 2]
    1302             [3 4]
    1303             [5 6]
    1304             [7 8]
    1305 
    1306 
    13071254        TESTS:
    13081255
    13091256        The following corner cases were problematic while working on #10628::
     
    13181265            [ 1.00000000000000]
    13191266            [0.000000000000000]
    13201267
     1268        Trac ticket #10628 allowed to provide the data be lists of matrices, but
     1269        :trac:`13012` prohibited it::
     1270
     1271            sage: MS = MatrixSpace(ZZ,4,2)
     1272            sage: MS0 = MatrixSpace(ZZ,2)
     1273            sage: MS.matrix([MS0([1,2,3,4]), MS0([5,6,7,8])])
     1274            Traceback (most recent call last):
     1275            ...
     1276            TypeError: cannot construct an element of
     1277            Full MatrixSpace of 4 by 2 dense matrices over Integer Ring
     1278            from [[1 2]
     1279            [3 4], [5 6]
     1280            [7 8]]!
     1281
     1282        A mixed list of matrices and vectors is prohibited as well::
     1283
     1284            sage: MS.matrix( [MS0([1,2,3,4])] + list(MS0([5,6,7,8])) )
     1285            Traceback (most recent call last):
     1286            ...
     1287            TypeError: cannot construct an element of
     1288            Full MatrixSpace of 4 by 2 dense matrices over Integer Ring
     1289            from [[1 2]
     1290            [3 4], (5, 6), (7, 8)]!
    13211291        """
    1322         if x is None or x==0:
    1323             return self.__matrix_class(self, x, False, False)
    1324 
    1325         if isinstance(x, (types.GeneratorType, xrange)):
    1326             x = list(x)
    1327         elif isinstance(x, (int, integer.Integer)) and x==1:
     1292        if x is None or isinstance(x, (int, integer.Integer)) and x == 0:
     1293            if self._copy_zero: # faster to copy than to create a new one.
     1294                return self.zero_matrix().__copy__()
     1295            else:
     1296                return self.__matrix_class(self, None, False, False)
     1297        if isinstance(x, (int, integer.Integer)) and x == 1:
    13281298            return self.identity_matrix().__copy__()
     1299        m, n, sparse = self.__nrows, self.__ncols, self.__is_sparse
     1300        if rows is not None:
     1301            deprecation("'rows=True/False' parameter is deprecated!", "Sage 5.1")
     1302        if rows is not None and not rows:
     1303            if not isinstance(x, dict):
     1304                MT =  MatrixSpace(self.base_ring(), n, m, sparse)
     1305                return MT.matrix(x, coerce=coerce, copy=copy).transpose()
    13291306        if matrix.is_Matrix(x):
    13301307            if x.parent() is self:
    13311308                if x.is_immutable():
     
    13331310                else:
    13341311                    return x.__copy__()
    13351312            else:
    1336                 if x.nrows() == self.__nrows and x.ncols() == self.__ncols:
     1313                if x.nrows() == m and x.ncols() == n:
    13371314                    x = x.list()
    13381315                else:
    13391316                    raise ValueError("a matrix from %s cannot be converted to "
    13401317                                     "a matrix in %s!" % (x.parent(), self))
     1318        from sage.groups.matrix_gps.matrix_group_element import \
     1319            is_MatrixGroupElement
     1320        from sage.modular.arithgroup.arithgroup_element import \
     1321            ArithmeticSubgroupElement
     1322        if is_MatrixGroupElement(x) or isinstance(x, ArithmeticSubgroupElement):
     1323            return self(x.matrix(), copy=False)
     1324        if isinstance(x, (types.GeneratorType, xrange)):
     1325            x = list(x)
     1326        if not sparse and isinstance(x, dict):
     1327            x = dict_to_list(x, m, n)
     1328            coerce = True
     1329            copy = False
     1330        MC = self.__matrix_class
     1331        if isinstance(x, (list, tuple)) and x:
     1332            if len(x) == m:     # Try unpacking elements
     1333                unpacked = True
     1334                new_x = []
     1335                for v in x:
     1336                    l = len(new_x)
     1337                    try:
     1338                        new_x.extend(v)
     1339                        if len(new_x) - l != n:
     1340                            raise TypeError
     1341                    except TypeError:
     1342                        unpacked = False
     1343                if unpacked:
     1344                    try:
     1345                        if sparse:
     1346                            return MC(self, list_to_dict(new_x, m, n),
     1347                                      copy=False, coerce=coerce)
     1348                        else:
     1349                            return MC(self, new_x, copy=False, coerce=coerce)
     1350                    except TypeError:
     1351                        pass
     1352            if len(x) != m * n:
     1353                raise TypeError("cannot construct an element of {} from {}!"
     1354                                .format(self, x))
     1355            if sparse:
     1356                x = list_to_dict(x, m, n)
     1357                copy = False
     1358        return MC(self, x, copy=copy, coerce=coerce)
    13411359
    1342         if isinstance(x, (list, tuple)):
    1343             lenx = len(x)
    1344             if lenx > 0:
    1345                 if (self.__ncols == 1 or lenx < self.__ncols*self.__nrows):
    1346                     # If the list has less than the expected length, then
    1347                     # we are likely to have a list of lists or matrices or vectors.
    1348                     # Hence, we expand the entries of x.
    1349                     e = []
    1350                     for v in x:
    1351                         if isinstance(v,(list, tuple)):
    1352                             e.extend(v)
    1353                         elif hasattr(v,'row'):
    1354                             try:
    1355                                 e.extend(v.list())
    1356                             except AttributeError:
    1357                                 pass
    1358                         else:
    1359                             e.append(v)
    1360                     x = e
    1361                     # x is a new list, hence, copy=False is OK
    1362                     copy = False
    1363                 # Now, x presumably is a list of ring elements.
    1364                 if not rows:
    1365                     new_x = []
    1366                     for k in xrange(len(x)):
    1367                         i = k % self.__ncols
    1368                         j = k // self.__ncols
    1369                         new_x.append( x[ i*self.__nrows + j ] )
    1370                     x = new_x
    1371                     copy = False
    1372         return self.__matrix_class(self, entries=x, copy=copy, coerce=coerce)
    1373      
    13741360    def matrix_space(self, nrows=None, ncols=None, sparse=False):
    13751361        """
    13761362        Return the matrix space with given number of rows, columns and
     
    15791565    d = {}
    15801566    if ncols == 0 or nrows == 0:
    15811567        return d
    1582     for i in range(len(entries)):
    1583         x = entries[i]
     1568    for i, x in enumerate(entries):
    15841569        if x != 0:
    15851570            col = i % ncols
    15861571            row = i // ncols
     
    15911576    return d
    15921577
    15931578
    1594 
    1595 # sage: m = matrix(F, 0,0, sparse=False)
    1596 # sage: m.determinant()
    1597 # 0
    1598 
    1599 
    16001579def test_trivial_matrices_inverse(ring, sparse=True, checkrank=True):
    16011580    """
    16021581    Tests inversion, determinant and is_invertible for trivial matrices.
  • sage/modules/matrix_morphism.py

    diff --git a/sage/modules/matrix_morphism.py b/sage/modules/matrix_morphism.py
    a b  
    11851185            sage: loads(A.dumps()) == A
    11861186            True
    11871187        """
    1188         if not matrix.is_Matrix(A):
    1189             A = matrix.MatrixSpace(parent.category().base_ring(),
    1190                                    parent.domain().rank(),
    1191                                    parent.codomain().rank())(A)
    11921188        R = A.base_ring()
    11931189        if A.nrows() != parent.domain().rank():
    11941190            raise ArithmeticError, "number of rows of matrix (=%s) must equal rank of domain (=%s)"%(A.nrows(), parent.domain().rank())
     
    12241220        EXAMPLES::
    12251221
    12261222            sage: V = ZZ^2; W = ZZ^3
    1227             sage: phi = V.hom([3*V.0 - 5*V.1, 4*V.0 + 2*V.1, V.0 + V.1], W)
     1223            sage: m = column_matrix([3*V.0 - 5*V.1, 4*V.0 + 2*V.1, V.0 + V.1])
     1224            sage: phi = V.hom(m, W)
    12281225            sage: phi.matrix()
    12291226            [ 3  4  1]
    12301227            [-5  2  1]