pgr_pickDeliverEuclidean - 实验

pgr_pickDeliverEuclidean -取货和送货车辆路径问题

Warning

可能服务器崩溃

  • 这些功能可能会导致服务器崩溃

Warning

实验功能

  • 它们不是当前版本的正式版本。

  • 它们可能不会正式成为下一个版本的一部分:

    • 这些函数可能不使用 ANY-INTEGER 和 ANY-NUMERICAL

    • 名称可能会改变。

    • 签名可能会改变。

    • 功能可能会改变。

    • pgTap 测试可能丢失。

    • 可能需要 c/c++编码。

    • 可能缺乏文档。

    • 文档(如果有)可能需要重写。

    • 可能需要自动生成文档示例。

    • 可能需要社区的大量反馈。

    • 可能取决于 pgRouting 的拟议功能

    • 可能依赖于 pgRouting 的已弃用函数

可用性

  • 版本3.0.0

    • 替换 pgr_gsoc_vrppdtw

    • 实验 函数

概要

问题:将取货-送货对分配并优化到车队中。

  • 优化问题是NP-hard。

  • 取货和送货:

    • 带容量限制的

    • 有时间窗口的。

  • 车辆

    • 有 (x, y) 开始和结束位置。

    • 有开始和结束服务时间。

    • 有开始和结束地点的开放和关闭时间。

  • 订单用于取货和送货。

    • 有 (x, y) 个取货和送货地点。

    • 有提货和送货地点的开放和关闭时间。

    • 有取货和送货服务时间。

  • 有客户需要送货。

    • 客户之间的旅行时间是距离/速度

    • 取货和送货是使用同一辆车完成的。

    • 送货前会进行取货。

特征

  • 一个位置没有多个时间窗口。

  • 使用的车辆越少越好。

  • 总持续时间越短越好。

  • 等待时间越短越好。

  • 六种不同的可选不同初始解决方案

    • 找到的最佳解决方案将作为结果

标识

pgr_pickDeliverEuclidean(Orders SQL, Vehicles SQL, [options])
options: [factor, max_cycles, initial_sol]
返回 (seq, vehicle_number, vehicle_id, stop, order_id, stop_type, cargo, travel_time, arrival_time, wait_time, service_time, departure_time) 的集合
示例:

解决以下问题

给定车辆:

SELECT id, capacity, start_x, start_y, start_open, start_close
FROM vehicles;
 id | capacity | start_x | start_y | start_open | start_close
----+----------+---------+---------+------------+-------------
  1 |       50 |       3 |       2 |          0 |          50
  2 |       50 |       3 |       2 |          0 |          50
(2 rows)

和顺序:

SELECT id, demand,
       p_x, p_y, p_open, p_close, p_service,
       d_x, d_y, d_open, d_close, d_service
FROM orders;
 id | demand | p_x | p_y | p_open | p_close | p_service | d_x | d_y | d_open | d_close | d_service
----+--------+-----+-----+--------+---------+-----------+-----+-----+--------+---------+-----------
  1 |     10 |   3 |   1 |      2 |      10 |         3 |   1 |   2 |      6 |      15 |         3
  2 |     20 |   4 |   2 |      4 |      15 |         2 |   4 |   1 |      6 |      20 |         3
  3 |     30 |   2 |   2 |      2 |      10 |         3 |   3 |   3 |      3 |      20 |         3
(3 rows)

查询:

SELECT * FROM pgr_pickDeliverEuclidean(
  $$SELECT id, demand,
       p_x, p_y, p_open, p_close, p_service,
       d_x, d_y, d_open, d_close, d_service
    FROM orders$$,
  $$SELECT id, capacity, start_x, start_y, start_open, start_close
    FROM vehicles$$);
 seq | vehicle_seq | vehicle_id | stop_seq | stop_type | order_id | cargo |  travel_time  | arrival_time  | wait_time | service_time | departure_time
