The R Project SVN R-packages

Rev

Rev 4817 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

#### Permutation Matrices -- Coercion and Methods

## The typical   'constructor' : coerce from  'index'
setAs("integer", "pMatrix",
      function(from) {
          n <- length(from)
          nn <- names(from)
          new("pMatrix", Dim = rep.int(n, 2), Dimnames = list(nn,nn),
              perm = from)
      })

setAs("numeric", "pMatrix",
      function(from)
      if(all(from == (i <- as.integer(from)))) as(i, "pMatrix")
      else stop("coercion to 'pMatrix' only works from integer numeric"))

setAs("pMatrix", "matrix",
      function(from) {
      fp <- from@perm
      r <- idiag(n = length(fp))[fp,]
      if(.has.DN(from)) dimnames(r) <- from@Dimnames
      r
      })

## coerce to 0/1 sparse matrix, i.e. sparse pattern
setAs("pMatrix", "ngTMatrix",
      function(from) {
          d <- from@Dim
      new("ngTMatrix", i = seq_len(d[1]) - 1L, j = from@perm - 1L,
              Dim = d, Dimnames = from@Dimnames)
      })

setAs("pMatrix", "TsparseMatrix", function(from) as(from, "ngTMatrix"))
setAs("pMatrix", "nMatrix",   function(from) as(from, "ngTMatrix"))
setAs("pMatrix", "lMatrix", function(from) as(as(from, "nMatrix"), "lMatrix"))
setAs("pMatrix", "dMatrix", function(from) as(as(from, "nMatrix"), "dMatrix"))

setAs("pMatrix", "CsparseMatrix",
      function(from) as(as(from, "ngTMatrix"), "CsparseMatrix"))

setAs("nMatrix", "pMatrix",
      function(from) {
      from <- as(as(from, "TsparseMatrix"), "ngTMatrix")
      n <- (d <- from@Dim)[1]
      if(n != d[2]) stop("not a square matrix")
      if(length(i <- from@i) != n)
          stop("the number of non-zero entries differs from nrow(.)")
      if((need.sort <- is.unsorted(i))) {
          ii <- sort.list(i)
          i <- i[ii]
      }
      if(n >= 1 && !identical(i, 0:(n - 1)))
          stop("must have exactly one non-zero entry per row")
      new("pMatrix", ## validity checking checks the 'perm' slot:
          perm = 1L + if(need.sort) from@j[ii] else from@j,
          Dim = d, Dimnames = from@Dimnames)
      })

setAs("matrix", "pMatrix", function(from) as(as(from, "nMatrix"), "pMatrix"))


setMethod("solve", signature(a = "pMatrix", b = "missing"),
      function(a, b) {
          ap <- a@perm
          ap[ap] <- seq_along(ap)
              a@perm <- ap
              a@Dimnames <- a@Dimnames[2:1]
              a
          })

setMethod("solve", signature(a = "Matrix", b = "pMatrix"),
      function(a, b) {
          ## Or alternatively  solve(a, as(b, "CsparseMatrix"))
          i <- b@perm
          i[i] <- seq_along(i)
          solve(a)[, i]
      })

## t(pM) is == the inverse  pM^(-1):
setMethod("t", signature(x = "pMatrix"), function(x) solve(x))

.m.mult.pMat <- function(x, y) {
    mmultCheck(x,y)
    i <- y@perm
    i[i] <- seq_along(i)
    x[, i]
}

setMethod("%*%", signature(x = "matrix", y = "pMatrix"),
      .m.mult.pMat, valueClass = "matrix")
setMethod("%*%", signature(x = "Matrix", y = "pMatrix"),
      .m.mult.pMat)

setMethod("%*%", signature(x = "pMatrix", y = "matrix"),
      function(x, y) { mmultCheck(x,y); y[x@perm ,]}, valueClass = "matrix")
setMethod("%*%", signature(x = "pMatrix", y = "Matrix"),
      function(x, y) { mmultCheck(x,y); y[x@perm ,]})

setMethod("%*%", signature(x = "pMatrix", y = "pMatrix"),
      function(x, y) {
              stopifnot(identical(d <- x@Dim, y@Dim))
              n <- d[1]
              ## FIXME: dimnames dealing: as with S3 matrix's  %*%
              x@perm <- x@perm[y@perm]
              x
          })

### FIXME: crossprod / tcrossprod currently work
### -----  via  t(.) and later  [ i, ] -- separate methods will be faster!

setMethod("crossprod", signature(x = "pMatrix", y = "missing"),
          function(x, y=NULL) Diagonal(nrow(x)))
setMethod("tcrossprod", signature(x = "pMatrix", y = "missing"),
          function(x, y=NULL) Diagonal(nrow(x)))


.pMat.nosense <- function (x, i, j, ..., value)
    stop('partially replacing "pMatrix" entries is not sensible')
setReplaceMethod("[", signature(x = "pMatrix", i = "index"), .pMat.nosense)
setReplaceMethod("[", signature(x = "pMatrix", i = "missing", j = "index"),
         .pMat.nosense) ##   explicit  ^^^^^^^^^^^^ for disambiguation