Leiden

术语表

有向

有向特征。该算法在有向图上定义良好。

有向

有向特征。该算法忽略图的方向。

有向

有向特征。该算法不能在有向图上运行。

无向

无向特征。该算法在无向图上定义良好。

无向

无向特征。该算法忽略图的无向性。

异构节点

异构节点完全支持。该算法有能力区分不同类型的节点。

异构节点

异构节点允许。该算法平等对待所有选定的节点,无论其标签如何。

异构关系

异构关系完全支持。该算法有能力区分不同类型的关系。

异构关系

异构关系允许。该算法平等对待所有选定的关系,无论其类型如何。

加权关系

加权特征。该算法支持将关系属性用作权重,通过 relationshipWeightProperty 配置参数指定。

加权关系

加权特征。该算法将每个关系视为同等重要,忽略任何关系权重值。

节点属性

节点属性特征。该算法使用节点属性。

简介

Leiden 算法是一种用于检测大型网络中社区的算法。该算法将节点划分为不相交的社区,以最大化每个社区的模块度(Modularity)得分。模块度量化了节点分配到社区的质量,即社区内节点的连接密度,与随机网络中预期连接密度的对比。

Leiden 算法是一种层次聚类算法,它通过贪婪地优化模块度,递归地将社区合并为单个节点,并在压缩后的图中重复此过程。它改进了 Louvain 算法,以解决其部分缺陷,即 Louvain 发现的某些社区连接不够紧密的问题。这是通过定期随机地将社区分解为更小的紧密连接社区来实现的。

有关此算法的更多信息,请参阅

运行此算法需要足够的可用内存。在运行之前,建议您阅读 内存估计 (Memory Estimation)

语法

本节介绍在每种执行模式下运行 Leiden 算法所使用的语法。我们这里描述的是命名图(Named Graph)的语法变体。要了解有关通用语法变体的更多信息,请参阅 语法概述

各模式下的 Leiden 语法
在命名图上以流(stream)模式运行 Leiden。
CALL gds.leiden.stream(
  graphName: String,
  configuration: Map
)
YIELD
  nodeId: Integer,
  communityId: Integer,
  intermediateCommunityIds: List of Integer
表 1. 参数
名称 类型 默认 可选 描述

graphName

字符串

不适用

存储在目录中的图的名称。

配置

Map

{}

算法特定配置和/或图过滤配置。

表 2. 配置
名称 类型 默认 可选 描述

nodeLabels

字符串列表

['*']

使用给定的节点标签过滤命名图。具有任何给定标签的节点都将被包含。

relationshipTypes

字符串列表

['*']

使用给定的关系类型过滤命名图。具有任何给定类型的关系都将被包含。

concurrency

整数

4 [1]

用于运行算法的并发线程数。

jobId

字符串

内部生成

可以提供一个 ID 以更轻松地跟踪算法的进度。

logProgress

布尔值

true

如果禁用,进度百分比将不会被记录。

relationshipWeightProperty

字符串

null

用作权重的关系属性名称。如果未指定,算法将作为无权重运行。

maxLevels

整数

10

图进行聚类并随后压缩的最大层级数。

gamma

浮点数

1.0

计算模块度时使用的分辨率参数。在内部,该值对于无权图会除以关系总数,否则除以所有关系权重之和。[2]

theta

浮点数

0.01

控制将社区分解为较小社区时的随机性。

tolerance

浮点数

0.0001

迭代之间模块度的最小变化值。如果模块度变化小于该容差值,则结果被视为稳定,算法终止。

includeIntermediateCommunities

布尔值

false

指示是否写入中间社区。如果设置为 false,则仅保留最终的社区。

seedProperty

字符串

不适用

用于设置节点的初始社区。属性值必须为非负数。

consecutiveIds

布尔值

false

用于决定组件标识符是否映射到连续 ID 空间的标志(需要额外的内存)。

randomSeed

整数

不适用

控制算法随机性的种子值。

minCommunitySize

整数

0

仅返回属于大于或等于给定值的社区的节点。

1. 在 GDS 会话中,默认值为可用处理器的数量。