-----+-------------+------------+----------+-----------+----------+-------+---------------+---------------+-----------+--------------+----------------
   1 |           1 |          1 |        1 |         1 |       -1 |     0 |             0 |             0 |         0 |            0 |              0
   2 |           1 |          1 |        2 |         2 |        3 |    30 |             1 |             1 |         1 |            3 |              5
   3 |           1 |          1 |        3 |         3 |        3 |     0 | 1.41421356237 | 6.41421356237 |         0 |            3 |  9.41421356237
   4 |           1 |          1 |        4 |         2 |        2 |    20 | 1.41421356237 | 10.8284271247 |         0 |            2 |  12.8284271247
   5 |           1 |          1 |        5 |         3 |        2 |     0 |             1 | 13.8284271247 |         0 |            3 |  16.8284271247
   6 |           1 |          1 |        6 |         6 |       -1 |     0 | 1.41421356237 | 18.2426406871 |         0 |            0 |  18.2426406871
   7 |           2 |          2 |        1 |         1 |       -1 |     0 |             0 |             0 |         0 |            0 |              0
   8 |           2 |          2 |        2 |         2 |        1 |    10 |             1 |             1 |         1 |            3 |              5
   9 |           2 |          2 |        3 |         3 |        1 |     0 |  2.2360679775 |  7.2360679775 |         0 |            3 |  10.2360679775
  10 |           2 |          2 |        4 |         6 |       -1 |     0 |             2 | 12.2360679775 |         0 |            0 |  12.2360679775
  11 |          -2 |          0 |        0 |        -1 |       -1 |    -1 | 11.4787086646 |            -1 |         2 |           17 |  30.4787086646
(11 rows)

参数

类型

描述

Orders SQL

TEXT

Orders SQL 如下所述。

Vehicles SQL

TEXT

Vehicles SQL 如下所述。

取货-送货可选参数

类型

默认

描述

factor

NUMERIC

1

旅行时间乘数。 请参阅 因素处理

max_cycles

INTEGER

10

执行优化的最大周期数。

initial_sol

INTEGER

4

要使用的初始解决方案。

  • 1 每辆卡车一份订单

  • 2 提前订单。

  • 3 推迟订单。

  • 4 优化插入。

  • 5 推迟订单,允许在后面插入更多订单

  • 6 提前订单,允许在前面插入更多订单

订单 SQL

返回以下列的 SELECT 语句:

id, demand
p_x, p_y, p_open, p_close, [p_service,]
d_x, d_y, d_open, d_close, [d_service]

其中:

类型

描述

id

ANY-INTEGER

提货-交货订单对的标识符。

demand

ANY-NUMERICAL

订单中的单位数量

p_open

ANY-NUMERICAL

相对于0的时间,提货地点开放。

p_close

ANY-NUMERICAL

提货地点关闭的时间(相对于 0)。

[p_service]

ANY-NUMERICAL

在取货地点装载的持续时间。

  • 缺失时:使用 0 个时间单位

d_open

ANY-NUMERICAL

交货地点开放的时间(相对于 0)。

d_close

ANY-NUMERICAL

交货地点关闭的时间(相对于 0)。

[d_service]

ANY-NUMERICAL

在交货地点卸货的持续时间。

  • 缺失时:使用 0 个时间单位

其中:

ANY-INTEGER:

SMALLINT, INTEGER, BIGINT

ANY-NUMERICAL:

SMALLINT, INTEGER, BIGINT, REAL, FLOAT

类型

描述

p_x

ANY-NUMERICAL

取货地点的 \(x\)

p_y

ANY-NUMERICAL

取货地点的 \(y\)

d_x

ANY-NUMERICAL

送货地点的 \(x\)

d_y

ANY-NUMERICAL

送货地点的 \(y\)

其中:

ANY-NUMERICAL:

SMALLINT, INTEGER, BIGINT, REAL, FLOAT

车辆 SQL

返回以下列的 SELECT 语句:

id, capacity
start_x, start_y, start_open, start_close [, start_service, ]
[ end_x, end_y, end_open, end_close, end_service ]

其中:

类型

描述

id

ANY-NUMERICAL

车辆的标识符。

capacity

ANY-NUMERICAL

最大容量单位

start_open

ANY-NUMERICAL

起始位置打开的时间(相对于 0)。

start_close

ANY-NUMERICAL

起始位置关闭的时间(相对于 0)。

[start_service]

ANY-NUMERICAL

在起始位置加载的持续时间。

  • 缺失时:使用 \(0\) 个时间单位的持续时间。

[end_open]

ANY-NUMERICAL

结束位置打开的时间(相对于 0)。

  • 缺失时:使用 start_open 的值

[end_close]

ANY-NUMERICAL

结束位置关闭的时间(相对于 0)。

  • 缺失时:使用 start_close 的值

[end_service]

ANY-NUMERICAL

在结束位置加载的持续时间。

  • 缺失时:使用 start_service 中的持续时间。

类型

描述

start_x

ANY-NUMERICAL

起始位置的 \(x\)

start_y

ANY-NUMERICAL

起始位置的 \(y\)

[end_x]

