C++ R/C++;
给定一个元素U={1,2,3,…,n}的宇宙和这个宇宙中的许多集合{S1,S2,…,Sm},我们能创建的最小集合是什么,它将覆盖m个集合中至少一个元素 例如,给定以下元素U={1,2,3,4}和集合S={{4,3,1},{3,1},{4},以下集合将覆盖每个集合中的至少一个元素: {1,4} 或 {3,4} 所以这里需要的最小尺寸是2 关于如何扩大规模以解决m=100或m=1000组的问题,您有何想法?或者关于如何在R或C++中编写代码? 使用R的C++ R/C++;,c++,algorithm,r,complexity-theory,set-cover,C++,Algorithm,R,Complexity Theory,Set Cover,给定一个元素U={1,2,3,…,n}的宇宙和这个宇宙中的许多集合{S1,S2,…,Sm},我们能创建的最小集合是什么,它将覆盖m个集合中至少一个元素 例如,给定以下元素U={1,2,3,4}和集合S={{4,3,1},{3,1},{4},以下集合将覆盖每个集合中的至少一个元素: {1,4} 或 {3,4} 所以这里需要的最小尺寸是2 关于如何扩大规模以解决m=100或m=1000组的问题,您有何想法?或者关于如何在R或C++中编写代码? 使用R的库(集合)从上面获取样本数据 s1如果将每个集合
库(集合)
从上面获取样本数据
s1如果将每个集合限制为有2个元素,那么就有了np完全问题节点覆盖。我猜更一般的问题也会是NP完全问题(对于确切的版本)。如果你只是对一个算法感兴趣(而不是一个有效/可行的算法),你可以简单地生成基数递增的宇宙子集,并检查与S中所有集合的交集是否为非空。一旦你找到一个有效的,就停下来;基数是可能的最小值
我认为,在最坏的情况下,这种情况的复杂性是2^ U |。根据Foo-Bah的答案,我认为你不会得到多项式时间的答案…这是一个集合,它基本上覆盖了元素和集合的角色互换。让A={4,3,1}和B={3,1}以及C={4},元素集包含关系为
A B C
1 + + -
2 - - -
3 + + -
4 + - +
所以你基本上想用集合1={A,B}和集合2={}和集合3={A,B}和集合4={A,C}来解决覆盖{A,B,C}的问题
在实际应用中,解决集合覆盖的非平凡实例最简单的方法是找到一个具有R或C++接口的整数规划包。您的示例将以LP格式呈现为以下整数程序
Minimize
obj: x1 + x2 + x3 + x4
Subject To
A: x1 + x3 + x4 >= 1
B: x1 + x3 >= 1
C: x4 >= 1
Binary
x1 x2 x3 x4
End
起初,我误解了问题的复杂性,提出了一个函数,可以找到一个覆盖m个集合的集合,但后来我意识到它不一定是最小的集合:
cover <- function(sets, elements = NULL) {
if (is.null(elements)) {
# Build the union of all sets
su <- integer()
for(si in sets) su <- union(su, si)
} else {
su <- elements
}
s <- su
for(i in seq_along(s)) {
# create set candidate with one element removed
sc <- s[-i]
ok <- TRUE
for(si in sets) {
if (!any(match(si, sc, nomatch=0L))) {
ok <- FALSE
break
}
}
if (ok) {
s <- sc
}
}
# The resulting set
s
}
sets <- list(s1=c(1,3,4), s2=c(1,3), s3=c(4))
> cover(sets) # [1] 3 4
cover嗨,每个集合中的元素在我正在解决的特定问题中都很重要,因此不能减少为2个元素。确实如此。如果2集的版本是NP完全的,那么它也是NP难的。由于可以用N-set版本轻松地求解2-set版本的实例(使用N=2的N-set版本),因此这也是NP难的。由于您可以在多项式时间内轻松验证证书(检查每个集合在S中的交集),因此它也是NP。因此NP-完全。你的意思是n=4,m=100吗?根据您的定义,m
是集合数,n
是元素数!我会尝试一下,但理想情况下,我正在寻找一种可行且高效的算法,可以扩展到大量集合,每个集合中包含大量元素。感谢您的回复,它为开始编写解决方案提供了良好的基础。hi@bar,这看起来很棒。问题是(我要从这里出来)我对LP不熟悉!好像我周末要看书!:-)
cover <- function(sets, elements = NULL) {
if (is.null(elements)) {
# Build the union of all sets
su <- integer()
for(si in sets) su <- union(su, si)
} else {
su <- elements
}
s <- su
for(i in seq_along(s)) {
# create set candidate with one element removed
sc <- s[-i]
ok <- TRUE
for(si in sets) {
if (!any(match(si, sc, nomatch=0L))) {
ok <- FALSE
break
}
}
if (ok) {
s <- sc
}
}
# The resulting set
s
}
sets <- list(s1=c(1,3,4), s2=c(1,3), s3=c(4))
> cover(sets) # [1] 3 4
n <- 100 # number of elements
m <- 1000 # number of sets
sets <- lapply(seq_len(m), function(i) sample.int(n, runif(1, 1, n)))
system.time( s <- cover(sets) ) # 0.53 seconds
ns <- 10 # number of samples
elements <- seq_len(n)
smin <- sets
for(i in seq_len(ns)) {
s <- cover(sets, sample(elements))
if (length(s) < length(smin)) {
smin <- s
}
}
length(smin) # approximate smallest length