Java中用Gurobi收集混合整数线性规划多解的技术求助
如何用Gurobi Java API获取多个混合整数线性规划解
嘿,作为Java新手能写到这一步已经很棒了!要获取多个解,核心是让Gurobi在求解时保留多个可行解,然后遍历所有可用解逐个提取。我帮你一步步修改代码:
关键改动点
- 首先开启解池功能:在调用
model.optimize()之前,设置PoolSolutions参数,告诉Gurobi最多保留多少个解(比如设为10,你可以根据需求调整)。 - 遍历所有找到的解:Gurobi的解编号从0开始,到
SolCount-1结束,每个编号对应一个可行解,逐个提取变量值。 - 补全
CLSPSolutionCollection的构造函数:你现在的构造函数里没初始化solutions列表,直接add会报空指针,得补上。
修改后的完整代码
优化器部分代码
CLSPSolutionCollection collection = new CLSPSolutionCollection(); try { // 关键:开启解池,设置最多保留10个解(可按需调整) model.set(GRB.IntParam.PoolSolutions, 10); model.optimize(); // 检查是否找到可行解(不一定是最优,也可以考虑FEASIBLE状态) if (model.get(GRB.IntAttr.Status) == GRB.Status.OPTIMAL || model.get(GRB.IntAttr.Status) == GRB.Status.FEASIBLE) { int solutionCount = model.get(GRB.IntAttr.SolCount); System.out.println("找到 " + solutionCount + " 个可行解"); // 遍历每个解,从0到solutionCount-1 for (int solIdx = 0; solIdx < solutionCount; solIdx++) { CLSPSolution sol = new CLSPSolution(K, T); // 切换到当前解 model.set(GRB.IntParam.SolutionNumber, solIdx); // 获取当前解的目标值 sol.setObjectiveValue((int) model.get(GRB.DoubleAttr.ObjNVal)); // 提取所有决策变量的值 for (int k = 0; k < K; k++) { for (int t = 0; t < T; t++) { sol.setProductionQuantity(k, t, q[k][t].get(GRB.DoubleAttr.Xn)); sol.setSetupDecision(k, t, gamma[k][t].get(GRB.DoubleAttr.Xn)); sol.setOvertimeDecision(t, beta[t].get(GRB.DoubleAttr.Xn)); } } // 将当前解加入集合 collection.add(sol); } } // 资源释放 model.dispose(); env.dispose(); } catch (GRBException e) { e.printStackTrace(); } return collection;
补全CLSPSolutionCollection类
public class CLSPSolutionCollection { private ArrayList<CLSPSolution> solutions; // 补全构造函数,初始化列表 public CLSPSolutionCollection() { solutions = new ArrayList<>(); } public void add(CLSPSolution solution) { solutions.add(solution); } public int size() { return solutions.size(); } public CLSPSolution get(int index) { return solutions.get(index); } }
额外说明
- 解池参数调整:除了
PoolSolutions,还可以设置PoolSearchMode来控制Gurobi寻找多个解的策略(比如设为1会更积极地找不同的解),具体可以参考Gurobi官方文档。 - 解的状态:如果问题没有最优解但有可行解,
model.get(GRB.IntAttr.Status)会是GRB.Status.FEASIBLE,所以代码里加上这个判断能拿到更多可行解。 - 变量提取注意:每个解都要新建
CLSPSolution对象,不能复用同一个,否则会覆盖之前解的变量值。
内容的提问来源于stack exchange,提问作者Stijn