2. 更高的分辨率会导致更多的社区,而较低的分辨率会导致更少的社区。

表 3. 结果
名称 类型 描述

nodeId

整数

节点 ID。

communityId

整数

最终层级的社区 ID。

intermediateCommunityIds

整数列表

每一层级的社区 ID。如果 includeIntermediateCommunities 设置为 false,则返回 Null

在命名图上以统计(stats)模式运行 Leiden。
CALL gds.leiden.stats(
  graphName: String,
  configuration: Map
)
YIELD
  preProcessingMillis: Integer,
  computeMillis: Integer,
  postProcessingMillis: Integer,
  communityCount: Integer,
  ranLevels: Integer,
  modularity: Float,
  modularities: List of Float,
  nodeCount: Integer,
  didConverge: Boolean,
  communityDistribution: Map,
  configuration: Map
表 4. 参数
名称 类型 默认 可选 描述

graphName

字符串

不适用

存储在目录中的图的名称。

配置

Map

{}

算法特定配置和/或图过滤配置。

表 5. 配置
名称 类型 默认 可选 描述

nodeLabels

字符串列表

['*']

使用给定的节点标签过滤命名图。具有任何给定标签的节点都将被包含。

relationshipTypes

字符串列表

['*']

使用给定的关系类型过滤命名图。具有任何给定类型的关系都将被包含。

concurrency

整数

4 [3]

用于运行算法的并发线程数。

jobId

字符串

内部生成

可以提供一个 ID 以更轻松地跟踪算法的进度。

logProgress

布尔值

true

如果禁用,进度百分比将不会被记录。

relationshipWeightProperty

字符串

null

用作权重的关系属性名称。如果未指定,算法将作为无权重运行。

maxLevels

整数

10

图进行聚类并随后压缩的最大层级数。

gamma

浮点数

1.0

计算模块度时使用的分辨率参数。在内部,该值对于无权图会除以关系总数,否则除以所有关系权重之和。[4]

theta

浮点数

0.01

控制将社区分解为较小社区时的随机性。

tolerance

浮点数

0.0001

迭代之间模块度的最小变化值。如果模块度变化小于该容差值,则结果被视为稳定,算法终止。

includeIntermediateCommunities

布尔值

false

指示是否写入中间社区。如果设置为 false,则仅保留最终的社区。

seedProperty

字符串

不适用

用于设置节点的初始社区。属性值必须为非负数。

consecutiveIds

布尔值

false

用于决定组件标识符是否映射到连续 ID 空间的标志(需要额外的内存)。

randomSeed

整数

不适用

控制算法随机性的种子值。

3. 在 GDS 会话中,默认值为可用处理器的数量。

4. 更高的分辨率会导致更多的社区,而较低的分辨率会导致更少的社区。

表 6. 结果
名称 类型 描述

preProcessingMillis

整数

预处理数据的毫秒数。

computeMillis

整数

运行算法的毫秒数。

postProcessingMillis

整数

计算百分位数和社区数量所需的毫秒数。

communityCount

整数

发现的社区数量。

ranLevels

整数

算法实际运行的层级数。

modularity

浮点数

最终的模块度得分。

modularities

浮点数列表

每一层级的模块度得分。

nodeCount

整数

图中的节点数。

didConverge

布尔值

指示算法是否收敛。

communityDistribution

Map

包含最后一级社区大小的最小值、最大值、平均值以及 p1、p5、p10、p25、p50、p75、p90、p95、p99 和 p999 百分位数的映射。

配置

Map

用于运行算法的配置。

在命名图上以变更(mutate)模式运行 Leiden。
CALL gds.leiden.mutate(
  graphName: String,
  configuration: Map
)
YIELD
  preProcessingMillis: Integer,
  computeMillis: Integer,
  mutateMillis: Integer,
  postProcessingMillis: Integer,
  communityCount: Integer,
  ranLevels: Integer,
  modularity: Float,
  modularities: List of Float,
  nodeCount: Integer,
  didConverge: Boolean,
  nodePropertiesWritten: Integer,
  communityDistribution: Map,
  configuration: Map
