此示例展示了如何使用过渡属性来优先考虑在同一时间段内由同一车辆执行附近取货和送货的路线。如需详细了解过渡属性,请参阅使用过渡属性对业务逻辑进行建模。
在此示例中:
- 货物 A、B 和 C 的送货地点位于同一条道路上,彼此相距不远。
- 后续还将有更多交付。
- 配送没有指定配送时间。
- 无论访问时间表如何,车辆都需要在这条道路上行驶两次:一次是在早上从补给站出发时,另一次是在晚上返回时。
- 无论何时执行 A、B 和 C,路线的总行驶距离和时长始终保持不变。
在这种情况下,对于仅使用每小时费用和每公里费用的请求,优化后的路线可能是在早上处理 A 和 B,在晚上处理 C,而解决方案的费用与同时处理这三项任务的费用相同。
具有阈值的每公里费用
如需对邻近的访问进行分组,您首先需要选择距离阈值。这是您认为两次访问属于邻近访问的最大距离。此示例使用的阈值为 100 米,大致相当于城市区域中的一个街区。您可以根据业务需求和司机的偏好提高或降低此阈值。
若要将彼此相距 100 米以内的附近访问归为一组,您可以为每次转换的前 100 米设置较高的费用,并为转换的任何额外米数设置较低的费用。由于前 100 米的费用最高,因此即使这意味着延长路线的总长度,优化器也会通过使用短于 100 米阈值的过渡来节省最多的费用。
如需设置费用,请向 ShipmentModel.transition_attributes
添加一个新条目,并设置以下属性:
- 如需匹配所有可能的过渡,请选择模型中任何位置都未使用的标记,例如
UNUSED_TAG
。将TransitionAttributes.excluded_src_tag
和TransitionAttributes.excluded_dst_tag
设置为此标记。 - 使用阈值距离和费用设置
TransitionAttributes.distance_limit
:- 将
DistanceLimit.soft_max_meters
设置为所选阈值。 - 将
DistanceLimit.cost_per_kilometer_below_soft_max
设置为低于阈值的每公里费用。 - 将
DistanceLimit.cost_per_kilometer_above_soft_max
设置为高于阈值的每公里费用。
- 将
{
"model": {
"transitionAttributes": [
{
"excluded_dst_tag": "UNUSED_TAG",
"excluded_src_tag": "UNUSED_TAG",
"distanceLimit": {
"softMaxMeters": 100,
"costPerKilometerBelowSoftMax": 50,
"costPerKilometerAboveSoftMax": 1,
}
}
]
}
}
任何货件或车辆都不得使用 #unused_tag#
标记来匹配所有可能的过渡。如需了解详情,请参阅如何匹配所有访问请求。
高费用低于阈值的运作方式
本部分展示了低于和高于阈值的费用如何影响示例方案中不同解决方案的总费用。
方案 1:去程时执行 A、B,回程时执行 C
在此解决方案中,货件会拆分为两次遍历此道路。其中两个在第一次遍历时传递,剩余一个在第二次遍历时传递。有 5 种过渡方式:
过渡 | 距离 | 低于阈值 | 高于阈值 | ||
---|---|---|---|---|---|
距离 | 费用 | 距离 | 费用 | ||
depot →A | 1000 米 | 100 m | 5 | 900 米 | 0.9 |
A→B | 50 米 | 50 米 | 2.5 | 0 分钟 | 0 |
B→其他 | 1030 米 | 100 m | 5 | 930 米 | 0.93 |
其他→C | 1000 米 | 100 m | 5 | 900 米 | 0.9 |
C→depot | 1080 米 | 100 m | 5 | 980 米 | 0.98 |
总计 | 450 米 | 22.5 | 3710 米 | 3.71 |
总费用是每公里两种费用的总和:
- 低于阈值(50)的每公里费用乘以低于阈值(450 米 = 0.45 公里)的总行驶距离,
- 超出阈值的每公里费用 (1) 乘以超出阈值的总行驶距离(3710 米 = 3.71 公里)。
因此,总费用为 0.45 * 50 + 3.71 * 1 = 22.5 + 3.71 = 26.21。
解决方案 2:去程执行 A、B、C,返程不执行任何操作
在此解决方案中,与解决方案 1 不同,所有三批货物都在一次道路遍历期间“成组”交付。而在另一次遍历中,车辆根本不会停靠。同样,这里有 5 个过渡,但它们的长度和组成不同:
过渡 | 距离 | 低于阈值 | 高于阈值 | ||
---|---|---|---|---|---|
距离 | 费用 | 距离 | 费用 | ||
depot →A | 1000 米 | 100 m | 5 | 900 米 | 0.9 |
A→B | 50 米 | 50 米 | 2.5 | 0 分钟 | 0 |
B→C | 30 米 | 30 米 | 1.5 | 0 分钟 | 0 |
C→其他 | 1000 米 | 100 m | 5 | 900 米 | 0.9 |
其他→仓库 | 2080 m | 100 m | 5 | 1980 m | 1.98 |
总计 | 380 米 | 19 | 3780 米 | 3.78 |
使用与解决方案 1 中相同的计算方式,总费用为 0.38 * 50 + 3.78 * 1 = 19 + 3.78 = 22.78,并且在一个时间段内完成所有访问的费用低于分两组完成的费用。您可以通过增加 DistanceLimit.cost_per_kilometer_below_soft_max
来增强此效果。
为什么低于阈值的每公里低费用不适用
由于您希望优先选择短途行程而非长途行程,因此您可能会倾向于为长途行程设置较高的每公里费用,而为短途行程设置较低的每公里费用。但实际上,这会产生相反的效果:由于过渡的前 100 米最便宜,因此优化器会优先选择接近或超过 100 米的过渡,从而最大限度地利用这些“便宜”的米数。
您可以在两个示例解决方案中看到此效果。如果您将阈值上下的每公里费用互换,路线费用会发生变化:
高于阈值的费用较高 | 低于阈值时费用较高 | |||
---|---|---|---|---|
解决方案 1 | 解决方案 2 | 解决方案 1 | 解决方案 2 | |
低于阈值的公里数 | 0.45 | 0.38 | 0.45 | 0.38 |
低于阈值的每公里费用 | 1.00 | 1.00 | 50.00 | 50.00 |
高于阈值的 KM | 3.71 | 3.78 | 3.71 | 3.78 |
超出阈值的每公里费用 | 50.00 | 50.00 | 1.00 | 1.00 |
总费用 | 185.95 | 189.38 | 26.21 | 22.78 |
对于每个版本,系统会以粗体突出显示两种解决方案的总费用中较低者。您可以看到,当您使用高于阈值的高成本时,访问次数分组的路线的总成本现在更高,这与您想要实现的目标相反。