我正在尝试计算及时购买量。这似乎工作得很好,但我想要
不幸的是,这个代码确保我每个月都会购买,而且我只想在某些时间购买。我该如何解决这个问题?
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()
我明白了,显然 16 个库存太多了。
# 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
我尝试将关键约束放入 if 函数中,但收到此错误:
Cannot convert non-constant Pyomo expression (%s) to bool.
您走在正确的道路上。这里有一些修复...
您缺少的主要概念是“半连续变量”,这意味着它要么为零,要么在某个范围内。这可以通过“big-M”类型的约束来完成(如下所示)。 (谷歌搜索或查看任何 LP 教科书)
我还对您的目标和约束中的 0 个月逻辑进行了一些更改。在 obj 中,您仍然需要包含第一个月以捕获当月的购买成本。
from pyomo.environ import *
model=ConcreteModel(name='Inventory-MIN')
demand=[4,3,2,1,2,3,4]
months=len(demand)
holding_cost=1
purchase_cost=2
max_purchase = 50 # some sufficiently large number (big M)
# SETS
model.months = Set(initialize=range(months))
# PARAMS
model.demand = Param(model.months, initialize={m:d for m, d in enumerate(demand)})
model.purchase_cost = Param(model.months, initialize={m: 2 for m in model.months})
model.holding_cost = Param(model.months, initialize={m: 1 for m in model.months})
# VARS
model.make_purchase = Var(model.months, domain=Binary)
model.purchase_qty=Var(model.months, domain=NonNegativeIntegers) # Not NonNegativeReals
# ending quantity of inventory per month
model.end_inventory=Var(model.months, domain=NonNegativeIntegers)
# start at zero... must pay for purchases, and end inventory is already held at zero, so no holding costs
model.cost=Objective(expr=sum(
model.purchase_qty[month] * # Purchase quantity
model.purchase_cost[month] + # Purchase price
model.end_inventory[month] * # previous inventory
model.holding_cost[month] # Holding cost
for month in model.months), sense=minimize)
model.constraints=ConstraintList() # empty list of constraints
for month in model.months:
if month == model.months.first():
# handle the first end-of-month inventory separately
model.constraints.add(model.end_inventory[month] == model.purchase_qty[month] - demand[month])
else: # handle the end-of-month inventory relative to prior...
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 * model.make_purchase[month])
model.constraints.add(model.purchase_qty[month] <= max_purchase * model.make_purchase[month])
# Solve the model
# SolverFactory('glpk',executable='/usr/bin/glpsol').solve(model).write()
solver = SolverFactory('cbc')
res = solver.solve(model)
print(res)
model.purchase_qty.display()
model.end_inventory.display()
purchase_qty : Size=7, Index=months
Key : Lower : Value : Upper : Fixed : Stale : Domain
0 : 0 : 7.0 : None : False : False : NonNegativeIntegers
1 : 0 : 6.0 : None : False : False : NonNegativeIntegers
2 : 0 : 0.0 : None : False : False : NonNegativeIntegers
3 : 0 : 0.0 : None : False : False : NonNegativeIntegers
4 : 0 : 5.0 : None : False : False : NonNegativeIntegers
5 : 0 : 0.0 : None : False : False : NonNegativeIntegers
6 : 0 : 5.0 : None : False : False : NonNegativeIntegers
end_inventory : Size=7, Index=months
Key : Lower : Value : Upper : Fixed : Stale : Domain
0 : 0 : 3.0 : None : False : False : NonNegativeIntegers
1 : 0 : 6.0 : None : False : False : NonNegativeIntegers
2 : 0 : 4.0 : None : False : False : NonNegativeIntegers
3 : 0 : 3.0 : None : False : False : NonNegativeIntegers
4 : 0 : 6.0 : None : False : False : NonNegativeIntegers
5 : 0 : 3.0 : None : False : False : NonNegativeIntegers
6 : 0 : 4.0 : None : False : False : NonNegativeIntegers
[Finished in 314ms]