【问题标题】:Minimal number of coverage of big data lists大数据列表的最小覆盖数量
【发布时间】:2017-06-19 11:04:54
【问题描述】:

关注我的question 我使用以下代码:

dist<-c('att1','att2','att3','att4','att5','att6')
p1<-c('att1','att5','att2')
p2<-c('att5','att1','att4')
p3<-c('att3','att4','att2')
p4<-c('att1','att2','att3')
p5<-c('att6')
....
p32<-c('att35','att34','att32')

在实际情况下可以有 1024 个向量。 我想找到所有相关的p,它们的统一将是 dist 的最大组成部分。在这种情况下,解决方案是p1p3p5。我想选择最少的p。另外,如果没有办法覆盖所有的 dist 组件,所以我想选择具有最少向量 (p) 的最大覆盖。

N = 32
library(qdapTools)
library(dplyr)
library(data.table)
## generate matrix of attributes
attribute_matrix <- mtabulate(list(p1, p2, p3, p4, p5,...,p32))

library (bigmemory)
## generate matrix of attributes
grid_matrix <- do.call(CJ, rep(list(1:0), N))  %>% as.big.matrix

Error: cannot allocate vector of size 8.0 Gb

我尝试了另一种方法:

grid_matrix <- do.call(CJ, rep(list(1:0), N))  %>% as.data.frame
grid_matrix <- as.matrix (grid_matrix)

仍然出现同样的错误。

如何修复它并将其用于大数据?我想继续:

 colnames(grid_matrix) <- paste0("p", 1:N)
    combin_all_element_present <- rowSums(grid_matrix %*% attribute_matrix > 0) %>% `==`(., ncol(attribute_matrix))
    grid_matrix_sub <- grid_matrix[combin_all_element_present, ]
    grid_matrix_sub[rowSums(grid_matrix_sub) == min(rowSums(grid_matrix_sub)), ]

