如何在ALGLIB线性规划(C#)中约束变量为整数?
解决整数线性规划约束问题
一、在ALGLIB中添加整数变量约束
ALGLIB的MINLP模块支持整数变量约束,你可以通过minlpsetintvar方法将每个变量标记为整数类型。修改你的代码,在初始化state后添加变量类型约束,同时修正原代码中al数组长度错误(约束矩阵a为7行,对应al需7个元素):
double[] c = new double[] { 1, 2, 3, 1, 2, 3 }; double[,] a = new double[,] { { 1, 2, 3, 1, 2, 3 }, { 1, 0, 0, 0, 0, 0 }, { 0, 1, 0, 0, 0, 0 }, { 0, 0, 1, 0, 0, 0 }, { 0, 0, 0, 1, 0, 0 }, { 0, 0, 0, 0, 1, 0 }, { 0, 0, 0, 0, 0, 1 } }; double[] lowerBounds = new double[] { 1, 1, 1, 1, 1, 1 }; double[] upperBounds = new double[] { double.PositiveInfinity, double.PositiveInfinity, double.PositiveInfinity, double.PositiveInfinity, double.PositiveInfinity, double.PositiveInfinity }; double[] s = new double[] { 1, 1, 1, 1, 1, 1 }; double[] x; double[] al = new double[] { 16, 1, 1, 1, 1, 1, 1 }; double[] au = new double[] { double.PositiveInfinity, double.PositiveInfinity, double.PositiveInfinity, double.PositiveInfinity, double.PositiveInfinity, double.PositiveInfinity, double.PositiveInfinity }; alglib.minlpstate state; alglib.minlpreport rep; alglib.minlpcreate(6, out state); alglib.minlpsetcost(state, c); alglib.minlpsetbc(state, lowerBounds, upperBounds); alglib.minlpsetlc2dense(state, a, al, au, 7); // 标记所有6个变量为整数类型 for (int i = 0; i < 6; i++) { alglib.minlpsetintvar(state, i); } alglib.minlpsetscale(state, s); alglib.minlpoptimize(state); alglib.minlpresults(state, out x, out rep); System.Diagnostics.Debug.WriteLine("{0}", alglib.ap.format(x, 3));
二、替代方案:使用Google OR-Tools求解整数线性规划
如果ALGLIB的MINLP求解效果不佳,推荐使用Google OR-Tools,它对整数线性规划(ILP)支持更完善,且免费开源。
首先通过NuGet安装Google.OrTools包,然后使用以下代码实现你的问题:
using Google.OrTools.LinearSolver; class Program { static void Main() { // 创建整数规划求解器 Solver solver = Solver.CreateSolver("SCIP"); if (solver == null) return; // 定义整数变量,下界为1,无上界 Variable A = solver.MakeIntVar(1.0, double.PositiveInfinity, "A"); Variable B = solver.MakeIntVar(1.0, double.PositiveInfinity, "B"); Variable C = solver.MakeIntVar(1.0, double.PositiveInfinity, "C"); Variable D = solver.MakeIntVar(1.0, double.PositiveInfinity, "D"); Variable E = solver.MakeIntVar(1.0, double.PositiveInfinity, "E"); Variable F = solver.MakeIntVar(1.0, double.PositiveInfinity, "F"); // 添加约束:A+2B+3C+E+2D+3F >=16 Constraint constraint = solver.MakeConstraint(16.0, double.PositiveInfinity); constraint.SetCoefficient(A, 1); constraint.SetCoefficient(B, 2); constraint.SetCoefficient(C, 3); constraint.SetCoefficient(D, 2); constraint.SetCoefficient(E, 1); constraint.SetCoefficient(F, 3); // 定义目标函数:最小化 A+2B+3C+D+2E+3F Objective objective = solver.Objective(); objective.SetCoefficient(A, 1); objective.SetCoefficient(B, 2); objective.SetCoefficient(C, 3); objective.SetCoefficient(D, 1); objective.SetCoefficient(E, 2); objective.SetCoefficient(F, 3); objective.SetMinimization(); // 求解并输出结果 Solver.ResultStatus resultStatus = solver.Solve(); if (resultStatus == Solver.ResultStatus.OPTIMAL) { System.Diagnostics.Debug.WriteLine($"最优解:"); System.Diagnostics.Debug.WriteLine($"A = {A.SolutionValue()}"); System.Diagnostics.Debug.WriteLine($"B = {B.SolutionValue()}"); System.Diagnostics.Debug.WriteLine($"C = {C.SolutionValue()}"); System.Diagnostics.Debug.WriteLine($"D = {D.SolutionValue()}"); System.Diagnostics.Debug.WriteLine($"E = {E.SolutionValue()}"); System.Diagnostics.Debug.WriteLine($"F = {F.SolutionValue()}"); System.Diagnostics.Debug.WriteLine($"目标函数值:{solver.Objective().Value()}"); // 验证约束 double sum = A.SolutionValue() + 2 * B.SolutionValue() + 3 * C.SolutionValue() + E.SolutionValue() + 2 * D.SolutionValue() + 3 * F.SolutionValue(); System.Diagnostics.Debug.WriteLine($"约束值验证:{sum} >=16 → {sum >=16}"); } else { System.Diagnostics.Debug.WriteLine("未找到合法最优解"); } } }
该代码会直接输出满足所有整数约束的最优解,无需手动取整,且保证约束条件成立。
为什么直接取整不可行?
连续线性规划的最优解是松弛了整数约束后的结果,直接取整可能破坏约束条件(如你示例中的情况),同时也不一定是整数规划的最优解。必须通过专门的整数规划求解算法(如分支定界、割平面法)来找到合法的整数解。
内容的提问来源于stack exchange,提问作者Henry Yu
相关产品推荐
相关产品推荐

