【问题标题】:Cannot reduce time taken to add constraints to pulp无法减少为纸浆添加约束所花费的时间
【发布时间】:2020-10-23 17:11:48
【问题描述】:

我有以下代码(python 3)用于向纸浆(v 2.3)添加约束。最多需要添加 400000 个约束(100^2 S, 4 A)。

    def linearProgram(self, error = 1e-12):
        lp_problem = p.LpProblem('best-Vpi', p.LpMinimize)

        #create problem variables
        V = p.LpVariable.dicts("V",range(self.S), cat = "Continuous")
        #objective function
        for i in range(self.S):
            self.v.append(V[i])
        lp_problem += p.lpSum(self.v)
        #constraints
        for s in range(self.S):
            for a in range(self.A):
                pv = p.LpAffineExpression([(V[x],self.T[s][a][x]) for x in range(self.S)])
                constraint = p.lpSum([self.PR[s][a], self.gamma*pv ])
                lp_problem += V[s] >= constraint

        status = lp_problem.solve(p.PULP_CBC_CMD(msg = 0)) #solve

我似乎无法进一步优化它..

我什至尝试过多处理,但它给出了很多错误-


    def __addconstraints(self, S0, S1, lp_problem):
        for s in range(S0, S1):
            for a in range(self.A):
                pv= p.lpDot(self.T[s][a],self.v)
                lp_problem += self.v[s] >= p.lpSum([self.PR[s][a], self.gamma*pv])
   ..................
   #in linearProgram
        if self.S%4:
            s0, s1 = 0, self.S//3
        else:
            s0, s1 = 0, self.S//4
        incr = s1
        processes = []
        for x in range(4):
            proc = multiprocessing.Process(target=self.__addconstraints, args=(s0, s1, lp_problem))
            processes.append(proc)
            proc.start()
            s0 = s1
            s1 = min(s1+incr, self.S)

        for proc in processes:
            proc.join()

        hard code for episodic? no need (due to initialization of mdp)
        if self.mdptype=="episodic":
            for state in self.end:
                lp_problem += V[state] == 0

我对纸浆和多处理都是新手,所以我真的不知道我在做什么:p

感谢任何形式的帮助。

【问题讨论】:

    标签: python optimization python-multiprocessing pulp


    【解决方案1】:

    在您的代码中,您首先构建p.LpAffineExpression,然后应用p.lpSum,最后对结果V[s] >= constraint 执行第三次操作。最后两个操作可能会增加时间,因为每次都在复制表达式。

    根据我的经验,我获得的最快时间是:

    # _vars_tup is a list of (key, value) pairs where each key is a variable and each value is a coefficient.
    #  it's like initializing a dictionary.
    # CONSTANT is a python number (not a pulp variable)
    model += p.LpAffineExpression(_vars_tup, constant=CONSTANT) >= 0
    

    这样做的目的是减少对 p.LpAffineExpression 对象进行操作的次数,因为每次操作都会完成一份副本。因此,为约束中存在的所有变量构建变量和系数列表 (_vars_tup),然后在最后一步创建 p.LpAffineExpression 并将其与常量进行比较。

    等效的方法是(虽然我没有尝试过):

    const = p.LpConstraint(e=p.LpAffineExpression(_vars_tup, constant=_constant), sense = p.LpConstraintGE, rhs = -CONSTANT)
    model.addConstraint(other)
    

    【讨论】:

    • 您好,感谢您的回答。我已经尝试了所有的变体,但所需的时间像疯了一样增加,也许是由于复杂性。有什么好的方法可以减少吗?我尝试将其转换为字典(numpy 数组),但也想不出一个好方法来做到这一点..
    • 你分析过代码了吗?您确定性能问题确实在于添加约束吗? 400.000 个约束很大,但并非不可能。你运行那部分需要多长时间?最后,需要多长时间才能解决?如果一个大问题可以快速解决,也许您可​​以预处理您的数据以仅创建所需的约束。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-17
    • 2017-03-31
    • 1970-01-01
    相关资源
    最近更新 更多