自学内容网 自学内容网

基于Python+Gurobi的库存分配问题建模求解

库存分配问题(Inventory Allocation Problem)是供应链管理中的一个经典问题,主要研究如何将有限的库存资源合理地分配给多个需求点(如客户、零售商或分销中心),以优化某些目标(如最小化成本、最大化服务水平等)。库存分配问题只需关注何时向哪些客户配送多少货物

数学模型

参数

  • T T T:时间周期集合。
  • N N N:客户集合。
  • d i t d_{it} dit:客户 i i i 在时间 t t t 的需求。
  • h i h_i hi:客户 i i i 的单位库存持有成本。
  • c i c_i ci:从供应商到客户 i i i 的单位运输成本。
  • S i S_i Si:客户 i i i 的库存容量。
  • I i 0 I_{i0} Ii0:客户 i i i 的初始库存。
  • S 0 S_0 S0:供应商的库存容量。
  • I 00 I_{00} I00:供应商的初始库存。

决策变量

  • y i t y_{it} yit:在时间 t t t 向客户 i i i 配送的货物量。

中间变量

  • I i t I_{it} Iit:客户 i i i 在时间 t t t 的库存水平。
  • I 0 t I_{0t} I0t:供应商在时间 t t t 的库存水平。

目标函数:最小化总成本(库存持有成本 + 运输成本):

min ⁡ ∑ t ∈ T ( ∑ i ∈ N h i I i t + ∑ i ∈ N c i y i t ) \min \sum_{t \in T} \left( \sum_{i \in N} h_i I_{it} + \sum_{i \in N} c_i y_{it} \right) mintT(iNhiIit+iNciyit)

约束条件

  1. 客户库存平衡
    I i t = I i , t − 1 + y i t − d i t , ∀ i ∈ N , t ∈ T I_{it} = I_{i,t-1} + y_{it} - d_{it}, \quad \forall i \in N, t \in T Iit=Ii,t1+yitdit,iN,tT

  2. 供应商库存平衡
    I 0 t = I 0 , t − 1 − ∑ i ∈ N y i t , ∀ t ∈ T I_{0t} = I_{0,t-1} - \sum_{i \in N} y_{it}, \quad \forall t \in T I0t=I0,t1iNyit,tT

  3. 客户库存容量
    0 ≤ I i t ≤ S i , ∀ i ∈ N , t ∈ T 0 \leq I_{it} \leq S_i, \quad \forall i \in N, t \in T 0IitSi,iN,tT

  4. 供应商库存容量
    0 ≤ I 0 t ≤ S 0 , ∀ t ∈ T 0 \leq I_{0t} \leq S_0, \quad \forall t \in T 0I0tS0,tT

  5. 配送量非负
    y i t ≥ 0 , ∀ i ∈ N , t ∈ T y_{it} \geq 0, \quad \forall i \in N, t \in T yit0,iN,tT

代码实现

from gurobipy import Model, GRB

# 参数设置
T = range(1, 5)  # 时间周期,例如 4 个周期
N = ["C1", "C2"]  # 客户集合
d = {
    ("C1", 1): 10,
    ("C1", 2): 20,
    ("C1", 3): 15,
    ("C1", 4): 25,  # 客户需求
    ("C2", 1): 15,
    ("C2", 2): 10,
    ("C2", 3): 20,
    ("C2", 4): 15,
}
h = {"C1": 1, "C2": 1}  # 客户单位库存持有成本
c = {"C1": 5, "C2": 7}  # 从供应商到客户的单位运输成本
S = {"C1": 100, "C2": 100}  # 客户库存容量(放宽容量)
S0 = 200  # 供应商库存容量(放宽容量)
I0 = {"C1": 50, "C2": 50}  # 客户初始库存(增加初始库存)
I00 = 100  # 供应商初始库存(增加初始库存)

# 创建模型
model = Model("Inventory_Allocation_Problem")

# 决策变量
y = model.addVars(N, T, name="Delivery")  # 配送量
I = model.addVars(N, T, name="Inventory")  # 客户库存水平
I_supplier = model.addVars(T, name="Supplier_Inventory")  # 供应商库存水平

# 目标函数
model.setObjective(
    sum(h[i] * I[i, t] for i in N for t in T)
    + sum(c[i] * y[i, t] for i in N for t in T),
    sense=GRB.MINIMIZE,
)

