You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于CPLEX与C++建模:如何线性化两个连续变量的乘积?

线性化[0,1]连续变量乘积x*y的方法(附CPLEX/C++实现)

我之前用CPLEX做数学建模时刚好处理过完全相同的场景,针对你这种两个0 ≤ x ≤ 1、0 ≤ y ≤ 1的连续变量乘积x*y,最直接且高效的线性化方式是引入辅助变量,再添加一组线性约束来等价替代乘积项,下面给你详细拆解:

核心思路:引入辅助变量z = x*y

我们可以定义一个新的连续变量z,让它等价于x*y,然后通过以下4个线性约束来确保z和x*y的行为完全一致:

  • z ≤ x:保证z不会超过x的取值(因为y≤1,所以x*y ≤x)
  • z ≤ y:同理,保证z不会超过y的取值(x≤1,所以x*y ≤y)
  • z ≥ x + y - 1:这是关键约束,当x和y都接近1时,它能保证z不会过小(比如x=0.9,y=0.9,那么z≥0.8,而x*y=0.81,刚好落在约束范围内)
  • 0 ≤ z ≤ 1:直接限定辅助变量的范围,和x、y保持一致

这组约束的优势在于,它完全刻画了x*y在[0,1]×[0,1]区间上的凸包,不会引入额外的松弛,CPLEX求解时能得到和原问题一致的最优解。

CPLEX/C++代码实现示例

假设你已经初始化了CPLEX的环境和模型,下面是具体的代码片段:

#include <ilcplex/ilocplex.h>

int main() {
    IloEnv env;
    try {
        IloModel model(env);

        // 定义原始连续变量x和y,范围[0,1]
        IloNumVar x(env, 0.0, 1.0, ILOFLOAT, "x");
        IloNumVar y(env, 0.0, 1.0, ILOFLOAT, "y");

        // 引入辅助变量z,用于替代x*y,范围[0,1]
        IloNumVar z(env, 0.0, 1.0, ILOFLOAT, "z");

        // 添加线性化约束
        model.add(z <= x);
        model.add(z <= y);
        model.add(z >= x + y - 1.0);

        // 替换目标函数中的x*y为z(示例:假设目标是最大化x*y + 2x + 3y)
        IloObjective obj(env, z + 2*x + 3*y, IloObjective::Maximize);
        model.add(obj);

        // 求解模型(省略求解和结果输出的代码)
        IloCplex cplex(model);
        if (cplex.solve()) {
            std::cout << "最优解:x=" << cplex.getValue(x) 
                      << ", y=" << cplex.getValue(y) 
                      << ", z=x*y=" << cplex.getValue(z) << std::endl;
        }
    } catch (IloException& e) {
        std::cerr << "CPLEX异常:" << e << std::endl;
    }
    env.end();
    return 0;
}

额外注意事项

  • 这个方法仅适用于x和y都在[0,1]区间的场景,如果变量范围更大,需要调整约束(比如当x∈[a,b],y∈[c,d]时,约束形式会更复杂)
  • 如果你要处理多个变量乘积的情况,需要逐个拆解,或者考虑其他线性化技巧,但两个变量的场景用上面的方法足够高效

内容的提问来源于stack exchange,提问作者Ernando Gomes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 10:46:51