表 7. 参数
名称 类型 默认 可选 描述

graphName

字符串

不适用

存储在目录中的图的名称。

配置

Map

{}

算法特定配置和/或图过滤配置。

表 8. 配置
名称 类型 默认 可选 描述

mutateProperty

字符串

不适用

GDS 图中写入社区 ID 的节点属性。

nodeLabels

字符串列表

['*']

使用给定的节点标签过滤命名图。

relationshipTypes

字符串列表

['*']

使用给定的关系类型过滤命名图。

concurrency

整数

4

用于运行算法的并发线程数。

logProgress

布尔值

true

如果禁用,进度百分比将不会被记录。

jobId

字符串

内部生成

可以提供一个 ID 以更轻松地跟踪算法的进度。

relationshipWeightProperty

字符串

null

用作权重的关系属性名称。如果未指定,算法将作为无权重运行。

maxLevels

整数

10

图进行聚类并随后压缩的最大层级数。

gamma

浮点数

1.0

计算模块度时使用的分辨率参数。在内部,该值对于无权图会除以关系总数,否则除以所有关系权重之和。[5]

theta

浮点数

0.01

控制将社区分解为较小社区时的随机性。

tolerance

浮点数

0.0001

迭代之间模块度的最小变化值。如果模块度变化小于该容差值,则结果被视为稳定,算法终止。

includeIntermediateCommunities

布尔值

false

指示是否写入中间社区。如果设置为 false,则仅保留最终的社区。

seedProperty

字符串

不适用

用于设置节点的初始社区。属性值必须为非负数。

consecutiveIds

布尔值

false

用于决定组件标识符是否映射到连续 ID 空间的标志(需要额外的内存)。

randomSeed

整数

不适用

控制算法随机性的种子值。

5. 更高的分辨率会导致更多的社区,而较低的分辨率会导致更少的社区。

表 9. 结果
名称 类型 描述

preProcessingMillis

整数

预处理数据的毫秒数。

computeMillis

整数

运行算法的毫秒数。

mutateMillis

整数

向投影图添加属性的毫秒数。

postProcessingMillis

整数

计算百分位数和社区数量所需的毫秒数。

communityCount

整数

发现的社区数量。

ranLevels

整数

算法实际运行的层级数。

modularity

浮点数

最终的模块度得分。

modularities

浮点数列表

每一层级的模块度得分。

nodeCount

整数

图中的节点数。

didConverge

布尔值

指示算法是否收敛。

nodePropertiesWritten

整数

添加到投影图中的属性数量。

communityDistribution

Map

包含最后一级社区大小的最小值、最大值、平均值以及 p1、p5、p10、p25、p50、p75、p90、p95、p99 和 p999 百分位数的映射。

配置

Map

用于运行算法的配置。

在命名图上以写入(write)模式运行 Leiden。
CALL gds.leiden.write(
  graphName: String,
  configuration: Map
)
YIELD
  preProcessingMillis: Integer,
  computeMillis: Integer,
  writeMillis: Integer,
  postProcessingMillis: Integer,
  communityCount: Integer,
  ranLevels: Integer,
  modularity: Float,
  modularities: List of Float,
  nodeCount: Integer,
  didConverge: Boolean,
  nodePropertiesWritten: Integer,
  communityDistribution: Map,
  configuration: Map
表 10. 参数
名称 类型 默认 可选 描述

graphName

字符串

不适用

存储在目录中的图的名称。

配置

Map

{}

算法特定配置和/或图过滤配置。

表 11. 配置
名称 类型 默认 可选 描述

nodeLabels

字符串列表

['*']

使用给定的节点标签过滤命名图。具有任何给定标签的节点都将被包含。

relationshipTypes

字符串列表

['*']

使用给定的关系类型过滤命名图。具有任何给定类型的关系都将被包含。

concurrency

整数

4 [6]

用于运行算法的并发线程数。

jobId

字符串

内部生成

可以提供一个 ID 以更轻松地跟踪算法的进度。

logProgress

布尔值

true

如果禁用,进度百分比将不会被记录。

