如何在CPLEX OPL的目标函数中对两个连续决策变量的乘积进行建模?

编程语言 2026-07-07

我在用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

当且仅当 xy 同时是连续变量 时,McCormick包络并不能实现。它们只提供双线性项的凸松弛。

因此:

  • MILP近似:仅使用四条McCormick不等式。
  • 精确等式:CPLEX无法求解一般的非凸双线性模型。你需要一个全局非凸求解器(例如带有 NonConvex=2 的Gurobi、BARON、SCIP或 Couenne)。

因此,如果你只使用CPLEX,精确的修复步骤是:

  1. 删除 p >= x*y
  2. 仅使用四条McCormick不等式。
  3. 在目标和约束中将每一次出现的 x*y 都替换为 p
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章