CPLEX C++ IloModel GetClone后新增约束求解结果异常问题
CPLEX C++接口克隆模型后新增约束求解结果异常
问题复现代码
IloEnv env; IloModel model(env); IloNumVar X(env, 0, IloInfinity, ILOFLOAT); IloNumVar Y(env, 0, IloInfinity, ILOFLOAT); model.add(X + Y <= 5); model.add(IloMaximize(env, 2*X + Y)); IloCplex mycplex(env); mycplex.extract(model); IloBool feasible = mycplex.solve(); if(feasible == IloTrue){ cout << mycplex.getObjValue() << "\n"; // 输出目标值10,结果符合预期 } IloModel model1 = model.getClone(env); model1.add(X <= 4); IloCplex mycplex1(env); mycplex1.extract(model1); IloBool feasible1 = mycplex1.solve(); if(feasible1 == IloTrue){ cout << mycplex1.getObjValue() << "\n"; // 预期目标值9,实际仍输出10 }
问题现象
初始模型配置约束X+Y<=5,目标函数为最大化2*X+Y,首次求解得到目标值10,符合预期。调用model.getClone(env)克隆得到新模型model1后,为model1新增X<=4的约束,重新提取模型求解,理论最优目标值应为9,实际求解输出仍为10。
根本原因
IloModel::getClone(env)执行的是模型的深度复制,会为克隆后的新模型生成一套完全独立的建模对象(包括变量、约束、目标函数),这些克隆生成的对象和代码中提前定义的原变量X/Y是完全独立、没有绑定关系的不同对象。
你给model1添加X<=4约束时,引用的是原模型下的旧变量X,这个变量不属于克隆模型model1的内部变量集合。CPLEX提取模型时如果发现约束引用了未被加入模型的变量,会自动将该变量作为独立新变量加入求解模型,但这个旧X既不出现在克隆模型的目标函数里,也不出现在其他原有约束中,X<=4的约束只会限制这个无关变量的取值,完全不会影响克隆模型内部原有变量副本的可行域,相当于新增的约束根本没有对原问题产生任何限制,因此求解结果和原模型完全一致,仍输出目标值10。
修正方法
- 如果需要基于克隆后的模型修改约束,必须先建立原变量和克隆后变量的映射关系,拿到克隆模型内部对应的变量副本后,再基于该副本构建新约束加入模型。
- 对于逻辑不复杂的场景,更稳妥的方式是直接在同一个环境下新建模型,重新按需添加变量、约束和目标函数,避免深度复制带来的对象不匹配问题。
内容的提问来源于stack exchange,提问作者m6rco
相关产品推荐
相关产品推荐