writeConcurrency

整数

'concurrency' 的值

用于将结果写入 Neo4j 的并发线程数。

writeProperty

字符串

不适用

Neo4j 数据库中写入社区 ID 的节点属性。

relationshipWeightProperty

字符串

null

用作权重的关系属性名称。如果未指定,算法将作为无权重运行。

maxLevels

整数

10

图进行聚类并随后压缩的最大层级数。

gamma

浮点数

1.0

计算模块度时使用的分辨率参数。在内部,该值对于无权图会除以关系总数,否则除以所有关系权重之和。[7]

theta

浮点数

0.01

控制将社区分解为较小社区时的随机性。

tolerance

浮点数

0.0001

迭代之间模块度的最小变化值。如果模块度变化小于该容差值,则结果被视为稳定,算法终止。

includeIntermediateCommunities

布尔值

false

指示是否写入中间社区。如果设置为 false,则仅保留最终的社区。

seedProperty

字符串

不适用

用于设置节点的初始社区。属性值必须为非负数。

consecutiveIds

布尔值

false

用于决定组件标识符是否映射到连续 ID 空间的标志(需要额外的内存)。

randomSeed

整数

不适用

控制算法随机性的种子值。

minCommunitySize

整数

0

仅将大小大于或等于给定值的社区的社区 ID 写入 Neo4j。

6. 在 GDS Session 中,默认值为可用处理器的数量。

7. 更高的分辨率会导致更多的社区,而较低的分辨率会导致更少的社区。

表 12. 结果
名称 类型 描述

preProcessingMillis

整数

预处理数据的毫秒数。

computeMillis

整数

运行算法的毫秒数。

writeMillis

整数

向投影图添加属性的毫秒数。

postProcessingMillis

整数

计算百分位数和社区数量所需的毫秒数。

communityCount

整数

发现的社区数量。

ranLevels

整数

算法实际运行的层级数。

modularity

浮点数

最终的模块度得分。

modularities

浮点数列表

每一层级的模块度得分。

nodeCount

整数

图中的节点数。

didConverge

布尔值

指示算法是否收敛。

nodePropertiesWritten

整数

添加到 Neo4j 数据库的属性数量。

communityDistribution

Map

包含最后一级社区大小的最小值、最大值、平均值以及 p1、p5、p10、p25、p50、p75、p90、p95、p99 和 p999 百分位数的映射。

配置

Map

用于运行算法的配置。

示例

以下所有示例应在空数据库中运行。

这些示例将 Cypher 投影作为规范。原生投影将在未来版本中弃用。

在本节中,我们将展示在具体图上运行 Leiden 社区检测算法的示例。目的是说明结果的样子,并提供在实际环境中使用该算法的指南。我们将使用一个小的社交网络图来完成此操作,该图包含以特定模式连接的少数节点。示例图如下所示:

Visualization of the example graph
以下 Cypher 语句将在 Neo4j 数据库中创建示例图:
CREATE
  (nAlice:User {name: 'Alice', seed: 42}),
  (nBridget:User {name: 'Bridget', seed: 42}),
  (nCharles:User {name: 'Charles', seed: 42}),
  (nDoug:User {name: 'Doug'}),
  (nMark:User {name: 'Mark'}),
  (nMichael:User {name: 'Michael'}),

  (nAlice)-[:LINK {weight: 1}]->(nBridget),
  (nAlice)-[:LINK {weight: 1}]->(nCharles),
  (nCharles)-[:LINK {weight: 1}]->(nBridget),

  (nAlice)-[:LINK {weight: 5}]->(nDoug),

  (nMark)-[:LINK {weight: 1}]->(nDoug),
  (nMark)-[:LINK {weight: 1}]->(nMichael),
  (nMichael)-[:LINK {weight: 1}]->(nMark);

该图有两个由 用户 (Users) 组成的簇,它们连接紧密。这些簇通过一条边连接。关系属性 weight 决定了节点间各自关系的强度。

我们现在可以投射该图并将其存储在图目录中。我们将 LINK 关系加载并将方向设置为 UNDIRECTED,因为这与 Leiden 算法配合使用效果最佳。

