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

如何调整Pyomo模型实现按需JIT采购(含最小采购/库存限制)

Pyomo实现JIT采购的约束修正方案

问题背景

使用Pyomo计算准时制(JIT)采购时,现有模型可正常运行,但存在以下问题:

  • 原模型强制每月采购,导致库存持续积压(最终月末库存达16),不符合按需采购的JIT核心要求
  • 尝试用Python的if函数添加"按需采购"逻辑时,触发错误:Cannot convert non-constant Pyomo expression (%s) to bool

需要满足的核心约束:

  1. 若当月采购,采购量不得低于5
  2. 每月月末库存不得低于3

原模型代码

model=ConcreteModel(name='Inventory-MIN')
demand=[4,3,2,1,2,3,4]
months=len(demand)

holding_cost=1

purchase_cost=2

model.purchase_qty=Var(range(months), domain=NonNegativeIntegers) # Not NonNegativeReals

# ending quantity of inventory per month
model.end_inventory=Var(range(months), domain=NonNegativeIntegers)

model.cost=Objective(expr=sum(
    model.purchase_qty[month]* # Purchase quantity
    purchase_cost+ # Purchase price
    model.end_inventory[month]* # previous inventory
    holding_cost # Holding cost
    for month in range(1,months,1)), sense=minimize) # start at 1, stop at months, iterate by 1

model.constraints=ConstraintList() # empty list of constraints

model.constraints.add(model.end_inventory[0] == 0)

for month in range(1,months,1):
  next_end_inventory = model.end_inventory[month-1]+model.purchase_qty[month]-demand[month]
  model.constraints.add(model.end_inventory[month] == next_end_inventory)
  # here is where we define a minimum inventory level
  model.constraints.add(model.end_inventory[month]>=3)
  # must buy in bulk
  model.constraints.add(model.purchase_qty[month]>=5) # none of the months have ZERO ORDER !??!?!?!?
# Solve the model
SolverFactory('glpk',executable='/usr/bin/glpsol').solve(model).write()

原模型求解结果

# How much we purchase every month
purchase_qty : Size=7, Index=purchase_qty_index
    Key : Lower : Value : Upper : Fixed : Stale : Domain
      0 :     0 :  None :  None : False :  True : NonNegativeIntegers
      1 :     0 :   6.0 :  None : False : False : NonNegativeIntegers
      2 :     0 :   5.0 :  None : False : False : NonNegativeIntegers
      3 :     0 :   5.0 :  None : False : False : NonNegativeIntegers
      4 :     0 :   5.0 :  None : False : False : NonNegativeIntegers
      5 :     0 :   5.0 :  None : False : False : NonNegativeIntegers
      6 :     0 :   5.0 :  None : False : False : NonNegativeIntegers
#
# Inventory at end of month
end_inventory : Size=7, Index=end_inventory_index
    Key : Lower : Value : Upper : Fixed : Stale : Domain
      0 :     0 :   0.0 :  None : False : False : NonNegativeIntegers
      1 :     0 :   3.0 :  None : False : False : NonNegativeIntegers
      2 :     0 :   6.0 :  None : False : False : NonNegativeIntegers
      3 :     0 :  10.0 :  None : False : False : NonNegativeIntegers
      4 :     0 :  13.0 :  None : False : False : NonNegativeIntegers
      5 :     0 :  15.0 :  None : False : False : NonNegativeIntegers
      6 :     0 :  16.0 :  None : False : False : NonNegativeIntegers

解决方案

问题根源

原模型直接添加purchase_qty[month]>=5,强制每月必须采购至少5个单位,导致库存持续累积。而Pyomo不支持直接用Python的if语句处理变量表达式(变量在求解前是未知的,无法转为布尔值),需使用Big-M方法实现"要么不采购,要么采购量≥5"的逻辑约束。

修改步骤与完整代码

from pyomo.environ import ConcreteModel, Var, Objective, ConstraintList, NonNegativeIntegers, Binary, SolverFactory

model=ConcreteModel(name='Inventory-JIT')
demand=[4,3,2,1,2,3,4]
months=len(demand)

holding_cost=1
purchase_cost=2
# 定义足够大的M值,确保覆盖最大可能采购量(总需求+安全库存)
M = sum(demand) + 10

# 采购量变量
model.purchase_qty=Var(range(months), domain=NonNegativeIntegers)
# 月末库存变量
model.end_inventory=Var(range(months), domain=NonNegativeIntegers)
# 采购标记变量:1表示当月采购,0表示不采购
model.buy = Var(range(months), domain=Binary)

# 目标函数:最小化采购成本+库存持有成本
model.cost=Objective(expr=sum(
    model.purchase_qty[month] * purchase_cost + model.end_inventory[month] * holding_cost
    for month in range(1, months)), sense=minimize)

model.constraints=ConstraintList()
# 初始库存为0
model.constraints.add(model.end_inventory[0] == 0)

for month in range(1, months):
    # 库存平衡约束:上月库存+当月采购-当月需求=当月库存
    model.constraints.add(model.end_inventory[month] == model.end_inventory[month-1] + model.purchase_qty[month] - demand[month])
    # 最小库存约束
    model.constraints.add(model.end_inventory[month] >= 3)
    
    # 采购逻辑约束:要么不采购(purchase_qty=0),要么采购量≥5
    # 1. 若不采购(buy=0),则purchase_qty必须为0
    model.constraints.add(model.purchase_qty[month] <= M * model.buy[month])
    # 2. 若采购(buy=1),则purchase_qty≥5
    model.constraints.add(model.purchase_qty[month] >= 5 * model.buy[month])

# 求解模型
SolverFactory('glpk', executable='/usr/bin/glpsol').solve(model).write()

# 打印结果
print("采购量:")
for month in range(months):
    print(f"第{month+1}月: {model.purchase_qty[month].value}")

print("\n月末库存:")
for month in range(months):
    print(f"第{month+1}月: {model.end_inventory[month].value}")

方案说明

  1. 二进制变量buy:标记当月是否采购,实现按需采购的逻辑开关
  2. Big-M约束:通过足够大的M值,确保当buy=0时采购量强制为0,buy=1时采购量不低于5
  3. 保留核心约束:维持库存平衡和最小库存要求,同时避免强制每月采购,贴合JIT按需采购的目标

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 10:12:04