Constructing Algebraic Matrices
There are several functions for creating matrices – in each case you need to indicate the ring to which the matrix elements belong, unless this is already unambiguously indicated by the ring to which the arguments belong. Here we present several of the basic functions for constructing matrices.
Why Julia matrices are not sufficient
Unfortunately, Julia's matrices cannot be used in our context due to two independent problems:
- In empty matrices (0 rows or columns) all that is known about a Julia matrix is the type of its entries,
however for advanced algebraic types, this information is insufficient to create elements, hence zero(T) or friends cannot work.
- Many Julia functions (e.g.
det) assume that all types used embed into the real or complex numbers. For
instance, in Julia det(ones(Int, (1,1))) == 1.0, so the fact that the determinant is exactly the integer 1 is lost. Furthermore, more general rings cannot be embedded into the reals at all.
For this reason, the matrix constructors below must accept (or infer) the ring in which all entries of the matrix reside.
Constructing matrices from entries
AbstractAlgebra.matrix — Method
matrix(R::NCRing, arr::AbstractMatrix{T}) where {T}Return the matrix over the ring R with entries as in the Julia AbstractMatrix arr. All entries of arr must be coercible into R.
Examples
julia> matrix(GF(3), [1 2 ; 3 4])
[1 2]
[0 1]
julia> matrix(ZZ, BigInt[3 1 2; 2 0 1])
[3 1 2]
[2 0 1]AbstractAlgebra.matrix — Method
matrix(R::NCRing, r::Int, c::Int, arr::AbstractVecOrMat{T}) where {T}Return the r by c matrix over the ring R from the entries of arr.
If arr is a vector, its entries are read row-wise, so the $(i, j)$ entry is given by arr[c*(i - 1) + j]. All entries must be coercible into R.
If arr is a matrix, this is equivalent to matrix(R, arr).
Examples
julia> matrix(ZZ, 3, 2, BigInt[3, 1, 2, 2, 0, 1])
[3 1]
[2 2]
[0 1]Several other signatures are supported:
matrix(arr::AbstractMatrix{T}) where {T<:NCRingElement}
matrix(arr::AbstractVector{T}) where {T<:NCRingElement}
matrix(arr::AbstractVector{<:AbstractVector{T}}) where {T<:NCRingElement}Nested vectors can also be used to construct matrices over a specified base ring:
matrix(R::NCRing, arr::AbstractVector{<:AbstractVector})Constructing matrices from existing matrices
Changing the base ring
Matrices can be converted to another base ring using change_base_ring.
AbstractAlgebra.change_base_ring — Method
change_base_ring(R::NCRing, M::MatrixElem{T}) where {T <: NCRingElement}Return a new matrix over R by coercing each entry of M into R.
The input matrix is not modified.
Examples
julia> M = matrix(ZZ, [1 2; 3 4])
[1 2]
[3 4]
julia> N = change_base_ring(QQ, M)
[1//1 2//1]
[3//1 4//1]
julia> base_ring(N)
RationalsThe same conversion can also be performed using the following constructors:
matrix(R::NCRing, arr::MatElem)
matrix(R::NCRing, arr::MatRingElem)Copying
An independent copy of an existing matrix can be created.
matrix(mat::MatElem{T}) where {T<:NCRingElement}Zero matrices
Base.zero — Method
zero(x::MatElem{T}, R::NCRing, r::Int, c::Int) where {T <: NCRingElement}
zero(x::MatElem{T}, r::Int, c::Int) where {T <: NCRingElement}
zero(x::MatElem{T}, R::NCRing) where T <: {NCRingElement}
zero(x::MatElem{T}) where {T <: NCRingElement}Create a zero matrix with the same implementation type as the given matrix x.
By default, the base ring and dimensions are inherited from x, but they can also be specified explicitly.
Identity matrices
AbstractAlgebra.identity_matrix — Method
identity_matrix(M::MatElem{T}) where {T <: NCRingElement}Return the identity matrix with the same base ring and dimensions as the given abstract matrix M. The matrix M must be square.
This is an alias for one(M).
Examples
julia> M = matrix(ZZ, [1 2; 3 4])
[1 2]
[3 4]
julia> identity_matrix(M)
[1 0]
[0 1]AbstractAlgebra.identity_matrix — Method
identity_matrix(M::MatElem{T}, n::Int) where {T <: NCRingElement}Return the identity $n \times n$ matrix over the same base ring as the given abstract matrix M.
Uninitialized matrices
Base.similar — Method
similar(x::MatElem{T}, R::NCRing, r::Int, c::Int) where T <: NCRingElement
similar(x::MatElem{T}, R::NCRing) where T <: NCRingElement
similar(x::MatElem{T}, r::Int, c::Int) where T <: NCRingElement
similar(x::MatElem{T}) where T <: NCRingElementCreate an uninitialized matrix with the same implementation type as x.
By default, the base ring and dimensions are inherited from x, but they can also be specified explicitly.
This method is useful when implementing algorithms which create new matrices whose entries will be filled in later.
Despite the name, similar is not related to similarity transformations or similar matrices in the mathematical sense.
Examples
julia> M = matrix(ZZ, [1 2 3; 4 5 6])
[1 2 3]
[4 5 6]
julia> similar(M)
[#undef #undef #undef]
[#undef #undef #undef]
julia> similar(M, 2, 2)
[#undef #undef]
[#undef #undef]Concatenation
Matrices can be constructed from existing matrices by concatenating them horizontally or vertically.
Base.hcat — Method
Base.hcat(A::MatElem...)Return the horizontal concatenation of the matrices in $A$.
All component matrices must have the same base ring and the same number of rows.
Examples
julia> M = matrix(ZZ, BigInt[1 2 3; 2 3 4; 3 4 5])
[1 2 3]
[2 3 4]
[3 4 5]
julia> N = matrix(ZZ, BigInt[1 0 1; 0 1 0; 1 0 1])
[1 0 1]
[0 1 0]
[1 0 1]
julia> hcat(M, N)
[1 2 3 1 0 1]
[2 3 4 0 1 0]
[3 4 5 1 0 1]Base.vcat — Method
Base.vcat(A::MatElem...)Return the vertical concatenation of the matrices in $A$.
All component matrices must have the same base ring and the same number of columns.
Examples
julia> M = matrix(ZZ, BigInt[1 2 3; 2 3 4; 3 4 5])
[1 2 3]
[2 3 4]
[3 4 5]
julia> N = matrix(ZZ, BigInt[1 0 1; 0 1 0; 1 0 1])
[1 0 1]
[0 1 0]
[1 0 1]
julia> vcat(M, N)
[1 2 3]
[2 3 4]
[3 4 5]
[1 0 1]
[0 1 0]
[1 0 1]Submatrices and views
Submatrices can be constructed using Julia indexing syntax. By default, this creates a new matrix containing the selected entries.
To avoid copying entries, one can instead construct a view using Julia's @view syntax. Views are particularly useful for working with small regions of large matrices, as modifications to a view also modify the original matrix.
Examples
julia> M = matrix(ZZ, [1 2 3; 2 3 4; 3 4 5])
[1 2 3]
[2 3 4]
[3 4 5]
julia> M[1:2, 1:2]
[1 2]
[2 3]
julia> N = @view M[1:2, 1:2]
[1 2]
[2 3]
julia> N[1, 1] = 10
10
julia> M
[10 2 3]
[ 2 3 4]
[ 3 4 5]Special constructors
The zero matrix
AbstractAlgebra.zero_matrix — Method
zero_matrix(R::NCRing, r::Int, c::Int)Return the $r \times c$ matrix over the ring R whose entries are all zero.
Examples
julia> P = zero_matrix(ZZ, 3, 2)
[0 0]
[0 0]
[0 0]The ones matrix
AbstractAlgebra.ones_matrix — Method
ones_matrix(R::NCRing, r::Int, c::Int)Return the $r \times c$ matrix over the ring R whose entries are all equal to the multiplicative identity of R.
Examples
julia> ones_matrix(ZZ, 3, 2)
[1 1]
[1 1]
[1 1]The identity matrix
AbstractAlgebra.identity_matrix — Method
identity_matrix(R::NCRing, n::Int)Return the $n \times n$ identity matrix over the ring R.
Examples
julia> identity_matrix(ZZ, 2)
[1 0]
[0 1]Scalar matrices
AbstractAlgebra.scalar_matrix — Method
scalar_matrix(R::NCRing, n::Int, a::NCRingElement)Return the $n \times n$ diagonal matrix over the ring R whose diagonal entries are all equal to the ring element a of R.
Examples
julia> scalar_matrix(QQ, 3, 1//2)
[1//2 0//1 0//1]
[0//1 1//2 0//1]
[0//1 0//1 1//2]AbstractAlgebra.scalar_matrix — Method
scalar_matrix(n::Int, a::NCRingElement)Return the $n \times n$ diagonal matrix over parent(a) whose diagonal entries are all equal to the ring element a.
Examples
julia> scalar_matrix(3, ZZ(5))
[5 0 0]
[0 5 0]
[0 0 5]Diagonal matrices
AbstractAlgebra.diagonal_matrix — Function
diagonal_matrix(x::NCRingElement, m::Int, n::Int = m)Return the $m \times n$ matrix over the ring parent(x) with x along the main diagonal and zeros elsewhere. If n is omitted, return an $m \times m$ matrix.
Examples
julia> diagonal_matrix(ZZ(2), 2, 3)
[2 0 0]
[0 2 0]
julia> diagonal_matrix(QQ(-1), 3)
[-1//1 0//1 0//1]
[ 0//1 -1//1 0//1]
[ 0//1 0//1 -1//1]AbstractAlgebra.diagonal_matrix — Method
diagonal_matrix(R::NCRing, entries::AbstractVector{<:NCRingElement})
diagonal_matrix(entries::AbstractVector{<:NCRingElement})
diagonal_matrix(x::T, xs::T...) where {T<:NCRingElement}Return a diagonal matrix with the given entries on the main diagonal.
For the vector forms, the diagonal entries are the elements of entries. For the vararg form, the diagonal entries are x, xs....
If the ring R is given, the entries are coerced into R. Otherwise, the base ring is inferred from the entries.
Examples
julia> diagonal_matrix(ZZ(1), ZZ(2))
[1 0]
[0 2]
julia> diagonal_matrix(ZZ, [5, 6])
[5 0]
[0 6]
julia> diagonal_matrix([ZZ(3), ZZ(4)])
[3 0]
[0 4]Diagonal matrices can also be constructed from matrix blocks. This is an alias for block_diagonal_matrix.
AbstractAlgebra.diagonal_matrix — Method
diagonal_matrix(V::Vector{T}) where {T <: MatElem}
diagonal_matrix(R::NCRing, V::Vector{<:MatElem})
diagonal_matrix(x::T, xs::T...) where {T <: MatElem}Return the block diagonal matrix whose diagonal blocks are the given matrices.
For the vector forms, the diagonal blocks are the elements of V. For the vararg form, the diagonal blocks are x, xs....
If the ring R is given, the entries of the blocks are coerced into R.
These constructors use the corresponding block_diagonal_matrix functionality.
Examples
julia> A = matrix(ZZ, [1 2; 3 4])
[1 2]
[3 4]
julia> B = matrix(ZZ, [5 6])
[5 6]
julia> diagonal_matrix([A, B])
[1 2 0 0]
[3 4 0 0]
[0 0 5 6]
julia> diagonal_matrix(QQ, [A, B])
[1//1 2//1 0//1 0//1]
[3//1 4//1 0//1 0//1]
[0//1 0//1 5//1 6//1]
julia> diagonal_matrix(B, A)
[5 6 0 0]
[0 0 1 2]
[0 0 3 4]Block diagonal matrix constructors
AbstractAlgebra.block_diagonal_matrix — Method
block_diagonal_matrix(V::Vector{<:MatElem{T}}) where {T <: NCRingElement}Return the block diagonal matrix whose diagonal blocks are the matrices in V.
The vector V must be non-empty, since otherwise the base ring cannot be inferred.
Examples
julia> M = matrix(ZZ, [1 2; 3 4])
[1 2]
[3 4]
julia> N = matrix(ZZ, [4 5 6; 7 8 9])
[4 5 6]
[7 8 9]
julia> block_diagonal_matrix([M, N])
[1 2 0 0 0]
[3 4 0 0 0]
[0 0 4 5 6]
[0 0 7 8 9]AbstractAlgebra.block_diagonal_matrix — Method
block_diagonal_matrix(R::NCRing, V::Vector{<:Matrix{T}}) where {T <: NCRingElement}Return the block diagonal matrix over the ring R whose diagonal blocks are the matrices in V.
The entries of the blocks are coerced into R. If V is empty, the $0 \times 0$ zero matrix over R is returned.
Examples
julia> block_diagonal_matrix(ZZ, [[1 2; 3 4], [4 5 6; 7 8 9]])
[1 2 0 0 0]
[3 4 0 0 0]
[0 0 4 5 6]
[0 0 7 8 9]Triangular matrices
AbstractAlgebra.lower_triangular_matrix — Method
lower_triangular_matrix(L::AbstractVector{T}) where {T <: NCRingElement}Return the $n \times n$ lower triangular matrix whose entries on and below the main diagonal are given by the elements of L. The entries are filled row by row.
The size $n$ is determined by the condition that L has length $n(n + 1)/2$. An exception is thrown if no such integer $n$ exists.
Examples
julia> lower_triangular_matrix([1, 2, 3])
[1 0]
[2 3]AbstractAlgebra.upper_triangular_matrix — Method
upper_triangular_matrix(L::AbstractVector{T}) where {T <: NCRingElement}Return the $n \times n$ upper triangular matrix whose entries on and below the main diagonal are given by the elements of L. The entries are filled row by row.
The size $n$ is determined by the condition that L has length $n(n + 1)/2$. An exception is thrown if no such integer $n$ exists.
Examples
julia> upper_triangular_matrix([1, 2, 3])
[1 2]
[0 3]AbstractAlgebra.strictly_lower_triangular_matrix — Method
strictly_lower_triangular_matrix(L::AbstractVector{T}) where {T <: NCRingElement}Return the $n \times n$ strictly lower triangular matrix whose entries below the main diagonal are given by the elements of L. The entries are filled row by row.
The size $n$ is determined by the condition that L has length $n(n - 1)/2$. An exception is thrown if no such integer $n$ exists.
Examples
julia> strictly_lower_triangular_matrix([1, 2, 3])
[0 0 0]
[1 0 0]
[2 3 0]AbstractAlgebra.strictly_upper_triangular_matrix — Method
strictly_upper_triangular_matrix(L::AbstractVector{T}) where {T <: NCRingElement}Return the $n \times n$ strictly upper triangular matrix whose entries above the main diagonal are given by the elements of L. The entries are filled row by row.
The size $n$ is determined by the condition that L has length $n(n - 1)/2$. An exception is thrown if no such integer $n$ exists.
Examples
julia> strictly_upper_triangular_matrix([1, 2, 3])
[0 1 2]
[0 0 3]
[0 0 0]