无法减少为纸浆添加约束所需的时间

问题描述

我有以下代码(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,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

感谢您提供任何帮助。

解决方法

在代码中,您首先构建一个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)