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++;
			else
				numSOSConflicts++;

		}
		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++;
			else
				numSOSConflicts++;
		}
	}
	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 requirements
	ub_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 changes
	Console.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");
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值