ANY-NUMERICAL

结束位置的 \(x\)

  • 缺失时:使用 start_x 值。

[end_y]

ANY-NUMERICAL

结束位置的 \(y\)

  • 缺失时:使用 start_y 值。

其中:

ANY-NUMERICAL:

SMALLINT, INTEGER, BIGINT, REAL, FLOAT

结果列

Returns set of
 (seq, vehicle_seq, vehicle_id, stop_seq, stop_type,
     travel_time, arrival_time, wait_time, service_time, departure_time)
 UNION
 (summary row)

类型

描述

seq

INTEGER

1 开始的顺序值。

vehicle_seq

INTEGER

当前车辆从 1 开始的顺序值。 解决方案中的第 \(n_{th}\) 辆车。

  • \(-2\) 表示它是汇总行。

vehicle_id

BIGINT

当前车辆标识符。

  • 摘要行有 总容量违规情况

    • 当车辆超载或欠载时,就会发生容量违规。

stop_seq

INTEGER

当前车辆停止的顺序值,从 1 开始。 当前第 \(m_{th}\) 车辆的停止。

  • 摘要行包含 总时间窗口违规情况

    • 在该地点关闭后到达时,会发生时间窗口违规。

stop_type

INTEGER

  • 车辆所在的停车位置类型

    • \(-1\): 在解决方案摘要行

    • \(1\): 起始位置

    • \(2\): 取货位置

    • \(3\): 送货位置

    • \(6\): 结束位置并指示车辆的摘要行

order_id

BIGINT

取货-送货订单对标识符。

  • \(-1\): 当前停留位置没有订单参与。

cargo

FLOAT

车辆离开停车点时的货物单位。

  • \(-1\) 在解决方案摘要行。

travel_time

FLOAT

从前一个 stop_seq 到当前 stop_seq 的行程时间。

  • 总结一下 总的行程时间

    • 所有 travel_time 的总和。

arrival_time

FLOAT

等待当前位置打开所花费的时间。

  • \(-1\): 在解决方案摘要行。

  • \(0\): 在起始位置。

wait_time

FLOAT

等待当前位置打开所花费的时间。

  • 摘要行包含 总等待时间

    • 所有 wait_time 的总和。

service_time

FLOAT

当前位置的服务持续时间。

  • 摘要行包含 总服务时间

    • 所有 service_time 的总和。

departure_time

FLOAT

  • 车辆离开车站的时间。

    • \(arrival\_time + wait\_time + service\_time\)

  • 结束位置有当前车辆使用的 总时间

  • 摘要行包含 总解决问题时间

    • \(total\ traveling\ time + total\ waiting\ time + total\ service\ time\)

示例

此数据示例 lc101 来自 https://www.sintef.no/projectweb/top/pdptw/li-lim-benchmark/ 上发布的数据

车辆

问题中有 25 辆车都具有相同的特征。

CREATE TABLE v_lc101(
  id BIGINT NOT NULL primary key,
  capacity BIGINT DEFAULT 200,
  start_x FLOAT DEFAULT 30,
  start_y FLOAT DEFAULT 50,
  start_open INTEGER DEFAULT 0,
  start_close INTEGER DEFAULT 1236);
CREATE TABLE
/* create 25 vehciles */
INSERT INTO v_lc101 (id)
(SELECT * FROM generate_series(1, 25));
INSERT 0 25

原始订单

对于同一订单的取货和配送,数据位于不同的行中。

CREATE table lc101_c(
  id BIGINT not null primary key,
  x DOUBLE PRECISION,
  y DOUBLE PRECISION,
  demand INTEGER,
  open INTEGER,
  close INTEGER,
  service INTEGER,
  pindex BIGINT,
  dindex BIGINT
);
CREATE TABLE
/* the original data */
INSERT INTO lc101_c(
  id,     x,    y, demand, open, close, service, pindex, dindex) VALUES
