|
| 1 | +## 多点最优路径规划 - (商旅问题,拼车,餐饮配送,包裹配送,包裹取件,回程单) |
| 2 | + |
| 3 | +### 作者 |
| 4 | +digoal |
| 5 | + |
| 6 | +### 日期 |
| 7 | +2017-04-09 |
| 8 | + |
| 9 | +### 标签 |
| 10 | +PostgreSQL , PostGIS , pgrouting , 商旅问题 , 拼车 , 餐饮配送 , 包裹配送 , 包裹取件 , 回程单 |
| 11 | + |
| 12 | +---- |
| 13 | + |
| 14 | +## 背景 |
| 15 | +小长假,带着一家人出去旅行,计划好了去几个地方,如何设计旅行线路是最优的?(里面还涉及到路费,路途时间等因素)。 |
| 16 | + |
| 17 | + |
| 18 | + |
| 19 | +又比如 拼车,餐饮配送,包裹取件、配送,都包含最佳路径计算的共性在里面。 |
| 20 | + |
| 21 | +PostgreSQL 在GIS领域有这非常丰富的用户和实际案例,路径规划方面,我之前写过一篇关于包裹配送的文章 |
| 22 | + |
| 23 | +[《聊一聊双十一背后的技术 - 物流、动态路径规划》](../201611/20161114_01.md) |
| 24 | + |
| 25 | +在商旅问题,拼车,餐饮配送,包裹取件、配送,等诸多最佳路径计算的需求方面,PostgreSQL又是如何满足需求的呢? |
| 26 | + |
| 27 | +## pgrouting 核心功能 |
| 28 | +pgRouting library contains following features: |
| 29 | + |
| 30 | +- All Pairs Shortest Path, Johnson’s Algorithm |
| 31 | + |
| 32 | +- All Pairs Shortest Path, Floyd-Warshall Algorithm |
| 33 | + |
| 34 | +- Shortest Path A* |
| 35 | + |
| 36 | +- Bi-directional Dijkstra Shortest Path |
| 37 | + |
| 38 | +- Bi-directional A* Shortest Path |
| 39 | + |
| 40 | +- Shortest Path Dijkstra |
| 41 | + |
| 42 | +- Driving Distance |
| 43 | + |
| 44 | +- K-Shortest Path, Multiple Alternative Paths |
| 45 | + |
| 46 | +- K-Dijkstra, One to Many Shortest Path |
| 47 | + |
| 48 | +- Traveling Sales Person |
| 49 | + |
| 50 | +- Turn Restriction Shortest Path (TRSP) |
| 51 | + |
| 52 | +## 最佳规划1 - 从一个点出发,经过多点,回到起点 |
| 53 | +解决 旅行、包裹配送、餐饮配送的问题 |
| 54 | + |
| 55 | +这个问题的定义如下,从一点出发,经过多点,回到起点。 |
| 56 | + |
| 57 | +Given a collection of cities and travel cost between each pair, find the cheapest way for visiting all of the cities and returning to the starting point. |
| 58 | + |
| 59 | +详情 |
| 60 | + |
| 61 | +http://docs.pgrouting.org/latest/en/TSP-family.html#tsp |
| 62 | + |
| 63 | +### 例子1 |
| 64 | +pgr_TSP - Returns a route that visits all the nodes exactly once. |
| 65 | + |
| 66 | +从5出发,经过array[-1, 3, 5, 6, -6],回到5。 |
| 67 | + |
| 68 | +``` |
| 69 | +SELECT * FROM pgr_TSP( |
| 70 | + $$ |
| 71 | + SELECT * FROM pgr_withPointsCostMatrix( |
| 72 | + 'SELECT id, source, target, cost, reverse_cost FROM edge_table ORDER BY id', |
| 73 | + 'SELECT pid, edge_id, fraction from pointsOfInterest', |
| 74 | + array[-1, 3, 5, 6, -6], directed := false); |
| 75 | + $$, |
| 76 | + start_id := 5, |
| 77 | + randomize := false |
| 78 | +); |
| 79 | + |
| 80 | + seq | node | cost | agg_cost |
| 81 | +-----+------+------+---------- |
| 82 | + 1 | 5 | 1 | 0 |
| 83 | + 2 | 6 | 1 | 1 |
| 84 | + 3 | 3 | 1.6 | 2 |
| 85 | + 4 | -1 | 1.3 | 3.6 |
| 86 | + 5 | -6 | 0.3 | 4.9 |
| 87 | + 6 | 5 | 0 | 5.2 |
| 88 | +(6 rows) |
| 89 | +``` |
| 90 | + |
| 91 | +### 例子2 |
| 92 | +pgr_eucledianTSP - Returns a route that visits all the coordinates pairs exactly once. |
| 93 | + |
| 94 | +``` |
| 95 | +SET client_min_messages TO DEBUG1; |
| 96 | +SET |
| 97 | +SELECT* from pgr_eucledianTSP( |
| 98 | + $$ |
| 99 | + SELECT id, st_X(the_geom) AS x, st_Y(the_geom) AS y FROM edge_table_vertices_pgr |
| 100 | + $$, |
| 101 | + tries_per_temperature := 0, |
| 102 | + randomize := false |
| 103 | +); |
| 104 | +DEBUG: pgr_eucledianTSP Processing Information |
| 105 | +Initializing tsp class ---> tsp.greedyInitial ---> tsp.annealing ---> OK |
| 106 | + |
| 107 | +Cycle(100) total changes =0 0 were because delta energy < 0 |
| 108 | +Total swaps: 3 |
| 109 | +Total slides: 0 |
| 110 | +Total reverses: 0 |
| 111 | +Times best tour changed: 4 |
| 112 | +Best cost reached = 18.7796 |
| 113 | + seq | node | cost | agg_cost |
| 114 | +-----+------+------------------+------------------ |
| 115 | + 1 | 1 | 1.4142135623731 | 0 |
| 116 | + 2 | 3 | 1 | 1.4142135623731 |
| 117 | + 3 | 4 | 1 | 2.41421356237309 |
| 118 | + 4 | 9 | 0.58309518948453 | 3.41421356237309 |
| 119 | + 5 | 16 | 0.58309518948453 | 3.99730875185762 |
| 120 | + 6 | 6 | 1 | 4.58040394134215 |
| 121 | + 7 | 5 | 1 | 5.58040394134215 |
| 122 | + 8 | 8 | 1 | 6.58040394134215 |
| 123 | + 9 | 7 | 1.58113883008419 | 7.58040394134215 |
| 124 | + 10 | 14 | 1.499999999999 | 9.16154277142634 |
| 125 | + 11 | 15 | 0.5 | 10.6615427714253 |
| 126 | + 12 | 13 | 1.5 | 11.1615427714253 |
| 127 | + 13 | 17 | 1.11803398874989 | 12.6615427714253 |
| 128 | + 14 | 12 | 1 | 13.7795767601752 |
| 129 | + 15 | 11 | 1 | 14.7795767601752 |
| 130 | + 16 | 10 | 2 | 15.7795767601752 |
| 131 | + 17 | 2 | 1 | 17.7795767601752 |
| 132 | + 18 | 1 | 0 | 18.7795767601752 |
| 133 | +(18 rows) |
| 134 | +``` |
| 135 | + |
| 136 | +## 最佳规划2 - 从一个点出发,经过多点,到达终点 |
| 137 | +拼车的问题更加复杂一些, |
| 138 | + |
| 139 | +从一个点出发(司机位置),经过多点(所有拼车乘客的上车地点),再去到多点(拼车乘客的下车地点)。 |
| 140 | + |
| 141 | +拼车的问题可以分为两个阶段来解决, |
| 142 | + |
| 143 | +第一个阶段,从司机位置到接上所有拼车乘客。 |
| 144 | + |
| 145 | +第二个阶段,从最后一个乘客上车地点,到达所有乘客的下车地点。 |
| 146 | + |
| 147 | +两个阶段的规划需求是一样的,从一个点出发,经过多点,到达终点。 |
| 148 | + |
| 149 | +详情 |
| 150 | + |
| 151 | +http://docs.pgrouting.org/latest/en/TSP-family.html#tsp |
| 152 | + |
| 153 | +### 例子 |
| 154 | +详情 |
| 155 | + |
| 156 | +http://docs.pgrouting.org/latest/en/pgr_dijkstraVia.html#pgr-dijkstravia |
| 157 | + |
| 158 | +Given a list of vertices and a graph, this function is equivalent to finding the shortest path between vertexivertexi and vertexi+1vertexi+1 for all i<size_of(vertexvia)i<size_of(vertexvia). |
| 159 | + |
| 160 | +## 参考 |
| 161 | +所有用到的路由函数,点对点成本矩阵函数,请参考 |
| 162 | + |
| 163 | +http://pgrouting.org/ |
| 164 | + |
| 165 | +[《聊一聊双十一背后的技术 - 物流、动态路径规划》](../201611/20161114_01.md) |
| 166 | + |
| 167 | +http://docs.pgrouting.org/latest/en/TSP-family.html#tsp |
0 commit comments