使用转换属性优先处理附近的访问

此示例展示了如何使用过渡属性来优先考虑在同一时间段内由同一车辆执行附近取货和送货的路线。如需详细了解过渡属性,请参阅使用过渡属性对业务逻辑进行建模

在此示例中:

  • 货物 A、B 和 C 的送货地址位于同一条道路上,彼此相距不远。
  • 后续还将有更多交付。
  • 配送没有指定配送时间。
  • 无论访问时间表如何,车辆都需要在这条道路上行驶两次:一次是在早上从补给站出发时,另一次是在晚上返回时。
  • 无论何时执行 A、B 和 C,路线的总行驶距离和时长始终保持不变。

示例:在同一条道路上配送多批货物。有三批货物 A、B 和 C 正在从配送中心运往其他货物。A 距离仓库 1000 米,B 距离仓库比 A 远 50 米,C 距离仓库比 B 远 30 米,方向相同。还有其他货物距离 C 点 1000 米。

在这种情况下,对于仅使用每小时费用和每公里费用的请求,优化后的路线可能是在上午处理 A 和 B,在晚上处理 C,而解决方案的费用与同时处理这三项任务的费用相同。

具有阈值的每公里费用

如需对附近的访问进行分组,您首先需要选择距离阈值。这是您认为两次访问属于邻近访问的最大距离。此示例使用 100 米的阈值,大致相当于城市区域中的一个街区。您可以根据业务需求和司机的偏好提高或降低此阈值。

若要将彼此相距 100 米以内的附近访问归为一组,您可以为每次转换的前 100 米设置较高的费用,并为转换的任何额外米数设置较低的费用。由于前 100 米的费用最高,因此即使这意味着延长路线的总长度,优化器也会通过使用短于 100 米阈值的过渡来节省最多的费用。

如需设置费用,请向 ShipmentModel.transition_attributes 添加一个新条目,并设置以下属性:

{
  "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 米 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

对于每个版本,系统会以粗体突出显示两种解决方案的总费用中较低者。您可以看到,当您使用高于阈值的高成本时,访问次数分组的路线的总成本现在更高,这与您想要实现的目标恰恰相反。