# 约束条件
for i in N:
    for t in T:
        # 客户库存平衡约束
        if t == 1:
            model.addConstr(
                I[i, t] == I0[i] + y[i, t] - d[i, t], name=f"Balance_{i}_{t}"
            )
        else:
            model.addConstr(
                I[i, t] == I[i, t - 1] + y[i, t] - d[i, t], name=f"Balance_{i}_{t}"
            )

        # 客户库存容量约束
        model.addConstr(I[i, t] <= S[i], name=f"Capacity_{i}_{t}")

for t in T:
    # 供应商库存平衡约束
    if t == 1:
        model.addConstr(
            I_supplier[t] == I00 - sum(y[i, t] for i in N), name=f"Supplier_Balance_{t}"
        )
    else:
        model.addConstr(
            I_supplier[t] == I_supplier[t - 1] - sum(y[i, t] for i in N),
            name=f"Supplier_Balance_{t}",
        )

    # 供应商库存容量约束
    model.addConstr(I_supplier[t] <= S0, name=f"Supplier_Capacity_{t}")

# 求解模型
model.optimize()

# 输出结果
if model.status == GRB.OPTIMAL:
    print("Optimal solution found!")
    print(f"Total Cost = {model.objVal}")

    print("\nDelivery Plan:")
    for i in N:
        for t in T:
            print(f"Delivery to {i} at time {t}: {y[i, t].X}")

    print("\nCustomer Inventory Levels:")
    for i in N:
        for t in T:
            print(f"Inventory of {i} at time {t}: {I[i, t].X}")

    print("\nSupplier Inventory Levels:")
    for t in T:
        print(f"Supplier Inventory at time {t}: {I_supplier[t].X}")
else:
    print("No optimal solution found.")
    if model.status == GRB.INFEASIBLE:
        print("Model is infeasible. Check constraints and parameters.")

打印结果:

Set parameter Username
Set parameter LicenseID to value 2583232
Academic license - for non-commercial use only - expires 2025-11-13
Gurobi Optimizer version 12.0.0 build v12.0.0rc1 (win64 - Windows 11+.0 (27774.2))

CPU model: 11th Gen Intel(R) Core(TM) i5-1135G7 @ 2.40GHz, instruction set [SSE2|AVX|AVX2|AVX512]
Thread count: 4 physical cores, 8 logical processors, using up to 8 threads

Optimize a model with 24 rows, 20 columns and 49 nonzeros
Model fingerprint: 0x9b8bbd90
Coefficient statistics:
  Matrix range     [1e+00, 1e+00]
  Objective range  [1e+00, 7e+00]
  Bounds range     [0e+00, 0e+00]
  RHS range        [1e+01, 2e+02]
Presolve removed 17 rows and 8 columns
Presolve time: 0.00s
Presolved: 7 rows, 12 columns, 22 nonzeros

Iteration    Objective       Primal Inf.    Dual Inf.      Time
       0    1.2994100e+02   3.761750e+00   0.000000e+00      0s
       6    3.0000000e+02   0.000000e+00   0.000000e+00      0s

Solved in 6 iterations and 0.00 seconds (0.00 work units)
Optimal objective  3.000000000e+02
Optimal solution found!
Total Cost = 300.0

Delivery Plan:
Delivery to C1 at time 1: 0.0
Delivery to C1 at time 2: 0.0
Delivery to C1 at time 3: 0.0
Delivery to C1 at time 4: 20.0
Delivery to C2 at time 1: 0.0
Delivery to C2 at time 2: 0.0
Delivery to C2 at time 3: 0.0
Delivery to C2 at time 4: 10.0

Customer Inventory Levels:
Inventory of C1 at time 1: 40.0
Inventory of C1 at time 2: 20.0
Inventory of C1 at time 3: 5.0
Inventory of C1 at time 4: 0.0
Inventory of C2 at time 1: 35.0
Inventory of C2 at time 2: 25.0
Inventory of C2 at time 3: 5.0
Inventory of C2 at time 4: 0.0

Supplier Inventory Levels:
Supplier Inventory at time 1: 100.0
Supplier Inventory at time 2: 100.0
Supplier Inventory at time 3: 100.0
Supplier Inventory at time 4: 70.0

原文地址:https://blog.csdn.net/qq_43276566/article/details/145217040

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!