PuLP求解线性系统最值结果不符问题排查与实现优化
问题根因
代码结果和参考答案不符的核心错误是遗漏了题目明确要求的关键约束:A + B = 1。
现有代码仅添加了线性组合M三个分量的取值范围约束,没有限制参数A、B的和为1,相当于在无参数和限制的全二维可行域内求解极值,得到的结果自然不符合题目要求:你跑出的最大值解A≈3.57、B≈-1.43,两者之和约为2.14;最小值解A=B=0,两者之和为0,均不满足题目的参数规则。
我们可以先手动化简目标函数验证参考答案的正确性:
展开点积计算目标函数r的系数:
- A的总系数:
0.1*0.6 + 0.2*0.2 + 0.1*0.2 = 0.12 - B的总系数:
0.1*0.8 + 0.2*(-0.2) + 0.1*0.4 = 0.08
即r = 0.12A + 0.08B,结合A+B=1的约束代入B=1-A,可得r = 0.08 + 0.04A,r的取值和A正相关:最大值对应A的最大可行取值,最小值对应A的最小可行取值,和题目给出的参考答案完全匹配。
修正后的可运行代码
from pulp import LpProblem, LpMaximize, LpMinimize, LpVariable, value # 求解r的最大值 max_problem = LpProblem("max_r", LpMaximize) A = LpVariable("A", cat=LpContinuous) B = LpVariable("B", cat=LpContinuous) # 目标函数 max_problem += 0.12 * A + 0.08 * B # 所有约束 max_problem += A + B == 1 max_problem += 0 <= 0.6*A + 0.8*B <= 1 max_problem += 0 <= 0.2*A - 0.2*B <= 1 max_problem += 0 <= 0.2*A + 0.4*B <= 1 max_problem.solve() print("===== 最大值求解结果 =====") print(f"A取值: {A.varValue}, B取值: {B.varValue}") print(f"r最大值: {value(max_problem.objective)}") # 求解r的最小值 min_problem = LpProblem("min_r", LpMinimize) A_min = LpVariable("A_min", cat=LpContinuous) B_min = LpVariable("B_min", cat=LpContinuous) min_problem += 0.12 * A_min + 0.08 * B_min min_problem += A_min + B_min == 1 min_problem += 0 <= 0.6*A_min + 0.8*B_min <= 1 min_problem += 0 <= 0.2*A_min - 0.2*B_min <= 1 min_problem += 0 <= 0.2*A_min + 0.4*B_min <= 1 min_problem.solve() print("===== 最小值求解结果 =====") print(f"A取值: {A_min.varValue}, B取值: {B_min.varValue}") print(f"r最小值: {value(min_problem.objective)}")
运行上述代码会输出和参考答案完全一致的结果:最大值0.16对应A=2、B=-1,最小值0.1对应A=B=0.5。
代码优化建议
- 导入pulp库时无需写重复导入语句,按需导入用到的类、函数即可,避免全局命名空间污染
- 编写线性规划代码前可先手动化简目标函数、约束的系数,减少代码中嵌套乘法计算,既提升运行效率,也方便排查公式书写错误
- pulp原生支持连续不等式写法,类似
0 <= 表达式 <= 1的范围约束无需拆成两个独立约束编写,代码可读性更高 - 约束命名不要和变量名重名,原代码中将分量约束命名为'B',和变量B同名,容易在调试时造成混淆
内容的提问来源于stack exchange,提问作者gunsnfloyd
相关产品推荐
相关产品推荐

