问题描述
我正在尝试使用 CPLEX 创建优化模型。
我的问题是:
我有生产产品的需求、生产能力(按机器计算)和生产成本(按机器计算)。 有些机器生产相同的产品具有不同的成本和生产能力。
我正在尝试构建一个优化模型,在生产需求产品的同时最小化生产成本。
import pandas as pd
dmd = {
'TONS_BY_MONTH': {'PRODUCT_A': 27283.781,'PRODUCT_B': 119.477,'PRODUCT_C': 4651.003}
}
df_demanda = pd.DataFrame(dmd)
df_demanda
custo = {
'MC05': {'PRODUCT_A': 1368,'PRODUCT_B': 1368,'PRODUCT_C': 1368},'MC06': {'PRODUCT_A': 1435,'PRODUCT_B': 1435,'PRODUCT_C': 1427},'MC07': {'PRODUCT_A': 1189,'PRODUCT_B': 1207,'PRODUCT_C': 0},'MC08': {'PRODUCT_A': 1221,'PRODUCT_B': 1209,'MC09': {'PRODUCT_A': 1905,'PRODUCT_B': 1907,'PRODUCT_C': 1965}
}
df_custo = pd.DataFrame(custo)
df_custo
produtos = ['PRODUCT_A','PRODUCT_B','PRODUCT_C']
maquinas = ['MC05','MC06','MC07','MC08','MC09']
dias = list(range(1,30))
capacidade = {
'MC05': {'PRODUCT_A': 371,'PRODUCT_B': 371,'PRODUCT_C': 427},'MC06': {'PRODUCT_A': 396,'PRODUCT_B': 396,'PRODUCT_C': 435},'MC07': {'PRODUCT_A': 547,'PRODUCT_B': 571,'MC08': {'PRODUCT_A': 476,'PRODUCT_B': 497,'MC09': {'PRODUCT_A': 657,'PRODUCT_B': 692,'PRODUCT_C': 790}
}
df_capacidade = pd.DataFrame(capacidade)
df_capacidade
from docplex.mp.model import Model
mdl = Model(name="DEMANDA_BY_DAY")
x = {(i,j):
mdl.continuous_var(name="PRODUCAO_{0}_{1}".format(i,j)) for i in produtos for j in maquinas }
DIAS = {(d):
mdl.binary_var(name="DIA_{0}".format(d)) for d in dias}
mdl.minimize(mdl.sum([ DIAS[d] * (df_custo.loc[i,j] * x[(i,j)]) for d in dias for i in produtos for j in maquinas]))
for i in produtos:
mdl.add_constraint( mdl.sum([x[(i,j)] * DIAS[d] for d in DIAS for j in maquinas ]) == df_demanda.loc[i,'TONS_BY_MONTH'])
for i in produtos:
mdl.add_constraint( mdl.sum([x[(i,j)] * DIAS[d] for d in DIAS for j in maquinas ]) <= mdl.sum([df_capacidade.loc[i,s] for s in maquinas]))
mdl.solve(log_output=True)
解决方法
您的模型包含具有 x_i * y_+i 形式的项总和的约束。 这种约束不是凸的,基本上任何两个不同变量 X * Y 的二次乘积都是非凸的。 CPLEX 尚未解决非凸 QCP,因此您需要在没有这些乘积的情况下重新表述您的问题。我看到两种可能的方式:
-
或者扩展 X 变量矩阵(顺便说一句,您可能可以使用 Model.continuous_var_matrix 来简化)增加一个维度数天,并且每个三元组(产品、机器、天)有一个变量
-
还检查指标约束:指标约束动态链接二元变量的值和线性约束。换句话说,如果在寻找解决方案的过程中,二元变量变为 1(或 0),那么一些线性约束被强制执行,否则无论是真还是假都是不确定的。
例如下面的代码
mdl.add_indicator(dias[0],x[1,2] ==0,active_value=0)
指出如果二元变量 dias[0]
的最终值为 0(active_value
),则约束 x[1,2]==0
变为真。
请注意,这是单向的:二进制变量的值会影响约束的状态,但不会反过来。
如果您对模型的重构有任何疑问,请告诉我。