Helpers for creating matrices#

class sage.matrix.args.MatrixArgs#

Bases: object

Collect arguments for constructing a matrix.

This class is meant to pass around arguments, for example from the global matrix() constructor to the matrix space or to the element class constructor.

A typical use case is first creating a MatrixArgs instance, possibly adjusting the attributes. This instance can then be passed around and a matrix can be constructed from it using the matrix() method. Also, a flat list can be constructed using list() or a sparse dict using dict(). It is safe to construct multiple objects (of the same or a different kind) from the same MatrixArgs instance.

MatrixArgs also supports iteration using the iter() method. This is a more low-level interface.

When MatrixArgs produces output, it is first finalized. This means that all missing attributes are derived or guessed. After finalization, you should no longer change the attributes or it will end up in an inconsistent state. You can also finalize explicitly by calling the finalized() method.

A MatrixArgs can contain invalid input. This is not checked when constructing the MatrixArgs instance, but it is checked either when finalizing or when constructing an object from it.

Warning

Instances of this class should only be temporary, they are not meant to be stored long-term.

EXAMPLES:

sage: from sage.matrix.args import MatrixArgs
sage: ma = MatrixArgs(2, 2, (x for x in range(4))); ma
<MatrixArgs for None; typ=UNKNOWN; entries=<generator ...>>
sage: ma.finalized()
<MatrixArgs for Full MatrixSpace of 2 by 2 dense matrices over Integer Ring; typ=SEQ_FLAT; entries=[0, 1, 2, 3]>

Many types of input are possible:

sage: ma = MatrixArgs(2, 2, entries=None); ma.finalized(); ma.matrix()
<MatrixArgs for Full MatrixSpace of 2 by 2 dense matrices over Integer Ring; typ=ZERO; entries=None>
[0 0]
[0 0]
sage: ma = MatrixArgs(2, 2, entries={}); ma.finalized(); ma.matrix()
<MatrixArgs for Full MatrixSpace of 2 by 2 sparse matrices over Integer Ring; typ=SEQ_SPARSE; entries=[]>
[0 0]
[0 0]
sage: ma = MatrixArgs(2, 2, entries=[1,2,3,4]); ma.finalized(); ma.matrix()
<MatrixArgs for Full MatrixSpace of 2 by 2 dense matrices over Integer Ring; typ=SEQ_FLAT; entries=[1, 2, 3, 4]>
[1 2]
[3 4]
sage: ma = MatrixArgs(2, 2, entries=math.pi); ma.finalized(); ma.matrix()
<MatrixArgs for Full MatrixSpace of 2 by 2 dense matrices over Real Double Field; typ=SCALAR; entries=3.141592653589793>
[3.141592653589793               0.0]
[              0.0 3.141592653589793]
sage: ma = MatrixArgs(2, 2, entries=pi); ma.finalized()                         # needs sage.symbolic
<MatrixArgs for Full MatrixSpace of 2 by 2 dense matrices
 over Symbolic Ring; typ=SCALAR; entries=pi>
sage: ma.matrix()                                                               # needs sage.symbolic
[pi  0]
[ 0 pi]
sage: ma = MatrixArgs(ZZ, 2, 2, entries={(0,0):7}); ma.finalized(); ma.matrix()
<MatrixArgs for Full MatrixSpace of 2 by 2 sparse matrices over Integer Ring; typ=SEQ_SPARSE; entries=[SparseEntry(0, 0, 7)]>
[7 0]
[0 0]
sage: ma = MatrixArgs(ZZ, 2, 2, entries=((1,2),(3,4))); ma.finalized(); ma.matrix()
<MatrixArgs for Full MatrixSpace of 2 by 2 dense matrices over Integer Ring; typ=SEQ_SEQ; entries=((1, 2), (3, 4))>
[1 2]
[3 4]
sage: ma = MatrixArgs(ZZ, 2, 2, entries=(1,2,3,4)); ma.finalized(); ma.matrix()
<MatrixArgs for Full MatrixSpace of 2 by 2 dense matrices over Integer Ring; typ=SEQ_FLAT; entries=(1, 2, 3, 4)>
[1 2]
[3 4]

sage: # needs sage.libs.pari
sage: ma = MatrixArgs(QQ, entries=pari("[1,2;3,4]")); ma.finalized()
<MatrixArgs for Full MatrixSpace of 2 by 2 dense matrices
 over Rational Field; typ=SEQ_FLAT; entries=[1, 2, 3, 4]>
sage: ma.matrix()
[1 2]
[3 4]
sage: ma = MatrixArgs(QQ, 2, 2, entries=pari("[1,2,3,4]")); ma.finalized()
<MatrixArgs for Full MatrixSpace of 2 by 2 dense matrices
 over Rational Field; typ=SEQ_FLAT; entries=[1, 2, 3, 4]>
