如何通过Python调用CPLEX获取无界问题的极射线?
如何获取CPLEX无界问题的极射线?
问题背景
尝试用Python API运行一个CPLEX无界问题,示例代码如下:
import docplex.mp.model as cpx from docplex.util.status import JobSolveStatus my_bdrex_SP=cpx.Model('My Benders Model Sub Problem') # 添加变量 v_1=my_bdrex_SP.continuous_var(name='v_1', lb=0) v_2=my_bdrex_SP.continuous_var(name='v_2', lb=0) # 定义目标函数 objective_SP=0*v_1-6*v_2 # 添加约束 my_bdrex_SP.add_constraint(4*v_1+2*v_2>=2) my_bdrex_SP.add_constraint(-2*v_1+3*v_2>=-3) my_bdrex_SP.add_constraint(3*v_1-1*v_2>=1) # 求解问题 my_bdrex_SP.minimize(objective_SP) my_bdrex_SP.solve() my_bdrex_SP.print_solution() print(my_bdrex_SP.get_solve_status())
该问题实际为无界问题,但CPLEX返回状态为unbounded or infeasible。为获取可行性割平面需要提取极射线,使用以下代码时出现错误:
ray = my_bdrex_SP.get_engine().get_cplex().solution.advanced.get_ray()
错误信息:
cplex.exceptions.errors.CplexSolverError: CPLEX Error 1217: No solution exists.
解决方案
要正确获取无界问题的极射线,需遵循以下步骤:
1. 提前设置CPLEX参数启用射线计算
在求解前,设置CPLEX的advance参数为1,确保求解器在检测到无界时自动计算并存储极射线:
my_bdrex_SP.parameters.advance.set(1)
2. 检查求解状态,明确问题类型
求解后先判断状态,避免在不可行问题上尝试获取射线(不可行问题不存在极射线):
status = my_bdrex_SP.get_solve_status() if status == JobSolveStatus.UNBOUNDED: cplex_instance = my_bdrex_SP.get_engine().get_cplex() ray = cplex_instance.solution.advanced.get_ray() print("极射线:", ray) elif status == JobSolveStatus.INFEASIBLE: print("问题不可行,无射线可获取") else: print("问题有可行解,无需射线")
3. 完整修改后的代码
整合上述步骤的完整代码如下:
import docplex.mp.model as cpx from docplex.util.status import JobSolveStatus my_bdrex_SP=cpx.Model('My Benders Model Sub Problem') # 添加变量 v_1=my_bdrex_SP.continuous_var(name='v_1', lb=0) v_2=my_bdrex_SP.continuous_var(name='v_2', lb=0) # 定义目标函数 objective_SP=0*v_1-6*v_2 # 添加约束 my_bdrex_SP.add_constraint(4*v_1+2*v_2>=2) my_bdrex_SP.add_constraint(-2*v_1+3*v_2>=-3) my_bdrex_SP.add_constraint(3*v_1-1*v_2>=1) # 设置参数启用射线计算 my_bdrex_SP.parameters.advance.set(1) # 求解问题 my_bdrex_SP.minimize(objective_SP) my_bdrex_SP.solve() # 检查状态并处理 status = my_bdrex_SP.get_solve_status() print("求解状态:", status) if status == JobSolveStatus.UNBOUNDED: cplex_instance = my_bdrex_SP.get_engine().get_cplex() ray = cplex_instance.solution.advanced.get_ray() print("极射线结果:", ray) else: my_bdrex_SP.print_solution()
说明
advance参数设为1是关键,它让CPLEX在检测到无界问题时主动计算极射线,否则get_ray()会因无存储的射线而报错。- 必须先明确求解状态,原返回的
unbounded or infeasible是模糊状态,需区分无界和不可行两种情况。
内容的提问来源于stack exchange,提问作者Mohammad Samiullah
相关产品推荐
相关产品推荐

