收缩 - 函数族

介绍

在大型图中,例如道路图或电网,图收缩可用于加速某些图算法。 收缩通过删除一些顶点和边来减小图的大小,例如,可能会添加表示原始边序列的边,从而减少图算法中使用的总时间和空间。

该实现为将来添加收缩算法提供了灵活的框架,目前它支持两种算法:

  1. 死端收缩

  2. 线性收缩

允许用户:

  • 禁止在一组节点上收缩。

  • 决定收缩算法的顺序并设置它们要执行的最大次数。

死端收缩

图的叶节点的收缩。

死端

当一个节点被认为是 死端 节点时

  • 在无向图上:

    • 相邻顶点的个数为1。

  • 在有向图上:

    • 相邻顶点的个数为1。

    • 没有传出边缘,但至少有一个传入边缘。

    • 没有传入边缘,但至少有一个传出边缘。

当条件成立时,可以进行当条件成立时,可以进行 操作: 死端收缩

无向图上的死端顶点

  • 绿色节点是 死端 节点

  • 蓝色节点具有无限数量的边。

graph G {
    u, v [shape=circle;style=filled;width=.4;color=deepskyblue];
    a, b [style=filled; color=green];
    G [shape=tripleoctagon;width=1.5;style=filled;
       color=deepskyblue;label = "Rest of the Graph"];

    rankdir=LR;
    G -- {u, v} [dir=none, weight=1, penwidth=3];
    u -- a [color=black];
    u -- a [color=darkgray];
    v -- b;
}

节点

相邻节点

相邻节点数

\(a\)

\(\{u\}\)

1

\(b\)

\(\{v\}\)

1

有向图上的死端顶点

  • 绿色节点是 死端 节点

  • 蓝色节点具有无限数量的传入和/或传出边缘。

digraph G {
    u, v, w, x, y [shape=circle;style=filled;width=.4;color=deepskyblue];
    a, b, c, d, e [style=filled; color=green];
    G [shape=tripleoctagon;width=1.5;style=filled;
       color=deepskyblue;label = "Rest of the Graph"];

    rankdir=LR;
    G -> {u, v, w} [dir=none, weight=1, penwidth=3];
    {x, y} -> G [dir=none, weight=1, penwidth=3];
    u -> a -> u;
    v -> b;
    {w, v} -> c;
    d -> x;
    e -> {x, y};
}

节点

相邻节点

相邻节点数

传入边数

传出边数

\(a\)

\(\{u\}\)

1

\(b\)

\(\{v\}\)

1

\(c\)

\(\{v, w\}\)

2

2

0

\(d\)

\(\{x\}\)

1

\(e\)

\(\{x, y\}\)

2

0

2

从上面来看,节点 \(\{a, b, d\}\) 是死端,因为相邻顶点的数量为 1。不需要对这些节点进行进一步检查。

下表中,节点 \(\{c, e\}\) 因为相邻顶点数不为1的偶数为

  • \(c\)

    • 没有传出边缘,但至少有一个传入边缘。

  • \(e\)

    • 没有传入边缘,但至少有一个传出边缘。

操作:死端收缩

死端收缩将停止,直到不再有死端节点。 例如,从下图中,其中 \(w\)死端 节点:

digraph G {
    u, v [shape=circle;style=filled;width=.4;color=deepskyblue];
    w [style=filled; color=green];
    "G" [shape=tripleoctagon;style=filled;
    color=deepskyblue; label = "Rest of the Graph"];

    rankdir=LR;
    G -> u [dir=none, weight=1, penwidth=3];
    u -> v -> w;
}

收缩 \(w\) 后,节点 \(v\) 现在是一个 死端 节点并且已收缩:

digraph G {
    u [shape=circle;style=filled;width=.4;color=deepskyblue];
    v [style=filled; color=green, label="v{w}"];
    "G" [shape=tripleoctagon;style=filled;
        color=deepskyblue; label = "Rest of the Graph"];

    rankdir=LR;
    G -> u [dir=none, weight=1, penwidth=3];
    u -> v;
}

在收缩 \(v\) 之后,停止。节点 \(u\) 有已收缩节点的信息。

digraph G {
    u [style=filled; color=green, label="u{v,w}"];
    "G" [shape=tripleoctagon;style=filled;
         color=deepskyblue; label = "Rest of the Graph"];

    rankdir=LR;
    G -> u [dir=none, weight=1, penwidth=3];
}

