Matrices

Matrices are represented in &GAP; by lists of row vectors (see ) (for future changes to this policy see Chapter ). The vectors must all have the same length, and their elements must lie in a common ring. However, since checking rectangularness can be expensive functions and methods of operations for matrices often will not give an error message for non-rectangular lists of lists –in such cases the result is undefined.

Because matrices are just a special case of lists, all operations and functions for lists are applicable to matrices also (see chapter ). This especially includes accessing elements of a matrix (see ), changing elements of a matrix (see ), and comparing matrices (see ).

Note that, since a matrix is a list of lists, the behaviour of for matrices is just a special case of for lists (see ); called with an immutable matrix mat, returns a mutable matrix whose rows are identical to the rows of mat. In particular the rows are still immutable. To get a matrix whose rows are mutable, one can use List( mat, ShallowCopy ).

InfoMatrix (Info Class)
<#Include Label="InfoMatrix">

Categories of Matrices
<#Include Label="IsMatrix"> <#Include Label="IsOrdinaryMatrix"> <#Include Label="IsLieMatrix">

Operators for Matrices

The rules for arithmetic operations involving matrices are in fact special cases of those for the arithmetic of lists, given in Section and the following sections, here we reiterate that definition, in the language of vectors and matrices.

Note that the additive behaviour sketched below is defined only for lists in the category , and the multiplicative behaviour is defined only for lists in the category (see ).

addition
mat1 + mat2

returns the sum of the two matrices mat1 and mat2, Probably the most usual situation is that mat1 and mat2 have the same dimensions and are defined over a common field; in this case the sum is a new matrix over the same field where each entry is the sum of the corresponding entries of the matrices.

In more general situations, the sum of two matrices need not be a matrix, for example adding an integer matrix mat1 and a matrix mat2 over a finite field yields the table of pointwise sums, which will be a mixture of finite field elements and integers if mat1 has bigger dimensions than mat2.

addition
scalar + mat

addition
mat + scalar

returns the sum of the scalar scalar and the matrix mat. Probably the most usual situation is that the entries of mat lie in a common field with scalar; in this case the sum is a new matrix over the same field where each entry is the sum of the scalar and the corresponding entry of the matrix.

More general situations are for example the sum of an integer scalar and a matrix over a finite field, or the sum of a finite field element and an integer matrix.

subtraction
mat1 - mat2

subtraction
scalar - mat

subtraction
mat - scalar

Subtracting a matrix or scalar is defined as adding its additive inverse, so the statements for the addition hold likewise.

multiplication
scalar * mat

multiplication
mat * scalar

returns the product of the scalar scalar and the matrix mat. Probably the most usual situation is that the elements of mat lie in a common field with scalar; in this case the product is a new matrix over the same field where each entry is the product of the scalar and the corresponding entry of the matrix.

More general situations are for example the product of an integer scalar and a matrix over a finite field, or the product of a finite field element and an integer matrix.

multiplication
vec * mat

returns the product of the row vector vec and the matrix mat. Probably the most usual situation is that vec and mat have the same lengths and are defined over a common field, and that all rows of mat have the same length m, say; in this case the product is a new row vector of length m over the same field which is the sum of the scalar multiples of the rows of mat with the corresponding entries of vec.

More general situations are for example the product of an integer vector and a matrix over a finite field, or the product of a vector over a finite field and an integer matrix.

multiplication
mat * vec

returns the product of the matrix mat and the row vector vec. (This is the standard product of a matrix with a column vector.) Probably the most usual situation is that the length of vec and of all rows of mat are equal, and that the elements of mat and vec lie in a common field; in this case the product is a new row vector of the same length as mat and over the same field which is the sum of the scalar multiples of the columns of mat with the corresponding entries of vec.

More general situations are for example the product of an integer matrix and a vector over a finite field, or the product of a matrix over a finite field and an integer vector.

multiplication
mat1 * mat2

This form evaluates to the (Cauchy) product of the two matrices mat1 and mat2. Probably the most usual situation is that the number of columns of mat1 equals the number of rows of mat2, and that the elements of mat and vec lie in a common field; if mat1 is a matrix with m rows and n columns, say, and mat2 is a matrix with n rows and o columns, the result is a new matrix with m rows and o columns. The element in row i at position j of the product is the sum of mat1[i][l] * mat2[l][j], with l running from 1 to n.

inverse
Inverse( mat )

returns the inverse of the matrix mat, which must be an invertible square matrix. If mat is not invertible then fail is returned.

quotient
mat1 / mat2

quotient
scalar / mat

quotient
mat / scalar

quotient
vec / mat

In general, left / right is defined as left * right^-1. Thus in the above forms the right operand must always be invertible.

power
mat ^ int

conjugate
mat1 ^ mat2

image
vec ^ mat

Powering a square matrix mat by an integer int yields the int-th power of mat; if int is negative then mat must be invertible, if int is 0 then the result is the identity matrix One( mat ), even if mat is not invertible.

Powering a square matrix mat1 by an invertible square matrix mat2 of the same dimensions yields the conjugate of mat1 by mat2, i.e., the matrix mat2^-1 * mat1 * mat2.

