0

我有这个 MILP 模型,我正在通过 cplex python API 解决:

def CModel():
    
 mdl=Model('Generate')

#variable declaration
        y=mdl.binary_var_dict(ijk,name='y')
        Sum=mdl.integer_var_dict(ij,name='S')
#objective
        mdl.minimize(0)

#constraints
        #1
        mdl.add_constraints(mdl.sum(y[(i,j,k)]+y[(j,i,k)] for j in T)==1 for i in T for k in K)
        #2

        mdl.add_constraints(mdl.sum(y[(i,j,k)]+y[(j,i,k)] for k in K1 )==1 for i in T for j in T if i!=j)
        #3

        mdl.add_constraints(mdl.sum(y[(i,j,k)]+y[(j,i,k)] for k in K2 )==1 for i in T for j in T if i!=j)
        #4

        mdl.add_constraints(mdl.sum(y[(i,j,k)] for k in K )==1 for i in T for j in T if i!=j)
        #5     
        for i,j in ij:
            for k in K4:
                Sum=mdl.sum(y[(j,i,k1)] for k1 in range(k+1,k+8 ))
                mdl.add(mdl.if_then(y[(i,j,k)]==1, Sum==0))
 return mdl

Sum 是我用来制作第五个约束的变量(我只是用它来将某些范围内的 y 限制为 0)。在解决方案池中,我只需要 y==1 的 y 的索引。我有这个解决模型的解决方案池:

def soln_pool(mdl):
    cpx = mdl.get_cplex()
    cpx.parameters.parallel.set(1)
    cpx.parameters.mip.pool.intensity.set(4)
    cpx.populatelim=50
    st2=time.time()
    try:
        cpx.populate_solution_pool()
    except CplexSolverError:
        print("Exception raised during populate")
        return []
    numsol = cpx.solution.pool.get_num() #max timing by 29 second
    sol_pool = []
    pool=[]
    pool2=[]

    if numsol!=0:
        for i in range(numsol):
            indices = [j for j, a in enumerate(cpx.solution.pool.get_values(i)) if a > 0.5]  

        for element in sol_pool:
              
                for j in element:
                        v = mdl.get_var_by_index(j)                        
                        i1 = int(v.name.split('_')[1])
                        i2 = int(v.name.split('_')[2])
                        i3 = int(v.name.split('_')[3])
                        pool.append([i1,i2,i3])
                pool2.append(pool)

在我添加 constriant #5 之前,解决方案池功能没有问题,但是在添加 #5 之后,我得到了这个错误:

    i1 = int(v.name.split('_')[1])

ValueError: invalid literal for int() with base 10: '{y'

您好,我可以只访问解决方案池上的变量 y 值然后转换为整数吗?

4

2 回答 2

0

您可以检查v.name.startswith('y')以过滤掉任何不是普通 y 变量的内容。我的猜测是,有问题的变量是一些在后台创建的辅助变量。您可以打印完整v.name的名称以查看有问题的变量名称的名称。如果它是一个自动创建的变量,那么它的名称将告诉它是为哪个约束创建的。

另请注意,您有

Sum=mdl.integer_var_dict(ij,name='S')

然后

Sum=mdl.sum(y[(j,i,k1)] for k1 in range(k+1,k+8 ))

后者覆盖前者。这可能不是你打算做的。

于 2020-07-06T13:34:50.250 回答
0

丹尼尔是对的。Model.if_then生成一个布尔变量。您可以使用以下小代码进行检查:

def is_gen(dv):
    return 'yes' if dv.is_generated() else 'no'
for dv in cm.iter_variables():
    print(f'-- variable: {dv.name}, index={dv.index}, generated={is_gen(dv)}')

生成如下输出:

-- variable: _bool{y_10_2_3 == 1}, index=5887, generated=yes

它表示约束 y_20_2_3==1 的真值变量。

如您所见,is_generated()当 Docplex 生成变量时,调用变量返回 True,因此您可以在拆分代码中过滤掉这些变量。

于 2020-07-10T09:31:13.510 回答