【问题标题】:optimization comparison between cvxpy and gurobicvxpy和gurobi的优化对比
【发布时间】: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)

这是内存分析比较:

memeory profiling for cvxpy

memory profiling for gurobi

【问题讨论】:

  • 没有 github 链接,即使有:这不是本网站要求的问题类型。特别是关于完全基于外部链接的问题(将来可能会下降)。关于您的基本问题:是的,不要做列表理解、循环等;使用稀疏代数。通常一个慢循环相当于一些稀疏的代数表达式:例如与一些单位矩阵的矩阵乘法。这些是 cvxpy(以及所有求解器)的核心。
  • 感谢您的想法@sascha。我现在添加了代码和内存分析比较问题
  • 您使用的内存分析器是什么?

标签: python gurobi cvxpy


【解决方案1】:

以前,我尝试通过定义类似于 gurobi 但 at 在 cvxpy 中不可用的字典变量来解决,代码在放大时效率不高。但现在我通过矩阵变量解决了它,然后转换为超快的字典变量!

assign_scores = np.array(list(ms.values())).reshape(len(res), len(job))
assign_cost = np.array(list(cst.values())).reshape(len(res), len(job))

# make a bool matrix variable with the shape of number of resources and jobs
x = cp.Variable(shape=(len(res), len(job)), boolean=True, name="assign")
# make a bool vector variable with the shape of number of jobs
g = cp.Variable(shape=(len(job), ), boolean=True, name="gap")

constraints = []
# each job can be assigned to at most one resource or remains unfilled due to budget cap 
constraints += [cp.sum(x[:, j]) + g[j] == 1 for j in range(len(job))]
# each resource can be assigned to at most one job
constraints += [cp.sum(x[r, :]) <= 1 for r in range(len(res))]
# budget cap
constraints += [cp.sum(cp.multiply(assign_cost, x)) <= budget]

# pentalty if a job is not filled 
job_gap_penalty=101
# objective is to maiximize performance score 
obj = cp.Maximize(cp.sum(cp.multiply(assign_scores, x) - job_gap_penalty * cp.sum(g)))
prob = cp.Problem(obj, constraints)
prob.solve(solver=cp.GUROBI, verbose=True)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多