sage: ma.matrix()
[1 2]
[3 4]
sage: ma = MatrixArgs(QQ, 2, 2, entries=pari("3/5")); ma.finalized()
<MatrixArgs for Full MatrixSpace of 2 by 2 dense matrices
 over Rational Field; typ=SCALAR; entries=3/5>
sage: ma.matrix()
[3/5   0]
[  0 3/5]

sage: ma = MatrixArgs(entries=matrix(2,2)); ma.finalized(); ma.matrix()
<MatrixArgs for Full MatrixSpace of 2 by 2 dense matrices over Integer Ring; typ=MATRIX; entries=[0 0]
[0 0]>
[0 0]
[0 0]
sage: ma = MatrixArgs(2, 2, entries=lambda i,j: 1+2*i+j); ma.finalized(); ma.matrix()
<MatrixArgs for Full MatrixSpace of 2 by 2 dense matrices over Integer Ring; typ=SEQ_FLAT; entries=[1, 2, 3, 4]>
[1 2]
[3 4]
sage: ma = MatrixArgs(ZZ, 2, 2, entries=lambda i,j: 1+2*i+j); ma.finalized(); ma.matrix()
<MatrixArgs for Full MatrixSpace of 2 by 2 dense matrices over Integer Ring; typ=CALLABLE; entries=<function ...>>
[1 2]
[3 4]

sage: # needs numpy
sage: from numpy import array
sage: ma = MatrixArgs(array([[1,2],[3,4]])); ma.finalized()
<MatrixArgs for Full MatrixSpace of 2 by 2 dense matrices
 over Integer Ring; typ=SEQ_SEQ; entries=array([[1, 2], [3, 4]])>
sage: ma.matrix()
[1 2]
[3 4]
sage: ma = MatrixArgs(array([[1.,2.],[3.,4.]])); ma.finalized()
<MatrixArgs for Full MatrixSpace of 2 by 2 dense matrices
 over Real Double Field; typ=MATRIX; entries=[1.0 2.0]
                                             [3.0 4.0]>
sage: ma.matrix()
[1.0 2.0]
[3.0 4.0]
sage: ma = MatrixArgs(RealField(20), array([[1.,2.],[3.,4.]])); ma.finalized()
<MatrixArgs for Full MatrixSpace of 2 by 2 dense matrices over Real Field
 with 20 bits of precision; typ=MATRIX; entries=[1.0 2.0]
                                                [3.0 4.0]>
sage: ma.matrix()
[1.0000 2.0000]
[3.0000 4.0000]

sage: # needs sage.graphs
sage: ma = MatrixArgs(graphs.CycleGraph(3)); ma.finalized()
<MatrixArgs for Full MatrixSpace of 3 by 3 dense matrices
 over Integer Ring; typ=MATRIX; entries=[0 1 1]
                                        [1 0 1]
                                        [1 1 0]>
sage: ma.matrix()
[0 1 1]
[1 0 1]
[1 1 0]

sage: ma = MatrixArgs([vector([0,1], sparse=True), vector([0,0], sparse=True)], sparse=True)
sage: ma.finalized(); ma.matrix()
<MatrixArgs for Full MatrixSpace of 2 by 2 sparse matrices over Integer Ring; typ=SEQ_SPARSE; entries=[SparseEntry(0, 1, 1)]>
[0 1]
[0 0]

Test invalid input:

sage: MatrixArgs(ZZ, 2, 2, entries="abcd").finalized()
Traceback (most recent call last):
...
TypeError: unable to convert 'abcd' to a matrix
sage: MatrixArgs(ZZ, 2, 2, entries=MatrixArgs()).finalized()
Traceback (most recent call last):
...
TypeError: unable to convert <MatrixArgs for None; typ=UNKNOWN; entries=None> to a matrix
base#
dict(convert=True)#

Return the entries of the matrix as a dict. The keys of this dict are the non-zero positions (i,j). The corresponding value is the entry at that position. Zero values are skipped.

If convert is True, the entries are converted to the base ring. Otherwise, the entries are returned as given.

EXAMPLES:

sage: from sage.matrix.args import MatrixArgs
sage: L = list(range(6))
sage: MatrixArgs(2, 3, L).dict()
{(0, 1): 1, (0, 2): 2, (1, 0): 3, (1, 1): 4, (1, 2): 5}
sage: ma = MatrixArgs(GF(2), 2, 3, L)
sage: ma.dict(convert=False)
{(0, 1): 1, (0, 2): 2, (1, 0): 3, (1, 1): 4, (1, 2): 5}
sage: ma.dict()
{(0, 1): 1, (1, 0): 1, (1, 2): 1}
entries#
finalized()#

Determine all missing values.

