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

如何在Pyomo优化过程中使用变量结果从列表插值实现阶梯定价

实现方案

我们可以通过二进制指示变量标记每日销量所属的档位区间,同时新增每日销量变量适配整数/浮点场景,完整实现阶梯定价的最优销量求解逻辑如下:


前置逻辑说明

首先需将每日的档位按销量阈值从小到大排序,保证阶梯顺序正确。对第i天第j个档位,记q[i][j]为档位销量上限,price[i][j]为对应档位的定价(支持固定总价/单位价两种模式)。


完整实现代码

from pyomo.environ import *

# 输入参数
# 每日档位格式:(销量阈值, 档位定价),已按销量阈值升序排序
daily_price_offer = [
    [(5, 8), (10, 4)],  # 第1天档位
    [(7, 6), (10, 4)],  # 第2天档位
    [(4, 6), (10, 3)]   # 第3天档位
]
max_apples_total = 14
options_per_day = len(daily_price_offer[0])
day_cnt = len(daily_price_offer)
# 最小销量默认从0开始,可根据业务调整
min_sale = 0

# 初始化模型和求解器
model = ConcreteModel()
solver = SolverFactory('gurobi')  # 无gurobi可替换为glpk

# 定义集合
model.DAYS = RangeSet(0, day_cnt-1)
model.OPTIONS = RangeSet(0, options_per_day-1)

# 定义变量
model.daily_sale = Var(model.DAYS, within=NonNegativeReals)  # 每日销量,改为Integer即可限定整数销量
model.active_bundle = Var(model.DAYS, model.OPTIONS, within=Binary)  # 当日生效档位标记
model.daily_revenue = Var(model.DAYS, within=NonNegativeReals)  # 每日收入

# 约束1:每日最多只能有一个生效档位
def single_bundle_rule(model, d):
    return sum(model.active_bundle[d, j] for j in model.OPTIONS) == 1
model.single_bundle_con = Constraint(model.DAYS, rule=single_bundle_rule)

# 约束2:销量匹配生效档位区间
def sale_range_rule(model, d, j):
    # 取当前档位的上下限阈值
    lower_q = min_sale if j == 0 else daily_price_offer[d][j-1][0]
    upper_q = daily_price_offer[d][j][0]
    # 大M约束:只有当前档位激活时,销量才会落在对应区间
    return (
        lower_q * model.active_bundle[d,j], 
        model.daily_sale[d], 
        upper_q * model.active_bundle[d,j] + 1e6 * (1 - model.active_bundle[d,j])
    )
model.sale_range_con = Constraint(model.DAYS, model.OPTIONS, rule=sale_range_rule)

# 约束3:每日收入匹配档位定价(默认按你示例的档位固定总价规则)
def revenue_rule(model, d):
    return model.daily_revenue[d] == sum(
        daily_price_offer[d][j][1] * model.active_bundle[d,j] 
        for j in model.OPTIONS
    )
model.revenue_con = Constraint(model.DAYS, rule=revenue_rule)

# 约束4:总销量不超过上限
def total_sale_rule(model):
    return sum(model.daily_sale[d] for d in model.DAYS) <= max_apples_total
model.total_sale_con = Constraint(rule=total_sale_rule)

# 目标函数:最大化总营收
model.total_profit = Objective(expr=sum(model.daily_revenue[d] for d in model.DAYS), sense=maximize)

# 求解
res = solver.solve(model)

# 输出结果
print("===== 求解结果 =====")
total_sale = 0
for d in model.DAYS:
    active_j = [j for j in model.OPTIONS if value(model.active_bundle[d,j]) > 0.5][0]
    sale_cnt = round(value(model.daily_sale[d]), 2)
    revenue = round(value(model.daily_revenue[d]), 2)
    total_sale += sale_cnt
    print(f"第{d+1}天:销量={sale_cnt}个,生效档位阈值={daily_price_offer[d][active_j][0]}个,当日收入=${revenue}")
print(f"总销量:{round(total_sale, 2)}个")
print(f"总营收:${round(value(model.total_profit), 2)}")

关键逻辑说明

  • 场景适配:将model.daily_sale的定义域改为Integer即可实现整数销量,默认NonNegativeReals支持浮点量级场景
  • 定价规则调整:如果需要使用档位内统一单位价(比如5个以内每单位8美元,5-10个每单位4美元),只需将revenue_rule替换为下方代码即可:
    def revenue_rule(model, d, j):
        return model.daily_revenue[d] >= daily_price_offer[d][j][1] * model.daily_sale[d] - 1e6 * (1 - model.active_bundle[d,j])
    model.revenue_con = Constraint(model.DAYS, model.OPTIONS, rule=revenue_rule)
    
  • 大M参数:代码中的1e6为大M常量,可根据业务的最大可能销量调整为合适值,避免数值求解误差

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 06:57:02