python纸浆库存优化程序

问题描述 投票:0回答:1

我想创建库存履行优化计划。
每个 Item 有 4 个数据框。我想建议每件商品的履行数量。

目标:
任何物品的现有数量(df2)小于安全库存数量(df3),我们希望满足批次数量(df4)的乘数

限制:
总履行重量应小于1000KG(最大容量小于一辆卡车)

df1

商品# 重量KG
细胞1 细胞2
细胞3 4 号电池

df2

商品# 现有数量
细胞1 细胞2
细胞3 4 号电池

df3

商品# 安全库存数量
细胞1 细胞2
细胞3 4 号电池

df4

商品# 批量
细胞1 细胞2
细胞3 4 号电池

我尝试了如下代码,但认为它是不正确的。
请建议正确的代码或方法来实现目标

m=model_max()

v1={(i):LpVariable('v%d'%(i),lowBound=0) for i in range(len(df4))}
m+=lpSum(df4.iloc[i]*v1[i] for i in range (len(df4))) 

for i in range(len(df_lt)):
    m+= lpSum(df_lt.iloc[i]*v1[i])>=df_ss.iloc[i]
python variables constraints mathematical-optimization pulp
1个回答
0
投票

如果我正确理解你的问题,你可以使用类似的东西:

# == Necessary Imports ============================================================
import pulp
import pandas as pd


# == Input Data ===================================================================
MAX_WEIGHT = 1_000

df1 = pd.DataFrame([["SKU1", 13], ["SKU2", 22]], columns=["Item #", "Weight KG"])

df2 = pd.DataFrame([["SKU1", 150], ["SKU2", 80]], columns=["Item #", "On Hand QTY"])

df3 = pd.DataFrame([["SKU1", 100], ["SKU2", 120]], columns=["Item #", "Safety Stock QTY"])

df4 = pd.DataFrame([["SKU1", 10], ["SKU2", 5]], columns=["Item #", "Lot QTY"])


# == Optimization =================================================================

# -- Create optimization problem instance -----------------------------------------
prob = pulp.LpProblem("Inventory_Optimization", sense=pulp.LpMinimize)
# NOTE: The parameter `sense` determines whether we want to maximize of minimize
#       our objective function

# -- Create problem variables -----------------------------------------------------
items = df1["Item #"].unique() # List of unique "Item #" values

# For each "Item #" we have, we'll create two variables:
# - Allocated (integer): quantity of items to allocate.
# - Lot_Allocated (integer): quantity of item lots to allocate.
allocations = pd.DataFrame(
    [
        [
            item,
            pulp.LpVariable(name=item, lowBound=0, cat=pulp.LpInteger),
            pulp.LpVariable(name=f"LOT_{item}", lowBound=0, cat=pulp.LpInteger),
        ] for item in items
    ], columns=["Item #", "Allocated", "Lot_Allocated"]
)

# Merge our input and variables dataframes, to create a table with all the information we need.
allocations = (
    allocations.merge(df1, on="Item #", how="inner")
    .merge(df2, on="Item #", how="inner")
    .merge(df3, on="Item #", how="inner")
    .merge(df4, on="Item #", how="inner")
)

# -- Create problem constraints ------------------------------------------------------
# Now we'll define our problem constraints.

# Constraint 1: Total Weight of Items allocated <= 1,000Kg
#               Where:
#                   - Total Weight of Items allocated = Σ(Allocated(i) * Weight KG(i)); for i in range Items
prob += pulp.lpSum(allocations["Allocated"] * allocations["Weight KG"]) <= MAX_WEIGHT, "TOTAL_ALLOCATIONS_LEQ_MAX_WEIGHT"

# Constraint 2: For each "Item #", if "On Hand QTY" >= "Safety Stock QTY" --> Then Allocated == 0
prob += pulp.lpSum(allocations[allocations["On Hand QTY"] >= allocations["Safety Stock QTY"]]["Allocated"]) == 0, "ON_HAND_LESS_SAFETY"

# Constraint 3: Allocated(i)/Lot QTY(i) == LOT_CONSTRAINT(i)
for index, row in allocations.iterrows():
    prob += row["Allocated"] * row["Lot QTY"]**-1 == row["Lot_Allocated"], f"LOT_CONSTRAINT_{index}"

    
# -- Set Objective Function ------------------------------------------------------------
# We'll define that our objective function will be to reach the
# Total Weight of Items allocated as close to 1,000Kg as possible.
obj = MAX_WEIGHT - pulp.lpSum(allocations["Allocated"] * allocations["Weight KG"])
prob.setObjective(obj)

# -- Solve the Optimization Problem ----------------------------------------------------
print(pulp.LpStatus[prob.solve(pulp.PULP_CBC_CMD(msg=False))])

if prob.status != 1:
    raise ValueError(f"Failed to solve optimization problem. Status: {pulp.LpStatus[prob.status]}")

allocations[["Allocated", "Lot_Allocated"]] = allocations[["Allocated", "Lot_Allocated"]].applymap(lambda value: value.value()).astype(int)
allocations
# Returns:
#
#   Item #  Allocated  Lot_Allocated  Weight KG  On Hand QTY  Safety Stock QTY  Lot QTY
# 0   SKU1          0              0         13          150               100       10
# 1   SKU2         45              9         22           80               120        5

输出:

商品# 已分配 已分配批次 重量KG 现有数量 安全库存数量 批量
SKU1 0 0 13 150 100 10
SKU2 45 9 22 80 120 5
© www.soinside.com 2019 - 2024. All rights reserved.