shortest_path,包含总线和时间表

时间:2013-07-22 15:28:29

标签: postgresql shortest-path bus pgrouting

我正在寻找解决方案,但是找不到解决方法。

我的目标是根据公交车之间的时间找到2个公交车站之间的最短路程。

所以我有总线和每个时间表。成本由实际公交车站和下一个公交车站之间的时间差(以秒为单位)表示。来源和目标是巴士站的ID

问题是:我有一些并行链接,因为每辆公共汽车每天多次排队,每次都以相同的方式运行。

我尝试过使用pgrouting的shortest_path函数,但由于并行链接,它会多次返回错误的解决方案。

我见过关于shooting_star,但我不认为我可以在没有几何体的情况下使用它。

我使用PostGIS 2.0.1获得PostGreSQL 9.1.9。以下是我的数据库提取示例:

        id        |      idcourse     |    source    |    target    |    cost    |
        1         |           1       |       62     |      34      |      60    |
        2         |           1       |       34     |      16      |     360    |
        3         |           1       |       16     |      61      |      60    |
        4         |           1       |       61     |      60      |      120   |
        5         |           2       |       62     |      34      |      60    |

这里的最后一行与其他行(idcourse = 1)相同,但一小时后

以下是获取此信息的请求:

select hc.idhorairecourse as id, c.idcourse,
hc.idarret as source,
(select hc2.idarret from horairecourse hc2 where hc2.idcourse = c.idcourse and hc2.heure > hc.heure order by hc2.heure limit 1) as target,
(extract(epoch from ((select horairecourse.heure from horairecourse where horairecourse.idcourse = c.idcourse and horairecourse.heure > hc.heure order by horairecourse.heure limit 1) - hc.heure))) as cost
from course c
inner join horairecourse hc on c.idcourse = hc.idcourse
where (select horairecourse.idarret from horairecourse where horairecourse.idcourse = c.idcourse and horairecourse.heure > hc.heure order by horairecourse.heure limit 1) is not null
order by c.idcourse, hc.heure

1 个答案:

答案 0 :(得分:1)

除了一条公交线路的多个实例的问题之外,这个带rCTE (recursive Common Table Expression)的查询解决了所述的问题:

  

我的目标是找到两个巴士站之间的最短路径,基于   公共汽车在他们之间的时间。

WITH RECURSIVE
   from_to AS (SELECT 34 AS _from, 60 AS _to)  -- insert from & to once

,  route AS (
   SELECT target, ARRAY[_from, target] AS stops, cost
       , (target = _to) AS arrived
   FROM   from_to, bus
   WHERE  source = _from

   UNION ALL
   SELECT b.target, r.stops || b.target, r.cost + b.cost
       , (b.target = _to) AS arrived
   FROM   from_to, route r
   JOIN   bus   b ON b.source = r.target
   WHERE  b.target <> ALL(stops) -- don't circle
   AND    r. target <> _to       -- we arrived
   )
SELECT stops, cost
FROM   route
WHERE  arrived
ORDER  BY cost
LIMIT  1;

<强> -> SQLfiddle demo.

您可以在此过程中轻松收集更多信息。

算法遍历每个连接,并检查它是否已经存在(放弃)或者它是否已到达(成功)。然后选择最短的成功途径。

这适用于中小型基数。但是,对于大表,不能很好地扩展,因为每个可能的路径(不进入圆圈)都会被尝试。递归CTE无法检查另一条路径是否已在较短时间内成功。通过消除已经花费太长时间的所有路由,专用算法可以更好地执行。您可以使用plpgsql函数执行此操作,但在C中实现它会快得多。