节点 \(u\) 有已收缩节点的信息。

线性收缩

算法中,线性收缩用2表示。

线性

在无向图的情况下,当满足以下条件时,节点被视为`线性`节点

  • 相邻顶点的数量为2。

在有向图的情况下,当满足以下条件时,节点被视为`线性`节点

  • 相邻顶点的数量为2。

  • 线性是对称的

无向图上的线性顶点

  • 绿色节点是 线性 节点

  • 蓝色节点具有无限数量的传入和传出边缘。

无向

graph G {
    u, w [shape=circle;style=filled;width=.4;color=deepskyblue];
    v [style=filled; color=green];
    G [shape=tripleoctagon;width=1.5;style=filled;
       color=deepskyblue;label = "Rest of the Graph"];

    rankdir=LR;
    w -- G -- u [dir=none, weight=1, penwidth=3];
    u -- v -- w;
}

节点

相邻节点

相邻节点数

\(v\)

\(\{u, w\}\)

2

有向图上的线性顶点

  • 绿色节点是 线性 节点

  • 蓝色节点具有无限数量的传入和传出边缘。

  • 白色节点不是线性的,因为线性不对称。

    • 它是可能去走 \(y \rightarrow c \rightarrow z\)

    • 不可能走 \(z \rightarrow c \rightarrow y\)

digraph G {
    u, v, w, x, y, z [shape=circle;style=filled;width=.4;color=deepskyblue];
    a, b [style=filled; color=green];
    G [shape=tripleoctagon;width=1.5;style=filled;
      color=deepskyblue;label = "Rest of the Graph"];

    rankdir=LR;
    {u, v} -> G -> {x, w, y, z} [dir=none, weight=1, penwidth=3];
    u -> a -> v;
    w -> b -> x;
    x -> b -> w [color=darkgray];
    y -> c -> z -> c;
}

节点

相邻节点

相邻节点数

是对称的吗?

\(a\)

\(\{u, v\}\)

2

\(b\)

\(\{w, x\}\)

2

\(c\)

\(\{y, z\}\)

2

操作:线性收缩

当不再有线性节点时,线性收缩将停止。 例如,在下图中,其中 \(v\)\(w\)线性 节点:

digraph G {
    u, z [shape=circle;style=filled;color=deepskyblue];
    v, w [style=filled; color=green];
    "G" [shape=tripleoctagon; style=filled;
         color=deepskyblue;label = "Rest of the Graph"];

    rankdir=LR;
    G -> {u, z} [dir=none, weight=1, penwidth=3];
    u -> v -> w -> z;
}

收缩 \(w\)

  • 顶点 \(w\) 已从图中移除

  • 从图中删除边 \(v \rightarrow w\)\(w \rightarrow z\)

  • 插入一条新边 \(v \rightarrow z\),以红色表示。

digraph G {
    u, z [shape=circle;style=filled;color=deepskyblue];
    v [style=filled; color=green];
    "G" [shape=tripleoctagon; style=filled;
         color=deepskyblue;label = "Rest of the Graph"];

    rankdir=LR;
    G -> {u, z} [dir=none, weight=1, penwidth=3];
    u -> v;
    v -> z [label="{w}";color=red]
}

收缩 \(v\)

  • 顶点 \(v\) 已从图中移除

  • 从图中删除边 \(u \rightarrow v\)\(v \rightarrow z\)

  • 插入一条新边 \(u \rightarrow z\),以红色表示。

digraph G {
    u, z [shape=circle;style=filled;color=deepskyblue];
    "G" [shape=tripleoctagon; style=filled;
         color=deepskyblue;label = "Rest of the Graph"];

    rankdir=LR;
    G -> {u, z} [dir=none, weight=1, penwidth=3];
    u -> z [label="{v, w}";color=red]
}

\(u \rightarrow z\) 有收缩点的信息。

循环

收缩一张图可以通过多个操作来完成。 操作的顺序会影响生成的收缩图,在应用一个操作后,可以由另一操作收缩的顶点集会发生变化。

此实现通过 operations_order``循环 ``max_cycles 次。

<input>
do max_cycles times {
    for (operation in operations_order)
     { do operation }
}
<output>

收缩示例数据

在本节中,将通过示例展示构建和使用收缩图。

  • 使用无向图的 示例数据

  • 首先是死端操作,然后是线性操作。

数据库中图的构建

原始数据

以下查询显示了收缩操作所涉及的原始数据。

