在本文中,我们将了解Flexport如何使用数学和数据科学解决交付问题并以最低的成本准时交付商品。考虑一个投机性场景:对于任何货运,货运代理都有十个出发点和一个目的地航班。唯一要做出的决定是是否将每个货件分配给该单个航班。如果我们没有为航班分配特定的负载,则可以以其他方式移动它。每批货物都有数量和成本,并且航班数量有限。您可能将其视为简化的背包问题。因此,有1024-1 = 1023个可能的解决方案(我们不会将飞机发送到完全空的状态)。我们可以创建一个电子表格以列出整个解决方案,然后选择利润最高的解决方案。但是,如果您有10个相同的出发航班却有2个航班,该怎么办?仅10批出货就提供了59,049个解决方案。大型货运代理有十多个出发点,当然还有两个以上的航班可供选择,这导致了数万亿到数万亿的可能解决方案。其中只有数百万个可行的解决方案,这意味着传统的电子表格方法可以找到至少一个可行的解决方案。但是,我们并不需要可行的解决方案。我们需要最佳,最佳的解决方案。如何在众多可能性中找到它们?一种答案是使用整数编程。整数编程是离散优化的一个子部分,是与受约束约束的一些目标函数最小化有关的操作研究领域。我们希望将总成本降到最低,只要将货物以正确的位置按时交付,并以ULD(单位装载设备-一种包装货物的方式)堆叠。我们努力寻求最佳解决方案,但实际上有时我们无法实现。在这种情况下,我们对良好或接近的解决方案感到满意。在这里,我们将自己局限于一个简单的模型,在该模型中可以实现最佳解决方案。解决此问题的第一步是转向文献。科学界多年来一直在处理货运代理。我们发现了几本让人回想起我们问题的作品。我们从这些作品中采用了以下许多概念和符号,并感谢作者对这一领域的贡献。我们首先定义目标函数。为了最大程度地降低成本,我们需要了解标准重量的概念。简而言之,标准重量是货运代理同意使用的最小重量,而与实际提供的重量无关。我们有总重量,标准重量以及超载的赔率,反之则是体重不足。标准重量乘以体重不足是一种低估,因此我们可以忽略体重不足,而将注意力放在过载系数乘以过载本身上。目标功能是使总成本最小化,总成本定义为ULD分配的所有货物的总重量乘以负载系数。例如,如果ULD1拥塞100公斤,而ULD1的拥塞率是每公斤$ 4,那么ULD1的总成本将是$ 400。因此,我们需要一些关于超重及其价值的表示法。让 -重量ULD j高于标准,并且 -同一ULD的成本因素。我们需要计算 对所有人 。如果那么目标函数将是 。它崩溃成。我们希望使价值最小化,因此我们的最终目标是:
价值 不是计算值。此参数是从电子表格或数据库获得的。但 我们定义为ULD的总过载重量 ,我们可以将其计算为ULD分配的所有耗材的总重量(表示为 )减去此ULD的标准重量。标准重量特定于ULD类型,并且也是一个参数。让 是ULD的标准重量 以千克为单位。然后是超重的额外重量 定义为 。当然,ULD的总权重取决于分配给ULD的权重及其权重。因此,我们需要一个表达式来计算它,包括上面提到的细节。这只是ULD分配的权重之和。如何指示一批货物已分配给特定的ULD?为此,我们不需要参数,而是解决方案变量。决策变量是求解器可以在最小化目标函数的同时进行控制的东西。让参数 代表毛重 以千克为单位。例如,表示4的负载重500公斤。让 -装运时取值为1的决策变量 ULD分配 和 除此以外。因此,当我们要计算ULD 3分配的所有货运时,我们可以遍历所有变量哪里 。如果我们有4个货件,并且货件编号1和3被分配给ULD 3,则如下所示:
但是我们需要总重量,而不是数量。要获得它,只需将每个解决方案变量乘以权重参数即可。由于决策变量的值为0,因此如果未分配权重,则将重置此权重并且不将其包括在总计中。假设货物1至4的重量分别为10、50、25和5。那么ULD 3中的总重量为:
让我们大致写出总重量的计算。确定ULD的总重量 如 。然后和 。我们可以使用求和符号来折叠 和 。因为我们希望所有情况都如此,我们使用“所有人”符号: 。这为我们提供了总重量限制的最终形式:
超重
现在我们有了总重量,我们可以将公式应用于额外的负载:
例如,如果 和 然后超重 公斤。将此乘以成本因子即可得出结果。乍一看,这似乎足够了,但是当ULD的整个货物的总重量不超过标准重量时,该怎么办?在这种情况下,如果我们使用“原样”公式,则过载权重将为负数。例如,如果标准重量为1650千克,分配的总重量为1000千克,则过载= 1000–1650 = -650。目标函数将此数字乘以过载的系数,得到负数。好像承运人为我们支付的运费少于标准重量的费用。这是我们真正想要的:。这与为变量设置0相同,就像创建约束一样简单。, 因此,我们在数学编程中实现了max()函数:a = max(b,c),即a> = b && a> = c。让我们看看我们的定义。目标功能::ULD过载率 :ULD超载 ; UjP:标准重量ULD jgi:总运输重量 ixi,j:决策变量; xi,j=1如果装运 iULD分配 j, 0除此以外。yj:ULD指定的所有货运的总重量 j; yj=∑i∈Igixi,j∀j∈J每个负载都必须飞行
此时,我们可以用Python编写此代码并将其发送到求解器。如果这样做,我们会发现求解器对任何航班都分配了零个交货,并且我们可以快速理解原因:最小化目标函数的最佳方法是不累积任何成本。这导致以下限制:必须将每个批次分配给某些ULD。我们会将其扩展到应分配给一个ULD的每个货物,尽管实际上我们可以将货物分为几个ULD甚至几个航班。代表着xi,j对于$ j $的单个值,只能为1。例如,如果我们考虑装运13,则x13,1+x13,2+x13,3+…+x13,J=1。我们想将此限制应用于每批货。i (我们写成 ∀i∈I),我们可以使用求和运算符((∑),因此我们的最终限制是:
∑j∈Jxi,j=1∀i∈I
鉴于此限制,求解器实际上将开始将货物分配给航班,但他将仅在所有可用航班之间分配货物,直到满足重量要求为止。然后,求解器将以最少的额外成本将每个剩余托运货物放置在一个ULD中。不包括此ULD的体积或重量。因此,以下附加限制是体积和重量。体积和重量限制
让我们决定 UjM作为最大有效载荷(以千克ULD为单位) j和 Uj以立方米为单位的最大体积 j。让我们决定vi,以及以立方米为单位的货物体积 i。为了将模型限制为最大负载能力和最大体积,我们具有以下条件:
yj<=UjM∀j∈J
∑i∈Ixi,jvi<=UjV∀j∈J
行业资深人士将立即意识到这是不正确的。为什么?因为这些限制将货物当作可以像水一样倒入任何体积的货物。实际上,负载是刚性的或具有其他限制,例如堆叠。 10立方米的货物不能以等于10立方米的任意体积包装。为了应对这些情况,您需要解决容器包装的问题。我们检查某些卷是否适合其他卷,但这不在本文讨论范围之内。现在,求解器将分配装运ULD,同时考虑最大重量和最大体积,同时使总成本最小化。但是还有另一个问题:我们没有说有关物品的指定和交货日期的遵守情况。实际上,分配货件时需要考虑四个时间戳:货件实际准备好与ULD中的其他货件合并并加载航班的时间。让我们用Qi−代表发货准备的时间 i。通常,必须将必须在目的地卸下货物的时间取消合并,并可以从货运站接收。让我们用$ Q_i ^ + $表示交货期限i。所有货物必须交付到货运站才能装载到航班上的时间。让我们用Tj−代表货物ULD $ j $的削波时间。航班到达时间:这是航班上的货物可在目标仓库中到达的时间。让我们用Tj+ 代表ULD航班到达时间 j来源和目的地
再介绍一套 Ji,我们将其定义为一组航班,其出发地和目的地与货物的出发和接收时间一致 i。换句话说,如果出发地85是从香港出发并到达伦敦的目的地,则$ J_ {85} $是所有从香港出发并到达目的地是伦敦的ULD的集合。现在我们可以使用j∈Ji 获得与运输贸易路线相匹配的ULD套件 i或者我们可以使用 j∉Ji得到一组不匹配的ULD。为了禁止将货物绑定到与原产地和目的地不符的ULD,我们仅限制xi,j=0对于所有此类航班。该限制的详细说明如下:
∑j∉Jixi,j=0∀i∈I
交货时间
在优化中使用时间戳时,将必要的时刻显示为Unix时间很方便。该方法的优点:- 将日期存储为数字。
- 无需处理时区。
- 求解器使用直接较少的比较。
航班必须在交货时间之前到达:∑j∈JiTj+xi,j<=Qi+∀i∈I请注意,就像上述对出发地和目的地的限制一样,我们已经表明此限制仅适用于集合中的ULD Ji哪里 Ji 是一组与发送和接收货件相匹配的ULD i。就这样!让我们看一下整个模型。完整模型
在这种限制下,求解器以成本最低的方式分配ULD项目,每批货物都从正确的出发地交付到正确的目的地。当然,货物可以按时交付,而不会因体积或重量而超载。参量
I:一组所有货件。提交了一批货iJ:一组所有ULD。个别ULD为小写j。Ji:一组匹配发送方和接收方的所有ULD i。gi:运输毛重 i以千克为单位。vi:装运量(立方米) icjE:ULD过载率 j美元/千克UjM:最大承重ULD j公斤UjV:ULD最大环绕声功率 j立方米UjP:标准重量ULD j公斤Tj−:允许到ULD终端的交货时间 j。Tj+:ULD到达时间 j。Qi−:发货准备时间 i。 Qi+:交货期 i。决策变量和目标函数:yj:ULD总重量 jyjE:ULD超载 j以千克为单位。xi,j:1如果发送 iULD分配 j否则为0。目标功能
Minimize∑yjEcjE
局限性
yj -ULD $ j $上的货物总重量: yj=∑i∈Igixi,j∀j∈J额外权重jE为最大值(0,yj-UjP):yjE>=yj−UjP∀j∈JyjE>=0∀j∈J必须将每个交货准确分配给1个ULD: ∑j∈Jxi,j=1∀i∈I。超低密度脂蛋白j 不能超过最大重量: yj<=UjM∀j∈J超低密度脂蛋白 j不能超过最大容量: ∑i∈Ixi,jvi<=UjV∀j∈J进一步的步骤
本文介绍了飞行负荷目的背后的数学编程。但是仅仅写数学是不够的。下一步是使用Pyomo之类的AML或使用自己的求解器API(例如Python Gurobi API)来实现该程序。之后,开发人员将编写代码以传输所有可用出发和飞行的参数。然后将模型实例发送到求解器。求解器以最佳方式设置决策变量的值。然后开发人员必须对决策变量的值做一些事情。