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

OR-tools中多批次生产产量分配至订单的实现技巧咨询

问题描述

需要履行订单并明确交付日期,允许分多次交付,将生产批次(含部分批次)分配至已知订单,核心规则为同产品的生产产量按订单顺序填充(即优先满足先出现的订单,产能不足时再用后续批次补充)。最终需通过OR-tools返回各订单对应的生产批次(含关联生产日)及分配的产量。

订单数据示例

orders = {
    0 : [50,45,65],  # 键:产品编号;值:订单需求量列表(按顺序)
    1 : [155,15,80,25] 
}

生产批次数据示例

已通过OR-tools定义变量形式的生产批次列表list_production,每个批次包含产品编号、产量、关联NewIntervalVar的生产日,示例如下:

# 格式:[产品编号, 产量, 生产日]
list_production = [
    [0, 30, 1],
    [1, 100, 1],
    [1, 90, 2],
    [0, 40, 2],
    [0, 60, 3],
    [1, 40, 3],
    [1, 35, 3]
]

注:该列表整体产品编号无序,但同产品的生产日变量已满足时间先后顺序约束。


实现技巧与方法

1. 按产品分组生产批次

先将无序的生产批次按产品编号分组,利用同产品生产日已有的顺序约束,得到每个产品对应的有序批次列表:

from collections import defaultdict

# 按产品编号分组,自动保留同产品的生产日顺序
product_batches = defaultdict(list)
for batch in list_production:
    product_id, qty, day = batch
    product_batches[product_id].append( (qty, day) )

2. 建模顺序填充约束

针对每个产品的订单序列和批次列表,创建分配变量并添加三类约束:

  • 批次产能约束:单个批次分配给所有订单的总量不能超过自身产量
  • 订单需求约束:所有批次分配给单个订单的总量必须等于该订单的需求量
  • 顺序填充约束:确保先填满前面的订单,再用剩余产能分配给后续订单

以下是OR-tools的具体实现代码:

from ortools.linear_solver import pywraplp

# 初始化求解器
solver = pywraplp.Solver.CreateSolver('SCIP')
all_assign_vars = {}  # 存储所有产品的分配变量

for product_id in orders:
    reqs = orders[product_id]
    batches = product_batches[product_id]
    num_orders = len(reqs)
    num_batches = len(batches)

    # 计算累计需求和累计批次产量,用于顺序约束
    cum_reqs = [0]
    for r in reqs:
        cum_reqs.append(cum_reqs[-1] + r)
    cum_batches = [0]
    for qty, _ in batches:
        cum_batches.append(cum_batches[-1] + qty)

    # 创建分配变量:assign[j][i] = 第j个批次分配给第i个订单的数量
    assign = []
    for j in range(num_batches):
        row = []
        for i in range(num_orders):
            var = solver.IntVar(0, batches[j][0], f'assign_p{product_id}_b{j}_o{i}')
            row.append(var)
        assign.append(row)
    all_assign_vars[product_id] = assign

    # 约束1:批次产能不超
    for j in range(num_batches):
        solver.Add(sum(assign[j]) <= batches[j][0])

    # 约束2:订单需求被完全满足
    for i in range(num_orders):
        solver.Add(sum(assign[j][i] for j in range(num_batches)) == reqs[i])

    # 约束3:顺序填充——前i个订单必须用完前j个批次的产能后,才能用后续批次给第i+1个订单分配
    for i in range(num_orders):
        for j in range(num_batches):
            # 前j个批次的总产能 <= 前i个订单的总需求 → 该批次不能分配给第i+1及之后的订单
            if cum_batches[j+1] <= cum_reqs[i]:
                for k in range(i+1, num_orders):
                    solver.Add(assign[j][k] == 0)
            # 前i个订单的总需求 <= 前j-1个批次的总产能 → 该批次不能分配给第i及之前的订单
            elif cum_reqs[i] <= cum_batches[j]:
                for k in range(i+1):
                    solver.Add(assign[j][k] == 0)

3. 提取并输出结果

求解完成后,遍历分配变量,整理每个订单对应的批次信息:

status = solver.Solve()
if status in (pywraplp.Solver.OPTIMAL, pywraplp.Solver.FEASIBLE):
    for product_id in all_assign_vars:
        reqs = orders[product_id]
        batches = product_batches[product_id]
        assign = all_assign_vars[product_id]
        print(f"=== 产品{product_id}的订单分配结果 ===")
        for i in range(len(reqs)):
            print(f"订单{i}(需求:{reqs[i]}):")
            for j in range(len(batches)):
                qty_assigned = assign[j][i].solution_value()
                if qty_assigned > 0:
                    print(f"  批次{j}:分配产量{qty_assigned},生产日{batches[j][1]}")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 12:25:44