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

如何在PuLP中构建商品采购利润优化的线性规划或MIP模型

PuLP混合整数规划建模修正方案

核心问题说明

当前代码存在3个核心错误:

  1. 分式约束PuLP不支持:线性规划/整数规划仅支持线性约束,不能直接写两个非常量表达式的除法,需要转换为等价线性形式
  2. 中标逻辑实现错误:直接用Python条件判断写的win_loss是静态值,不是依赖决策变量的模型变量,完全无法动态判断是否中标
  3. 决策变量定义冗余:需求是每个商品类别对应一个定价系数,原代码定义了「商品+类别」的全组合变量,存在大量无效冗余

建模修正逻辑

1. 变量定义优化

  • 仅为10个商品类别定义定价系数:s[i],取值范围[0, 1.0],满足单个系数不超过1的约束
  • 为每个商品定义0-1二进制中标变量:win[j],win[j]=1代表商品j中标,win[j]=0代表未中标

2. 中标逻辑线性化(大M法)

要实现「出价≥实际成交价时win[j]=1,否则win[j]=0」的逻辑,需要引入足够大的常数M,添加两条约束:

  • Bid[j] >= ACTUAL_PX[j] - M * (1 - win[j]):当win[j]=1时,强制出价≥实际成交价
  • Bid[j] <= ACTUAL_PX[j] - 1e-6 + M * win[j]:当win[j]=0时,强制出价<实际成交价,1e-6是避免浮点误差的容差

3. 比率约束线性化

原约束aggFV / 净收入 <= -2.0,首先添加约束保证净收入为正(避免不等号方向反转),再两边乘净收入得到等价线性约束:
aggFV <= RATIO_CONSTRAINT * 净收入,即aggFV + 2 * 净收入 <= 0


修正后可运行代码

from pulp import LpMaximize, LpProblem, lpSum, LpVariable, LpBinary
import pandas as pd

df = pd.read_excel('data.xlsx')

# 常量定义
MAX_STAT = 1.0
RATIO_CONSTRAINT = -2.0
PRODUCTS = list(range(10))
ITEMS = df['ITEMS'].tolist()
# 大M取值设为所有商品最大可能出价的2倍,可根据实际数据调整
M = 2 * (df['THEO_PX'].max() + df['FV'].max() - df['COST'].min() - df['EXPENSE'].min())
TOL = 1e-6

# 基础映射字典(无需冗余矩阵,按商品直接取所属类别对应值即可)
ITEM_TO_PROD = {j: df.loc[df['ITEMS']==j, 'PRODUCT'].iloc[0] for j in ITEMS}
ACTUAL_PX = {j: df.loc[df['ITEMS']==j, 'ACTUAL_PX'].iloc[0] for j in ITEMS}
THEO_PX = {j: df.loc[df['ITEMS']==j, 'THEO_PX'].iloc[0] for j in ITEMS}
COST = {j: df.loc[df['ITEMS']==j, 'COST'].iloc[0] for j in ITEMS}
EXPENSE = {j: df.loc[df['ITEMS']==j, 'EXPENSE'].iloc[0] for j in ITEMS}
QUANTITY = {j: df.loc[df['ITEMS']==j, 'QUANTITY'].iloc[0] for j in ITEMS}
FV = {j: df.loc[df['ITEMS']==j, 'FV'].iloc[0] for j in ITEMS}

# 初始化模型
model = LpProblem(name="maximize_margin", sense=LpMaximize)

# 定义决策变量
# 10个类别对应的定价系数
s = LpVariable.dicts('category_stat', PRODUCTS, lowBound=0, upBound=MAX_STAT)
# 每个商品的中标0-1变量
win = LpVariable.dicts('win_flag', ITEMS, cat=LpBinary)

# 计算每个商品的出价
def calc_bid(j):
    prod_i = ITEM_TO_PROD[j]
    return THEO_PX[j] + s[prod_i] * FV[j] - COST[j] - EXPENSE[j]

# 添加中标逻辑约束
for j in ITEMS:
    bid_j = calc_bid(j)
    model += bid_j >= ACTUAL_PX[j] - M * (1 - win[j])
    model += bid_j <= ACTUAL_PX[j] - TOL + M * win[j]

# 计算聚合指标
agg_revenue = lpSum(win[j] * THEO_PX[j] * QUANTITY[j] for j in ITEMS)
agg_cost = lpSum(win[j] * calc_bid(j) * QUANTITY[j] for j in ITEMS)
agg_fv = lpSum(win[j] * FV[j] * QUANTITY[j] for j in ITEMS)
net_income = agg_revenue - agg_cost

# 目标函数:最大化总利润=净收入+未来增值
model += net_income + agg_fv

# 约束1:净收入必须为正,避免比率约束不等号反转
model += net_income >= 1e-3
# 约束2:转换后的比率约束
model += agg_fv <= RATIO_CONSTRAINT * net_income

# 求解模型
model.solve()
print("求解状态:", model.status)
print("最优总利润:", model.objective.value())
# 输出各品类的最优定价系数
for i in PRODUCTS:
    print(f"品类{i}最优系数:", s[i].value())

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.19 06:54:04