读取MPS优化模型并使用or-tools求解时遇到的问题
OR-Tools PDLP求解器处理MPS文件时的不可行性与解错误问题分析
问题背景
某MPS文件可通过Gurobi正常求解,确认问题本身可行。但通过自行实现的MPS解析器导入OR-Tools的PDLP求解器后,求解器判定问题不可行;移除等式约束的创建逻辑后,问题变为可行,但求解得到的最优解与Gurobi结果不符。
核心原因分析
1. 自定义MPS解析器的细节遗漏
MPS格式包含诸多容易被忽略的细节,自定义解析器若未完全覆盖,会导致问题模型导入错误:
- 未处理全量变量边界类型:当前解析器仅处理
LO/UP/FX类型的边界,未处理FR(自由变量,上下界为正负无穷)、MI(负无穷到0)等类型,导致这类变量被错误设置为默认的[0, +inf]边界,直接破坏约束可行性。 - RHS段的多条目处理缺失:部分MPS文件中,同一个约束的RHS值可能分散在多行(对应不同的RHS名称),当前解析器会直接覆盖之前的RHS值,若原问题存在多RHS叠加逻辑,会导致RHS值错误。
- 约束表达式方向错误:若解析时误将约束系数的符号反转,会导致约束逻辑与原问题完全相反(例如原问题为
sum(a_ij x_j) = b,解析后变为sum(-a_ij x_j) = b),直接引发不可行性。 - INTORG/INTEND的处理不当:虽然PDLP是连续求解器,但跳过整数变量标记后,若原问题包含整数约束,PDLP求解的是松弛解,必然与Gurobi的整数最优解存在差异。
2. PDLP求解器参数设置问题
PDLP作为内点法求解器,默认参数的可行性容差可能偏严格,对部分数值精度较高的问题,会误判为不可行;同时默认的预处理策略可能未适配当前问题,导致求解结果偏差。
3. 等式约束的实现逻辑验证
当前等式约束通过solver.RowConstraint(rhs, rhs, constr_name)实现,逻辑上是正确的(要求约束表达式严格等于rhs),但需确认:约束表达式的构建是否与原MPS一致(即sum(coeff * var)是否等于原问题的左边项)。
解决方案
1. 替换自定义解析器为OR-Tools内置MPS加载功能
OR-Tools原生支持MPS文件加载,可彻底避免自定义解析的错误,代码示例:
from ortools.linear_solver import pywraplp file_path = "237794.mps" # 创建PDLP求解器 solver = pywraplp.Solver.CreateSolver('PDLP') # 加载MPS文件 if not solver.LoadModel(file_path): print("MPS文件加载失败") else: # 求解 status = solver.Solve() if status == pywraplp.Solver.OPTIMAL: print(f"最优目标值: {solver.Objective().Value()}") elif status == pywraplp.Solver.INFEASIBLE: print("问题不可行") elif status == pywraplp.Solver.UNBOUNDED: print("问题无界") else: print("求解器未找到最优解")
若此代码能正常求解并得到与Gurobi一致的结果,说明问题出在自定义解析器上;若仍存在问题,则需调整PDLP参数。
2. 修复自定义MPS解析器的缺陷
- 补充全量边界类型处理:
# 在BOUNDS段处理中添加以下分支 elif bound_type == 'FR': variables[var_name]['lb'] = -float('inf') variables[var_name]['ub'] = float('inf') elif bound_type == 'MI': variables[var_name]['lb'] = -float('inf') variables[var_name]['ub'] = 0.0 elif bound_type == 'PL': variables[var_name]['lb'] = 0.0 variables[var_name]['ub'] = float('inf') - 验证RHS与约束系数的正确性:将Gurobi加载MPS后导出的约束系数、RHS值与自定义解析器的结果对比,确认每一项都完全一致。
- 整数变量的处理:若原问题包含整数约束,PDLP作为连续求解器无法处理,需切换至OR-Tools的MIP求解器(如CBC),或明确松弛整数约束。
3. 调整PDLP求解器参数
通过设置求解器特定参数,放宽容差或调整预处理策略:
# 设置可行性容差与对偶容差,开启预处理 solver.SetSolverSpecificParametersAsString(""" primal_feasibility_tolerance: 1e-6 dual_feasibility_tolerance: 1e-6 enable_preprocessing: true """)
参数可根据问题的数值特性进一步调整。
内容的提问来源于stack exchange,提问作者Sia EA
相关产品推荐
相关产品推荐

