将 Python Ray 与 CPLEX 模型对象结合使用



我正在尝试并行化与计算成本高昂的Python对象的交互。 我想用Ray来做这件事,但到目前为止,我最大的努力都失败了。

该对象是 CPLEX 模型对象,我正在尝试为条件列表添加一组约束。

这是我的设置:

import numpy as np
import docplex.mp.model as cpx
import ray
m = cpx.Model(name="mymodel")
def mask_array(arr, mask_val):
array_mask = np.argwhere(arr == mask_val)
arg_slice = [i[0] for i in array_mask]
return arg_slice
weeks = [1,3,7,8,9]
const = 1.5
r = rate = np.array(df['r'].tolist(), dtype=np.float)
x1 = m.integer_var_list(data_indices, lb=lower_bound, ub=upper_bound)
x2 = m.dot(x1, r)
@ray.remote
def add_model_constraint(m, x2, x2sum, const):
m.add_constraint(x2sum <= x2*const)
return m
x2sums = []
for w in weeks:
arg_slice = mask_array(x2, w)
x2sum = m.dot([x2[i] for i in arg_slice], r[arg_slice])
x2sums.append(x2sum)
#: this is the expensive part 
for x2sum in x2sums:
add_model_constraint.remote(m, x2, x2sum, const)

简而言之,我正在做的是创建一个模型对象,一些变量,然后在一组星期内循环以构建约束。我对变量进行子集化,计算一些点积并应用约束。我希望能够并行创建约束,因为这需要一段时间,但到目前为止,我的代码只是挂起,我不确定为什么。

我不知道我是否应该在我的函数中返回模型对象,因为默认情况下 m.add_constraint 方法会就地修改对象。 但与此同时,我知道 Ray 返回对远程值的引用,所以是的,不确定那里应该发生什么。

这是射线的有效使用吗? 期望能够以这种方式修改 CPLEX 对象(或任何其他任意 python 对象(是否合理?

我是 Ray 的新手,所以我可能把这一切都搞错了,或者这可能永远不会适用于 X、Y 和 Z 的原因,这也很高兴知道。

Model对象不是为并行使用而设计的。不能同时添加来自多个线程的约束。这将导致未定义的行为。您必须至少有一个锁,以确保一次只有线程添加约束。

请注意,并行模型构建可能根本不是一个好主意:约束的顺序或多或少是随机的。另一方面,求解器的行为可能取决于约束的顺序(这称为性能可变性(。因此,您可能很难重现某些结果/行为。

我知道主要问题是模块构建的性能。 从您发送的代码中,我有两个建议来解决此问题:

  1. 批量发布约束,即将约束存储在列表中并使用 Model.add_constraints(( 添加一次,这应该比一次添加一个更有效。
  2. 使用 Model.dotf(((函数式标量产品(进行实验。它避免构建辅助列表,而是传递键的函数,返回系数。 此方法是 Docplex 版本 2.12 中的新功能。 例如,假设一个包含 3 个变量的列表:

abc = m.integer_var_list(3, name=["a", "b", "c"]( m.dotf(abc, lambda k: k+2(

docplex.mp.LinearExpression(a+2b+3c(

Model.dotf(( 通常比 Model.dot(( 快

最新更新