SELECT id, source, target, cost, reverse_cost
FROM edges ORDER BY id;
 id | source | target | cost | reverse_cost
----+--------+--------+------+--------------
  1 |      5 |      6 |    1 |            1
  2 |      6 |     10 |   -1 |            1
  3 |     10 |     15 |   -1 |            1
  4 |      6 |      7 |    1 |            1
  5 |     10 |     11 |    1 |           -1
  6 |      1 |      3 |    1 |            1
  7 |      3 |      7 |    1 |            1
  8 |      7 |     11 |    1 |            1
  9 |     11 |     16 |    1 |            1
 10 |      7 |      8 |    1 |            1
 11 |     11 |     12 |    1 |           -1
 12 |      8 |     12 |    1 |           -1
 13 |     12 |     17 |    1 |           -1
 14 |      8 |      9 |    1 |            1
 15 |     16 |     17 |    1 |            1
 16 |     15 |     16 |    1 |            1
 17 |      2 |      4 |    1 |            1
 18 |     13 |     14 |    1 |            1
(18 rows)

原始图:

_images/Fig6-undirected.png

收缩结果

结果不代表收缩图。 它们表示应用收缩算法后对图所做的更改。

例如,观察到顶点 \(6\) 没有出现在结果中,因为它不受收缩算法的影响。

SELECT * FROM pgr_contraction(
  'SELECT id, source, target, cost, reverse_cost FROM edges',
  array[1, 2], directed => false);
 type | id | contracted_vertices | source | target | cost
------+----+---------------------+--------+--------+------
 v    |  4 | {2}                 |     -1 |     -1 |   -1
 v    |  7 | {1,3}               |     -1 |     -1 |   -1
 v    | 14 | {13}                |     -1 |     -1 |   -1
 e    | -1 | {5,6}               |      7 |     10 |    2
 e    | -2 | {8,9}               |      7 |     12 |    2
 e    | -3 | {17}                |     12 |     16 |    2
 e    | -4 | {15}                |     10 |     16 |    2
(7 rows)

进行死端收缩操作后:

_images/undirected_sampledata_b.png

对上图进行线性收缩运算后:

_images/undirected_sampledata_c.png

在数据库上创建收缩图的过程:

添加附加列

edge_table 和``edge_table_vertices_pgr`` 表添加额外的列,其中:

描述

contracted_vertices

属于顶点/边的顶点集

is_contracted

在顶点表上

  • true 时,顶点收缩,它不是收缩图的一部分。

  • false 时,顶点不收缩,它是收缩图的一部分。

is_new

在边表上

  • true 时,边缘由收缩算法生成。 它是收缩图的一部分。

  • false 时,边是原始边,可能是也可能不是收缩图的一部分。

ALTER TABLE vertices ADD is_contracted BOOLEAN DEFAULT false;
ALTER TABLE
ALTER TABLE vertices ADD contracted_vertices BIGINT[];
ALTER TABLE
ALTER TABLE edges ADD is_new BOOLEAN DEFAULT false;
ALTER TABLE
ALTER TABLE edges ADD contracted_vertices BIGINT[];
ALTER TABLE

存储收缩信息

收缩结果 存储在表中

SELECT * INTO contraction_results
FROM pgr_contraction(
  'SELECT id, source, target, cost, reverse_cost FROM edges',
  array[1, 2], directed => false);
SELECT 7

顶点表更新

使用 is_contracted 列来指示收缩的顶点。

UPDATE vertices
SET is_contracted = true
WHERE id IN (SELECT  unnest(contracted_vertices) FROM  contraction_results);
UPDATE 10

使用属于顶点的结果中的信息填充 contracted_vertices

UPDATE vertices
SET contracted_vertices = contraction_results.contracted_vertices
FROM contraction_results
WHERE type = 'v' AND vertices.id = contraction_results.id;
UPDATE 3

修改后的顶点表:

SELECT id, contracted_vertices, is_contracted
FROM vertices
ORDER BY id;
 id | contracted_vertices | is_contracted
----+---------------------+---------------
  1 |                     | t
  2 |                     | t
  3 |                     | t
  4 | {2}                 | f
  5 |                     | t
  6 |                     | t
  7 | {1,3}               | f
  8 |                     | t
  9 |                     | t
 10 |                     | f
 11 |                     | f
 12 |                     | f
 13 |                     | t
 14 | {13}                | f
 15 |                     | t
 16 |                     | f
 17 |                     | t
