我有一个很大的模型(大约500万个变量和约束)。
构建时间为几分钟,求解时间也为几分钟(使用古罗比)
但是编写模型需要很长时间(大约2个小时)
这是我使用model.write('model.lp', io_options={'symbolic_solver_labels': True})
进行录制的时间
如果我直接使用pyomo中的模型SolverFactory
和solve
,大约是同一时间
这里有一个小样本,我知道这个模型对于gurobi来说是微不足道的,所以我不在这里将求解时间与构建时间进行比较,但是我不明白为什么它这么长,尽管有这个问题可能是因为磁盘的写入速度所致,但似乎磁盘从未过载并且几乎没有被使用
import pyomo.environ as pyo
import time
size = 500000
model = pyo.ConcreteModel()
model.set = pyo.RangeSet(0, size)
model.x = pyo.Var(model.set, within=pyo.Reals)
model.constrList = pyo.ConstraintList()
for i in range(size):
model.constrList.add(expr = model.x[i] >= 1)
model.obj = pyo.Objective(expr=sum(model.x[i] for i in range(size)), sense=pyo.minimize)
opt = pyo.SolverFactory('gurobi')
_time = time.time()
res = opt.solve(model)
print(">>> total time () in {:.2f}s".format(time.time() - _time))
print(res)
结果是整个求解函数的时间为27 s,而古罗比的求解时间仅为4 s。
答案 0 :(得分:1)
我认为您的隐性问题是“我怎样才能使其更快?”
如果写入时间有问题,您可以研究与Gurobi SolverFactory('gurobi', io_format='python')
的直接python接口。将symbolic_solver_labels
标志设置为True
几乎总是会增加模型的写入时间,因为查找组件名称可能会很昂贵。
答案 1 :(得分:1)
从加快pyomo模型生成的速度出发,您需要首先确定该过程的哪一部分正在减慢它的速度。 (这实际上是性能调整的一般建议)
所以我将您的代码放入一个函数中
def main():
size = 500000
model = pyo.ConcreteModel()
model.set = pyo.RangeSet(0, size)
model.x = pyo.Var(model.set, within=pyo.Reals)
model.constrList = pyo.ConstraintList()
for i in range(size):
model.constrList.add(expr = model.x[i] >= 1)
model.obj = pyo.Objective(expr=sum(model.x[i] for i in range(size)), sense=pyo.minimize)
return model
所以我可以在ipython中通过行探查器运行
In [1]: %load_ext line_profiler
In [2]: import test_pyo
In [3]: %lprun -f test_pyo.main test_pyo.main()
这表明大部分时间都花在 model.constrList.add(expr = model.x [i]> = 1)中。
通过将其移至基于规则的约束中并没有看到太大的改进,因此我决定尝试像PyPSA code中一样手动构造表达式。
import pyomo.environ as pyo
import time
from pyomo.core.expr.numeric_expr import LinearExpression
from pyomo.core.base.constraint import _GeneralConstraintData
from pyomo.core.base.numvalue import NumericConstant
def main():
size = 500000
model = pyo.ConcreteModel()
model.set = pyo.RangeSet(0, size)
model.x = pyo.Var(model.set, within=pyo.Reals)
setattr(model, "constraint", pyo.Constraint(model.set, noruleinit=True))
v = getattr(model, "constraint")
for i in v._index:
v._data[i] = _GeneralConstraintData(None, v)
expr = LinearExpression()
expr.linear_vars = [model.x[i]]
expr.linear_coefs = [1]
expr.constant = 0
v._data[i]._body = expr
v._data[i]._equality = False
v._data[i]._lower = NumericConstant(1)
v._data[i]._upper = None
model.obj = pyo.Objective(expr=pyo.quicksum(model.x[i] for i in range(size)), sense=pyo.minimize)
return model
似乎可以提高约50%的性能。线剖析器显示,现在花费大量时间来创建集合,空的LinearExpression对象以及创建目标。摆弄目标也许可以使事情有所改善。
答案 2 :(得分:0)
也值得检查您是否安装了最新版本的pyomo。我最近从5.5.0版更新到5.6.8版,看到构建+解决时间从5s减少到1s(这个问题显然比您的要小得多!)。