Depending on the input, this might be a non-trivial operation. In some cases, this will do most of the work of constructing the matrix. That is actually not a problem since we eventually want to construct the matrix anyway. However, care is taken to avoid double work or needless checking or copying.

OUTPUT: self

EXAMPLES:

sage: from sage.matrix.args import MatrixArgs
sage: MatrixArgs(pi).finalized()                                            # needs sage.symbolic
Traceback (most recent call last):
...
TypeError: the dimensions of the matrix must be specified
sage: MatrixArgs(RR, pi).finalized()                                        # needs sage.symbolic
Traceback (most recent call last):
...
TypeError: the dimensions of the matrix must be specified
sage: MatrixArgs(2, 3, 0.0).finalized()
<MatrixArgs for Full MatrixSpace of 2 by 3 dense matrices over Real Field with 53 bits of precision; typ=ZERO; entries=0.000000000000000>
sage: MatrixArgs(RR, 2, 3, 1.0).finalized()
Traceback (most recent call last):
...
TypeError: nonzero scalar matrix must be square

Check github issue #19134:

sage: matrix(2, 3, [])
Traceback (most recent call last):
...
ValueError: sequence too short (expected length 6, got 0)
sage: matrix(ZZ, 2, 3, [])
Traceback (most recent call last):
...
ValueError: sequence too short (expected length 6, got 0)
sage: matrix(2, 3, [1])
Traceback (most recent call last):
...
ValueError: sequence too short (expected length 6, got 1)

Check github issue #36065:

sage: # needs sage.rings.number_field sage: class MyAlgebraicNumber(sage.rings.qqbar.AlgebraicNumber): ….: def __bool__(self): ….: raise ValueError sage: matrix(1, 1, MyAlgebraicNumber(0)) [0] sage: matrix(1, 1, MyAlgebraicNumber(3)) [3] sage: matrix(1, 2, MyAlgebraicNumber(0)) Traceback (most recent call last): … TypeError: scalar matrix must be square if the value cannot be determined to be zero sage: matrix(1, 2, MyAlgebraicNumber(3)) Traceback (most recent call last): … TypeError: scalar matrix must be square if the value cannot be determined to be zero

iter(convert=True, sparse=False)#

Iteration over the entries in the matrix

INPUT:

  • convert – If True, the entries are converted to the base right. If False, the entries are returned as given.

  • sparse – See OUTPUT below.

OUTPUT: iterator

  • If sparse is False: yield all entries of the matrix in the following order:

    [1 2 3]
    [4 5 6]
    
  • If sparse is True: yield instances of SparseEntry. The indices (i, j) are guaranteed to lie within the matrix. Zero entries in the input are not skipped.

Warning

If an iterator is given as input to MatrixArgs, it may be exhausted breaking any further usage. Otherwise, it is safe to iterate multiple times.

EXAMPLES:

sage: from sage.matrix.args import SparseEntry, MatrixArgs
sage: ma = MatrixArgs(ZZ, 2, 3, iter(range(6)))
sage: list(ma.iter())
[0, 1, 2, 3, 4, 5]
sage: ma = MatrixArgs(ZZ, 3, 3, [SparseEntry(0, 0, 0)])
sage: list(ma.iter())
Traceback (most recent call last):
...
TypeError: dense iteration is not supported for sparse input

Sparse examples:

sage: ma = MatrixArgs(3, 3, pi)                                             # needs sage.symbolic
sage: list(ma.iter(sparse=True))                                            # needs sage.symbolic
[SparseEntry(0, 0, pi), SparseEntry(1, 1, pi), SparseEntry(2, 2, pi)]
sage: ma = MatrixArgs(2, 3)
sage: list(ma.iter(sparse=True))
[]
sage: ma = MatrixArgs(2, 2, lambda i, j: i > j)
sage: list(ma.iter(convert=False, sparse=True))
[SparseEntry(0, 0, False),
 SparseEntry(0, 1, False),
 SparseEntry(1, 0, True),
 SparseEntry(1, 1, False)]
sage: ma = MatrixArgs(2, 2, {(1,0):88, (0,1):89})
sage: sorted(tuple(x) for x in ma.iter(sparse=True))
[(0, 1, 89), (1, 0, 88)]
sage: ma = MatrixArgs(QQ, 2, 1, {(1,0):88, (0,1):89})
sage: ma.finalized()
Traceback (most recent call last):
...
IndexError: invalid column index 1
sage: ma = MatrixArgs(QQ, 1, 2, {(1,0):88, (0,1):89})
sage: ma.finalized()
Traceback (most recent call last):
...
IndexError: invalid row index 1
kwds#
list(convert=True)#

Return the entries of the matrix as a flat list of scalars.

If possible and convert=False, this returns a direct reference to self.entries without copying.

INPUT:

  • convert – If True, the entries are converted to the base ring. Otherwise, the entries are returned as given.

Note

