离散优化算法

时间:2014-06-21 14:43:39

标签: algorithm matlab mathematical-optimization

我正在尝试为我的问题决定最佳方法,如下所示:

我有一组对象(大约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函数支持这类问题?

2 个答案:

答案 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。您有两种类型的约束:

    所有j的
  • \ sum_i x_ {ij}< = c_j,组的容量限制
  • 对于所有i,
  • \ sum_j x_ {ij}< = 1,限制最多分配给一个组的对象

以下是如何在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

虽然这是用二进制变量建模的,但它可以非常有效地解决假设积分容量。