(17 rows)

边缘表更新

插入由 pgr_contraction 生成的新边。

INSERT INTO edges(source, target, cost, reverse_cost, contracted_vertices, is_new)
SELECT source, target, cost, -1, contracted_vertices, true
FROM contraction_results
WHERE type = 'e';
INSERT 0 4

修改后的 edge_table

SELECT id, source, target, cost, reverse_cost, contracted_vertices, is_new
FROM edges
ORDER BY id;
 id | source | target | cost | reverse_cost | contracted_vertices | is_new
----+--------+--------+------+--------------+---------------------+--------
  1 |      5 |      6 |    1 |            1 |                     | f
  2 |      6 |     10 |   -1 |            1 |                     | f
  3 |     10 |     15 |   -1 |            1 |                     | f
  4 |      6 |      7 |    1 |            1 |                     | f
  5 |     10 |     11 |    1 |           -1 |                     | f
  6 |      1 |      3 |    1 |            1 |                     | f
  7 |      3 |      7 |    1 |            1 |                     | f
  8 |      7 |     11 |    1 |            1 |                     | f
  9 |     11 |     16 |    1 |            1 |                     | f
 10 |      7 |      8 |    1 |            1 |                     | f
 11 |     11 |     12 |    1 |           -1 |                     | f
 12 |      8 |     12 |    1 |           -1 |                     | f
 13 |     12 |     17 |    1 |           -1 |                     | f
 14 |      8 |      9 |    1 |            1 |                     | f
 15 |     16 |     17 |    1 |            1 |                     | f
 16 |     15 |     16 |    1 |            1 |                     | f
 17 |      2 |      4 |    1 |            1 |                     | f
 18 |     13 |     14 |    1 |            1 |                     | f
 19 |      7 |     10 |    2 |           -1 | {5,6}               | t
 20 |      7 |     12 |    2 |           -1 | {8,9}               | t
 21 |     12 |     16 |    2 |           -1 | {17}                | t
 22 |     10 |     16 |    2 |           -1 | {15}                | t
(22 rows)

收缩图

属于收缩图的顶点。

SELECT id
FROM vertices
WHERE is_contracted = false
ORDER BY id;
 id
----
  4
  7
 10
 11
 12
 14
 16
(7 rows)

属于收缩图的边。

WITH
vertices_in_graph AS (
  SELECT id
  FROM vertices
  WHERE is_contracted = false
)
SELECT id, source, target, cost, reverse_cost, contracted_vertices
FROM edges
WHERE source IN (SELECT * FROM vertices_in_graph)
AND target IN (SELECT * FROM vertices_in_graph)
ORDER BY id;
 id | source | target | cost | reverse_cost | contracted_vertices
----+--------+--------+------+--------------+---------------------
  5 |     10 |     11 |    1 |           -1 |
  8 |      7 |     11 |    1 |            1 |
  9 |     11 |     16 |    1 |            1 |
 11 |     11 |     12 |    1 |           -1 |
 19 |      7 |     10 |    2 |           -1 | {5,6}
 20 |      7 |     12 |    2 |           -1 | {8,9}
 21 |     12 |     16 |    2 |           -1 | {17}
 22 |     10 |     16 |    2 |           -1 | {15}
(8 rows)

收缩图

_images/newgraph.png

使用收缩图

将收缩图与 pgr_dijkstra 一起使用

计算收缩图中给定源和目标之间的最短路径时,存在三种情况:

  • 情况1:源和目标都属于收缩图。

  • 情况 2:源和/或目标属于边缘子图。

  • 情况 3:源和/或目标属于一个顶点。

情况1:源和目标都属于收缩图。

使用 属于收缩图的边。 第 11 至 20 行。

 1CREATE OR REPLACE FUNCTION my_dijkstra(
 2  departure BIGINT, destination BIGINT,
 3  OUT seq INTEGER, OUT path_seq INTEGER,
 4  OUT start_vid BIGINT, OUT end_vid BIGINT,
 5  OUT node BIGINT, OUT edge BIGINT,
 6  OUT cost FLOAT, OUT agg_cost FLOAT)
 7RETURNS SETOF RECORD AS
 8$BODY$
 9SELECT * FROM pgr_dijkstra(
10  $$
11  WITH
12  vertices_in_graph AS (
13    SELECT id
14    FROM vertices
15    WHERE is_contracted = false
16  )
17  SELECT id, source, target, cost, reverse_cost
18  FROM edges
19  WHERE source IN (SELECT * FROM vertices_in_graph)
20  AND target IN (SELECT * FROM vertices_in_graph)
21  $$,
22  departure, destination, false);
23$BODY$
24LANGUAGE SQL VOLATILE;
25CREATE FUNCTION