以下语句将投影图并将其存储在图目录中。
MATCH (source:User)-[r:LINK]->(target:User)
RETURN gds.graph.project(
  'myGraph',
  source,
  target,
  {
    sourceNodeProperties: source { .seed },
    targetNodeProperties: target { .seed },
    relationshipProperties: r { .weight }
  },
  { undirectedRelationshipTypes: ['*'] }
)

在接下来的示例中,我们将演示在此图上使用 Leiden 算法。

内存估算

首先,我们将使用 estimate 过程估算运行算法的成本。这可以在任何执行模式下完成。在这个例子中我们将使用 write 模式。估算算法有助于了解在您的图上运行该算法将产生的内存影响。当您随后在其中一种执行模式下真正运行算法时,系统将执行一次估算。如果估算显示执行超出其内存限制的可能性非常高,则禁止执行。要阅读更多关于此的内容,请参阅 自动估算和执行阻塞

有关 estimate 的更多详细信息,请参阅 内存估算

以下内容将估算以写入模式运行算法所需的内存要求:
CALL gds.leiden.write.estimate('myGraph', {writeProperty: 'communityId', randomSeed: 19})
YIELD nodeCount, relationshipCount, requiredMemory
表 13. 结果
nodeCount relationshipCount requiredMemory

6

14

"[551 KiB ... 551 KiB]"

流 (Stream)

stream 执行模式下,算法会返回每个节点的社区 ID。这使我们能够直接检查结果,或者在 Cypher 中对其进行后处理,而不会产生任何副作用。

有关 stream 模式的更多详细信息,请参阅 流式读取

以下命令将运行算法并流式传输结果
CALL gds.leiden.stream('myGraph', { randomSeed: 19 })
YIELD nodeId, communityId
RETURN gds.util.asNode(nodeId).name AS name, communityId
ORDER BY name ASC
表 14. 结果
名称 (name) communityId

"Alice"

1

“Bridget”

1

“Charles”

1

“Doug”

5

“Mark”

5

“Michael”

5

我们对过程配置参数使用默认值。maxLevels 设置为 10,gammatheta 参数分别设置为 1.0 和 0.01。

统计 (Stats)

stats 执行模式下,算法返回一行包含算法结果摘要的数据。此执行模式没有任何副作用。它对于通过检查 computeMillis 返回项来评估算法性能很有用。在下面的示例中,我们将省略返回的时间信息。该过程的完整签名可以在 语法部分 中找到。

有关 stats 模式的更多详细信息,请参阅 统计

以下命令将运行算法并以统计和测量值的形式返回结果
CALL gds.leiden.stats('myGraph', { randomSeed: 19 })
YIELD communityCount
表 15. 结果
communityCount

2

变更 (Mutate)

mutate 执行模式扩展了 stats 模式,并带有一个重要的副作用:用包含该节点社区 ID 的新节点属性更新命名图。新属性的名称通过必需的配置参数 mutateProperty 指定。结果是一个摘要行,类似于 stats,但带有额外的指标。mutate 模式在多个算法协同使用时特别有用。

有关 mutate 模式的更多详细信息,请参阅 变更

以下代码将运行算法并将结果存储在 myGraph 中:
CALL gds.leiden.mutate('myGraph', { mutateProperty: 'communityId', randomSeed: 19 })
YIELD communityCount
表 16. 结果
communityCount

2

mutate 模式下,过程仅返回一行结果。该结果包含元信息,如识别出的社区数量。结果被写入 GDS 内存图,而不是 Neo4j 数据库。

写入 (Write)

write 执行模式扩展了 stats 模式,并带有一个重要的副作用:将每个节点的社区 ID 作为属性写入 Neo4j 数据库。新属性的名称通过必需的配置参数 writeProperty 指定。结果是一个摘要行,类似于 stats,但带有额外的指标。write 模式允许直接将结果持久化到数据库中。

有关 write 模式的更多详细信息,请参阅 写入