Powering a row vector vec by a matrix mat is in every respect equivalent to vec * mat. This operations reflects the fact that matrices act naturally on row vectors by multiplication from the right, and that the powering operator is &GAP;'s standard for group actions.

matrices
Comm( mat1, mat2 )

returns the commutator of the square invertible matrices mat1 and mat2 of the same dimensions and over a common field, which is the matrix mat1^-1 * mat2^-1 * mat1 * mat2.

The following cases are still special cases of the general list arithmetic defined in .

addition
scalar + matlist

addition
matlist + scalar

subtraction
scalar - matlist

subtraction
matlist - scalar

multiplication
scalar * matlist

multiplication
matlist * scalar

quotient
matlist / scalar

A scalar scalar may also be added, subtracted, multiplied with, or divided into a list matlist of matrices. The result is a new list of matrices where each matrix is the result of performing the operation with the corresponding matrix in matlist.

multiplication
mat * matlist

multiplication
matlist * mat

A matrix mat may also be multiplied with a list matlist of matrices. The result is a new list of matrices, where each entry is the product of mat and the corresponding entry in matlist.

quotient
matlist / mat

Dividing a list matlist of matrices by an invertible matrix mat evaluates to matlist * mat^-1.

multiplication
vec * matlist

returns the product of the vector vec and the list of matrices mat. The lengths l of vec and matlist must be equal. All matrices in matlist must have the same dimensions. The elements of vec and the elements of the matrices in matlist must lie in a common ring. The product is the sum over vec[i] * matlist[i] with i running from 1 to l.

For the mutability of results of arithmetic operations, see .

Properties and Attributes of Matrices
<#Include Label="DimensionsMat"> <#Include Label="DefaultFieldOfMatrix"> <#Include Label="TraceMat"> <#Include Label="DeterminantMat"> <#Include Label="DeterminantMatDestructive"> <#Include Label="DeterminantMatDivFree"> <#Include Label="IsMonomialMatrix"> <#Include Label="IsDiagonalMat"> <#Include Label="IsUpperTriangularMat"> <#Include Label="IsLowerTriangularMat">

Matrix Constructions
<#Include Label="IdentityMat"> <#Include Label="NullMat"> <#Include Label="EmptyMatrix"> <#Include Label="DiagonalMat"> <#Include Label="PermutationMat"> <#Include Label="TransposedMatImmutable"> <#Include Label="TransposedMatDestructive"> <#Include Label="KroneckerProduct"> <#Include Label="ReflectionMat"> <#Include Label="PrintArray">

Random Matrices
<#Include Label="RandomMat"> <#Include Label="RandomInvertibleMat"> <#Include Label="RandomUnimodularMat">

Matrices Representing Linear Equations and the Gaussian Algorithm
Gaussian algorithm
<#Include Label="RankMat"> <#Include Label="TriangulizedMat"> <#Include Label="TriangulizeMat"> <#Include Label="NullspaceMat"> <#Include Label="NullspaceMatDestructive"> <#Include Label="SolutionMat"> <#Include Label="SolutionMatDestructive"> <#Include Label="BaseFixedSpace">

Eigenvectors and eigenvalues
<#Include Label="GeneralisedEigenvalues"> <#Include Label="GeneralisedEigenspaces"> <#Include Label="Eigenvalues"> <#Include Label="Eigenspaces"> <#Include Label="Eigenvectors">

Elementary Divisors

See also chapter .

<#Include Label="ElementaryDivisorsMat"> <#Include Label="ElementaryDivisorsTransformationsMat"> <#Include Label="DiagonalizeMat">

Echelonized Matrices
<#Include Label="SemiEchelonMat"> <#Include Label="SemiEchelonMatDestructive"> <#Include Label="SemiEchelonMatTransformation"> <#Include Label="SemiEchelonMats"> <#Include Label="SemiEchelonMatsDestructive">

Matrices as Basis of a Row Space

See also chapter

<#Include Label="BaseMat"> <#Include Label="BaseMatDestructive"> <#Include Label="BaseOrthogonalSpaceMat"> <#Include Label="SumIntersectionMat"> <#Include Label="BaseSteinitzVectors">

Triangular Matrices
<#Include Label="DiagonalOfMat"> <#Include Label="UpperSubdiagonal"> <#Include Label="DepthOfUpperTriangularMatrix">

Matrices as Linear Mappings
<#Include Label="CharacteristicPolynomial"> <#Include Label="JordanDecomposition"> <#Include Label="BlownUpMat"> <#Include Label="BlownUpVector"> <#Include Label="CompanionMat">

Matrices over Finite Fields

Just as for row vectors, (see section ), &GAP; has a special representation for matrices over small finite fields.

To be eligible to be represented in this way, each row of a matrix must be able to be represented as a compact row vector of the same length over the same finite field.

