访问cplex解决方案池中不同类型的变量值时出现问题



我有这个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的索引,其中y==1。我有这个解决方案池来解决模型:

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)

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

i1 = int(v.name.split('_')[1])
ValueError: invalid literal for int() with base 10: '{y'

为什么我只能访问解决方案池中的变量y值并将其转换为整数?

您只需检查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 ))

后者覆盖前者。这可能不是你想要做的。

Daniel是对的。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

3==1的真值变量。

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

最新更新