以下代码将运行算法并将结果存储在 Neo4j 数据库中:
CALL gds.leiden.write('myGraph', { writeProperty: 'communityId', randomSeed: 19 })
YIELD communityCount, nodePropertiesWritten
表 17. 结果
communityCount nodePropertiesWritten

2

6

write 模式下,过程仅返回一行结果。该结果包含元信息,如识别出的社区数量。结果被写入 Neo4j 数据库,而不是 GDS 内存图。

加权 (Weighted)

Leiden 算法也可以在加权图上运行,在计算模块度时考虑给定的关系权重。

以下代码将在加权图上运行算法并流式传输结果:
CALL gds.leiden.stream('myGraph', { relationshipWeightProperty: 'weight', randomSeed: 19 })
YIELD nodeId, communityId
RETURN gds.util.asNode(nodeId).name AS name, communityId
ORDER BY name ASC
表 18. 结果
名称 (name) communityId

"Alice"

4

“Bridget”

1

“Charles”

1

“Doug”

4

“Mark”

5

“Michael”

5

使用加权关系,我们看到 AliceDoug 形成了他们自己的社区,因为他们的链接比其他所有链接都要强得多。

使用中间社区

如前所述,Leiden 是一种层次聚类算法。这意味着在每个聚类步骤之后,所有属于同一簇的节点都会被简化为一个节点。同一簇中节点之间的关系变为自循环关系,与其他簇节点的关系则连接到该簇的代表节点。然后,这个压缩后的图被用于运行下一层聚类。该过程重复进行,直到簇稳定为止。

为了演示这种迭代行为,我们需要构建一个更复杂的图。

CREATE (a:Node {name: 'a'})
CREATE (b:Node {name: 'b'})
CREATE (c:Node {name: 'c'})
CREATE (d:Node {name: 'd'})
CREATE (e:Node {name: 'e'})
CREATE (f:Node {name: 'f'})
CREATE (g:Node {name: 'g'})
CREATE (h:Node {name: 'h'})
CREATE (i:Node {name: 'i'})
CREATE (j:Node {name: 'j'})
CREATE (k:Node {name: 'k'})
CREATE (l:Node {name: 'l'})
CREATE (m:Node {name: 'm'})
CREATE (n:Node {name: 'n'})
CREATE (x:Node {name: 'x'})

CREATE (a)-[:TYPE]->(b)
CREATE (a)-[:TYPE]->(d)
CREATE (a)-[:TYPE]->(f)
CREATE (b)-[:TYPE]->(d)
CREATE (b)-[:TYPE]->(x)
CREATE (b)-[:TYPE]->(g)
CREATE (b)-[:TYPE]->(e)
CREATE (c)-[:TYPE]->(x)
CREATE (c)-[:TYPE]->(f)
CREATE (d)-[:TYPE]->(k)
CREATE (e)-[:TYPE]->(x)
CREATE (e)-[:TYPE]->(f)
CREATE (e)-[:TYPE]->(h)
CREATE (f)-[:TYPE]->(g)
CREATE (g)-[:TYPE]->(h)
CREATE (h)-[:TYPE]->(i)
CREATE (h)-[:TYPE]->(j)
CREATE (i)-[:TYPE]->(k)
CREATE (j)-[:TYPE]->(k)
CREATE (j)-[:TYPE]->(m)
CREATE (j)-[:TYPE]->(n)
CREATE (k)-[:TYPE]->(m)
CREATE (k)-[:TYPE]->(l)
CREATE (l)-[:TYPE]->(n)
CREATE (m)-[:TYPE]->(n);
以下语句将投影图并将其存储在图目录中。
MATCH (source:Node)
OPTIONAL MATCH (source)-[r:TYPE]->(target:Node)
RETURN gds.graph.project(
  'myGraph2',
  source,
  target,
  {},
  { undirectedRelationshipTypes: ['*'] }
)

流式传输中间社区

以下代码将运行算法并流式传输包括中间社区在内的结果:
CALL gds.leiden.stream('myGraph2', {
  randomSeed: 23,
  includeIntermediateCommunities: true,
  concurrency: 1
})
YIELD nodeId, communityId, intermediateCommunityIds
RETURN gds.util.asNode(nodeId).name AS name, communityId, intermediateCommunityIds
ORDER BY name ASC
表 19. 结果
名称 (name) communityId intermediateCommunityIds

