如何在CPLEX OPL的目标函数中对两个连续决策变量的乘积进行建模?
我在用CPLEX OPL求解一个优化模型,其中目标函数包含两个连续决策变量的乘积。
例如,
dvar float x in 0..50;
dvar float y in 1.2..3.8;
minimize x * y;
当我在目标函数(或约束)中直接使用乘积 x * y 时,OPL会报告
来自IBM ILOG CPLEX的异常:CPLEX错误5002:'q1' 不是凸的。->. Trialnonconvex Unknown OPL Problem Marker
我读到关于McCormick线性化 的资料,其中引入一个新变量 p,使得 p = x * y,并且在目标中用 p 替代双线性项。然而,我不确定对于一个两个变量都是连续决策变量的问题,在CPLEX OPL中这是否是正确的做法。
我已经尝试了这个。仍然得到同样的错误。该如何解决?
int T = 4;
range TRange = 1..T;
int ncs=2;
range crange=1..ncs;
int nv=3;
range vrange=1..nv;
dvar float+ x[TRange][vrange][crange];
dvar float+ y[TRange][crange];
dvar float+ p[TRange][vrange][crange];
int z=5;
minimize sum(t in TRange, c in crange, v in vrange)(p[t][v][c]+5*z);
subject to{
forall(t in TRange, c in crange, v in vrange){
0<=x[t][v][c]<=50;
1.2<=y[t][c]<=3.8;
p[t][v][c]>=x[t][v][c]*y[t][c];
p[t][v][c]>=x[t][v][c]*3.8+50*y[t][c]-50*3.8;
p[t][v][c]<=x[t][v][c]*1.2+50*y[t][c]-50*1.2;
p[t][v][c]<=x[t][v][c]*3.8;
}
}
解决方案
错误是由这个约束引起的:
p[t][v][c] >= x[t][v][c] * y[t][c];
它仍然是双线性项,因此CPLEX将模型视为一个非凸二次规划,这会导致:
CPLEX Error 5002: 'q1' is not convex
正确的McCormick线性化
给定:
-
-
将所有出现的 x*y 替换为 p,并且在模型中不要在任何地方使用 x*y。
仅使用这四个线性约束:
p[t][v][c] >= 1.2 * x[t][v][c];
p[t][v][c] >= 3.8 * x[t][v][c]
+ 50 * y[t][c]
- 190;
p[t][v][c] <= 1.2 * x[t][v][c]
+ 50 * y[t][c]
- 60;
p[t][v][c] <= 3.8 * x[t][v][c];
你的错误
你写了:
p >= x*y; // ❌ Wrong
这不是McCormick线性化的一部分,必须被移除。
还有一个重要点
如果你的目标是严格地强制
p = xy
当且仅当 x 和 y 同时是连续变量 时,McCormick包络并不能实现。它们只提供双线性项的凸松弛。
因此:
- MILP近似:仅使用四条McCormick不等式。
- 精确等式:CPLEX无法求解一般的非凸双线性模型。你需要一个全局非凸求解器(例如带有
NonConvex=2的Gurobi、BARON、SCIP或 Couenne)。
因此,如果你只使用CPLEX,精确的修复步骤是:
- 删除
p >= x*y。 - 仅使用四条McCormick不等式。
- 在目标和约束中将每一次出现的
x*y都替换为p。
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。