Yen’s 最短路径算法
简介
Yen’s 最短路径算法用于计算两个节点之间的多条最短路径。该算法通常被称为 Yen’s k-最短路径算法,其中 k 是要计算的最短路径数量。该算法支持带有正向关系权重的加权图。在计算多条最短路径时,它还会考虑相同两个节点之间的平行关系。
对于 k = 1,该算法的行为与 Dijkstra 最短路径算法完全相同,返回最短路径。对于 k = 2,该算法会返回同一源节点和目标节点之间的最短路径和次短路径。通常,对于 k = n,该算法会计算最多 n 条路径,并按总成本从小到大的顺序发现它们。
GDS 的实现基于原始描述。在实际的路径计算中,Yen’s 算法使用 Dijkstra 最短路径算法。该算法确保不会重复遍历已经发现的最短路径。
该算法的实现是并行化的,但受到源-目标路径中节点数量的限制。如果预期这些路径的长度较短(即仅包含少量新节点),则不建议设置较高的并发值,因为部分核心可能无法得到利用。
语法
本节介绍执行 Yen’s 最短路径算法所使用的语法。
CALL Neo4j_Graph_Analytics.graph.yens(
'CPU_X64_XS', (1)
{
['defaultTablePrefix': '...',] (2)
'project': {...}, (3)
'compute': {...}, (4)
'write': {...} (5)
}
);
| 1 | 计算池选择器。 |
| 2 | 表引用的可选前缀。 |
| 3 | 项目配置。 |
| 4 | 计算配置。 |
| 5 | 写入配置。 |
| 名称 | 类型 | 默认 | 可选 | 描述 |
|---|---|---|---|---|
computePoolSelector |
字符串 |
|
否 |
用于运行 Yen’s 最短路径算法作业的计算池选择器。 |
配置 |
Map |
|
否 |
用于图项目、算法计算和结果回写的配置。 |
配置映射由以下三个条目组成。
| 有关以下项目配置的更多详细信息,请参阅 项目文档。 |
| 名称 | 类型 |
|---|---|
nodeTables |
节点表列表。 |
relationshipTables |
关系类型到关系表的映射。 |
| 名称 | 类型 | 默认 | 可选 | 描述 |
|---|---|---|---|---|
sourceNode |
整数或字符串 |
|
否 |
源节点标识符。 |
sourceNodeTable |
字符串 |
|
否 |
用于映射源节点标识符的表。 |
targetNode |
整数或字符串 |
|
否 |
目标节点标识符。 |
targetNodeTable |
字符串 |
|
否 |
用于映射目标节点标识符的表。 |
k |
整数 |
|
否 |
源节点和目标节点之间要计算的最短路径数量。 |
resultProperty |
字符串 |
|
是 |
将回写到 Snowflake 数据库的关系属性。 |
resultRelationshipType |
字符串 |
|
是 |
用于回写到 Snowflake 数据库的关系类型。 |
relationshipWeightProperty |
字符串 |
|
是 |
用作权重的关系属性名称。如果未指定,算法将作为无权重运行。 |
| 关于下文写入配置的更多详细信息,请参考 写入文档。 |
| 名称 | 类型 | 默认 | 可选 | 描述 |
|---|---|---|---|---|
sourceLabel |
字符串 |
|
否 |
内存图中待回写关系起始节点的节点标签。 |
targetLabel |
字符串 |
|
否 |
内存图中待回写关系结束节点的节点标签。 |
outputTable |
字符串 |
|
否 |
关系写入的 Snowflake 数据库表。 |
关系类型 (relationshipType) |
字符串 |
|
是 |
将回写到 Snowflake 数据库的关系类型。 |
relationshipProperty |
字符串 |
|
是 |
将回写到 Snowflake 数据库的关系属性。 |
示例
现在,我们将了解如何将 Yen’s 最短路径算法应用于道路网络。
CREATE OR REPLACE TABLE EXAMPLE_DB.DATA_SCHEMA.LOCATIONS (NODEID VARCHAR);
INSERT INTO EXAMPLE_DB.DATA_SCHEMA.LOCATIONS VALUES
('A'),
('B'),
('C'),
('D'),
('E'),
('F');
CREATE OR REPLACE TABLE EXAMPLE_DB.DATA_SCHEMA.ROADS (SOURCENODEID VARCHAR, TARGETNODEID VARCHAR, COST FLOAT);
INSERT INTO EXAMPLE_DB.DATA_SCHEMA.ROADS VALUES
('A', 'B', 50),
('A', 'C', 50),
('A', 'D', 100),
('B', 'D', 40),
('C', 'D', 40),
('C', 'E', 80),
('D', 'E', 30),
('D', 'F', 80),
('E', 'F', 40);
我们使用上表作为输入,并将它们投影到内存图(in-memory graph)中。该图构建了一个包含地点间道路的交通网络。与现实世界一样,图中的道路具有不同的长度。这些长度由 cost 关系属性表示。
在下面的示例中,我们将演示如何使用此图来运行 Yen’s 最短路径算法。
运行作业
运行 Yen’s 最短路径算法作业涉及三个步骤:投影 (Project)、计算 (Compute) 和写入 (Write)。
CALL Neo4j_Graph_Analytics.graph.yens('CPU_X64_XS', {
'defaultTablePrefix': 'EXAMPLE_DB.DATA_SCHEMA',
'project': {
'nodeTables': [ 'LOCATIONS' ],
'relationshipTables': {
'ROADS': {
'sourceTable': 'LOCATIONS',
'targetTable': 'LOCATIONS'
}
}
},
'compute': {
'sourceNode': 'A',
'sourceNodeTable': 'LOCATIONS',
'targetNode': 'E',
'k': 3,
'targetNodeTable': 'LOCATIONS',
'relationshipWeightProperty': 'COST'
},
'write': [{
'sourceLabel': 'LOCATIONS',
'targetLabel': 'LOCATIONS',
'outputTable': 'PATHS'
}]
});
| JOB_ID | JOB_STATUS | JOB_START | JOB_END | JOB_RESULT |
|---|---|---|---|---|
job_8fde6ff409b14e32946625921a264811 |
SUCCESS |
2026-03-16 21:56:45.771000 |
2026-03-16 21:56:53.839000 |
{
"yens_1": {
"computeMillis": 79,
"configuration": {
"concurrency": 6,
"resultRelationshipType": "PATH",
"nodeLabels": [
"*"
],
"relationshipTypes": [
"*"
],
"relationshipWeightProperty": "COST",
"sourceNode": "A",
"sourceNodeTable": "EXAMPLE_DB.DATA_SCHEMA.LOCATIONS",
"targetNode": "E",
}
},
"project_1": {
"graphName": "snowgraph",
"nodeCount": 6,
"nodeLabels": ...,
"nodeMillis": 265,
"relationshipCount": 9,
"relationshipMillis": 741,
"relationshipTypes": ...,
"totalMillis": 1006
},
"write_relationship_type_1": {
"outputTable": "EXAMPLE_DB.DATA_SCHEMA.PATHS",
"relationshipProperty": "[SOURCENODEID, TARGETNODEID, NODEIDS, NODELABELS, COSTS, TOTALCOST]",
"relationshipType": "PATH",
"rowsWritten": 3,
"writeMillis": 2869
}
} |
返回的结果包含有关任务执行的信息。此外,最短路径已写回 Snowflake 数据库。我们可以像这样进行查询
SELECT * FROM EXAMPLE_DB.DATA_SCHEMA.PATHS;
这显示了存储在数据库中的计算结果
| SOURCENODEID | TARGETNODEID | NODEIDS | NODELABELS | COSTS | TOTALCOST |
|---|---|---|---|---|---|
A |
E |
["A", "B", "D", "E"] |
["LOCATIONS", "LOCATIONS", "LOCATIONS", "LOCATIONS"] |
[0, 50, 90, 120] |
120 |
A |
E |
["A", "C", "D", "E"] |
["LOCATIONS", "LOCATIONS", "LOCATIONS", "LOCATIONS"] |
[0, 50, 90, 120] |
120 |
A |
E |
["A", "D", "E"] |
["LOCATIONS", "LOCATIONS", "LOCATIONS"] |
[0, 100, 130] |
130 |
结果显示了节点 A 和节点 E 之间最短路径的总成本。前两条路径的总成本相同,但第一条路径通过 B 节点从 A 遍历到 D,而第二条路径则通过 C 节点。第三条路径的总成本更高,因为它使用成本为 100 的关系直接从 A 到 D,而前两条路径经由 B 和 C 的绕路成本各为 50。这一点可以在示例图中进行验证。