C#调用iLog Cplex 输出不收敛的约束
需求
用C#调用 iLog Cplex 的API 求解规划问题,如果模型不收敛(infeasible),需要知道是哪里出了问题,根据IBM管网的Java示例,写一个C#版本。
步骤
首先,在构造好模型后需要保存模型文件(*.lp)
cplex.ExportModel("optmodel.lp");
然后,判断求解是否成功,如果不成功则执行下文的逻辑
if (cplex.Solve())
{...
}
else
{//下方代码
}
导入optmodel.lp,这样才能获取到矩阵,遍历约束判断是否有冲突,打印冲突的约束,需要时可以打开 optmodel.lp 文件,对照分析约束不满足的原因。
cplex.ImportModel("optmodel.lp");
var matrixEnum = cplex.GetLPMatrixEnumerator();
matrixEnum.MoveNext();
var lp = (ILPMatrix)matrixEnum.Current;
Console.WriteLine($"Solution status = {cplex.GetStatus()}");
Console.WriteLine("Model Infeasible, Calling CONFLICT REFINER");
var rng = lp.Ranges;
int numVars = 0;//calculate the number of non-boolean variables
for (int c1 = 0; c1 < lp.NumVars.Length; c1++)if (lp.NumVars[c1].Type != NumVarType.Bool)numVars++;
//find the number of SOSs in the model
int numSOS = cplex.NSOSs;
Console.WriteLine("Number of SOSs=" + numSOS);int numConstraints = rng.Length + 2 * numVars + numSOS;
var constraints = new IConstraint[numConstraints];
for (int c1 = 0; c1 < rng.Length; c1++)
{constraints[c1] = rng[c1];
}
int numVarCounter = 0;
//add variable bounds to the constraints array
for (int c1 = 0; c1 < lp.NumVars.Length; c1++)
{if (lp.NumVars[c1].Type != NumVarType.Bool){constraints[rng.Length + 2 * numVarCounter] = cplex.AddLe(lp.NumVars[c1].LB, lp.NumVars[c1]);constraints[rng.Length + 2 * numVarCounter].Name = lp.NumVars[c1].ToString() + "_LB";constraints[rng.Length + 2 * numVarCounter + 1] = cplex.AddGe(lp.NumVars[c1].UB, lp.NumVars[c1]);constraints[rng.Length + 2 * numVarCounter + 1].Name = lp.NumVars[c1].ToString() + "_UB";numVarCounter++;}
}
//add SOSs to the constraints array
if (numSOS > 0)
{int s1Counter = 0;var s1 = cplex.GetSOS1Enumerator();while (s1.MoveNext()){var cur = (ISOS1)s1.Current;Console.WriteLine(cur);constraints[rng.Length + numVars * 2 + s1Counter] = cur;s1Counter++;}int s2Counter = 0;var s2 = cplex.GetSOS2Enumerator();while (s2.MoveNext()){var cur = (ISOS2)s2.Current;Console.WriteLine(cur);constraints[rng.Length + numVars * 2 + s1Counter + s2Counter] = cur;s2Counter++;}
}
double[] prefs = new double[constraints.Length];
for (int c1 = 0; c1 < constraints.Length; c1++)
{//Console.WriteLine(constraints[c1]);prefs[c1] = 1.0;//change it per your requirements
}
if (cplex.RefineConflict(constraints, prefs))
{Console.WriteLine("Conflict Refinement process finished: Printing Conflicts");var conflict = cplex.GetConflict(constraints);int numConConflicts = 0;int numBoundConflicts = 0;int numSOSConflicts = 0;for (int c2 = 0; c2 < constraints.Length; c2++){if (conflict[c2] == Cplex.ConflictStatus.Member){Console.WriteLine(" Proved : " + constraints[c2]);if (c2 < rng.Length)numConConflicts++;else if (c2 < rng.Length + 2 * numVars)numBoundConflicts++;elsenumSOSConflicts++;}else if (conflict[c2] == Cplex.ConflictStatus.PossibleMember){Console.WriteLine(" Possible : " + constraints[c2]);if (c2 < rng.Length)numConConflicts++;else if (c2 < rng.Length + 2 * numVars)numBoundConflicts++;elsenumSOSConflicts++;}}Console.WriteLine("Conflict Summary:");Console.WriteLine(" Constraint conflicts = " + numConConflicts);Console.WriteLine(" Variable Bound conflicts = " + numBoundConflicts);Console.WriteLine(" SOS conflicts = " + numSOSConflicts);
}
else
{Console.WriteLine("Conflict could not be refined");
}
还可以进一步打印 Cplex 给出的建议,不过这部分我没用
Console.WriteLine("Calling FEASOPT");
// cplex.SetParam(Cplex.IntParam.FeasOptMode, 0);//change per feasopt requirements
// Relax contraints only, modify if variable bound relaxation is required
double[] lb_pref = new double[rng.Length];
double[] ub_pref = new double[rng.Length];
for (int c1 = 0; c1 < rng.Length; c1++)
{lb_pref[c1] = 1.0;//change it per your requirementsub_pref[c1] = 1.0;//change it per your requirements
}
if (cplex.FeasOpt(rng, lb_pref, ub_pref))
{Console.WriteLine("Finished Feasopt");double[] infeas = cplex.GetInfeasibilities(rng);//Print bound changesConsole.WriteLine("Suggested Bound changes:");for (int c3 = 0; c3 < infeas.Length; c3++)if (infeas[c3] != 0)Console.WriteLine(" " + rng[c3] + " : Change=" + infeas[c3]);Console.WriteLine("Relaxed Model's obj value=" + cplex.ObjValue);Console.WriteLine("Relaxed Model's solution status:" + cplex.GetCplexStatus());double[] x = cplex.GetValues(lp);for (int j = 0; j < x.Length; ++j)Console.WriteLine("Relaxed Model's Variable Name:" + lp.NumVars[j].Name + "; Value = " + x[j]);
}
else
{Console.WriteLine("FeasOpt failed- Could not repair infeasibilities");
}
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
