C++调用CPLEX API建模结果与CPLEX Studio不一致求排查
CPLEX模型转C++ API实现报错排查
问题描述
原本在IBM ILOG CPLEX Optimization Studio中构建的优化模型可得到目标值2.429,但使用C++ API实现后运行提示“Optimization failed”,无法找到可行解。
原CPLEX模型代码(修正笔误后)
range i = 1..3; range j = 1..3; dvar int+ x[i]; dvar float+ y[j]; maximize -3*x[1] - 2*x[2] + 4*x[3] + y[1] - 3*y[2] - 2*y[3]; subject to { c1: -2*x[1] + 4*x[2] - x[3] + 3*y[1] - 2*y[2] + 3*y[3] <= -4; c2: -x[1] - 2*x[2] + 4*x[3] + 2*y[1] + 4*y[2] - 5*y[3] <= 2; c3: forall(i in i) x[i] <= 6; }
原C++代码中的问题
- 头文件包含错误:
#include "ilcplex//ilocplex.h";存在路径双斜杠、双引号使用不当、多余分号的问题,正确写法应为#include <ilcplex/ilocplex.h>。 - 缺乏求解日志输出:未开启CPLEX的求解日志,无法判断模型是不可行还是无界,难以定位问题。
- 未释放环境资源:代码末尾未调用
env.end();,虽不影响求解,但属于不良编程习惯。
另外,若Studio中能得到可行解但C代码报错,大概率是**Studio模型与提供的C代码存在不一致**,或求解器参数未正确设置。
修正后的C++代码
#include <iostream> #include <ilcplex/ilocplex.h> using namespace std; int main() { IloEnv env; try { IloModel Model(env); // 定义变量,直接设置x的上限为6,与原模型约束一致 IloIntVar x1(env, 0, 6, "x1"); IloIntVar x2(env, 0, 6, "x2"); IloIntVar x3(env, 0, 6, "x3"); IloNumVar y1(env, 0, IloInfinity, ILOFLOAT, "y1"); IloNumVar y2(env, 0, IloInfinity, ILOFLOAT, "y2"); IloNumVar y3(env, 0, IloInfinity, ILOFLOAT, "y3"); // 添加目标函数 Model.add(IloMaximize(env, -3 * x1 - 2 * x2 + 4 * x3 + y1 - 3 * y2 - 2 * y3)); // 添加约束 Model.add(-2 * x1 + 4 * x2 - x3 + 3 * y1 - 2 * y2 + 3 * y3 <= -4); Model.add(-x1 - 2 * x2 + 4 * x3 + 2 * y1 + 4 * y2 - 5 * y3 <= 2); Model.add(x1 <= 6); Model.add(x2 <= 6); Model.add(x3 <= 6); IloCplex cplex(Model); // 开启求解日志,便于排查问题 cplex.setOut(env.getOut()); if (!cplex.solve()) { env.error() << "Optimization failed" << endl; // 判断模型状态 if (cplex.getStatus() == IloCplex::Infeasible) { env.error() << "模型不可行" << endl; } else if (cplex.getStatus() == IloCplex::Unbounded) { env.error() << "模型无界" << endl; } throw(-1); } double obj = cplex.getObjValue(); cout << "\n\n\t objective value: " << obj << endl; cout << "x1 = " << cplex.getValue(x1) << endl; cout << "x2 = " << cplex.getValue(x2) << endl; cout << "x3 = " << cplex.getValue(x3) << endl; cout << "y1 = " << cplex.getValue(y1) << endl; cout << "y2 = " << cplex.getValue(y2) << endl; cout << "y3 = " << cplex.getValue(y3) << endl; } catch (IloException& e) { cerr << "CPLEX异常: " << e.getMessage() << endl; throw; } catch (...) { cerr << "未知异常" << endl; throw; } // 释放环境资源 env.end(); return 0; }
排查建议
- 对比模型一致性:仔细检查目标函数系数、约束条件的符号和系数,确保Studio模型与C++代码完全一致(比如原Studio模型是否存在约束符号笔误)。
- 查看求解日志:通过
cplex.setOut(env.getOut());开启日志,根据日志判断模型状态:- 若模型不可行:说明约束之间存在冲突,需重新检查约束逻辑。
- 若模型无界:说明目标函数可以无限增大/减小,需添加额外约束限制变量范围。
- 验证变量类型:确保整数变量和浮点变量的定义与原模型一致,避免类型错误导致求解异常。
内容的提问来源于stack exchange,提问作者arc_rudnevs
相关产品推荐
相关产品推荐

