【发布时间】:2023-03-24 22:05:01
【问题描述】:
有许多作业要分配给许多资源,每个资源都有一个分数(绩效指标)和成本。资源分配问题 (RAP) 的目标是在考虑预算的情况下最大化分配分数。 限制条件:每个资源最多只能处理一项工作,每个工作如果被填满,应该由一个资源完成。此外,预算有限。 我用两种方式解决了这个问题:CVXPY 使用 gurobi 求解器和 gurobi 包。我的挑战是我不能用 cvxpy 以高效的方式对其进行编程。有数百个约束列表推导!如何提高 cvxpy 中代码的效率? 例如,有没有更好的方法来定义类似于 gurobi 的 cvxpy 中的字典变量?
ms 是 {('firstName lastName', 'job') 格式的字典, score_value}
cst 是 {('firstName lastName' 格式的字典, 'job'), cost_value}
job 是一组作业
res 是一组资源 {'firstName lastName'}
G(或 gurobi 实现中的 g)是一个字典,其中作业作为键和值 0 或 1,无论该作业是否因预算限制而被填补(如果已满则为 0,如果未满则为 1)
谢谢 github link including codes and memory profiling comparison
gurobi 实现:
m = gp.Model("RAP")
assign = m.addVars(ms.keys(), vtype=GRB.BINARY, name="assign")
g = m.addVars(job, name="gap")
m.addConstrs((assign.sum("*", j) + g[j] == 1 for j in job), name="demand")
m.addConstrs((assign.sum(r, "*") <= 1 for r in res), name="supply")
m.addConstr(assign.prod(cst) <= budget, name="Budget")
job_gap_penalty = 101 # penatly of not filling a job
m.setObjective(assign.prod(ms) -job_gap_penalty*g.sum(), GRB.MAXIMIZE)
m.optimize()
cvxpy 实现:
X = {}
for a in ms.keys():
X[a] = cp.Variable(boolean=True, name="assign")
G = {}
for g in job:
G[g] = cp.Variable(boolean=True, name="gap")
constraints = []
for j in job:
X_r = 0
for r in res:
X_r += X[r, j]
constraints += [
X_r + G[j] == 1
]
for r in res:
X_j = 0
for j in job:
X_j += X[r, j]
constraints += [
X_j <= 1
]
constraints += [
np.array(list(cst.values())) @ np.array(list(X.values())) <= budget,
]
obj = cp.Maximize(np.array(list(ms.values())) @ np.array(list(X.values()))
- job_gap_penalty * cp.sum(list(G.values())))
prob = cp.Problem(obj, constraints)
prob.solve(solver=cp.GUROBI, verbose=False)
这是内存分析比较:
【问题讨论】:
-
没有 github 链接,即使有:这不是本网站要求的问题类型。特别是关于完全基于外部链接的问题(将来可能会下降)。关于您的基本问题:是的,不要做列表理解、循环等;使用稀疏代数。通常一个慢循环相当于一些稀疏的代数表达式:例如与一些单位矩阵的矩阵乘法。这些是 cvxpy(以及所有求解器)的核心。
-
感谢您的想法@sascha。我现在添加了代码和内存分析比较问题
-
您使用的内存分析器是什么?