情况1

当源和目标都属于收缩图时,就找到了一条路径。

SELECT * FROM my_dijkstra(10, 12);
 seq | path_seq | start_vid | end_vid | node | edge | cost | agg_cost
-----+----------+-----------+---------+------+------+------+----------
   1 |        1 |        10 |      12 |   10 |    5 |    1 |        0
   2 |        2 |        10 |      12 |   11 |   11 |    1 |        1
   3 |        3 |        10 |      12 |   12 |   -1 |    0 |        2
(3 rows)

情况2

当源和/或目标属于边缘子图时,则找不到路径。

在这种情况下,收缩图没有与节点 \(4\) 相连的边。

SELECT * FROM my_dijkstra(15, 12);
 seq | path_seq | start_vid | end_vid | node | edge | cost | agg_cost
-----+----------+-----------+---------+------+------+------+----------
(0 rows)

情况3

当源和/或目标属于顶点时,则找不到路径。

在这种情况下,收缩图没有与第二种情况的节点 \(7\) 和节点 \(4\) 连接的边。

SELECT * FROM my_dijkstra(15, 1);
 seq | path_seq | start_vid | end_vid | node | edge | cost | agg_cost
-----+----------+-----------+---------+------+------+------+----------
(0 rows)

情况 2:源和/或目标属于边缘子图。

改进上述函数以包含属于边的节点。

  • 需要扩展的顶点在第 11 至 17 行计算。

  • 将第 26 至 28 行的附加部分添加到收缩图中。

 1CREATE OR REPLACE FUNCTION my_dijkstra(
 2  departure BIGINT, destination BIGINT,
 3  OUT seq INTEGER, OUT path_seq INTEGER,
 4  OUT start_vid BIGINT, OUT end_vid BIGINT,
 5  OUT node BIGINT, OUT edge BIGINT,
 6  OUT cost FLOAT, OUT agg_cost FLOAT)
 7RETURNS SETOF RECORD AS
 8$BODY$
 9SELECT * FROM pgr_dijkstra(
10  $$
11  WITH
12  edges_to_expand AS (
13    SELECT id
14    FROM edges
15    WHERE ARRAY[$$ || departure || $$]::BIGINT[] <@ contracted_vertices
16    OR ARRAY[$$ || destination || $$]::BIGINT[] <@ contracted_vertices
17  ),
18
19  vertices_in_graph AS (
20    SELECT id
21    FROM vertices
22    WHERE is_contracted = false
23
24    UNION
25
26    SELECT unnest(contracted_vertices)
27    FROM edges
28    WHERE id IN (SELECT id FROM edges_to_expand)
29  )
30
31  SELECT id, source, target, cost, reverse_cost
32  FROM edges
33  WHERE source IN (SELECT * FROM vertices_in_graph)
34  AND target IN (SELECT * FROM vertices_in_graph)
35  $$,
36  departure, destination, false);
37$BODY$
38LANGUAGE SQL VOLATILE;
39CREATE FUNCTION

情况1

当源和目标都属于收缩图时,就找到了一条路径。

SELECT * FROM my_dijkstra(10, 12);
 seq | path_seq | start_vid | end_vid | node | edge | cost | agg_cost
-----+----------+-----------+---------+------+------+------+----------
   1 |        1 |        10 |      12 |   10 |    5 |    1 |        0
   2 |        2 |        10 |      12 |   11 |   11 |    1 |        1
   3 |        3 |        10 |      12 |   12 |   -1 |    0 |        2
(3 rows)

情况2

当源和目标都属于收缩图时,就找到了一条路径。

路由图现在有一条与节点 \(4\) 连接的边。

SELECT * FROM my_dijkstra(15, 12);
 seq | path_seq | start_vid | end_vid | node | edge | cost | agg_cost
-----+----------+-----------+---------+------+------+------+----------
   1 |        1 |        15 |      12 |   15 |   16 |    1 |        0
   2 |        2 |        15 |      12 |   16 |   21 |    2 |        1
   3 |        3 |        15 |      12 |   12 |   -1 |    0 |        3
