为已知解决方案添加约束会导致超出范围的异常

gra*_*aph 2 linear-programming solver ms-solver-foundation

我有一个最大化EE + FF的线性优化目标,其中EE和FF各自由一些C和D组成.

用我编写的代码,我可以找到求解器:

EE_quantity: 0, FF_quantity: 7
Run Code Online (Sandbox Code Playgroud)

...但我知道还有另一种解决方案:

EE_quantity: 1, FF_quantity: 6
Run Code Online (Sandbox Code Playgroud)

为了验证其他有效解决方案的用户输入,我为EE和FF添加了约束.所以我EE_quantity == 0, FF_quantity == 7在下面的代码中添加了一个可运行的例子:

SolverContext c2 = SolverContext.GetContext();
Model m2 = c2.CreateModel();
p.elements = elements_multilevel_productmix();

Decision C_quantity = new Decision(Domain.IntegerNonnegative, "C_quantity"); 
Decision D_quantity = new Decision(Domain.IntegerNonnegative, "D_quantity");
Decision EE_quantity = new Decision(Domain.IntegerNonnegative, "EE_quantity");
Decision FF_quantity = new Decision(Domain.IntegerNonnegative, "FF_quantity");
m2.AddDecisions(C_quantity, D_quantity, EE_quantity, FF_quantity);

m2.AddConstraints("production",
    6 * C_quantity + 4 * D_quantity <= 100,
    1 * C_quantity + 2 * D_quantity <= 200,
    2 * EE_quantity + 1 * FF_quantity <= C_quantity,
    1 * EE_quantity + 2 * FF_quantity <= D_quantity,
    EE_quantity == 0,
    FF_quantity == 7
);
m2.AddGoal("fixed_EE_FF", GoalKind.Maximize, "EE_quantity + FF_quantity");

Solution sol = c2.Solve(new SimplexDirective());             
foreach (var item in sol.Decisions)
{
    System.Diagnostics.Debug.WriteLine(
        item.Name + ": " + item.GetDouble().ToString()
    );
}
Run Code Online (Sandbox Code Playgroud)

似乎Solver Foundation真的不喜欢这种特定的组合.使用EE_quantity == 1, FF_quantity == 6很好,就像使用EE_quantity == 0FF_quantity == 7.但是使用两者,并且其中一个为零,则抛出异常:

指数数组的边界之外.

引擎盖下发生了什么事,这里?我如何指定我想为特定问题找到"所有"解决方案?

小智 8

(注意:没有新版本的Solver Foundation即将推出 - 它基本上被微软放弃了.)

堆栈跟踪表明这是单纯形解算器的预解算例程中的错误.不幸的是,SimplexDirective没有办法禁用presolve(不像InteriorPointDirective).因此,解决此问题的方法是以不同方式指定固定变量.

删除设置的最后两个约束,EE_quantityFF_quantity在创建Decision对象时分别将上限和下限分别设置为0和7.这相当于您想表达的内容,但似乎避免了MSF错误:

Decision EE_quantity = new Decision(Domain.IntegerRange(0, 0), "EE_quantity");
Decision FF_quantity = new Decision(Domain.IntegerRange(7, 7), "FF_quantity");
Run Code Online (Sandbox Code Playgroud)

与许多混合整数解算器一样,MSF单纯形求解器仅返回最优解.如果希望MSF返回所有解,请更改为约束编程解算器(ConstraintProgrammingDirective).如果您查看文档,Solution.GetNext()请了解如何执行此操作.

当然,CP解算器不能保证立即产生全局最优解决方案.但如果你足够长时间地遍历解决方案,你就会到达那里.