我正在解决一个基本的线性规划问题:min c*x
,与A*x = b
约束,使用CPLEX与Python (DOCPLEX)。
然后我对b
和c
的10k-100k种不同组合运行上述LP (A
保持固定),以便从中找到最小解(它们每个都计算一个"距离";我们正在寻找"最短的"距离)。
为了实现这一点,我必须"创建";每次迭代都要重复这个问题,即每次都要重新创建目标函数和约束条件。这个设置花费了我总处理时间的75%,而实际求解只花费了25%,所以我希望以某种方式加快速度。我的想法是使用某种"模板"来创建问题。值,然后对于每个(b, c)组合只传递值并解决问题。这类东西存在于其他库中,如CVXPY,但我在CPLEX/DocPlex文档中找不到类似的东西。
这是我的"解决方案"。方法:
def _solve(self, coeffs: np.array, b: np.array) -> float:
self._model.minimize(self._model.sum(self._model.dot(self._x, coeffs)))
self._model.clear_constraints()
self._model.add_constraints(
self._model.dotf(self._x, lambda j: self._a[i][j]) == b[i]
for i in range(self._num_colours)
)
sol = self._model.solve()
return sol.get_objective_value()
模型、变量和A
固定并初始化一次:
self._a = <GENERATE FIXED A>
self._model = _model.Model()
self._x = self._model.integer_var_list(self._a.shape[1])
使用docplex可以对矩阵进行增量更改。
看例子
from docplex.mp.model import Model
# original model
mdl = Model(name='buses')
nbbus40 = mdl.integer_var(name='nbBus40')
nbbus30 = mdl.integer_var(name='nbBus30')
mdl.add_constraint(nbbus40*40 + nbbus30*30 >= 300, 'kids')
mdl.minimize(nbbus40*500 + nbbus30*400)
mdl.solve()
for v in mdl.iter_integer_vars():
print(v," = ",v.solution_value)
#now 350 kids instead of 300
print()
print("now 350 kids instead of 300")
mdl.get_constraint_by_name("kids").rhs=350;
mdl.solve()
for v in mdl.iter_integer_vars():
print(v," = ",v.solution_value)
# no more than 4 buses 40 seats
print()
print("no more than 4 buses 40 seats")
mdl.get_var_by_name("nbBus40").ub=4
mdl.solve()
for v in mdl.iter_integer_vars():
print(v," = ",v.solution_value)
#change the objective so that cost for 40 seats is 450
#and remove the limit on the number of buses 40 seats
print()
print("change the objective so that cost for 40 seats is 450")
print("and remove the limit on the number of buses 40 seats ")
mdl.get_var_by_name("nbBus40").ub=1000
mdl.set_objective("min",nbbus40*450 + nbbus30*400);
mdl.solve()
for v in mdl.iter_integer_vars():
print(v," = ",v.solution_value)