用于使用 igraph C 库
社区检测关注将网络的顶点聚类成紧密连接的子图,称为“社区”。以下参考文献提供了社区检测主题的一个很好的介绍
S. Fortunato: "Graphs 中社区检测"。物理报告 486, no. 3–5 (2010): 75–174. https://doi.org/10.1016/j.physrep.2009.11.002。
S. Fortunato 和 D. Hric: "Networks 中的社区检测:用户指南"。物理报告 659 (2016): 1–44. https://doi.org/10.1016/j.physrep.2016.09.002。
igraph_modularity
— 计算图相对于某些聚类或顶点类型的模块化。igraph_modularity_matrix
— 计算模块化矩阵。igraph_community_optimal_modularity
— 计算具有最高模块化值的社区结构。igraph_community_to_membership
— 从社区结构树状图创建一个成员向量。igraph_reindex_membership
— 使成员向量中的 ID 连续。igraph_compare_communities
— 使用各种指标比较社区结构。igraph_split_join_distance
— 计算两个社区结构的拆分-连接距离。
igraph_error_t igraph_modularity(const igraph_t *graph, const igraph_vector_int_t *membership, const igraph_vector_t *weights, const igraph_real_t resolution, const igraph_bool_t directed, igraph_real_t *modularity);
图相对于顶点的某些聚类(或顶点类型的分配)的模块化衡量了与随机零模型相比,不同聚类彼此分离的程度。它被定义为
Q = 1/(2m) sum_ij (A_ij - γ k_i k_j / (2m)) δ(c_i,c_j)
,
其中 m
是边的数量,A_ij
是邻接矩阵,k_i
是顶点 i
的度,c_i
是顶点 i
所属的聚类(或其顶点类型),如果 i=j
则 δ(i,j)=1
,否则为 0,并且总和遍历所有 i
、j
顶点对。请注意,在此公式中,邻接矩阵的对角线包含自环数量的两倍。
分辨率参数 γ
允许对随机零模型进行加权,这可能在找到具有高模块化的分区时很有用。在寻找具有高模块化的分区时,使用较高的分辨率参数最大化模块化通常会导致更多、更小的聚类。较低的值通常会导致更少、更大的聚类。当设置 γ = 1
时,将检索模块化的原始定义。
也可以在有向图上计算模块化。这只需要相对适度的改变,
Q = 1/m sum_ij (A_ij - γ k^out_i k^in_j / m) δ(c_i,c_j)
,
其中 k^out_i
是节点 i
的出度,k^in_j
是节点 j
的入度。
加权图上的模块化也很有意义。当考虑边权重时,A_ij
等于相应边的权重(如果不存在边则为 0),k_i
是顶点 i
的强度(即加权度),对于有向图,有类似的对应项,m
是所有边的总权重。
请注意,模块化对于没有边的图没有明确定义。 igraph 为没有边的图返回 NaN
;有关详细讨论,请参见 https://github.com/igraph/igraph/issues/1539。
有关模块化的原始定义,请参见 Newman, M. E. J., 和 Girvan, M. (2004)。在网络中寻找和评估社区结构。物理评论 E 69, 026113. https://doi.org/10.1103/PhysRevE.69.026113
有关模块化的有向定义,请参见 Leicht, E. A., 和 Newman, M. E. J. (2008)。有向网络中的社区结构。物理评论快报 100, 118703. https://doi.org/10.1103/PhysRevLett.100.118703
有关分辨率参数 γ
的介绍,请参见 Reichardt, J., 和 Bornholdt, S. (2006)。社区检测的统计力学。物理评论 E 74, 016110. https://doi.org/10.1103/PhysRevE.74.016110
参数:
|
输入图。 |
|
整数值的数字向量,给出每个顶点的类型,即它所属的聚类。它不必是连续的,即允许空社区。 |
|
权重向量或 |
|
分辨率参数 |
|
是否使用模块化的有向或无向版本。对于无向图,将被忽略。 |
|
指向实数的指针,结果将存储在此处。 |
返回值:
错误代码。 |
另请参阅:
时间复杂度:O(|V|+|E|),顶点数加上边数。
igraph_error_t igraph_modularity_matrix(const igraph_t *graph, const igraph_vector_t *weights, const igraph_real_t resolution, igraph_matrix_t *modmat, igraph_bool_t directed);
此函数返回模块化矩阵,该矩阵定义为
B_ij = A_ij - γ k_i k_j / (2m)
对于无向图,其中 A_ij
是邻接矩阵,γ
是分辨率参数,k_i
是顶点 i
的度,m
是图中的边数。当没有边,或者权重加起来为零时,结果是未定义的。
对于有向图,模块化矩阵更改为
B_ij = A_ij - γ k^out_i k^in_j / m
其中 k^out_i
是节点 i
的出度,k^in_j
是节点 j
的入度。
请注意,在此实现中,无向图中的自环乘以 2。如果指定了权重,则使用邻接矩阵和度的加权对应物。
参数:
|
输入图。 |
|
边权重,指向向量的指针。如果这是一个空指针,则假定每条边的权重为 1。 |
|
分辨率参数 |
|
指向已初始化矩阵的指针,模块化矩阵存储在该矩阵中。 |
|
对于有向图:是否应将边视为无向边。对于无向图,此参数将被忽略。 |
另请参阅:
igraph_error_t igraph_community_optimal_modularity(const igraph_t *graph, igraph_real_t *modularity, igraph_vector_int_t *membership, const igraph_vector_t *weights);
此函数计算图的最佳社区结构,以最大模块化分数表示。
通过将模块化最大化转换为整数规划问题,然后调用 GLPK 库来解决该问题来完成计算。请参见 Ulrik Brandes 等人:关于模块化聚类,IEEE Transactions on Knowledge and Data Engineering 20(2):172-188, 2008 https://doi.org/10.1109/TKDE.2007.190689。
请注意,精确的模块化优化是一个 NP 完全问题,并且所有已知的算法都具有指数时间复杂度。这意味着您可能不想在较大的图上运行此函数。具有最多 50 个顶点的图应该没问题,具有几百个顶点的图可能是可以的。
参数:
|
输入图。它可以是无向的或有向的。 |
|
指向实数的指针,或空指针。如果它不是空指针,则最佳模块化值将在此处返回。 |
|
指向向量的指针,或空指针。如果不是空指针,则最佳社区结构的成员向量将存储在此处。 |
|
给出边权重的向量。如果它是 |
返回值:
错误代码。当 GLPK 不可用时,返回 |
另请参阅:
|
时间复杂度:顶点数量的指数。
示例 24.1. 文件 examples/simple/igraph_community_optimal_modularity.c
#include <igraph.h> void prepare_weights_vector(igraph_vector_t* weights, const igraph_t* graph) { igraph_integer_t i, n = igraph_ecount(graph); igraph_vector_resize(weights, n); for (i = 0; i < n; i++) { VECTOR(*weights)[i] = i % 5; } } int main(void) { igraph_t graph; igraph_vector_int_t v; igraph_integer_t edges[] = { 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, 10, 0, 11, 0, 12, 0, 13, 0, 17, 0, 19, 0, 21, 0, 31, 1, 2, 1, 3, 1, 7, 1, 13, 1, 17, 1, 19, 1, 21, 1, 30, 2, 3, 2, 7, 2, 27, 2, 28, 2, 32, 2, 9, 2, 8, 2, 13, 3, 7, 3, 12, 3, 13, 4, 6, 4, 10, 5, 6, 5, 10, 5, 16, 6, 16, 8, 30, 8, 32, 8, 33, 9, 33, 13, 33, 14, 32, 14, 33, 15, 32, 15, 33, 18, 32, 18, 33, 19, 33, 20, 32, 20, 33, 22, 32, 22, 33, 23, 25, 23, 27, 23, 32, 23, 33, 23, 29, 24, 25, 24, 27, 24, 31, 25, 31, 26, 29, 26, 33, 27, 33, 28, 31, 28, 33, 29, 32, 29, 33, 30, 32, 30, 33, 31, 32, 31, 33, 32, 33 }; igraph_vector_int_t membership; igraph_vector_t weights; igraph_real_t modularity; igraph_bool_t simple; igraph_error_t retval; igraph_vector_int_view(&v, edges, sizeof(edges) / sizeof(edges[0])); igraph_create(&graph, &v, 0, IGRAPH_UNDIRECTED); igraph_vector_init(&weights, 0); igraph_is_simple(&graph, &simple); if (!simple) { return 1; } igraph_vector_int_init(&membership, 0); igraph_set_error_handler(&igraph_error_handler_printignore); /* Zachary karate club, unweighted */ retval = igraph_community_optimal_modularity(&graph, &modularity, &membership, 0); if (retval == IGRAPH_UNIMPLEMENTED) { return 77; } if (fabs(modularity - 0.4197896) > 0.0000001) { return 2; } /* Zachary karate club, weighted */ prepare_weights_vector(&weights, &graph); igraph_community_optimal_modularity(&graph, &modularity, &membership, &weights); if (fabs(modularity - 0.5115767) > 0.0000001) { return 4; } igraph_destroy(&graph); /* simple graph with loop edges, unweighted */ igraph_small(&graph, 6, IGRAPH_UNDIRECTED, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 0, 0, 0, 2, 2, -1); igraph_community_optimal_modularity(&graph, &modularity, &membership, 0); if (fabs(modularity - 0.28125) > 0.00001) { return 3; } /* simple graph with loop edges, weighted */ prepare_weights_vector(&weights, &graph); igraph_community_optimal_modularity(&graph, &modularity, &membership, &weights); if (fabs(modularity - 0.36686) > 0.00001) { return 5; } igraph_destroy(&graph); igraph_vector_int_destroy(&membership); igraph_vector_destroy(&weights); return 0; }
igraph_error_t igraph_community_to_membership(const igraph_matrix_int_t *merges, igraph_integer_t nodes, igraph_integer_t steps, igraph_vector_int_t *membership, igraph_vector_int_t *csize);
此函数从社区结构树状图创建一个成员向量。成员向量包含每个顶点的图组件的 ID,图组件从零开始编号,有关成员向量的示例,请参见 igraph_connected_components()
的相同参数。
许多社区检测算法返回一个 merges 矩阵,igraph_community_walktrap()
和 igraph_community_edge_betweenness()
是两个示例。该矩阵包含在映射网络的层次结构时执行的合并操作。如果矩阵有 n-1
行,其中 n
是图中的顶点数,则它包含整个网络的层次结构,并且称为树状图。
此函数执行 steps
合并操作,如 merges
矩阵所规定,并返回网络的当前状态。
如果 merges
不是完整的树状图,则如果 steps
不大于 merges
中的行数,则可以执行 steps
步。
参数:
|
包含合并操作的两列矩阵。有关详细语法,请参见 |
|
树状图中的叶节点数。 |
|
整数常量,要执行的步数。 |
|
指向已初始化向量的指针,如果不是 NULL,则成员结果将存储在此处。向量将根据需要调整大小。 |
|
指向已初始化向量的指针,或 NULL。如果不是 NULL,则组件的大小将存储在此处,向量将根据需要调整大小。 |
另请参阅:
|
时间复杂度:O(|V|),图中顶点的数量。
igraph_error_t igraph_reindex_membership(igraph_vector_int_t *membership, igraph_vector_int_t *new_to_old, igraph_integer_t *nb_clusters);
此函数以一种方式重新索引成员向量中的组件 ID,即新 ID 从零开始,一直到 C-1,其中 C 是原始向量中唯一组件 ID 的数量。提供的成员资格预计在 0, ..., n - 1 范围内。
参数:
|
数字向量,给出每个顶点的类型,即它所属的组件。向量将就地更改。 |
|
指向一个向量的指针,该向量将包含每个新组件的旧组件 ID,或者 |
|
指向不同聚类数量的整数的指针。如果不是 |
时间复杂度:对于 n 个元素,应该是 O(n)。
igraph_error_t igraph_compare_communities(const igraph_vector_int_t *comm1, const igraph_vector_int_t *comm2, igraph_real_t* result, igraph_community_comparison_t method);
此函数使用 Meila (2003) 的信息变异 (VI) 指标、Danon 等人 (2005) 的归一化互信息 (NMI)、van Dongen (2000) 的拆分-连接距离、Rand (1971) 的 Rand 索引或 Hubert 和 Arabie (1985) 的调整 Rand 索引来评估两个社区结构之间的距离。
这些度量中的一些是基于与给定顶点聚类 C
相关的离散随机变量的熵定义的。令 p_i
为随机选择的顶点属于聚类 i
的概率。那么聚类的熵为
H(C) = - sum_i p_i log p_i
类似地,我们可以根据随机顶点属于第一个聚类中的聚类 i
和第二个聚类中的聚类 j
的概率 p_ij
来定义两个聚类 C_1
和 C_2
的联合熵
H(C_1, C_2) = - sum_ii p_ij log p_ij
那么 C_1
和 C_2
的互信息为 MI(C_1, C_2) = H(C_1) + H(C_2) - H(C_1, C_2) >= 0
。较大的互信息表示两个聚类之间的高度重叠。归一化互信息,如 igraph 计算的那样,是
NMI(C_1, C_2) = 2 MI(C_1, C_2) / (H(C_1) + H(C_2))
.
它从区间 (0, 1] 取值,当两个聚类重合时,达到 1。
信息变异定义为 VI(C_1, C_2) = [H(C_1) - MI(C_1, C_2)] + [H(C_2) - MI(C_1, C_2)]
。信息变异的较低值表示两个聚类之间的差异较小,当它们重合时,VI = 0
。igraph 使用自然单位进行信息变异,即在计算熵时使用自然对数。
Rand 索引定义为两个聚类对随机选择的顶点对的聚类成员资格达成一致的概率。考虑所有顶点对,如果两个顶点在两个聚类中都位于同一聚类中,或者在两个聚类中都位于不同的聚类中,则认为两个聚类对顶点对的成员资格达成一致。然后,Rand 索引是达成一致的顶点对的数量,除以顶点对的总数。Rand 索引为零表示两个聚类对所有顶点对的成员资格都不同意,而 1 表示两个聚类是相同的。
调整后的 Rand 索引类似于 Rand 索引,但它考虑了即使两个聚类完全随机选择,两个聚类之间的一致也可能偶然发生。因此,调整后的 Rand 索引从 Rand 索引的值中减去预期的一致分数,并将结果除以 1 减去预期的一致分数。调整后的 Rand 索引的最大值仍然是 1(类似于 Rand 索引),表示最大一致性,但如果两个聚类之间的一致性小于偶然预期的一致性,则该值可能小于零。
有关拆分-连接距离的说明,请参见 igraph_split_join_distance()
。
参考
Meilă M: 通过信息变异比较聚类。In: Schölkopf B, Warmuth MK (eds.). 学习理论和核机器:第 16 届计算学习理论年会和第 7 届核研讨会,COLT/Kernel 2003,华盛顿特区,美国。计算机科学讲义,卷。2777,施普林格,2003 年。ISBN:978-3-540-40720-1. https://doi.org/10.1007/978-3-540-45167-9_14
Danon L, Diaz-Guilera A, Duch J, Arenas A: 比较社区结构识别。J Stat Mech P09008, 2005. https://doi.org/10.1088/1742-5468/2005/09/P09008
van Dongen S: 图聚类和马尔可夫聚类实验的性能标准。技术报告 INS-R0012,荷兰国家数学和计算机科学研究所,阿姆斯特丹,2000 年 5 月。 https://ir.cwi.nl/pub/4461
Rand WM: 评估聚类方法的客观标准。J Am Stat Assoc 66(336):846-850, 1971. https://doi.org/10.2307/2284239
Hubert L 和 Arabie P: 比较分区。Journal of Classification 2:193-218, 1985. https://doi.org/10.1007/BF01908075
参数:
|
第一个社区结构的成员向量 |
|
第二个社区结构的成员向量 |
|
结果存储在此处。 |
|
要使用的比较方法。 |
返回值:
错误代码。 |
另请参阅:
时间复杂度:O(n log(n))。
igraph_error_t igraph_split_join_distance(const igraph_vector_int_t *comm1, const igraph_vector_int_t *comm2, igraph_integer_t *distance12, igraph_integer_t *distance21);
分区 A 和 B 之间的拆分-连接距离是 A 从 B 的投影距离和 B 从 A 的投影距离之和。投影距离是不对称的度量,定义如下
首先,根据分区 B 中的所有集合评估分区 A 中的每个集合。对于分区 A 中的每个集合,找到分区 B 中最佳匹配的集合,并计算重叠大小。(匹配通过两个集合之间的重叠大小来量化)。然后,将 A 中每个集合的最大重叠大小加在一起,并从 A 中的元素数量中减去。
拆分-连接距离将在两个参数中返回,distance12
将包含第一个分区从第二个分区的投影距离,而 distance21
将是第二个分区从第一个分区的投影距离。这使得更容易检测分区是否是另一个分区的子分区,因为在这种情况下,相应的距离将为零。
参考
van Dongen S: 图聚类和马尔可夫聚类实验的性能标准。技术报告 INS-R0012,荷兰国家数学和计算机科学研究所,阿姆斯特丹,2000 年 5 月。
参数:
|
第一个社区结构的成员向量 |
|
第二个社区结构的成员向量 |
|
指向一个 |
|
指向一个 |
返回值:
错误代码。 |
另请参阅:
如果您不关心单独的距离而只关心它们的总和,请使用 |
时间复杂度:O(n log(n))。
igraph_error_t igraph_community_spinglass(const igraph_t *graph, const igraph_vector_t *weights, igraph_real_t *modularity, igraph_real_t *temperature, igraph_vector_int_t *membership, igraph_vector_int_t *csize, igraph_integer_t spins, igraph_bool_t parupdate, igraph_real_t starttemp, igraph_real_t stoptemp, igraph_real_t coolfact, igraph_spincomm_update_t update_rule, igraph_real_t gamma, igraph_spinglass_implementation_t implementation, igraph_real_t gamma_minus);
此函数实现了 Joerg Reichardt 和 Stefan Bornholdt 提出的社区结构检测算法。该算法在他们的论文中描述:社区检测的统计力学,http://arxiv.org/abs/cond-mat/0603718 。
从 0.6 版本开始,igraph 还支持该算法的扩展,该算法允许负边权重。这在 V. A. Traag 和 Jeroen Bruggeman 中描述:具有正负链接的网络中的社区检测,http://arxiv.org/abs/0811.2329 。
参数:
|
输入图,它可以是有向图,但算法忽略了边的方向。 |
|
给出边权重的向量,它可以是 |
|
指向实数的指针,如果不是 |
|
指向实数的指针,如果不是 |
|
指向已初始化向量或 |
|
指向已初始化向量或 |
|
整数给出自旋的数量,即最大聚类数。即使自旋数很高,结果中的聚类数也可能很小。 |
|
一个布尔常量,指示是否并行更新所有自旋。它未在 |
|
实数,开始时的温度。一个合理的默认值为 1.0。 |
|
实数,算法在此温度下停止。一个合理的默认值为 0.01。 |
|
实数,模拟退火的冷却因子。一个合理的默认值为 0.99。 |
|
更新规则的类型。可能的值: |
|
实数。算法的 gamma 参数,充当分辨率参数。较小的值通常会导致较大的聚类,较大的值通常会导致较小的聚类。 |
|
常量,在 igraph 中包含的 spin-glass 算法的两个实现之间进行选择。 |
|
实数。 |
返回值:
错误代码。 |
另请参阅:
有关计算单个顶点的社区的信息,请参见 |
时间复杂度:待定。
igraph_error_t igraph_community_spinglass_single(const igraph_t *graph, const igraph_vector_t *weights, igraph_integer_t vertex, igraph_vector_int_t *community, igraph_real_t *cohesion, igraph_real_t *adhesion, igraph_integer_t *inner_links, igraph_integer_t *outer_links, igraph_integer_t spins, igraph_spincomm_update_t update_rule, igraph_real_t gamma);
此函数实现了 Joerg Reichardt 和 Stefan Bornholdt 提出的社区结构检测算法。它在他们的论文中描述:社区检测的统计力学,http://arxiv.org/abs/cond-mat/0603718 。
此函数计算单个顶点的社区,而无需计算图中的所有社区。
参数:
|
输入图,它可以是有向图,但该算法中未使用边的方向。 |
|
指向带有边权重的向量的指针。或者,可以提供 |
|
为其计算社区的顶点的顶点 ID。 |
|
指向已初始化向量的指针,结果(输入顶点的社区中顶点的 ID)将存储在此处。向量将根据需要调整大小。 |
|
指向实数变量的指针,如果不是 |
|
指向实数变量的指针,如果不是 |
|
指向整数的指针,如果不是 |
|
指向整数的指针,如果不是 |
|
要使用的自旋数,这可以高于网络中实际的聚类数,在这种情况下,某些聚类将包含零个顶点。 |
|
更新规则的类型。可能的值: |
|
实数。算法的 gamma 参数。这定义了聚类质量函数中缺失链接和现有链接的权重。原始代码中的默认值为 1.0,这等于缺失边和现有边的权重。较小的值使现有链接对能量函数的贡献更大,该能量函数在该算法中最小化。较大的值使缺失的链接更重要。(如果我的理解是正确的。) |
返回值:
错误代码。 |
另请参阅:
对于算法的传统版本,请参见 igraph_community_spinglass()。 |
时间复杂度:待定。
在这些部分中记录的函数实现了由 Mark Newman 开发并在 MEJ Newman 中发布的“主导特征向量”方法:使用矩阵特征向量查找社区结构,Phys Rev E 74:036104 (2006)。
该方法的核心是模块化矩阵 B = A - P
的定义,其中 A
是(无向)网络的邻接矩阵,P
包含根据“配置模型”存在的某些边的概率。换句话说,P_ij
的元素 P
是在随机网络中顶点 i
和 j
之间存在边的概率,在该随机网络中,所有顶点的度与输入图中的度相同。有关更多详细信息,请参见 igraph_modularity_matrix()
。
主导特征向量方法的工作原理是计算最大正特征值模块化矩阵的特征向量,然后基于特征向量中相应元素的符号将顶点分为两个社区。如果特征向量中的所有元素都具有相同的符号,则表示网络没有潜在的社区结构。请检查 Newman 的论文,以了解为什么这是一种检测社区结构的好方法。
领先特征向量社群结构检测方法通过 igraph_community_leading_eigenvector()
实现。在初始分割之后,后续的分割将以优化相对于原始网络的模块度的方式进行。请注意,此处未实现任何进一步的优化,例如使用 Newman (2006) 第 V.A 节中提出的 Kernighan-Lin 方法。
示例 24.2. 文件 examples/simple/igraph_community_leading_eigenvector.c
#include <igraph.h> int main(void) { igraph_t g; igraph_matrix_int_t merges; igraph_vector_int_t membership; igraph_vector_t x; igraph_arpack_options_t options; /* Zachary Karate club */ igraph_small(&g, 0, IGRAPH_UNDIRECTED, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, 10, 0, 11, 0, 12, 0, 13, 0, 17, 0, 19, 0, 21, 0, 31, 1, 2, 1, 3, 1, 7, 1, 13, 1, 17, 1, 19, 1, 21, 1, 30, 2, 3, 2, 7, 2, 8, 2, 9, 2, 13, 2, 27, 2, 28, 2, 32, 3, 7, 3, 12, 3, 13, 4, 6, 4, 10, 5, 6, 5, 10, 5, 16, 6, 16, 8, 30, 8, 32, 8, 33, 9, 33, 13, 33, 14, 32, 14, 33, 15, 32, 15, 33, 18, 32, 18, 33, 19, 33, 20, 32, 20, 33, 22, 32, 22, 33, 23, 25, 23, 27, 23, 29, 23, 32, 23, 33, 24, 25, 24, 27, 24, 31, 25, 31, 26, 29, 26, 33, 27, 33, 28, 31, 28, 33, 29, 32, 29, 33, 30, 32, 30, 33, 31, 32, 31, 33, 32, 33, -1); igraph_matrix_int_init(&merges, 0, 0); igraph_vector_int_init(&membership, 0); igraph_vector_init(&x, 0); igraph_arpack_options_init(&options); igraph_community_leading_eigenvector(&g, /*weights=*/ 0, &merges, &membership, 1, &options, /*modularity=*/ 0, /*start=*/ 0, /*eigenvalues=*/ 0, /*eigenvectors=*/ 0, /*history=*/ 0, /*callback=*/ 0, /*callback_extra=*/ 0); igraph_matrix_int_print(&merges); igraph_vector_int_print(&membership); printf("\n"); /* Make all the steps */ igraph_community_leading_eigenvector(&g, /*weights=*/ 0, &merges, &membership, igraph_vcount(&g), &options, /*modularity=*/ 0, /*start=*/ 0, /*eigenvalues=*/ 0, /*eigenvectors=*/ 0, /*history=*/ 0, /*callback=*/ 0, /*callback_extra=*/ 0); igraph_matrix_int_print(&merges); igraph_vector_int_print(&membership); igraph_vector_destroy(&x); igraph_vector_int_destroy(&membership); igraph_matrix_int_destroy(&merges); igraph_destroy(&g); return 0; }
igraph_error_t igraph_community_leading_eigenvector( const igraph_t *graph, const igraph_vector_t *weights, igraph_matrix_int_t *merges, igraph_vector_int_t *membership, igraph_integer_t steps, igraph_arpack_options_t *options, igraph_real_t *modularity, igraph_bool_t start, igraph_vector_t *eigenvalues, igraph_vector_list_t *eigenvectors, igraph_vector_t *history, igraph_community_leading_eigenvector_callback_t *callback, void *callback_extra);
Newman 的领先特征向量方法用于检测社群结构。这是递归、分裂算法的正确实现:每次分割都通过最大化相对于原始网络的模块度来完成,参见 MEJ Newman: Finding community structure in networks using the eigenvectors of matrices, Phys Rev E 74:036104 (2006)。https://doi.org/10.1103/PhysRevE.74.036104
参数:
|
输入图。边的方向将被忽略。 |
||||||||
|
边的权重,对于未加权图,则为 null 指针。 |
||||||||
|
算法的结果,是一个包含已执行分割信息的矩阵。但是,该矩阵是以相反的方式构建的,类似于凝聚算法的结果。与 igraph 中大多数其他分层社群检测函数不同,此矩阵中的整数表示社群索引,而不是顶点索引。如果在算法结束时(执行 |
||||||||
|
所有分割执行完毕后,顶点成员资格将存储在此处。该向量必须在调用之前初始化,并会根据需要调整大小。如果此参数为 |
||||||||
|
要执行的最大步数。可能发生某些组件(或整个网络)没有底层社群结构,并且无法执行进一步的步骤。如果您想要尽可能多的步骤,请在此处提供网络中的顶点数。 |
||||||||
|
ARPACK 的选项。在此处提供 |
||||||||
|
如果不是 null 指针,则它必须是指向实数的指针,并且最终分割的模块度分数将存储在此处。 |
||||||||
|
布尔值,是否使用 |
||||||||
|
指向已初始化向量的指针或 null 指针。如果不是 null 指针,则沿社群结构检测计算的特征值将存储在此处。不导致分割的非正特征值也会被存储。 |
||||||||
|
如果不是 null 指针,则在算法的每个步骤中计算的特征向量将存储在此处,以向量列表的形式存储。每个特征向量都存储在 |
||||||||
|
指向已初始化向量的指针或 null 指针。如果不是 null 指针,则算法的轨迹将以数字方式编码存储在此处。各种操作
|
||||||||
|
一个 null 指针或 |
||||||||
|
要传递给回调函数的额外参数。 |
返回值:
错误代码。 |
另请参阅:
|
时间复杂度:O(|E|+|V|^2*steps),|V| 是顶点数,|E| 是边数,“steps” 是执行的分割数。
typedef igraph_error_t igraph_community_leading_eigenvector_callback_t( const igraph_vector_int_t *membership, igraph_integer_t comm, igraph_real_t eigenvalue, const igraph_vector_t *eigenvector, igraph_arpack_function_t *arpack_multiplier, void *arpack_extra, void *extra);
igraph 中的领先特征向量社群发现实现能够在每次特征值计算后调用回调函数。此回调函数必须是 igraph_community_leading_eigenvector_callback_t
类型。以下参数将传递给回调
参数:
|
实际成员资格向量,在记录新发现的特征值所暗示的潜在变化之前。 |
|
算法尝试在上次迭代中分割的社群的 id。社群 ID 从零开始索引! |
|
算法刚刚找到的特征值。 |
|
与算法刚刚找到的特征值相对应的特征向量。 |
|
传递给 |
|
传递给 ARPACK 求解器的额外参数。 |
|
传递给 |
另请参阅:
igraph_error_t igraph_le_community_to_membership(const igraph_matrix_int_t *merges, igraph_integer_t steps, igraph_vector_int_t *membership, igraph_vector_int_t *csize);
此函数从 igraph_community_leading_eigenvector()
的结果创建成员资格向量。它接受 membership
并根据提供的 merges
矩阵执行 steps
合并。
参数:
|
包含合并操作的两列矩阵。有关详细语法,请参阅 |
|
根据 |
|
最初是起始成员资格向量,在输出时是执行 |
|
可选地,社群的大小存储在此处,如果这不是 null 指针,而是已初始化的向量。 |
返回值:
错误代码。 |
时间复杂度:O(|V|),顶点数。
igraph_error_t igraph_community_walktrap(const igraph_t *graph, const igraph_vector_t *weights, igraph_integer_t steps, igraph_matrix_int_t *merges, igraph_vector_t *modularity, igraph_vector_int_t *membership);
此函数是 Walktrap 社群发现算法的实现,参见 Pascal Pons, Matthieu Latapy: Computing communities in large networks using random walks, https://arxiv.org/abs/physics/0512106
目前,igraph 中使用了原始 C++ 实现,参见 https://www-complexnetworks.lip6.fr/~latapy/PP/walktrap.html 我们感谢 Matthieu Latapy 和 Pascal Pons 提供了此源代码。
与原始实现相比,图中允许存在孤立的顶点,并且假定它们具有权重为 1 的单个入射环边。
参数:
|
输入图,边的方向将被忽略。 |
|
给出边的权重的数字向量。如果它是 NULL 指针,则所有边将具有相等的权重。权重预计为正。 |
|
整数常数,随机游走的长度。通常,使用 3-8 之间的值可以获得良好的结果,其中 4-5 是合理的默认值。 |
|
指向矩阵的指针,算法执行的合并将存储在此处(如果不是 |
|
指向向量的指针。如果不是 |
|
指向向量的指针。如果不是 |
返回值:
错误代码。 |
另请参阅:
时间复杂度:最坏情况下为 O(|E||V|^2),通常为 O(|V|^2 log|V|),|V| 是顶点数,|E| 是边数。
示例 24.3. 文件 examples/simple/walktrap.c
#include <igraph.h> int main(void) { igraph_t g; igraph_matrix_int_t merges; igraph_vector_t modularity; igraph_integer_t no_of_nodes; igraph_integer_t i; igraph_small(&g, 5, IGRAPH_UNDIRECTED, 0, 1, 0, 2, 0, 3, 0, 4, 1, 2, 1, 3, 1, 4, 2, 3, 2, 4, 3, 4, 5, 6, 5, 7, 5, 8, 5, 9, 6, 7, 6, 8, 6, 9, 7, 8, 7, 9, 8, 9, 0, 5, 4, 9, -1); igraph_vector_init(&modularity, 0); igraph_matrix_int_init(&merges, 0, 0); igraph_community_walktrap(&g, NULL /* no weights */, 4 /* steps */, &merges, &modularity, /* membership=*/ NULL); no_of_nodes = igraph_vcount(&g); printf("Merges:\n"); for (i = 0; i < igraph_matrix_int_nrow(&merges); i++) { printf("%2.1" IGRAPH_PRId " + %2." IGRAPH_PRId " -> %2." IGRAPH_PRId " (modularity %4.2f)\n", MATRIX(merges, i, 0), MATRIX(merges, i, 1), no_of_nodes + i, VECTOR(modularity)[i]); } igraph_destroy(&g); igraph_matrix_int_destroy(&merges); igraph_vector_destroy(&modularity); return 0; }
igraph_error_t igraph_community_edge_betweenness(const igraph_t *graph, igraph_vector_int_t *removed_edges, igraph_vector_t *edge_betweenness, igraph_matrix_int_t *merges, igraph_vector_int_t *bridges, igraph_vector_t *modularity, igraph_vector_int_t *membership, igraph_bool_t directed, const igraph_vector_t *weights);
基于网络中边的介数的社群结构检测,称为 Grivan-Newman 算法。
其思想是,连接两个社群的边的介数通常很高,因为单独社群中节点之间的许多最短路径都通过它们。因此,我们逐渐从网络中删除具有最高介数的边,并在每次删除后重新计算边介数。这样,网络迟早会分成两个组件,然后在一段时间后,其中一个组件再次分成两个较小的组件,依此类推,直到所有边都被删除。这是一种分裂式分层方法,其结果是树状图。
在有向图中,当 directed
设置为 true 时,将使用有向版本的介数和模块度,但是,仅检测到分割成弱连通组件的情况。
参考
M. Girvan 和 M. E. J. Newman:社交和生物网络中的社群结构。Proc. Nat. Acad. Sci. USA 99, 7821-7826 (2002)。https://doi.org/10.1073/pnas.122653799
参数:
|
输入图。 |
|
指向已初始化向量的指针,结果将存储在此处,已删除边的 ID 按删除顺序排列。它会根据需要调整大小。如果调用方不需要边 ID,则可以为 |
|
指向已初始化向量或 |
|
指向已初始化矩阵或 |
|
指向 |
|
如果不是 null 指针,则不同分割的模块度值将存储在此处,其顺序与合并矩阵相对应。如果 |
|
如果不是 null 指针,则与最高模块度值相对应的成员资格向量将存储在此处。 |
|
布尔常量。控制是否为有向图计算有向介数(即有向路径),以及是否使用有向版本的模块度。它对于无向图将被忽略。 |
|
包含边权重的可选向量。如果为 null,将计算并使用未加权的边介数分数。如果不为 null,将计算并使用加权的边介数分数。 |
返回值:
错误代码。 |
另请参阅:
时间复杂度:O(|V||E|^2),因为介数计算需要 O(|V||E|),并且我们执行 |E|-1 次。
示例 24.4. 文件 examples/simple/igraph_community_edge_betweenness.c
#include <igraph.h> int main(void) { igraph_t graph; igraph_vector_int_t edges; igraph_vector_t eb, weights; igraph_matrix_int_t merges; igraph_vector_int_t bridges; igraph_small(&graph, 0, IGRAPH_UNDIRECTED, 0,1, 0,1, 0,1, -1); igraph_vector_init_int(&weights, 3, 1, 2, 3); igraph_vector_init(&eb, 0); igraph_vector_int_init(&edges, 0); igraph_matrix_int_init(&merges, 0, 0); igraph_vector_int_init(&bridges, 0); igraph_community_edge_betweenness(&graph, &edges, &eb, &merges, &bridges, /*modularity*/ NULL, /*membership*/ NULL, IGRAPH_UNDIRECTED, &weights); printf("edges:\n"); igraph_vector_int_print(&edges); printf("edge betweenness:\n"); igraph_vector_print(&eb); printf("merges:\n"); igraph_matrix_int_print(&merges); printf("bridges:\n"); igraph_vector_int_print(&bridges); igraph_destroy(&graph); igraph_vector_int_destroy(&edges); igraph_vector_destroy(&eb); igraph_vector_destroy(&weights); igraph_matrix_int_destroy(&merges); igraph_vector_int_destroy(&bridges); return 0; }
igraph_error_t igraph_community_eb_get_merges(const igraph_t *graph, const igraph_bool_t directed, const igraph_vector_int_t *edges, const igraph_vector_t *weights, igraph_matrix_int_t *res, igraph_vector_int_t *bridges, igraph_vector_t *modularity, igraph_vector_int_t *membership);
如果您有一系列逐渐从网络中删除的边,并且您想知道网络如何分解为单独的组件,则此函数很方便。边序列可能来自 igraph_community_edge_betweenness()
函数,但这并不是必需的。请注意,igraph_community_edge_betweenness()
也可以通过其 merges
参数来计算树状图。当反向运行边删除过程并且两个组件连接在一起时,会发生合并。
参数:
|
输入图。 |
|
包含要从网络中删除的边的向量,所有边预计在向量中恰好出现一次。 |
|
是否使用有向或无向版本的模块度。对于无向图将被忽略。 |
|
包含边权重的可选向量。如果为 null,将计算未加权的模块度分数。如果不为 null,将计算加权的模块度分数。如果 |
|
指向已初始化矩阵的指针,如果不是 |
|
指向 |
|
如果不是 null 指针,则与合并矩阵相对应的不同分割的模块度值将存储在此处。 |
|
如果不是 null 指针,则最佳分割(就模块度而言)的成员资格向量将存储在此处。 |
返回值:
错误代码。 |
另请参阅:
时间复杂度:O(|E|+|V|log|V|),|V| 是顶点数,|E| 是边数。
igraph_error_t igraph_community_fastgreedy(const igraph_t *graph, const igraph_vector_t *weights, igraph_matrix_int_t *merges, igraph_vector_t *modularity, igraph_vector_int_t *membership);
此函数实现快速贪婪模块度优化算法来查找社群结构,有关详细信息,请参阅 A Clauset, MEJ Newman, C Moore: Finding community structure in very large networks, http://www.arxiv.org/abs/cond-mat/0408187。
还实现了一些 K Wakita, T Tsurumi: Finding community structure in mega-scale social networks, http://www.arxiv.org/abs/cs.CY/0702048v1 中提出的改进。
参数:
|
输入图。它必须是没有多重边的图。这将进行检查,并且对于具有多重边的图,将给出错误消息。 |
|
可能是包含边权重的数字向量。对于未加权图,请在此处提供 null 指针。权重预计为非负数。 |
|
指向已初始化矩阵或 |
|
指向已初始化向量或 |
|
指向向量的指针。如果不是 null 指针,则与最佳分割(就模块度而言)相对应的成员资格向量将存储在此处。 |
返回值:
错误代码。 |
另请参阅:
对于其他社群检测算法,请参阅 |
时间复杂度:最坏情况下为 O(|E||V|log|V|),通常为 O(|E|+|V|log^2|V|),|V| 是顶点数,|E| 是边数。
示例 24.5. 文件 examples/simple/igraph_community_fastgreedy.c
#include <igraph.h> int main(void) { igraph_t g; igraph_vector_t weights; igraph_matrix_int_t merges; igraph_matrix_int_init(&merges, 0, 0); igraph_vector_init_int(&weights, 8, 10, 10, 1, 1, 1, 1, 1, 1); igraph_small(&g, 6, IGRAPH_UNDIRECTED, 0,1, 1,2, 2,3, 2,4, 2,5, 3,4, 3,5, 4,5, -1); igraph_community_fastgreedy(&g, &weights, &merges, /*modularity*/ NULL, /*membership=*/ NULL); igraph_matrix_int_print(&merges); igraph_destroy(&g); igraph_vector_destroy(&weights); igraph_matrix_int_destroy(&merges); return 0; }
igraph_error_t igraph_community_multilevel(const igraph_t *graph, const igraph_vector_t *weights, const igraph_real_t resolution, igraph_vector_int_t *membership, igraph_matrix_int_t *memberships, igraph_vector_t *modularity);
此函数实现一种多层模块度优化算法来查找社群结构,有时称为 Louvain 算法。
该算法基于模块度度量和分层方法。最初,每个顶点都分配给自己的社群。在每个步骤中,顶点都以局部贪婪的方式重新分配给社群:以随机顺序,每个顶点都会移动到对其模块度贡献最高的社群。当没有顶点可以重新分配时,每个社群都被视为自己的顶点,并且该过程会重新开始,合并后的社群。当只剩下一个顶点或模块度在一个步骤中不能再增加时,该过程停止。
分辨率参数 γ
允许在不同的分辨率下查找社群。分辨率参数的较高值通常会导致更多、更小的社群。较低的值通常会导致更少、更大的社群。当设置 γ=1
时,将检索模块度的原始定义。请注意,返回的模块度值是使用指示的分辨率参数计算的。有关更多详细信息,请参阅 igraph_modularity()
。
此函数的原始版本由 Tom Gregorovic 贡献。
参考
Blondel, V. D., Guillaume, J.-L., Lambiotte, R., & Lefebvre, E.: 大型网络中社群的快速展开。Journal of Statistical Mechanics: Theory and Experiment, 10008(10), 6 (2008)。https://doi.org/10.1088/1742-5468/2008/10/P10008
参数:
|
输入图。它必须是无向图。 |
|
包含边权重的数字向量。如果 |
|
分辨率参数。必须大于或等于 0。较低的值有利于更少、更大的社群;较高的值有利于更多、更小的社群。将其设置为 1 以使用模块度的经典定义。 |
|
成员资格向量,结果将在此处返回。对于每个顶点,它都给出其社群的 ID。该向量必须初始化,并且会相应地调整大小。 |
|
数字矩阵,如果不是 |
|
数字向量,如果不是 |
返回值:
错误代码。 |
时间复杂度:在稀疏图上平均接近线性。
示例 24.6. 文件 examples/simple/igraph_community_multilevel.c
#include <igraph.h> void show_results(igraph_t *g, igraph_vector_int_t *membership, igraph_matrix_int_t *memberships, igraph_vector_t *modularity, FILE* f) { igraph_integer_t i, j, no_of_nodes = igraph_vcount(g); j = igraph_vector_which_max(modularity); for (i = 0; i < igraph_vector_int_size(membership); i++) { if (VECTOR(*membership)[i] != MATRIX(*memberships, j, i)) { fprintf(f, "WARNING: best membership vector element %" IGRAPH_PRId " does not match the best one in the membership matrix\n", i); } } fprintf(f, "Modularities:\n"); igraph_vector_print(modularity); for (i = 0; i < igraph_matrix_int_nrow(memberships); i++) { for (j = 0; j < no_of_nodes; j++) { fprintf(f, "%" IGRAPH_PRId " ", MATRIX(*memberships, i, j)); } fprintf(f, "\n"); } fprintf(f, "\n"); } int main(void) { igraph_t g; igraph_vector_t modularity; igraph_vector_int_t edges; igraph_vector_int_t membership; igraph_matrix_int_t memberships; igraph_integer_t i, j, k; igraph_vector_init(&modularity, 0); igraph_vector_int_init(&membership, 0); igraph_matrix_int_init(&memberships, 0, 0); igraph_rng_seed(igraph_rng_default(), 42); /* Unweighted test graph from the paper of Blondel et al */ igraph_small(&g, 16, IGRAPH_UNDIRECTED, 0, 2, 0, 3, 0, 4, 0, 5, 1, 2, 1, 4, 1, 7, 2, 4, 2, 5, 2, 6, 3, 7, 4, 10, 5, 7, 5, 11, 6, 7, 6, 11, 8, 9, 8, 10, 8, 11, 8, 14, 8, 15, 9, 12, 9, 14, 10, 11, 10, 12, 10, 13, 10, 14, 11, 13, -1); igraph_community_multilevel(&g, 0, 1, &membership, &memberships, &modularity); show_results(&g, &membership, &memberships, &modularity, stdout); /* Higher resolution */ igraph_community_multilevel(&g, 0, 1.5, &membership, &memberships, &modularity); show_results(&g, &membership, &memberships, &modularity, stdout); igraph_destroy(&g); /* Ring of 30 cliques */ igraph_vector_int_init(&edges, 0); for (i = 0; i < 30; i++) { for (j = 0; j < 5; j++) { for (k = j + 1; k < 5; k++) { igraph_vector_int_push_back(&edges, i * 5 + j); igraph_vector_int_push_back(&edges, i * 5 + k); } } } for (i = 0; i < 30; i++) { igraph_vector_int_push_back(&edges, i * 5 % 150); igraph_vector_int_push_back(&edges, (i * 5 + 6) % 150); } igraph_create(&g, &edges, 150, 0); igraph_community_multilevel(&g, 0, 1, &membership, &memberships, &modularity); show_results(&g, &membership, &memberships, &modularity, stdout); igraph_destroy(&g); igraph_vector_destroy(&modularity); igraph_vector_int_destroy(&membership); igraph_vector_int_destroy(&edges); igraph_matrix_int_destroy(&memberships); return 0; }
igraph_error_t igraph_community_leiden(const igraph_t *graph, const igraph_vector_t *edge_weights, const igraph_vector_t *node_weights, const igraph_real_t resolution_parameter, const igraph_real_t beta, const igraph_bool_t start, const igraph_integer_t n_iterations, igraph_vector_int_t *membership, igraph_integer_t *nb_clusters, igraph_real_t *quality);
此函数实现 Leiden 算法来查找社群结构。
它类似于多层算法,通常称为 Louvain 算法,但它更快,并产生更高质量的解决方案。它可以优化模块度和常数 Potts 模型,该模型不受分辨率限制的影响(参见 Tragg、Van Dooren 和 Nesterov)。
Leiden算法包含三个阶段:(1)节点的局部移动,(2)划分的细化,以及(3)基于细化划分的网络聚合,使用非细化划分来为聚合网络创建初始划分。在Leiden算法的局部移动过程中,仅访问邻域已更改的节点。仅进行严格改善质量函数的移动。细化是通过从每个集群内的单例划分重新开始,并逐步合并子集群来完成的。聚合时,单个集群可以由多个节点表示(这些节点是在细化中识别出的子集群)。
Leiden算法提供多个保证。Leiden算法通常是迭代的:一个迭代的输出用作下一个迭代的输入。在每次迭代中,保证所有集群都是连接良好且分隔良好的。在没有任何变化的迭代之后,保证所有节点和某些部分都已局部优化分配。请注意,即使单个迭代没有导致任何更改,后续迭代仍有可能发现一些改进。每次迭代都会探索不同的节点子集,以考虑从一个集群移动到另一个集群。最后,渐近地,保证所有集群的所有子集都已局部优化分配。更多详细信息,请参阅Traag, Waltman & van Eck (2019)。
正在优化的目标函数是
1 / 2m sum_ij (A_ij - γ n_i n_j) δ(s_i, s_j)
其中m是总边权重,A_ij
是边(i,j)的权重,γ
是所谓的解析度参数,n_i
是节点i
的节点权重,s_i
是节点i
的集群,如果且仅当x = y
时δ(x, y) = 1
,否则为0。通过设置n_i = k_i
(节点i
的度数)并将γ
除以2m
,我们可以有效地获得模块化的表达式。因此,当您将度数作为node_weights
提供,并通过提供解析度参数1/(2m)
(其中m
是边的数量)时,将优化标准模块化。
参考
V. A. Traag, L. Waltman, N. J. van Eck: From Louvain to Leiden: guaranteeing well-connected communities. Scientific Reports, 9(1), 5233 (2019). http://dx.doi.org/10.1038/s41598-019-41695-z
V. A. Traag, P. Van Dooren, and Y. Nesterov: Narrow scope for resolution-limit-free community detection. Phys. Rev. E 84, 016114 (2011). https://doi.org/10.1103/PhysRevE.84.016114
参数:
|
输入图。它必须是无向图。 |
|
包含边权重的数字向量。如果 |
|
包含节点权重的数字向量。如果 |
|
使用的解析度参数,在文档中提到的目标函数中用gamma表示。 |
|
合并时细化步骤中使用的随机性。少量随机性( |
|
Start from membership vector. |
|
将核心Leiden算法迭代指示的次数。如果这是一个负数,它将继续迭代直到迭代没有改变聚类。 |
|
成员向量。这既用作优化的初始成员,也在适当的位置进行更新。因此,必须正确初始化。从头开始查找集群时,通常使用单例聚类开始。这可以使用 |
|
|
|
划分的质量,根据文档中包含的目标函数。如果 |
返回值:
错误代码。 |
时间复杂度:在稀疏图上接近线性。
示例 24.7. 文件 examples/simple/igraph_community_leiden.c
#include <igraph.h> int main(void) { igraph_t graph; igraph_vector_int_t membership; igraph_vector_int_t degree; igraph_vector_t weights; igraph_integer_t nb_clusters, i; igraph_real_t quality; /* Set default seed to get reproducible results */ igraph_rng_seed(igraph_rng_default(), 0); /* Simple unweighted graph */ igraph_small(&graph, 10, IGRAPH_UNDIRECTED, 0, 1, 0, 2, 0, 3, 0, 4, 1, 2, 1, 3, 1, 4, 2, 3, 2, 4, 3, 4, 5, 6, 5, 7, 5, 8, 5, 9, 6, 7, 6, 8, 6, 9, 7, 8, 7, 9, 8, 9, 0, 5, -1); /* Perform Leiden algorithm using CPM for 1 iteration */ igraph_vector_int_init(&membership, igraph_vcount(&graph)); igraph_community_leiden(&graph, NULL, NULL, 0.05, 0.01, 0, 1, &membership, &nb_clusters, &quality); printf("Leiden found %" IGRAPH_PRId " clusters using CPM (resolution parameter 0.05), quality is %.4f.\n", nb_clusters, quality); printf("Membership: "); igraph_vector_int_print(&membership); printf("\n"); /* Start from existing membership for 10 iterations to improve it further */ igraph_community_leiden(&graph, NULL, NULL, 0.05, 0.01, 1, 10, &membership, &nb_clusters, &quality); printf("Iterated Leiden, using CPM (resolution parameter 0.05), quality is %.4f.\n", quality); printf("Membership: "); igraph_vector_int_print(&membership); printf("\n"); /* Initialize degree vector to use for optimizing modularity */ igraph_vector_int_init(°ree, igraph_vcount(&graph)); igraph_degree(&graph, °ree, igraph_vss_all(), IGRAPH_ALL, 1); igraph_vector_init(&weights, igraph_vector_int_size(°ree)); for (i = 0; i < igraph_vector_int_size(°ree); i++) { VECTOR(weights)[i] = VECTOR(degree)[i]; } /* Perform Leiden algorithm using modularity until stable iteration */ igraph_community_leiden(&graph, NULL, &weights, 1.0 / (2 * igraph_ecount(&graph)), 0.01, 0, -1, &membership, &nb_clusters, &quality); printf("Leiden found %" IGRAPH_PRId " clusters using modularity, quality is %.4f.\n", nb_clusters, quality); printf("Membership: "); igraph_vector_int_print(&membership); printf("\n"); igraph_vector_destroy(&weights); igraph_vector_int_destroy(°ree); igraph_vector_int_destroy(&membership); igraph_destroy(&graph); return 0; }
igraph_error_t igraph_community_fluid_communities(const igraph_t *graph, igraph_integer_t no_of_communities, igraph_vector_int_t *membership);
该算法基于这样一种简单的想法,即几种流体在非均匀环境(图拓扑)中相互作用,并根据它们的相互作用和密度进行扩展和收缩。不支持加权图。
此函数实现了以下社区检测方法:Parés F, Gasulla DG, et. al. (2018) Fluid Communities: A Competitive, Scalable and Diverse Community Detection Algorithm. In: Complex Networks & Their Applications VI: Proceedings of Complex Networks 2017 (The Sixth International Conference on Complex Networks and Their Applications), Springer, vol 689, p 229. https://doi.org/10.1007/978-3-319-72150-7_19
参数:
|
输入图。该图必须是简单且连通的。将忽略边方向。 |
|
要找到的社区的数量。必须大于0且少于图中顶点的数量。 |
|
结果向量,将顶点映射到它们被分配到的社区。 |
|
如果不是空指针,则它必须是指向实数的指针。检测到的社区结构的模块化分数存储在此处。 |
返回值:
错误代码。 |
时间复杂度:O(|E|)
igraph_error_t igraph_community_label_propagation(const igraph_t *graph, igraph_vector_int_t *membership, igraph_neimode_t mode, const igraph_vector_t *weights, const igraph_vector_int_t *initial, const igraph_vector_bool_t *fixed);
此函数实现了Raghavan、Albert和Kumara描述的基于标签传播的社区检测算法。此版本通过考虑边权重以及允许固定某些标签来扩展了原始方法。
权重考虑如下:当确定节点i
的新标签时,算法迭代节点i
上的所有边,并计算通向标签为0、1、2、...、k
- 1的其他节点的边的总权重(其中k
是可能标签的数量)。然后,节点i
的新标签将是其边(在节点i
上的边中)具有最高总权重的标签。
对于有向图,重要的是要知道标签只能在图的强连通分量内自由循环,并且可能仅在一个方向(或根本不)在强连通分量之间传播。如果您了解后果,则应将有向边视为有向边。
参考
Raghavan, U.N. and Albert, R. and Kumara, S.: Near linear time algorithm to detect community structures in large-scale networks. Phys Rev E 76, 036106 (2007). https://doi.org/10.1103/PhysRevE.76.036106
Šubelj, L.: Label propagation for clustering. Chapter in "Advances in Network Clustering and Blockmodeling" edited by P. Doreian, V. Batagelj & A. Ferligoj (Wiley, New York, 2018). https://doi.org/10.1002/9781119483298.ch5 https://arxiv.org/abs/1709.05634
参数:
|
输入图。请注意,该算法最初是为无向图定义的。如果在此处传递有向图以将其视为无向图,则建议将 |
|
成员向量,结果在此处返回。对于每个顶点,它给出其社区(标签)的ID。 |
|
是否考虑用于标签传播的边方向,如果是,则标签应沿哪个方向传播。无向图将被忽略。 |
|
权重向量,它应包含所有边的正权重。 |
|
初始状态。如果 |
|
指示哪些标签是固定的布尔向量。当然,只有在您提供初始状态时才有意义,否则将忽略此元素。请注意,没有标签的顶点无法固定。对于那些带有警告的顶点,将忽略固定状态。另请注意,标签编号本身没有任何意义,igraph可能会重新编号标签。但是,共成员约束将得到尊重:可以将两个顶点固定在同一社区中或不同的社区中。 |
|
如果不是空指针,则它必须是指向实数的指针。检测到的社区结构的模块化分数存储在此处。请注意,如果输入图是有向的,即使您将 |
返回值:
错误代码。 |
时间复杂度:O(m+n)
示例 24.8. 文件 examples/simple/igraph_community_label_propagation.c
#include <igraph.h> #include <stdio.h> int main(void) { igraph_t graph; igraph_vector_int_t membership; igraph_real_t modularity; igraph_famous(&graph, "Zachary"); /* We use Zachary's karate club network. */ /* Label propagation is a stochastic method; the result will depend on the random seed. */ igraph_rng_seed(igraph_rng_default(), 123); /* All igraph functions that returns their result in an igraph_vector_t must be given an already initialized vector. */ igraph_vector_int_init(&membership, 0); igraph_community_label_propagation( &graph, &membership, /* mode = */ IGRAPH_ALL, /* weights= */ NULL, /* initial= */ NULL, /* fixed= */ NULL ); /* Also calculate the modularity of the partition */ igraph_modularity( &graph, &membership, /* weights= */ NULL, /* resolution = */ 1, /* directed= */ 0, &modularity); printf("%" IGRAPH_PRId " communities found; modularity score is %g.\n", igraph_vector_int_max(&membership) + 1, modularity); printf("Communities membership: "); igraph_vector_int_print(&membership); /* Destroy data structures at the end. */ igraph_vector_int_destroy(&membership); igraph_destroy(&graph); return 0; }
igraph_error_t igraph_community_infomap(const igraph_t * graph, const igraph_vector_t *e_weights, const igraph_vector_t *v_weights, igraph_integer_t nb_trials, igraph_vector_int_t *membership, igraph_real_t *codelength);
Martin Rosvall和Carl T. Bergstrom的Infomap社区检测算法的实现。该算法考虑了边方向。
有关更多详细信息,请参见数学可视化和地图生成器,网址为https://www.mapequation.org 。描述该算法的原始论文是:M. Rosvall和C. T. Bergstrom, Maps of information flow reveal community structure in complex networks, PNAS 105, 1118 (2008) (https://dx.doi.org/10.1073/pnas.0706851105, https://arxiv.org/abs/0707.0609)。有关该算法的更详细的论文是:M. Rosvall, D. Axelsson, and C. T. Bergstrom, The map equation, Eur. Phys. J. Special Topics 178, 13 (2009). (https://dx.doi.org/10.1140/epjst/e2010-01179-1, https://arxiv.org/abs/0906.1405)
使用了Martin Rosvall的原始C++实现,请参见http://www.tp.umu.se/~rosvall/downloads/infomap_undir.tgz 。在igraph中的集成由Emmanuel Navarro完成(他感谢Martin Rosvall和Carl T. Bergstrom提供此源代码)。
请注意,该图不能包含孤立的顶点。
如果您想指定一个随机种子(如原始实现中一样),则可以使用igraph_rng_seed()
。
参数:
|
输入图。考虑了边方向。 |
|
数字向量,给出边的权重。随机游走者将偏爱权重高的边而不是权重低的边;从节点选择特定出站边的概率与其权重成正比。如果它是 |
|
数字向量,给出顶点的权重。当随机游走者需要在陷入接收器节点(即没有出站边的节点)后“传送”到新节点时,具有较高权重的顶点会受到青睐。当随机游走者传送时,选择顶点的概率与顶点的权重成正比。如果此参数为 |
|
尝试划分网络的次数(可以是等于或大于1的任何整数值)。 |
|
指向向量的指针。成员向量存储在此处。 |
|
指向实数的指针。如果不是NULL,则分区的代码长度存储在此处。 |
返回值:
错误代码。 |
另请参阅:
时间复杂度:待定。
igraph_error_t igraph_community_voronoi( const igraph_t *graph, igraph_vector_int_t *membership, igraph_vector_int_t *generators, igraph_real_t *modularity, const igraph_vector_t *lengths, const igraph_vector_t *weights, igraph_neimode_t mode, igraph_real_t r);
此函数是实验性的,其签名尚未被视为最终签名。我们保留更改函数签名的权利,而无需更改 igraph 的主要版本。使用它需要您自担风险。
此函数使用基于给定边长度除以边聚类系数的顶点的Voronoi分区来查找社区(igraph_ecc()
)。生成器顶点被选择为在半径r
内具有最大局部相对密度的顶点,其中顶点的局部相对密度定义为s m / (m + k)
,其中s
是顶点的强度,m
是顶点一阶邻域内的边数,而k
是只有端点在此邻域内的边数。
参考
Deritei et al., Community detection by graph Voronoi diagrams, New Journal of Physics 16, 063007 (2014) https://doi.org/10.1088/1367-2630/16/6/063007
Molnár et al., Community Detection in Directed Weighted Networks using Voronoi Partitioning, Scientific Reports 14, 8124 (2024) https://doi.org/10.1038/s41598-024-58624-4
参数:
|
输入图。它必须是简单的。 |
|
如果不是 |
|
如果不是 |
|
如果不是 |
|
边长度,或 |
|
边权重,或 |
|
如果 |
|
选择生成器点时要使用的半径/分辨率。此值越大,分区越少。传入一个负值以自动选择使模块化最大化的半径。 |
返回值:
错误代码。 |
另请参阅:
时间复杂度:待定。
← Chapter 23. Vertex separators | Chapter 25. Graphlets → |