使用 Python 中的 OR-Tools CP Solver(多背包)进行包裹运输(包裹合并)

Posted

技术标签:

【中文标题】使用 Python 中的 OR-Tools CP Solver(多背包)进行包裹运输(包裹合并)【英文标题】:Packages shipment (packages consolidation) with OR-Tools CP Solver in Python (multi-knapsack) 【发布时间】:2019-10-11 11:36:28 【问题描述】:

我正在使用 OR-Tools CP Solver 实施包裹整合解决方案(基于护士问题解决方案)。

有一家工厂生产一些需要邮寄给客户的小包裹。 将一些 mini_Package 合并为更大的 Package 是最佳选择(例如,如果我们遵守总重量限制,我们可以将 3 个轻 mini_Package 合并为一个 Package,并支付一次而不是 3 次的运输费用)。

Mini_Packages 在数据源中有一些重要的属性(固定目的地、重量、可接受的交货日期范围)。

我的主要 0-1 整数变量如下所示:

x[mini_package_source_number, destination, optimal_shipment_date, package_number]

如果 mini_package 应该在某一天到达某个目的地,合并到某个 Package_number,则它 == 1。

我已经成功构建了大部分模型,除了:

1.主要挑战 如何进行约束以确保当求解器分配最佳包裹编号时,它不能与任何其他目的地或 shipping_date 一起使用? (它的意思是物理上是一个统一的包裹去某个地方)

潜在代码:

for package_number in range(Packages):
  model.Add(sum(x[mini_package_source_number, destination, optimal_shipment_date, package_number] for ...) <= 1)

会错,因为分配的Package_number可以存在很多次,合并几个mini_Packages。 它可以存在多次,但必须始终分配到相同的目的地和日期。

潜在的求解器解决方案:

x[1, Place67, 2019-01-01, 8] = 1
x[2, Place124, 2019-01-04, 119] = 1
x[3, Place124, 2019-01-04, 119] = 1

还可以,mini_Packages 2 和 3 被合并到 Package 119 到相同的目的地(和日期)。

x[4, Place55, 2019-01-05, 119] = 1

可能是错误的,因为 mini_Package 4 也被合并到 Package 119 中,之前由求解器决定前往另一个目的地(并且在另一个日期)。

它是如何编码的?我非常感谢任何解决方案的建议。

2。加法

@Stradivari 的感觉(下面的答案)是准确的。我很可能使用了过多的变量。

3.冲突产品挑战

第 2-3 点已移至:https://or.stackexchange.com/questions/2786/shipments-consolidation-with-or-tools-cp-solver-in-python-multi-knapsack

【问题讨论】:

这是交叉张贴在这里:groups.google.com/forum/#!topic/or-tools-discuss/TkaPJT-i168 你能把原来的问题留在这里,把建模问题移到or.stackexchange.com吗? 好的。点 2-3 移至:or.stackexchange.com/questions/2786/… 【参考方案1】:

为每个 [pkg,destination] 对创建一个布尔变量。

for package_number in range(Packages):
    for destination in destinations:
        model.AddBoolOr(v for k, v in x.items() if k[1] == destination and k[3] == package_number).OnlyEnforceIf(pkg_dest[package_number, destination])
        model.AddBoolAnd(v.Not() for k, v in x.items() if k[1] == destination and k[3] == package_number).OnlyEnforceIf(pkg_dest[package_number, destination].Not())
    model.Add(sum(pkg_dest[package_number, destination] for destination in destinations) == 1)

日期的逻辑相同。

顺便说一句,我觉得你可能用这个公式创造了很多无用的变量,你真的可以决定一个小包装的目的地和/或日期吗?或者只是它的包裹,然后,对于每个包裹,它的目的地和日期?

【讨论】:

2.你的感觉是准确的。我很可能使用了过多的变量(第一个背包项目)。我在上面的帖子中添加了第 2 点来描述它并询问潜在的简化想法。 3.为了让所有人了解整个想法,在上面的帖子中,我添加了一个额外的挑战(第 3 点),这很重要(并且可以影响最佳解决方案方向)。

以上是关于使用 Python 中的 OR-Tools CP Solver(多背包)进行包裹运输(包裹合并)的主要内容,如果未能解决你的问题,请参考以下文章

Or-Tools CP-SAT 求解器导出/导入:加载模型后如何访问变量?

or-tools,CP SAT:在目标函数中使用 AddDivisionEquality 的目标

如何在 MiniZinc 中安装 Google 的 CP 求解器 OR-Tools?

addDivisionEquality with Java google or-tools CP-SAT

如果条件与 OR-Tools CP Solver 一起应用约束

如何使用 or-tools 在 bool 数组中制作 K 个不同的元素?