"a"

4

[2, 4]

"b"

4

[2, 4]

"c"

5

[7, 5]

"d"

4

[2, 4]

"e"

5

[6, 5]

"f"

5

[7, 5]

"g"

5

[7, 5]

"h"

5

[11, 5]

"i"

5

[11, 5]

"j"

1

[12, 1]

"k"

1

[12, 1]

"l"

1

[12, 1]

"m"

1

[12, 1]

"n"

1

[12, 1]

"x"

5

[6, 5]

种子 (Seeded)

通过提供种子(seed)属性,可以增量运行 Leiden 算法。如果指定,种子属性将为部分已加载节点提供初始社区映射。算法将尝试保留种子社区 ID。

以下代码将运行算法并流式传输种子图的结果:
CALL gds.leiden.stream('myGraph', { seedProperty: 'seed' })
YIELD nodeId, communityId, intermediateCommunityIds
RETURN gds.util.asNode(nodeId).name AS name, communityId, intermediateCommunityIds
ORDER BY name ASC
表 20. 结果
名称 (name) communityId intermediateCommunityIds

"Alice"

42

null

“Bridget”

42

null

“Charles”

42

null

“Doug”

45

null

“Mark”

45

null

“Michael”

45

null

可以看出,使用种子图时,节点 Alice 保留了其初始社区 ID 42。另一个社区被分配了一个新的社区 ID,该 ID 保证大于最大的种子社区 ID。注意,consecutiveIds 配置选项不能与种子设定结合使用,以便保留种子值。

变更中间社区

以下代码将运行算法并使用中间社区变更内存图:
CALL gds.leiden.mutate('myGraph2', {
  mutateProperty: 'intermediateCommunities',
  randomSeed: 23,
  includeIntermediateCommunities: true,
  concurrency: 1
})
YIELD communityCount, modularity, modularities
表 21. 结果
communityCount modularity modularities

3

0.3624

[0.3296, 0.3624]

以下代码流式传输内存图中变更后的属性:
CALL gds.graph.nodeProperty.stream('myGraph2', 'intermediateCommunities')
YIELD nodeId, propertyValue
RETURN
  gds.util.asNode(nodeId).name AS name,
  toIntegerList(propertyValue) AS intermediateCommunities
ORDER BY name ASC
表 22. 结果
名称 (name) intermediateCommunities

"a"

[2, 4]

"b"

[2, 4]

"c"

[7, 5]

"d"

[2, 4]

"e"

[6, 5]

"f"

[7, 5]

"g"

[7, 5]

"h"

[11, 5]

"i"

[11, 5]

"j"

[12, 1]

"k"

[12, 1]

"l"

[12, 1]

"m"

[12, 1]

"n"

[12, 1]

"x"

[6, 5]

写入中间社区

以下代码将运行算法并将中间社区写入 Neo4j 数据库:
CALL gds.leiden.write('myGraph2', {
  writeProperty: 'intermediateCommunities',
  randomSeed: 19,
  includeIntermediateCommunities: true,
  concurrency: 1
})
YIELD communityCount, modularity, modularities
表 23. 结果
communityCount modularity modularities

3

0.3624

[0.3296, 0.3624]

以下代码流式传输 Neo4j 数据库中写入的属性:
MATCH (n:Node) RETURN n.name AS name, toIntegerList(n.intermediateCommunities) AS intermediateCommunities
ORDER BY name ASC
表 24. 结果
名称 (name) intermediateCommunities

"a"

[2, 4]

"b"

[2, 4]

"c"

[7, 5]

"d"

[2, 4]

"e"

[6, 5]

"f"

[7, 5]

"g"

[7, 5]

"h"

[11, 5]

"i"

[11, 5]

"j"

[12, 1]

"k"

[12, 1]

"l"

[12, 1]

"m"

[12, 1]

"n"

[12, 1]

"x"

[6, 5]