pMatrix-class.RdThe pMatrix class is the class of permutation matrices,
stored as 1-based integer permutation vectors. A permutation
matrix is a square matrix whose rows and columns are all
standard unit vectors. It follows that permutation matrices are
a special case of index matrices (hence pMatrix
is defined as a direct subclass of indMatrix).
Multiplying a matrix on the left by a permutation matrix is equivalent to permuting its rows. Analogously, multiplying a matrix on the right by a permutation matrix is equivalent to permuting its columns. Indeed, such products are implemented in Matrix as indexing operations; see ‘Details’ below.
Objects can be created explicitly with calls of the form
new("pMatrix", ...), but they are more commonly created
by coercing 1-based integer index vectors, with calls of the
form as(., "pMatrix"); see ‘Methods’ below.
Class "indMatrix", directly.
%*%signature(x = "pMatrix", y = "Matrix")
and others listed by showMethods("%*%", classes = "pMatrix"):
matrix products implemented where appropriate as indexing operations.
coercesignature(from = "numeric", to = "pMatrix"):
supporting typical pMatrix construction from a vector
of positive integers, specifically a permutation of 1:n.
Row permutation is assumed.
signature(x = "pMatrix"):
the transpose, which is a pMatrix with identical
perm but opposite margin. Coincides with
the inverse, as permutation matrices are orthogonal.
signature(a = "pMatrix", b = "missing"):
the inverse permutation matrix, which is a pMatrix
with identical perm but opposite margin.
Coincides with the transpose, as permutation matrices are
orthogonal. See showMethods("solve", classes = "pMatrix")
for more signatures.
signature(x = "pMatrix", logarithm = "logical"):
always returning 1 or -1, as permutation matrices are orthogonal.
In fact, the result is exactly the sign of the permutation.
By definition, a permutation matrix is both a row index matrix
and a column index matrix. However, the perm slot of
a pMatrix cannot be used interchangeably as a row index
vector and column index vector. If margin=1, then
perm is a row index vector, and the corresponding column
index vector can be computed as invPerm(perm), i.e.,
by inverting the permutation. Analogously, if margin=2,
then perm and invPerm(perm) are column and row
index vectors, respectively.
Given an n-by-n row permutation matrix P
with perm slot p and a matrix M with
conformable dimensions, we have
| \(P M\) | = | P %*% M | = | M[p, ] |
| \(M P\) | = | M %*% P | = | M[, i(p)] |
| \(P'M\) | = | crossprod(P, M) | = | M[i(p), ] |
| \(MP'\) | = | tcrossprod(M, P) | = | M[, p] |
| \(P'P\) | = | crossprod(P) | = | Diagonal(n) |
| \(PP'\) | = | tcrossprod(P) | = | Diagonal(n) |
where i := invPerm.
(pm1 <- as(as.integer(c(2,3,1)), "pMatrix"))
#> 3 x 3 sparse Matrix of class "pMatrix"
#>
#> [1,] . | .
#> [2,] . . |
#> [3,] | . .
t(pm1) # is the same as
#> 3 x 3 sparse Matrix of class "pMatrix"
#>
#> [1,] . . |
#> [2,] | . .
#> [3,] . | .
solve(pm1)
#> 3 x 3 sparse Matrix of class "pMatrix"
#>
#> [1,] . . |
#> [2,] | . .
#> [3,] . | .
pm1 %*% t(pm1) # check that the transpose is the inverse
#> 3 x 3 sparse Matrix of class "pMatrix"
#>
#> [1,] | . .
#> [2,] . | .
#> [3,] . . |
stopifnot(all(diag(3) == as(pm1 %*% t(pm1), "matrix")),
is.logical(as(pm1, "matrix")))
set.seed(11)
## random permutation matrix :
(p10 <- as(sample(10),"pMatrix"))
#> 10 x 10 sparse Matrix of class "pMatrix"
#>
#> [1,] . . . . . . . . . |
#> [2,] . | . . . . . . . .
#> [3,] . . . . . . . | . .
#> [4,] | . . . . . . . . .
#> [5,] . . . . . . | . . .
#> [6,] . . . . | . . . . .
#> [7,] . . . | . . . . . .
#> [8,] . . . . . . . . | .
#> [9,] . . | . . . . . . .
#> [10,] . . . . . | . . . .
## Permute rows / columns of a numeric matrix :
(mm <- round(array(rnorm(3 * 3), c(3, 3)), 2))
#> [,1] [,2] [,3]
#> [1,] -0.15 -0.44 -0.38
#> [2,] 1.04 -0.05 -0.04
#> [3,] 0.19 0.47 -2.14
mm %*% pm1
#> 3 x 3 Matrix of class "dgeMatrix"
#> [,1] [,2] [,3]
#> [1,] -0.38 -0.15 -0.44
#> [2,] -0.04 1.04 -0.05
#> [3,] -2.14 0.19 0.47
pm1 %*% mm
#> 3 x 3 Matrix of class "dgeMatrix"
#> [,1] [,2] [,3]
#> [1,] 1.04 -0.05 -0.04
#> [2,] 0.19 0.47 -2.14
#> [3,] -0.15 -0.44 -0.38
try(as(as.integer(c(3,3,1)), "pMatrix"))# Error: not a permutation
#> Error in .perm2ind(from, check.p = 2L) :
#> 'perm' is not a permutation of seq_len(max(perm, 0))
as(pm1, "TsparseMatrix")
#> 3 x 3 sparse Matrix of class "ngTMatrix"
#>
#> [1,] . | .
#> [2,] . . |
#> [3,] | . .
p10[1:7, 1:4] # gives an "ngTMatrix" (most economic!)
#> 7 x 4 sparse Matrix of class "ngCMatrix"
#>
#> [1,] . . . .
#> [2,] . | . .
#> [3,] . . . .
#> [4,] | . . .
#> [5,] . . . .
#> [6,] . . . .
#> [7,] . . . |
## row-indexing of a <pMatrix> keeps it as an <indMatrix>:
p10[1:3, ]
#> 3 x 10 sparse Matrix of class "indMatrix"
#>
#> [1,] . . . . . . . . . |
#> [2,] . | . . . . . . . .
#> [3,] . . . . . . . | . .