微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

cvxpy和gurobi的优化对比

如何解决cvxpy和gurobi的优化对比

有许多作业要分配给许多资源,每个作业都有一个分数(性能指标)和成本。资源分配问题 (RAP) 的目标是在考虑预算的情况下最大化分配分数。 限制条件:每个资源最多只能处理一项工作,并且每项工作如果被填充应由一个资源完成。此外,预算有限。 我通过两种方式解决了这个问题:CVXPY 使用 gurobi 求解器和 gurobi 包。我的挑战是我无法使用 cvxpy 以节省内存的方式对其进行编程。有数百个约束列​​表推导式!如何提高 cvxpy 中代码的效率? 比如在cvxpy中有没有更好的方法来定义类似于gurobi的字典变量?

ms 是格式为 {('firstName lastName','job'),score_value}
的字典 cst 是格式为 {('firstName lastName',cost_value}
的字典 job 是一组工作
res 是一组资源 {'firstName lastName'}
G(或 gurobi 实现中的 g )是一个字典,以工作为键,值为 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

解决方法

以前,我试图通过定义类似于 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),),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)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。