更改二进制矩阵中的值

时间:2017-06-07 07:26:08

标签: r

考虑8乘6的二进制矩阵M

M <- matrix(c(0,0,1,1,0,0,1,1,
          0,1,1,0,0,1,1,0,
          0,0,0,0,1,1,1,1,
          0,1,0,1,1,0,1,0,
          0,0,1,1,1,1,0,0,
          0,1,1,0,1,0,0,1),nrow = 8,ncol = 6)

以下是M

      [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    0    0    0    0    0    0
[2,]    0    1    0    1    0    1
[3,]    1    1    0    0    1    1
[4,]    1    0    0    1    1    0
[5,]    0    0    1    1    1    1
[6,]    0    1    1    0    1    0
[7,]    1    1    1    1    0    0
[8,]    1    0    1    0    0    1

以下矩阵包含矩阵1

M的列索引
    [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    3    2    5    2    3    2
[2,]    4    3    6    4    4    3
[3,]    7    6    7    5    5    5
[4,]    8    7    8    7    6    8

让我们来表示

ind <- matrix(c(3,4,7,8,
                2,3,6,7,
                5,6,7,8,
                2,4,5,7,
                3,4,5,6,
                2,3,5,8),nrow = 4, ncol=6)

我试图在1的每一列中将0的单个位置更改为M

例如,每列中1 s索引的一种可能性是(4,2,5,4,3,2)i.e. 4th Column1的位置,2nd位置Column2,Column3的5th位置,依此类推。设N为结果矩阵。这将生成以下矩阵N

N <- matrix(c(0,0,1,0,0,0,1,1,
          0,0,1,0,0,1,1,0,
          0,0,0,0,0,1,1,1,
          0,1,0,0,1,0,1,0,
          0,0,0,1,1,1,0,0,
          0,0,1,0,1,0,0,1),nrow = 8,ncol = 6)

这是N

    [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    0    0    0    0    0    0
[2,]    0    0    0    1    0    0
[3,]    1    1    0    0    0    1
[4,]    0    0    0    0    1    0
[5,]    0    0    0    1    1    1
[6,]    0    1    1    0    1    0
[7,]    1    1    1    1    0    0
[8,]    1    0    1    0    0    1

对于N生成的矩阵的 EACH ,我会进行以下计算。

X <- cbind(c(rep(1,nrow(N))),N)
ans <- sum(diag(solve(t(X)%*%X)[-1,-1]))

然后,我想获得矩阵N,它产生ans的最小值。我该如何有效地做到这一点?

1 个答案:

答案 0 :(得分:1)

让我知道这是否有效。

我们首先构建一个我需要的转换函数,并且我们还构建了反向函数,因为您可能需要它:

ind_to_M <- function(ind){
  M   <- matrix(rep(0,6*8),ncol=6)
  for(i in 1:ncol(ind)){M[ind[,i],i] <- 1}
  return(M)
}

M_to_ind <- function(M){apply(M==1,2,which)}

然后我们将建立一个可能的方法来抛弃一个值

all_possible_ways_to_ditch_value <- 1:4
for (i in 2:ncol(M)){
  all_possible_ways_to_ditch_value <- merge(all_possible_ways_to_ditch_value,1:4,by=NULL)
}
# there's probably a more elegant way to do that
head(all_possible_ways_to_ditch_value)
# x y.x y.y y.x y.y y 
# 1 1   1   1   1   1 1 # will be used to ditch the 1st value of ind for every column
# 2 2   1   1   1   1 1
# 3 3   1   1   1   1 1
# 4 4   1   1   1   1 1
# 5 1   2   1   1   1 1
# 6 2   2   1   1   1 1

然后我们遍历这些,每次都存储ans和N(因为数据总体上非常小)。

ans_list <- list()
N_list   <- list()
for(j in 1:nrow(all_possible_ways_to_ditch_value)){
  #print(j)
  ind_N   <- matrix(rep(0,6*3),ncol=6)                            # initiate ind_N as an empty matrix
  for(i in 1:ncol(M)){
    ind_N[,i] <- ind[-all_possible_ways_to_ditch_value[j,i],i]    # fill with ind except for the value we ditch
  }
  N <- ind_to_M(ind_N)
  X <- cbind(c(rep(1,nrow(N))),N)
  ans_list[[j]] <- try(sum(diag(solve(t(X)%*%X)[-1,-1])),silent=TRUE) # some systems are not well defined, we'll just ignore the errors
  N_list[[j]] <- N
}

我们最终检索了最小的ans和相关的N

ans <- ans_list[[which.min(ans_list)]]
# [1] -3.60288e+15
N   <- N_list[[which.min(ans_list)]]
# [,1] [,2] [,3] [,4] [,5] [,6]
# [1,]    0    0    0    0    0    0
# [2,]    0    1    0    1    0    1
# [3,]    1    1    0    0    1    1
# [4,]    1    0    0    1    1    0
# [5,]    0    0    1    1    1    1
# [6,]    0    1    1    0    0    0
# [7,]    1    0    1    0    0    0
# [8,]    0    0    0    0    0    0

编辑:

获得最小的积极性

ans_list[which(!sapply(ans_list,is.numeric))] <- Inf
ans <- ans_list[[which.min(abs(unlist(ans_list)))]]
# [1] 3.3
N   <- N_list[[which.min(abs(unlist(ans_list)))]]
# [,1] [,2] [,3] [,4] [,5] [,6]
# [1,]    0    0    0    0    0    0
# [2,]    0    1    0    1    0    0
# [3,]    1    1    0    0    0    1
# [4,]    1    0    0    0    1    0
# [5,]    0    0    0    1    1    1
# [6,]    0    1    1    0    1    0
# [7,]    1    0    1    1    0    0
# [8,]    0    0    1    0    0    1

编辑2:概括ind的行数到沟渠

对于n_ditch = 1,似乎给出了相同的结果,结果对n_ditch = 2有意义

n_ditch <- 2
ditch_possibilities <- combn(1:4,n_ditch) # these are all the possible sets of indices to ditch for one given columns
all_possible_ways_to_ditch_value <- 1:ncol(ditch_possibilities) # this will be all the possible sets of indices of ditch_possibilities to test
for (i in 2:ncol(M)){
  all_possible_ways_to_ditch_value <- merge(all_possible_ways_to_ditch_value,1:ncol(ditch_possibilities),by=NULL)
}

ans_list <- list()
N_list   <- list()
for(j in 1:nrow(all_possible_ways_to_ditch_value)){
  #print(j)
  ind_N   <- matrix(rep(0,6*(4-n_ditch)),ncol=6)                            # initiate ind_N as an empty matrix
  for(i in 1:ncol(M)){
    ind_N[,i] <- ind[-ditch_possibilities[,all_possible_ways_to_ditch_value[j,i]],i]    # fill with ind except for the value we ditch
  }
  N <- ind_to_M(ind_N)
  X <- cbind(c(rep(1,nrow(N))),N)
  ans_list[[j]] <- try(sum(diag(solve(t(X)%*%X)[-1,-1])),silent=TRUE) # some systems are not well defined, we'll just ignore the errors
  N_list[[j]] <- N
}