在CPLEX Concert Technology中直接获取对偶规划的目标与约束
Absolutely! You don’t need to write to and read from a DUA file to get the dual problem’s objective function and constraints—you can build or extract the dual structure directly in your algorithm using CPLEX’s C++ API. Here’s how to do it:
Option 1: Manually Construct the Dual Model (Most Direct)
Since the dual problem’s structure is a direct transformation of the primal, you can build it by iterating over your primal model’s variables and constraints. This gives you full control and avoids file I/O entirely.
Example Code Snippet
Assume you have a primal LP model set up with an IloModel, IloObjective, and IloRangeArray of constraints:
// Primal model setup (example) IloEnv env; IloModel primalModel(env); IloNumVarArray primalVars(env, 3, 0, IloInfinity); // Non-negative primal variables IloRangeArray primalCons(env); primalCons.add(IloRange(env, -IloInfinity, primalVars[0] + 2*primalVars[1], 10)); // <=10 primalCons.add(IloRange(env, 5, 3*primalVars[0] + primalVars[1] + primalVars[2], IloInfinity)); // >=5 primalCons.add(IloRange(env, 7, primalVars[1] + 4*primalVars[2], 7)); // ==7 IloObjective primalObj = IloMinimize(env, 2*primalVars[0] + 3*primalVars[1] + primalVars[2]); primalModel.add(primalObj); primalModel.add(primalCons); // Build dual model IloModel dualModel(env); IloNumVarArray dualVars(env, primalCons.getSize()); // Step 1: Create dual variables (one per primal constraint) for (int i = 0; i < primalCons.getSize(); ++i) { IloRange con = primalCons[i]; if (con.getSense() == IloRange::LessEqual) { dualVars[i] = IloNumVar(env, 0, IloInfinity); // Dual var >=0 for primal <= constraints } else if (con.getSense() == IloRange::GreaterEqual) { dualVars[i] = IloNumVar(env, -IloInfinity, 0); // Dual var <=0 for primal >= constraints } else { dualVars[i] = IloNumVar(env, -IloInfinity, IloInfinity); // Free dual var for primal == constraints } } // Step 2: Define dual objective function IloExpr dualObjExpr(env); for (int i = 0; i < primalCons.getSize(); ++i) { // Use primal constraint's RHS (UB works for all cases since lb=ub for equality) dualObjExpr += primalCons[i].getUB() * dualVars[i]; } // Flip objective sense: primal Min -> dual Max; primal Max -> dual Min IloObjective dualObj = (primalObj.getSense() == IloObjective::Minimize) ? IloMaximize(env, dualObjExpr) : IloMinimize(env, dualObjExpr); dualModel.add(dualObj); dualObjExpr.end(); // Step 3: Create dual constraints (one per primal variable) for (int j = 0; j < primalVars.getSize(); ++j) { IloExpr dualConExpr(env); for (int i = 0; i < primalCons.getSize(); ++i) { // Use primal constraint's coefficient for the j-th variable dualConExpr += primalCons[i].getLinearExpr()[primalVars[j]] * dualVars[i]; } IloRange dualCon; // Match constraint sense to primal variable type if (primalVars[j].getLB() == 0 && primalVars[j].getUB() == IloInfinity) { // Primal var >=0 -> dual constraint >= primal objective coefficient dualCon = IloRange(env, primalObj.getLinearExpr()[primalVars[j]], IloInfinity, dualConExpr); } else if (primalVars[j].getLB() == -IloInfinity && primalVars[j].getUB() == 0) { // Primal var <=0 -> dual constraint <= primal objective coefficient dualCon = IloRange(env, -IloInfinity, primalObj.getLinearExpr()[primalVars[j]], dualConExpr); } else { // Primal free var -> dual constraint == primal objective coefficient dualCon = IloRange(env, primalObj.getLinearExpr()[primalVars[j]], primalObj.getLinearExpr()[primalVars[j]], dualConExpr); } dualModel.add(dualCon); dualConExpr.end(); } // Now you can access the dual model's components directly // Example: Print dual objective std::cout << "Dual Objective: " << dualObj << std::endl; // Example: Iterate over dual constraints IloRangeArray dualCons(dualModel.getRanges()); for (int i = 0; i < dualCons.getSize(); ++i) { std::cout << "Dual Constraint " << i << ": " << dualCons[i] << std::endl; }
Option 2: Export Primal Model to Memory (Alternative)
If you don’t want to manually construct the dual, you can export the primal model to an in-memory stream as LP format, then parse the stream to generate the dual. This avoids writing to disk, but requires parsing LP syntax (which can be error-prone for complex models).
For example, use IloOStream with a std::stringstream:
std::stringstream ss; IloOStream os(ss); cplex.exportModel(os); std::string lpContent = ss.str(); // Parse lpContent to derive dual structure (implementation depends on your parsing logic)
Key Note About Preprocessing::Dual
The parameter cplex.setParam(IloCplex::Param::Preprocessing::Dual, 1) tells CPLEX to solve the dual problem instead of the primal, but this only gives you the dual solution values—not the dual model’s structure. You don’t need this parameter for accessing the dual’s objective and constraints.
内容的提问来源于stack exchange,提问作者rasul

