You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用PuLP生成类Excel Solver的线性规划灵敏度分析报告?

PuLP生成Excel Solver风格的灵敏度报告方案

PuLP本身的高层API没有直接暴露目标函数系数和约束右端值的允许增减范围,但可以通过调用底层CBC求解器的灵敏度输出功能,再解析日志来实现。以下是具体步骤:

1. 配置CBC求解器输出灵敏度信息

创建模型时,使用PULP_CBC_CMD并传入-sensitivity参数开启灵敏度分析,同时指定日志文件保存输出:

import pulp

# 构建示例LP模型
model = pulp.LpProblem("Example_LP", pulp.LpMaximize)
x1 = pulp.LpVariable('x1', lowBound=0)
x2 = pulp.LpVariable('x2', lowBound=0)

model += 3*x1 + 2*x2, "Objective"
model += 2*x1 + x2 <= 100, "Constraint1"
model += x1 + x2 <= 80, "Constraint2"
model += x1 <= 40, "Constraint3"

# 配置求解器,开启灵敏度输出并保存到日志文件
solver = pulp.PULP_CBC_CMD(msg=True, options=['-sensitivity', '-logpath', 'sensitivity_log.txt'])
model.solve(solver)

# 输出已获取的基础信息
print("=== 基础求解结果 ===")
print("变量值与缩减成本:")
for var in model.variables():
    print(f"{var.name}: {var.varValue:.2f}, 缩减成本: {var.dj:.2f}")

print("\n约束松弛值与影子价格:")
for name, constraint in model.constraints.items():
    print(f"{name}: 松弛值: {constraint.slack:.2f}, 影子价格: {constraint.pi:.2f}")

2. 解析灵敏度日志生成报告

CBC会在日志文件中输出目标系数、约束RHS的允许增减范围,编写解析函数提取这些信息并格式化输出:

def parse_sensitivity_log(log_path, model):
    var_report = []
    const_report = []
    current_section = None

    with open(log_path, 'r') as f:
        for line in f:
            line = line.strip()
            if not line:
                continue
            # 切换解析章节
            if line.startswith("Variable Sensitivity Analysis"):
                current_section = "var"
                continue
            elif line.startswith("Constraint Sensitivity Analysis"):
                current_section = "const"
                continue

            # 解析变量灵敏度
            if current_section == "var":
                parts = line.split(':')
                var_name = parts[0].strip()
                details = parts[1].split(',')
                obj_coeff = float(details[0].split()[-1])
                allow_inc = details[1].split()[-1]
                allow_inc = float(allow_inc) if allow_inc != "Infinity" else float('inf')
                allow_dec = details[2].split()[-1]
                allow_dec = float(allow_dec) if allow_dec != "Infinity" else float('inf')
                # 匹配已有的缩减成本
                dj = next(var.dj for var in model.variables() if var.name == var_name)
                var_report.append({
                    "变量名": var_name,
                    "目标系数": obj_coeff,
                    "允许增加量": allow_inc,
                    "允许减少量": allow_dec,
                    "缩减成本": dj
                })
            # 解析约束灵敏度
            elif current_section == "const":
                parts = line.split(':')
                const_name = parts[0].strip()
                details = parts[1].split(',')
                rhs_val = float(details[0].split()[-1])
                shadow_price = float(details[1].split()[-1])
                allow_inc = details[2].split()[-1]
                allow_inc = float(allow_inc) if allow_inc != "Infinity" else float('inf')
                allow_dec = details[3].split()[-1]
                allow_dec = float(allow_dec) if allow_dec != "Infinity" else float('inf')
                # 匹配已有的松弛值
                slack = model.constraints[const_name].slack
                const_report.append({
                    "约束名": const_name,
                    "右端值(RHS)": rhs_val,
                    "影子价格": shadow_price,
                    "允许增加量": allow_inc,
                    "允许减少量": allow_dec,
                    "松弛值": slack
                })
    return var_report, const_report

# 生成并打印Excel风格报告
var_sens, const_sens = parse_sensitivity_log("sensitivity_log.txt", model)

print("\n=== 变量灵敏度报告(Excel Solver风格) ===")
print(f"{'变量名':<10} {'目标系数':<10} {'允许增加量':<15} {'允许减少量':<15} {'缩减成本':<10}")
for item in var_sens:
    print(f"{item['变量名']:<10} {item['目标系数']:<10.2f} {item['允许增加量']:<15} {item['允许减少量']:<15} {item['缩减成本']:<10.2f}")

print("\n=== 约束灵敏度报告(Excel Solver风格) ===")
print(f"{'约束名':<15} {'右端值(RHS)':<15} {'影子价格':<10} {'允许增加量':<15} {'允许减少量':<15} {'松弛值':<10}")
for item in const_sens:
    print(f"{item['约束名']:<15} {item['右端值(RHS)']:<15.2f} {item['影子价格']:<10.2f} {item['允许增加量']:<15} {item['允许减少量']:<15} {item['松弛值']:<10.2f}")

注意事项

  • 该方案依赖PuLP默认的CBC求解器,其他免费求解器(如GLPK)的输出格式不同,需调整解析逻辑。
  • CBC版本可能会微调日志格式,若解析失败需根据实际输出修改分割规则。
  • 若不想生成日志文件,可通过subprocess直接调用CBC并捕获stdout,但logpath参数更简便。

内容的提问来源于stack exchange,提问作者KDL4ever

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 03:35:02