Skip to content

@graphrs/community

社区检测算法,用于识别图中的簇和群组。每种算法使用不同的策略将节点划分为社区。

bash
npm install @graphrs/community

基于模块度

通过优化模块度来检测社区 —— 模块度衡量网络分解为密集子组(组间连接稀疏)的质量。

louvain(graph, options?)

Louvain 方法 —— 最广泛使用的社区检测算法。通过迭代的节点移动和社区聚合来贪心优化模块度。快速且可扩展,但社区内部可能不连通。

typescript
import { Graph } from '@graphrs/core';
import { louvain } from '@graphrs/community';

const graph = Graph.fromEdges([
  [0,1],[1,2],[2,0],   // 集群 A
  [3,4],[4,5],[5,3],   // 集群 B
  [2,3],               // 桥接边
]);

const result = await louvain(graph, { resolution: 1.0 });
console.log(result.membership); // 例如 [0, 0, 0, 1, 1, 1]
console.log(result.modularity); // 例如 0.357
console.log(result.clusters);   // 2
选项类型默认值说明
resolutionnumber1.0分辨率参数 —— 值越大,产生的社区越多越小

leiden(graph, options?)

Leiden 算法 —— Louvain 的改进版本,保证社区的连通性。通过在每次聚合后细化社区来产生更高质量的划分。当划分质量重要时优先选择 Leiden 而非 Louvain。

typescript
import { leiden } from '@graphrs/community';

const result = await leiden(graph, { resolution: 1.0 });
选项类型默认值说明
resolutionnumber1.0分辨率参数
betanumber细化阶段的随机性参数
iterationsnumber最大迭代次数

fastGreedy(graph)

快速贪心模块度优化 —— 层次聚合方法,在每一步合并社区以最大化模块度增益。无需调参。

typescript
import { fastGreedy } from '@graphrs/community';

const result = await fastGreedy(graph);
console.log(result.clusters);   // 发现的社区数量
console.log(result.modularity); // 质量分数

spinglass(graph, options?)

Spinglass 算法 —— 基于 Potts 自旋玻璃模型的统计力学方法。将社区检测视为寻找自旋系统的基态。能检测不同大小的社区,但要求图是连通的。

typescript
import { spinglass } from '@graphrs/community';

const result = await spinglass(graph, { spins: 25 });
选项类型默认值说明
spinsnumber25自旋数(社区数量的上限)
gammanumber社区间边的奖惩参数

信息论方法

infomap(graph, options?)

Infomap 算法 —— 使用映射方程找到最小化图上随机游走描述长度的划分。擅长发现基于流的社区。结果中的 modularity 字段包含的是代码长度(描述长度),而非标准模块度。

typescript
import { infomap } from '@graphrs/community';

const result = await infomap(graph, { trials: 10 });
console.log(result.modularity); // 代码长度(越低 = 划分越好)
选项类型默认值说明
trialsnumber10优化试验次数(次数越多结果越好,但越慢)

基于传播

标签或流体在网络中传播并稳定为社区的算法。

labelPropagation(graph, options?)

标签传播 —— 快速的近线性时间社区检测。每个节点采用其邻居中最常见的标签。非确定性:不同运行结果可能不同。modularity 字段始终为 0(标签传播不优化模块度)。

typescript
import { labelPropagation } from '@graphrs/community';

const result = await labelPropagation(graph);
console.log(result.clusters); // 发现的社区数量
选项类型默认值说明
fixednumber[]保持初始标签不变的节点索引

fluidCommunities(graph, options)

流体社区 —— 基于传播的算法,模拟相互作用的流体将图划分为恰好 numCommunities 个组。与大多数算法不同,社区数量需要预先指定。modularity 字段始终为 0。

typescript
import { fluidCommunities } from '@graphrs/community';

const result = await fluidCommunities(graph, { numCommunities: 3 });
console.log(result.clusters); // 3
选项类型默认值说明
numCommunitiesnumber必填要发现的确切社区数

基于随机游走

walktrap(graph, options?)

Walktrap —— 使用短随机游走检测社区。同一社区中的节点倾向于具有相似的随机游走转移概率。生成层次树状图并在最大化模块度处切割。

typescript
import { walktrap } from '@graphrs/community';

const result = await walktrap(graph, { steps: 4 });
选项类型默认值说明
stepsnumber4随机游走长度(4–5 对大多数图效果好)

如何选择算法

算法策略速度可调参数最适合
louvain模块度resolution通用场景,首选
leiden模块度resolution, beta高质量划分
fastGreedy模块度快速基线,无需调参
infomap信息论中等trials基于流/有向图的社区
labelPropagation传播极快fixed超大图(>100k 节点)
fluidCommunities传播numCommunities已知社区数量
walktrap随机游走中等steps层次社区结构
spinglass统计力学spins, gamma中小规模连通图

结果类型

所有函数返回 Promise<CommunityResult>

typescript
interface CommunityResult {
  membership: number[];  // 每个节点的社区 ID(按节点顺序索引)
  modularity: number;    // 质量分数(-0.5 到 1.0),infomap 返回代码长度
  clusters: number;      // 发现的社区数量
}

完整示例

在同一个图上比较多种算法:

typescript
import { Graph } from '@graphrs/core';
import {
  louvain, leiden, fastGreedy, infomap,
  labelPropagation, walktrap,
} from '@graphrs/community';

const graph = Graph.fromEdges([
  [0,1],[1,2],[2,0],       // 集群 A
  [3,4],[4,5],[5,3],       // 集群 B
  [6,7],[7,8],[8,6],       // 集群 C
  [2,3],[5,6],             // 桥接边
]);

const algorithms = [
  { name: 'Louvain',    fn: () => louvain(graph) },
  { name: 'Leiden',     fn: () => leiden(graph) },
  { name: 'FastGreedy', fn: () => fastGreedy(graph) },
  { name: 'Infomap',    fn: () => infomap(graph) },
  { name: 'LabelProp',  fn: () => labelPropagation(graph) },
  { name: 'Walktrap',   fn: () => walktrap(graph) },
];

for (const { name, fn } of algorithms) {
  const result = await fn();
  console.log(
    `${name}: ${result.clusters} 个社区, ` +
    `模块度=${result.modularity.toFixed(3)}, ` +
    `成员=[${result.membership.join(',')}]`
  );
}

API 总结

函数策略返回值
louvain模块度优化Promise<CommunityResult>
leiden改进模块度Promise<CommunityResult>
fastGreedy贪心模块度Promise<CommunityResult>
infomap信息论Promise<CommunityResult>
labelPropagation标签传播Promise<CommunityResult>
fluidCommunities流体传播Promise<CommunityResult>
walktrap随机游走Promise<CommunityResult>
spinglass自旋玻璃模型Promise<CommunityResult>

MIT License (TS code) · GPL-2.0 (WASM binary)