【问题讨论】:

    标签: r list vector bigdata


    【解决方案1】:

    这被称为集合覆盖问题。它可以使用整数线性规划来解决。令 x1, x2, ... 为 0/1 变量(每个 p 变量一个)并将 p1, p2, ... 表示为 0/1 向量 P1, P2, ... 并将 dist 表示为 一个0/1向量D。那么问题可以表述为:

    min x1 + x2 + ... + x32
    such that
    P1 * x1 + P2 + x2 + ... + P32 * x32 >= D
    

    R 代码中的内容如下。首先创建一个列表p,其中 p 个向量按排序顺序排列。使用mixedsort 使p32 出现在末尾,而不是紧随p3 之后。将attnames 定义为所有 p 个向量中所有 att 名称的集合。 然后制定目标函数(等于封面中 p 的数量)、约束矩阵(由作为列的 P 个向量组成)和约束方程的右侧(作为 0/1 向量的 dist)。最后运行整数线性程序并将解从 0/1 向量转换为 p 个名称的向量。

    library(gtools)
    library(lpSolve)
    
    p <- mget(mixedsort(ls(pattern = "^p\\d+$")))
    attnames <- mixedsort(unique(unlist(p)))
    objective <- rep(1L, length(p))
    const.mat <- sapply(p, function(x) attnames %in% x) + 0L
    const.rhs <- (attnames %in% dist) + 0L
    
    ans <- lp("min", objective, const.mat, ">=", const.rhs, all.bin = TRUE)
    names(p)[ans$solution == 1L]
    ## [1] "p2" "p4" "p5"
    

    约束矩阵对于每个attnames 条目都有一行,对于每个p 向量都有一列。

    该解决方案生成dist 中的那些attnames 元素的最小覆盖。如果dist 的每个元素都出现在至少一个p 向量中,那么解决方案将代表dist 的封面。如果不是,解决方案将在一个或多个 p 向量中表示这些 att 名称的覆盖,这些向量也在 dist 中;因此,这处理了问题中讨论的两种情况。 dist 的未覆盖元素是:

    setdiff(dist, attnames)
    

    因此,如果它的长度为零,则该解决方案代表dist 的完整覆盖。如果不是,则解决方案代表

    intersect(dist, attnames)
    

    代码中完成的排序并不是严格需要的,但通过将约束矩阵的行和列按逻辑顺序排列,可以更轻松地处理优化的各种输入。

    注意:在运行上述代码之前运行问题中的这段代码:

    dist<-c('att1','att2','att3','att4','att5','att6')
    p1<-c('att1','att5','att2')
    p2<-c('att5','att1','att4')
    p3<-c('att3','att4','att2')
    p4<-c('att1','att2','att3')
    p5<-c('att6')
    p32<-c('att35','att34','att32')
    

    【讨论】:

    • 非常感谢@G。格洛腾迪克!我想问:(1)使用混合排序是否意味着每个向量编号都会在之前的向量编号之后(即p1,p2,p3,p4 ...,p31,p32)? (2)如果没有最优解,我想得到最大覆盖,但不是全覆盖,代码支持吗?最后,这是解决问题最有效的方法吗?
    • 再次感谢!我得到一个错误: > const.mat
    • 如果我有一个包含所有 p 的列表而不是 p 列表,即名为 nam 的列表 nam[[1]] 是 p1... nam[[32]] 是 p32 我是否必须更改进入 p
    • 您可能只需要在答案中设置 p
    • 您的p 没有名称,但您在最后一行代码中指的是names(p)。使用 0/1 向量 ans$solution 作为您的解决方案。
    【解决方案2】:

    已经提供的答案是完美的,但另一种方法可能如下:

    dist<-c('att1','att2','att3','att4','att5','att6')
    p1<-c('att1','att5','att2')
    p2<-c('att5','att1','att4')
    p3<-c('att3','att4','att2')
    p4<-c('att1','att2','att3')
    p5<-c('att6')
    
    
    library(qdapTools)
    library(data.table)
    attribute_matrix <- mtabulate(list(p1, p2, p3, p4, p5))
    
    
    minimal_sets <- function(superset, subsets_matrix, p){
    
      setDT(subsets_matrix)
      # removing the columns that are not in the superset
      updated_sub_matr <- subsets_matrix[, which(names(subsets_matrix) %in% superset), with = F]
    
      # initializing counter for iterations and the subset selected 
      subset_selected <- integer(0)
      counter <- p
    
      ## Loop until either we ran out of iterations counter = 0 or we found the solution
      while (counter > 0 & length(superset) > 0){
    
        ## find the row with the most matches with the superset we want to achieve  
        max_index <- which.max(rowSums(updated_sub_matr))
    
        ## remove from the superset the entries that match that line and from the subsets_matrix those columns as they dont contribute anymore
        superset <- superset[which(updated_sub_matr[max_index, ] == 0)]
        updated_sub_matr <- updated_sub_matr[, - which(updated_sub_matr[max_index, ] != 0), with = F]
    
        counter <- counter - 1
        subset_selected <- c(subset_selected, max_index)
      }
    
      if (length(superset) > 0){
        print(paste0("No solution found, there are(is) ", length(superset), " element(s) left ", paste(superset, collapse = "-")))            
      } else {            
        print(paste0("Found a solution after ", p - counter, " iterations"))           
      }
    
      print(paste0("Selected the following subsets: ", paste(subset_selected, collapse = "-")))
    
    }
    

    在此函数中,您输入您的超集(在本例中为 dist)、attribute_matrix 和要检查的数字 p,它会输出找到的最佳解决方案以及迭代次数。

    > minimal_sets(dist, attribute_matrix, 1)
    [1] "No solution found, there are(is) 3 element(s) left att3-att4-att6"
    [1] "Selected the following subsets: 1"
    
    > minimal_sets(dist, attribute_matrix, 3)
    [1] "Found a solution after 3 iterations"
    [1] "Selected the following subsets: 1-3-5"
    
    > minimal_sets(dist, attribute_matrix, 5)
    [1] "Found a solution after 3 iterations"
    [1] "Selected the following subsets: 1-3-5
    

    【讨论】:

      猜你喜欢
      • 2016-07-09
      • 2015-12-31
      • 2015-10-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-12
      • 1970-01-01
      相关资源
      最近更新 更多