(  1,    45,   68,   -10,   912,   967,   90,   11,    0),
(  2,    45,   70,   -20,   825,   870,   90,    6,    0),
(  3,    42,   66,    10,    65,   146,   90,    0,   75),
(  4,    42,   68,   -10,   727,   782,   90,    9,    0),
(  5,    42,   65,    10,    15,    67,   90,    0,    7),
(  6,    40,   69,    20,   621,   702,   90,    0,    2),
(  7,    40,   66,   -10,   170,   225,   90,    5,    0),
(  8,    38,   68,    20,   255,   324,   90,    0,   10),
(  9,    38,   70,    10,   534,   605,   90,    0,    4),
( 10,    35,   66,   -20,   357,   410,   90,    8,    0),
( 11,    35,   69,    10,   448,   505,   90,    0,    1),
( 12,    25,   85,   -20,   652,   721,   90,   18,    0),
( 13,    22,   75,    30,    30,    92,   90,    0,   17),
( 14,    22,   85,   -40,   567,   620,   90,   16,    0),
( 15,    20,   80,   -10,   384,   429,   90,   19,    0),
( 16,    20,   85,    40,   475,   528,   90,    0,   14),
( 17,    18,   75,   -30,    99,   148,   90,   13,    0),
( 18,    15,   75,    20,   179,   254,   90,    0,   12),
( 19,    15,   80,    10,   278,   345,   90,    0,   15),
( 20,    30,   50,    10,    10,    73,   90,    0,   24),
( 21,    30,   52,   -10,   914,   965,   90,   30,    0),
( 22,    28,   52,   -20,   812,   883,   90,   28,    0),
( 23,    28,   55,    10,   732,   777,    0,    0,  103),
( 24,    25,   50,   -10,    65,   144,   90,   20,    0),
( 25,    25,   52,    40,   169,   224,   90,    0,   27),
( 26,    25,   55,   -10,   622,   701,   90,   29,    0),
( 27,    23,   52,   -40,   261,   316,   90,   25,    0),
( 28,    23,   55,    20,   546,   593,   90,    0,   22),
( 29,    20,   50,    10,   358,   405,   90,    0,   26),
( 30,    20,   55,    10,   449,   504,   90,    0,   21),
( 31,    10,   35,   -30,   200,   237,   90,   32,    0),
( 32,    10,   40,    30,    31,   100,   90,    0,   31),
( 33,     8,   40,    40,    87,   158,   90,    0,   37),
( 34,     8,   45,   -30,   751,   816,   90,   38,    0),
( 35,     5,   35,    10,   283,   344,   90,    0,   39),
( 36,     5,   45,    10,   665,   716,    0,    0,  105),
( 37,     2,   40,   -40,   383,   434,   90,   33,    0),
( 38,     0,   40,    30,   479,   522,   90,    0,   34),
( 39,     0,   45,   -10,   567,   624,   90,   35,    0),
( 40,    35,   30,   -20,   264,   321,   90,   42,    0),
( 41,    35,   32,   -10,   166,   235,   90,   43,    0),
( 42,    33,   32,    20,    68,   149,   90,    0,   40),
( 43,    33,   35,    10,    16,    80,   90,    0,   41),
( 44,    32,   30,    10,   359,   412,   90,    0,   46),
( 45,    30,   30,    10,   541,   600,   90,    0,   48),
( 46,    30,   32,   -10,   448,   509,   90,   44,    0),
( 47,    30,   35,   -10,  1054,  1127,   90,   49,    0),
( 48,    28,   30,   -10,   632,   693,   90,   45,    0),
( 49,    28,   35,    10,  1001,  1066,   90,    0,   47),
( 50,    26,   32,    10,   815,   880,   90,    0,   52),
( 51,    25,   30,    10,   725,   786,    0,    0,  101),
( 52,    25,   35,   -10,   912,   969,   90,   50,    0),
( 53,    44,    5,    20,   286,   347,   90,    0,   58),
( 54,    42,   10,    40,   186,   257,   90,    0,   60),
( 55,    42,   15,   -40,    95,   158,   90,   57,    0),
( 56,    40,    5,    30,   385,   436,   90,    0,   59),
( 57,    40,   15,    40,    35,    87,   90,    0,   55),
( 58,    38,    5,   -20,   471,   534,   90,   53,    0),
( 59,    38,   15,   -30,   651,   740,   90,   56,    0),
( 60,    35,    5,   -40,   562,   629,   90,   54,    0),
( 61,    50,   30,   -10,   531,   610,   90,   67,    0),
( 62,    50,   35,    20,   262,   317,   90,    0,   68),
( 63,    50,   40,    50,   171,   218,   90,    0,   74),
( 64,    48,   30,    10,   632,   693,    0,    0,  102),
( 65,    48,   40,    10,    76,   129,   90,    0,   72),
( 66,    47,   35,    10,   826,   875,   90,    0,   69),
( 67,    47,   40,    10,    12,    77,   90,    0,   61),
( 68,    45,   30,   -20,   734,   777,   90,   62,    0),
( 69,    45,   35,   -10,   916,   969,   90,   66,    0),
( 70,    95,   30,   -30,   387,   456,   90,   81,    0),
( 71,    95,   35,    20,   293,   360,   90,    0,   77),
( 72,    53,   30,   -10,   450,   505,   90,   65,    0),
( 73,    92,   30,   -10,   478,   551,   90,   76,    0),
( 74,    53,   35,   -50,   353,   412,   90,   63,    0),
( 75,    45,   65,   -10,   997,  1068,   90,    3,    0),
( 76,    90,   35,    10,   203,   260,   90,    0,   73),
( 77,    88,   30,   -20,   574,   643,   90,   71,    0),
( 78,    88,   35,    20,   109,   170,    0,    0,  104),
( 79,    87,   30,    10,   668,   731,   90,    0,   80),
( 80,    85,   25,   -10,   769,   820,   90,   79,    0),
( 81,    85,   35,    30,    47,   124,   90,    0,   70),
( 82,    75,   55,    20,   369,   420,   90,    0,   85),
( 83,    72,   55,   -20,   265,   338,   90,   87,    0),
( 84,    70,   58,    20,   458,   523,   90,    0,   89),
( 85,    68,   60,   -20,   555,   612,   90,   82,    0),
( 86,    66,   55,    10,   173,   238,   90,    0,   91),
( 87,    65,   55,    20,    85,   144,   90,    0,   83),
( 88,    65,   60,   -10,   645,   708,   90,   90,    0),
( 89,    63,   58,   -20,   737,   802,   90,   84,    0),
( 90,    60,   55,    10,    20,    84,   90,    0,   88),
( 91,    60,   60,   -10,   836,   889,   90,   86,    0),
( 92,    67,   85,    20,   368,   441,   90,    0,   93),
( 93,    65,   85,   -20,   475,   518,   90,   92,    0),
( 94,    65,   82,   -10,   285,   336,   90,   96,    0),
( 95,    62,   80,   -20,   196,   239,   90,   98,    0),
( 96,    60,   80,    10,    95,   156,   90,    0,   94),
( 97,    60,   85,    30,   561,   622,    0,    0,  106),
( 98,    58,   75,    20,    30,    84,   90,    0,   95),
( 99,    55,   80,   -20,   743,   820,   90,  100,    0),
( 100,   55,   85,    20,   647,   726,   90,    0,   99),
( 101,   25,   30,   -10,   725,   786,   90,   51,    0),
( 102,   48,   30,   -10,   632,   693,   90,   64,    0),
( 103,   28,   55,   -10,   732,   777,   90,   23,    0),
( 104,   88,   35,   -20,   109,   170,   90,   78,    0),
( 105,    5,   45,   -10,   665,   716,   90,   36,    0),
( 106,   60,   85,   -30,   561,   622,   90,   97,    0);
INSERT 0 106

