我正在尝试为我的问题决定最佳方法,如下所示:
我有一组对象(大约3k-5k),我想要唯一地分配给大约10组(每个对象1组)。 每个对象都有一组等级,与每组中的适合程度相对应。 每个组都有一个可以管理的对象容量(约束)。 我的目标是最大化我的作业所获得的成绩总和。
例如,假设我有3个对象(o1,o2,o3)和2个具有上限的组(g1,g2)。每个1个对象。 现在假设成绩是:
o1: g1 = 11,g2 = 8
o2: g1 = 10,g2 = 5
o3: g1 = 5,g2 = 6
在这种情况下,对于最优结果,g1应该接收o2,而g2应该接收o1,总共产生10 + 8 = 18个点。
请注意,对象的数量可以超过配额的总和(例如,将o3留作“剩余”),或者不能填充配额。
我应该如何解决这个问题(旅行推销员,一种加权的Knap-Sack等)?应该在常规计算机上强制使用多长时间?是否有任何标准工具,如Matlab中的linprog函数支持这类问题?
答案 0 :(得分:1)
可以用最小成本流算法解决。 该图表可以采用以下方式:
它应该是双方的。左侧部分表示对象(每个对象的一个顶点)。右边的部分代表组(每个组的一个顶点)。每个顶点从左侧部分到右侧部分的每个顶点都有一条边,此对为capacity
= 1和cost
= - 。从左侧部分到源顶点到每个顶点还有一条边capacity
= 1和cost
= 0,从右边部分到汇点顶点的每个顶点都有一条边(水槽)和源是两个额外的顶点)capacity
=该组的约束,cost
= 0。
答案是-the cheapest flow cost from the source to the sink
。
可以用O(N^2 * M * log(N + M))
时间复杂度实现它(使用具有势的Dijkstra算法)(N
是对象的数量,M
是组的数量。)
答案 1 :(得分:1)
这可以用整数程序解决。二进制变量x_ {ij}表示如果将对象i分配给组j。目标最大化\ sum_ {i,j} s_ {ij} x_ {ij},其中s_ {ij}是与将i分配给j和x_ {ij}相关联的分数,是i是否被分配给j。您有两种类型的约束:
以下是如何在R中实现它 - R中的lp
函数与matlab中的linprog
函数非常相似。
# Score matrix
S <- matrix(c(11, 10, 5, 8, 5, 6), nrow=3)
# Capacity vector
cvec <- c(1, 1)
# Helper function to construct constraint matrices
unit.vec <- function(pos, n) {
ret <- rep(0, n)
ret[pos] <- 1
ret
}
# Capacity constraints
cap <- t(sapply(1:ncol(S), function(j) rep(unit.vec(j, ncol(S)), nrow(S))))
# Object assignment constraints
obj <- t(sapply(1:nrow(S), function(i) rep(unit.vec(i, nrow(S)), each=ncol(S))))
# Solve the LP
res <- lp(direction="max",
objective.in=as.vector(t(S)),
const.mat=rbind(cap, obj),
const.dir="<=",
const.rhs=c(cvec, rep(1, nrow(S))),
all.bin=TRUE)
# Grab assignments and objective
sln <- t(matrix(res$solution, nrow=ncol(S)))
apply(sln, 1, function(x) ifelse(sum(x) > 0.999, which(x == 1), NA))
# [1] 2 1 NA
res$objval
# [1] 18
虽然这是用二进制变量建模的,但它可以非常有效地解决假设积分容量。