(3 rows)

情况3

当源和/或目标属于顶点时,则找不到路径。

在这种情况下,收缩图没有与节点 \(7\) 相连的边。

SELECT * FROM my_dijkstra(15, 1);
 seq | path_seq | start_vid | end_vid | node | edge | cost | agg_cost
-----+----------+-----------+---------+------+------+------+----------
(0 rows)

情况 3:源和/或目标属于一个顶点。

改进上述函数以包含属于边的节点。

  • 需要扩展的顶点在第19到24行计算。

  • 将第 38 至 40 行的附加部分添加到收缩图中。

 1CREATE OR REPLACE FUNCTION my_dijkstra(
 2  departure BIGINT, destination BIGINT,
 3  OUT seq INTEGER, OUT path_seq INTEGER,
 4  OUT start_vid BIGINT, OUT end_vid BIGINT,
 5  OUT node BIGINT, OUT edge BIGINT,
 6  OUT cost FLOAT, OUT agg_cost FLOAT)
 7RETURNS SETOF RECORD AS
 8$BODY$
 9SELECT * FROM pgr_dijkstra(
10  $$
11  WITH
12  edges_to_expand AS (
13    SELECT id
14    FROM edges
15    WHERE ARRAY[$$ || departure || $$]::BIGINT[] <@ contracted_vertices
16    OR ARRAY[$$ || destination || $$]::BIGINT[] <@ contracted_vertices
17  ),
18
19  vertices_to_expand AS (
20    SELECT id
21    FROM vertices
22    WHERE ARRAY[$$ || departure || $$]::BIGINT[] <@ contracted_vertices
23    OR ARRAY[$$ || destination || $$]::BIGINT[] <@ contracted_vertices
24  ),
25
26  vertices_in_graph AS (
27    SELECT id
28    FROM vertices
29    WHERE is_contracted = false
30
31    UNION
32
33    SELECT unnest(contracted_vertices)
34    FROM edges
35    WHERE id IN (SELECT id FROM edges_to_expand)
36
37    UNION
38
39    SELECT unnest(contracted_vertices)
40    FROM vertices
41    WHERE id IN (SELECT id FROM vertices_to_expand)
42  )
43
44  SELECT id, source, target, cost, reverse_cost
45  FROM edges
46  WHERE source IN (SELECT * FROM vertices_in_graph)
47  AND target IN (SELECT * FROM vertices_in_graph)
48  $$,
49  departure, destination, false);
50$BODY$
51LANGUAGE SQL VOLATILE;
52CREATE FUNCTION

情况1

当源和目标都属于收缩图时,就找到了一条路径。

SELECT * FROM my_dijkstra(10, 12);
 seq | path_seq | start_vid | end_vid | node | edge | cost | agg_cost
-----+----------+-----------+---------+------+------+------+----------
   1 |        1 |        10 |      12 |   10 |    5 |    1 |        0
   2 |        2 |        10 |      12 |   11 |   11 |    1 |        1
   3 |        3 |        10 |      12 |   12 |   -1 |    0 |        2
(3 rows)

情况2

代码更改不会影响这种情况,因此当源和/或目标属于边缘子图时,仍然会找到路径。

SELECT * FROM my_dijkstra(15, 12);
 seq | path_seq | start_vid | end_vid | node | edge | cost | agg_cost
-----+----------+-----------+---------+------+------+------+----------
   1 |        1 |        15 |      12 |   15 |   16 |    1 |        0
   2 |        2 |        15 |      12 |   16 |   21 |    2 |        1
   3 |        3 |        15 |      12 |   12 |   -1 |    0 |        3
(3 rows)

情况3

当源和/或目标属于一个顶点时,现在就找到了一条路径。

现在,路由图有一条与节点 \(7\) 连接的边。

SELECT * FROM my_dijkstra(15, 1);
 seq | path_seq | start_vid | end_vid | node | edge | cost | agg_cost
-----+----------+-----------+---------+------+------+------+----------
   1 |        1 |        15 |       1 |   15 |    3 |    1 |        0
   2 |        2 |        15 |       1 |   10 |   19 |    2 |        1
   3 |        3 |        15 |       1 |    7 |    7 |    1 |        3
   4 |        4 |        15 |       1 |    3 |    6 |    1 |        4
   5 |        5 |        15 |       1 |    1 |   -1 |    0 |        5
(5 rows)

另请参阅

索引和表格