使用Cplex求解Pyomo模型时如何正确读取不可行结果
Pyomo调用Cplex关闭预求解后不可行场景的结果读取方案
关闭Cplex的presolve功能后,求解器判定模型不可行时不会生成任何可行赋值结果,Pyomo默认会对未收到求解器返回值的变量统一填充0,这是你读取到全0结果的根本原因。不可行场景下不存在有效变量解,你需要先做状态判定再决定是否读取变量值,具体操作如下:
- 首先,调用求解时关闭自动加载解的配置,先校验求解器返回状态
避免Pyomo不管求解结果是否有效都自动给变量赋值,示例代码如下:from pyomo.opt import SolverFactory, SolverStatus, TerminationCondition from pyomo.core import Var # 初始化求解器,关闭presolve solver = SolverFactory('cplex') solver.options['preind'] = 0 # 求解时添加load_solutions=False,不自动加载解到模型 solve_result = solver.solve(your_pyomo_model, load_solutions=False) # 仅当求解状态正常、且存在可行/最优解时,才加载并读取变量值 if solve_result.solver.status == SolverStatus.ok and solve_result.termination_condition == TerminationCondition.optimal: your_pyomo_model.solutions.load_from(solve_result) # 此处正常读取变量值即可 for v in your_pyomo_model.component_objects(ctype=Var, active=True): print(f"{v.name}: {v.value}") elif solve_result.termination_condition == TerminationCondition.infeasible: # 不可行场景下无有效变量值,直接做异常处理即可 print("模型不可行,不存在有效解") - 若需要排查不可行原因,可开启Cplex的冲突检测功能
你关闭presolve通常是为了保留原始模型的求解信息,不可行场景下可以通过Cplex自带的冲突定位功能找到问题约束,无需读取无意义的0值,配置示例:# 开启不可行冲突检测 solver.options['conflict'] = 1 solve_result = solver.solve(your_pyomo_model) if solve_result.termination_condition == TerminationCondition.infeasible: # 获取冲突约束集合 conflict = solver._solver_model.conflict() print(f"检测到{conflict.get_num()}条互相冲突的约束") # 遍历输出冲突约束信息 for i in range(conflict.get_num()): con_name = solver._solver_model.linear_constraints.get_names(conflict.get_constraint(i)) print(f"冲突约束:{con_name}")
注意:关闭presolve会大幅降低Cplex的求解效率,仅在需要排查求解过程、避免预求解修改模型结构的场景下使用该配置,常规求解不建议关闭。
内容的提问来源于stack exchange,提问作者Leonel Henríquez
相关产品推荐
相关产品推荐