订单

需要将原始数据转换为合适的表格:

WITH deliveries AS (SELECT * FROM lc101_c WHERE dindex = 0)
SELECT
  row_number() over() AS id, p.demand,
  p.id as p_node_id, p.x AS p_x, p.y AS p_y, p.open AS p_open, p.close as p_close, p.service as p_service,
  d.id as d_node_id, d.x AS d_x, d.y AS d_y, d.open AS d_open, d.close as d_close, d.service as d_service
INTO c_lc101
FROM deliveries as d JOIN lc101_c as p ON (d.pindex = p.id);
SELECT 53
SELECT * FROM c_lc101 LIMIT 1;
 id | demand | p_node_id | p_x | p_y | p_open | p_close | p_service | d_node_id | d_x | d_y | d_open | d_close | d_service
----+--------+-----------+-----+-----+--------+---------+-----------+-----------+-----+-----+--------+---------+-----------
  1 |     10 |         3 |  42 |  66 |     65 |     146 |        90 |        75 |  45 |  65 |    997 |    1068 |        90
(1 row)

查询

仅显示相关信息,以便与 https://www.sintef.no/projectweb/top/pdptw/100-customers/ 上发布的最佳解决方案信息进行比较

  • 找到的 lc101 的最佳解是行程时间:828.94

  • 此实施的行程时间:854.54

SELECT travel_time, 828.94 AS best
FROM pgr_pickDeliverEuclidean(
  $$SELECT * FROM c_lc101 $$,
  $$SELECT * FROM v_lc101 $$,
  max_cycles => 2, initial_sol => 4) WHERE vehicle_seq = -2;
    travel_time    |  best
-------------------+--------
 854.5412705652799 | 828.94
(1 row)

另请参阅

索引和表格