问题描述
我有以下代码(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)