R中零唯一向量的唯一排列

时间:2016-09-08 00:51:35

标签: r algorithm vector permutation

我的问题如下:

想象一下,我们有一个长度为(1,1,1,...,0,0)的向量n,其中k个为{}}。将此向量视为向量,并将某些变量L1实现到Ln。我需要计算的是

sum over all unique permutations of (1,1,1,...,0,0) of Function(L1,...,Ln)

我已经搜索了我的问题的解决方案,是的,有一些,只要n不是太大就可以工作。

只要n小于30,我的电脑就不会死,并且想法有效:

1)借助以下代码(found it here)创建所有唯一排列的data.frame

uniqueperm2 <- function(d) {
  dat <- factor(d)
  N <- length(dat)
  n <- tabulate(dat)
  ng <- length(n)
  if(ng==1) return(d)
  a <- N-c(0,cumsum(n))[-(ng+1)]
  foo <- lapply(1:ng, function(i) matrix(combn(a[i],n[i]),nrow=n[i]))
  out <- matrix(NA, nrow=N, ncol=prod(sapply(foo, ncol)))
  xxx <- c(0,cumsum(sapply(foo, nrow)))
  xxx <- cbind(xxx[-length(xxx)]+1, xxx[-1])
  miss <- matrix(1:N,ncol=1)
  for(i in seq_len(length(foo)-1)) {
    l1 <- foo[[i]]
    nn <- ncol(miss)
    miss <- matrix(rep(miss, ncol(l1)), nrow=nrow(miss))
    k <- (rep(0:(ncol(miss)-1), each=nrow(l1)))*nrow(miss) + 
               l1[,rep(1:ncol(l1), each=nn)]
    out[xxx[i,1]:xxx[i,2],] <- matrix(miss[k], ncol=ncol(miss))
    miss <- matrix(miss[-k], ncol=ncol(miss))
  }
  k <- length(foo)
  out[xxx[k,1]:xxx[k,2],] <- miss
  out <- out[rank(as.numeric(dat), ties="first"),]
  foo <- cbind(as.vector(out), as.vector(col(out)))
  out[foo] <- d
  t(out)
}

2)对此data.frame

的组件求和

可悲的是,我的问题n已达到100以上。对我来说好消息是我实际上不需要RAM中的整个data.frame。一种记住最后排列的算法,用它来评估Funktion(L1,...,Ln)并在循环中计算下一个排列等就足够了。任何帮助表示赞赏。

修改 Hack-R问了一个例子,这里是我得到的

    > d <- c()
    > d[1:25]=0
    > d[25:50]=1
    > d
     [1] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
> uniqueperm2(d)
Error: cannot allocate vector of size 905608.1 Gb
In addition: Warning messages:
1: In vector("list", count) :
  Reached total allocation of 8109Mb: see help(memory.size)
2: In vector("list", count) :
  Reached total allocation of 8109Mb: see help(memory.size)
3: In vector("list", count) :
  Reached total allocation of 8109Mb: see help(memory.size)
4: In vector("list", count) :
  Reached total allocation of 8109Mb: see help(memory.size)

2 个答案:

答案 0 :(得分:1)

这是走一条排列的唯一方法。我仍然认为有更好的方法,但还没有想到它。

此函数查看1和0的数组,并尽可能尝试将最右边的1向左移动。 (基本上将向量看作二进制数,并试图找到具有n位的下一个最大数字)

next_x <- function(x) {
    i <- tail(which(diff(x)==1),1)
    if (length(i)>0) {
        x[c(i, i+1)]<-c(1,0)
        x[(i+1):length(x)] <- sort(x[(i+1):length(x)])
    } else {
        stop("no more moves")
    }
    x
}

你从右边的x开始,你可以用

进行迭代
x <- c(0,0,0,0,1,1,1)
while(!all(x==c(1,1,1,0,0,0,0))) {
    x <- next_x(x)
    print(x)
}

答案 1 :(得分:0)

iterpc是另一种解决方案

k <- 5
n <- 10
library(iterpc)
it <- iterpc(c(k, n-k), ordered=TRUE)
while (!is.null(x <- getnext(it))){
  print(x)
}

PS:默认标签为1和2,而不是0和1。

简单基准测试表明,当next_xn=10

时,iterpc至少比k=5快2倍
Unit: milliseconds
   expr       min        lq      mean    median        uq       max neval
 next_x 11.663353 12.599623 13.665913 13.532414 14.411556 17.619208   100
 iterpc  4.987268  5.325663  5.939558  5.613265  6.572008  8.685916   100