This changes self.entries to the returned list. This means that it is unsafe to access the self.entries attribute after calling this method.

EXAMPLES:

sage: from sage.matrix.args import MatrixArgs
sage: L = list(range(6))
sage: MatrixArgs(2, 3, L).list()
[0, 1, 2, 3, 4, 5]
sage: ma = MatrixArgs(RDF, 2, 3, L)
sage: ma.list(convert=False)
[0, 1, 2, 3, 4, 5]
sage: ma.list()
[0.0, 1.0, 2.0, 3.0, 4.0, 5.0]

If we remove our reference to the input L and convert=False, no copy is made:

sage: idL = id(L)
sage: ma = MatrixArgs(2, 3, L)
sage: del L
sage: L = ma.list(convert=False)
sage: id(L) == idL
True
matrix(convert=True)#

Return the entries of the matrix as a Sage Matrix.

If possible, this returns a direct reference to self.entries without copying.

INPUT:

  • convert – if True, the matrix is guaranteed to have the correct parent matrix space. If False, the input matrix may be returned even if it lies in the wrong space.

Note

This changes self.entries to the returned matrix. This means that it is unsafe to access the self.entries attribute after calling this method.

EXAMPLES:

sage: from sage.matrix.args import MatrixArgs
sage: M = matrix(2, 3, range(6), sparse=True)
sage: ma = MatrixArgs(M); ma.finalized()
<MatrixArgs for Full MatrixSpace of 2 by 3 sparse matrices over Integer Ring; typ=MATRIX; entries=[0 1 2]
[3 4 5]>
sage: ma.matrix()
[0 1 2]
[3 4 5]
sage: ma = MatrixArgs(M, sparse=False); ma.finalized()
<MatrixArgs for Full MatrixSpace of 2 by 3 dense matrices over Integer Ring; typ=MATRIX; entries=[0 1 2]
[3 4 5]>
sage: ma.matrix()
[0 1 2]
[3 4 5]
sage: ma = MatrixArgs(RDF, M); ma.finalized()
<MatrixArgs for Full MatrixSpace of 2 by 3 sparse matrices over Real Double Field; typ=MATRIX; entries=[0 1 2]
[3 4 5]>
sage: ma.matrix(convert=False)
[0 1 2]
[3 4 5]
sage: ma.matrix()
[0.0 1.0 2.0]
[3.0 4.0 5.0]

If we remove our reference to the input M, no copy is made:

sage: idM = id(M)
sage: ma = MatrixArgs(M)
sage: del M
sage: M = ma.matrix()
sage: id(M) == idM
True

Immutable matrices are never copied:

sage: M.set_immutable()
sage: matrix(M) is M
True
ncols#
nrows#
set_space(space)#

Set inputs from a given matrix space.

INPUT:

EXAMPLES:

sage: from sage.matrix.args import MatrixArgs
sage: ma = MatrixArgs()
sage: S = MatrixSpace(QQ, 3, 2, sparse=True)
sage: _ = ma.set_space(S)
sage: ma.finalized()
<MatrixArgs for Full MatrixSpace of 3 by 2 sparse matrices over Rational Field; typ=ZERO; entries=None>
sage: M = ma.matrix(); M
[0 0]
[0 0]
[0 0]
sage: M.parent() is S
True
space#
sparse#
sage.matrix.args.MatrixArgs_init(space, entries)#

Construct a MatrixArgs object from a matrix space and entries. This is the typical use in a matrix constructor.

If the given entries is already an instance of MatrixArgs, then just set the space and return the same object.

EXAMPLES:

sage: from sage.matrix.args import MatrixArgs_init
sage: S = MatrixSpace(GF(2), 2, 4)
sage: ma = MatrixArgs_init(S, {(1, 3): 7})
sage: M = ma.matrix(); M
[0 0 0 0]
[0 0 0 1]
sage: parent(M) is S
True
class sage.matrix.args.SparseEntry#

Bases: object

Specialized class for dealing with sparse input in MatrixArgs. An instance of SparseEntry represents one position in a matrix to be constructed. To construct a sparse matrix, one would typically make a list of such.

Previous versions of Sage used a dict as data structure for sparse input, but that is not so suitable because the keys are not guaranteed to be of the correct format. There is also the performance cost of creating tuples of Python integers.

Users of this class are expected to know what they are doing, so the indices are not checked when constructing a matrix.

INPUT:

  • i, j – row and column index

  • entry – value to be put at position \((i,j)\)

EXAMPLES:

sage: from sage.matrix.args import SparseEntry
sage: SparseEntry(123, 456, "abc")
SparseEntry(123, 456, 'abc')
sage: SparseEntry(1/3, 2/3, x)                                                  # needs sage.symbolic
Traceback (most recent call last):
...
TypeError: unable to convert rational 1/3 to an integer
entry#
i#
j#