Matrices can be indexed using one or two arguments. In single-argument
indexing of a matrix A, the index runs from
-len(A)
to len(A)-1
, and is interpreted as an
index in the one-dimensional array of coefficients of A
in column-major order. Negative indices have the standard Python
interpretation: for negative k, A[k]
is the
same element as A[len(A)+k]
.
Four different types of one-argument indexing are implemented.
A[0]
is the first element of A.
A[[0,1,2,3]]
is the 4 by 1 matrix consisting
of elements 0, 1, 2, 3 of A.
A[::2]
is the column matrix defined by taking every other element of A,
stored in column-major order.
A[0:0]
is a matrix with size (0,1).
Note that an index list or an index matrix are equivalent,
but they are both useful, especially when we perform operations on
index sets. For example, if I and J are lists then
I+J
is the concatenated list, and 2*I
is I repeated twice. If they are matrices, these operations are
interpreted as arithmetic operations.
For large index sets, indexing with integer matrices is also faster
than indexing with lists.
The following example illustrates one-argument indexing.
>>> from cvxopt.base import matrix >>> A = matrix(range(16), (4,4), 'd') >>> print A 0.0000e+00 4.0000e+00 8.0000e+00 1.2000e+01 1.0000e+00 5.0000e+00 9.0000e+00 1.3000e+01 2.0000e+00 6.0000e+00 1.0000e+01 1.4000e+01 3.0000e+00 7.0000e+00 1.1000e+01 1.5000e+01 >>> A[4] 4.0 >>> I = matrix([0, 5, 10, 15]) >>> print A[I] # the diagonal 0.0000e+00 5.0000e+00 1.0000e+01 1.5000e+01 >>> I = [0,2]; J = [1,3] >>> print A[2*I+J] # duplicate I and append J 0.0000e+00 2.0000e+00 0.0000e+00 2.0000e+00 1.0000e+00 3.0000e+00 >>> I = matrix([0, 2]); J = matrix([1, 3]) >>> print A[2*I+J] # multiply I by 2 and add J 1.0000e+00 7.0000e+00 >>> print A[4::4] # get every fourth element skipping the first four 4.0000e+00 8.0000e+00 1.2000e+01
In two-argument indexing the arguments can be any combinations of the four types listed above. The first argument indexes the rows of the matrix and the second argument indexes the columns. If both indices are scalars, then a scalar is returned. In all other cases, a matrix is returned. We continue the example.
>>> print A[:,1] 4.0000e+00 5.0000e+00 6.0000e+00 7.0000e+00 >>> J = matrix([0, 2]) >>> print A[J,J] 0.0000e+00 8.0000e+00 2.0000e+00 1.0000e+01 >>> print A[:2, -2:] 8.0000e+00 1.2000e+01 9.0000e+00 1.3000e+01
Expressions of the form A[I]
or
A[I,J]
can also appear on the lefthand side
of an assignment.
The righthand side must be a scalar (i.e., a number or a 1 by 1 dense
matrix), a sequence of numbers, or a dense or sparse matrix.
If the righthand side is a scalar, it is interpreted as a
matrix with identical entries and the dimensions of the lefthand side.
If the righthand side is a sequence of numbers (list, tuple,
array array, xrange object, ...) its values are
interpreted as the coefficients of the lefthand side in column-major
order. If the righthand side is a matrix (matrix or spmatrix), it must
have the same size as the lefthand side. Sparse matrices are
converted to dense in the assignment.
Indexed assignments are only allowed if they do not change the type of
the matrix. For example, if A is a matrix with type 'd'
, then
A[I] = B
is only permitted if B is
an integer, a float, or a matrix of type 'i'
or 'd'
.
If A is an integer matrix, then A[I] = B
is only permitted if B is an integer or an integer matrix.
The following example illlustrates indexed assignment.
>>> A = matrix(range(16), (4,4)) >>> A[::2,::2] = matrix([[-1, -2], [-3, -4]]) >>> print A -1 4 -3 12 1 5 9 13 -2 6 -4 14 3 7 11 15 >>> A[::5] += 1 >>> print A 0 4 -3 12 1 6 9 13 -2 6 -3 14 3 7 11 16 >>> A[0,:] = -1, 1, -1, 1 >>> print A -1 1 -1 1 1 6 9 13 -2 6 -3 14 3 7 11 16 >>> A[2:,2:] = xrange(4) >>> print A -1 1 -1 1 1 6 9 13 -2 6 0 2 3 7 1 3