gap> v := Z(2)*[1,0,0,1,1]; [ Z(2)^0, 0*Z(2), 0*Z(2), Z(2)^0, Z(2)^0 ] gap> ConvertToVectorRep(v,2); 2 gap> v; <a GF2 vector of length 5> gap> m := [v];; ConvertToMatrixRep(m,GF(2));; m; <a 1x5 matrix over GF2> gap> m := [v,v];; ConvertToMatrixRep(m,GF(2));; m; <a 2x5 matrix over GF2> gap> m := [v,v,v];; ConvertToMatrixRep(m,GF(2));; m; <a 3x5 matrix over GF2> gap> v := Z(3)*[1..8]; [ Z(3), Z(3)^0, 0*Z(3), Z(3), Z(3)^0, 0*Z(3), Z(3), Z(3)^0 ] gap> ConvertToVectorRep(v); 3 gap> m := [v];; ConvertToMatrixRep(m,GF(3));; m; [ [ Z(3), Z(3)^0, 0*Z(3), Z(3), Z(3)^0, 0*Z(3), Z(3), Z(3)^0 ] ] gap> RepresentationsOfObject(m); [ "IsPositionalObjectRep", "Is8BitMatrixRep" ] gap> m := [v,v,v,v];; ConvertToMatrixRep(m,GF(3));; m; < mutable compressed matrix 4x8 over GF(3) >

All compressed matrices over GF(2) are viewed as <a nxm matrix over GF2>, while over fields GF(q) for q between 3 and 256, matrices with 25 or more entries are viewed in this way, and smaller ones as lists of lists.

Matrices can be converted to this special representation via the following functions.

Note that the main advantage of this special representation of matrices is in low dimensions, where various overheads can be reduced. In higher dimensions, a list of compressed vectors will be almost as fast. Note also that list access and assignment will be somewhat slower for compressed matrices than for plain lists.

In order to form a row of a compressed matrix a vector must accept certain restrictions. Specifically, it cannot change its length or change the field over which it is compressed. The main consequences of this are: that only elements of the appropriate field can be assigned to entries of the vector, and only to positions between 1 and the original length; that the vector cannot be shared between two matrices compressed over different fields.

This is enforced by the filter IsLockedRepresentationVector. When a vector becomes part of a compressed matrix, this filter is set for it. Assignment, , and are all prevented from altering a vector with this filter.

gap> v := [Z(2),Z(2)];; ConvertToVectorRep(v,GF(2));; v; <a GF2 vector of length 2> gap> m := [v,v]; [ <a GF2 vector of length 2>, <a GF2 vector of length 2> ] gap> ConvertToMatrixRep(m,GF(2)); 2 gap> m2 := [m[1], [Z(4),Z(4)]]; # now try and mix in some GF(4) [ <a GF2 vector of length 2>, [ Z(2^2), Z(2^2) ] ] gap> ConvertToMatrixRep(m2); # but m2[1] is locked #I ConvertToVectorRep: locked vector not converted to different field fail gap> m2 := [ShallowCopy(m[1]), [Z(4),Z(4)]]; # a fresh copy of row 1 [ <a GF2 vector of length 2>, [ Z(2^2), Z(2^2) ] ] gap> ConvertToMatrixRep(m2); # now it works 4 gap> m2; [ [ Z(2)^0, Z(2)^0 ], [ Z(2^2), Z(2^2) ] ] gap> RepresentationsOfObject(m2); [ "IsPositionalObjectRep", "Is8BitMatrixRep" ]

Arithmetic operations (see and the following sections) preserve the compression status of matrices in the sense that if all arguments are compressed matrices written over the same field and the result is a matrix then also the result is a compressed matrix written over this field.

There are also two operations that are only available for matrices written over finite fields.

<#Include Label="ImmutableMatrix"> <#Include Label="ConvertToMatrixRep"> <#Include Label="ProjectiveOrder"> <#Include Label="SimultaneousEigenvalues">

Inverse and Nullspace of an Integer Matrix Modulo an Ideal

The following two operations deal with matrices over a ring, but only care about the residues of their entries modulo some ring element. In the case of the integers and a prime number p, say, this is effectively computation in a matrix over the prime field in characteristic p.

<#Include Label="InverseMatMod"> <#Include Label="NullspaceModQ">

Special Multiplication Algorithms for Matrices over GF(2)

When multiplying two compressed matrices M and N over GF(2) of dimensions a \times b and b \times c, say, where a, b and c are all greater than or equal to 128, &GAP; by default uses a more sophisticated matrix multiplication algorithm, in which linear combinations of groups of 8 rows of M are remembered and re-used in constructing various rows of the product. This is called level 8 grease. To optimise memory access patterns, these combinations are stored for (b+255)/256 sets of 8 rows at once. This number is called the blocking level.

These levels of grease and blocking are found experimentally to give good performance across a range of processors and matrix sizes, but other levels may do even better in some cases. You can control the levels exactly using the functions below.

We plan to include greased blocked matrix multiplication for other finite fields, and greased blocked algorithms for inversion and other matrix operations in a future release.

This function performs the standard unblocked and ungreased matrix multiplication for matrices of any size.

This function computes the product of m1 and m2, which must be compressed matrices over GF(2) of compatible dimensions, using level g grease and level b blocking.
Block Matrices
<#Include Label="[1]{matblock}"> <#Include Label="AsBlockMatrix"> <#Include Label="BlockMatrix"> <#Include Label="MatrixByBlockMatrix">