igraph 参考手册

用于使用 igraph C 库

搜索手册

第 13 章。图的结构属性

这些函数通常计算图的某些结构属性,例如其直径、节点的度等。

1. 基本属性

1.1. igraph_are_adjacent — 确定两个顶点是否相邻。

igraph_error_t igraph_are_adjacent(const igraph_t *graph,
                         igraph_integer_t v1, igraph_integer_t v2,
                         igraph_bool_t *res);

确定是否存在以 v1v2 作为端点的边。 对于无向图,此函数当然是对称的。

参数: 

:

图对象。

v1:

第一个顶点。

v2:

第二个顶点。

res:

布尔值,如果存在从 v1v2 的边,则为 true,否则为 false

返回值: 

如果给出了无效的顶点 ID,则返回错误代码 IGRAPH_EINVVID

时间复杂度:O( min(log(d1), log(d2)) ),d1 是 v1 的(出)度,d2 是 v2 的(入)度。

2. 稀疏化器

2.1. igraph_spanner — 计算具有给定伸展因子的图的生成树。

igraph_error_t igraph_spanner(const igraph_t *graph, igraph_vector_int_t *spanner,
        igraph_real_t stretch, const igraph_vector_t *weights);

具有伸展 t 的图 G = (V,E) 的生成树是一个子图 H = (V,Es),使得 EsE 的子集,并且 H 中任意一对节点之间的距离最多为 G 中距离的 t 倍。 返回的图始终是给定图的生成树,具有指定的伸展。 对于加权图,生成树中边的数量为 O(k n^(1 + 1 / k)),其中 kk = (t + 1) / 2m 是边的数量,nG 中节点的数量。 对于未加权图,边的数量为 O(n^(1 + 1 / k) + kn)

此函数基于 Baswana 和 Sen 的算法:“用于计算加权图中稀疏生成树的简单线性时间随机算法”。 https://doi.org/10.1002/rsa.20130

参数: 

:

一个无向连通图对象。 如果图是有向的,则将忽略边的方向。

spanner:

一个初始化的向量,构成计算出的生成树的边的 ID 将在此处返回。 使用 igraph_subgraph_from_edges() 将生成树提取为单独的图对象。

stretch:

生成树的伸展因子 t

weights:

边权重或 NULL

返回值: 

错误代码

IGRAPH_ENOMEM

临时数据没有足够的内存。

时间复杂度:该算法是一种随机拉斯维加斯算法。 预期运行时间为 O(km),其中 k 是上面提到的值,m 是边的数量。

3. (最短)路径相关函数

3.1. igraph_distances — 顶点之间最短路径的长度。
3.2. igraph_distances_cutoff — 顶点之间最短路径的长度,带截止值。
3.3. igraph_distances_dijkstra — 顶点之间加权最短路径的长度。
3.4. igraph_distances_dijkstra_cutoff — 顶点之间加权最短路径的长度,带截止值。
3.5. igraph_distances_bellman_ford — 顶点之间加权最短路径的长度,允许负权重。
3.6. igraph_distances_johnson — 顶点之间加权最短路径的长度,使用 Johnson 算法。
3.7. igraph_distances_floyd_warshall — 使用 Floyd-Warshall 算法的加权所有对最短路径长度。
3.8. igraph_get_shortest_paths — 从顶点出发的最短路径。
3.9. igraph_get_shortest_path — 从一个顶点到另一个顶点的最短路径。
3.10. igraph_get_shortest_paths_dijkstra — 从顶点出发的加权最短路径。
3.11. igraph_get_shortest_path_dijkstra — 从一个顶点到另一个顶点的加权最短路径(Dijkstra)。
3.12. igraph_get_shortest_paths_bellman_ford — 从顶点出发的加权最短路径,允许负权重。
3.13. igraph_get_shortest_path_bellman_ford — 从一个顶点到另一个顶点的加权最短路径(Bellman-Ford)。
3.14. igraph_get_shortest_path_astar — A* 算法给出从一个顶点到另一个顶点的最短路径,带有启发式。
3.15. igraph_astar_heuristic_func_t — A* 算法的距离估计器。
3.16. igraph_get_all_shortest_paths — 从顶点出发的所有最短路径(测地线)。
3.17. igraph_get_all_shortest_paths_dijkstra — 从顶点出发的所有加权最短路径(测地线)。
3.18. igraph_get_k_shortest_paths — 两个顶点之间的 k 条最短路径。
3.19. igraph_get_all_simple_paths — 列出从一个源出发的所有简单路径。
3.20. igraph_average_path_length — 所有顶点对之间的平均未加权最短路径长度。
3.21. igraph_average_path_length_dijkstra — 所有顶点对之间的平均加权最短路径长度。
3.22. igraph_path_length_hist — 创建所有最短路径长度的直方图。
3.23. igraph_diameter — 计算图的直径(最长测地线)。
3.24. igraph_diameter_dijkstra — 使用 Dijkstra 算法计算图的加权直径。
3.25. igraph_girth — 图的周长是其中最短循环的长度。
3.26. igraph_eccentricity — 一些顶点的离心率。
3.27. igraph_eccentricity_dijkstra — 一些顶点的离心率,使用加权边。
3.28. igraph_radius — 图的半径。
3.29. igraph_radius_dijkstra — 图的半径,使用加权边。
3.30. igraph_graph_center — 图的中心顶点。
3.31. igraph_graph_center_dijkstra — 图的中心顶点,使用加权边。
3.32. igraph_pseudo_diameter — 直径的近似值和下界。
3.33. igraph_pseudo_diameter_dijkstra — 加权图直径的近似值和下界。
3.34. igraph_voronoi — 图的 Voronoi 分区。
3.35. igraph_vertex_path_from_edge_path — 将边 ID 的游走转换为遍历的顶点 ID。

3.1. igraph_distances — 顶点之间最短路径的长度。

igraph_error_t igraph_distances(const igraph_t *graph, igraph_matrix_t *res,
                                const igraph_vs_t from, const igraph_vs_t to,
                                igraph_neimode_t mode);

参数: 

:

图对象。

res:

计算结果,一个矩阵。 更准确地说,是指向初始化矩阵的指针。 如果需要,将调整矩阵大小。 它的行数与 from 参数的长度相同,其列数是 to 参数中顶点的数量。 矩阵的一行显示从/到给定顶点到 to 中顶点的距离。 对于无法到达的顶点,返回 IGRAPH_INFINITY

:

源顶点。

:

目标顶点。 不允许将一个顶点多次包含在内。

模式:

用于计算有向图中最短路径的类型。 可能的值

IGRAPH_OUT

计算传出路径的长度。

IGRAPH_IN

计算传入路径的长度。

IGRAPH_ALL

在计算时,有向图被视为无向图。

返回值: 

错误代码

IGRAPH_ENOMEM

临时数据没有足够的内存。

IGRAPH_EINVVID

传递了无效的顶点 ID。

IGRAPH_EINVMODE

无效的模式参数。

时间复杂度:O(n(|V|+|E|)),n 是要计算的顶点数,|V| 和 |E| 是图中顶点和边的数量。

另请参阅: 

igraph_get_shortest_paths() 获取路径本身,igraph_distances_dijkstra() 用于具有非负权重的加权版本,如果您也有负权重,请使用 igraph_distances_bellman_ford()

示例 13.1.  文件 examples/simple/distances.c

#include <igraph.h>

int main(void) {

    igraph_t graph;
    igraph_vector_t weights;
    igraph_real_t weights_data[] = { 0, 2, 1, 0, 5, 2, 1, 1, 0, 2, 2, 8, 1, 1, 3, 1, 1, 4, 2, 1 };
    igraph_matrix_t res;
    igraph_real_t cutoff;

    igraph_small(&graph, 10, IGRAPH_DIRECTED,
                 0, 1, 0, 2, 0, 3,    1, 2, 1, 4, 1, 5,
                 2, 3, 2, 6,          3, 2, 3, 6,
                 4, 5, 4, 7,          5, 6, 5, 8, 5, 9,
                 7, 5, 7, 8,          8, 9,
                 5, 2,
                 2, 1,
                 -1);

    igraph_matrix_init(&res, 0, 0);

    printf("Unweighted distances:\n\n");

    igraph_distances(&graph, &res, igraph_vss_all(), igraph_vss_all(), IGRAPH_OUT);
    igraph_matrix_print(&res);

    cutoff = 3; /* distances longer than this will be returned as infinity */
    printf("\nUnweighted distances with a cutoff of %g:\n\n", cutoff);
    igraph_distances_cutoff(&graph, &res, igraph_vss_all(), igraph_vss_all(), IGRAPH_OUT, cutoff);
    igraph_matrix_print(&res);

    printf("\nWeighted distances:\n\n");

    igraph_vector_view(&weights, weights_data,
                       sizeof(weights_data) / sizeof(weights_data[0]));

    igraph_distances_dijkstra(&graph, &res, igraph_vss_all(), igraph_vss_all(),
                              &weights, IGRAPH_OUT);
    igraph_matrix_print(&res);

    cutoff = 8; /* distances longer than this will be returned as infinity */
    printf("\nWeighted distances with a cutoff of %g:\n\n", cutoff);
    igraph_distances_dijkstra_cutoff(&graph, &res, igraph_vss_all(), igraph_vss_all(),
                              &weights, IGRAPH_OUT, cutoff);
    igraph_matrix_print(&res);

    igraph_matrix_destroy(&res);
    igraph_destroy(&graph);

    return 0;
}


3.2. igraph_distances_cutoff — 顶点之间最短路径的长度,带截止值。

igraph_error_t igraph_distances_cutoff(const igraph_t *graph, igraph_matrix_t *res,
                          const igraph_vs_t from, const igraph_vs_t to,
                          igraph_neimode_t mode, igraph_real_t cutoff);

警告

此函数是实验性的,其签名尚未被视为最终签名。我们保留更改函数签名的权利,而无需更改 igraph 的主要版本。使用它需要您自担风险。

此函数类似于 igraph_distances(),但是不会考虑长于 cutoff 的路径。

参数: 

:

图对象。

res:

计算结果,一个矩阵。 更准确地说,是指向初始化矩阵的指针。 如果需要,将调整矩阵大小。 它的行数与 from 参数的长度相同,其列数是 to 参数中顶点的数量。 矩阵的一行显示从/到给定顶点到 to 中顶点的距离。 对于无法到达的顶点,返回 IGRAPH_INFINITY

:

源顶点._d

:

目标顶点。 不允许将一个顶点多次包含在内。

模式:

用于计算有向图中最短路径的类型。 可能的值

IGRAPH_OUT

计算传出路径的长度。

IGRAPH_IN

计算传入路径的长度。

IGRAPH_ALL

在计算时,有向图被视为无向图。

cutoff:

将考虑的路径的最大长度。 当两个顶点之间的距离大于此值时,它将作为 IGRAPH_INFINITY 返回。 负截止值被视为无穷大。

返回值: 

错误代码

IGRAPH_ENOMEM

临时数据没有足够的内存。

IGRAPH_EINVVID

传递了无效的顶点 ID。

IGRAPH_EINVMODE

无效的模式参数。

时间复杂度:O(s |E| + |V|),其中 s 是要使用的源顶点数,|V| 和 |E| 是图中顶点和边的数量。

另请参阅: 

igraph_distances_dijkstra_cutoff() 用于具有非负权重的加权版本。

示例 13.2.  文件 examples/simple/distances.c

#include <igraph.h>

int main(void) {

    igraph_t graph;
    igraph_vector_t weights;
    igraph_real_t weights_data[] = { 0, 2, 1, 0, 5, 2, 1, 1, 0, 2, 2, 8, 1, 1, 3, 1, 1, 4, 2, 1 };
    igraph_matrix_t res;
    igraph_real_t cutoff;

    igraph_small(&graph, 10, IGRAPH_DIRECTED,
                 0, 1, 0, 2, 0, 3,    1, 2, 1, 4, 1, 5,
                 2, 3, 2, 6,          3, 2, 3, 6,
                 4, 5, 4, 7,          5, 6, 5, 8, 5, 9,
                 7, 5, 7, 8,          8, 9,
                 5, 2,
                 2, 1,
                 -1);

    igraph_matrix_init(&res, 0, 0);

    printf("Unweighted distances:\n\n");

    igraph_distances(&graph, &res, igraph_vss_all(), igraph_vss_all(), IGRAPH_OUT);
    igraph_matrix_print(&res);

    cutoff = 3; /* distances longer than this will be returned as infinity */
    printf("\nUnweighted distances with a cutoff of %g:\n\n", cutoff);
    igraph_distances_cutoff(&graph, &res, igraph_vss_all(), igraph_vss_all(), IGRAPH_OUT, cutoff);
    igraph_matrix_print(&res);

    printf("\nWeighted distances:\n\n");

    igraph_vector_view(&weights, weights_data,
                       sizeof(weights_data) / sizeof(weights_data[0]));

    igraph_distances_dijkstra(&graph, &res, igraph_vss_all(), igraph_vss_all(),
                              &weights, IGRAPH_OUT);
    igraph_matrix_print(&res);

    cutoff = 8; /* distances longer than this will be returned as infinity */
    printf("\nWeighted distances with a cutoff of %g:\n\n", cutoff);
    igraph_distances_dijkstra_cutoff(&graph, &res, igraph_vss_all(), igraph_vss_all(),
                              &weights, IGRAPH_OUT, cutoff);
    igraph_matrix_print(&res);

    igraph_matrix_destroy(&res);
    igraph_destroy(&graph);

    return 0;
}


3.3. igraph_distances_dijkstra — 顶点之间加权最短路径的长度。

igraph_error_t igraph_distances_dijkstra(const igraph_t *graph,
                                         igraph_matrix_t *res,
                                         const igraph_vs_t from,
                                         const igraph_vs_t to,
                                         const igraph_vector_t *weights,
                                         igraph_neimode_t mode);

此函数实现了 Dijkstra 算法,该算法可以找到从源顶点到所有其他顶点的加权最短路径长度。 此函数允许指定一组源顶点和目标顶点。 该算法为每个源独立运行,结果仅保留用于指定的目标。 此实现使用二叉堆以提高效率。

参数: 

:

输入图,可以是有向的。

res:

结果,一个矩阵。 指向初始化矩阵的指针应在此处传递。 将根据需要调整矩阵大小。 每行包含从单个源到 to 参数中给出的顶点的距离。 无法到达的顶点的距离为 IGRAPH_INFINITY

:

源顶点。

:

目标顶点。 不允许将一个顶点多次包含在内。

weights:

边权重。 所有边权重必须为非负数,Dijkstra 算法才能工作。 此外,没有边权重可以为 NaN。 如果其中任何一种情况不成立,则返回错误。 如果这是一个空指针,则调用未加权版本 igraph_distances()

模式:

对于有向图; 是否沿边方向 (IGRAPH_OUT) 或相反方向 (IGRAPH_IN) 跟踪路径,或者完全忽略边方向 (IGRAPH_ALL)。 对于无向图,它将被忽略。

返回值: 

错误代码。

时间复杂度:O(s*|E|log|V|+|V|),其中 |V| 是顶点数,|E| 是边的数量,s 是源的数量。

另请参阅: 

igraph_distances() 用于(稍微)更快的未加权版本,或者 igraph_distances_bellman_ford() 用于在存在负边权重(但没有负循环)的情况下工作的加权变体

示例 13.3.  文件 examples/simple/distances.c

#include <igraph.h>

int main(void) {

    igraph_t graph;
    igraph_vector_t weights;
    igraph_real_t weights_data[] = { 0, 2, 1, 0, 5, 2, 1, 1, 0, 2, 2, 8, 1, 1, 3, 1, 1, 4, 2, 1 };
    igraph_matrix_t res;
    igraph_real_t cutoff;

    igraph_small(&graph, 10, IGRAPH_DIRECTED,
                 0, 1, 0, 2, 0, 3,    1, 2, 1, 4, 1, 5,
                 2, 3, 2, 6,          3, 2, 3, 6,
                 4, 5, 4, 7,          5, 6, 5, 8, 5, 9,
                 7, 5, 7, 8,          8, 9,
                 5, 2,
                 2, 1,
                 -1);

    igraph_matrix_init(&res, 0, 0);

    printf("Unweighted distances:\n\n");

    igraph_distances(&graph, &res, igraph_vss_all(), igraph_vss_all(), IGRAPH_OUT);
    igraph_matrix_print(&res);

    cutoff = 3; /* distances longer than this will be returned as infinity */
    printf("\nUnweighted distances with a cutoff of %g:\n\n", cutoff);
    igraph_distances_cutoff(&graph, &res, igraph_vss_all(), igraph_vss_all(), IGRAPH_OUT, cutoff);
    igraph_matrix_print(&res);

    printf("\nWeighted distances:\n\n");

    igraph_vector_view(&weights, weights_data,
                       sizeof(weights_data) / sizeof(weights_data[0]));

    igraph_distances_dijkstra(&graph, &res, igraph_vss_all(), igraph_vss_all(),
                              &weights, IGRAPH_OUT);
    igraph_matrix_print(&res);

    cutoff = 8; /* distances longer than this will be returned as infinity */
    printf("\nWeighted distances with a cutoff of %g:\n\n", cutoff);
    igraph_distances_dijkstra_cutoff(&graph, &res, igraph_vss_all(), igraph_vss_all(),
                              &weights, IGRAPH_OUT, cutoff);
    igraph_matrix_print(&res);

    igraph_matrix_destroy(&res);
    igraph_destroy(&graph);

    return 0;
}


3.4. igraph_distances_dijkstra_cutoff — 顶点之间加权最短路径的长度,带截止值。

igraph_error_t igraph_distances_dijkstra_cutoff(const igraph_t *graph,
                                   igraph_matrix_t *res,
                                   const igraph_vs_t from,
                                   const igraph_vs_t to,
                                   const igraph_vector_t *weights,
                                   igraph_neimode_t mode,
                                   igraph_real_t cutoff);

警告

此函数是实验性的,其签名尚未被视为最终签名。我们保留更改函数签名的权利,而无需更改 igraph 的主要版本。使用它需要您自担风险。

此函数类似于 igraph_distances_dijkstra(),但是不会考虑长于 cutoff 的路径。

参数: 

:

输入图,可以是有向的。

res:

结果,一个矩阵。 指向初始化矩阵的指针应在此处传递。 将根据需要调整矩阵大小。 每行包含从单个源到 to 参数中给出的顶点的距离。 在距离 cutoff 内无法到达的顶点将被分配距离 IGRAPH_INFINITY

:

源顶点。

:

目标顶点。 不允许将一个顶点多次包含在内。

weights:

边权重。 所有边权重必须为非负数,Dijkstra 算法才能工作。 此外,没有边权重可以为 NaN。 如果其中任何一种情况不成立,则返回错误。 如果这是一个空指针,则调用未加权版本 igraph_distances()。 具有正无穷权重的边将被忽略。

模式:

对于有向图; 是否沿边方向 (IGRAPH_OUT) 或相反方向 (IGRAPH_IN) 跟踪路径,或者完全忽略边方向 (IGRAPH_ALL)。 对于无向图,它将被忽略。

cutoff:

将考虑的路径的最大长度。 当两个顶点之间的距离大于此值时,它将作为 IGRAPH_INFINITY 返回。 负截止值被视为无穷大。

返回值: 

错误代码。

时间复杂度:最多 O(s |E| log|V| + |V|),其中 |V| 是顶点数,|E| 是边的数量,s 是源的数量。 cutoff 参数将限制从每个源顶点遍历的边数,这将减少计算时间。

另请参阅: 

igraph_distances_cutoff() 用于(稍微)更快的未加权版本。

示例 13.4.  文件 examples/simple/distances.c

#include <igraph.h>

int main(void) {

    igraph_t graph;
    igraph_vector_t weights;
    igraph_real_t weights_data[] = { 0, 2, 1, 0, 5, 2, 1, 1, 0, 2, 2, 8, 1, 1, 3, 1, 1, 4, 2, 1 };
    igraph_matrix_t res;
    igraph_real_t cutoff;

    igraph_small(&graph, 10, IGRAPH_DIRECTED,
                 0, 1, 0, 2, 0, 3,    1, 2, 1, 4, 1, 5,
                 2, 3, 2, 6,          3, 2, 3, 6,
                 4, 5, 4, 7,          5, 6, 5, 8, 5, 9,
                 7, 5, 7, 8,          8, 9,
                 5, 2,
                 2, 1,
                 -1);

    igraph_matrix_init(&res, 0, 0);

    printf("Unweighted distances:\n\n");

    igraph_distances(&graph, &res, igraph_vss_all(), igraph_vss_all(), IGRAPH_OUT);
    igraph_matrix_print(&res);

    cutoff = 3; /* distances longer than this will be returned as infinity */
    printf("\nUnweighted distances with a cutoff of %g:\n\n", cutoff);
    igraph_distances_cutoff(&graph, &res, igraph_vss_all(), igraph_vss_all(), IGRAPH_OUT, cutoff);
    igraph_matrix_print(&res);

    printf("\nWeighted distances:\n\n");

    igraph_vector_view(&weights, weights_data,
                       sizeof(weights_data) / sizeof(weights_data[0]));

    igraph_distances_dijkstra(&graph, &res, igraph_vss_all(), igraph_vss_all(),
                              &weights, IGRAPH_OUT);
    igraph_matrix_print(&res);

    cutoff = 8; /* distances longer than this will be returned as infinity */
    printf("\nWeighted distances with a cutoff of %g:\n\n", cutoff);
    igraph_distances_dijkstra_cutoff(&graph, &res, igraph_vss_all(), igraph_vss_all(),
                              &weights, IGRAPH_OUT, cutoff);
    igraph_matrix_print(&res);

    igraph_matrix_destroy(&res);
    igraph_destroy(&graph);

    return 0;
}


3.5. igraph_distances_bellman_ford — 顶点之间加权最短路径的长度,允许负权重。

igraph_error_t igraph_distances_bellman_ford(const igraph_t *graph,
                                       igraph_matrix_t *res,
                                       const igraph_vs_t from,
                                       const igraph_vs_t to,
                                       const igraph_vector_t *weights,
                                       igraph_neimode_t mode);

此函数实现了 Bellman-Ford 算法,以找到从单个源到所有顶点的加权最短路径,允许负权重。 它为给定的源独立运行。 如果没有负权重,最好使用 igraph_distances_dijkstra()

参数: 

:

输入图,可以是有向的。

res:

结果,一个矩阵。 指向初始化矩阵的指针应在此处传递,将根据需要调整矩阵大小。 每行包含从单个源到图中所有顶点的距离,按顶点 ID 的顺序排列。 对于无法到达的顶点,矩阵包含 IGRAPH_INFINITY

:

源顶点。

:

目标顶点。

weights:

边权重。 图中不得有任何具有负总权重的闭环(因为这将允许我们无限地减少包含此循环至少一个顶点的任何路径的权重)。 此外,没有边权重可以为 NaN。 如果其中任何一种情况不成立,则返回错误。 如果这是一个空指针,则调用未加权版本 igraph_distances()

模式:

对于有向图; 是否沿边方向 (IGRAPH_OUT) 或相反方向 (IGRAPH_IN) 跟踪路径,或者完全忽略边方向 (IGRAPH_ALL)。 对于无向图,它将被忽略。

返回值: 

错误代码。

时间复杂度:O(s*|E|*|V|),其中 |V| 是顶点数,|E| 是边的数量,s 是源的数量。

另请参阅: 

igraph_distances() 用于更快的未加权版本,或者 igraph_distances_dijkstra() 如果您没有负边权重,则使用,或者 igraph_distances_bellman_ford() 如果您只需要计算来自几个源的最短路径。

示例 13.5.  文件 examples/simple/bellman_ford.c

#include <igraph.h>

int main(void) {

    igraph_t g;
    igraph_vector_t weights;
    igraph_real_t weights_data_0[] = { 0, 2, 1, 0, 5, 2, 1, 1, 0, 2, 2, 8, 1, 1, 3, 1, 1, 4, 2, 1 };
    igraph_real_t weights_data_1[] = { 6, 7, 8, -4, -2, -3, 9, 2, 7 };
    igraph_real_t weights_data_2[] = { 6, 7, 2, -4, -2, -3, 9, 2, 7 };
    igraph_matrix_t res;

    /* Graph with only positive weights */
    igraph_small(&g, 10, IGRAPH_DIRECTED,
                 0, 1, 0, 2, 0, 3,    1, 2, 1, 4, 1, 5,
                 2, 3, 2, 6,         3, 2, 3, 6,
                 4, 5, 4, 7,         5, 6, 5, 8, 5, 9,
                 7, 5, 7, 8,         8, 9,
                 5, 2,
                 2, 1,
                 -1);

    igraph_vector_view(&weights, weights_data_0,
                       sizeof(weights_data_0) / sizeof(weights_data_0[0]));

    igraph_matrix_init(&res, 0, 0);
    igraph_distances_bellman_ford(&g, &res, igraph_vss_all(), igraph_vss_all(),
                                  &weights, IGRAPH_OUT);
    igraph_matrix_print(&res);

    igraph_matrix_destroy(&res);
    igraph_destroy(&g);

    printf("\n");

    /***************************************/

    /* Graph with negative weights */
    igraph_small(&g, 5, IGRAPH_DIRECTED,
                 0, 1, 0, 3, 1, 3, 1, 4, 2, 1, 3, 2, 3, 4, 4, 0, 4, 2, -1);

    igraph_vector_view(&weights, weights_data_1,
                       sizeof(weights_data_1) / sizeof(weights_data_1[0]));

    igraph_matrix_init(&res, 0, 0);
    igraph_distances_bellman_ford(&g, &res, igraph_vss_all(),
                                  igraph_vss_all(), &weights, IGRAPH_OUT);
    igraph_matrix_print(&res);

    /***************************************/

    /* Same graph with negative loop */
    igraph_set_error_handler(igraph_error_handler_ignore);
    igraph_vector_view(&weights, weights_data_2,
                       sizeof(weights_data_2) / sizeof(weights_data_2[0]));
    if (igraph_distances_bellman_ford(&g, &res, igraph_vss_all(),
                                      igraph_vss_all(),
                                      &weights, IGRAPH_OUT) != IGRAPH_ENEGLOOP) {
        return 1;
    }

    igraph_matrix_destroy(&res);
    igraph_destroy(&g);

    if (!IGRAPH_FINALLY_STACK_EMPTY) {
        return 1;
    }

    return 0;
}


3.6. igraph_distances_johnson — 顶点之间加权最短路径的长度,使用 Johnson 算法。

igraph_error_t igraph_distances_johnson(const igraph_t *graph,
                                  igraph_matrix_t *res,
                                  const igraph_vs_t from,
                                  const igraph_vs_t to,
                                  const igraph_vector_t *weights);

此算法支持具有负边权重的有向图,并且在从许多不同源计算距离时(典型的用例是所有对距离计算),其性能优于 Bellman-Ford 方法。 它通过使用单源 Bellman-Ford 运行将所有边权重转换为非负权重,然后使用新权重调用 Dijkstra 算法来工作。 有关更多详细信息,请参见 Wikipedia 页面:http://en.wikipedia.org/wiki/Johnson's_algorithm

如果没有提供边权重,则调用未加权版本 igraph_distances()。 如果提供的边权重都不是负数,则通过调用 igraph_distances_dijkstra() 来使用 Dijkstra 算法。

请注意,Johnson 算法仅适用于有向图。 此函数拒绝具有 任何 负边权重的无向图,即使 fromto 顶点都在没有负权重的连接组件中。

参考

Donald B. Johnson:稀疏网络中最短路径的有效算法。 J. ACM 24, 1 (1977), 1–13. https://doi.org/10.1145/321992.321993

参数: 

:

输入图。 如果存在负权重,则应将其定向。

res:

指向初始化矩阵的指针,结果将存储在此处,每个源顶点一行,每个目标顶点一列。

:

源顶点。

:

目标顶点。 不允许将一个顶点多次包含在内。

weights:

可选的边权重。 如果它是一个空指针,则将调用基于未加权广度优先搜索的 igraph_distances()。 具有正无穷权重的边将被忽略。

返回值: 

错误代码。

时间复杂度:O(s|V|log|V|+|V||E|),|V| 和 |E| 是顶点数和边的数量,s 是源顶点的数量。

另请参阅: 

igraph_distances() 用于更快的未加权版本,igraph_distances_dijkstra() 如果您没有负边权重,则使用,igraph_distances_bellman_ford() 如果您只需要计算来自几个源的最短路径。

3.7. igraph_distances_floyd_warshall — 使用 Floyd-Warshall 算法的加权所有对最短路径长度。

igraph_error_t igraph_distances_floyd_warshall(
        const igraph_t *graph, igraph_matrix_t *res,
        igraph_vs_t from, igraph_vs_t to,
        const igraph_vector_t *weights, igraph_neimode_t mode,
        const igraph_floyd_warshall_algorithm_t method);

警告

此函数是实验性的,其签名尚未被视为最终签名。我们保留更改函数签名的权利,而无需更改 igraph 的主要版本。使用它需要您自担风险。

Floyd-Warshall 算法同时计算所有顶点对之间的加权最短路径长度。 它对于非常密集的加权图很有用,因为它的运行时间主要由顶点数决定,并且对图密度不敏感。 在稀疏图中,Dijkstra 或 Bellman-Ford 算法等其他方法将表现得更好。

除了原始的 Floyd-Warshall 算法外,igraph 还包含一些变体的实现,这些变体提供了更好的渐近复杂度以及大多数实例的更好的实际运行时间。 有关更多信息,请参见下面的参考。

请注意,在内部,此函数始终计算所有顶点对的距离矩阵。 fromto 参数仅用于子集化此矩阵,但不影响计算所花费的时间或内存。

参考

Brodnik, A., Grgurovič, M., Požar, R.: Floyd-Warshall 算法的修改,具有接近二次方的预期时间,Ars Mathematica Contemporanea,第 22 卷,第 1 期,第 #P1.01 页 (2021)。 https://doi.org/10.26493/1855-3974.2467.497

参数: 

:

图对象。

res:

一个初始化矩阵,距离将存储在此处。

:

源顶点。

:

目标顶点。

weights:

边权重。 如果 NULL,则假定所有权重均为 1。 允许负权重,但图不能包含负循环。 具有正无穷权重的边将被忽略。

模式:

用于计算有向图中最短路径的类型。 可能的值

IGRAPH_OUT

计算传出路径。

IGRAPH_IN

计算传入路径。

IGRAPH_ALL

在计算时,有向图被视为无向图。

method:

使用的算法类型。

IGRAPH_FLOYD_WARSHALL_AUTOMATIC

尝试为当前图选择性能最佳的变体; 目前,此选项始终使用“Tree”方法。

IGRAPH_FLOYD_WARSHALL_ORIGINAL

基本的 Floyd-Warshall 算法。

IGRAPH_FLOYD_WARSHALL_TREE

Brodnik 等人的“Tree”加速,在大多数情况下比原始算法更快。

返回值: 

错误代码。 如果找到负权重循环,则返回 IGRAPH_ENEGLOOP

另请参阅: 

时间复杂度:原始变体的复杂度为 O(|V|^3 + |E|)。 根据 Brodnik 等人,“Tree”变体的预期情况复杂度为 O(|V|^2 log^2 |V|),而其最坏情况复杂度仍然为 O(|V|^3)。 在这里,|V| 表示顶点数,|E| 是边的数量。

3.8. igraph_get_shortest_paths — 从顶点出发的最短路径。

igraph_error_t igraph_get_shortest_paths(const igraph_t *graph,
                              igraph_vector_int_list_t *vertices,
                              igraph_vector_int_list_t *edges,
                              igraph_integer_t from, const igraph_vs_t to,
                              igraph_neimode_t mode,
                              igraph_vector_int_t *parents,
                              igraph_vector_int_t *inbound_edges);

查找从单个源顶点到指定目标顶点集的未加权最短路径。 如果两个顶点之间有多条测地线,则此函数仅给出其中一条。 使用 igraph_get_all_shortest_paths() 查找 所有 最短路径。

参数: 

:

图对象。

vertices:

结果,沿路径的顶点 ID。 这是一个整数向量列表,其中每个元素都是一个 igraph_vector_int_t 对象。 将根据需要调整列表大小。 如果您不需要这些向量,请在此处提供空指针。

:

结果,沿路径的边 ID。 这是一个整数向量列表,其中每个元素都是一个 igraph_vector_int_t 对象。 将根据需要调整列表大小。 如果您不需要这些向量,请在此处提供空指针。

:

从中/向其计算测地线的顶点的 ID。

:

顶点序列,其中包含从中/向其计算最短路径的顶点的 ID。 一个顶点可能会被多次给出。

模式:

用于计算有向图中最短路径的类型。 可能的值

IGRAPH_OUT

计算传出路径。

IGRAPH_IN

计算传入路径。

IGRAPH_ALL

在计算时,有向图被视为无向图。

parents:

指向初始化 igraph 向量的指针或 NULL。 如果不为 NULL,则会在此处返回一个向量,其中包含单源最短路径树中每个顶点的父节点。 树中顶点 i 的父节点是从其到达顶点 i 的顶点。 开始顶点(在 from 参数中)的父节点为 -1。 如果父节点为 -2,则表示在搜索期间无法从源到达给定顶点。 请注意,如果已到达 to 中的所有顶点,则搜索将终止。

inbound_edges:

指向初始化 igraph 向量的指针或 NULL。 如果不为 NULL,则会在此处返回一个向量,其中包含单源最短路径树中每个顶点的入站边。 树中顶点 i 的入站边是通过其到达顶点 i 的边。 开始顶点和在搜索期间未到达的顶点将在向量的相应条目中具有 -1。 请注意,如果已到达 to 中的所有顶点,则搜索将终止。

返回值: 

错误代码

IGRAPH_ENOMEM

临时数据没有足够的内存。

IGRAPH_EINVVID

from 是无效的顶点 ID

IGRAPH_EINVMODE

无效的模式参数。

时间复杂度:O(|V|+|E|),|V| 是图中顶点的数量,|E| 是边的数量。

另请参阅: 

igraph_distances() 如果您只需要路径长度而不是路径本身; igraph_get_shortest_paths_dijkstra() 用于加权版本; igraph_get_all_shortest_paths() 返回 (源, 目标) 对之间的所有最短路径。

示例 13.6.  文件 examples/simple/igraph_get_shortest_paths.c

#include <igraph.h>

#include <stdlib.h>

int check_evecs(const igraph_t *graph, const igraph_vector_int_list_t *vecs,
                const igraph_vector_int_list_t *evecs, int error_code) {

    igraph_bool_t directed = igraph_is_directed(graph);
    igraph_integer_t i, n = igraph_vector_int_list_size(vecs);
    if (igraph_vector_int_list_size(evecs) != n) {
        exit(error_code + 1);
    }

    for (i = 0; i < n; i++) {
        igraph_vector_int_t *vvec = igraph_vector_int_list_get_ptr(vecs, i);
        igraph_vector_int_t *evec = igraph_vector_int_list_get_ptr(evecs, i);
        igraph_integer_t j, n2 = igraph_vector_int_size(evec);
        if (igraph_vector_int_size(vvec) == 0 && n2 == 0) {
            continue;
        }
        if (igraph_vector_int_size(vvec) != n2 + 1) {
            exit(error_code + 2);
        }
        for (j = 0; j < n2; j++) {
            igraph_integer_t edge = VECTOR(*evec)[j];
            igraph_integer_t from = VECTOR(*vvec)[j];
            igraph_integer_t to = VECTOR(*vvec)[j + 1];
            if (directed) {
                if (from != IGRAPH_FROM(graph, edge) ||
                    to   != IGRAPH_TO  (graph, edge)) {
                    exit(error_code);
                }
            } else {
                igraph_integer_t from2 = IGRAPH_FROM(graph, edge);
                igraph_integer_t to2 = IGRAPH_TO(graph, edge);
                igraph_integer_t min1 = from < to ? from : to;
                igraph_integer_t max1 = from < to ? to : from;
                igraph_integer_t min2 = from2 < to2 ? from2 : to2;
                igraph_integer_t max2 = from2 < to2 ? to2 : from2;
                if (min1 != min2 || max1 != max2) {
                    exit(error_code + 3);
                }
            }
        }
    }

    return 0;
}

int main(void) {

    igraph_t g;
    igraph_vector_int_list_t vecs, evecs;
    igraph_vector_int_t parents, inbound;
    igraph_integer_t i;
    igraph_vs_t vs;

    igraph_ring(&g, 10, IGRAPH_DIRECTED, 0, 1);

    igraph_vector_int_list_init(&vecs, 0);
    igraph_vector_int_list_init(&evecs, 0);
    igraph_vector_int_init(&parents, 0);
    igraph_vector_int_init(&inbound, 0);

    igraph_vs_vector_small(&vs, 1, 3, 5, 2, 1,  -1);

    igraph_get_shortest_paths(&g, &vecs, &evecs, 0, vs, IGRAPH_OUT, &parents, &inbound);

    check_evecs(&g, &vecs, &evecs, 10);

    for (i = 0; i < igraph_vector_int_list_size(&vecs); i++) {
        igraph_vector_int_print(igraph_vector_int_list_get_ptr(&vecs, i));
    }

    igraph_vector_int_print(&parents);
    igraph_vector_int_print(&inbound);

    igraph_vector_int_list_destroy(&vecs);
    igraph_vector_int_list_destroy(&evecs);
    igraph_vector_int_destroy(&parents);
    igraph_vector_int_destroy(&inbound);

    igraph_vs_destroy(&vs);
    igraph_destroy(&g);

    if (!IGRAPH_FINALLY_STACK_EMPTY) {
        return 1;
    }

    return 0;
}


3.9. igraph_get_shortest_path — 从一个顶点到另一个顶点的最短路径。

igraph_error_t igraph_get_shortest_path(const igraph_t *graph,
                             igraph_vector_int_t *vertices,
                             igraph_vector_int_t *edges,
                             igraph_integer_t from,
                             igraph_integer_t to,
                             igraph_neimode_t mode);

计算并返回从给定顶点到另一个顶点的单个未加权最短路径。 如果两个顶点之间有多条最短路径,则返回任意一条。

此函数是 igraph_get_shortest_paths() 的包装器,用于仅考虑一个目标顶点的特殊情况。

参数: 

:

输入图,可以是有向的或无向的。 在有向图中考虑有向路径。

vertices:

指向初始化向量的指针或空指针。 如果不是空指针,则沿路径的顶点 ID 将存储在此处,包括源顶点和目标顶点。

:

指向初始化向量的指针或空指针。 如果不是空指针,则沿路径的边 ID 将存储在此处。

:

源顶点的 ID。

:

目标顶点的 ID。

模式:

一个常量,用于指定如何在有向图中考虑边方向。 有效模式为:IGRAPH_OUT,跟随边方向;IGRAPH_IN,跟随相反方向;和 IGRAPH_ALL,忽略边方向。 对于无向图,此参数将被忽略。

返回值: 

错误代码。

时间复杂度:O(|V|+|E|),与图中顶点和边的数量呈线性关系。

另请参阅: 

igraph_get_shortest_paths() 用于具有更多目标顶点的版本。

3.10. igraph_get_shortest_paths_dijkstra — 从顶点出发的加权最短路径。

igraph_error_t igraph_get_shortest_paths_dijkstra(const igraph_t *graph,
                                       igraph_vector_int_list_t *vertices,
                                       igraph_vector_int_list_t *edges,
                                       igraph_integer_t from,
                                       igraph_vs_t to,
                                       const igraph_vector_t *weights,
                                       igraph_neimode_t mode,
                                       igraph_vector_int_t *parents,
                                       igraph_vector_int_t *inbound_edges);

使用 Dijkstra 算法查找从单个源顶点到指定目标顶点集的加权最短路径。 如果两个顶点之间有多条权重最小的路径,则此函数仅给出其中一条。 要查找所有此类路径,请使用 igraph_get_all_shortest_paths_dijkstra()

参数: 

:

图对象。

vertices:

结果,沿路径的顶点 ID。 这是一个整数向量列表,其中每个元素都是一个 igraph_vector_int_t 对象。 将根据需要调整列表大小。 如果您不需要这些向量,请在此处提供空指针。

:

结果,沿路径的边 ID。 这是一个整数向量列表,其中每个元素都是一个 igraph_vector_int_t 对象。 将根据需要调整列表大小。 如果您不需要这些向量,请在此处提供空指针。

:

从中/向其计算测地线的顶点的 ID。

:

顶点序列,其中包含从中/向其计算最短路径的顶点的 ID。 一个顶点可能会被多次给出。 *

weights:

边权重。 所有边权重必须为非负数,Dijkstra 算法才能工作。 此外,没有边权重可以为 NaN。 如果其中任何一种情况不成立,则返回错误。 如果这是一个空指针,则调用未加权版本 igraph_get_shortest_paths()

模式:

用于计算有向图中最短路径的类型。 可能的值

IGRAPH_OUT

计算传出路径。

IGRAPH_IN

计算传入路径。

IGRAPH_ALL

在计算时,有向图被视为无向图。

parents:

指向初始化 igraph 向量的指针或 null。 如果不为 null,则会在此处返回一个向量,其中包含单源最短路径树中每个顶点的父节点。 树中顶点 i 的父节点是从其到达顶点 i 的顶点。 开始顶点(在 from 参数中)的父节点为 -1。 如果父节点为 -2,则表示在搜索期间无法从源到达给定顶点。 请注意,如果已到达 to 中的所有顶点,则搜索将终止。

inbound_edges:

指向初始化 igraph 向量的指针或 null。 如果不为 null,则会在此处返回一个向量,其中包含单源最短路径树中每个顶点的入站边。 树中顶点 i 的入站边是通过其到达顶点 i 的边。 开始顶点和在搜索期间未到达的顶点将在向量的相应条目中具有 -1。 请注意,如果已到达 to 中的所有顶点,则搜索将终止。

返回值: 

错误代码

IGRAPH_ENOMEM

临时数据没有足够的内存。

IGRAPH_EINVVID

from 是无效的顶点 ID

IGRAPH_EINVMODE

无效的模式参数。

时间复杂度:O(|E|log|V|+|V|),其中 |V| 是顶点数,|E| 是边的数量

另请参阅: 

igraph_distances_dijkstra() 如果您只需要路径长度而不是路径本身; igraph_get_shortest_paths() 如果所有边权重都相等; igraph_get_all_shortest_paths() 查找 (源, 目标) 对之间的所有最短路径; igraph_get_shortest_paths_bellman_ford() 如果某些边权重为负数。

示例 13.7.  文件 examples/simple/igraph_get_shortest_paths_dijkstra.c

#include <igraph.h>
#include <stdlib.h>

int main(void) {

    igraph_t g;
    igraph_vector_int_list_t vecs, evecs;
    igraph_vector_int_t parents, inbound;
    igraph_integer_t i;
    igraph_real_t weights[] = { 0, 2, 1, 0, 5, 2, 1, 1, 0, 2, 2, 8, 1, 1, 3, 1, 1, 4, 2, 1 };
    igraph_vector_t weights_vec;
    igraph_vs_t vs;

    igraph_vector_int_list_init(&vecs, 0);
    igraph_vector_int_list_init(&evecs, 0);
    igraph_vector_int_init(&parents, 0);
    igraph_vector_int_init(&inbound, 0);

    igraph_vs_vector_small(&vs, 0, 1, 3, 5, 2, 1, -1);
    igraph_small(&g, 10, IGRAPH_DIRECTED,
                 0, 1, 0, 2, 0, 3,   1, 2, 1, 4, 1, 5,
                 2, 3, 2, 6,         3, 2, 3, 6,
                 4, 5, 4, 7,         5, 6, 5, 8, 5, 9,
                 7, 5, 7, 8,         8, 9,
                 5, 2,
                 2, 1,
                 -1);

    igraph_vector_view(&weights_vec, weights, sizeof(weights) / sizeof(weights[0]));
    igraph_get_shortest_paths_dijkstra(&g, /*vertices=*/ &vecs,
                                       /*edges=*/ &evecs, /*from=*/ 0, /*to=*/ vs,
                                       &weights_vec, IGRAPH_OUT,
                                       &parents,
                                       /*inbound_edges=*/ &inbound);
    printf("Vertices:\n");
    for (i = 0; i < igraph_vector_int_list_size(&vecs); i++) {
        igraph_vector_int_print(igraph_vector_int_list_get_ptr(&vecs, i));
    }

    printf("\nEdges:\n");
    for (i = 0; i < igraph_vector_int_list_size(&evecs); i++) {
        igraph_vector_int_print(igraph_vector_int_list_get_ptr(&evecs, i));
    }

    printf("\nParents:\n");
    igraph_vector_int_print(&parents);

    printf("\nInbound:\n");
    igraph_vector_int_print(&inbound);

    igraph_vector_int_list_destroy(&vecs);
    igraph_vector_int_list_destroy(&evecs);
    igraph_vector_int_destroy(&parents);
    igraph_vector_int_destroy(&inbound);

    igraph_vs_destroy(&vs);
    igraph_destroy(&g);

    return 0;
}


3.11. igraph_get_shortest_path_dijkstra — 从一个顶点到另一个顶点的加权最短路径(Dijkstra)。

igraph_error_t igraph_get_shortest_path_dijkstra(const igraph_t *graph,
                                      igraph_vector_int_t *vertices,
                                      igraph_vector_int_t *edges,
                                      igraph_integer_t from,
                                      igraph_integer_t to,
                                      const igraph_vector_t *weights,
                                      igraph_neimode_t mode);

使用 Dijkstra 算法,从单个源顶点查找加权最短路径到单个目标顶点。如果存在多个最短路径,则返回任意一个。

此函数是 igraph_get_shortest_paths_dijkstra() 的特例(和包装器)。

参数: 

:

输入图,可以是定向的或非定向的。

vertices:

指向初始化向量的指针或空指针。 如果不是空指针,则沿路径的顶点 ID 将存储在此处,包括源顶点和目标顶点。

:

指向初始化向量的指针或空指针。 如果不是空指针,则沿路径的边 ID 将存储在此处。

:

源顶点的 ID。

:

目标顶点的 ID。

weights:

边权重。 所有边权重必须为非负数,Dijkstra 算法才能工作。 此外,没有边权重可以为 NaN。 如果其中任何一种情况不成立,则返回错误。 如果这是一个空指针,则调用未加权版本 igraph_get_shortest_paths()

模式:

一个常量,指定在有向图中如何考虑边的方向。IGRAPH_OUT 遵循边的方向,IGRAPH_IN 遵循相反的方向,IGRAPH_ALL 忽略边的方向。此参数在无向图中将被忽略。

返回值: 

错误代码。

时间复杂度:O(|E|log|V|+|V|),|V| 是顶点数,|E| 是图中的边数。

另请参阅: 

更多目标顶点版本请参考 igraph_get_shortest_paths_dijkstra()

3.12. igraph_get_shortest_paths_bellman_ford — 从顶点加权最短路径,允许负权重。

igraph_error_t igraph_get_shortest_paths_bellman_ford(const igraph_t *graph,
                                        igraph_vector_int_list_t *vertices,
                                        igraph_vector_int_list_t *edges,
                                        igraph_integer_t from,
                                        igraph_vs_t to,
                                        const igraph_vector_t *weights,
                                        igraph_neimode_t mode,
                                        igraph_vector_int_t *parents,
                                        igraph_vector_int_t *inbound_edges);

此函数使用 Bellman-Ford 算法计算从单个顶点或到单个顶点的加权最短路径,该算法可以处理负权重。当两个顶点之间存在多条最短路径时,仅返回其中一条。当没有负权重时,igraph_get_shortest_paths_dijkstra() 可能会更快。

参数: 

:

输入图,可以是有向的。

vertices:

结果,沿路径的顶点 ID。 这是一个整数向量列表,其中每个元素都是一个 igraph_vector_int_t 对象。 将根据需要调整列表大小。 如果您不需要这些向量,请在此处提供空指针。

:

结果,沿路径的边 ID。 这是一个整数向量列表,其中每个元素都是一个 igraph_vector_int_t 对象。 将根据需要调整列表大小。 如果您不需要这些向量,请在此处提供空指针。

:

从中/向其计算测地线的顶点的 ID。

:

顶点序列,其中包含从中/向其计算最短路径的顶点的 ID。 一个顶点可能会被多次给出。

weights:

边的权重。图中不能存在总权重为负数的闭环(因为这将使我们能够无限地减少包含该循环的至少一个顶点的任何路径的权重)。如果这是一个空指针,则调用非加权版本 igraph_get_shortest_paths()。具有正无穷权重的边将被忽略。

模式:

对于有向图; 是否沿边方向 (IGRAPH_OUT) 或相反方向 (IGRAPH_IN) 跟踪路径,或者完全忽略边方向 (IGRAPH_ALL)。 对于无向图,它将被忽略。

parents:

指向初始化 igraph 向量的指针或 null。 如果不为 null,则会在此处返回一个向量,其中包含单源最短路径树中每个顶点的父节点。 树中顶点 i 的父节点是从其到达顶点 i 的顶点。 开始顶点(在 from 参数中)的父节点为 -1。 如果父节点为 -2,则表示在搜索期间无法从源到达给定顶点。 请注意,如果已到达 to 中的所有顶点,则搜索将终止。

inbound_edges:

指向初始化 igraph 向量的指针或 null。 如果不为 null,则会在此处返回一个向量,其中包含单源最短路径树中每个顶点的入站边。 树中顶点 i 的入站边是通过其到达顶点 i 的边。 开始顶点和在搜索期间未到达的顶点将在向量的相应条目中具有 -1。 请注意,如果已到达 to 中的所有顶点,则搜索将终止。

返回值: 

错误代码

IGRAPH_ENOMEM

临时数据内存不足。

IGRAPH_EINVAL

权重向量与边的数量不匹配。

IGRAPH_EINVVID

from 是无效的顶点 ID

IGRAPH_ENEGLOOP

Bellman-ford 算法遇到负环。

时间复杂度:O(|E|*|V|),其中 |V| 是顶点数,|E| 是边数。

另请参阅: 

若仅计算最短路径长度而非路径本身,请参考 igraph_distances_bellman_ford();若使用更快的非加权版本,请参考 igraph_get_shortest_paths();若没有负边权重,请参考 igraph_get_shortest_paths_dijkstra()

3.13. igraph_get_shortest_path_bellman_ford — 从一个顶点到另一个顶点的加权最短路径 (Bellman-Ford)。

igraph_error_t igraph_get_shortest_path_bellman_ford(const igraph_t *graph,
                                          igraph_vector_int_t *vertices,
                                          igraph_vector_int_t *edges,
                                          igraph_integer_t from,
                                          igraph_integer_t to,
                                          const igraph_vector_t *weights,
                                          igraph_neimode_t mode);

使用 Bellman-Ford 算法,查找从单个源顶点到单个目标的加权最短路径。

此函数是 igraph_get_shortest_paths_bellman_ford() 的特例(和包装器)。

参数: 

:

输入图,可以是定向的或非定向的。

vertices:

指向初始化向量的指针或空指针。 如果不是空指针,则沿路径的顶点 ID 将存储在此处,包括源顶点和目标顶点。

:

指向初始化向量的指针或空指针。 如果不是空指针,则沿路径的边 ID 将存储在此处。

:

源顶点的 ID。

:

目标顶点的 ID。

weights:

边的权重。图中不能存在总权重为负数的闭环(因为这将使我们能够无限地减少包含该循环的至少一个顶点的任何路径的权重)。如果这是一个空指针,则调用非加权版本。

模式:

一个常量,指定在有向图中如何考虑边的方向。IGRAPH_OUT 遵循边的方向,IGRAPH_IN 遵循相反的方向,IGRAPH_ALL 忽略边的方向。此参数在无向图中将被忽略。

返回值: 

错误代码。

时间复杂度:O(|E|*|V|),|V| 是顶点数,|E| 是图中的边数。

另请参阅: 

更多目标顶点版本请参考 igraph_get_shortest_paths_bellman_ford()

3.14. igraph_get_shortest_path_astar — A* 算法给出从一个顶点到另一个顶点的最短路径,带启发式。

igraph_error_t igraph_get_shortest_path_astar(const igraph_t *graph,
                                      igraph_vector_int_t *vertices,
                                      igraph_vector_int_t *edges,
                                      igraph_integer_t from,
                                      igraph_integer_t to,
                                      const igraph_vector_t *weights,
                                      igraph_neimode_t mode,
                                      igraph_astar_heuristic_func_t *heuristic,
                                      void *extra);

警告

此函数是实验性的,其签名尚未被视为最终签名。我们保留更改函数签名的权利,而无需更改 igraph 的主要版本。使用它需要您自担风险。

使用 A* 算法,计算从单个源顶点到单个目标的最短路径。A* 尝试通过从 from 开始,移动到位于估计长度最短路径上的顶点来找到最短路径。此长度估计是两个数字的总和:从源 (from) 到中间顶点的距离,以及启发式函数返回的值。启发式函数提供中间候选顶点与目标顶点 to 之间的距离估计。只有当启发式不估计过高距离时,即如果启发式函数是可采纳的,A* 算法才能保证给出正确的短路径(如果存在)。

参数: 

:

输入图,可以是定向的或非定向的。

vertices:

指向初始化向量的指针或 NULL 指针。如果不是 NULL,则沿路径的顶点 ID 存储在此处,包括源和目标顶点。

:

指向初始化向量的指针或 NULL 指针。如果不是 NULL,则沿路径的边 ID 存储在此处。

:

源顶点的 ID。

:

目标顶点的 ID。

weights:

可选边权重。为非加权图提供 NULL。所有边权重必须为非负数。此外,没有边权重可以是 NaN。如果任一情况不成立,则返回错误。具有正无穷权重的边将被忽略。

模式:

一个常量,指定在有向图中如何考虑边的方向。IGRAPH_OUT 遵循边的方向,IGRAPH_IN 遵循相反的方向,IGRAPH_ALL 忽略边的方向。此参数在无向图中将被忽略。

heuristic:

提供到目标顶点的距离估计的函数。有关更多信息,请参见 igraph_astar_heuristic_func_t

extra:

此参数传递给启发式函数。

返回值: 

错误代码。

时间复杂度:在最坏情况下,O(|E|log|V|+|V|),其中 |V| 是图中的顶点数,|E| 是边数。运行时间取决于启发式函数返回的距离估计的准确性。假设启发式是可接受的,估计越好,运行时间越短。

3.15. igraph_astar_heuristic_func_t — A* 算法的距离估计器。

typedef igraph_error_t igraph_astar_heuristic_func_t(
            igraph_real_t *result,
            igraph_integer_t from, igraph_integer_t to,
            void *extra);

igraph_get_shortest_path_astar() 使用基于到目标顶点的距离估计的启发式来指导其搜索,并确定接下来尝试哪个顶点。启发式函数应计算 fromto 之间的距离估计。为了使 igraph_get_shortest_path_astar() 找到精确的最短路径,距离不得被高估,即启发式函数必须是可采纳的

参数: 

result:

启发式的结果,即估计距离。较低的值将意味着此顶点将是探索的更好候选者。

:

候选顶点的顶点 ID 将在此处传递。

:

路径终点的顶点 ID,即传递给 igraph_get_shortest_path_astar()to 参数将在此处传递。

extra:

传递给 igraph_get_shortest_path_astar()extra 参数。

返回值: 

错误代码。如果没有错误,则必须返回 IGRAPH_SUCCESS。如果发生意外情况,例如内存分配失败 (IGRAPH_ENOMEM),则可以使用它来中断算法。

另请参阅: 

3.16. igraph_get_all_shortest_paths — 从顶点出发的所有最短路径(测地线)。

igraph_error_t igraph_get_all_shortest_paths(const igraph_t *graph,
                                  igraph_vector_int_list_t *vertices,
                                  igraph_vector_int_list_t *edges,
                                  igraph_vector_int_t *nrgeo,
                                  igraph_integer_t from, const igraph_vs_t to,
                                  igraph_neimode_t mode);

当两个顶点之间存在多条最短路径时,将返回所有路径。每条边都单独考虑,因此在具有多条边的图中,此函数可能会产生大量结果。

参数: 

:

图对象。

vertices:

结果,沿路径的顶点的 ID。这是整数向量的列表,其中每个元素都是一个 igraph_vector_int_t 对象。每个向量对象包含从 from 到另一个顶点的最短路径上的顶点。向量根据其目标顶点排序:首先是到顶点 0 的最短路径,然后是到顶点 1 的最短路径,依此类推。不包括不可达顶点的数据。列表将根据需要调整大小。如果不需要这些向量,请在此处提供一个空指针。

:

结果,沿路径的边的 ID。这是整数向量的列表,其中每个元素都是一个 igraph_vector_int_t 对象。每个向量对象包含从 from 到另一个顶点的最短路径上的边。向量根据其目标顶点排序:首先是到顶点 0 的最短路径,然后是到顶点 1 的最短路径,依此类推。不包括不可达顶点的数据。列表将根据需要调整大小。如果不需要这些向量,请在此处提供一个空指针。

nrgeo:

指向初始化 igraph_vector_int_t 对象的指针或 NULL。如果不是 NULL,则从 from 出发的最短路径数将存储在此处,用于图中的每个顶点。请注意,这些值仅对目标顶点序列中的那些顶点准确(请参见 to),因为一旦找到所有目标顶点,搜索就会终止。

:

从中/向其计算测地线的顶点的 ID。

:

顶点序列,其中包含从中/向其计算最短路径的顶点的 ID。 一个顶点可能会被多次给出。

模式:

用于计算有向图中最短路径的类型。 可能的值

IGRAPH_OUT

计算传出路径的长度。

IGRAPH_IN

计算传入路径的长度。

IGRAPH_ALL

在计算时,有向图被视为无向图。

返回值: 

错误代码

IGRAPH_ENOMEM

临时数据没有足够的内存。

IGRAPH_EINVVID

from 是无效的顶点 ID。

IGRAPH_EINVMODE

无效的模式参数。

在 0.2 版本中添加。

时间复杂度:对于大多数图为 O(|V|+|E|),在最坏情况下为 O(|V|^2)。

3.17. igraph_get_all_shortest_paths_dijkstra — 从顶点出发的所有加权最短路径(测地线)。

igraph_error_t igraph_get_all_shortest_paths_dijkstra(const igraph_t *graph,
        igraph_vector_int_list_t *vertices,
        igraph_vector_int_list_t *edges,
        igraph_vector_int_t *nrgeo,
        igraph_integer_t from, igraph_vs_t to,
        const igraph_vector_t *weights,
        igraph_neimode_t mode);

参数: 

:

图对象。

vertices:

指向初始化整数向量列表的指针或 NULL。如果不是 NULL,则每个向量对象都包含从 from 到另一个顶点的最短路径上的顶点。向量根据其目标顶点排序:首先是到顶点 0 的最短路径,然后是到顶点 1 的最短路径,依此类推。不包括不可达顶点的数据。

:

指向初始化整数向量列表的指针或 NULL。如果不是 NULL,则每个向量对象都包含从 from 到另一个顶点的最短路径上的边。向量根据其目标顶点排序:首先是到顶点 0 的最短路径,然后是到顶点 1 的最短路径,依此类推。不包括不可达顶点的数据。

nrgeo:

指向初始化 igraph_vector_int_t 对象的指针或 NULL。如果不是 NULL,则从 from 出发的最短路径数将存储在此处,用于图中的每个顶点。请注意,这些值仅对目标顶点序列中的那些顶点准确(请参见 to),因为一旦找到所有目标顶点,搜索就会终止。

:

从中/向其计算测地线的顶点的 ID。

:

顶点序列,其中包含从中/向其计算最短路径的顶点的 ID。 一个顶点可能会被多次给出。

weights:

边的权重。对于 Dijkstra 算法,所有边权重必须为非负数。此外,没有边权重可以是 NaN。如果任一情况不成立,则返回错误。如果这是一个空指针,则调用非加权版本 igraph_get_all_shortest_paths()

模式:

用于计算有向图中最短路径的类型。 可能的值

IGRAPH_OUT

计算传出路径。

IGRAPH_IN

计算传入路径。

IGRAPH_ALL

在计算时,有向图被视为无向图。

返回值: 

错误代码

IGRAPH_ENOMEM

临时数据没有足够的内存。

IGRAPH_EINVVID

from 是无效的顶点 ID

IGRAPH_EINVMODE

无效的模式参数。

时间复杂度:O(|E|log|V|+|V|),其中 |V| 是顶点数,|E| 是边的数量

另请参阅: 

如果只需要路径长度而不是路径本身,请使用 igraph_distances_dijkstra();如果所有边权重相等,请使用 igraph_get_all_shortest_paths()

示例 13.8.  文件 examples/simple/igraph_get_all_shortest_paths_dijkstra.c

#include <igraph.h>
#include <stdlib.h>

void print_and_destroy_items(igraph_vector_int_list_t* vec) {
    igraph_integer_t i;

    /* Sort the paths in a deterministic manner to avoid problems with
     * different qsort() implementations on different platforms */
    igraph_vector_int_list_sort(vec, igraph_vector_int_colex_cmp);
    for (i = 0; i < igraph_vector_int_list_size(vec); i++) {
        igraph_vector_int_print(igraph_vector_int_list_get_ptr(vec, i));
    }

    igraph_vector_int_list_destroy(vec);
}

int main(void) {

    igraph_t g;
    igraph_vector_int_list_t vertices, edges;

    igraph_real_t weights[] = { 0, 2, 1, 0, 5, 2, 1, 1, 0, 2, 2, 8, 1, 1, 3, 1, 1, 4, 2, 1 };

    igraph_vector_t weights_vec;
    igraph_vector_int_t nrgeo;
    igraph_vs_t vs;

    igraph_vector_int_list_init(&vertices, 0);
    igraph_vector_int_list_init(&edges, 0);
    igraph_vs_vector_small(&vs, 1, 3, 4, 5, 2, 1, -1);
    igraph_vector_int_init(&nrgeo, 0);
    igraph_small(&g, 10, IGRAPH_DIRECTED,
                 0, 1, 0, 2, 0, 3,   1, 2, 1, 4, 1, 5,
                 2, 3, 2, 6,         3, 2, 3, 6,
                 4, 5, 4, 7,         5, 6, 5, 8, 5, 9,
                 7, 5, 7, 8,         8, 9,
                 5, 2,
                 2, 1,
                 -1);

    igraph_vector_view(&weights_vec, weights, sizeof(weights) / sizeof(weights[0]));
    igraph_get_all_shortest_paths_dijkstra(
                &g,
                /*vertices=*/ &vertices, /*edges=*/ &edges, /*nrgeo=*/ &nrgeo,
                /*from=*/ 0, /*to=*/ vs,
                /*weights=*/ &weights_vec, /*mode=*/ IGRAPH_OUT);

    printf("Vertices:\n");
    print_and_destroy_items(&vertices);
    printf("\nEdges:\n");
    print_and_destroy_items(&edges);
    printf("\nNumber of geodesics:\n");
    igraph_vector_int_print(&nrgeo);

    igraph_vector_int_destroy(&nrgeo);
    igraph_vs_destroy(&vs);
    igraph_destroy(&g);

    return 0;
}


3.18. igraph_get_k_shortest_paths — 两个顶点之间的 k 条最短路径。

igraph_error_t igraph_get_k_shortest_paths(
    const igraph_t *graph, const igraph_vector_t *weights,
    igraph_vector_int_list_t *vertex_paths,
    igraph_vector_int_list_t *edge_paths,
    igraph_integer_t k, igraph_integer_t from, igraph_integer_t to,
    igraph_neimode_t mode
);

此函数按长度递增的顺序返回两个顶点之间的 k 条最短路径。

参考

Yen, Jin Y.: An algorithm for finding shortest routes from all source nodes to a given destination in general networks. Quarterly of Applied Mathematics. 27 (4): 526–530. (1970) https://doi.org/10.1090/qam/253822

参数: 

:

图对象。

weights:

图的边权重。对于非加权图,可以为 NULL。无穷权重将被视为缺失的边。

vertex_paths:

指向整数向量的初始化列表的指针,结果将存储在此处的 igraph_vector_int_t 对象中。每个向量对象包含 fromto 之间的第 k 条最短路径上的顶点 ID,其中 k 是向量列表索引。如果不需要顶点路径,则可以为 NULL

edge_paths:

指向整数向量的初始化列表的指针,结果将存储在此处的 igraph_vector_int_t 对象中。每个向量对象包含 fromto 之间的第 k 条最短路径上的边 ID,其中 k 是向量列表索引。如果不需要边路径,则可以为 NULL

k:

路径数。

:

从中计算路径的顶点的 ID。

:

计算路径所指向的顶点的 ID。

模式:

用于计算有向图中的路径的类型。可能的值

IGRAPH_OUT

计算 from 的传出路径。

IGRAPH_IN

计算 from 的传入路径。

IGRAPH_ALL

对于计算,有向图被视为无向图。

返回值: 

错误代码

IGRAPH_ENOMEM

临时数据内存不足。

IGRAPH_EINVVID

fromto 是无效的顶点 id。

IGRAPH_EINVMODE

无效的模式参数。

IGRAPH_EINVAL

无效的参数。

时间复杂度:k |V| (|V| log|V| + |E|),其中 |V| 是顶点数,|E| 是边数。

另请参阅: 

3.19. igraph_get_all_simple_paths — 列出从一个源出发的所有简单路径。

igraph_error_t igraph_get_all_simple_paths(const igraph_t *graph,
                                igraph_vector_int_t *res,
                                igraph_integer_t from,
                                const igraph_vs_t to,
                                igraph_integer_t cutoff,
                                igraph_neimode_t mode);

如果路径的顶点是唯一的,则该路径是简单的,即没有顶点被访问多次。

请注意,两个图的顶点之间可能存在指数级的路径,并且当图有多个周期时,您可能会在使用此函数时耗尽内存。当您不需要长路径时,请考虑使用 cutoff 参数。

参数: 

:

输入图。

res:

初始化整数向量。路径在此处以顶点的形式返回,由 -1 标记分隔。路径以任意顺序包含在内,因为它们被发现。

:

起始顶点。

:

目标顶点。

cutoff:

考虑的路径的最大长度。如果为负,则考虑所有长度的路径。

模式:

要考虑的路径的类型,它在无向图中被忽略。

返回值: 

错误代码。

另请参阅: 

时间复杂度:最坏情况下为 O(n!),n 是顶点数。

3.20. igraph_average_path_length — 所有顶点对之间的平均非加权最短路径长度。

igraph_error_t igraph_average_path_length(const igraph_t *graph,
                               igraph_real_t *res, igraph_real_t *unconn_pairs,
                               igraph_bool_t directed, igraph_bool_t unconn);

如果没有顶点对可以包含在计算中,例如因为图的顶点少于两个,或者如果图没有边并且 unconn 设置为 true,则返回 NaN。

参数: 

:

图对象。

res:

指向实数的指针,这将包含结果。

unconn_pairs:

指向实数的指针。如果不是空指针,则将在此处存储第二个顶点从第一个顶点不可到达的有序顶点对的数量。

有向:

布尔值,是否考虑有向路径。在无向图中被忽略。

unconn:

如果图未连接,该怎么做。如果 true,则只有那些顶点对之间存在路径的顶点对才会包含在计算中。如果 false,则为断开连接的图返回 IGRAPH_INFINITY

返回值: 

错误代码:IGRAPH_ENOMEM,数据结构内存不足

时间复杂度:O(|V| |E|),顶点数乘以边数。

另请参阅: 

加权版本请参考 igraph_average_path_length_dijkstra()

示例 13.9.  文件 examples/simple/igraph_average_path_length.c

#include <igraph.h>

int main(void) {
    igraph_t graph;
    igraph_real_t result;

    /* Create a random preferential attachment graph. */
    igraph_barabasi_game(&graph, 30, /*power=*/ 1, 30, 0, 0, /*A=*/ 1,
                         IGRAPH_DIRECTED, IGRAPH_BARABASI_BAG,
                         /*start_from=*/ 0);

    /* Compute the average shortest path length. */
    igraph_average_path_length(&graph, &result, NULL, IGRAPH_UNDIRECTED, 1);
    printf("Average length of all-pairs shortest paths: %g\n", result);

    /* Destroy no-longer-needed objects. */
    igraph_destroy(&graph);

    return 0;
}


3.21. igraph_average_path_length_dijkstra — 所有顶点对之间的平均加权最短路径长度。

igraph_error_t igraph_average_path_length_dijkstra(const igraph_t *graph,
                                        igraph_real_t *res, igraph_real_t *unconn_pairs,
                                        const igraph_vector_t *weights,
                                        igraph_bool_t directed, igraph_bool_t unconn);

如果没有顶点对可以包含在计算中,例如因为图的顶点少于两个,或者如果图没有边并且 unconn 设置为 true,则返回 NaN。

将考虑所有不同的有序顶点对。

参数: 

:

图对象。

res:

指向实数的指针,这将包含结果。

unconn_pairs:

指向实数的指针。如果不是空指针,则将在此处存储第二个顶点从第一个顶点不可到达的有序顶点对的数量。

weights:

边的权重。对于 Dijkstra 算法,所有边权重必须为非负数。此外,没有边权重可以是 NaN。如果任一情况不成立,则返回错误。如果这是一个空指针,则调用非加权版本 igraph_average_path_length()。具有正无穷权重的边将被忽略。

有向:

布尔值,是否考虑有向路径。在无向图中被忽略。

unconn:

如果 true,则只考虑那些顶点对之间存在路径的顶点对进行计算。如果 false,则为断开连接的图返回 IGRAPH_INFINITY

返回值: 

错误代码

IGRAPH_ENOMEM

数据结构内存不足

IGRAPH_EINVAL

无效的权重向量

时间复杂度:O(|V| |E| log|E| + |V|),其中 |V| 是顶点数,|E| 是边数。

另请参阅: 

非加权版本请参考稍快的 igraph_average_path_length()

示例 13.10.  文件 examples/simple/igraph_grg_game.c

#include <igraph.h>
#include <math.h>

int main(void) {
    igraph_t graph;
    igraph_vector_t x, y;
    igraph_vector_t weights;
    igraph_eit_t eit;
    igraph_real_t avg_dist;

    /* Set random seed for reproducible results */

    igraph_rng_seed(igraph_rng_default(), 42);

    /* Create a random geometric graph and retrieve vertex coordinates */

    igraph_vector_init(&x, 0);
    igraph_vector_init(&y, 0);

    igraph_grg_game(&graph, 200, 0.1, /* torus */ 0, &x, &y);

    /* Compute edge weights as geometric distance */

    igraph_vector_init(&weights, igraph_ecount(&graph));
    igraph_eit_create(&graph, igraph_ess_all(IGRAPH_EDGEORDER_ID), &eit);
    for (; ! IGRAPH_EIT_END(eit); IGRAPH_EIT_NEXT(eit)) {
        igraph_integer_t e = IGRAPH_EIT_GET(eit);
        igraph_integer_t u = IGRAPH_FROM(&graph, e);
        igraph_integer_t v = IGRAPH_TO(&graph, e);

        VECTOR(weights)[e] = hypot(VECTOR(x)[u] - VECTOR(x)[v], VECTOR(y)[u] - VECTOR(y)[v]);
    }
    igraph_eit_destroy(&eit);

    /* Compute average path length */

    igraph_average_path_length_dijkstra(&graph, &avg_dist, NULL, &weights, IGRAPH_UNDIRECTED, /* unconn */ 1);

    printf("Average distance in the geometric graph: %g.\n", avg_dist);

    /* Destroy data structures when no longer needed */

    igraph_vector_destroy(&weights);
    igraph_destroy(&graph);
    igraph_vector_destroy(&x);
    igraph_vector_destroy(&y);

    return 0;
}


3.22. igraph_path_length_hist — 创建所有最短路径长度的直方图。

igraph_error_t igraph_path_length_hist(const igraph_t *graph, igraph_vector_t *res,
                            igraph_real_t *unconnected, igraph_bool_t directed);

此函数通过计算所有顶点对之间的最短路径长度来计算直方图。在有向图中,两个方向都被考虑,这意味着每个顶点对在直方图中出现两次。

参数: 

:

输入图。

res:

指向初始化向量的指针,结果存储在此处。第一个(即索引 0)元素包含长度为 1 的最短路径数,第二个包含长度为 2 的最短路径数,依此类推。提供的向量将根据需要调整大小。

unconnected:

指向实数的指针,第二个顶点无法从第一个顶点到达的顶点对数存储在此处。

有向:

是否考虑有向图中的有向路径。此参数在无向图中被忽略。

返回值: 

错误代码。

时间复杂度:O(|V||E|),顶点数乘以边数。

另请参阅: 

3.23. igraph_diameter — 计算图的直径(最长测地线)。

igraph_error_t igraph_diameter(const igraph_t *graph, igraph_real_t *res,
                    igraph_integer_t *from, igraph_integer_t *to,
                    igraph_vector_int_t *vertex_path, igraph_vector_int_t *edge_path,
                    igraph_bool_t directed, igraph_bool_t unconn);

图的直径是其具有的最长最短路径的长度,即图顶点的最大偏心率。此函数计算直径以及相应的路径。按照惯例,空图的直径被认为是无穷大。如果图没有顶点,则返回 IGRAPH_NAN

参数: 

:

图对象。

res:

指向实数的指针,如果不是 NULL,则它将包含直径(实际距离)。

:

指向整数的指针,如果不是 NULL,则将设置为直径路径的源顶点。如果图没有直径路径,则将其设置为 -1。

:

指向整数的指针,如果不是 NULL,则将设置为直径路径的目标顶点。如果图没有直径路径,则将其设置为 -1。

vertex_path:

指向初始化向量的指针。如果不是 NULL,则以顶点的形式存储实际的最长测地线路径。向量将根据需要调整大小。

edge_path:

指向初始化向量的指针。如果不是 NULL,则以边的形式存储实际的最长测地线路径。向量将根据需要调整大小。

有向:

布尔值,是否考虑有向路径。在无向图中被忽略。

unconn:

如果图未连接,该怎么做。如果 true,则将返回组件中最长的测地线,否则返回 IGRAPH_INFINITY

返回值: 

错误代码:IGRAPH_ENOMEM,临时数据内存不足。

时间复杂度:O(|V||E|),顶点数乘以边数。

另请参阅: 

加权版本请参考 igraph_diameter_dijkstra(),最小偏心率请参考 igraph_radius()

示例 13.11.  文件 examples/simple/igraph_diameter.c

#include <igraph.h>

void print_vector_int(igraph_vector_int_t *v) {
    igraph_integer_t i, n = igraph_vector_int_size(v);
    for (i = 0; i < n; i++) {
        printf(" %" IGRAPH_PRId, VECTOR(*v)[i]);
    }
    printf("\n");
}

int main(void) {

    igraph_t g;
    igraph_real_t result;
    igraph_integer_t from, to;
    igraph_vector_int_t path, path_edge;

    igraph_barabasi_game(&g, 30, /*power=*/ 1, 30, 0, 0, /*A=*/ 1,
                         IGRAPH_DIRECTED, IGRAPH_BARABASI_BAG,
                         /*start_from=*/ 0);
    igraph_diameter(&g, &result, 0, 0, 0, 0, IGRAPH_UNDIRECTED, 1);

    /*   printf("Diameter: %" IGRAPH_PRId "\n", (igraph_integer_t) result); */

    igraph_destroy(&g);

    igraph_ring(&g, 10, IGRAPH_DIRECTED, 0, 0);
    igraph_vector_int_init(&path, 0);
    igraph_vector_int_init(&path_edge, 0);
    igraph_diameter(&g, &result, &from, &to, &path, &path_edge, IGRAPH_DIRECTED, 1);
    printf(
        "diameter: %" IGRAPH_PRId ", from %" IGRAPH_PRId " to %" IGRAPH_PRId "\n",
        (igraph_integer_t) result, from, to
    );
    print_vector_int(&path);
    print_vector_int(&path_edge);

    igraph_vector_int_destroy(&path);
    igraph_vector_int_destroy(&path_edge);
    igraph_destroy(&g);

    return 0;
}


3.24. igraph_diameter_dijkstra — 使用 Dijkstra 算法计算图的加权直径。

igraph_error_t igraph_diameter_dijkstra(const igraph_t *graph,
                             const igraph_vector_t *weights,
                             igraph_real_t *res,
                             igraph_integer_t *from,
                             igraph_integer_t *to,
                             igraph_vector_int_t *vertex_path,
                             igraph_vector_int_t *edge_path,
                             igraph_bool_t directed,
                             igraph_bool_t unconn);

此函数计算图的加权直径,定义为最长的加权最短路径,或图顶点的最大加权偏心率。也可以选择计算相应的最短路径及其端点。

如果图没有顶点,则返回 IGRAPH_NAN

参数: 

:

输入图,可以是定向图或无向图。

weights:

图的边权重。对于非加权图,可以为 NULL。具有正无穷权重的边将被忽略。

res:

指向实数的指针,如果不是 NULL,则它将包含直径(实际距离)。

:

指向整数的指针,如果不是 NULL,则将设置为直径路径的源顶点。如果图没有直径路径,则将其设置为 -1。

:

指向整数的指针,如果不是 NULL,则将设置为直径路径的目标顶点。如果图没有直径路径,则将其设置为 -1。

vertex_path:

指向初始化向量的指针。如果不是 NULL,则以顶点的形式存储实际的最长测地线路径。向量将根据需要调整大小。

edge_path:

指向初始化向量的指针。如果不是 NULL,则以边的形式存储实际的最长测地线路径。向量将根据需要调整大小。

有向:

布尔值,是否考虑有向路径。在无向图中被忽略。

unconn:

如果图未连接,该怎么做。如果 true,则将返回组件中最长的测地线,否则返回 IGRAPH_INFINITY

返回值: 

错误代码。

时间复杂度:O(|V||E|*log|E|),|V| 是顶点数,|E| 是边数。

另请参阅: 

非加权版本请参考 igraph_diameter(),最小加权偏心率请参考 igraph_radius_dijkstra()

3.25. igraph_girth — 图的围长是其中最短周期的长度。

igraph_error_t igraph_girth(const igraph_t *graph, igraph_real_t *girth,
                 igraph_vector_int_t *circle);

当前的实现仅适用于无向图,有向图被视为无向图。自环和多重边将被忽略,即不考虑长度为 1 或 2 的周期。

对于不包含周期的图,并且仅对于此类图,将返回无穷大。

此函数的第一个实现由 Keith Briggs 完成,感谢 Keith。

参考

Alon Itai 和 Michael Rodeh:Finding a minimum circuit in a graph Proceedings of the ninth annual ACM symposium on Theory of computing , 1-10, 1977. https://doi.org/10.1145/800105.803390

参数: 

:

输入图。边的方向将被忽略。

girth:

指向 igraph_real_t 的指针,如果不是 NULL,则结果将存储在此处。

circle:

指向初始化向量的指针,最短周期中的顶点 ID 将存储在此处。如果 NULL,则将其忽略。

返回值: 

错误代码。

时间复杂度:O((|V|+|E|)^2),|V| 是顶点数,|E| 是通用情况下的边数。如果图根本没有周期,则该函数需要 O(|V|+|E|) 时间来实现此目的,然后停止。

示例 13.12.  文件 examples/simple/igraph_girth.c

#include <igraph.h>

int main(void) {
    igraph_t g;
    igraph_real_t girth;
    igraph_vector_int_t v;
    igraph_vector_int_t circle;
    igraph_integer_t chord[] = { 0, 50 };

    igraph_ring(&g, 100, IGRAPH_UNDIRECTED, 0, 1);
    igraph_vector_int_view(&v, chord, sizeof(chord) / sizeof(chord[0]));
    igraph_add_edges(&g, &v, 0);
    igraph_girth(&g, &girth, 0);
    if (girth != 51) {
        return 1;
    }

    igraph_destroy(&g);

    /* Special case: null graph */
    igraph_ring(&g, 0, IGRAPH_UNDIRECTED, 0, 1);
    igraph_vector_int_init(&circle, 1);
    VECTOR(circle)[0] = 2;
    igraph_girth(&g, &girth, &circle);
    if (girth != IGRAPH_INFINITY) {
        return 2;
    }
    if (igraph_vector_int_size(&circle) != 0) {
        return 3;
    }
    igraph_vector_int_destroy(&circle);
    igraph_destroy(&g);

    return 0;
}


3.26. igraph_eccentricity — 某些顶点的偏心率。

igraph_error_t igraph_eccentricity(const igraph_t *graph,
                        igraph_vector_t *res,
                        igraph_vs_t vids,
                        igraph_neimode_t mode);

通过测量从(或到)顶点到(或来自)图中所有顶点的最短距离并取最大值来计算顶点的偏心率。

此实现忽略了不同组件中的顶点对。孤立顶点的偏心率为零。

参数: 

:

输入图,可以是定向的或非定向的。

res:

指向初始化向量的指针,结果存储在此处。

vids:

为其计算偏心率的顶点。

模式:

要考虑用于计算的路径类型:IGRAPH_OUT,遵循边方向的路径;IGRAPH_IN,遵循相反方向的路径;和 IGRAPH_ALL,忽略边方向的路径。此参数在无向图中被忽略。

返回值: 

错误代码。

时间复杂度:O(|S| (|V|+|E|)),其中 |V| 是顶点数,|E| 是边数,|S| 是为其计算偏心率的顶点数。

另请参阅: 

示例 13.13.  文件 examples/simple/igraph_eccentricity.c

#include <igraph.h>

int main(void) {

    igraph_t g;
    igraph_vector_t ecc;

    igraph_vector_init(&ecc, 0);

    igraph_star(&g, 10, IGRAPH_STAR_UNDIRECTED, 0);
    igraph_eccentricity(&g, &ecc, igraph_vss_all(), IGRAPH_OUT);
    igraph_vector_print(&ecc);
    igraph_destroy(&g);

    igraph_star(&g, 10, IGRAPH_STAR_OUT, 0);
    igraph_eccentricity(&g, &ecc, igraph_vss_all(), IGRAPH_ALL);
    igraph_vector_print(&ecc);
    igraph_destroy(&g);

    igraph_star(&g, 10, IGRAPH_STAR_OUT, 0);
    igraph_eccentricity(&g, &ecc, igraph_vss_all(), IGRAPH_OUT);
    igraph_vector_print(&ecc);
    igraph_destroy(&g);

    igraph_vector_destroy(&ecc);

    return 0;
}


3.27. igraph_eccentricity_dijkstra — 某些顶点的偏心率,使用加权边。

igraph_error_t igraph_eccentricity_dijkstra(const igraph_t *graph,
                        const igraph_vector_t *weights,
                        igraph_vector_t *res,
                        igraph_vs_t vids,
                        igraph_neimode_t mode);

通过测量从(或到)顶点到(或来自)图中所有顶点的最短距离并取最大值来计算顶点的偏心率。

此实现忽略了不同组件中的顶点对。孤立顶点的偏心率为零。

参数: 

:

输入图,可以是定向的或非定向的。

weights:

边的权重。对于 Dijkstra 算法,所有边权重必须为非负数。此外,没有边权重可以是 NaN。如果任一情况不成立,则返回错误。如果这是一个空指针,则调用非加权版本 igraph_eccentricity()。具有正无穷权重的边将被忽略。

res:

指向初始化向量的指针,结果存储在此处。

vids:

为其计算偏心率的顶点。

模式:

要考虑用于计算的路径类型:IGRAPH_OUT,遵循边方向的路径;IGRAPH_IN,遵循相反方向的路径;和 IGRAPH_ALL,忽略边方向的路径。此参数在无向图中被忽略。

返回值: 

错误代码。

时间复杂度:O(|V| |E| log|V| + |V|),其中 |V| 是顶点数,|E| 是边数。

3.28. igraph_radius — 图的半径。

igraph_error_t igraph_radius(const igraph_t *graph, igraph_real_t *radius,
                             igraph_neimode_t mode);

图的半径定义为其顶点的最小偏心率,参见 igraph_eccentricity()

参数: 

:

输入图,可以是定向的或非定向的。

radius:

指向实变量的指针,结果存储在此处。

模式:

要考虑用于计算的路径类型:IGRAPH_OUT,遵循边方向的路径;IGRAPH_IN,遵循相反方向的路径;和 IGRAPH_ALL,忽略边方向的路径。此参数在无向图中被忽略。

返回值: 

错误代码。

时间复杂度:O(|V|(|V|+|E|)),其中 |V| 是顶点数,|E| 是边数。

另请参阅: 

加权版本请参考 igraph_radius_dijkstra(),最大偏心率请参考 igraph_diameter(),所有顶点的偏心率请参考 igraph_eccentricity()

示例 13.14.  文件 examples/simple/igraph_radius.c

#include <igraph.h>

int main(void) {

    igraph_t g;
    igraph_real_t radius;

    igraph_star(&g, 10, IGRAPH_STAR_UNDIRECTED, 0);
    igraph_radius(&g, &radius, IGRAPH_OUT);
    if (radius != 1) {
        return 1;
    }
    igraph_destroy(&g);

    igraph_star(&g, 10, IGRAPH_STAR_OUT, 0);
    igraph_radius(&g, &radius, IGRAPH_ALL);
    if (radius != 1) {
        return 2;
    }
    igraph_destroy(&g);

    igraph_star(&g, 10, IGRAPH_STAR_OUT, 0);
    igraph_radius(&g, &radius, IGRAPH_OUT);
    if (radius != 0) {
        return 3;
    }
    igraph_destroy(&g);

    return 0;
}


3.29. igraph_radius_dijkstra — 图的半径,使用加权边。

igraph_error_t igraph_radius_dijkstra(const igraph_t *graph, const igraph_vector_t *weights,
                                      igraph_real_t *radius, igraph_neimode_t mode);

警告

此函数是实验性的,其签名尚未被视为最终签名。我们保留更改函数签名的权利,而无需更改 igraph 的主要版本。使用它需要您自担风险。

图的半径定义为其顶点的最小偏心率,参见 igraph_eccentricity()

参数: 

:

输入图,可以是定向的或非定向的。

weights:

边的权重。对于 Dijkstra 算法,所有边权重必须为非负数。此外,没有边权重可以是 NaN。如果任一情况不成立,则返回错误。如果这是一个空指针,则调用非加权版本 igraph_radius()。具有正无穷权重的边将被忽略。

radius:

指向实变量的指针,结果存储在此处。

模式:

要考虑用于计算的路径类型:IGRAPH_OUT,遵循边方向的路径;IGRAPH_IN,遵循相反方向的路径;和 IGRAPH_ALL,忽略边方向的路径。此参数在无向图中被忽略。

返回值: 

错误代码。

时间复杂度:O(|V| |E| log|V| + |V|),其中 |V| 是顶点数,|E| 是边数。

另请参阅: 

非加权版本请参考 igraph_radius(),最大加权偏心率请参考 igraph_diameter_dijkstra(),所有顶点的加权偏心率请参考 igraph_eccentricity_dijkstra()

3.30. igraph_graph_center — 图的中心顶点。

igraph_error_t igraph_graph_center(
    const igraph_t *graph, igraph_vector_int_t *res, igraph_neimode_t mode
);

通过找到具有最小偏心率的顶点来计算图的中心顶点。此概念通常应用于(强)连接图。在断开连接的图中,最小偏心率取自所有组件。

参数: 

:

输入图,可以是定向的或非定向的。

res:

指向初始化向量的指针,结果存储在此处。

模式:

要考虑用于计算的路径类型:IGRAPH_OUT,遵循边方向的路径;IGRAPH_IN,遵循相反方向的路径;和 IGRAPH_ALL,忽略边方向的路径。此参数在无向图中被忽略。

返回值: 

错误代码。

时间复杂度:O(|V| (|V|+|E|)),其中 |V| 是顶点数,|E| 是边数。

另请参阅: 

3.31. igraph_graph_center_dijkstra — 图的中心顶点,使用加权边。

igraph_error_t igraph_graph_center_dijkstra(
    const igraph_t *graph, const igraph_vector_t *weights, igraph_vector_int_t *res, igraph_neimode_t mode
);

警告

此函数是实验性的,其签名尚未被视为最终签名。我们保留更改函数签名的权利,而无需更改 igraph 的主要版本。使用它需要您自担风险。

通过找到具有最小偏心率的顶点来计算图的中心顶点。此函数考虑了边权重,并使用 Dijkstra 算法进行最短路径计算。图中心的概念通常应用于(强)连接图。在断开连接的图中,最小偏心率取自所有组件。

参数: 

:

输入图,可以是定向的或非定向的。

weights:

边的权重。对于 Dijkstra 算法,所有边权重必须为非负数。此外,没有边权重可以是 NaN。如果任一情况不成立,则返回错误。如果这是一个空指针,则调用非加权版本 igraph_graph_center()。具有正无穷权重的边将被忽略。

res:

指向初始化向量的指针,结果存储在此处。

模式:

要考虑用于计算的路径类型:IGRAPH_OUT,遵循边方向的路径;IGRAPH_IN,遵循相反方向的路径;和 IGRAPH_ALL,忽略边方向的路径。此参数在无向图中被忽略。

返回值: 

错误代码。

时间复杂度:O(|V| |E| log|V| + |V|),其中 |V| 是顶点数,|E| 是边数。

另请参阅: 

3.32. igraph_pseudo_diameter — 直径的近似值和下限。

igraph_error_t igraph_pseudo_diameter(const igraph_t *graph,
                           igraph_real_t *diameter,
                           igraph_integer_t vid_start,
                           igraph_integer_t *from,
                           igraph_integer_t *to,
                           igraph_bool_t directed,
                           igraph_bool_t unconn);

此算法查找伪外围顶点并返回其偏心率。此值可以用作图的直径的近似值和下限。

伪周边顶点是指顶点 v,对于每个与 v 尽可能远的顶点 u,v 也与 u 尽可能远。找到伪周边顶点的过程取决于搜索的起点,对于非连通图,找到的最大直径将是 vid_start 所在的连通分量的直径。

参数: 

:

输入图,如果是定向图,则忽略其边的方向。

diameter:

指向实变量的指针,结果存储在此处。

vid_start:

起始顶点的 ID。如果为负数,则选择一个随机起始顶点。

:

指向整数的指针,如果不为 NULL,则它将被设置为直径路径的源顶点。如果 unconnfalse,并且检测到非连通图,则此值设置为 -1。

:

指向整数的指针,如果不为 NULL,则它将被设置为直径路径的目标顶点。如果 unconnfalse,并且检测到非连通图,则此值设置为 -1。

有向:

布尔值,是否考虑有向路径。在无向图中被忽略。

unconn:

如果图未连接,该怎么做。如果 true,则将返回组件中最长的测地线,否则返回 IGRAPH_INFINITY

返回值: 

错误代码。

时间复杂度:O(|V| |E|)),其中 |V| 是顶点数,|E| 是边数。

另请参阅: 

3.33. igraph_pseudo_diameter_dijkstra — 加权图直径的近似值和下限。

igraph_error_t igraph_pseudo_diameter_dijkstra(const igraph_t *graph,
                                    const igraph_vector_t *weights,
                                    igraph_real_t *diameter,
                                    igraph_integer_t vid_start,
                                    igraph_integer_t *from,
                                    igraph_integer_t *to,
                                    igraph_bool_t directed,
                                    igraph_bool_t unconn);

此算法找到一个伪周边顶点,并返回其加权离心率。此值可用作图直径的近似值和下限。

伪周边顶点是指顶点 v,对于每个与 v 尽可能远的顶点 u,v 也与 u 尽可能远。找到伪周边顶点的过程取决于搜索的起点,对于非连通图,找到的最大直径将是 vid_start 所在的连通分量的直径。

如果图没有顶点,则返回 IGRAPH_NAN

参数: 

:

输入图,可以是定向图或无向图。

weights:

图的边权重。对于未加权图,可以为 NULL。所有权重应为非负数。具有正无穷权重的边将被忽略。

diameter:

这将包含加权伪直径。

vid_start:

起始顶点的 ID。如果为负数,则选择一个随机起始顶点。

:

如果不为 NULL,则将被设置为直径路径的源顶点。如果该图没有直径路径,则它将被设置为 -1。

:

如果不为 NULL,则将被设置为直径路径的目标顶点。如果该图没有直径路径,则它将被设置为 -1。

有向:

布尔值,是否考虑有向路径。在无向图中被忽略。

unconn:

如果图未连接,该怎么做。如果 true,则将返回组件中最长的测地线,否则返回 IGRAPH_INFINITY

返回值: 

错误代码。

时间复杂度:O(|V| |E| log|E|),|V| 是顶点数,|E| 是边数。

另请参阅: 

3.34. igraph_voronoi — 图的 Voronoi 分区。

igraph_error_t igraph_voronoi(
        const igraph_t *graph,
        igraph_vector_int_t *membership,
        igraph_vector_t *distances,
        const igraph_vector_int_t *generators,
        const igraph_vector_t *weights,
        igraph_neimode_t mode,
        igraph_voronoi_tiebreaker_t tiebreaker);

警告

此函数是实验性的,其签名尚未被视为最终签名。我们保留更改函数签名的权利,而无需更改 igraph 的主要版本。使用它需要您自担风险。

要获得图的 Voronoi 分区,我们从一组生成器顶点开始,这些顶点将定义分区。每个顶点都被分配给它最接近的生成器顶点。

此函数使用 BFS 搜索来处理未加权图,并使用 Dijkstra 算法来处理加权图。

参数: 

:

要分区的图。

membership:

如果不为 NULL,则每个顶点的 Voronoi 分区将存储在此处。membership[v] 将设置为 generatorsv 所属的生成器顶点的索引。对于任何生成器都无法到达的顶点,将返回 -1

distances:

如果不为 NULL,则每个顶点到其各自生成器的距离将存储在此处。对于任何生成器都无法到达的顶点,将返回 IGRAPH_INFINITY

generators:

生成器顶点的顶点 ID。

weights:

边权重,被解释为最短路径计算中的长度。所有权重必须为非负数。

模式:

在定向图中,是否计算 生成器顶点到其他顶点的距离 (IGRAPH_OUT), 其他顶点到生成器顶点的距离 (IGRAPH_IN),或完全忽略边的方向 (IGRAPH_ALL)。

tiebreaker:

控制当顶点与多个生成器顶点距离/来自多个生成器顶点的距离相等时,将顶点分配给哪个生成器顶点。

IGRAPH_VORONOI_FIRST 将顶点分配给第一个生成器顶点。

IGRAPH_VORONOI_LAST 将顶点分配给最后一个生成器顶点。

IGRAPH_VORONOI_RANDOM 将顶点分配给一个随机生成器顶点。

请注意,IGRAPH_VORONOI_RANDOM 不保证所有分区都将是连续的。例如,如果 1 和 2 被选为图 1-3, 2-3, 3-4 的生成器,则 3 和 4 与两个生成器距离相等。如果 3 被分配给 2 但 4 被分配给 1,则分区 {1, 4} 将不会产生一个连通子图。

返回值: 

错误代码。

时间复杂度:在加权图中,O((log |S|) |E| (log |V|) + |V|),在未加权图中 O((log |S|) |E| + |V|),其中 |S| 是生成器顶点的数量,|V| 和 |E| 是图中顶点和边的数量。

另请参阅: 

3.35. igraph_vertex_path_from_edge_path — 将边的 ID 序列转换为遍历的顶点 ID。

igraph_error_t igraph_vertex_path_from_edge_path(
   const igraph_t *graph, igraph_integer_t start,
   const igraph_vector_int_t *edge_path, igraph_vector_int_t *vertex_path,
   igraph_neimode_t mode
);

当您有一个表示图中连续步行的边 ID 序列,并且想要获得该步行遍历的顶点 ID 时,此函数非常有用。多个最短路径相关函数隐式使用此函数,以将边 ID 路径转换为相应的表示形式,该表示形式以顶点 ID 描述路径。

结果将始终包含比提供的边数多一个顶点。如果没有给出边,则输出将仅包含起始顶点。

允许步行多次遍历同一个顶点。它适用于路径、循环或任意步行。

参数: 

:

边 ID 引用的图。

开始:

路径的起始顶点。如果为负数,则自动确定。只有当步行包含至少一条边时才有可能。如果无向步行中只存在一条边,则会任意选择其一个端点。

edge_path:

描述路径的边 ID 序列。

vertex_path:

此处将返回遍历的顶点 ID 序列。

返回值: 

错误代码:如果内存不足,则为 IGRAPH_ENOMEM;如果起始顶点无效,则为 IGRAPH_EINVVID;如果边步行未从给定的顶点开始,或者如果至少有一条边的起始顶点与前一条边的结束顶点不匹配,则为 IGRAPH_EINVAL

时间复杂度:O(n),其中 n 是步行的长度。

4. 最宽路径相关函数

4.1. igraph_get_widest_path — 从一个顶点到另一个顶点的最宽路径。

igraph_error_t igraph_get_widest_path(const igraph_t *graph,
                                      igraph_vector_int_t *vertices,
                                      igraph_vector_int_t *edges,
                                      igraph_integer_t from,
                                      igraph_integer_t to,
                                      const igraph_vector_t *weights,
                                      igraph_neimode_t mode);

使用 Dijkstra 算法计算从单个顶点到另一个顶点的单个最宽路径。

此函数是 igraph_get_widest_paths() 的特殊情况(和包装器)。

参数: 

:

输入图,可以是定向的或非定向的。

vertices:

指向初始化向量的指针或空指针。 如果不是空指针,则沿路径的顶点 ID 将存储在此处,包括源顶点和目标顶点。

:

指向初始化向量的指针或空指针。 如果不是空指针,则沿路径的边 ID 将存储在此处。

:

源顶点的 ID。

:

目标顶点的 ID。

weights:

边权重。边权重可以为负数。如果这是一个空指针,或者任何边权重为 NaN,则返回一个错误。具有正无穷权重的边将被忽略。

模式:

一个常量,指定在有向图中如何考虑边的方向。IGRAPH_OUT 遵循边的方向,IGRAPH_IN 遵循相反的方向,IGRAPH_ALL 忽略边的方向。此参数在无向图中将被忽略。

返回值: 

错误代码。

时间复杂度:O(|E|*|V|),|V| 是顶点数,|E| 是图中的边数。

另请参阅: 

igraph_get_widest_paths() 用于具有更多目标顶点的版本。

4.2. igraph_get_widest_paths — 从单个顶点出发的最宽路径。

igraph_error_t igraph_get_widest_paths(const igraph_t *graph,
                                       igraph_vector_int_list_t *vertices,
                                       igraph_vector_int_list_t *edges,
                                       igraph_integer_t from,
                                       igraph_vs_t to,
                                       const igraph_vector_t *weights,
                                       igraph_neimode_t mode,
                                       igraph_vector_int_t *parents,
                                       igraph_vector_int_t *inbound_edges);

使用改进的 Dijkstra 算法计算从单个节点到所有其他指定节点的最宽路径。如果两个顶点之间存在多条具有最大宽度的路径,则此函数仅给出其中一条。

参数: 

:

图对象。

vertices:

结果,沿路径的顶点 ID。 这是一个整数向量列表,其中每个元素都是一个 igraph_vector_int_t 对象。 将根据需要调整列表大小。 如果您不需要这些向量,请在此处提供空指针。

:

结果,沿路径的边 ID。 这是一个整数向量列表,其中每个元素都是一个 igraph_vector_int_t 对象。 将根据需要调整列表大小。 如果您不需要这些向量,请在此处提供空指针。

:

从/到计算最宽路径的顶点的 ID。

:

包含从/到计算最宽路径的顶点的 ID 的顶点序列。一个顶点可能会被多次给定。

weights:

边权重。边权重可以为负数。如果这是一个空指针,或者任何边权重为 NaN,则返回一个错误。具有正无穷权重的边将被忽略。

模式:

定向图中用于计算的最宽路径的类型。可能的值

IGRAPH_OUT

计算传出路径。

IGRAPH_IN

计算传入路径。

IGRAPH_ALL

在计算时,有向图被视为无向图。

parents:

指向已初始化的 igraph 向量或 null 的指针。如果不为 null,则将在此处返回一个向量,该向量包含单源最宽路径树中每个顶点的父顶点。树中顶点 i 的父顶点是顶点 i 到达的顶点。from 参数中起始顶点的父顶点为 -1。如果父顶点为 -2,则意味着在搜索过程中无法从源顶点到达给定的顶点。请注意,如果到达了 to 中的所有顶点,则搜索将终止。

inbound_edges:

指向已初始化的 igraph 向量或 null 的指针。如果不为 null,则将在此处返回一个向量,该向量包含单源最宽路径树中每个顶点的入边。树中顶点 i 的入边是顶点 i 到达的边。起始顶点和在搜索过程中未到达的顶点将在向量的相应条目中具有 -1。请注意,如果到达了 to 中的所有顶点,则搜索将终止。

返回值: 

错误代码

IGRAPH_ENOMEM

临时数据没有足够的内存。

IGRAPH_EINVVID

from 是无效的顶点 ID

IGRAPH_EINVMODE

无效的模式参数。

时间复杂度:O(|E|log|E|+|V|),其中 |V| 是图中的顶点数,|E| 是边数

另请参阅: 

如果您只需要路径的宽度而不是路径本身,则可以使用 igraph_widest_path_widths_dijkstra()igraph_widest_path_widths_floyd_warshall()

4.3. igraph_widest_path_widths_dijkstra — 顶点之间最宽路径的宽度。

igraph_error_t igraph_widest_path_widths_dijkstra(const igraph_t *graph,
                                   igraph_matrix_t *res,
                                   const igraph_vs_t from,
                                   const igraph_vs_t to,
                                   const igraph_vector_t *weights,
                                   igraph_neimode_t mode);

此函数实现了一种改进的 Dijkstra 算法,可以找到从源顶点到所有其他顶点的最宽路径宽度。此函数允许指定一组源顶点和目标顶点。该算法独立地为每个源运行,并且仅保留指定目标的结果。此实现使用二进制堆来提高效率。

参数: 

:

输入图,可以是有向的。

res:

结果,一个矩阵。应在此处传递指向已初始化矩阵的指针。矩阵将根据需要调整大小。每行包含从单个源到 to 参数中给出的顶点的宽度。无法到达的顶点具有宽度 IGRAPH_NEGINFINITY,顶点本身具有宽度 IGRAPH_POSINFINITY

:

源顶点。

:

目标顶点。 不允许将一个顶点多次包含在内。

weights:

边权重。边权重可以为负数。如果这是一个空指针,或者任何边权重为 NaN,则返回一个错误。具有正无穷权重的边将被忽略。

模式:

对于有向图; 是否沿边方向 (IGRAPH_OUT) 或相反方向 (IGRAPH_IN) 跟踪路径,或者完全忽略边方向 (IGRAPH_ALL)。 对于无向图,它将被忽略。

返回值: 

错误代码。

时间复杂度:O(s*(|E|log|E|+|V|)),其中 |V| 是图中的顶点数,|E| 是边数,s 是源的数量。

另请参阅: 

igraph_widest_path_widths_floyd_warshall() 适用于在密集图上运行速度更快的变体。

4.4. igraph_widest_path_widths_floyd_warshall — 顶点之间最宽路径的宽度。

igraph_error_t igraph_widest_path_widths_floyd_warshall(const igraph_t *graph,
                                   igraph_matrix_t *res,
                                   const igraph_vs_t from,
                                   const igraph_vs_t to,
                                   const igraph_vector_t *weights,
                                   igraph_neimode_t mode);

此函数实现了一种改进的 Floyd-Warshall 算法,用于查找一组源顶点和目标顶点之间最宽路径的宽度。它主要用于非常密集图中的所有顶点对路径宽度,因为其运行时间主要由顶点计数决定,并且对图密度不敏感。在稀疏图中,其他方法(例如 Dijkstra 算法)将表现更好。

请注意,此函数在内部始终计算所有顶点对的路径宽度矩阵。fromto 参数仅用于子集化此矩阵,但不影响计算所花费的时间。

参数: 

:

输入图,可以是有向的。

res:

结果,一个矩阵。应在此处传递指向已初始化矩阵的指针。矩阵将根据需要调整大小。每行包含从单个源到 to 参数中给出的顶点的宽度。无法到达的顶点具有宽度 IGRAPH_NEGINFINITY,顶点本身具有宽度 IGRAPH_POSINFINITY

:

源顶点。

:

目标顶点。

weights:

边权重。边权重可以为负数。如果这是一个空指针,或者任何边权重为 NaN,则返回一个错误。具有正无穷权重的边将被忽略。

模式:

对于有向图; 是否沿边方向 (IGRAPH_OUT) 或相反方向 (IGRAPH_IN) 跟踪路径,或者完全忽略边方向 (IGRAPH_ALL)。 对于无向图,它将被忽略。

返回值: 

错误代码。

时间复杂度:O(|V|^3),其中 |V| 是图中的顶点数。

另请参阅: 

igraph_widest_path_widths_dijkstra() 适用于在稀疏图上运行速度更快的变体。

5. 效率度量

5.1. igraph_global_efficiency — 计算网络的全局效率。

igraph_error_t igraph_global_efficiency(const igraph_t *graph, igraph_real_t *res,
                             const igraph_vector_t *weights,
                             igraph_bool_t directed);

网络的全局效率定义为所有顶点对之间逆距离的平均值:E_g = 1/(N*(N-1)) sum_{i!=j} 1/d_ij,其中 N 是顶点数。彼此无法到达的顶点对之间的逆距离被认为是零。对于顶点少于 2 个的图,将返回 NaN。

参考

V. Latora 和 M. Marchiori,《小世界网络的有效行为》,Phys. Rev. Lett. 87, 198701 (2001)。https://dx.doi.org/10.1103/PhysRevLett.87.198701

参数: 

:

图对象。

res:

指向实数的指针,这将包含结果。

weights:

边权重。对于 Dijkstra 算法,所有边权重必须为非负数。此外,任何边权重都不能为 NaN。如果上述任何一种情况不成立,则返回一个错误。如果这是一个空指针,则在计算全局效率时使用未加权版本 igraph_average_path_length()。具有正无穷权重的边将被忽略。

有向:

布尔值,是否考虑有向路径。在无向图中被忽略。

返回值: 

错误代码

IGRAPH_ENOMEM

数据结构内存不足

IGRAPH_EINVAL

无效的权重向量

时间复杂度:加权图为 O(|V| |E| log|E| + |V|),未加权图为 O(|V| |E|)。|V| 表示顶点数,|E| 表示边数。

另请参阅: 

5.2. igraph_local_efficiency — 计算网络中每个顶点周围的局部效率。

igraph_error_t igraph_local_efficiency(const igraph_t *graph, igraph_vector_t *res,
                            const igraph_vs_t vids,
                            const igraph_vector_t *weights,
                            igraph_bool_t directed, igraph_neimode_t mode);

网络中顶点周围的局部效率定义如下:我们删除该顶点,并计算其邻居通过网络其余部分的距离(最短路径长度)。删除的顶点周围的局部效率是这些距离的倒数的平均值。

彼此无法到达的两个顶点之间的逆距离被认为是零。按照惯例,邻居少于两个的顶点周围的局部效率被认为是零。

参考

I. Vragović、E. Louis 和 A. Díaz-Guilera,《常规网络和复杂网络中的信息传输效率》,Phys. Rev. E 71, 1 (2005)。http://dx.doi.org/10.1103/PhysRevE.71.036122

参数: 

:

图对象。

res:

指向已初始化向量的指针,这将包含结果。

vids:

将围绕其计算局部效率的顶点。

weights:

边权重。所有边权重必须为非负数。此外,任何边权重都不能为 NaN。如果上述任何一种情况不成立,则返回一个错误。如果这是一个空指针,则调用未加权版本 igraph_average_path_length()。具有正无穷权重的边将被忽略。

有向:

布尔值,是否考虑有向路径。在无向图中被忽略。

模式:

如何确定定向图中每个顶点的局部邻域。在无向图中被忽略。

IGRAPH_ALL

同时获取入邻居和出邻居;这是高级接口的合理默认设置。

IGRAPH_OUT

仅获取出邻居

IGRAPH_IN

仅获取入邻居

返回值: 

错误代码

IGRAPH_ENOMEM

数据结构内存不足

IGRAPH_EINVAL

无效的权重向量

时间复杂度:加权图为 O(|E|^2 log|E|),未加权图为 O(|E|^2)。|E| 表示边数。

另请参阅: 

5.3. igraph_average_local_efficiency — 计算网络中的平均局部效率。

igraph_error_t igraph_average_local_efficiency(const igraph_t *graph, igraph_real_t *res,
                                    const igraph_vector_t *weights,
                                    igraph_bool_t directed, igraph_neimode_t mode);

对于空图,按照惯例返回零。

参数: 

:

图对象。

res:

指向实数的指针,这将包含结果。

weights:

边权重。它们必须都是非负数。如果给出了一个空指针,则假定所有权重都为 1。具有正无穷权重的边将被忽略。

有向:

布尔值,是否考虑有向路径。在无向图中被忽略。

模式:

如何确定定向图中每个顶点的局部邻域。在无向图中被忽略。

IGRAPH_ALL

同时获取入邻居和出邻居;这是高级接口的合理默认设置。

IGRAPH_OUT

仅获取出邻居

IGRAPH_IN

仅获取入邻居

返回值: 

错误代码

IGRAPH_ENOMEM

数据结构内存不足

IGRAPH_EINVAL

无效的权重向量

时间复杂度:加权图为 O(|E|^2 log|E|),未加权图为 O(|E|^2)。|E| 表示边数。

另请参阅: 

6. 顶点的邻域

6.1. igraph_neighborhood_size — 计算给定顶点邻域的大小。

igraph_error_t igraph_neighborhood_size(const igraph_t *graph, igraph_vector_int_t *res,
                             igraph_vs_t vids, igraph_integer_t order,
                             igraph_neimode_t mode,
                             igraph_integer_t mindist);

给定阶数的顶点的邻域包括所有比该阶数更靠近该顶点的顶点。即,阶数 0 始终是顶点本身,阶数 1 是顶点及其直接邻居,阶数 2 是阶数 1 加上阶数 1 中顶点的直接邻居,依此类推。

此函数计算给定阶数的邻域对于给定顶点的大小。

参数: 

:

输入图。

res:

指向已初始化向量的指针,结果将存储在此处。它将根据需要调整大小。

vids:

为其执行计算的顶点。

order:

整数,给出邻域的阶数。负值被视为无穷大。

模式:

指定如果分析定向图,如何使用边的方向。对于 IGRAPH_OUT,仅跟踪传出边,因此最多在 order 步中从源顶点可到达的所有顶点都被计算在内。对于 IGRAPH_IN,最多在 order 步中从其可到达源顶点的所有顶点都被计算在内。IGRAPH_ALL 忽略边的方向。此参数对于无向图将被忽略。

mindist:

将顶点包括在计数中的最小距离。可以通过比此值短的路径到达的顶点将被排除在外。如果这是 1,则起始顶点不被计算在内。如果这是 2,则其邻居也不会被计算在内,依此类推。

返回值: 

错误代码。

另请参阅: 

igraph_neighborhood() 用于计算实际邻域;igraph_neighborhood_graphs() 用于从邻域创建单独的图。

时间复杂度:O(n*d*o),其中 n 是为其执行计算的顶点数,d 是平均度数,o 是阶数。

6.2. igraph_neighborhood — 计算顶点的邻域。

igraph_error_t igraph_neighborhood(const igraph_t *graph, igraph_vector_int_list_t *res,
                        igraph_vs_t vids, igraph_integer_t order,
                        igraph_neimode_t mode, igraph_integer_t mindist);

给定阶数的顶点的邻域包括所有比该阶数更靠近该顶点的顶点。即,阶数 0 始终是顶点本身,阶数 1 是顶点及其直接邻居,阶数 2 是阶数 1 加上阶数 1 中顶点的直接邻居,依此类推。

此函数计算指定顶点邻域内的顶点。

参数: 

:

输入图。

res:

已初始化整数向量列表。计算结果将存储在此处。该列表将根据需要调整大小。

vids:

为其执行计算的顶点。

order:

整数,给出邻域的阶数。负值被视为无穷大。

模式:

指定如果分析定向图,如何使用边的方向。对于 IGRAPH_OUT,仅跟踪传出边,因此最多在 order 步中从源顶点可到达的所有顶点都被包括在内。对于 IGRAPH_IN,最多在 order 步中从其可到达源顶点的所有顶点都被包括在内。IGRAPH_ALL 忽略边的方向。此参数对于无向图将被忽略。

mindist:

将顶点包括在计数中的最小距离。可以通过比此值短的路径到达的顶点将被排除在外。如果这是 1,则起始顶点不被计算在内。如果这是 2,则其邻居也不会被计算在内,依此类推。

返回值: 

错误代码。

另请参阅: 

igraph_neighborhood_size() 用于计算邻域的大小;igraph_neighborhood_graphs() 用于从邻域创建图;igraph_subcomponent() 用于查找从单个顶点可到达的顶点。

时间复杂度:O(n*d*o),n 是为其执行计算的顶点数,d 是平均度数,o 是阶数。

6.3. igraph_neighborhood_graphs — 从一些顶点的一个或多个邻域创建图。

igraph_error_t igraph_neighborhood_graphs(const igraph_t *graph, igraph_graph_list_t *res,
                               igraph_vs_t vids, igraph_integer_t order,
                               igraph_neimode_t mode,
                               igraph_integer_t mindist);

给定阶数的顶点的邻域包括所有比该阶数更靠近该顶点的顶点。即,阶数 0 始终是顶点本身,阶数 1 是顶点及其直接邻居,阶数 2 是阶数 1 加上阶数 1 中顶点的直接邻居,依此类推。

此函数查找给定参数顶点邻域中的每个顶点,并从这些顶点创建导出的子图。

此函数的第一个版本由 Vincent Matossian 编写,感谢 Vincent。

参数: 

:

输入图。

res:

指向图列表的指针,结果将存储在此处。列表中的每个项目都是一个 igraph_t 对象。该列表将根据需要调整大小。

vids:

为其执行计算的顶点。

order:

整数,给出邻域的阶数。负值被视为无穷大。

模式:

指定如果分析定向图,如何使用边的方向。对于 IGRAPH_OUT,仅跟踪传出边,因此最多在 order 步中从源顶点可到达的所有顶点都被计算在内。对于 IGRAPH_IN,最多在 order 步中从其可到达源顶点的所有顶点都被计算在内。IGRAPH_ALL 忽略边的方向。此参数对于无向图将被忽略。

mindist:

将顶点包括在计数中的最小距离。可以通过比此值短的路径到达的顶点将被排除在外。如果这是 1,则起始顶点不被计算在内。如果这是 2,则其邻居也不会被计算在内,依此类推。

返回值: 

错误代码。

另请参阅: 

igraph_neighborhood_size() 仅用于计算邻域大小;igraph_neighborhood() 用于计算邻域(但不创建图)。

时间复杂度:O(n*(|V|+|E|)),其中 n 是为其执行计算的顶点数,|V| 和 |E| 是原始输入图中的顶点数和边数。

7. 局部扫描统计

扫描统计是从每个顶点的局部邻域计算得出的局部统计的摘要。有关详细信息,请参见 Priebe, C. E., Conroy, J. M., Marchette, D. J., Park, Y. (2005)。Enron 图上的扫描统计。计算和数学组织理论。

7.1. “Us” 统计

7.1.1. igraph_local_scan_0 — 局部扫描统计,k=0

igraph_error_t igraph_local_scan_0(const igraph_t *graph, igraph_vector_t *res,
                        const igraph_vector_t *weights,
                        igraph_neimode_t mode);

K=0 扫描统计被任意定义为未加权图的顶点度数和加权图的顶点强度。请参见 igraph_degree()igraph_strength()

参数: 

:

输入图

res:

已初始化的向量,结果存储在此处。

weights:

加权图的权重向量,未加权图的 null 指针。

模式:

邻域的类型,IGRAPH_OUT 表示传出,IGRAPH_IN 表示传入,IGRAPH_ALL 表示所有边。

返回值: 

错误代码。

7.1.2. igraph_local_scan_1_ecount — 局部扫描统计,k=1,边数和权重总和

igraph_error_t igraph_local_scan_1_ecount(const igraph_t *graph, igraph_vector_t *res,
                               const igraph_vector_t *weights,
                               igraph_neimode_t mode);

计算顶点的 1 邻域中的边数或边权重的总和。

参数: 

:

输入图

res:

已初始化的向量,结果存储在此处。

weights:

加权图的权重向量,未加权图的 null 指针。

模式:

邻域的类型,IGRAPH_OUT 表示传出,IGRAPH_IN 表示传入,IGRAPH_ALL 表示所有边。

返回值: 

错误代码。

7.1.3. igraph_local_scan_k_ecount — 对每个顶点的 k 邻域中的边数或权重求和。

igraph_error_t igraph_local_scan_k_ecount(const igraph_t *graph, igraph_integer_t k,
                               igraph_vector_t *res,
                               const igraph_vector_t *weights,
                               igraph_neimode_t mode);

参数: 

:

输入图。

k:

邻域的大小,非负整数。k=0 的情况很特殊,请参见 igraph_local_scan_0()

res:

已初始化的向量,结果存储在此处。

weights:

加权图的权重向量,未加权图的 null 指针。

模式:

邻域的类型,IGRAPH_OUT 表示传出,IGRAPH_IN 表示传入,IGRAPH_ALL 表示所有边。

返回值: 

错误代码。

7.2. “Them” 统计

7.2.1. igraph_local_scan_0_them — 局部 THEM 扫描统计,k=0

igraph_error_t igraph_local_scan_0_them(const igraph_t *us, const igraph_t *them,
                             igraph_vector_t *res,
                             const igraph_vector_t *weights_them,
                             igraph_neimode_t mode);

K=0 扫描统计被任意定义为未加权图的顶点度数和加权图的顶点强度。请参见 igraph_degree()igraph_strength()

参数: 

us:

输入图,用于提取邻域。

them:

用于实际计数的输入图。

res:

已初始化的向量,结果存储在此处。

weights_them:

加权图的权重向量,未加权图的 null 指针。

模式:

邻域的类型,IGRAPH_OUT 表示传出,IGRAPH_IN 表示传入,IGRAPH_ALL 表示所有边。

返回值: 

错误代码。

7.2.2. igraph_local_scan_1_ecount_them — 局部 THEM 扫描统计,k=1,边数和权重总和

igraph_error_t igraph_local_scan_1_ecount_them(const igraph_t *us, const igraph_t *them,
                                    igraph_vector_t *res,
                                    const igraph_vector_t *weights_them,
                                    igraph_neimode_t mode);

计算顶点的 1 邻域中的边数或边权重的总和。

参数: 

us:

用于提取邻域的输入图。

them:

用于执行计数的输入图。

weights_them:

加权图的权重向量,未加权图的 null 指针。

模式:

邻域的类型,IGRAPH_OUT 表示传出,IGRAPH_IN 表示传入,IGRAPH_ALL 表示所有边。

返回值: 

错误代码。

另请参阅: 

igraph_local_scan_1_ecount() 用于 US 统计。

7.2.3. igraph_local_scan_k_ecount_them — 局部 THEM 扫描统计,边数或权重总和。

igraph_error_t igraph_local_scan_k_ecount_them(const igraph_t *us, const igraph_t *them,
                                    igraph_integer_t k, igraph_vector_t *res,
                                    const igraph_vector_t *weights_them,
                                    igraph_neimode_t mode);

计算顶点的 k 邻域中的边数或边权重的总和。

参数: 

us:

用于提取邻域的输入图。

them:

用于执行计数的输入图。

k:

邻域的大小,非负整数。k=0 的情况很特殊,请参见 igraph_local_scan_0_them()

weights_them:

加权图的权重向量,未加权图的 null 指针。

模式:

邻域的类型,IGRAPH_OUT 表示传出,IGRAPH_IN 表示传入,IGRAPH_ALL 表示所有边。

返回值: 

错误代码。

另请参阅: 

igraph_local_scan_1_ecount() 用于 US 统计。

7.3. 预先计算的子集

7.3.1. igraph_local_scan_neighborhood_ecount — 具有预先计算的邻域的局部扫描统计

igraph_error_t igraph_local_scan_neighborhood_ecount(const igraph_t *graph,
        igraph_vector_t *res,
        const igraph_vector_t *weights,
        const igraph_vector_int_list_t *neighborhoods);

计算边数,或对作为参数给出的邻域中的边权重求和。

警告

自版本 0.10.0 起已弃用。请勿在新代码中使用此函数;请改用 igraph_local_scan_subset_ecount()

参数: 

:

要在其中执行计数/求和的图。

res:

已初始化的向量,结果存储在此处。

weights:

加权图的权重向量,未加权图的 null 指针。

neighborhoods:

igraph_vector_int_t 对象列表,邻域,图中每个顶点一个。

返回值: 

错误代码。

7.3.2. igraph_local_scan_subset_ecount — 由顶点子集导出的子图的局部扫描统计。

igraph_error_t igraph_local_scan_subset_ecount(const igraph_t *graph,
        igraph_vector_t *res,
        const igraph_vector_t *weights,
        const igraph_vector_int_list_t *subsets);

计算边数,或对来自作为参数给出的顶点的导出子图中的边权重求和。

参数: 

:

要在其中执行计数/求和的图。

res:

已初始化的向量,结果存储在此处。

weights:

加权图的权重向量,未加权图的 null 指针。

subsets:

igraph_vector_int_t 对象列表,顶点子集。

返回值: 

错误代码。

8. 图组件

8.1. igraph_subcomponent — 从给定顶点可到达的顶点。

igraph_error_t igraph_subcomponent(
    const igraph_t *graph, igraph_vector_int_t *res, igraph_integer_t vertex,
    igraph_neimode_t mode
);

此函数返回从指定顶点可到达的顶点集。在无向图中,这只是同一组件内的顶点集。

参数: 

:

图对象。

res:

结果,包含从 vertex 可到达的顶点的 ID 的向量。

vertex:

正在搜索组件的顶点的 ID。

模式:

定向图的组件类型,可能的值

IGRAPH_OUT

可到达顶点的集合vertex,

IGRAPH_IN

vertex可以到达的顶点的集合。

IGRAPH_ALL

该图被视为无向图。请注意,这与前两者的并集同。

返回值: 

错误代码

IGRAPH_ENOMEM

临时数据没有足够的内存。

IGRAPH_EINVVID

vertex是一个无效的顶点 ID

IGRAPH_EINVMODE

传递了无效的模式参数。

时间复杂度:O(|V|+|E|),|V| 和 |E| 是图中顶点和边的数量。

另请参阅: 

如果您想要一个仅由一组给定的顶点及其之间的边组成的图形对象,请使用igraph_induced_subgraph();使用 igraph_reachability() 可以有效地计算所有顶点的可到达集;使用 igraph_neighborhood() 可以查找给定距离内的顶点。

8.2. igraph_connected_components — 计算图中的(弱或强)连通分量。

igraph_error_t igraph_connected_components(
    const igraph_t *graph, igraph_vector_int_t *membership,
    igraph_vector_int_t *csize, igraph_integer_t *no, igraph_connectedness_t mode
);

当计算强连通分量时,分量将按拓扑顺序索引。换句话说,顶点 v 可以从顶点 u 到达,当且仅当 membership[u] <= membership[v]

参数: 

:

要分析的图对象。

membership:

对于每个顶点,给出其分量的 ID。必须预先初始化该向量,并且会根据需要调整大小。或者,此参数可以是 NULL,在这种情况下将被忽略。

csize:

对于每个分量,它都会给出其大小,顺序由分量 ID 定义。必须预先初始化该向量,并且会根据需要调整大小。或者,此参数可以是 NULL,在这种情况下将被忽略。

no:

指向一个整数的指针,如果不是 NULL,则组件的数量将存储在此处。

模式:

对于有向图,这指定是计算弱连通分量还是强连通分量。可能的值

IGRAPH_WEAK

计算弱连通分量,即忽略边的方向。

IGRAPH_STRONG

计算强连通分量,即考虑边的方向。

对于无向图,此参数将被忽略。

返回值: 

错误代码。

时间复杂度:O(|V|+|E|),其中 |V| 和 |E| 是图中顶点和边的数量。

例子 13.15. 文件 examples/simple/igraph_contract_vertices.c

#include <igraph.h>

/* Create the condensation of a directed graph.
 * See https://en.wikipedia.org/wiki/Strongly_connected_component#Definitions
 * This example demonstrates how to write a basic igraph function, complete
 * with error handling. */
igraph_error_t condensation(const igraph_t *graph, igraph_t *cond) {
    igraph_vector_int_t membership;

    /* Data structures such as vector must be initialized in igraph before use. */
    IGRAPH_CHECK(igraph_vector_int_init(&membership, 0));

    /* Adding the initialized vector to the "finally" stack ensures that it will
     * be automatically destroyed if an error occurs. */
    IGRAPH_FINALLY(igraph_vector_int_destroy, &membership);

    /* Functions that return an error code can be wrapped in IGRAPH_CHECK to pass that error
     * up to the caller. */
    IGRAPH_CHECK(igraph_connected_components(graph, &membership, /* csize */ NULL, /* no */ NULL, IGRAPH_STRONG));

    /* To compute the condensation, we simply contract strongly connected components.
     * Since igraph_contract_vertices() modifies graphs in-place, we make a copy first. */
    IGRAPH_CHECK(igraph_copy(cond, graph));

    /* Since we are not done creating the condensation yet, we add 'cond' to the
     * "finally" stack, so that it will be destroyed if an error occurs. */
    IGRAPH_FINALLY(igraph_destroy, cond);

    /* Contract strongly connected components. */
    IGRAPH_CHECK(igraph_contract_vertices(cond, &membership, NULL));

    /* igraph_contract_vertices() preserves all edges, some of which become
     * parallel edges or self-loops after the contraction. We simplify these. */
    IGRAPH_CHECK(igraph_simplify(cond, /* remove_multiple */ true, /* remove_loops */ true, NULL));

    /* Data structures that are no longer needed must be explicitly destroyed.
     * If they were added to the "finally" stack, they must be removed explicitly,
     * in the opposite order to how they were added. IGRAPH_FINALLY_CLEAN removes
     * the indicated number of entries from the "finally" stack. We remove
     * 'membership' because it was destroyed, and 'cond' because the responsibility
     * to destroy it is now with the caller. */
    igraph_vector_int_destroy(&membership);
    IGRAPH_FINALLY_CLEAN(2);

    return IGRAPH_SUCCESS; /* return with no error */
}

int main(void) {
    igraph_t graph, cond;

    /* Create a random directed graph with mean degree 2 and compute its condensation. */
    igraph_erdos_renyi_game_gnm(&graph, 100, 200, IGRAPH_DIRECTED, IGRAPH_NO_LOOPS);
    condensation(&graph, &cond);

    printf("Number of vertices in the condensation: %" IGRAPH_PRId "\n", igraph_vcount(&cond));
    igraph_write_graph_edgelist(&cond, stdout);

    /* Destroy data structures that are no longer needed. */
    igraph_destroy(&graph);
    igraph_destroy(&cond);

    return 0;
}


8.3. igraph_clusters — 计算图中的(弱或强)连通分量(已弃用的别名)。

igraph_error_t igraph_clusters(const igraph_t *graph, igraph_vector_int_t *membership,
                    igraph_vector_int_t *csize, igraph_integer_t *no,
                    igraph_connectedness_t mode);

警告

自 0.10 版本起已弃用。请不要在新代码中使用此函数;请改用 igraph_connected_components()

8.4. igraph_is_connected — 确定图是否(弱或强)连通。

igraph_error_t igraph_is_connected(const igraph_t *graph, igraph_bool_t *res,
                        igraph_connectedness_t mode);

当它的任何顶点都可以从任何其他顶点到达时,该图被认为是连通的。具有此属性的有向图称为连通图。如果忽略边的方向,则连通的有向图称为连通图。

根据定义,具有零个顶点(即空图)的图连通。此行为在 igraph 0.9 中已更改;早期版本假定空图是连通的。有关导致我们更改定义的参数,请参阅 Github 上的以下问题:https://github.com/igraph/igraph/issues/1539

此函数的返回值缓存在图本身中,分别用于弱连通性和强连通性。多次调用该函数,并且两次调用之间不对图进行修改,将在 O(1) 时间内返回缓存的值。

参数: 

:

要分析的图对象。

res:

指向布尔变量的指针,结果将存储在此处。

模式:

对于有向图,这指定是计算弱连通性还是强连通性。可能的值:IGRAPH_WEAK, IGRAPH_STRONG。对于无向图,此参数将被忽略。

返回值: 

错误代码:IGRAPH_EINVAL:无效的模式参数。

另请参阅: 

igraph_connected_components() 可以查找连通分量,igraph_is_biconnected() 可以检查图是否是 2 顶点连通的。

时间复杂度:O(|V|+|E|),图中的顶点数加上边数。

8.5. igraph_decompose — 将图分解为连通分量。

igraph_error_t igraph_decompose(const igraph_t *graph, igraph_graph_list_t *components,
                     igraph_connectedness_t mode,
                     igraph_integer_t maxcompno, igraph_integer_t minelements);

为图的每个分量创建一个单独的图。请注意,新图中的顶点 ID 将与原始图中的顶点 ID 不同,除非原始图中只有一个分量。

参数: 

:

原始图。

组件:

此图列表将包含各个组件。应在调用此函数之前对其进行初始化,并且将调整大小以容纳这些图。

模式:

对于弱连通分量和强连通分量,分别为 IGRAPH_WEAKIGRAPH_STRONG

maxcompno:

要返回的最大组件数。将返回前 maxcompno 个组件(这些组件至少包含 minelements 个顶点,请参见下一个参数),其余组件将被忽略。如果不希望限制组件的数量,请在此处提供 -1

minelements:

为了将其放置在 components 向量中,组件应包含的最小顶点数。例如,在此处提供 2 会忽略孤立的顶点。

返回值: 

错误代码,如果没有足够的内存来执行该操作,则返回 IGRAPH_ENOMEM

在 0.2 版本中添加。

时间复杂度:O(|V|+|E|),顶点数加上边数。

例子 13.16. 文件 examples/simple/igraph_decompose.c

#include <igraph.h>
#include <stdlib.h>

int main(void) {

    igraph_t ring, g, *component;
    igraph_graph_list_t complist;
    igraph_integer_t i;
    igraph_integer_t edges[] = { 0, 1, 1, 2, 2, 0,
                              3, 4, 4, 5, 5, 6,
                              8, 9, 9, 10
                            };
    igraph_vector_int_t v;

    igraph_graph_list_init(&complist, 0);

    /* A ring, a single component */
    igraph_ring(&ring, 10, IGRAPH_UNDIRECTED, 0, 1);

    igraph_decompose(&ring, &complist, IGRAPH_WEAK, -1, 0);
    component = igraph_graph_list_get_ptr(&complist, 0);
    igraph_write_graph_edgelist(component, stdout);
    igraph_destroy(&ring);
    igraph_graph_list_clear(&complist);

    /* Random graph with a giant component */
    igraph_erdos_renyi_game_gnp(&g, 100, 4.0 / 100, IGRAPH_UNDIRECTED, 0);
    igraph_decompose(&g, &complist, IGRAPH_WEAK, -1, 20);
    if (igraph_graph_list_size(&complist) != 1) {
        return 1;
    }
    igraph_destroy(&g);
    igraph_graph_list_clear(&complist);

    /* A toy graph, three components maximum, with at least 2 vertices each */
    igraph_create(&g,
                  igraph_vector_int_view(&v, edges, sizeof(edges) / sizeof(edges[0])),
                  0, IGRAPH_DIRECTED);
    igraph_decompose(&g, &complist, IGRAPH_WEAK, 3, 2);
    for (i = 0; i < igraph_graph_list_size(&complist); i++) {
        component = igraph_graph_list_get_ptr(&complist, i);
        igraph_write_graph_edgelist(component, stdout);
    }
    igraph_destroy(&g);

    igraph_graph_list_destroy(&complist);

    return 0;
}


8.6. igraph_decompose_destroy — 释放保存图的指针向量的内容。

void igraph_decompose_destroy(igraph_vector_ptr_t *complist);

此函数销毁并释放 complist 中保存的所有 igraph_t 对象。但是,它不会销毁 complist 本身。使用 igraph_vector_ptr_destroy() 来销毁 complist

参数: 

complist:

要销毁的图列表。

时间复杂度:O(n),n 是项目的数量。

警告

自 0.10.0 版本起已弃用。请不要在新代码中使用此函数。

8.7. igraph_reachability — 计算图中每个顶点可到达的顶点。

igraph_error_t igraph_reachability(
        const igraph_t *graph,
        igraph_vector_int_t *membership,
        igraph_vector_int_t *csize,
        igraph_integer_t *no_of_components,
        igraph_bitset_list_t *reach,
        igraph_neimode_t mode);

警告

此函数是实验性的,其签名尚未被视为最终签名。我们保留更改函数签名的权利,而无需更改 igraph 的主要版本。使用它需要您自担风险。

结果列表将包含每个强连通分量的一个位集。如果顶点 j 可以从分量 i 中的某个顶点在 0 步或更多步到达,则分量 i 的位集将设置其第 j 位。特别地,顶点始终可以从自身到达。

参数: 

:

要分析的图对象。

membership:

指向整数向量的指针。对于每个顶点,给出其分量的 ID。该向量将根据需要调整大小。此参数不得为 NULL

csize:

指向整数向量或 NULL 的指针。对于每个分量,它都会给出其大小(顶点数),顺序由分量 ID 定义。该向量将根据需要调整大小。

no_of_components:

指向整数或 NULL 的指针。组件的数量将存储在此处。

reach:

表示结果的位集列表。它将根据需要调整大小。reach[membership[u]][v] 如果顶点 v 可以从顶点 u 到达,则设置为 true

模式:

在有向图中,控制边的方向的处理。在无向图中将被忽略。使用 IGRAPH_OUT,通过沿其方向遍历边来计算可到达性。使用 IGRAPH_IN,边的遍历方向与其方向相反。使用 IGRAPH_ALL,忽略边的方向并将图视为无向图。

返回值: 

错误代码:如果没有足够的内存来执行该操作,则返回 IGRAPH_ENOMEM

另请参阅: 

igraph_connected_components() 可以查找图的连通分量;igraph_count_reachable() 可以计算每个顶点可到达的顶点数;igraph_subcomponent() 可以查找可以从单个顶点到达的顶点。

时间复杂度:O(|C||V|/w + |V| + |E|),其中 |C| 是强连通分量的数量(最多 |V|),|V| 是顶点的数量,|E| 分别是边的数量,w 是 igraph_integer_t 的位宽,通常是机器的字大小(32 或 64)。

8.8. igraph_count_reachable — 图中每个顶点可到达的顶点数。

igraph_error_t igraph_count_reachable(const igraph_t *graph,
                                      igraph_vector_int_t *counts,
                                      igraph_neimode_t mode);

警告

此函数是实验性的,其签名尚未被视为最终签名。我们保留更改函数签名的权利,而无需更改 igraph 的主要版本。使用它需要您自担风险。

参数: 

:

要分析的图对象。

counts:

整数向量。counts[v] 将存储可以从顶点 v 到达的顶点数,包括 v 本身。

模式:

在有向图中,控制边的方向的处理。在无向图中将被忽略。使用 IGRAPH_OUT,通过沿其方向遍历边来计算可到达性。使用 IGRAPH_IN,边的遍历方向与其方向相反。使用 IGRAPH_ALL,忽略边的方向并将图视为无向图。

返回值: 

错误代码:如果没有足够的内存来执行该操作,则返回 IGRAPH_ENOMEM

另请参阅: 

时间复杂度:O(|C||V|/w + |V| + |E|),其中 |C| 是强连通分量的数量(最多 |V|),|V| 是顶点的数量,|E| 分别是边的数量,w 是 igraph_integer_t 的位宽,通常是机器的字大小(32 或 64)。

8.9. igraph_transitive_closure — 计算图的传递闭包。

igraph_error_t igraph_transitive_closure(const igraph_t *graph, igraph_t *closure);

警告

此函数是实验性的,其签名尚未被视为最终签名。我们保留更改函数签名的权利,而无需更改 igraph 的主要版本。使用它需要您自担风险。

如果 j 可以从 i 到达,则结果图将具有从顶点 i 到顶点 j 的边。

参数: 

:

要分析的图对象。

closure:

表示传递闭包的结果图。

返回值: 

错误代码:如果没有足够的内存来执行该操作,则返回 IGRAPH_ENOMEM

另请参阅: 

时间复杂度:O(|V|^2 + |E|),其中 |V| 是顶点的数量,|E| 分别是边的数量。

8.10. igraph_biconnected_components — 计算双连通分量。

igraph_error_t igraph_biconnected_components(const igraph_t *graph,
                                  igraph_integer_t *no,
                                  igraph_vector_int_list_t *tree_edges,
                                  igraph_vector_int_list_t *component_edges,
                                  igraph_vector_int_list_t *components,
                                  igraph_vector_int_t *articulation_points);

如果删除任何单个顶点(及其关联的边)不会断开它的连接,则图是双连通的。

图的双连通分量是它的最大双连通子图。图的双连通分量可以通过其边的分区给出:每条边都是恰好一个双连通分量的成员。请注意,这对于顶点不成立:同一个顶点可以是多个双连通分量的一部分,而孤立的顶点不是任何双连通分量的一部分。

请注意,一些作者不认为由两个连通顶点组成的图是双连通的,但是 igraph 认为它是双连通的。

igraph 不认为仅包含单个顶点的分量是双连通的。孤立的顶点不会是任何双连通分量的一部分。这意味着检查是否存在单个双连通分量不足以确定图是否是双连通的。为此,请使用 igraph_is_biconnected()

参数: 

:

输入图。它将被视为无向图。

no:

如果不是 NULL 指针,则双连通分量的数量将存储在此处。

tree_edges:

如果不是 NULL 指针,则在此处以向量列表的形式存储找到的组件。列表中的每个向量都是一个双连通分量,由其边表示。更准确地说,返回双连通分量的生成树。

component_edges:

如果不是 NULL 指针,则双连通分量的边将存储在此处,形式与 tree_edges 的形式相同。

组件:

如果不是 NULL 指针,则双连通分量的顶点将存储在此处,格式与前两个参数的格式相同。

articulation_points:

如果不是 NULL 指针,则图的割点将存储在此向量中。如果删除顶点会增加图中(弱)连通分量的数量,则该顶点是一个割点。

返回值: 

错误代码。

时间复杂度:O(|V|+|E|),在线性于顶点和边的数量,但前提是您不计算 componentscomponent_edges。如果计算 components,则顶点数呈二次方。如果还计算 component_edges,则顶点数呈三次方。

另请参阅: 

例子 13.17. 文件 examples/simple/igraph_biconnected_components.c

#include <igraph.h>

/* Prints a vector of edge IDs as u--v vertex pairs. */
void print_edge_vector(const igraph_t *graph, const igraph_vector_int_t *edges) {
    const igraph_integer_t n = igraph_vector_int_size(edges);
    for (igraph_integer_t i=0; i < n; i++) {
        igraph_integer_t edge = VECTOR(*edges)[i];
        printf("%" IGRAPH_PRId "--%" IGRAPH_PRId " ", IGRAPH_FROM(graph, edge), IGRAPH_TO(graph, edge));
    }
    printf("\n");
}

int main(void) {
    igraph_t graph;
    igraph_vector_int_list_t component_vertices, component_edges;
    igraph_integer_t no;

    /* Create an example graph. */
    igraph_small(&graph, 7, IGRAPH_UNDIRECTED,
                 0,1, 1,2, 2,3, 3,0,
                 2,4, 4,5, 5,2,
                 0,6,
                 0,7,
                 -1);

    /* The data structures that the result will be written to must be initialized first. */
    igraph_vector_int_list_init(&component_vertices, 0);
    igraph_vector_int_list_init(&component_edges, 0);

    igraph_biconnected_components(&graph, &no, NULL, &component_edges, &component_vertices, NULL);

    printf("Number of components: %" IGRAPH_PRId "\n", no);
    for (igraph_integer_t i=0; i < no; i++) {
        printf("\n");
        printf("Component %" IGRAPH_PRId ":\n", i);
        printf("Vertices: ");
        igraph_vector_int_print(igraph_vector_int_list_get_ptr(&component_vertices, i));
        printf("Edges: ");
        print_edge_vector(&graph, igraph_vector_int_list_get_ptr(&component_edges, i));
    }

    /* Destroy data structures after we no longer need them. */

    igraph_vector_int_list_destroy(&component_edges);
    igraph_vector_int_list_destroy(&component_vertices);

    igraph_destroy(&graph);

    return 0;
}


8.11. igraph_articulation_points — 查找图中的割点。

igraph_error_t igraph_articulation_points(const igraph_t *graph, igraph_vector_int_t *res);

如果删除顶点会增加图中(弱)连通分量的数量,则该顶点是一个割点。

请注意,没有任何割点的图不一定是双连通的。反例是双顶点完全图以及空图。使用 igraph_is_biconnected() 来检查图是否是双连通的。

参数: 

:

输入图。它将被视为无向图。

res:

指向已初始化向量的指针,割点将存储在此处。

返回值: 

错误代码。

时间复杂度:O(|V|+|E|),顶点数和边数的线性关系。

另请参阅: 

8.12. igraph_bridges — 查找图中的所有桥。

igraph_error_t igraph_bridges(const igraph_t *graph, igraph_vector_int_t *bridges);

如果删除边会增加图中(弱)连通分量的数量,则该边是一座桥。

参数: 

:

输入图。它将被视为无向图。

res:

指向已初始化向量的指针,桥将作为边索引存储在此处。

返回值: 

错误代码。

时间复杂度:O(|V|+|E|),顶点数和边数的线性关系。

另请参阅: 

8.13. igraph_is_biconnected — 检查图是否是双连通的。

igraph_error_t igraph_is_biconnected(const igraph_t *graph, igraph_bool_t *res);

警告

此函数是实验性的,其签名尚未被视为最终签名。我们保留更改函数签名的权利,而无需更改 igraph 的主要版本。使用它需要您自担风险。

如果删除任何单个顶点(及其关联的边)不会断开它的连接,则图是双连通的。

igraph 不认为单顶点图是双连通的。

请注意,一些作者不认为由两个连通顶点组成的图是双连通的,但是 igraph 认为它是双连通的。

参数: 

:

输入图。它将被视为无向图。

result:

如果不是 NULL 指针,则结果将返回到此处。

返回值: 

错误代码。

时间复杂度:O(|V|+|E|),顶点数和边数的线性关系。

另请参阅: 

例子 13.18. 文件 examples/simple/igraph_is_biconnected.c

#include <igraph.h>
#include <stdio.h>

int main(void) {

    igraph_t g;
    igraph_bool_t result;

    igraph_small(&g, 7, 0, 0, 1, 1, 2, 2, 3, 3, 0, 2, 4, 4, 5, 2, 5, -1);
    igraph_is_biconnected(&g, &result);
    printf("Graph is%sbiconnected.\n", result ? " " : " not ");
    igraph_destroy(&g);

    return 0;
}


9. 度序列

9.1. igraph_is_graphical — 是否存在具有给定度序列的图?

igraph_error_t igraph_is_graphical(const igraph_vector_int_t *out_degrees,
                        const igraph_vector_int_t *in_degrees,
                        const igraph_edge_type_sw_t allowed_edge_types,
                        igraph_bool_t *res);

确定整数序列是否可以是某个图的度序列。图形性的经典概念假设简单图。当允许图中有自环、多边或两者时,此函数也可以执行检查。

对于简单无向图,Erdős-Gallai 条件使用 Cloteaux 的线性时间算法进行检查。如果允许自环和多边,则足以检查度之和是否为偶数。如果仅允许使用多边,但不允许使用自环,则还有一个附加条件,即度之和不小于最大度的两倍。如果每个顶点最多允许一个自环,但不允许使用多边,则使用 Erdős-Gallai 条件的修改版本(请参阅 Cairns 和 Mendan)。

对于简单有向图,使用 Fulkerson-Chen-Anstee 定理和 Berger 的松弛。如果允许自环和多边,则足以检查入度和出度之和是否相同。如果仅允许使用多边,但不允许使用自环,则还有一个附加条件,即出度之和(或等效地,入度之和)不小于最大总度。如果允许使用单个自环,但不允许使用多边,则问题等效于作为简单二分图的可实现性,因此可以使用 Gale-Ryser 定理;有关更多信息,请参阅 igraph_is_bigraphical()

参考

P. Erdős 和 T. Gallai,Gráfok előírt fokú pontokkal,Matematikai Lapok 11, pp. 264–274 (1960)。https://users.renyi.hu/~p_erdos/1961-05.pdf

Z. Király,识别图形度序列并生成所有实现。TR-2011-11,Egerváry Research Group, H-1117, Budapest, Hungary. ISSN 1587-4451 (2012)。https://egres.elte.hu/tr/egres-11-11.pdf

B. Cloteaux,Is This for Real? Fast Graphicality Testing, Comput. Sci. Eng. 17, 91 (2015)。https://dx.doi.org/10.1109/MCSE.2015.125

A. Berger,关于双图序列的表征的说明,Discrete Math. 314, 38 (2014)。https://dx.doi.org/10.1016/j.disc.2013.09.010

G. Cairns 和 S. Mendan,具有循环的图的度序列 (2013)。https://arxiv.org/abs/1303.2145v1

参数: 

out_degrees:

一个整数向量,用于指定无向图的度序列或有向图的出度序列。

in_degrees:

一个整数向量,用于指定有向图的入度序列。对于无向图,它必须为 NULL

allowed_edge_types:

要在图中允许的边类型

IGRAPH_SIMPLE_SW

简单图(即不允许自环或多边)。

IGRAPH_LOOPS_SW

允许使用单个自环,但不允许使用多边。

IGRAPH_MULTI_SW

允许使用多边,但不允许使用自环。

IGRAPH_LOOPS_SW | IGRAPH_MULTI_SW

允许使用自环和多边。

res:

指向布尔值的指针。结果将存储在此处。

返回值: 

错误代码。

另请参阅: 

igraph_is_bigraphical() 可以检查双度序列是否可以实现为二分图;igraph_realize_degree_sequence() 可以构造具有给定度序列的图。

时间复杂度:O(n),其中 n 是度序列的长度。

9.2. igraph_is_bigraphical — 是否存在具有给定双度序列的二分图?

igraph_error_t igraph_is_bigraphical(const igraph_vector_int_t *degrees1,
                          const igraph_vector_int_t *degrees2,
                          const igraph_edge_type_sw_t allowed_edge_types,
                          igraph_bool_t *res);

确定两个整数序列是否可以是二分图的度序列。这种一对度序列被称为双图。

当允许使用多边时,足以检查两个分区中的度之和是否相同。对于简单图,Gale-Ryser 定理与 Berger 的松弛一起使用。

参考

H. J. Ryser,零和一矩阵的组合性质,Can. J. Math. 9, 371 (1957)。https://dx.doi.org/10.4153/cjm-1957-044-3

D. Gale,网络中流的定理,Pacific J. Math. 7, 1073 (1957)。https://dx.doi.org/10.2140/pjm.1957.7.1073

A. Berger,关于双图序列的表征的说明,Discrete Math. 314, 38 (2014)。https://dx.doi.org/10.1016/j.disc.2013.09.010

参数: 

degrees1:

一个整数向量,用于指定第一个分区中的度

degrees2:

一个整数向量,用于指定第二个分区中的度

allowed_edge_types:

要在图中允许的边类型

IGRAPH_SIMPLE_SW

简单图(即不允许使用多边)。

IGRAPH_MULTI_SW

允许使用多边。

res:

指向布尔值的指针。结果将存储在此处。

返回值: 

错误代码。

另请参阅: 

时间复杂度:O(n),其中 n 是较大度序列的长度。

10. 中心性度量

10.1. igraph_closeness — 某些顶点的紧密度中心性计算。

igraph_error_t igraph_closeness(const igraph_t *graph, igraph_vector_t *res,
                     igraph_vector_int_t *reachable_count, igraph_bool_t *all_reachable,
                     const igraph_vs_t vids, igraph_neimode_t mode,
                     const igraph_vector_t *weights,
                     igraph_bool_t normalized);

顶点的紧密度中心性衡量了其他顶点从该顶点可以轻松到达的程度(或者反过来:从其他顶点可以轻松到达该顶点的程度)。它被定义为到(或来自)所有其他顶点的平均距离的倒数。

紧密度中心性仅对连通图有意义。如果图未连通,则 igraph 计算到(或来自)所有可到达顶点的平均距离的倒数。在无向图中,这等效于在每个连通分量中分别计算紧密度。提供可选的 all_reachable 输出参数是为了帮助检测图何时断开连接。

虽然对于断开连接的图,紧密度中心性没有普遍采用的定义,但已经有一些尝试将该概念推广到断开连接的情况。一种类型的方法仅考虑到可到达顶点的平均距离,然后将获得的中心性分数重新缩放一个取决于可到达顶点数(即无向情况下的分量大小)的因子。为了便于计算紧密度中心性的这些泛化,可到达顶点数(不包括起始顶点)在 reachable_count 中返回。

在断开连接的图中,请考虑使用调和中心性,该中心性可以使用 igraph_harmonic_centrality() 计算。

对于孤立的顶点,即没有关联路径的顶点,将返回 NaN。

参数: 

:

图对象。

res:

计算结果,一个包含给定顶点的紧密度中心性分数的向量。

reachable_count:

如果不是 NULL,则此向量将包含从每个计算紧密度的顶点可以到达的顶点数(不包括该顶点)。

all_reachable:

指向布尔值的指针。如果不是 NULL,则指示图中的所有顶点是否都可以从 vids 中的每个顶点到达。如果为 false,则图为非连通图。如果为 true,并且图是无向图,或者如果图是有向图并且 vids 包含所有顶点,则该图是连通的。

vids:

将为其计算紧密度中心性的顶点。

模式:

用于计算有向图中最短路径的类型。 可能的值

IGRAPH_OUT

计算传出路径的长度。

IGRAPH_IN

计算传入路径的长度。

IGRAPH_ALL

在计算时,有向图被视为无向图。

weights:

一个可选向量,包含加权紧密度的边权重。不允许 NaN 值作为权重。在此处提供一个空指针以获得传统的未加权紧密度。

normalized:

如果为 true,则返回到可到达顶点的平均距离的倒数。如果为 false,则返回距离之和的倒数。

返回值: 

错误代码

IGRAPH_ENOMEM

临时数据没有足够的内存。

IGRAPH_EINVVID

传递了无效的顶点 ID。

IGRAPH_EINVMODE

无效的模式参数。

时间复杂度:未加权情况为 O(n|E|),加权情况为 O(n|E|log|V|+|V|),其中 n 是执行计算的顶点数,|V| 是顶点数,|E| 是图中边的数量。

另请参阅: 

其他中心性类型:igraph_degree(), igraph_betweenness(), igraph_harmonic_centrality()。有关范围有限的紧密度中心性,请参阅 igraph_closeness_cutoff()

10.2. igraph_harmonic_centrality — 某些顶点的调和中心性。

igraph_error_t igraph_harmonic_centrality(const igraph_t *graph, igraph_vector_t *res,
                               const igraph_vs_t vids, igraph_neimode_t mode,
                               const igraph_vector_t *weights,
                               igraph_bool_t normalized);

顶点的调和中心性是到所有其他顶点的平均逆距离。到不可达顶点的逆距离被认为是零。

参考

M. Marchiori 和 V. Latora,《小世界中的和谐》,Physica A 285,第 539-546 页 (2000)。https://doi.org/10.1016/S0378-4371%2800%2900311-3

Y. Rochat,《扩展到非连通图的紧密度中心性:调和中心性指标》,ASNA 2009。https://infoscience.epfl.ch/record/200525

S. Vigna 和 P. Boldi,《中心性的公理》,Internet Mathematics 10,(2014)。https://doi.org/10.1080/15427951.2013.865686

参数: 

:

图对象。

res:

计算结果,一个向量,包含给定顶点的调和中心性得分。

vids:

将为其计算调和中心性的顶点。

模式:

用于计算有向图中最短路径的类型。 可能的值

IGRAPH_OUT

计算传出路径的长度。

IGRAPH_IN

计算传入路径的长度。

IGRAPH_ALL

在计算时,有向图被视为无向图。

weights:

一个可选的向量,包含加权调和中心性的边权重。任何边权重都不能为 NaN。如果为 NULL,则所有权重都被认为是一。

normalized:

布尔值,是否对结果进行归一化。如果为真,则结果是到其他顶点的平均逆路径长度,即通过顶点数减一进行归一化。如果为假,则结果是到其他顶点的逆路径长度之和。

返回值: 

错误代码

IGRAPH_ENOMEM

临时数据没有足够的内存。

IGRAPH_EINVVID

传递了无效的顶点 ID。

IGRAPH_EINVMODE

无效的模式参数。

时间复杂度:对于未加权的情况为 O(n|E|),对于加权的情况为 O(n*|E|log|V|+|V|),其中 n 是执行计算的顶点数,|V| 是顶点数,|E| 是图中的边数。

另请参阅: 

10.3. igraph_betweenness — 一些顶点的介数中心性。

igraph_error_t igraph_betweenness(const igraph_t *graph, igraph_vector_t *res,
                       const igraph_vs_t vids, igraph_bool_t directed,
                       const igraph_vector_t* weights);

顶点的介数中心性是穿过它的测地线的数量。如果两个顶点之间存在多条测地线,则这些测地线的值将按测地线数量的倒数加权。

参考

Ulrik Brandes:一种更快的介数中心性算法。《数学社会学杂志》,25(2),163–177 (2001)。https://doi.org/10.1080/0022250X.2001.9990249

参数: 

:

图对象。

res:

计算结果,一个向量,包含指定顶点的介数中心性得分。

vids:

将计算介数中心性得分的顶点。

有向:

如果为真,对于有向图,将考虑有向路径。对于无向图,它将被忽略。

weights:

一个可选的向量,包含用于计算加权介数中心性的边权重。任何边权重都不能为 NaN。在此处提供一个空指针以进行未加权的介数中心性计算。

返回值: 

错误代码:IGRAPH_ENOMEM,临时数据内存不足。IGRAPH_EINVVID,在 vids 中传递了无效的顶点 ID。

时间复杂度:O(|V||E|),|V| 和 |E| 是图中的顶点数和边数。请注意,时间复杂度与计算得分的顶点数无关。

另请参阅: 

其他中心性类型:igraph_degree()igraph_closeness()。请参阅 igraph_edge_betweenness() 以计算图中边的介数中心性得分。请参阅 igraph_betweenness_cutoff() 以计算图中顶点的范围限制介数中心性。

10.4. igraph_edge_betweenness — 边的介数中心性。

igraph_error_t igraph_edge_betweenness(const igraph_t *graph, igraph_vector_t *result,
                            igraph_bool_t directed,
                            const igraph_vector_t *weights);

边的介数中心性是穿过它的测地线的数量。如果两个顶点之间存在多条测地线,则这些测地线的值将按测地线数量的倒数加权。

参考

Ulrik Brandes:一种更快的介数中心性算法。《数学社会学杂志》,25(2),163–177 (2001)。https://doi.org/10.1080/0022250X.2001.9990249

参数: 

:

图对象。

result:

计算结果,一个向量,包含边的介数中心性得分。

有向:

如果为真,对于有向图,将考虑有向路径。对于无向图,它将被忽略。

weights:

加权边介数中心性的可选权重向量。任何边权重都不能为 NaN。在此处提供一个空指针以获取未加权的版本。

返回值: 

错误代码:IGRAPH_ENOMEM,临时数据内存不足。

时间复杂度:O(|V||E|),|V| 和 |E| 是图中的顶点数和边数。

另请参阅: 

其他中心性类型:igraph_degree()igraph_closeness()。请参阅 igraph_edge_betweenness() 以计算图中边的介数中心性得分。请参阅 igraph_edge_betweenness_cutoff() 以计算图中边的范围限制介数中心性得分。

10.5. igraph_pagerank_algo_t — PageRank 算法实现。

typedef enum {
    IGRAPH_PAGERANK_ALGO_ARPACK = 1,
    IGRAPH_PAGERANK_ALGO_PRPACK = 2
} igraph_pagerank_algo_t;

用于计算 PageRank 的算法。

值: 

IGRAPH_PAGERANK_ALGO_ARPACK:

使用 ARPACK 库,这是从 igraph 版本 0.5 到 0.7 的 PageRank 实现。

IGRAPH_PAGERANK_ALGO_PRPACK:

使用 PRPACK 库。目前推荐使用此实现。

10.6. igraph_pagerank — 计算指定顶点的 Google PageRank。

igraph_error_t igraph_pagerank(const igraph_t *graph, igraph_pagerank_algo_t algo,
                    igraph_vector_t *vector,
                    igraph_real_t *value, const igraph_vs_t vids,
                    igraph_bool_t directed, igraph_real_t damping,
                    const igraph_vector_t *weights, igraph_arpack_options_t *options);

顶点的 PageRank 中心性是随机游走者遍历图在该顶点上花费的时间比例。游走者以与其权重成比例的概率沿着外向边行进。此外,在每个步骤中,它会以概率 1 - damping 从随机顶点重新开始游走。如果随机游走者被困在汇聚顶点中,它也会从随机顶点重新开始。

PageRank 中心性主要用于有向图。在无向图中,随着阻尼因子接近 1,它会收敛到与度成比例的平凡值。

从版本 0.9 开始,igraph 有两种 PageRank 实现,用户可以在它们之间进行选择。第一种实现是 IGRAPH_PAGERANK_ALGO_ARPACK,它将 PageRank 计算表示为特征值问题,然后使用 ARPACK 库解决该问题。这是 igraph 版本 0.7 之前的默认设置。第二种也是推荐的实现是 IGRAPH_PAGERANK_ALGO_PRPACK。它使用 PRPACK 包,请参阅 https://github.com/dgleich/prpack。PRPACK 使用代数方法,即求解线性系统以获得 PageRank 分数。

请注意,给定顶点的 PageRank 取决于所有其他顶点的 PageRank,因此即使您只想计算某些顶点的 PageRank,也必须计算所有顶点。仅请求某些顶点的 PageRank 不会导致任何性能提升。

参考

Sergey Brin 和 Larry Page:《大规模超文本网络搜索引擎的解剖》。第 7 届万维网会议论文集,澳大利亚布里斯班,1998 年 4 月。https://doi.org/10.1016/S0169-7552(98)00110-X

参数: 

:

图对象。

algo:

要使用的 PageRank 实现。可能的值:IGRAPH_PAGERANK_ALGO_ARPACKIGRAPH_PAGERANK_ALGO_PRPACK

vector:

指向已初始化向量的指针,结果存储在此处。根据需要调整大小。

value:

指向实变量的指针。使用 IGRAPH_PAGERANK_ALGO_ARPACK 时,与 PageRank 向量对应的特征值存储在此处。预计它恰好为 1。检查此值可用于诊断 ARPACK 未能收敛到主要特征向量的情况。使用 IGRAPH_PAGERANK_ALGO_PRPACK 时,此值始终设置为 1.0。

vids:

为其返回 PageRank 的顶点 ID。此参数仅为方便起见。计算少于所有顶点的 PageRank 不会加快计算速度。

有向:

布尔值,是否考虑边的方向。对于无向图,此值将被忽略。

damping:

阻尼因子(原始论文中的“d”)。必须是 [0, 1] 范围内的概率。常用的值是 0.85。

weights:

可选的边权重。可以是 NULL 指针,表示未加权的边,也可以是与边数相同长度的非负值的向量。

选项:

ARPACK 方法的选项。有关详细信息,请参阅 igraph_arpack_options_t。在此处提供 NULL 以使用默认值。请注意,该函数会覆盖 n(顶点数)、nev (1)、ncv (3) 和 which (LM) 参数,并且它始终从基于顶点度计算的非随机向量开始计算。

返回值: 

错误代码:IGRAPH_ENOMEM,临时数据内存不足。IGRAPH_EINVVIDvids 中的无效顶点 ID。

时间复杂度:取决于输入图,通常为 O(|E|),边的数量。

另请参阅: 

igraph_personalized_pagerank()igraph_personalized_pagerank_vs() 用于个性化的 PageRank 度量。请参阅 igraph_arpack_rssolve()igraph_arpack_rnsolve(),了解 IGRAPH_PAGERANK_ALGO_ARPACK 使用的基础机制。

示例 13.19. 文件 examples/simple/igraph_pagerank.c

#include <igraph.h>
#include <float.h>

int main(void) {
    igraph_t graph;
    igraph_vector_t pagerank;
    igraph_real_t value;

    /* Create a directed graph */
    igraph_kautz(&graph, 2, 3);

    /* Initialize the vector where the results will be stored */
    igraph_vector_init(&pagerank, 0);

    igraph_pagerank(&graph, IGRAPH_PAGERANK_ALGO_PRPACK,
                    &pagerank, &value,
                    igraph_vss_all(), IGRAPH_DIRECTED,
                    /* damping */ 0.85, /* weights */ NULL,
                    NULL /* not needed with PRPACK method */);

    /* Check that the eigenvalue is 1, as expected. */
    if (fabs(value - 1.0) > 32*DBL_EPSILON) {
        fprintf(stderr, "PageRank failed to converge.\n");
        return 1;
    }

    /* Output the result */
    igraph_vector_print(&pagerank);

    /* Destroy data structure when no longer needed */
    igraph_vector_destroy(&pagerank);
    igraph_destroy(&graph);

    return 0;
}


10.7. igraph_personalized_pagerank — 计算指定顶点的个性化 Google PageRank。

igraph_error_t igraph_personalized_pagerank(const igraph_t *graph,
                                 igraph_pagerank_algo_t algo, igraph_vector_t *vector,
                                 igraph_real_t *value, const igraph_vs_t vids,
                                 igraph_bool_t directed, igraph_real_t damping,
                                 const igraph_vector_t *reset,
                                 const igraph_vector_t *weights,
                                 igraph_arpack_options_t *options);

个性化 PageRank 与原始 PageRank 度量相似,但是当随机游走重新开始时,根据 reset 中指定的分布(而不是原始 PageRank 度量中的均匀分布)非均匀地选择新的起始顶点。当以概率 1 - damping 随机重新开始时,以及当游走者因被困在汇聚顶点(没有外向边的顶点)而被迫重新开始时,都会使用 reset 分布。

请注意,给定顶点的个性化 PageRank 取决于所有其他顶点的个性化 PageRank,因此即使您只想计算某些顶点的个性化 PageRank,也必须计算所有顶点。仅请求某些顶点的个性化 PageRank 不会导致任何性能提升。

参数: 

:

图对象。

algo:

要使用的 PageRank 实现。可能的值:IGRAPH_PAGERANK_ALGO_ARPACKIGRAPH_PAGERANK_ALGO_PRPACK

vector:

指向已初始化向量的指针,结果存储在此处。根据需要调整大小。

value:

指向实变量的指针。使用 IGRAPH_PAGERANK_ALGO_ARPACK 时,与 PageRank 向量对应的特征值存储在此处。预计它恰好为 1。检查此值可用于诊断 ARPACK 未能收敛到主要特征向量的情况。使用 IGRAPH_PAGERANK_ALGO_PRPACK 时,此值始终设置为 1.0。

vids:

为其返回 PageRank 的顶点 ID。此参数仅为方便起见。计算少于所有顶点的 PageRank 不会加快计算速度。

有向:

布尔值,是否考虑边的方向。对于无向图,此值将被忽略。

damping:

阻尼因子(原始论文中的“d”)。必须是 [0, 1] 范围内的概率。常用的值是 0.85。

reset:

在重置随机游走时使用的顶点上的概率分布。它要么是 NULL 指针(表示均匀选择,导致原始 PageRank 度量),要么是与顶点数相同长度的向量。

weights:

可选的边权重。可以是 NULL 指针,表示未加权的边,也可以是与边数相同长度的非负值的向量。

选项:

ARPACK 方法的选项。有关详细信息,请参阅 igraph_arpack_options_t。在此处提供 NULL 以使用默认值。请注意,该函数会覆盖 n(顶点数)、nev (1)、ncv (3) 和 which (LM) 参数,并且它始终从基于顶点度计算的非随机向量开始计算。

返回值: 

错误代码:IGRAPH_ENOMEM,临时数据内存不足。IGRAPH_EINVVIDvids 中的无效顶点 ID 或 reset 中的无效重置向量。

时间复杂度:取决于输入图,通常为 O(|E|),边的数量。

另请参阅: 

igraph_pagerank() 用于非个性化实现,igraph_personalized_pagerank_vs() 用于使用重置到特定顶点的个性化实现。

10.8. igraph_personalized_pagerank_vs — 计算指定顶点的个性化 Google PageRank。

igraph_error_t igraph_personalized_pagerank_vs(const igraph_t *graph,
                                    igraph_pagerank_algo_t algo, igraph_vector_t *vector,
                                    igraph_real_t *value, const igraph_vs_t vids,
                                    igraph_bool_t directed, igraph_real_t damping,
                                    igraph_vs_t reset_vids,
                                    const igraph_vector_t *weights,
                                    igraph_arpack_options_t *options);

个性化 PageRank 与原始 PageRank 度量相似,但是当随机游走重新开始时,根据指定的分布选择新的起始顶点。当以概率 1 - damping 随机重新开始时,以及当游走者因被困在汇聚顶点(没有外向边的顶点)而被迫重新开始时,都会使用此分布。

此简化的接口采用顶点序列,并将随机游走重置为指定顶点序列中的顶点之一,并统一选择。个性化 PageRank 的典型应用是每次将随机游走重置为同一顶点 - 这可以使用 igraph_vss_1() 轻松实现,该函数生成仅包含单个顶点的顶点序列。

请注意,给定顶点的个性化 PageRank 取决于所有其他顶点的个性化 PageRank,因此即使您只想计算某些顶点的个性化 PageRank,也必须计算所有顶点。仅请求某些顶点的个性化 PageRank 不会导致任何性能提升。

参数: 

:

图对象。

algo:

要使用的 PageRank 实现。可能的值:IGRAPH_PAGERANK_ALGO_ARPACKIGRAPH_PAGERANK_ALGO_PRPACK

vector:

指向已初始化向量的指针,结果存储在此处。根据需要调整大小。

value:

指向实变量的指针。使用 IGRAPH_PAGERANK_ALGO_ARPACK 时,与 PageRank 向量对应的特征值存储在此处。预计它恰好为 1。检查此值可用于诊断 ARPACK 未能收敛到主要特征向量的情况。使用 IGRAPH_PAGERANK_ALGO_PRPACK 时,此值始终设置为 1.0。

vids:

为其返回 PageRank 的顶点 ID。此参数仅为方便起见。计算少于所有顶点的 PageRank 不会加快计算速度。

有向:

布尔值,是否考虑边的方向。对于无向图,此值将被忽略。

damping:

阻尼因子(原始论文中的“d”)。必须是 [0, 1] 范围内的概率。常用的值是 0.85。

reset_vids:

重置随机游走时使用的顶点的 ID。

weights:

可选的边权重,它可以是一个空指针,在这种情况下,边未加权,或者是一个长度与边数相同的向量。

选项:

ARPACK 方法的选项。有关详细信息,请参阅 igraph_arpack_options_t。在此处提供 NULL 以使用默认值。请注意,该函数会覆盖 n(顶点数)、nev (1)、ncv (3) 和 which (LM) 参数,并且它始终从基于顶点度计算的非随机向量开始计算。

返回值: 

错误代码:IGRAPH_ENOMEM,临时数据内存不足。IGRAPH_EINVVIDvids 中的无效顶点 ID 或 vids_reset 中的空重置顶点序列。

时间复杂度:取决于输入图,通常为 O(|E|),边的数量。

另请参阅: 

igraph_pagerank() 用于非个性化实现。

10.9. igraph_constraint — Burt 的约束分数。

igraph_error_t igraph_constraint(const igraph_t *graph, igraph_vector_t *res,
                      igraph_vs_t vids, const igraph_vector_t *weights);

此函数计算给定顶点的 Burt 的约束分数,也称为结构洞。

如果自我拥有较少或相互之间更强的相关性(即更冗余)的联系,则 Burt 的约束更高。Burt 对顶点 i 的自我网络 V[i] 的约束度量 C[i] 定义为有向图和值图,

C[i] = sum( sum( (p[i,q] p[q,j])^2, q in V[i], q != i,j ), j in V[], j != i)

对于阶数(即顶点数)为 N 的图,其中比例联系强度定义为

p[i,j]=(a[i,j]+a[j,i]) / sum(a[i,k]+a[k,i], k in V[i], k != i),

a[i,j] 是 A 的元素,后者是图的邻接矩阵。对于孤立的顶点,约束未定义。

Burt, R.S. (2004)。结构洞和好主意。《美国社会学杂志》110, 349-399。

此函数的第一个 R 版本由 Jeroen Bruggeman 贡献。

参数: 

:

一个图对象。

res:

指向已初始化向量的指针,结果将存储在此处。向量将调整大小以具有适当的大小来保存结果。

vids:

包含应为其计算约束的顶点的顶点选择器。

weights:

给出边的权重的向量。如果为 NULL,则假定每条边都具有相同的权重。

返回值: 

错误代码。

时间复杂度:O(|V|+E|+n*d^2),n 是为其计算约束的顶点数,d 是平均度,|V| 是顶点数,|E| 是图中的边数。如果 weights 参数为 NULL,则时间复杂度为 O(|V|+n*d^2)。

10.10. igraph_maxdegree — 图(或顶点集)中的最大度。

igraph_error_t igraph_maxdegree(const igraph_t *graph, igraph_integer_t *res,
                     igraph_vs_t vids, igraph_neimode_t mode,
                     igraph_bool_t loops);

计算指定顶点的最大入度、出度或总度。如果图没有顶点,或者 vids 为空,则返回 0,因为这是度的最小可能值。

参数: 

:

输入图。

res:

指向整数 (igraph_integer_t) 的指针,结果将存储在此处。

vids:

给出将计算最大度的顶点 ID 的向量。

模式:

定义度的类型。IGRAPH_OUT,出度,IGRAPH_IN,入度,IGRAPH_ALL,总度(入度和出度之和)。对于无向图,此参数将被忽略。

循环:

布尔值,指示是否应计算自环。

返回值: 

错误代码:IGRAPH_EINVVID:无效的顶点 ID。IGRAPH_EINVMODE:无效的 mode 参数。

时间复杂度:如果 loopstrue,则为 O(v),否则为 O(v*d)。v 是将计算度的顶点数,d 是它们的(平均)度。

另请参阅: 

igraph_degree() 以检索多个顶点的度。

10.11. igraph_strength — 顶点的强度,也称为加权顶点度。

igraph_error_t igraph_strength(const igraph_t *graph, igraph_vector_t *res,
                    const igraph_vs_t vids, igraph_neimode_t mode,
                    igraph_bool_t loops, const igraph_vector_t *weights);

在加权网络中,顶点的强度是所有入射边的权重之和。在非加权网络中,这正是顶点度。

参数: 

:

输入图。

res:

指向已初始化向量的指针,结果存储在此处。根据需要调整大小。

vids:

为其执行计算的顶点。

模式:

指示是仅计算外向 (IGRAPH_OUT)、内向 (IGRAPH_IN) 边还是两者 (IGRAPH_ALL)。对于无向图,此参数将被忽略。

循环:

布尔值,是否也计算循环边。

weights:

给出边权重的向量。如果这是一个 NULL 指针,则调用 igraph_degree() 以执行计算。

返回值: 

错误代码。

时间复杂度:O(|V|+|E|),顶点数和边的数量的线性关系。

另请参阅: 

igraph_degree() 用于传统的非加权版本。

10.12. igraph_eigenvector_centrality — 顶点的特征向量中心性。

igraph_error_t igraph_eigenvector_centrality(const igraph_t *graph,
                                  igraph_vector_t *vector,
                                  igraph_real_t *value,
                                  igraph_bool_t directed, igraph_bool_t scale,
                                  const igraph_vector_t *weights,
                                  igraph_arpack_options_t *options);

特征向量中心性是一种衡量网络中节点重要性的指标。它根据来自高分节点的连接比来自低分节点的相等连接对相关节点的得分贡献更多的原则,为网络中的所有节点分配相对分数。具体来说,每个顶点的特征向量中心性与其邻居的特征向量中心性之和成正比。在实践中,中心性是通过计算与邻接矩阵的最大正特征值对应的特征向量来确定的。在无向情况下,此函数认为邻接矩阵的对角线条目是相应顶点上的自环数的 两倍

在加权情况下,顶点的特征向量中心性与其邻居的中心性的加权和成正比,即 c_j = sum_i w_ij c_i,其中 w_ij 是连接顶点 ij 的边的权重。并行边的权重相加。

igraph 返回的中心性分数可以归一化(使用 scale 参数),使得最大特征向量中心性分数为 1(一个例外,请参见下文)。

在有向图中,计算邻接矩阵的左特征向量。换句话说,一个顶点的中心性与指向它的顶点的中心性之和成正比。

特征向量中心性仅对(强)连通图有意义。未连接的无向图应分解为连通分量,并分别计算每个分量的特征向量中心性。分量之间的分数不具有可比性。此函数不验证图是否已连接。如果未连接,在无向情况下,除一个分量外的所有分量的分数将为零。

另请注意,有向无环图的邻接矩阵或空图的邻接矩阵不具有正特征值,因此特征向量中心性对这些图没有意义。在这种情况下,igraph 将返回特征值零。对于出度为零的顶点,返回的特征向量中心性将全部相等,对于其他顶点,返回的特征向量中心性将为零。可以通过要求 igraph 同时计算特征值(使用 value 参数,请参见下文)并检查特征值是否非常接近于零来检测此类病态情况。

处理有向图时,请考虑使用枢纽和权威分数,请参见 igraph_hub_and_authority_scores()

参数: 

:

输入图。它可以是有向的。

vector:

指向已初始化向量的指针,将根据需要调整大小。计算结果存储在此处。它可以是一个空指针,在这种情况下,它将被忽略。

value:

如果不是空指针,则与找到的特征向量对应的特征值将存储在此处。

有向:

布尔标量,指示是否考虑有向图中的边方向。对于无向图,此值将被忽略。

scale:

如果不为零,则将缩放结果,使得最大中心性的绝对值为 1。

weights:

空指针(表示没有边权重)或给出边权重的向量。权重应为正,以保证有意义的结果。当某些权重为负且图是有向的时,该算法可能会产生复数。在这种情况下,仅报告实部。

选项:

ARPACK 的选项。有关详细信息,请参阅 igraph_arpack_options_t。在此处提供 NULL 以使用默认值。请注意,该函数会覆盖 n(顶点数)参数,并且它始终从基于顶点度计算的非随机向量开始计算。

返回值: 

错误代码。

时间复杂度:取决于输入图,通常为 O(|V|+|E|)。

另请参阅: 

igraph_pagerankigraph_personalized_pagerank 用于修改特征向量中心性。igraph_hub_and_authority_scores() 用于有向图的类似度量对。

示例 13.20. 文件 examples/simple/eigenvector_centrality.c

#include <igraph.h>

int main(void) {

    igraph_t graph;
    igraph_vector_t vector, weights;
    igraph_real_t value;

    /* Create a star graph, with vertex 0 at the center, and associated edge weights. */
    igraph_star(&graph, 10, IGRAPH_STAR_UNDIRECTED, 0);
    igraph_vector_init_range(&weights, 1, igraph_ecount(&graph)+1);

    /* Initialize the vector where the result will be stored. */
    igraph_vector_init(&vector, 0);

    /* Compute eigenvector centrality. */
    igraph_eigenvector_centrality(&graph, &vector, &value, IGRAPH_UNDIRECTED,
                                  /*scale=*/ true, &weights, /*options=*/ NULL);

    /* Print results. */
    printf("eigenvalue: %g\n", value);
    printf("eigenvector:\n");
    igraph_vector_print(&vector);

    /* Free allocated data structures. */
    igraph_vector_destroy(&vector);
    igraph_vector_destroy(&weights);
    igraph_destroy(&graph);

    return 0;
}


10.13. igraph_hub_and_authority_scores — Kleinberg 的枢纽和权威分数 (HITS)。

igraph_error_t igraph_hub_and_authority_scores(const igraph_t *graph,
        igraph_vector_t *hub_vector, igraph_vector_t *authority_vector,
        igraph_real_t *value, igraph_bool_t scale,
        const igraph_vector_t *weights, igraph_arpack_options_t *options);

枢纽和权威分数是对有向图的特征向量中心性背后思想的推广。顶点的权威分数与其指向的顶点的枢纽分数之和成正比。相反,顶点的枢纽分数与其指向的顶点的权威分数之和成正比。这些概念也以超链接诱导主题搜索 (HITS) 的名称而闻名。

顶点的枢纽和权威分数分别定义为 A A^TA^T A 的主要特征向量,其中 A 是图的邻接矩阵,A^T 是其转置。

如果向量 ha 包含枢纽分数和权威分数,则两个分数通过 h = Aaa = A^T h 相关。当 A A^T 的主要特征值是简并的时,枢纽分数和权威分数问题没有唯一的解决方案。igraph 保证即使在这种情况下,返回的分数也是匹配的,即通过这些公式相关。

枢纽和权威分数的概念是为 有向 图开发的。在无向图中,枢纽分数和权威分数都等于特征向量中心性,可以使用 igraph_eigenvector_centrality() 计算。

请参阅以下有关此分数含义的参考文献:J. Kleinberg. 超链接环境中的权威来源。Proc. 第 9 届 ACM-SIAM 离散算法研讨会, 1998 年。扩展版本在 ACM 杂志 46(1999) 中。https://doi.org/10.1145/324133.324140 也以 IBM 研究报告 RJ 10076,1997 年 5 月的形式出现。

参数: 

:

输入图。可以是定向的也可以是非定向的。

hub_vector:

指向已初始化向量的指针,枢纽分数存储在此处。如果为空指针,则将被忽略。

authority_vector:

指向已初始化向量的指针,权威分数存储在此处。如果为空指针,则将被忽略。

value:

如果不是空指针,则与计算的特征向量对应的特征值将存储在此处。

scale:

如果不为零,则将缩放结果,使得最大中心性的绝对值为 1。

weights:

空指针(表示没有边权重)或给出边权重的向量。

选项:

ARPACK 的选项。有关详细信息,请参阅 igraph_arpack_options_t。在此处提供 NULL 以使用默认值。请注意,该函数会覆盖 n(顶点数)参数,并且它始终从基于顶点度计算的向量开始计算。

返回值: 

错误代码。

时间复杂度:取决于输入图,通常为 O(|V|),顶点的数量。

另请参阅: 

10.14. igraph_convergence_degree — 计算图中每条边的收敛度。

igraph_error_t igraph_convergence_degree(const igraph_t *graph, igraph_vector_t *result,
                              igraph_vector_t *ins, igraph_vector_t *outs);

让我们将边 (i, j) 的输入集定义为通过 (i, j) 的最短路径的起点的顶点集,类似地,让我们将边 (i, j) 的输出集定义为通过 (i, j) 的最短路径的终点的顶点集。边的收敛度定义为输入集的大小与输出集的大小之差的归一化值,即将它们之差除以它们之和。收敛度在 (-1, 1) 范围内;正值表示边是 收敛的,因为通过它的最短路径起源于较大的集合并终止于较小的集合,而负值表示边是 发散的,因为路径起源于小集合并终止于较大集合。

请注意,如上定义的收敛度在无向图中没有意义,因为输入集和输出集之间没有区别。因此,对于无向图,边的输入集和输出集是通过任意定向边,同时保持剩余的边无向,然后取收敛度的绝对值来确定的。

参数: 

:

输入图,它可以是有向的也可以是无向的。

result:

指向已初始化向量的指针;每条边的收敛度将存储在此处。如果我们对确切的收敛度不感兴趣,则可以为 NULL

ins:

指向已初始化向量的指针;每条边的输入集的大小将存储在此处。如果我们对输入集的大小不感兴趣,则可以为 NULL

outs:

指向已初始化向量的指针;每条边的输出集的大小将存储在此处。如果我们对输出集的大小不感兴趣,则可以为 NULL

返回值: 

错误代码。

时间复杂度:O(|V||E|),顶点数乘以边数。

11. 范围限制中心性度量

11.1. igraph_closeness_cutoff — 范围限制紧密度中心性。

igraph_error_t igraph_closeness_cutoff(const igraph_t *graph, igraph_vector_t *res,
                            igraph_vector_int_t *reachable_count, igraph_bool_t *all_reachable,
                            const igraph_vs_t vids, igraph_neimode_t mode,
                            const igraph_vector_t *weights,
                            igraph_bool_t normalized,
                            igraph_real_t cutoff);

此函数通过仅考虑长度不大于给定截止值的最短路径来计算紧密度中心性的范围限制版本。

参数: 

:

图对象。

res:

计算结果,一个向量,包含给定顶点的范围限制紧密度中心性得分。

reachable_count:

如果不是 NULL,则此向量将包含在截止距离内从为其计算范围限制紧密度的每个顶点可到达的顶点数(不包括该顶点)。

all_reachable:

指向布尔值的指针。如果不是 NULL,则指示是否可以从 vids 中的每个顶点在给定的截止距离内到达图的所有顶点。

vids:

将为其计算范围限制紧密度中心性的顶点。

模式:

用于计算有向图中最短路径的类型。 可能的值

IGRAPH_OUT

计算传出路径的长度。

IGRAPH_IN

计算传入路径的长度。

IGRAPH_ALL

在计算时,有向图被视为无向图。

weights:

包含加权紧密度中心性的可选边权重的向量。任何边权重都不能为 NaN。在此处提供一个空指针以获取传统的未加权紧密度中心性。

normalized:

如果为真,则返回可到达顶点的平均距离的倒数。如果为假,则返回距离总和的倒数。

cutoff:

将考虑的路径的最大长度。如果为负数,则将计算确切的紧密度中心性(对路径长度没有上限)。

返回值: 

错误代码

IGRAPH_ENOMEM

临时数据没有足够的内存。

IGRAPH_EINVVID

传递了无效的顶点 ID。

IGRAPH_EINVMODE

无效的模式参数。

时间复杂度:对于未加权的情况,最多为 O(n|E|),对于加权的情况,为 O(n|E|log|V|+|V|),其中 n 是执行计算的顶点数,|V| 是顶点数,|E| 是图中的边数。定时会随着较小的截止值而降低,降低方式取决于图结构。

另请参阅: 

igraph_closeness() 用于计算确切的紧密度中心性。

11.2. igraph_harmonic_centrality_cutoff — 范围限制调和中心性。

igraph_error_t igraph_harmonic_centrality_cutoff(const igraph_t *graph, igraph_vector_t *res,
                                      const igraph_vs_t vids, igraph_neimode_t mode,
                                      const igraph_vector_t *weights,
                                      igraph_bool_t normalized,
                                      igraph_real_t cutoff);

此函数计算调和中心性的范围限制版本:仅考虑长度不超过给定截止值的最短路径。到在截止值内不可到达的顶点的逆距离被认为是零。

参数: 

:

图对象。

res:

计算结果,一个向量,包含给定顶点的范围限制调和中心性得分。

vids:

将为其计算调和中心性的顶点。

模式:

用于计算有向图中最短路径的类型。 可能的值

IGRAPH_OUT

计算传出路径的长度。

IGRAPH_IN

计算传入路径的长度。

IGRAPH_ALL

在计算时,有向图被视为无向图。

weights:

一个可选的向量,包含加权调和中心性的边权重。任何边权重都不能为 NaN。如果为 NULL,则所有权重都被认为是一。

normalized:

布尔值,是否对结果进行归一化。如果为真,则结果是到其他顶点的平均逆路径长度。即通过顶点数减一进行归一化。如果为假,则结果是到其他顶点的逆路径长度之和。

cutoff:

将考虑的路径的最大长度。到在截止路径长度内不可到达的顶点的逆距离被认为是零。提供一个负值以计算确切的调和中心性,而对路径长度没有任何上限。

返回值: 

错误代码

IGRAPH_ENOMEM

临时数据没有足够的内存。

IGRAPH_EINVVID

传递了无效的顶点 ID。

IGRAPH_EINVMODE

无效的模式参数。

时间复杂度:对于未加权的情况,最多为 O(n|E|),对于加权的情况,为 O(n|E|log|V|+|V|),其中 n 是执行计算的顶点数,|V| 是顶点数,|E| 是图中的边数。定时会随着较小的截止值而降低,降低方式取决于图结构。

另请参阅: 

igraph_harmonic_centrality() 用于计算确切的调和中心性。其他中心性类型:igraph_closeness()igraph_betweenness()

11.3. igraph_betweenness_cutoff — 范围限制介数中心性。

igraph_error_t igraph_betweenness_cutoff(const igraph_t *graph, igraph_vector_t *res,
                              const igraph_vs_t vids, igraph_bool_t directed,
                              const igraph_vector_t *weights, igraph_real_t cutoff);

此函数通过仅考虑长度不大于给定截止值的最短路径来计算介数中心性的范围限制版本。

参数: 

:

图对象。

res:

计算结果,一个向量,包含指定顶点的范围限制介数得分。

vids:

将为其计算范围限制介数中心性得分的顶点。

有向:

如果为真,对于有向图,将考虑有向路径。对于无向图,它将被忽略。

weights:

一个可选的向量,包含用于计算加权介数中心性的边权重。任何边权重都不能为 NaN。在此处提供一个空指针以进行未加权的介数中心性计算。

cutoff:

将考虑的路径的最大长度。如果为负数,则将计算确切的介数中心性,并且对路径长度没有上限。

返回值: 

错误代码:IGRAPH_ENOMEM,临时数据内存不足。IGRAPH_EINVVID,在 vids 中传递了无效的顶点 ID。

时间复杂度:O(|V||E|),|V| 和 |E| 是图中的顶点数和边数。请注意,时间复杂度与计算得分的顶点数无关。

另请参阅: 

igraph_betweenness() 用于计算确切的介数中心性,igraph_edge_betweenness_cutoff() 用于计算范围限制边介数中心性。

11.4. igraph_edge_betweenness_cutoff — 边的范围限制中间中心性。

igraph_error_t igraph_edge_betweenness_cutoff(const igraph_t *graph, igraph_vector_t *result,
                                   igraph_bool_t directed,
                                   const igraph_vector_t *weights, igraph_real_t cutoff);

此函数计算边的中间中心性的范围限制版本,只考虑长度不大于给定截止值的最短路径。

参数: 

:

图对象。

result:

计算结果,一个向量,包含边的介数中心性得分。

有向:

如果为真,对于有向图,将考虑有向路径。对于无向图,它将被忽略。

weights:

一个可选的加权中间中心性的权重向量。边权重不能为 NaN。对于未加权的中间中心性,此处请提供空指针。

cutoff:

将被考虑的路径的最大长度。如果为负数,将计算精确的中间中心性(路径长度没有上限)。

返回值: 

错误代码:IGRAPH_ENOMEM,临时数据内存不足。

时间复杂度:O(|V||E|),|V| 和 |E| 是图中的顶点数和边数。

另请参阅: 

igraph_edge_betweenness() 一起计算精确的边中间中心性,以及与 igraph_betweenness_cutoff() 一起计算范围限制的顶点中间中心性。

12. 子集限制的中心性度量

12.1. igraph_betweenness_subset — 源和目标顶点子集的中间中心性。

igraph_error_t igraph_betweenness_subset(const igraph_t *graph, igraph_vector_t *res,
                              const igraph_vs_t vids, igraph_bool_t directed,
                              const igraph_vs_t sources, const igraph_vs_t targets,
                              const igraph_vector_t *weights);

此函数计算中间中心性的子集限制版本,只考虑位于给定源和目标子集中的顶点之间的最短路径。

参数: 

:

图对象。

res:

计算结果,一个包含顶点子集的中间中心性分数的向量。

vids:

将计算子集限制的中间中心性分数的顶点。

有向:

如果为真,对于有向图,将考虑有向路径。对于无向图,它将被忽略。

weights:

一个可选的向量,包含用于计算加权介数中心性的边权重。任何边权重都不能为 NaN。在此处提供一个空指针以进行未加权的介数中心性计算。

来源:

一个顶点选择器,用于选择中间中心性计算中考虑的最短路径的来源。

目标:

一个顶点选择器,用于选择中间中心性计算中考虑的最短路径的目标。

返回值: 

错误代码:IGRAPH_ENOMEM,临时数据内存不足。IGRAPH_EINVVID,在 vidssourcestargets 中传递了无效的顶点 ID。

时间复杂度:O(|S||E|),其中 |S| 是子集中顶点的数量,|E| 是图中的边的数量。

另请参阅: 

igraph_betweenness() 一起计算精确的顶点中间中心性,以及与 igraph_betweenness_cutoff() 一起计算范围限制的顶点中间中心性。

12.2. igraph_edge_betweenness_subset — 源和目标顶点子集的边中间中心性。

igraph_error_t igraph_edge_betweenness_subset(const igraph_t *graph, igraph_vector_t *res,
                                   const igraph_es_t eids, igraph_bool_t directed,
                                   const igraph_vs_t sources, const igraph_vs_t targets,
                                   const igraph_vector_t *weights);

此函数计算边中间中心性的子集限制版本,只考虑位于给定源和目标子集中的顶点之间的最短路径。

参数: 

:

图对象。

res:

计算结果,一个向量,包含边的介数中心性得分。

eids:

将计算子集限制的中间中心性分数的边。

有向:

如果为真,对于有向图,将考虑有向路径。对于无向图,它将被忽略。

weights:

一个可选的加权中间中心性的权重向量。边权重不能为 NaN。对于未加权的中间中心性,此处请提供空指针。

来源:

一个顶点选择器,用于选择中间中心性计算中考虑的最短路径的来源。

目标:

一个顶点选择器,用于选择中间中心性计算中考虑的最短路径的目标。

返回值: 

错误代码:IGRAPH_ENOMEM,临时数据内存不足。IGRAPH_EINVVID,在 sourcestargets 中传递了无效的顶点 ID。

时间复杂度:O(|S||E|),其中 |S| 是子集中顶点的数量,|E| 是图中的边的数量。

另请参阅: 

igraph_edge_betweenness() 一起计算精确的边中间中心性,以及与 igraph_edge_betweenness_cutoff() 一起计算范围限制的边中间中心性。

13. 集中化

13.1. igraph_centralization — 从节点级别分数计算集中化分数。

igraph_real_t igraph_centralization(const igraph_vector_t *scores,
                                    igraph_real_t theoretical_max,
                                    igraph_bool_t normalized);

对于在图的顶点上定义的中心性分数,可以通过计算与最大中心性分数的偏差之和来定义图级别的集中化索引。因此,图的集中化索引越高,结构越集中。

为了使不同大小的图具有可比性,集中化索引通常被归一化为零和一之间的数字,方法是将最集中结构的(未归一化的)集中化分数除以相同数量的顶点。

对于大多数中心性指标,最集中的结构是星图,一个中心连接到网络中的所有其他节点。根据图是否是有向的,是否允许环边等,存在一些差异。

如果给定了节点级别分数和理论最大值,此函数仅计算图级别索引。它由所有特定于度量的集中化函数调用。它使用以下计算

C = sum_v ((max_u c_u) - c_v)

其中 c 是在 scores 中传递的中心性分数。如果 normalizedtrue,则返回 C/theoretical_max

参数: 

分数:

一个包含节点级别中心性分数的向量。

theoretical_max:

具有相同顶点数量的最集中图的图级别中心性分数。仅当 normalized 设置为 true 时才使用。

normalized:

布尔值,是否通过除以提供的理论最大值来归一化集中化。

返回值: 

图级别索引。

另请参阅: 

时间复杂度:O(n),分数向量的长度。

示例 13.21.  文件 examples/simple/centralization.c

#include <igraph.h>

int main(void) {

    igraph_t graph;
    igraph_real_t cent;

    /* Create an undirected star graph, which is the most centralized graph
     * with several common centrality scores. */
    printf("undirected star graph:\n");
    igraph_star(&graph, 10, IGRAPH_STAR_UNDIRECTED, /*center=*/ 0);

    igraph_centralization_degree(&graph, /*res=*/ NULL,
                                 /*mode=*/ IGRAPH_ALL, IGRAPH_NO_LOOPS,
                                 &cent, /*theoretical_max=*/ NULL,
                                 /*normalized=*/ true);
    printf("degree centralization: %g\n", cent);

    igraph_centralization_betweenness(&graph, /*res=*/ NULL,
                                      IGRAPH_UNDIRECTED, &cent,
                                      /*theoretical_max=*/ NULL,
                                      /*normalized=*/ true);
    printf("betweenness centralization: %g\n", cent);


    igraph_centralization_closeness(&graph, /*res=*/ NULL,
                                    IGRAPH_ALL, &cent,
                                    /*theoretical_max=*/ NULL,
                                    /*normalized=*/ true);
    printf("closeness centralization: %g\n", cent);

    igraph_destroy(&graph);

    /* With eigenvector centrality, the most centralized structure is
     * a graph containing a single edge. */
    printf("\ngraph with single edge:\n");
    igraph_small(&graph, /*n=*/ 10, /*directed=*/ 0,
                 0,1, -1);

    igraph_centralization_eigenvector_centrality(
                &graph,
                /*vector=*/ NULL,
                /*value=*/ NULL,
                IGRAPH_DIRECTED,
                /*scale=*/ true,
                /*options=*/ NULL,
                &cent,
                /*theoretical_max=*/ NULL,
                /*normalized=*/ true);
    printf("eigenvector centralization: %g\n", cent);

    igraph_destroy(&graph);

    return 0;
}


13.2. igraph_centralization_degree — 计算顶点度数和图集中化。

igraph_error_t igraph_centralization_degree(const igraph_t *graph, igraph_vector_t *res,
                                 igraph_neimode_t mode, igraph_bool_t loops,
                                 igraph_real_t *centralization,
                                 igraph_real_t *theoretical_max,
                                 igraph_bool_t normalized);

此函数通过将其参数传递给 igraph_degree() 来计算顶点的度数;并通过调用 igraph_centralization() 基于结果计算图级别集中化索引。

参数: 

:

输入图。

res:

如果您需要节点级别的度数分数,则为一个向量,否则为空指针。

模式:

指定有向图的度数类型的常量。可能的值:IGRAPH_INIGRAPH_OUTIGRAPH_ALL。对于无向图,此参数将被忽略。

循环:

布尔值,在计算度数(和集中化)时是否考虑环边。

集中化:

指向实数的指针,集中化分数将放置在此处。

theoretical_max:

指向实数的指针或空指针。如果不是空指针,则具有相同数量顶点的图的理论最大图中心性分数将存储在此处。

normalized:

布尔值,是否计算归一化的集中化分数。有关如何进行归一化的信息,请参见 igraph_centralization()

返回值: 

错误代码。

另请参阅: 

时间复杂度:igraph_degree() 的复杂度加上 O(n),即查询的顶点数,用于计算集中化分数。

13.3. igraph_centralization_betweenness — 计算顶点中间中心性和图集中化。

igraph_error_t igraph_centralization_betweenness(const igraph_t *graph,
                                      igraph_vector_t *res,
                                      igraph_bool_t directed,
                                      igraph_real_t *centralization,
                                      igraph_real_t *theoretical_max,
                                      igraph_bool_t normalized);

此函数通过将其参数传递给 igraph_betweenness() 来计算顶点的中间中心性;并通过调用 igraph_centralization() 基于结果计算图级别集中化索引。

参数: 

:

输入图。

res:

如果您需要节点级别的中间中心性分数,则为一个向量,否则为空指针。

有向:

布尔值,在计算中间中心性时是否考虑有向路径。

集中化:

指向实数的指针,集中化分数将放置在此处。

theoretical_max:

指向实数的指针或空指针。如果不是空指针,则具有相同数量顶点的图的理论最大图中心性分数将存储在此处。

normalized:

布尔值,是否计算归一化的集中化分数。有关如何进行归一化的信息,请参见 igraph_centralization()

返回值: 

错误代码。

另请参阅: 

时间复杂度:igraph_betweenness() 的复杂度加上 O(n),即查询的顶点数,用于计算集中化分数。

13.4. igraph_centralization_closeness — 计算顶点接近中心性和图集中化。

igraph_error_t igraph_centralization_closeness(const igraph_t *graph,
                                    igraph_vector_t *res,
                                    igraph_neimode_t mode,
                                    igraph_real_t *centralization,
                                    igraph_real_t *theoretical_max,
                                    igraph_bool_t normalized);

此函数通过将其参数传递给 igraph_closeness() 来计算顶点的接近中心性;并通过调用 igraph_centralization() 基于结果计算图级别集中化索引。

参数: 

:

输入图。

res:

如果您需要节点级别的接近中心性分数,则为一个向量,否则为空指针。

模式:

指定有向图的接近中心性类型的常量。可能的值:IGRAPH_INIGRAPH_OUTIGRAPH_ALL。对于无向图,此参数将被忽略。有关更多信息,请参见 igraph_closeness() 中具有相同名称的参数。

集中化:

指向实数的指针,集中化分数将放置在此处。

theoretical_max:

指向实数的指针或空指针。如果不是空指针,则具有相同数量顶点的图的理论最大图中心性分数将存储在此处。

normalized:

布尔值,是否计算归一化的集中化分数。有关如何进行归一化的信息,请参见 igraph_centralization()

返回值: 

错误代码。

另请参阅: 

时间复杂度:igraph_closeness() 的复杂度加上 O(n),即查询的顶点数,用于计算集中化分数。

13.5. igraph_centralization_eigenvector_centrality — 计算特征向量中心性分数和图集中化。

igraph_error_t igraph_centralization_eigenvector_centrality(
    const igraph_t *graph,
    igraph_vector_t *vector,
    igraph_real_t *value,
    igraph_bool_t directed,
    igraph_bool_t scale,
    igraph_arpack_options_t *options,
    igraph_real_t *centralization,
    igraph_real_t *theoretical_max,
    igraph_bool_t normalized);

此函数通过将其参数传递给 igraph_eigenvector_centrality) 来计算顶点的特征向量中心性;并通过调用 igraph_centralization() 基于结果计算图级别集中化索引。

请注意,顶点级别特征向量中心性分数没有自然尺度。与任何特征向量一样,它们的解释对于按常数因子缩放是不变的。但是,由于图级别的 集中化 的定义方式,其值取决于用于顶点级别分数的特定尺度/归一化。哪个图具有更高的特征向量 集中化 取决于中心性的归一化选择。此函数使用按其最大值缩放顶点级别中心性分数的特定选择(即,它使用 ∞-范数)。其他归一化选择,例如 1-范数或 2-范数,目前尚未实现。

参数: 

:

输入图。

vector:

如果您需要节点级别的特征向量中心性分数,则为一个向量,否则为空指针。

value:

如果不是空指针,则此处存储主导特征值。

scale:

自 igraph 0.10.14 以来,此参数已弃用并忽略。顶点级别中心性分数始终缩放为最大值为 1。

选项:

ARPACK 的选项。有关详细信息,请参见 igraph_arpack_options_t。请注意,该函数会覆盖 n(顶点数)参数,并且始终从基于顶点度数计算的非随机向量开始计算。

集中化:

指向实数的指针,集中化分数将放置在此处。

theoretical_max:

指向实数的指针或空指针。如果不是空指针,则具有相同数量顶点的图的理论最大图中心性分数将存储在此处。

normalized:

布尔值,是否计算归一化的集中化分数。有关如何进行归一化的信息,请参见 igraph_centralization()

返回值: 

错误代码。

另请参阅: 

时间复杂度:igraph_eigenvector_centrality() 的复杂度加上 O(|V|),即计算集中化的顶点数。

13.6. igraph_centralization_degree_tmax — 基于度数的图集中化的理论最大值。

igraph_error_t igraph_centralization_degree_tmax(const igraph_t *graph,
                                      igraph_integer_t nodes,
                                      igraph_neimode_t mode,
                                      igraph_bool_t loops,
                                      igraph_real_t *res);

此函数返回基于顶点度数的理论最大图中心性。

有两种方法可以调用此函数,第一种是将图作为 graph 参数提供,然后从该对象中获取顶点数,并且还会考虑其方向性。在这种情况下,nodes 参数将被忽略。如果提供的图是无向图,则 mode 参数也将被忽略。

另一种方法是将空指针作为 graph 参数提供。在这种情况下,将考虑 nodesmode 参数。

最集中的结构是星形。更具体地说,对于无向图,它是星形,对于有向图,它是入星形或出星形。

参数: 

:

图对象或空指针,请参见上面的描述。

节点:

节点数。如果 graph 参数不是空指针,则忽略此参数。

模式:

常量,计算是基于入度 (IGRAPH_IN)、出度 (IGRAPH_OUT) 还是总度 (IGRAPH_ALL)。如果 graph 参数不是空指针且给定的图是无向图,则忽略此参数。

循环:

布尔值,在计算中是否考虑环边。

res:

指向实变量的指针,结果存储在此处。

返回值: 

错误代码。

时间复杂度:O(1)。

另请参阅: 

13.7. igraph_centralization_betweenness_tmax — 基于中间中心性的图集中化的理论最大值。

igraph_error_t igraph_centralization_betweenness_tmax(const igraph_t *graph,
        igraph_integer_t nodes,
        igraph_bool_t directed,
        igraph_real_t *res);

此函数返回基于顶点中间中心性的理论最大图中心性。

有两种方法可以调用此函数,第一种是将图作为 graph 参数提供,然后从该对象中获取顶点数,并且还会考虑其方向性。在这种情况下,nodes 参数将被忽略。如果提供的图是无向图,则 directed 参数也将被忽略。

另一种方法是将空指针作为 graph 参数提供。在这种情况下,将考虑 nodesdirected 参数。

最集中的结构是星形。

参数: 

:

图对象或空指针,请参见上面的描述。

节点:

节点数。如果 graph 参数不是空指针,则忽略此参数。

有向:

布尔值,在中间中心性计算中是否使用有向路径。如果 graph 不是空指针且它是无向图,则忽略此参数。

res:

指向实变量的指针,结果存储在此处。

返回值: 

错误代码。

时间复杂度:O(1)。

另请参阅: 

13.8. igraph_centralization_closeness_tmax — 基于接近中心性的图集中化的理论最大值。

igraph_error_t igraph_centralization_closeness_tmax(const igraph_t *graph,
        igraph_integer_t nodes,
        igraph_neimode_t mode,
        igraph_real_t *res);

此函数返回基于顶点接近中心性的理论最大图中心性。

有两种方法可以调用此函数,第一种是将图作为 graph 参数提供,然后从该对象中获取顶点数,并且还会考虑其方向性。在这种情况下,nodes 参数将被忽略。如果提供的图是无向图,则 mode 参数也将被忽略。

另一种方法是将空指针作为 graph 参数提供。在这种情况下,将考虑 nodesmode 参数。

最集中的结构是星形。

参数: 

:

图对象或空指针,请参见上面的描述。

节点:

节点数。如果 graph 参数不是空指针,则忽略此参数。

模式:

常量,指定计算接近中心性时要考虑的距离类型。有关详细信息,请参见 igraph_closeness()mode 参数。如果 graph 不是空指针且它是无向图,则忽略此参数。

res:

指向实变量的指针,结果存储在此处。

返回值: 

错误代码。

时间复杂度:O(1)。

另请参阅: 

13.9. igraph_centralization_eigenvector_centrality_tmax — 特征向量中心性的理论最大集中化。

igraph_error_t igraph_centralization_eigenvector_centrality_tmax(
    const igraph_t *graph,
    igraph_integer_t nodes,
    igraph_bool_t directed,
    igraph_bool_t scale,
    igraph_real_t *res);

此函数返回基于顶点特征向量中心性的理论最大图中心性。

有两种方法可以调用此函数,第一种是将图作为 graph 参数提供,然后从该对象中获取顶点数,并且还会考虑其方向性。在这种情况下,nodes 参数将被忽略。如果提供的图是无向图,则 directed 参数也将被忽略。

另一种方法是将空指针作为 graph 参数提供。在这种情况下,将考虑 nodesdirected 参数。

最集中的有向结构被假定为入星形。最集中的无向结构被假定为具有单条边的图。出于历史原因,igraph 继续实现这些选择。请记住,这两种结构都不是连通的,这使得它们在特征向量中心性计算中的使用存在争议。特征向量中心性对于非连通结构不是唯一定义的。

请注意,顶点级别特征向量中心性分数没有自然尺度。与任何特征向量一样,它们的解释对于按常数因子缩放是不变的。但是,由于图级别的 集中化 的定义方式,其值取决于用于顶点级别分数的特定尺度/归一化。此外,哪个图具有更高的特征向量 集中化 也取决于中心性的归一化选择。此函数使用按其最大值缩放顶点级别中心性分数的特定选择(即,它使用 ∞-范数)。其他归一化选择,例如 1-范数或 2-范数,目前尚未实现。

参数: 

:

图对象或空指针,请参见上面的描述。

节点:

节点数。如果 graph 参数不是空指针,则忽略此参数。

有向:

布尔值,是否考虑边方向。如果 graph 不是空指针且它是无向图,则忽略此参数。

scale:

自 igraph 0.10.14 以来,此参数已弃用并忽略。顶点级别中心性分数始终假定缩放为最大值为 1。

res:

指向实变量的指针,结果存储在此处。

返回值: 

错误代码。

时间复杂度:O(1)。

另请参阅: 

14. 相似性度量

14.1. igraph_bibcoupling — 文献耦合。

igraph_error_t igraph_bibcoupling(const igraph_t *graph, igraph_matrix_t *res,
                       const igraph_vs_t vids);

两个顶点的文献耦合是它们都引用的其他顶点的数量,igraph_bibcoupling() 计算此数量。将计算每个给定顶点和图中所有其他顶点的文献耦合分数。

参数: 

:

要分析的图对象。

res:

指向矩阵的指针,计算结果将存储在此处。其行数与 vids 中的顶点 ID 数相同,列数是图中的顶点数。

vids:

将为其完成计算的顶点的顶点 ID。

返回值: 

错误代码:IGRAPH_EINVVID:无效的顶点 ID。

时间复杂度:O(|V|d^2),|V| 是图中的顶点数,d 是图中顶点(最大)度数。

另请参阅: 

示例 13.22.  文件 examples/simple/igraph_cocitation.c

#include <igraph.h>
#include <stdio.h>

int main(void) {
    igraph_t graph;
    igraph_matrix_t matrix;

    /* Create a small test graph. */
    igraph_small(&graph, 0, IGRAPH_DIRECTED,
                 0, 1, 2, 1, 2, 0, 3, 0,
                 -1);

    /* As usual with igraph functions, the data structure in which the result
       will be returned must be initialized in advance. */
    igraph_matrix_init(&matrix, 0, 0);
    igraph_bibcoupling(&graph, &matrix, igraph_vss_all());
    printf("Bibliographic coupling matrix:\n");
    igraph_matrix_print(&matrix);

    igraph_cocitation(&graph, &matrix, igraph_vss_all());
    printf("\nCocitation matrix:\n");
    igraph_matrix_print(&matrix);

    /* Destroy data structures when we are done with them. */
    igraph_matrix_destroy(&matrix);
    igraph_destroy(&graph);

    return 0;
}


14.2. igraph_cocitation — 同被引耦合。

igraph_error_t igraph_cocitation(const igraph_t *graph, igraph_matrix_t *res,
                      const igraph_vs_t vids);

如果存在另一个顶点同时引用两个顶点,则这两个顶点是同被引的。igraph_cocitation() 简单地计算两个顶点被同被引的次数。将计算每个给定顶点和图中所有其他顶点的同被引分数。

参数: 

:

要分析的图对象。

res:

指向矩阵的指针,计算结果将存储在此处。其行数与 vids 中的顶点 ID 数相同,列数是图中的顶点数。

vids:

将为其完成计算的顶点的顶点 ID。

返回值: 

错误代码:IGRAPH_EINVVID:无效的顶点 ID。

时间复杂度:O(|V|d^2),|V| 是图中的顶点数,d 是图中顶点(最大)度数。

另请参阅: 

示例 13.23.  文件 examples/simple/igraph_cocitation.c

#include <igraph.h>
#include <stdio.h>

int main(void) {
    igraph_t graph;
    igraph_matrix_t matrix;

    /* Create a small test graph. */
    igraph_small(&graph, 0, IGRAPH_DIRECTED,
                 0, 1, 2, 1, 2, 0, 3, 0,
                 -1);

    /* As usual with igraph functions, the data structure in which the result
       will be returned must be initialized in advance. */
    igraph_matrix_init(&matrix, 0, 0);
    igraph_bibcoupling(&graph, &matrix, igraph_vss_all());
    printf("Bibliographic coupling matrix:\n");
    igraph_matrix_print(&matrix);

    igraph_cocitation(&graph, &matrix, igraph_vss_all());
    printf("\nCocitation matrix:\n");
    igraph_matrix_print(&matrix);

    /* Destroy data structures when we are done with them. */
    igraph_matrix_destroy(&matrix);
    igraph_destroy(&graph);

    return 0;
}


14.3. igraph_similarity_jaccard — 给定顶点的 Jaccard 相似性系数。

igraph_error_t igraph_similarity_jaccard(const igraph_t *graph, igraph_matrix_t *res,
                              const igraph_vs_t vids, igraph_neimode_t mode, igraph_bool_t loops);

两个顶点的 Jaccard 相似性系数是公共邻居的数量除以至少两个顶点之一的邻居的顶点数量。此函数计算某些(或所有)顶点的成对 Jaccard 相似性。

参数: 

:

要分析的图对象

res:

指向矩阵的指针,计算结果将存储在此处。其行数和列数与 vids 中的顶点 ID 数相同。

vids:

将为其完成计算的顶点的顶点 ID。

模式:

用于有向图中计算的邻居类型。可能的值

IGRAPH_OUT

对于每个节点,将考虑出边。

IGRAPH_IN

对于每个节点,将考虑入边。

IGRAPH_ALL

在计算时,有向图被视为无向图。

循环:

是否将顶点本身包含在邻居集中。

返回值: 

错误代码

IGRAPH_ENOMEM

临时数据没有足够的内存。

IGRAPH_EINVVID

传递了无效的顶点 ID。

IGRAPH_EINVMODE

无效的模式参数。

时间复杂度:O(|V|^2 d),|V| 是给定顶点迭代器中的顶点数,d 是图中顶点(最大)度数。

另请参阅: 

igraph_similarity_dice(),一种与 Jaccard 系数非常相似的度量

示例 13.24.  文件 examples/simple/igraph_similarity.c

#include <igraph.h>

int main(void) {

    igraph_t g;
    igraph_matrix_t m;
    igraph_vector_int_t pairs;
    igraph_vector_t res;
    igraph_integer_t i, j, n;

    igraph_small(&g, 0, IGRAPH_DIRECTED,
                 0, 1, 2, 1, 2, 0, 3, 0,
                 -1);

    igraph_matrix_init(&m, 0, 0);
    igraph_vector_init(&res, 0);
    igraph_vector_int_init(&pairs, 0);

    n = igraph_vcount(&g);
    for (i = 0; i < n; i++) {
        for (j = n - 1; j >= 0; j--) {
            igraph_vector_int_push_back(&pairs, i);
            igraph_vector_int_push_back(&pairs, j);
        }
    }

    printf("Jaccard similarity:\n");
    igraph_similarity_jaccard(&g, &m, igraph_vss_range(1, 3), IGRAPH_ALL, 0);
    igraph_matrix_printf(&m, "%.2f");

    printf("\nJaccard similarity, pairs:\n");
    igraph_similarity_jaccard_pairs(&g, &res, &pairs, IGRAPH_ALL, 0);
    igraph_vector_print(&res);

    printf("\nJaccard similarity with edge selector:\n");
    igraph_similarity_jaccard_es(&g, &res, igraph_ess_all(IGRAPH_EDGEORDER_FROM), IGRAPH_IN, 0);
    igraph_vector_print(&res);

    printf("\nDice similarity:\n");
    igraph_similarity_dice(&g, &m, igraph_vss_range(1, 3), IGRAPH_ALL, 0);
    igraph_matrix_printf(&m, "%.2f");

    printf("\nDice similarity, pairs:\n");
    igraph_similarity_dice_pairs(&g, &res, &pairs, IGRAPH_ALL, 0);
    igraph_vector_print(&res);

    printf("\nDice similarity with edge selector:\n");
    igraph_similarity_dice_es(&g, &res, igraph_ess_all(IGRAPH_EDGEORDER_FROM), IGRAPH_IN, 0);
    igraph_vector_print(&res);

    printf("\nWeighted inverse log similarity:\n");
    igraph_similarity_inverse_log_weighted(&g, &m, igraph_vss_all(), IGRAPH_ALL);
    igraph_matrix_printf(&m, "%.2f");

    igraph_matrix_destroy(&m);
    igraph_destroy(&g);
    igraph_vector_destroy(&res);
    igraph_vector_int_destroy(&pairs);

    return 0;
}


14.4. igraph_similarity_jaccard_pairs — 给定顶点对的 Jaccard 相似性系数。

igraph_error_t igraph_similarity_jaccard_pairs(const igraph_t *graph, igraph_vector_t *res,
                                    const igraph_vector_int_t *pairs, igraph_neimode_t mode, igraph_bool_t loops);

两个顶点的 Jaccard 相似性系数是公共邻居的数量除以至少两个顶点之一的邻居的顶点数量。此函数计算顶点对列表的成对 Jaccard 相似性。

参数: 

:

要分析的图对象

res:

指向向量的指针,计算结果将存储在此处。元素数与 pairs 中的对数相同。

:

一个向量,包含将为其计算相似性的对。每对由两个连续元素定义,即,向量的第一个和第二个元素指定第一对,第三个和第四个元素指定第二对,依此类推。

模式:

用于有向图中计算的邻居类型。可能的值

IGRAPH_OUT

对于每个节点,将考虑出边。

IGRAPH_IN

对于每个节点,将考虑入边。

IGRAPH_ALL

在计算时,有向图被视为无向图。

循环:

是否将顶点本身包含在邻居集中。

返回值: 

错误代码

IGRAPH_ENOMEM

临时数据没有足够的内存。

IGRAPH_EINVVID

传递了无效的顶点 ID。

IGRAPH_EINVMODE

无效的模式参数。

时间复杂度:O(nd),n 是给定向量中的对数,d 是图中顶点的(最大)度数。

另请参阅: 

使用 igraph_similarity_jaccard() 计算顶点集的所有对之间的 Jaccard 相似性,或使用 igraph_similarity_dice()igraph_similarity_dice_pairs() 来进行与 Jaccard 系数非常相似的度量

示例 13.25.  文件 examples/simple/igraph_similarity.c

#include <igraph.h>

int main(void) {

    igraph_t g;
    igraph_matrix_t m;
    igraph_vector_int_t pairs;
    igraph_vector_t res;
    igraph_integer_t i, j, n;

    igraph_small(&g, 0, IGRAPH_DIRECTED,
                 0, 1, 2, 1, 2, 0, 3, 0,
                 -1);

    igraph_matrix_init(&m, 0, 0);
    igraph_vector_init(&res, 0);
    igraph_vector_int_init(&pairs, 0);

    n = igraph_vcount(&g);
    for (i = 0; i < n; i++) {
        for (j = n - 1; j >= 0; j--) {
            igraph_vector_int_push_back(&pairs, i);
            igraph_vector_int_push_back(&pairs, j);
        }
    }

    printf("Jaccard similarity:\n");
    igraph_similarity_jaccard(&g, &m, igraph_vss_range(1, 3), IGRAPH_ALL, 0);
    igraph_matrix_printf(&m, "%.2f");

    printf("\nJaccard similarity, pairs:\n");
    igraph_similarity_jaccard_pairs(&g, &res, &pairs, IGRAPH_ALL, 0);
    igraph_vector_print(&res);

    printf("\nJaccard similarity with edge selector:\n");
    igraph_similarity_jaccard_es(&g, &res, igraph_ess_all(IGRAPH_EDGEORDER_FROM), IGRAPH_IN, 0);
    igraph_vector_print(&res);

    printf("\nDice similarity:\n");
    igraph_similarity_dice(&g, &m, igraph_vss_range(1, 3), IGRAPH_ALL, 0);
    igraph_matrix_printf(&m, "%.2f");

    printf("\nDice similarity, pairs:\n");
    igraph_similarity_dice_pairs(&g, &res, &pairs, IGRAPH_ALL, 0);
    igraph_vector_print(&res);

    printf("\nDice similarity with edge selector:\n");
    igraph_similarity_dice_es(&g, &res, igraph_ess_all(IGRAPH_EDGEORDER_FROM), IGRAPH_IN, 0);
    igraph_vector_print(&res);

    printf("\nWeighted inverse log similarity:\n");
    igraph_similarity_inverse_log_weighted(&g, &m, igraph_vss_all(), IGRAPH_ALL);
    igraph_matrix_printf(&m, "%.2f");

    igraph_matrix_destroy(&m);
    igraph_destroy(&g);
    igraph_vector_destroy(&res);
    igraph_vector_int_destroy(&pairs);

    return 0;
}


14.5. igraph_similarity_jaccard_es — 给定边选择器的 Jaccard 相似性系数。

igraph_error_t igraph_similarity_jaccard_es(const igraph_t *graph, igraph_vector_t *res,
                                 const igraph_es_t es, igraph_neimode_t mode, igraph_bool_t loops);

两个顶点的 Jaccard 相似性系数是公共邻居的数量除以至少两个顶点之一的邻居的顶点数量。此函数计算给定边选择器中边的端点的成对 Jaccard 相似性。

参数: 

:

要分析的图对象

res:

指向向量的指针,计算结果将存储在此处。元素数与 es 中的边数相同。

es:

一个边选择器,用于指定结果中要包含的边。

模式:

用于有向图中计算的邻居类型。可能的值

IGRAPH_OUT

对于每个节点,将考虑出边。

IGRAPH_IN

对于每个节点,将考虑入边。

IGRAPH_ALL

在计算时,有向图被视为无向图。

循环:

是否将顶点本身包含在邻居集中。

返回值: 

错误代码

IGRAPH_ENOMEM

临时数据没有足够的内存。

IGRAPH_EINVVID

传递了无效的顶点 ID。

IGRAPH_EINVMODE

无效的模式参数。

时间复杂度:O(nd),n 是边选择器中的边数,d 是图中顶点的(最大)度数。

另请参阅: 

使用 igraph_similarity_jaccard()igraph_similarity_jaccard_pairs() 计算顶点集的所有对之间或一些选定顶点对之间的 Jaccard 相似性,或使用 igraph_similarity_dice()igraph_similarity_dice_pairs()igraph_similarity_dice_es() 来进行与 Jaccard 系数非常相似的度量

示例 13.26.  文件 examples/simple/igraph_similarity.c

#include <igraph.h>

int main(void) {

    igraph_t g;
    igraph_matrix_t m;
    igraph_vector_int_t pairs;
    igraph_vector_t res;
    igraph_integer_t i, j, n;

    igraph_small(&g, 0, IGRAPH_DIRECTED,
                 0, 1, 2, 1, 2, 0, 3, 0,
                 -1);

    igraph_matrix_init(&m, 0, 0);
    igraph_vector_init(&res, 0);
    igraph_vector_int_init(&pairs, 0);

    n = igraph_vcount(&g);
    for (i = 0; i < n; i++) {
        for (j = n - 1; j >= 0; j--) {
            igraph_vector_int_push_back(&pairs, i);
            igraph_vector_int_push_back(&pairs, j);
        }
    }

    printf("Jaccard similarity:\n");
    igraph_similarity_jaccard(&g, &m, igraph_vss_range(1, 3), IGRAPH_ALL, 0);
    igraph_matrix_printf(&m, "%.2f");

    printf("\nJaccard similarity, pairs:\n");
    igraph_similarity_jaccard_pairs(&g, &res, &pairs, IGRAPH_ALL, 0);
    igraph_vector_print(&res);

    printf("\nJaccard similarity with edge selector:\n");
    igraph_similarity_jaccard_es(&g, &res, igraph_ess_all(IGRAPH_EDGEORDER_FROM), IGRAPH_IN, 0);
    igraph_vector_print(&res);

    printf("\nDice similarity:\n");
    igraph_similarity_dice(&g, &m, igraph_vss_range(1, 3), IGRAPH_ALL, 0);
    igraph_matrix_printf(&m, "%.2f");

    printf("\nDice similarity, pairs:\n");
    igraph_similarity_dice_pairs(&g, &res, &pairs, IGRAPH_ALL, 0);
    igraph_vector_print(&res);

    printf("\nDice similarity with edge selector:\n");
    igraph_similarity_dice_es(&g, &res, igraph_ess_all(IGRAPH_EDGEORDER_FROM), IGRAPH_IN, 0);
    igraph_vector_print(&res);

    printf("\nWeighted inverse log similarity:\n");
    igraph_similarity_inverse_log_weighted(&g, &m, igraph_vss_all(), IGRAPH_ALL);
    igraph_matrix_printf(&m, "%.2f");

    igraph_matrix_destroy(&m);
    igraph_destroy(&g);
    igraph_vector_destroy(&res);
    igraph_vector_int_destroy(&pairs);

    return 0;
}


14.6. igraph_similarity_dice — Dice 相似性系数。

igraph_error_t igraph_similarity_dice(const igraph_t *graph, igraph_matrix_t *res,
                                      const igraph_vs_t vids,
                                      igraph_neimode_t mode, igraph_bool_t loops);

两个顶点的 Dice 相似性系数是公共邻居数量的两倍除以顶点的度数之和。此函数计算某些(或所有)顶点的成对 Dice 相似性。

参数: 

:

要分析的图对象。

res:

指向矩阵的指针,计算结果将存储在此处。其行数和列数与 vids 中的顶点 ID 数相同。

vids:

将为其完成计算的顶点的顶点 ID。

模式:

用于有向图中计算的邻居类型。可能的值

IGRAPH_OUT

对于每个节点,将考虑出边。

IGRAPH_IN

对于每个节点,将考虑入边。

IGRAPH_ALL

在计算时,有向图被视为无向图。

循环:

是否将顶点本身作为自己的邻居包含在内。

返回值: 

错误代码

IGRAPH_ENOMEM

临时数据没有足够的内存。

IGRAPH_EINVVID

传递了无效的顶点 ID。

IGRAPH_EINVMODE

无效的模式参数。

时间复杂度:O(|V|^2 d),其中 |V| 是给定顶点迭代器中的顶点数,d 是图中顶点的(最大)度数。

另请参阅: 

igraph_similarity_jaccard(),一种与 Dice 系数非常相似的度量

示例 13.27.  文件 examples/simple/igraph_similarity.c

#include <igraph.h>

int main(void) {

    igraph_t g;
    igraph_matrix_t m;
    igraph_vector_int_t pairs;
    igraph_vector_t res;
    igraph_integer_t i, j, n;

    igraph_small(&g, 0, IGRAPH_DIRECTED,
                 0, 1, 2, 1, 2, 0, 3, 0,
                 -1);

    igraph_matrix_init(&m, 0, 0);
    igraph_vector_init(&res, 0);
    igraph_vector_int_init(&pairs, 0);

    n = igraph_vcount(&g);
    for (i = 0; i < n; i++) {
        for (j = n - 1; j >= 0; j--) {
            igraph_vector_int_push_back(&pairs, i);
            igraph_vector_int_push_back(&pairs, j);
        }
    }

    printf("Jaccard similarity:\n");
    igraph_similarity_jaccard(&g, &m, igraph_vss_range(1, 3), IGRAPH_ALL, 0);
    igraph_matrix_printf(&m, "%.2f");

    printf("\nJaccard similarity, pairs:\n");
    igraph_similarity_jaccard_pairs(&g, &res, &pairs, IGRAPH_ALL, 0);
    igraph_vector_print(&res);

    printf("\nJaccard similarity with edge selector:\n");
    igraph_similarity_jaccard_es(&g, &res, igraph_ess_all(IGRAPH_EDGEORDER_FROM), IGRAPH_IN, 0);
    igraph_vector_print(&res);

    printf("\nDice similarity:\n");
    igraph_similarity_dice(&g, &m, igraph_vss_range(1, 3), IGRAPH_ALL, 0);
    igraph_matrix_printf(&m, "%.2f");

    printf("\nDice similarity, pairs:\n");
    igraph_similarity_dice_pairs(&g, &res, &pairs, IGRAPH_ALL, 0);
    igraph_vector_print(&res);

    printf("\nDice similarity with edge selector:\n");
    igraph_similarity_dice_es(&g, &res, igraph_ess_all(IGRAPH_EDGEORDER_FROM), IGRAPH_IN, 0);
    igraph_vector_print(&res);

    printf("\nWeighted inverse log similarity:\n");
    igraph_similarity_inverse_log_weighted(&g, &m, igraph_vss_all(), IGRAPH_ALL);
    igraph_matrix_printf(&m, "%.2f");

    igraph_matrix_destroy(&m);
    igraph_destroy(&g);
    igraph_vector_destroy(&res);
    igraph_vector_int_destroy(&pairs);

    return 0;
}


14.7. igraph_similarity_dice_pairs — 给定顶点对的 Dice 相似性系数。

igraph_error_t igraph_similarity_dice_pairs(const igraph_t *graph, igraph_vector_t *res,
                                 const igraph_vector_int_t *pairs, igraph_neimode_t mode, igraph_bool_t loops);

两个顶点的 Dice 相似性系数是公共邻居数量的两倍除以顶点的度数之和。此函数计算顶点对列表的成对 Dice 相似性。

参数: 

:

要分析的图对象

res:

指向向量的指针,计算结果将存储在此处。元素数与 pairs 中的对数相同。

:

一个向量,包含将为其计算相似性的对。每对由两个连续元素定义,即,向量的第一个和第二个元素指定第一对,第三个和第四个元素指定第二对,依此类推。

模式:

用于有向图中计算的邻居类型。可能的值

IGRAPH_OUT

对于每个节点,将考虑出边。

IGRAPH_IN

对于每个节点,将考虑入边。

IGRAPH_ALL

在计算时,有向图被视为无向图。

循环:

是否将顶点本身作为自己的邻居包含在内。

返回值: 

错误代码

IGRAPH_ENOMEM

临时数据没有足够的内存。

IGRAPH_EINVVID

传递了无效的顶点 ID。

IGRAPH_EINVMODE

无效的模式参数。

时间复杂度:O(nd),n 是给定向量中的对数,d 是图中顶点的(最大)度数。

另请参阅: 

使用 igraph_similarity_dice() 计算顶点集的所有对之间的 Dice 相似性,或使用 igraph_similarity_jaccard()igraph_similarity_jaccard_pairs()igraph_similarity_jaccard_es() 来进行与 Dice 系数非常相似的度量

示例 13.28.  文件 examples/simple/igraph_similarity.c

#include <igraph.h>

int main(void) {

    igraph_t g;
    igraph_matrix_t m;
    igraph_vector_int_t pairs;
    igraph_vector_t res;
    igraph_integer_t i, j, n;

    igraph_small(&g, 0, IGRAPH_DIRECTED,
                 0, 1, 2, 1, 2, 0, 3, 0,
                 -1);

    igraph_matrix_init(&m, 0, 0);
    igraph_vector_init(&res, 0);
    igraph_vector_int_init(&pairs, 0);

    n = igraph_vcount(&g);
    for (i = 0; i < n; i++) {
        for (j = n - 1; j >= 0; j--) {
            igraph_vector_int_push_back(&pairs, i);
            igraph_vector_int_push_back(&pairs, j);
        }
    }

    printf("Jaccard similarity:\n");
    igraph_similarity_jaccard(&g, &m, igraph_vss_range(1, 3), IGRAPH_ALL, 0);
    igraph_matrix_printf(&m, "%.2f");

    printf("\nJaccard similarity, pairs:\n");
    igraph_similarity_jaccard_pairs(&g, &res, &pairs, IGRAPH_ALL, 0);
    igraph_vector_print(&res);

    printf("\nJaccard similarity with edge selector:\n");
    igraph_similarity_jaccard_es(&g, &res, igraph_ess_all(IGRAPH_EDGEORDER_FROM), IGRAPH_IN, 0);
    igraph_vector_print(&res);

    printf("\nDice similarity:\n");
    igraph_similarity_dice(&g, &m, igraph_vss_range(1, 3), IGRAPH_ALL, 0);
    igraph_matrix_printf(&m, "%.2f");

    printf("\nDice similarity, pairs:\n");
    igraph_similarity_dice_pairs(&g, &res, &pairs, IGRAPH_ALL, 0);
    igraph_vector_print(&res);

    printf("\nDice similarity with edge selector:\n");
    igraph_similarity_dice_es(&g, &res, igraph_ess_all(IGRAPH_EDGEORDER_FROM), IGRAPH_IN, 0);
    igraph_vector_print(&res);

    printf("\nWeighted inverse log similarity:\n");
    igraph_similarity_inverse_log_weighted(&g, &m, igraph_vss_all(), IGRAPH_ALL);
    igraph_matrix_printf(&m, "%.2f");

    igraph_matrix_destroy(&m);
    igraph_destroy(&g);
    igraph_vector_destroy(&res);
    igraph_vector_int_destroy(&pairs);

    return 0;
}


14.8. igraph_similarity_dice_es — 给定边选择器的 Dice 相似性系数。

igraph_error_t igraph_similarity_dice_es(const igraph_t *graph, igraph_vector_t *res,
                              const igraph_es_t es, igraph_neimode_t mode, igraph_bool_t loops);

两个顶点的 Dice 相似性系数是公共邻居数量的两倍除以顶点的度数之和。此函数计算给定边选择器中边的端点的成对 Dice 相似性。

参数: 

:

要分析的图对象

res:

指向向量的指针,计算结果将存储在此处。元素数与 es 中的边数相同。

es:

一个边选择器,用于指定结果中要包含的边。

模式:

用于有向图中计算的邻居类型。可能的值

IGRAPH_OUT

对于每个节点,将考虑出边。

IGRAPH_IN

对于每个节点,将考虑入边。

IGRAPH_ALL

在计算时,有向图被视为无向图。

循环:

是否将顶点本身作为自己的邻居包含在内。

返回值: 

错误代码

IGRAPH_ENOMEM

临时数据没有足够的内存。

IGRAPH_EINVVID

传递了无效的顶点 ID。

IGRAPH_EINVMODE

无效的模式参数。

时间复杂度:O(nd),n 是给定向量中的对数,d 是图中顶点的(最大)度数。

另请参阅: 

使用 igraph_similarity_dice()igraph_similarity_dice_pairs() 计算顶点集的所有对之间或一些选定顶点对之间的 Dice 相似性,或使用 igraph_similarity_jaccard()igraph_similarity_jaccard_pairs()igraph_similarity_jaccard_es() 来进行与 Dice 系数非常相似的度量

示例 13.29.  文件 examples/simple/igraph_similarity.c

#include <igraph.h>

int main(void) {

    igraph_t g;
    igraph_matrix_t m;
    igraph_vector_int_t pairs;
    igraph_vector_t res;
    igraph_integer_t i, j, n;

    igraph_small(&g, 0, IGRAPH_DIRECTED,
                 0, 1, 2, 1, 2, 0, 3, 0,
                 -1);

    igraph_matrix_init(&m, 0, 0);
    igraph_vector_init(&res, 0);
    igraph_vector_int_init(&pairs, 0);

    n = igraph_vcount(&g);
    for (i = 0; i < n; i++) {
        for (j = n - 1; j >= 0; j--) {
            igraph_vector_int_push_back(&pairs, i);
            igraph_vector_int_push_back(&pairs, j);
        }
    }

    printf("Jaccard similarity:\n");
    igraph_similarity_jaccard(&g, &m, igraph_vss_range(1, 3), IGRAPH_ALL, 0);
    igraph_matrix_printf(&m, "%.2f");

    printf("\nJaccard similarity, pairs:\n");
    igraph_similarity_jaccard_pairs(&g, &res, &pairs, IGRAPH_ALL, 0);
    igraph_vector_print(&res);

    printf("\nJaccard similarity with edge selector:\n");
    igraph_similarity_jaccard_es(&g, &res, igraph_ess_all(IGRAPH_EDGEORDER_FROM), IGRAPH_IN, 0);
    igraph_vector_print(&res);

    printf("\nDice similarity:\n");
    igraph_similarity_dice(&g, &m, igraph_vss_range(1, 3), IGRAPH_ALL, 0);
    igraph_matrix_printf(&m, "%.2f");

    printf("\nDice similarity, pairs:\n");
    igraph_similarity_dice_pairs(&g, &res, &pairs, IGRAPH_ALL, 0);
    igraph_vector_print(&res);

    printf("\nDice similarity with edge selector:\n");
    igraph_similarity_dice_es(&g, &res, igraph_ess_all(IGRAPH_EDGEORDER_FROM), IGRAPH_IN, 0);
    igraph_vector_print(&res);

    printf("\nWeighted inverse log similarity:\n");
    igraph_similarity_inverse_log_weighted(&g, &m, igraph_vss_all(), IGRAPH_ALL);
    igraph_matrix_printf(&m, "%.2f");

    igraph_matrix_destroy(&m);
    igraph_destroy(&g);
    igraph_vector_destroy(&res);
    igraph_vector_int_destroy(&pairs);

    return 0;
}


14.9. igraph_similarity_inverse_log_weighted — 基于顶点度数的倒数对数加权的顶点相似性。

igraph_error_t igraph_similarity_inverse_log_weighted(const igraph_t *graph,
        igraph_matrix_t *res, const igraph_vs_t vids, igraph_neimode_t mode);

两个顶点的倒数对数加权相似性是它们的公共邻居的数量,按它们的度数的倒数对数加权。它基于以下假设:如果两个顶点共享一个低度数的公共邻居,则应认为它们更相似,因为即使是纯粹的偶然,也更有可能出现高度数的公共邻居。

孤立的顶点将与任何其他顶点具有零相似性。不计算自相似性。

请注意,环边的存在可能会产生与直觉相反的结果。具有环边的节点被认为是它自身的邻居两次(因为有两个边柄与该节点相连)。向节点添加环边可能会降低其与其他节点的相似性,但也可能增加其相似性。例如,如果节点 A 和 B 连接但没有共同邻居,则它们的相似度为零。但是,如果向 B 添加环边,则 B 本身将成为 A 和 B 的共同邻居,因此 A 和 B 的相似度将会增加。考虑在使用 igraph_simplify() 调用此函数之前显式移除环边。

更多详细信息,请参见以下论文:Lada A. Adamic 和 Eytan Adar:Friends and neighbors on the Web. Social Networks, 25(3):211-230, 2003. https://doi.org/10.1016/S0378-8733(03)00009-1

参数: 

:

要分析的图对象。

res:

指向矩阵的指针,计算结果将存储在此处。其行数与 vids 中的顶点 ID 数相同,列数是图中的顶点数。

vids:

将为其完成计算的顶点的顶点 ID。

模式:

用于有向图中计算的邻居类型。可能的值

IGRAPH_OUT

将考虑每个节点的出边。节点将根据它们的入度进行加权。

IGRAPH_IN

将考虑每个节点的入边。节点将根据它们的出度进行加权。

IGRAPH_ALL

有向图在计算时被视为无向图。每个节点都根据其无向度数进行加权。

返回值: 

错误代码:IGRAPH_EINVVID:无效的顶点 ID。

时间复杂度:O(|V|d^2),|V| 是图中的顶点数,d 是图中顶点(最大)度数。

示例 13.30.  文件 examples/simple/igraph_similarity.c

#include <igraph.h>

int main(void) {

    igraph_t g;
    igraph_matrix_t m;
    igraph_vector_int_t pairs;
    igraph_vector_t res;
    igraph_integer_t i, j, n;

    igraph_small(&g, 0, IGRAPH_DIRECTED,
                 0, 1, 2, 1, 2, 0, 3, 0,
                 -1);

    igraph_matrix_init(&m, 0, 0);
    igraph_vector_init(&res, 0);
    igraph_vector_int_init(&pairs, 0);

    n = igraph_vcount(&g);
    for (i = 0; i < n; i++) {
        for (j = n - 1; j >= 0; j--) {
            igraph_vector_int_push_back(&pairs, i);
            igraph_vector_int_push_back(&pairs, j);
        }
    }

    printf("Jaccard similarity:\n");
    igraph_similarity_jaccard(&g, &m, igraph_vss_range(1, 3), IGRAPH_ALL, 0);
    igraph_matrix_printf(&m, "%.2f");

    printf("\nJaccard similarity, pairs:\n");
    igraph_similarity_jaccard_pairs(&g, &res, &pairs, IGRAPH_ALL, 0);
    igraph_vector_print(&res);

    printf("\nJaccard similarity with edge selector:\n");
    igraph_similarity_jaccard_es(&g, &res, igraph_ess_all(IGRAPH_EDGEORDER_FROM), IGRAPH_IN, 0);
    igraph_vector_print(&res);

    printf("\nDice similarity:\n");
    igraph_similarity_dice(&g, &m, igraph_vss_range(1, 3), IGRAPH_ALL, 0);
    igraph_matrix_printf(&m, "%.2f");

    printf("\nDice similarity, pairs:\n");
    igraph_similarity_dice_pairs(&g, &res, &pairs, IGRAPH_ALL, 0);
    igraph_vector_print(&res);

    printf("\nDice similarity with edge selector:\n");
    igraph_similarity_dice_es(&g, &res, igraph_ess_all(IGRAPH_EDGEORDER_FROM), IGRAPH_IN, 0);
    igraph_vector_print(&res);

    printf("\nWeighted inverse log similarity:\n");
    igraph_similarity_inverse_log_weighted(&g, &m, igraph_vss_all(), IGRAPH_ALL);
    igraph_matrix_printf(&m, "%.2f");

    igraph_matrix_destroy(&m);
    igraph_destroy(&g);
    igraph_vector_destroy(&res);
    igraph_vector_int_destroy(&pairs);

    return 0;
}


15. 树和森林

15.1. igraph_minimum_spanning_tree — 计算图的最小生成树之一。

igraph_error_t igraph_minimum_spanning_tree(
    const igraph_t *graph, igraph_vector_int_t *res, const igraph_vector_t *weights
);

查找图的生成树。如果图未连接,则返回其最小生成森林。这是每个组件的最小生成树的集合。

对于此计算,有向图被视为无向图。

此函数是确定性的,即它始终返回相同的生成树。有关图的生成树的均匀随机采样,请参见 igraph_random_spanning_tree()

参数: 

:

图对象。

res:

将在此处返回一个初始化的向量,其中包含构成生成树的边的 ID。使用 igraph_subgraph_from_edges() 将生成树提取为单独的图对象。

weights:

一个向量,包含边的权重,顺序与简单边迭代器访问它们的顺序相同(即,按边 ID 的递增顺序)。

返回值: 

错误代码:IGRAPH_ENOMEM,临时数据内存不足。

时间复杂度:对于无权情况为 O(|V|+|E|),对于加权情况为 O(|E| log |V|)。|V| 是顶点数,|E| 是图中边的数量。

另请参阅: 

如果只需要树作为单独的图对象,请使用 igraph_minimum_spanning_tree_unweighted()igraph_minimum_spanning_tree_prim()

示例 13.31.  文件 examples/simple/igraph_minimum_spanning_tree.c

#include <igraph.h>

int main(void) {
    igraph_t graph;
    igraph_vector_t eb;
    igraph_vector_int_t edges;

    /* Create the vector where the tree edges will be stored. */
    igraph_vector_int_init(&edges, 0);

    /* Create the Frucht graph */
    igraph_famous(&graph, "Frucht");

    /* Compute the edge betweenness. */
    igraph_vector_init(&eb, igraph_ecount(&graph));
    igraph_edge_betweenness(&graph, &eb, IGRAPH_UNDIRECTED, /*weights=*/ NULL);

    /* Use Prim's algorithm to compute the edges that belong to the minimum weight
     * spanning tree, using edge betweenness values as edge weights. */
    igraph_minimum_spanning_tree(&graph, &edges, &eb);
    printf("Minimum spanning tree edges:\n");
    igraph_vector_int_print(&edges);

    /* A maximum spanning tree can be computed by first negating the weights. */
    igraph_vector_scale(&eb, -1);

    /* Compute and output the edges that belong to the maximum weight spanning tree,
     * letting igraph automatically select the most suitable algorithm. */
    igraph_minimum_spanning_tree(&graph, &edges, &eb);
    printf("\nMaximum spanning tree edges:\n");
    igraph_vector_int_print(&edges);

    igraph_real_t total_tree_weight = 0;
    igraph_integer_t n = igraph_vector_int_size(&edges);
    for (igraph_integer_t i=0; i < n; i++) {
        total_tree_weight += -VECTOR(eb)[ VECTOR(edges)[i] ];
    }
    printf("\nTotal maximum spanning tree weight: %g\n", total_tree_weight);

    /* Clean up */
    igraph_destroy(&graph);
    igraph_vector_destroy(&eb);
    igraph_vector_int_destroy(&edges);

    return 0;
}


15.2. igraph_minimum_spanning_tree_unweighted — 计算无权图的最小生成树之一。

igraph_error_t igraph_minimum_spanning_tree_unweighted(const igraph_t *graph,
        igraph_t *mst);

警告

自版本 0.10.14 起已弃用。请不要在新代码中使用此函数;请改用 igraph_minimum_spanning_tree()

如果图有多个最小生成树(除非它是森林,否则总是这样),则此实现仅返回相同的生成树。

对于此计算,有向图被视为无向图。

如果图未连接,则返回其最小生成森林。这是每个组件的最小生成树的集合。

参数: 

:

图对象。将忽略边方向。

mst:

最小生成树,另一个图对象。在将其传递给此函数之前,不要初始化此对象,但请务必在不再需要它时调用 igraph_destroy()

返回值: 

错误代码:IGRAPH_ENOMEM,临时数据内存不足。

时间复杂度:O(|V|+|E|),|V| 是图中顶点的数量,|E| 是边的数量。

另请参阅: 

对于加权图,请使用 igraph_minimum_spanning_tree_prim(),如果需要构成生成树的边的 ID,请使用 igraph_minimum_spanning_tree()

15.3. igraph_minimum_spanning_tree_prim — 计算加权图的最小生成树之一。

igraph_error_t igraph_minimum_spanning_tree_prim(const igraph_t *graph, igraph_t *mst,
                                      const igraph_vector_t *weights);

警告

自版本 0.10.14 起已弃用。请不要在新代码中使用此函数;请改用 igraph_minimum_spanning_tree()

查找边权重之和最小的生成树或生成森林。此函数使用 Prim 算法进行计算。

对于此计算,有向图被视为无向图。

参考

Prim, R.C.: Shortest connection networks and some generalizations, Bell System Technical Journal, Vol. 36, 1957, 1389--1401. https://doi.org/10.1002/j.1538-7305.1957.tb01515.x

参数: 

:

图对象。将忽略边方向。

mst:

计算结果,一个包含图的最小生成树的图对象。在将其传递给此函数之前,不要初始化此对象,但请务必在不再需要它时调用 igraph_destroy()

weights:

一个向量,包含边的权重,顺序与简单边迭代器访问它们的顺序相同(即,按边 ID 的递增顺序)。

返回值: 

错误代码:IGRAPH_ENOMEM,内存不足。IGRAPH_EINVAL,权重向量的长度与边数不匹配。

时间复杂度:O(|E| log |V|),|V| 是顶点数,|E| 是图中边的数量。

另请参阅: 

对于无权图,请使用 igraph_minimum_spanning_tree_unweighted(),如果需要构成生成树的边的 ID,请使用 igraph_minimum_spanning_tree()

示例 13.32.  文件 examples/simple/igraph_minimum_spanning_tree.c

#include <igraph.h>

int main(void) {
    igraph_t graph;
    igraph_vector_t eb;
    igraph_vector_int_t edges;

    /* Create the vector where the tree edges will be stored. */
    igraph_vector_int_init(&edges, 0);

    /* Create the Frucht graph */
    igraph_famous(&graph, "Frucht");

    /* Compute the edge betweenness. */
    igraph_vector_init(&eb, igraph_ecount(&graph));
    igraph_edge_betweenness(&graph, &eb, IGRAPH_UNDIRECTED, /*weights=*/ NULL);

    /* Use Prim's algorithm to compute the edges that belong to the minimum weight
     * spanning tree, using edge betweenness values as edge weights. */
    igraph_minimum_spanning_tree(&graph, &edges, &eb);
    printf("Minimum spanning tree edges:\n");
    igraph_vector_int_print(&edges);

    /* A maximum spanning tree can be computed by first negating the weights. */
    igraph_vector_scale(&eb, -1);

    /* Compute and output the edges that belong to the maximum weight spanning tree,
     * letting igraph automatically select the most suitable algorithm. */
    igraph_minimum_spanning_tree(&graph, &edges, &eb);
    printf("\nMaximum spanning tree edges:\n");
    igraph_vector_int_print(&edges);

    igraph_real_t total_tree_weight = 0;
    igraph_integer_t n = igraph_vector_int_size(&edges);
    for (igraph_integer_t i=0; i < n; i++) {
        total_tree_weight += -VECTOR(eb)[ VECTOR(edges)[i] ];
    }
    printf("\nTotal maximum spanning tree weight: %g\n", total_tree_weight);

    /* Clean up */
    igraph_destroy(&graph);
    igraph_vector_destroy(&eb);
    igraph_vector_int_destroy(&edges);

    return 0;
}


15.4. igraph_random_spanning_tree — 均匀地对图的生成树进行采样。

igraph_error_t igraph_random_spanning_tree(const igraph_t *graph, igraph_vector_int_t *res, igraph_integer_t vid);

在图上执行环擦除随机游走以均匀地对其生成树进行采样。忽略边方向。

支持多重图,边重数会影响采样频率。例如,考虑 3 环图 1=2-3-1,顶点 1 和 2 之间有两条边。由于这些平行边,树 1-2-33-1-2 将以重数 2 进行采样,而树 2-3-1 将以重数 1 进行采样。

参数: 

:

输入图。忽略边方向。

res:

将在此处返回一个初始化的向量,其中包含构成生成树的边的 ID。使用 igraph_subgraph_from_edges() 将生成树提取为单独的图对象。

vid:

如果图未连接,则此参数相关。如果为负数,则将生成所有组件的随机生成森林。否则,它应该是顶点的 ID。将生成包含该顶点的组件的随机生成树。

返回值: 

错误代码。

另请参阅: 

15.5. igraph_is_tree — 确定图是否为树。

igraph_error_t igraph_is_tree(const igraph_t *graph, igraph_bool_t *res, igraph_integer_t *root, igraph_neimode_t mode);

如果无向图已连接且没有环,则它是一棵树。

在有向图中,一个附加要求是所有边都从根定向(外向树或树状图)或所有边都朝向根定向(内向树或反树状图)。可以使用 mode 参数控制此测试。

按照惯例,空图(即没有顶点的图)被认为未连接,因此不是树。

参数: 

:

要分析的图对象。

res:

指向布尔变量的指针,结果将存储在此处。

root:

如果不为 NULL,则根节点将存储在此处。当 modeIGRAPH_ALL 或图是无向图时,任何顶点都可以是根,并且 root 设置为 0(第一个顶点)。当 modeIGRAPH_OUTIGRAPH_IN 时,根设置为入度或出度为零的顶点。

模式:

对于有向图,这指定是测试外向树、内向树还是忽略边方向。可能的相应值为:IGRAPH_OUTIGRAPH_INIGRAPH_ALL。此参数对于无向图将被忽略。

返回值: 

错误代码:IGRAPH_EINVAL:无效的模式参数。

时间复杂度:最多 O(|V|+|E|),顶点数加上图中边的数量。

另请参阅: 

igraph_is_forest() 检查所有组件是否都是树,这等效于图缺少无向环;igraph_is_connected(), igraph_is_acyclic()

示例 13.33.  文件 examples/simple/igraph_kary_tree.c

#include <igraph.h>

int main(void) {
    igraph_t graph;
    igraph_bool_t res;

    /* Create a directed binary tree on 15 nodes,
       with edges pointing towards the root. */
    igraph_kary_tree(&graph, 15, 2, IGRAPH_TREE_IN);

    igraph_is_tree(&graph, &res, NULL, IGRAPH_IN);
    printf("Is it an in-tree? %s\n", res ? "Yes" : "No");

    igraph_is_tree(&graph, &res, NULL, IGRAPH_OUT);
    printf("Is it an out-tree? %s\n", res ? "Yes" : "No");

    igraph_destroy(&graph);

    return 0;
}


15.6. igraph_is_forest — 确定图是否为森林。

igraph_error_t igraph_is_forest(const igraph_t *graph, igraph_bool_t *res,
                                igraph_vector_int_t *roots, igraph_neimode_t mode);

如果无向图没有环,则它是森林。等效地,如果所有连接的组件都是树,则该图是森林。

在有向图中,一个附加要求是每个树中的边都从根定向(外向树或树状图)或所有边都朝向根定向(内向树或反树状图)。可以使用 mode 参数控制此测试。

按照惯例,空图(即没有顶点的图)被认为是森林。

如果 mode 设置为 IGRAPH_ALL 或者图是无向图,则此函数的 res 返回值缓存在图本身中。如果在两次调用函数之间没有修改图,则多次调用该函数将在 O(1) 时间内返回缓存值(如果未请求根)。

参数: 

:

要分析的图对象。

res:

指向布尔变量的指针。如果不为 NULL,则结果将存储在此处。

roots:

如果不为 NULL,则根节点将存储在此处。当 modeIGRAPH_ALL 或图是无向图时,每个组件中的任何一个顶点都可以是根。当 modeIGRAPH_OUTIGRAPH_IN 时,所有入度或出度为零的顶点分别被视为根节点。

模式:

对于有向图,这指定是测试外向森林、内向森林还是忽略边方向。可能的相应值为:IGRAPH_OUTIGRAPH_INIGRAPH_ALL。此参数对于无向图将被忽略。

返回值: 

错误代码:IGRAPH_EINVMODE:无效的 mode 参数。

时间复杂度:最多 O(|V|+|E|),顶点数加上图中边的数量。

另请参阅: 

使用 igraph_is_tree() 检查图是否为树,即具有单个组件的森林。

15.7. igraph_to_prufer — 将树转换为其 Prüfer 序列。

igraph_error_t igraph_to_prufer(const igraph_t *graph, igraph_vector_int_t* prufer);

Prüfer 序列是与标记树关联的唯一整数序列。具有 n >= 2 个顶点的树可以用 n-2 个整数的序列表示,每个整数都在 0 到 n-1 之间(包括 0 和 n-1)。

参数: 

:

指向初始化的图对象的指针,该对象必须是具有 n >= 2 个顶点的树。

prufer:

指向应保存 Prüfer 序列的整数向量的指针;必须初始化该向量并将大小调整为 n - 2。

返回值: 

错误代码

IGRAPH_ENOMEM

没有足够的内存来执行该操作。

IGRAPH_EINVAL

该图不是树或者顶点数少于 2 个

另请参阅: 

16. 传递性或聚类系数

16.1. igraph_transitivity_undirected — 计算图的传递性(聚类系数)。

igraph_error_t igraph_transitivity_undirected(const igraph_t *graph,
                                   igraph_real_t *res,
                                   igraph_transitivity_mode_t mode);

传递性衡量顶点的两个邻居相连的概率。更准确地说,这是图中三角形和连接的三元组的比率,结果是一个实数。有向图被视为无向图,多重边将被忽略。

请注意,此度量与局部传递性度量(请参见 igraph_transitivity_local_undirected() )不同,因为它计算整个图的单个值。

聚类系数是传递性的替代名称。

参考

S. Wasserman 和 K. Faust: Social Network Analysis: Methods and Applications. Cambridge: Cambridge University Press, 1994.

参数: 

:

图对象。将忽略边方向和重数。

res:

指向实变量的指针,结果将存储在此处。

模式:

定义如何处理没有连接的三元组的图。IGRAPH_TRANSITIVITY_NAN 在这种情况下返回 NaNIGRAPH_TRANSITIVITY_ZERO 返回零。

返回值: 

错误代码:IGRAPH_ENOMEM:临时数据没有足够的内存。

另请参阅: 

时间复杂度:O(|V|*d^2),|V| 是图中的顶点数,d 是平均节点度。

示例 13.34.  文件 examples/simple/igraph_transitivity.c

#include <igraph.h>

int main(void) {

    igraph_t g;
    igraph_real_t res;

    /* Trivial cases */

    igraph_ring(&g, 100, IGRAPH_UNDIRECTED, 0, 0);
    igraph_transitivity_undirected(&g, &res, IGRAPH_TRANSITIVITY_NAN);
    igraph_destroy(&g);

    if (res != 0) {
        return 1;
    }

    igraph_full(&g, 20, IGRAPH_UNDIRECTED, IGRAPH_NO_LOOPS);
    igraph_transitivity_undirected(&g, &res, IGRAPH_TRANSITIVITY_NAN);
    igraph_destroy(&g);

    if (res != 1) {
        return 2;
    }

    /* Degenerate cases */
    igraph_small(&g, 0, IGRAPH_UNDIRECTED,
                 0,  1,  2,  3,  4,  5, -1);
    igraph_transitivity_undirected(&g, &res, IGRAPH_TRANSITIVITY_NAN);
    /* res should be NaN here, any comparison must return false */
    if (res == 0 || res > 0 || res < 0) {
        return 4;
    }
    igraph_transitivity_undirected(&g, &res, IGRAPH_TRANSITIVITY_ZERO);
    /* res should be zero here */
    if (res) {
        return 5;
    }
    igraph_destroy(&g);

    /* 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_transitivity_undirected(&g, &res, IGRAPH_TRANSITIVITY_NAN);
    igraph_destroy(&g);

    if (res != 0.2556818181818181767717) {
        fprintf(stderr, "%f != %f\n", res, 0.2556818181818181767717);
        return 3;
    }

    return 0;
}


16.2. igraph_transitivity_local_undirected — 某些顶点的局部传递性(聚类系数)。

igraph_error_t igraph_transitivity_local_undirected(const igraph_t *graph,
        igraph_vector_t *res,
        const igraph_vs_t vids,
        igraph_transitivity_mode_t mode);

传递性衡量顶点的两个邻居相连的概率。对于局部传递性,此概率是为每个顶点单独计算的。

请注意,此度量与全局传递性度量(请参见 igraph_transitivity_undirected() )不同,因为它单独计算每个顶点的传递性值。

聚类系数是传递性的替代名称。

参考

D. J. Watts 和 S. Strogatz: Collective dynamics of small-world networks. Nature 393(6684):440-442 (1998).

参数: 

:

输入图。将忽略边方向和重数。

res:

指向已初始化向量的指针,结果将存储在此处。它将根据需要调整大小。

vids:

顶点集,将为其计算局部传递性的顶点。

模式:

定义如何处理度小于 2 的顶点。IGRAPH_TRANSITIVITY_NAN 为这些顶点返回 NaNIGRAPH_TRANSITIVITY_ZERO 返回零。

返回值: 

错误代码。

另请参阅: 

时间复杂度:O(n*d^2),n 是计算传递性的顶点数,d 是平均顶点度。

16.3. igraph_transitivity_avglocal_undirected — 平均局部传递性(聚类系数)。

igraph_error_t igraph_transitivity_avglocal_undirected(const igraph_t *graph,
        igraph_real_t *res,
        igraph_transitivity_mode_t mode);

传递性衡量顶点的两个邻居相连的概率。对于平均局部传递性,此概率是为每个顶点计算的,然后取平均值。邻居数少于两个的顶点需要特殊处理,它们将被排除在计算之外,或者它们将被视为具有零传递性,具体取决于 mode 参数。忽略边方向和边重数。

请注意,此度量与全局传递性度量(请参见 igraph_transitivity_undirected() )不同,因为它只是取整个网络的平均局部传递性。

聚类系数是传递性的替代名称。

参考

D. J. Watts 和 S. Strogatz: Collective dynamics of small-world networks. Nature 393(6684):440-442 (1998).

参数: 

:

输入图。忽略边方向和重数。

res:

指向实变量的指针,结果将存储在此处。

模式:

定义如何处理度小于 2 的顶点。IGRAPH_TRANSITIVITY_NAN 将它们排除在平均之外,IGRAPH_TRANSITIVITY_ZERO 将它们包含在内,传递性为零。如果模式为 IGRAPH_TRANSITIVITY_NAN 且没有邻居数大于 1 的顶点,则结果将为 NaN

返回值: 

错误代码。

另请参阅: 

时间复杂度:O(|V|*d^2),|V| 是图中的顶点数,d 是平均度。

16.4. igraph_transitivity_barrat — 某些顶点的加权局部传递性,由 A. Barrat 定义。

igraph_error_t igraph_transitivity_barrat(const igraph_t *graph,
                               igraph_vector_t *res,
                               const igraph_vs_t vids,
                               const igraph_vector_t *weights,
                               igraph_transitivity_mode_t mode);

这是一个局部传递性,即顶点级索引。对于给定的顶点 i,从它参与的所有三角形中,我们考虑事件于 i 的边的权重。传递性是这些权重的总和除以顶点强度的两倍(请参见 igraph_strength()) 和顶点度减 1。请参见 Alain Barrat, Marc Barthelemy, Romualdo Pastor-Satorras, Alessandro Vespignani: The architecture of complex weighted networks, Proc. Natl. Acad. Sci. USA 101, 3747 (2004) at https://doi.org/10.1073/pnas.0400087101 中的公式 (5),了解确切的公式。

参数: 

:

输入图。对于有向图,将忽略边方向。请注意,该函数适用于非简单图。

res:

指向已初始化向量的指针,结果将存储在此处。它将根据需要调整大小。

vids:

为其执行计算的顶点。

weights:

边权重。如果这是一个空指针,则会发出警告并调用 igraph_transitivity_local_undirected()

模式:

定义如何处理强度为零的顶点。IGRAPH_TRANSITIVITY_NAN 表示这些顶点的传递性为 NaNIGRAPH_TRANSITIVITY_ZERO 表示它为零。

返回值: 

错误代码。

时间复杂度:O(|V|*d^2),|V| 是图中的顶点数,d 是平均节点度。

另请参阅: 

16.5. igraph_ecc — 某些边的边聚类系数。

igraph_error_t igraph_ecc(const igraph_t *graph, igraph_vector_t *res,
                          const igraph_es_t eids, igraph_integer_t k,
                          igraph_bool_t offset, igraph_bool_t normalize);

警告

此函数是实验性的,其签名尚未被视为最终签名。我们保留更改函数签名的权利,而无需更改 igraph 的主要版本。使用它需要您自担风险。

边 (i, j) 的边聚类系数 C^(k)_ij 基于边参与的 k 环数 z^(k)_ij 和给定其端点度数的它可能参与的最大此类环数 s^(k)_ij 定义。下面引用中的原始定义为

C^(k)_ij = (z^(k)_ij + 1) / s^(k)_ij

对于 k=3s^(k)_ij = min(d_i - 1, d_j - 1),其中 d_id_j 是边端点度数。对于 k=4s^(k)_ij = (d_i - 1) (d_j - 1)

normalizeoffset 参数允许跳过按 s^(k) 归一化,并在 C^(k) 的分子中将环计数 z^(k) 偏移 1。将两者都设置为 true 以计算此度量的原始定义。

当列出 k 环(即 z^(k))时,此函数将忽略边重数,但在计算边可以参与的最大环数(s^(k))时不忽略边重数。

参考

F. Radicchi, C. Castellano, F. Cecconi, V. Loreto, 和 D. Parisi, PNAS 101, 2658 (2004). https://doi.org/10.1073/pnas.0400054101

参数: 

:

输入图。

res:

初始化的向量,结果将存储在此处。

eids:

将为其计算边聚类系数的边。

k:

用于计算的环的大小。必须至少为 3。目前仅支持值 3 和 4。

offset:

布尔值,是否将 1 添加到环计数。如果 false,则使用 z^(k) 代替 z^(k) + 1。在这种情况下,归一化度量的最大值为 1。对于 k=3,这对于完全图中的所有边都适用。

normalize:

布尔值,是否按给定度数的最大可能计数 s^(k) 归一化环计数。

返回值: 

错误代码。

时间复杂度:当 k 为 3 时,O(|V| d log d + |E| d)。当 k 为 4 时,O(|V| d log d + |E| d^2)。d 表示顶点的度数。

17. 有向性转换

17.1. igraph_to_directed — 将无向图转换为有向图。

igraph_error_t igraph_to_directed(igraph_t *graph,
                       igraph_to_directed_t mode);

如果提供的图是有向图,则此函数不执行任何操作。

参数: 

:

要转换的图对象。

模式:

常量,指定转换的确切方式的详细信息。可能的值

IGRAPH_TO_DIRECTED_ARBITRARY

图中的边数保持不变,为每条无向边创建任意方向的有向边。

IGRAPH_TO_DIRECTED_MUTUAL

为每条无向边创建两条有向边,每个方向一条。

IGRAPH_TO_DIRECTED_RANDOM

每条无向边都转换为随机方向的有向边。

IGRAPH_TO_DIRECTED_ACYCLIC

每条无向边都转换为有向边,方向从较低索引的顶点到较高索引的顶点。如果没有自环,则结果是有向无环图。

返回值: 

错误代码。

时间复杂度:O(|V|+|E|),顶点数加上边数。

17.2. igraph_to_undirected — 将有向图转换为无向图。

igraph_error_t igraph_to_undirected(igraph_t *graph,
                         igraph_to_undirected_t mode,
                         const igraph_attribute_combination_t *edge_comb);

如果提供的图是无向图,则此函数不执行任何操作。

参数: 

:

要转换的图对象。

模式:

常量,指定转换的确切方式的详细信息。可能的值:IGRAPH_TO_UNDIRECTED_EACH:边数保持不变,为每条有向边创建一条无向边,此版本可能会创建具有多重边的图;IGRAPH_TO_UNDIRECTED_COLLAPSE:为每对至少有一条有向边连接的顶点创建一条无向边,不会创建多重边。IGRAPH_TO_UNDIRECTED_MUTUAL 为有向图中的每对互连边创建一条无向边。非互连边将丢失;循环边将被无条件保留。此模式可能会创建多重边。

edge_comb:

如何处理边属性。有关详细信息,请参见 igraph 手册中有关属性的部分。NULL 表示在转换过程中会丢失边属性,除非 modeIGRAPH_TO_UNDIRECTED_EACH,在这种情况下,边属性将保持不变。

返回值: 

错误代码。

时间复杂度:O(|V|+|E|),顶点数加上边数。

示例 13.35.  文件 examples/simple/igraph_to_undirected.c

#include <igraph.h>

int main(void) {

    igraph_vector_int_t v;
    igraph_t g;

    igraph_vector_int_init_int(&v, 2, 5, 5);
    igraph_square_lattice(&g, &v, 1, IGRAPH_DIRECTED, 1 /*mutual*/, 0 /*periodic*/);
    igraph_to_undirected(&g, IGRAPH_TO_UNDIRECTED_COLLAPSE,
                         /*edge_comb=*/ 0);
    igraph_write_graph_edgelist(&g, stdout);

    igraph_destroy(&g);
    igraph_vector_int_destroy(&v);

    printf("---\n");

    igraph_small(&g, 10, IGRAPH_DIRECTED,
                 0, 1, 2, 1, 2, 3, 2, 3, 4, 3, 4, 3,
                 5, 6, 6, 5, 6, 7, 6, 7, 7, 6, 7, 8, 7, 8, 8, 7, 8, 7, 8, 8, 9, 9, 9, 9,
                 -1);
    igraph_to_undirected(&g, IGRAPH_TO_UNDIRECTED_MUTUAL,
                         /*edge_comb=*/ 0);
    igraph_write_graph_edgelist(&g, stdout);
    igraph_destroy(&g);

    return 0;
}


18. 谱性质

18.1. igraph_get_laplacian — 返回图的拉普拉斯矩阵。

igraph_error_t igraph_get_laplacian(
    const igraph_t *graph, igraph_matrix_t *res, igraph_neimode_t mode,
    igraph_laplacian_normalization_t normalization,
    const igraph_vector_t *weights
);

图的拉普拉斯矩阵 L 定义为 L_ij = - A_ij(当 i != j 时)和 L_ii = d_i - A_ii。此处 A 表示(可能加权的)邻接矩阵,d_i 是顶点 i 的度数(如果加权,则为强度)。在有向图中,mode 参数控制是使用出度还是入度。相应地,行或列的总和将为零。在无向图中,A_ii 被视为自环数的两倍(或总权重),确保 d_i = \sum_j A_ij。因此,无向图的拉普拉斯算子与通过将每条无向边替换为两条互反有向边获得的有向图的拉普拉斯算子相同。

更简洁地说,L = D - A,其中 D 是包含度数的对角矩阵。拉普拉斯矩阵也可以归一化,并使用几种常规归一化方法。有关 igraph 中可用的方法,请参见 igraph_laplacian_normalization_t

此函数的第一个版本由 Vincent Matossian 编写。

参数: 

:

指向要转换的图的指针。

res:

指向已初始化的矩阵对象的指针,结果将存储在此处。如果需要,将调整其大小。

模式:

控制是否在有向图中使用出度或入度。如果设置为 IGRAPH_ALL,则将忽略边方向。

normalization:

计算拉普拉斯矩阵时要使用的归一化方法。有关可能的值,请参见 igraph_laplacian_normalization_t

weights:

一个可选向量,包含非负边权重,用于计算加权拉普拉斯矩阵。将其设置为空指针以计算未加权拉普拉斯算子。

返回值: 

错误代码。

时间复杂度:O(|V|^2),|V| 是图中的顶点数。

示例 13.36.  文件 examples/simple/igraph_get_laplacian.c

#include <igraph.h>

int main(void) {
    igraph_t g;
    igraph_vector_t weights;
    igraph_matrix_t m;

    igraph_matrix_init(&m, 1, 1);
    igraph_vector_init_int(&weights, 5, 1, 2, 3, 4, 5);

    igraph_ring(&g, 5, IGRAPH_DIRECTED, 0, 1);
    igraph_get_laplacian(&g, &m, IGRAPH_OUT, IGRAPH_LAPLACIAN_SYMMETRIC, &weights);
    igraph_matrix_print(&m);

    igraph_vector_destroy(&weights);
    igraph_matrix_destroy(&m);
    igraph_destroy(&g);
}


18.2. igraph_get_laplacian_sparse — 以稀疏矩阵格式返回图的拉普拉斯矩阵。

igraph_error_t igraph_get_laplacian_sparse(
    const igraph_t *graph, igraph_sparsemat_t *sparseres, igraph_neimode_t mode,
    igraph_laplacian_normalization_t normalization,
    const igraph_vector_t *weights
);

有关拉普拉斯矩阵的定义,请参阅 igraph_get_laplacian()

此函数的第一个版本由 Vincent Matossian 编写。

参数: 

:

指向要转换的图的指针。

sparseres:

指向已初始化的稀疏矩阵对象的指针,结果将存储在此处。

模式:

控制是否在有向图中使用出度或入度。如果设置为 IGRAPH_ALL,则将忽略边方向。

normalization:

计算拉普拉斯矩阵时要使用的归一化方法。有关可能的值,请参见 igraph_laplacian_normalization_t

weights:

一个可选向量,包含非负边权重,用于计算加权拉普拉斯矩阵。将其设置为空指针以计算未加权拉普拉斯算子。

返回值: 

错误代码。

时间复杂度:O(|E|),|E| 是图中的边数。

示例 13.37.  文件 examples/simple/igraph_get_laplacian_sparse.c

#include <igraph.h>

int test_laplacian(const igraph_vector_t *w, igraph_bool_t dir, igraph_laplacian_normalization_t normalization) {
    igraph_t g;
    igraph_matrix_t m;
    igraph_sparsemat_t sm;
    igraph_vector_int_t vec;
    igraph_vector_t *weights = 0;
    igraph_neimode_t mode = IGRAPH_OUT;

    igraph_sparsemat_init(&sm, 0, 0, 0);

    if (w) {
        weights = (igraph_vector_t*) calloc(1, sizeof(igraph_vector_t));
        igraph_vector_init_copy(weights, w);
    }

    /* Base graph, no loop or multiple edges */
    igraph_ring(&g, 5, dir, 0, 1);
    igraph_get_laplacian_sparse(&g, &sm, mode, normalization, weights);
    igraph_matrix_init(&m, 0, 0);
    igraph_sparsemat_as_matrix(&m, &sm);
    igraph_matrix_print(&m);
    igraph_matrix_destroy(&m);
    printf("===\n");

    /* Add some loop edges */
    igraph_vector_int_init_int(&vec, 4, 1, 1, 2, 2);
    igraph_add_edges(&g, &vec, 0);
    igraph_vector_int_destroy(&vec);
    if (weights) {
        igraph_vector_push_back(weights, 2);
        igraph_vector_push_back(weights, 2);
    }

    igraph_get_laplacian_sparse(&g, &sm, mode, normalization, weights);
    igraph_matrix_init(&m, 0, 0);
    igraph_sparsemat_as_matrix(&m, &sm);
    igraph_matrix_print(&m);
    igraph_matrix_destroy(&m);
    printf("===\n");

    /* Duplicate some edges */
    igraph_vector_int_init_int(&vec, 4, 1, 2, 3, 4);
    igraph_add_edges(&g, &vec, 0);
    igraph_vector_int_destroy(&vec);
    if (weights) {
        igraph_vector_push_back(weights, 3);
        igraph_vector_push_back(weights, 3);
    }

    igraph_get_laplacian_sparse(&g, &sm, mode, normalization, weights);
    igraph_matrix_init(&m, 0, 0);
    igraph_sparsemat_as_matrix(&m, &sm);
    igraph_matrix_print(&m);
    igraph_matrix_destroy(&m);
    printf("===\n");

    /* Add an isolated vertex */
    igraph_add_vertices(&g, 1, NULL);

    igraph_get_laplacian_sparse(&g, &sm, mode, normalization, weights);
    igraph_matrix_init(&m, 0, 0);
    igraph_sparsemat_as_matrix(&m, &sm);
    igraph_matrix_print(&m);
    igraph_matrix_destroy(&m);

    igraph_destroy(&g);

    if (weights) {
        igraph_vector_destroy(weights);
        free(weights);
    }

    igraph_sparsemat_destroy(&sm);

    return 0;
}

int main(void) {
    int res;
    int i;
    igraph_vector_t weights;

    igraph_vector_init_int(&weights, 5, 1, 2, 3, 4, 5);

    for (i = 0; i < 8; i++) {
        igraph_bool_t is_normalized = i / 4;
        igraph_vector_t* v = ((i & 2) / 2 ? &weights : 0);
        igraph_bool_t dir = (i % 2 ? IGRAPH_DIRECTED : IGRAPH_UNDIRECTED);

        printf("=== %sormalized, %sweighted, %sdirected\n",
               (is_normalized ? "N" : "Unn"),
               (v != 0 ? "" : "un"),
               (dir == IGRAPH_DIRECTED ? "" : "un")
              );

        res = test_laplacian(v, dir, is_normalized ? IGRAPH_LAPLACIAN_SYMMETRIC : IGRAPH_LAPLACIAN_UNNORMALIZED);

        if (res) {
            return i + 1;
        }
    }

    igraph_vector_destroy(&weights);

    return 0;
}


18.3. igraph_laplacian_normalization_t — 拉普拉斯矩阵的归一化方法。

typedef enum {
    IGRAPH_LAPLACIAN_UNNORMALIZED = 0,
    IGRAPH_LAPLACIAN_SYMMETRIC = 1,
    IGRAPH_LAPLACIAN_LEFT = 2,
    IGRAPH_LAPLACIAN_RIGHT = 3
} igraph_laplacian_normalization_t;

igraph_get_laplacian()igraph_get_laplacian_sparse() 的归一化方法。在下文中,A 指的是(可能加权的)邻接矩阵,D 是包含度数(未加权情况)或强度(加权情况)的对角矩阵。根据 mode 参数,可以使用出度、入度或总度数。

值: 

IGRAPH_LAPLACIAN_UNNORMALIZED:

未归一化的拉普拉斯矩阵,L = D - A

IGRAPH_LAPLACIAN_SYMMETRIC:

对称归一化的拉普拉斯矩阵,L = I - D^(-1/2) A D^(-1/2)

IGRAPH_LAPLACIAN_LEFT:

左随机归一化的拉普拉斯矩阵,L = I - D^-1 A

IGRAPH_LAPLACIAN_RIGHT:

右随机归一化的拉普拉斯矩阵,L = I - A D^-1

19. 非简单图:多重边和环边

19.1. igraph_is_simple — 判断输入图是否为简单图。

igraph_error_t igraph_is_simple(const igraph_t *graph, igraph_bool_t *res);

如果图不包含环边和多重边,则该图为简单图。

参数: 

:

输入图。

res:

指向布尔常量的指针,结果将存储在此处。

返回值: 

错误代码。

另请参阅: 

igraph_is_loop()igraph_is_multiple() 用于查找环边和多重边,igraph_simplify() 用于删除它们,或 igraph_has_multiple() 用于判断是否存在至少一条多重边。

时间复杂度:O(|V|+|E|)。

19.2. igraph_is_loop — 在图中查找环边。

igraph_error_t igraph_is_loop(const igraph_t *graph, igraph_vector_bool_t *res,
                              igraph_es_t es);

环边,也称为自环,是从一个顶点到其自身的边。

参数: 

:

输入图。

res:

指向已初始化的布尔向量的指针,用于存储结果,它将根据需要调整大小。

es:

要检查的边,对于所有边,在此处提供 igraph_ess_all()

返回值: 

错误代码。

另请参阅: 

igraph_simplify() 用于删除环边。

时间复杂度:O(e),要检查的边数。

示例 13.38.  文件 examples/simple/igraph_is_loop.c

#include <igraph.h>

void analyze_loops(const igraph_t *graph) {
    igraph_vector_bool_t is_loop;
    igraph_bool_t has_loop;
    igraph_integer_t loop_count;

    igraph_has_loop(graph, &has_loop);
    printf("Has loops? %s\n", has_loop ? "Yes" : "No");

    igraph_count_loops(graph, &loop_count);
    printf("How many? %" IGRAPH_PRId "\n", loop_count);

    igraph_vector_bool_init(&is_loop, 0);
    igraph_is_loop(graph, &is_loop, igraph_ess_all(IGRAPH_EDGEORDER_ID));
    printf("Loop positions: "); igraph_vector_bool_print(&is_loop);
    igraph_vector_bool_destroy(&is_loop);

    printf("\n");
}

int main(void) {

    igraph_t graph;

    igraph_small(&graph, 0, IGRAPH_DIRECTED,
                 0,1, 1,2, 2,1, 0,1, 1,0, 3,4, 11,10, -1);
    analyze_loops(&graph);
    igraph_destroy(&graph);

    igraph_small(&graph, 0, IGRAPH_UNDIRECTED,
                 0,0, 1,1, 2,2, 2,3, 2,4, 2,5, 2,6, 2,2, 0,0, -1);
    analyze_loops(&graph);
    igraph_destroy(&graph);

    return 0;
}


19.3. igraph_has_loop — 返回图是否至少有一条环边。

igraph_error_t igraph_has_loop(const igraph_t *graph, igraph_bool_t *res);

环边是从一个顶点到其自身的边。

此函数的返回值缓存在图本身中;多次调用该函数,且中间未对图进行修改,将在 O(1) 时间内返回缓存值。

参数: 

:

输入图。

res:

指向已初始化的布尔向量的指针,用于存储结果。

另请参阅: 

igraph_simplify() 用于删除环边。

时间复杂度:O(e),要检查的边数。

示例 13.39.  文件 examples/simple/igraph_is_loop.c

#include <igraph.h>

void analyze_loops(const igraph_t *graph) {
    igraph_vector_bool_t is_loop;
    igraph_bool_t has_loop;
    igraph_integer_t loop_count;

    igraph_has_loop(graph, &has_loop);
    printf("Has loops? %s\n", has_loop ? "Yes" : "No");

    igraph_count_loops(graph, &loop_count);
    printf("How many? %" IGRAPH_PRId "\n", loop_count);

    igraph_vector_bool_init(&is_loop, 0);
    igraph_is_loop(graph, &is_loop, igraph_ess_all(IGRAPH_EDGEORDER_ID));
    printf("Loop positions: "); igraph_vector_bool_print(&is_loop);
    igraph_vector_bool_destroy(&is_loop);

    printf("\n");
}

int main(void) {

    igraph_t graph;

    igraph_small(&graph, 0, IGRAPH_DIRECTED,
                 0,1, 1,2, 2,1, 0,1, 1,0, 3,4, 11,10, -1);
    analyze_loops(&graph);
    igraph_destroy(&graph);

    igraph_small(&graph, 0, IGRAPH_UNDIRECTED,
                 0,0, 1,1, 2,2, 2,3, 2,4, 2,5, 2,6, 2,2, 0,0, -1);
    analyze_loops(&graph);
    igraph_destroy(&graph);

    return 0;
}


19.4. igraph_count_loops — 统计图中的自环数。

igraph_error_t igraph_count_loops(const igraph_t *graph, igraph_integer_t *loop_count);

警告

此函数是实验性的,其签名尚未被视为最终签名。我们保留更改函数签名的权利,而无需更改 igraph 的主要版本。使用它需要您自担风险。

统计环边,即两个端点重合的边。

参数: 

:

输入图。

res:

指向整数的指针,自环数将存储在此处。

返回值: 

错误代码。

时间复杂度:O(|E|),与边数呈线性关系。

示例 13.40.  文件 examples/simple/igraph_is_loop.c

#include <igraph.h>

void analyze_loops(const igraph_t *graph) {
    igraph_vector_bool_t is_loop;
    igraph_bool_t has_loop;
    igraph_integer_t loop_count;

    igraph_has_loop(graph, &has_loop);
    printf("Has loops? %s\n", has_loop ? "Yes" : "No");

    igraph_count_loops(graph, &loop_count);
    printf("How many? %" IGRAPH_PRId "\n", loop_count);

    igraph_vector_bool_init(&is_loop, 0);
    igraph_is_loop(graph, &is_loop, igraph_ess_all(IGRAPH_EDGEORDER_ID));
    printf("Loop positions: "); igraph_vector_bool_print(&is_loop);
    igraph_vector_bool_destroy(&is_loop);

    printf("\n");
}

int main(void) {

    igraph_t graph;

    igraph_small(&graph, 0, IGRAPH_DIRECTED,
                 0,1, 1,2, 2,1, 0,1, 1,0, 3,4, 11,10, -1);
    analyze_loops(&graph);
    igraph_destroy(&graph);

    igraph_small(&graph, 0, IGRAPH_UNDIRECTED,
                 0,0, 1,1, 2,2, 2,3, 2,4, 2,5, 2,6, 2,2, 0,0, -1);
    analyze_loops(&graph);
    igraph_destroy(&graph);

    return 0;
}


19.5. igraph_is_multiple — 在图中查找多重边。

igraph_error_t igraph_is_multiple(const igraph_t *graph, igraph_vector_bool_t *res,
                                  igraph_es_t es);

如果图中存在另一条具有相同头顶点和尾顶点的边,则该边为多重边。

请注意,此函数仅对多重边的第二次或更多次出现返回 true。

参数: 

:

输入图。

res:

指向布尔向量的指针,结果将存储在此处。它将根据需要调整大小。

es:

要检查的边。如果要检查所有边,请提供 igraph_ess_all()

返回值: 

错误代码。

另请参阅: 

时间复杂度:O(e*d),e 是要检查的边数,d 是边尾顶点的平均度数(有向图中的出度)。

示例 13.41.  文件 examples/simple/igraph_is_multiple.c

#include <igraph.h>

void print_vector(igraph_vector_bool_t *v, FILE *f) {
    igraph_integer_t i;
    for (i = 0; i < igraph_vector_bool_size(v); i++) {
        fprintf(f, " %i", VECTOR(*v)[i] ? 1 : 0);
    }
    fprintf(f, "\n");
}

int main(void) {

    igraph_t graph;
    igraph_vector_bool_t v;

    igraph_vector_bool_init(&v, 0);

    igraph_small(&graph, 0, IGRAPH_DIRECTED, 0, 1, 1, 2, 2, 1, 0, 1, 1, 0, 3, 4, 11, 10, -1);
    igraph_is_multiple(&graph, &v, igraph_ess_all(IGRAPH_EDGEORDER_ID));
    print_vector(&v, stdout);
    igraph_destroy(&graph);

    igraph_small(&graph, 0, IGRAPH_UNDIRECTED,
                 0, 0, 1, 2, 1, 1, 2, 2, 2, 1, 2, 3, 2, 4,
                 2, 5, 2, 6, 2, 2, 3, 2, 0, 0, 6, 2, 2, 2, 0, 0, -1);
    igraph_is_multiple(&graph, &v, igraph_ess_all(IGRAPH_EDGEORDER_ID));
    print_vector(&v, stdout);
    igraph_destroy(&graph);

    igraph_vector_bool_destroy(&v);

    return 0;
}


19.6. igraph_has_multiple — 检查图是否至少有一条多重边。

igraph_error_t igraph_has_multiple(const igraph_t *graph, igraph_bool_t *res);

如果图中存在另一条具有相同头顶点和尾顶点的边,则该边为多重边。

此函数的返回值缓存在图本身中;多次调用该函数,且中间未对图进行修改,将在 O(1) 时间内返回缓存值。

参数: 

:

输入图。

res:

指向布尔变量的指针,结果将存储在此处。

返回值: 

错误代码。

另请参阅: 

时间复杂度:O(e*d),e 是要检查的边数,d 是边尾顶点的平均度数(有向图中的出度)。

示例 13.42.  文件 examples/simple/igraph_has_multiple.c

#include <igraph.h>

int main(void) {

    igraph_t graph;
    igraph_bool_t res;

    igraph_small(&graph, 0, IGRAPH_DIRECTED, 0, 1, 1, 2, 2, 1, 0, 1, 1, 0, 3, 4, 11, 10, -1);
    igraph_has_multiple(&graph, &res);
    if (!res) {
        return 1;
    }
    igraph_destroy(&graph);

    igraph_small(&graph, 0, IGRAPH_UNDIRECTED,
                 0, 0, 1, 2, 1, 1, 2, 2, 2, 1, 2, 3, 2, 4,
                 2, 5, 2, 6, 2, 2, 3, 2, 0, 0, 6, 2, 2, 2, 0, 0, -1);
    igraph_has_multiple(&graph, &res);
    if (!res) {
        return 2;
    }
    igraph_destroy(&graph);

    igraph_small(&graph, 0, IGRAPH_DIRECTED, 0, 1, 1, 2, 2, 1, 1, 0, 3, 4, 11, 10, -1);
    igraph_has_multiple(&graph, &res);
    if (res) {
        return 3;
    }
    igraph_destroy(&graph);

    igraph_small(&graph, 0, IGRAPH_UNDIRECTED,
                 0, 0, 1, 2, 1, 1, 2, 2, 2, 3, 2, 4, 2, 5, 2, 6, 2, 2, -1);
    igraph_has_multiple(&graph, &res);
    if (!res) {
        return 4;
    }
    igraph_destroy(&graph);

    igraph_small(&graph, 0, IGRAPH_UNDIRECTED,
                 0, 0, 1, 2, 1, 1, 2, 2, 2, 3, 2, 4, 2, 5, 2, 6, -1);
    igraph_has_multiple(&graph, &res);
    if (res) {
        return 5;
    }
    igraph_destroy(&graph);

    igraph_small(&graph, 0, IGRAPH_UNDIRECTED, 0, 1, 0, 1, 1, 2, -1);
    igraph_has_multiple(&graph, &res);
    if (!res) {
        return 6;
    }
    igraph_destroy(&graph);

    igraph_small(&graph, 0, IGRAPH_UNDIRECTED, 0, 0, 0, 0, -1);
    igraph_has_multiple(&graph, &res);
    if (!res) {
        return 7;
    }
    igraph_destroy(&graph);

    return 0;
}


19.7. igraph_count_multiple — 图中某些边的重数。

igraph_error_t igraph_count_multiple(const igraph_t *graph, igraph_vector_int_t *res,
                                     igraph_es_t es);

当两个顶点之间存在一条或多条其他边时,该边称为多重边。边的重数是其端点之间的边数。

参数: 

:

输入图。

res:

指向向量的指针,结果将存储在此处。它将根据需要调整大小。

es:

要检查的边。如果要检查所有边,请提供 igraph_ess_all()

返回值: 

错误代码。

另请参阅: 

如果您只需要单条边的重数,请使用 igraph_count_multiple_1();如果您只对图是否具有至少一条重数大于 1 的边感兴趣,请使用 igraph_is_multiple();使用 igraph_simplify() 以确保图没有多重边。

时间复杂度:O(E d),E 是要检查的边数,d 是边尾顶点的平均度数(有向图中的出度)。

19.8. igraph_count_multiple_1 — 图中单条边的重数。

igraph_error_t igraph_count_multiple_1(const igraph_t *graph, igraph_integer_t *res,
                                       igraph_integer_t eid);

参数: 

:

输入图。

res:

指向整数的指针,结果将存储在此处。

eid:

要检查的边的 ID。

返回值: 

错误代码。

另请参阅: 

如果您需要多条边的重数,请使用 igraph_count_multiple();如果您只对图是否具有至少一条重数大于 1 的边感兴趣,请使用 igraph_is_multiple();使用 igraph_simplify() 以确保图没有多重边。

时间复杂度:O(d),其中 d 是边尾顶点的出度。

20. 混合模式和度相关性

20.1. igraph_assortativity_nominal — 基于顶点类别的图的同配性。

igraph_error_t igraph_assortativity_nominal(const igraph_t *graph,
                                            const igraph_vector_int_t *types,
                                            igraph_real_t *res,
                                            igraph_bool_t directed,
                                            igraph_bool_t normalized);

假设输入图的顶点属于不同的类别,此函数计算图的同配性系数。同配性系数介于负一和一之间,如果所有连接都保持在类别内,则为一;如果网络完全异配,则为负一。对于随机连接的网络,它(渐近地)为零。

normalized 设置为 false 时计算的未归一化版本与模块化度相同,并且对于有向网络定义如下

1/m sum_ij (A_ij - k^out_i k^in_j / m) d(i,j),

其中 m 表示边数,A_ij 是邻接矩阵,k^outk^in 是出度和入度,d(i,j) 是如果顶点 ij 属于同一类别则为一,否则为零。

归一化同配性系数是通过将之前的表达式除以

1/m sum_ij (m - k^out_i k^in_j d(i,j) / m).

来获得的。它可以取 [-1, 1] 区间内的任何值。

无向图实际上被视为具有全互易边的有向图。因此,自环在无向图中被计算两次。

参考

M. E. J. Newman: Mixing patterns in networks, Phys. Rev. E 67, 026126 (2003) https://doi.org/10.1103/PhysRevE.67.026126. 有关概念的定义,请参见第 II 节和等式 (2)。

有关同配性的教育性概述,请参见 M. E. J. Newman, Networks: An Introduction, Oxford University Press (2010)。https://doi.org/10.1093/acprof%3Aoso/9780199206650.001.0001

参数: 

:

输入图,可以是定向的或非定向的。

types:

给出顶点类别的整数向量。类型由从零开始的整数表示。

res:

指向实变量的指针,结果存储在此处。

有向:

布尔值,给出是否考虑有向图中的边方向。它在无向图中被忽略。

normalized:

布尔值,是否计算通常的归一化同配性。未归一化的版本与模块化度相同。在此处提供 true 以计算标准同配性。

返回值: 

错误代码。

时间复杂度:O(|E|+t),|E| 是边数,t 是顶点类型数。

另请参阅: 

如果您具有基于连续顶点值而不是离散类别的同配性,请使用 igraph_assortativity()。使用 igraph_modularity() 来计算广义模块化度。使用 igraph_joint_type_distribution() 来获得混合矩阵。

示例 13.43.  文件 examples/simple/igraph_assortativity_nominal.c

#include <igraph.h>
#include <stdio.h>

int main(void) {
    igraph_integer_t nodes = 120, types = 4;

    igraph_matrix_t pref_matrix;
    igraph_matrix_init(&pref_matrix, types, types);

    igraph_rng_seed(igraph_rng_default(), 42);
    printf("Randomly generated graph with %" IGRAPH_PRId " nodes and %" IGRAPH_PRId " vertex types\n\n", nodes, types);

    /* Generate preference matrix giving connection probabilities for different vertex types */
    for (igraph_integer_t i = 0; i < types; i++) {
        for (igraph_integer_t j = 0; j < types; j++) {
            MATRIX(pref_matrix, i, j) = (i == j ? 0.1: 0.01);
        }
    }

    igraph_vector_int_t node_type_vec;
    igraph_vector_int_init(&node_type_vec, nodes);

    for (int i = 0; i < 5; i++) {
        igraph_real_t assortativity;
        igraph_t g;

        /* Generate undirected graph with 1000 nodes and 50 vertex types */
        igraph_preference_game(&g, nodes, types, /* type_dist= */ NULL, /* fixed_sizes= */ 1, &pref_matrix, &node_type_vec, IGRAPH_UNDIRECTED, IGRAPH_NO_LOOPS);

        igraph_assortativity_nominal(&g, &node_type_vec, &assortativity, IGRAPH_UNDIRECTED, 1);
        printf("Assortativity before rewiring = %g\n", assortativity);

        /* Rewire graph */
        igraph_rewire(&g, 10 * igraph_ecount(&g), IGRAPH_REWIRING_SIMPLE);

        igraph_assortativity_nominal(&g, &node_type_vec, &assortativity, IGRAPH_UNDIRECTED, 1);
        printf("Assortativity after rewiring = %g\n\n", assortativity);

        igraph_destroy(&g);
    }
    igraph_vector_int_destroy(&node_type_vec);
    igraph_matrix_destroy(&pref_matrix);
}


20.2. igraph_assortativity — 基于顶点数值属性的同配性。

igraph_error_t igraph_assortativity(const igraph_t *graph,
                         const igraph_vector_t *values,
                         const igraph_vector_t *values_in,
                         igraph_real_t *res,
                         igraph_bool_t directed,
                         igraph_bool_t normalized);

此函数基于每个顶点 i 的给定值 x_i 计算图的同配性系数。这种类型的同配性系数等于边两端值的皮尔逊相关性。

normalized 设置为 false 时计算的值的未归一化协方差在有向图中定义如下

cov(x_out, x_in) = 1/m sum_ij (A_ij - k^out_i k^in_j / m) x_i x_j,

其中 m 表示边数,A_ij 是邻接矩阵,k^outk^in 是出度和入度。x_outx_in 指的是有向边开始和结束处的顶点值集合。

归一化协方差,即皮尔逊相关性,是通过将之前的表达式除以 sqrt(var(x_out)) sqrt(var(x_in)) 获得的,其中

var(x_out) = 1/m sum_i k^out_i x_i^2 - (1/m sum_i k^out_i x_i^2)^2

var(x_in) = 1/m sum_j k^in_j x_j^2 - (1/m sum_j k^in_j x_j^2)^2

无向图实际上被视为所有边都是互易边的有向图。因此,自环在无向图中有效地被计算两次。

参考

M. E. J. Newman: Mixing patterns in networks, Phys. Rev. E 67, 026126 (2003) https://doi.org/10.1103/PhysRevE.67.026126. 有关定义,请参见第 III 节和等式 (21);有关使用度数作为值在有向图中执行计算,请参见等式 (26)。

M. E. J. Newman: Assortative mixing in networks, Phys. Rev. Lett. 89, 208701 (2002) https://doi.org/10.1103/PhysRevLett.89.208701. 有关使用度数作为值在无向图中执行计算,请参见等式 (4)。

有关同配性概念的教育性概述,请参见 M. E. J. Newman, Networks: An Introduction, Oxford University Press (2010)。https://doi.org/10.1093/acprof%3Aoso/9780199206650.001.0001

参数: 

:

输入图,可以是定向的或非定向的。

values:

顶点值,这些可以是任意数值。

values_in:

第二个值向量,用于在计算有向图同配性时用于传入边。如果想要对传出边和传入边使用相同的值,请在此处提供 NULL。如果此参数不是空指针并且正在计算无向同配性系数,则会忽略此参数(并发出警告)。

res:

指向实变量的指针,结果存储在此处。

有向:

布尔值,是否考虑有向图的边方向。它在无向图中被忽略。

normalized:

布尔值,是否计算归一化协方差,即皮尔逊相关性。在此处提供 true 以计算标准同配性。

返回值: 

错误代码。

时间复杂度:O(|E|),与图的边数呈线性关系。

另请参阅: 

如果您具有离散顶点类别而不是数值标签,请使用 igraph_assortativity_nominal();对于基于顶点度数的同配性特殊情况,请使用 igraph_assortativity_degree()

20.3. igraph_assortativity_degree — 基于顶点度数的图的同配性。

igraph_error_t igraph_assortativity_degree(const igraph_t *graph,
                                igraph_real_t *res,
                                igraph_bool_t directed);

基于顶点度数的同配性,有关详细信息,请参见 igraph_assortativity() 文档中的讨论。此函数只是以度数作为顶点值并启用归一化来调用 igraph_assortativity()。在有向情况下,它使用出度作为传出值,并使用入度作为传入值。

对于规则图,即所有顶点都具有相同度数的图,计算度数相关性没有意义,此函数返回 NaN。

参数: 

:

输入图,可以是定向的或非定向的。

res:

指向实变量的指针,结果存储在此处。

有向:

布尔值,是否考虑有向图的边方向。此参数在无向图中被忽略。在此处提供 true 以执行自然操作,即对有向图使用度量标准的有向版本,对无向图使用无向版本。

返回值: 

错误代码。

时间复杂度:O(|E|+|V|),|E| 是边数,|V| 是顶点数。

另请参阅: 

对于计算任何类型的数值顶点值的同配性的通用函数,请使用 igraph_assortativity();对于获得完整的联合度分布,请使用 igraph_joint_degree_distribution()

示例 13.44.  文件 examples/simple/igraph_assortativity_degree.c

#include <igraph.h>
#include <stdio.h>

int main(void){
    igraph_t g;
    igraph_integer_t vcount = 1000;
    igraph_real_t pf = 0.2;

    /* Seed random number generator to ensure reproducibility. */
    igraph_rng_seed(igraph_rng_default(), 42);

    printf("Forest fire model network with %" IGRAPH_PRId " vertices and %g forward burning probability.\n\n",
           vcount, pf);

    for (int i = 0; i < 5; i++) {
        igraph_real_t assortativity;

        /* Generate graph from the forest fire model. */
        igraph_forest_fire_game(&g, vcount, pf, 1.0, 1, IGRAPH_UNDIRECTED);

        /* Compute assortativity. */
        igraph_assortativity_degree(&g, &assortativity, /* ignore edge directions */ IGRAPH_UNDIRECTED);
        printf("Assortativity before rewiring = %g\n", assortativity);

        /* Randomize the graph while preserving the degrees. */
        igraph_rewire(&g, 20 * igraph_ecount(&g), IGRAPH_REWIRING_SIMPLE);

        /* Re-compute assortativity. Did it change? */
        igraph_assortativity_degree(&g, &assortativity, /* ignore edge directions */ IGRAPH_UNDIRECTED);
        printf("Assortativity after rewiring = %g\n\n", assortativity);

        igraph_destroy(&g);
    }
}


20.4. igraph_avg_nearest_neighbor_degree — 平均邻居度。

igraph_error_t igraph_avg_nearest_neighbor_degree(const igraph_t *graph,
                                       igraph_vs_t vids,
                                       igraph_neimode_t mode,
                                       igraph_neimode_t neighbor_degree_mode,
                                       igraph_vector_t *knn,
                                       igraph_vector_t *knnk,
                                       const igraph_vector_t *weights);

计算每个顶点的邻居的平均度数 (knn),以及可选地,作为顶点度数的函数 (knnk) 的相同量。

对于孤立顶点,knn 设置为 NaN。在 knnk 中对于图中未出现的顶点度数也是如此。

加权版本计算邻居度数的加权平均值,如下所示

k_nn_u = 1/s_u sum_v w_uv k_v,

其中 s_u = sum_v w_uv 是顶点 u 的入射边权重的总和,即其强度。总和在顶点 u 的邻居 v 上运行,如 mode 所指示。 w_uv 表示加权邻接矩阵,k_v 是邻居的度数,由 neighbor_degree_mode 指定。这是下面参考资料中的等式 (6)。

当只需要 k_nn(k) 度相关函数时,也可以使用 igraph_degree_correlation_vector()。此函数提供对如何计算有向边每一端的度数的更灵活的控制。

参考

A. Barrat, M. Barthélemy, R. Pastor-Satorras, and A. Vespignani, The architecture of complex weighted networks, Proc. Natl. Acad. Sci. USA 101, 3747 (2004). https://dx.doi.org/10.1073/pnas.0400087101

参数: 

:

输入图。它可以是有向的。

vids:

为其执行计算的顶点。

模式:

要考虑的有向图中邻居的类型。 IGRAPH_OUT 考虑传出邻居,IGRAPH_IN 考虑传入邻居,IGRAPH_ALL 忽略边方向。

neighbor_degree_mode:

有向图中要平均的度数的类型。 IGRAPH_OUT 平均传出度,IGRAPH_IN 平均传入度,IGRAPH_ALL 忽略度数计算的边方向。

vids:

为其执行计算的顶点。

knn:

指向已初始化向量的指针,结果将存储在此处。它将根据需要调整大小。如果只想计算 knnk,请在此处提供 NULL 指针。

knnk:

指向已初始化向量的指针,平均邻居度数作为顶点度数的函数存储在此处。有时这被称为 k_nn(k) 度相关函数。第一个(第零个)元素用于一度顶点等。计算仅基于顶点 vids 完成。如果不想计算此值,请在此处提供 NULL 指针。

weights:

可选边权重。对于未加权版本,请在此处提供空指针。

返回值: 

错误代码。

另请参阅: 

对于仅计算度相关函数,并对度数计算进行更灵活的控制,请使用 igraph_degree_correlation_vector()

时间复杂度:O(|V|+|E|),顶点数和边数的线性关系。

示例 13.45.  文件 examples/simple/igraph_avg_nearest_neighbor_degree.c

#include <igraph.h>

int main(void) {
    igraph_t graph;
    igraph_vector_t knn, knnk;
    igraph_vector_t weights;

    igraph_famous(&graph, "Zachary");

    igraph_vector_init(&knn, 0);
    igraph_vector_init(&knnk, 0);

    igraph_avg_nearest_neighbor_degree(&graph, igraph_vss_all(),
                                       IGRAPH_ALL, IGRAPH_ALL,
                                       &knn, &knnk, /*weights=*/ NULL);

    printf("knn: ");
    igraph_vector_print(&knn);
    printf("knn(k): ");
    igraph_vector_print(&knnk);

    igraph_vector_init_range(&weights, 0, igraph_ecount(&graph));

    igraph_avg_nearest_neighbor_degree(&graph, igraph_vss_all(),
                                       IGRAPH_ALL, IGRAPH_ALL,
                                       &knn, &knnk, &weights);
    igraph_vector_destroy(&weights);

    printf("knn: ");
    igraph_vector_print(&knn);
    printf("knn(k): ");
    igraph_vector_print(&knnk);

    igraph_vector_destroy(&knn);
    igraph_vector_destroy(&knnk);

    igraph_destroy(&graph);

    return 0;
}


20.5. igraph_degree_correlation_vector — 度相关函数。

igraph_error_t igraph_degree_correlation_vector(
        const igraph_t *graph, const igraph_vector_t *weights,
        igraph_vector_t *knnk,
        igraph_neimode_t from_mode, igraph_neimode_t to_mode,
        igraph_bool_t directed_neighbors);

警告

此函数是实验性的,其签名尚未被视为最终签名。我们保留更改函数签名的权利,而无需更改 igraph 的主要版本。使用它需要您自担风险。

计算度相关函数 k_nn(k),定义为源度数为 k 的有向边的目标的平均度数。平均值是在所有有向边上完成的。 from_modeto_mode 参数控制如何计算源顶点度和目标顶点度。通过这种方式,可以计算出出入、出出、入入和出入度相关函数。

在无向图中,边被视为一对互易有向边。

如果 P_ij 是图的联合度分布,可以使用 igraph_joint_degree_distribution() 计算,则 k_nn(k) = (sum_j j P_kj) / (sum_j P_kj)

函数 igraph_avg_nearest_neighbor_degree() 的主要目的是单独计算每个顶点的平均邻居度数,也可以计算 k_nn(k)。它与此函数的不同之处在于,它可以采用顶点子集来作为计算基础,但不允许对如何计算度数进行相同的细粒度控制。

参考

R. Pastor-Satorras, A. Vazquez, A. Vespignani: Dynamical and Correlation Properties of the Internet, Phys. Rev. Lett., vol. 87, pp. 258701 (2001). https://doi.org/10.1103/PhysRevLett.87.258701

A. Vazquez, R. Pastor-Satorras, A. Vespignani: Large-scale topological and dynamical properties of the Internet, Phys. Rev. E, vol. 65, pp. 066130 (2002). https://doi.org/10.1103/PhysRevE.65.066130

A. Barrat, M. Barthélemy, R. Pastor-Satorras, and A. Vespignani, The architecture of complex weighted networks, Proc. Natl. Acad. Sci. USA 101, 3747 (2004). https://dx.doi.org/10.1073/pnas.0400087101

参数: 

:

输入图。

weights:

可选权重向量。如果不为 NULL,则将计算加权平均值。

knnk:

已初始化向量,结果将写入此处。 knnk[d] 将包含由度数为 d 的顶点连接的顶点的平均度数。请注意,与 igraph_avg_nearest_neighbor_degree() 相比,d=0 也包括在内。

from_mode:

如何计算源的度数?可以是 IGRAPH_OUT 表示传出度,IGRAPH_IN 表示传入度,或 IGRAPH_ALL 表示总度数。在无向图中被忽略。

to_mode:

如何计算源的度数?可以是 IGRAPH_OUT 表示传出度,IGRAPH_IN 表示传入度,或 IGRAPH_ALL 表示总度数。在无向图中被忽略。

directed_neighbors:

是否将 u -> v 连接视为有向连接。无向连接被视为互易有向连接,即 u -> vv -> u 都将被考虑。在无向图中被忽略。

返回值: 

错误代码。

另请参阅: 

对于计算一组顶点的平均邻居度数,请使用 igraph_avg_nearest_neighbor_degree();对于获得完整的联合度分布,请使用 igraph_joint_degree_distribution();对于计算度数同配性,请使用 igraph_assortativity_degree()

时间复杂度:O(|E| + |V|)

20.6. igraph_joint_type_distribution — 顶点类别的混合矩阵。

igraph_error_t igraph_joint_type_distribution(
        const igraph_t *graph, const igraph_vector_t *weights,
        igraph_matrix_t *p,
        const igraph_vector_int_t *from_types, const igraph_vector_int_t *to_types,
        igraph_bool_t directed, igraph_bool_t normalized);

警告

此函数是实验性的,其签名尚未被视为最终签名。我们保留更改函数签名的权利,而无需更改 igraph 的主要版本。使用它需要您自担风险。

计算混合矩阵 M_ij,即边有向端点处顶点类型的联合分布。类别由非负整数索引表示,在 from_typesto_types 中传递。 m 的行数和列数将分别比最大源类型和目标类型大一。如果类型向量不是连续整数,请使用 igraph_reindex_membership() 对其进行重新索引,以避免生成非常大的矩阵。

M_ij 与随机选择的顶点有序对具有类型 ij 的概率成正比。

当存在顶点的单一分类时,即 from_typesto_types 相同,M_ij 与模块度(igraph_modularity())和标称同配性(igraph_assortativity_nominal())相关。令 a_i = sum_j M_ijb_j = sum_i M_ij。如果 M_ij 被归一化,即 sum_ij M_ij = 1,并且类型表示顶点划分中的成员资格,那么划分的模块度可以计算为

Q = sum_ii M_ii - sum_i a_i b_i

归一化的标称同配性为

Q / (1 - sum_i a_i b_i)

igraph_joint_degree_distribution() 是此函数的一个特殊情况,其中类别由相同度的顶点组成。

参考

M. E. J. Newman: Mixing patterns in networks, Phys. Rev. E 67, 026126 (2003) https://doi.org/10.1103/PhysRevE.67.026126.

参数: 

:

输入图。

p:

混合矩阵 M_ij 将存储在此处。

weights:

包含边权重的向量。如果传递 NULL 指针,则假定边具有单位权重。

from_types:

源顶点的顶点类型。这些必须是非负整数。

to_types:

目标顶点的顶点类型。这些必须是非负整数。如果为 NULL,则假定与 from_types 相同。

有向:

是否将边视为有向边。对于无向图,此参数将被忽略。

normalized:

是否对矩阵进行归一化,使条目总和为 1.0。如果为 false,则矩阵条目将为连接计数。如果某些边权重为负数,则归一化没有意义。

返回值: 

错误代码。

另请参阅: 

igraph_joint_degree_distribution() 用于计算顶点度的联合分布;igraph_modularity() 用于计算顶点划分的模块度;igraph_assortativity_nominal() 用于计算基于顶点类别的同配性。

时间复杂度:O(E),其中 E 是输入图中的边数。

20.7. igraph_joint_degree_distribution — 图的联合度分布。

igraph_error_t igraph_joint_degree_distribution(
        const igraph_t *graph, const igraph_vector_t *weights,
        igraph_matrix_t *p,
        igraph_neimode_t from_mode, igraph_neimode_t to_mode,
        igraph_bool_t directed_neighbors,
        igraph_bool_t normalized,
        igraph_integer_t max_from_degree, igraph_integer_t max_to_degree);

警告

此函数是实验性的,其签名尚未被视为最终签名。我们保留更改函数签名的权利,而无需更改 igraph 的主要版本。使用它需要您自担风险。

计算图的联合度分布 P_ij,用于度相关性的研究。P_ij 是随机选择的连接的顶点对具有度 ij 的概率。

在有向图中,考虑方向连接的 u -> v 对。无向图的联合度分布与相应的有向图的联合度分布相同,其中所有连接都是双向的,假设 from_modeIGRAPH_OUTto_modeIGRAPH_IN,并且 directed_neighbors 为 true。

normalized 为 false 时,sum_ij P_ij 给出有向图中的连接总数,或无向图中的该值的两倍。总和是在有序的 (i,j) 度对上取的。

联合度分布与其他用于度相关性研究的概念相关。如果 P_ij 被归一化,则度相关函数 k_nn(k) 可以表示为

k_nn(k) = (sum_j j P_kj) / (sum_j P_kj).

非归一化的度同配性可以表示为

a = sum_ij i j (P_ij - q_i r_j),

其中 q_i = sum_k P_ikr_j = sum_k P_kj

请注意,联合度分布 P_ij 类似于但不等同于 igraph_joint_degree_matrix() 计算的联合度矩阵 J_ij。如果图是无向的,则非归一化的 P_ij 的对角线条目是 J_ij 的两倍,因为相同度顶点之间的任何无向连接都在两个方向上计数。与 igraph_joint_degree_matrix() 相比,此函数返回的矩阵包括对应于零度的行和列。在有向图中,当 from_modeIGRAPH_OUT 不同或 to_modeIGRAPH_IN 不同时,此行和列不一定是零。

参考

M. E. J. Newman: Mixing patterns in networks, Phys. Rev. E 67, 026126 (2003) https://doi.org/10.1103/PhysRevE.67.026126.

参数: 

:

指向已初始化的图对象的指针。

weights:

包含边权重的向量。如果传递 NULL 指针,则假定边具有单位权重。

p:

指向将调整大小的已初始化矩阵的指针。P_ij 值将写入 p[i,j]

from_mode:

如何计算源的度数?可以是 IGRAPH_OUT 表示传出度,IGRAPH_IN 表示传入度,或 IGRAPH_ALL 表示总度数。在无向图中被忽略。

to_mode:

如何计算目标的度?可以是 IGRAPH_OUT 表示出度,IGRAPH_IN 表示入度,或 IGRAPH_ALL 表示总度。在无向图中,此参数将被忽略。

directed_neighbors:

是否将 u -> v 连接视为有向连接。无向连接被视为互易有向连接,即 u -> vv -> u 都将被考虑。在无向图中被忽略。

normalized:

是否对矩阵进行归一化,使条目总和为 1.0。如果为 false,则矩阵条目将为连接计数。如果某些边权重为负数,则归一化没有意义。

max_from_degree:

要考虑的最大源顶点度。如果为负数,将使用最大源度。结果矩阵的行数比此值大 1。

max_to_degree:

要考虑的最大目标顶点度。如果为负数,将使用最大目标度。结果矩阵的列数比此值大 1。

返回值: 

错误代码。

另请参阅: 

igraph_joint_degree_matrix() 用于计算联合度矩阵;igraph_assortativity_degree()igraph_assortativity() 用于计算度相关系数,以及 igraph_degree_correlation_vector() 用于计算度相关函数。

时间复杂度:O(E),其中 E 是输入图中的边数。

20.8. igraph_joint_degree_matrix — 图的联合度矩阵。

igraph_error_t igraph_joint_degree_matrix(
        const igraph_t *graph, const igraph_vector_t *weights,
        igraph_matrix_t *jdm,
        igraph_integer_t max_out_degree, igraph_integer_t max_in_degree);

警告

此函数是实验性的,其签名尚未被视为最终签名。我们保留更改函数签名的权利,而无需更改 igraph 的主要版本。使用它需要您自担风险。

在图论中,图的联合度矩阵 J_ij 给出了度 i 和度 j 的顶点之间的边数或边权重之和。此函数将 J_ij 存储到 jdm[i-1, j-1] 中。每条边,包括自环,在无向图和有向图中都只精确计数一次。

sum_(i,j) J_ij 是图中的边总数(或边权重总和)m,其中 (i,j) 分别指有向图和无向图中的有序或无序对。因此,J_ij / m 是随机选择的边(概率与其权重成正比)连接具有度 ij 的顶点的概率。

请注意,J_ij 类似于但不等同于 igraph_joint_degree_distribution() 计算的联合度分布,,该分布是为有序 (i, j) 度对定义的,即使在无向情况下也是如此。当考虑无向图时,联合度分布的对角线是联合度矩阵的两倍。

参考

Isabelle Stanton and Ali Pinar: Constructing and sampling graphs with a prescribed joint degree distribution. ACM J. Exp. Algorithmics 17, Article 3.5 (2012). https://doi.org/10.1145/2133803.2330086

参数: 

:

指向已初始化的图对象的指针。

weights:

包含边权重的向量。如果传递 NULL 指针,则假定边具有单位权重,即矩阵条目将为连接计数。

jdm:

指向将调整大小的已初始化矩阵的指针。这些值将写入此处。

max_out_degree:

结果中的行数,即要考虑的最大(出)度。如果为负数,将使用图的最大(出)度。

max_in_degree:

结果中的列数,即要考虑的最大(入)度。如果为负数,将使用图的最大(入)度。

返回值: 

错误代码。

另请参阅: 

igraph_joint_degree_distribution() 用于计数有序顶点对而不是边,或者获得归一化矩阵。

时间复杂度:O(E),其中 E 是输入图中的边数。

21. K-核和 k-桁架

21.1. igraph_coreness — 图中顶点的核数。

igraph_error_t igraph_coreness(const igraph_t *graph,
        igraph_vector_int_t *cores, igraph_neimode_t mode);

图的 k-核是一个最大子图,其中每个顶点至少具有度 k。(此处的度当然是指子图中的度)。顶点的核数是包含该顶点的 k-核的最高阶数。

此函数实现了 Vladimir Batagelj, Matjaz Zaversnik 中提出的算法:An O(m) Algorithm for Cores Decomposition of Networks. https://arxiv.org/abs/cs/0310049

参数: 

:

输入图。

cores:

指向已初始化向量的指针,计算结果将存储在此处。它将根据需要调整大小。对于每个顶点,它包含包含该顶点的核的最高阶数。

模式:

对于有向图,它指定是计算入核、出核还是无向版本。对于无向图,此参数将被忽略。可能的值:IGRAPH_ALL 无向版本,IGRAPH_IN 入核,IGRAPH_OUT 出核。

返回值: 

错误代码。

时间复杂度:O(|E|),边的数量。

21.2. igraph_trussness — 查找网络中边的“桁架性”。

igraph_error_t igraph_trussness(const igraph_t* graph, igraph_vector_int_t* trussness);

k-桁架是一个子图,其中每条边都出现在子图中的至少 k-2 个三角形中。边的桁架性表示该边出现的最高 k-桁架。

此函数返回每条边的最高 k。如果您对特定的 k-桁架子图感兴趣,您可以将图划分为那些 >= k 的边,因为每个 k-桁架都是 (k–1)-桁架的子图。因此,要获得所有 4-桁架,请采用 k >= 4,因为需要包括 5-桁架、6-桁架等。

此函数的当前实现迭代地减少每条边的支持,使用 O(|E|) 空间和 O(|E|^1.5) 时间。该实现不支持多重图;在调用此函数之前,请使用 igraph_simplify() 折叠边。

参考

参见 Wang, Jia, and James Cheng 中的算法 2. "Truss decomposition in massive networks." Proceedings of the VLDB Endowment 5.9 (2012): 812-823. https://doi.org/10.14778/2311906.2311909

参数: 

:

输入图。允许环边;不允许使用多重图。

truss:

指向桁架值初始化向量的指针,该向量将指示每条边出现的最高 k-桁架。它将根据需要调整大小。

返回值: 

错误代码。

时间复杂度:根据参考资料,它应该是 O(|E|^1.5)。

22. 拓扑排序,有向无环图

22.1. igraph_is_dag — 检查图是否是有向无环图 (DAG)。

igraph_error_t igraph_is_dag(const igraph_t* graph, igraph_bool_t *res);

有向无环图 (DAG) 是没有环的有向图。

此函数对无向图返回 false。

此函数的返回值缓存在图本身中;多次调用该函数,且中间未对图进行修改,将在 O(1) 时间内返回缓存值。

参数: 

:

输入图。

res:

指向布尔常量的指针,结果将存储在此处。

返回值: 

错误代码。

时间复杂度:O(|V|+|E|),其中 |V| 和 |E| 是原始输入图中顶点和边的数量。

另请参阅: 

igraph_topological_sorting() 用于获取 DAG 的一种可能的拓扑排序。

22.2. igraph_topological_sorting — 计算图的一种可能的拓扑排序。

igraph_error_t igraph_topological_sorting(
        const igraph_t* graph, igraph_vector_int_t *res, igraph_neimode_t mode);

有向无环图 (DAG) 的拓扑排序是其顶点的线性排序,其中每个顶点都位于与其有边的所有节点之前。每个 DAG 至少有一个拓扑排序,并且可能有多个。此函数返回其中的一种可能的拓扑排序。如果该图包含任何非自环的环,则会引发错误。

参数: 

:

输入图。

res:

指向向量的指针,结果将存储在此处。如果需要,它将调整大小。

模式:

指定如何使用边的方向。对于 IGRAPH_OUT,排序顺序确保每个顶点都位于与其有边的所有顶点之前,因此没有传入边的顶点排在最前面。对于 IGRAPH_IN,情况恰恰相反:每个顶点都位于其接收边的所有顶点之前。没有传出边的顶点排在最前面。

返回值: 

错误代码。

时间复杂度:O(|V|+|E|),其中 |V| 和 |E| 是原始输入图中顶点和边的数量。

另请参阅: 

如果您只对给定的图是否为 DAG 感兴趣,请使用 igraph_is_dag(),或者使用 igraph_feedback_arc_set() 查找一组删除后使图无环的边。

示例 13.46. 文件 examples/simple/igraph_topological_sorting.c

#include <igraph.h>
#include <stdio.h>

int main(void) {
    igraph_t graph;
    igraph_vector_int_t res;

    /* Test graph taken from http://en.wikipedia.org/wiki/Topological_sorting
     * @ 05.03.2006 */
    igraph_small(&graph, 8, IGRAPH_DIRECTED,
                 0, 3, 0, 4, 1, 3, 2, 4, 2, 7, 3, 5, 3, 6, 3, 7, 4, 6,
                 -1);

    igraph_vector_int_init(&res, 0);

    /* Sort the vertices in "increasing" order. */
    igraph_topological_sorting(&graph, &res, IGRAPH_OUT);
    igraph_vector_int_print(&res);
    printf("\n");

    /* Sort the vertices in "decreasing" order. */
    igraph_topological_sorting(&graph, &res, IGRAPH_IN);
    igraph_vector_int_print(&res);

    /* Destroy data structures when done using them. */
    igraph_destroy(&graph);
    igraph_vector_int_destroy(&res);

    return 0;
}


22.3. igraph_feedback_arc_set — 使用精确或启发式方法计算图的反馈弧集。

igraph_error_t igraph_feedback_arc_set(
        const igraph_t *graph,
        igraph_vector_int_t *result,
        const igraph_vector_t *weights,
        igraph_fas_algorithm_t algo);

反馈弧集是一组删除后使图无环的边。我们通常对最小反馈弧集感兴趣,即总权重在所有反馈弧集中最小的一组边。

对于无向图,解决方案很简单:必须找到最大权重生成树,然后删除所有不在生成树中的边。对于有向图,这是一个 NP 完全问题,通常使用各种启发式方法来找到该问题的近似解。此函数实现了精确方法和启发式方法,可以使用 algo 参数进行选择。

参考

Eades P, Lin X and Smyth WF: A fast and effective heuristic for the feedback arc set problem. Information Processing Letters 47(6), pp 319-323 (1993). https://doi.org/10.1016/0020-0190(93)90079-O

Baharev A, Hermann S, Arnold N and Tobias A: An Exact Method for the Minimum Feedback Arc Set Problem. ACM Journal of Experimental Algorithmics 26, 1–28 (2021). https://doi.org/10.1145/3446429.

参数: 

:

图对象。

result:

已初始化的向量,结果将写入此处。

weights:

权重向量,如果未指定权重,则为 NULL

algo:

如果图是有向的,则用于解决问题的算法。可能的值

IGRAPH_FAS_EXACT_IP

使用整数规划 (IP) 查找最小反馈弧集,自动选择此类型的最佳方法(当前始终为 IGRAPH_FAS_EXACT_IP_CG)。当然,复杂度至少是指数级的。

IGRAPH_FAS_EXACT_IP_CG

这是一种基于最小集合覆盖公式并使用增量约束生成 (CG) 的整数规划方法,已添加到 igraph 0.10.14 中。我们最小化 sum_e w_e b_e,并服从所有环 c 的约束 sum_e c_e b_e >= 1。此处 w_e 是边 e 的权重,b_e 是一个二进制变量(0 或 1),表示边 e 是否在反馈集中,c_e 是一个二进制系数,表示边 e 是否在环 c 中。该约束表示所有环都必须与由 b 表示的边集相交(被其打破)的要求。由于图中存在非常大量的环,因此约束是增量生成的,迭代地添加一些与当前边集 b 不相交的环,然后再次求解 b,直到最终没有未打破的环为止。此方法类似于 Baharev 等人描述的方法(尽管使用更简单的环生成方案),并且类似于 SageMath 的 feedback_edge_set 函数的实现。

IGRAPH_FAS_EXACT_IP_TI

这是另一种基于查找服从拓扑顺序的最大(最大权重)边集的整数规划方法。它使用通过三角形不等式 (TI) 的常用公式,有关概述,请参见 Baharev 等人 (2021) 的第 3.1 节。此方法在 igraph 0.10.14 之前使用,并且通常比 IGRAPH_FAS_EXACT_IP_CG 慢得多。

IGRAPH_FAS_APPROX_EADES

使用 Eades、Lin 和 Smyth (1993) 的启发式方法查找反馈弧集。这保证小于 |E|/2 - |V|/6,并且计算复杂度与边数呈线性关系(即 O(|E|))。

返回值: 

错误代码:如果指定了未知方法或权重向量无效,则为 IGRAPH_EINVAL

示例 13.47. 文件 examples/simple/igraph_feedback_arc_set.c

#include <igraph.h>
#include <string.h>

int main(void) {
    igraph_t g;
    igraph_vector_t weights;
    igraph_vector_int_t result;
    igraph_bool_t dag;

    igraph_vector_int_init(&result, 0);

    /***********************************************************************/
    /* Approximation with Eades' method                                    */
    /***********************************************************************/

    /* Simple unweighted graph */
    igraph_small(&g, 0, IGRAPH_DIRECTED, 0, 1, 1, 2, 2, 0, 2, 3, 2, 4, 0, 4, 4, 3, 5, 0, 6, 5, -1);
    igraph_feedback_arc_set(&g, &result, 0, IGRAPH_FAS_APPROX_EADES);
    igraph_vector_int_print(&result);
    igraph_delete_edges(&g, igraph_ess_vector(&result));
    igraph_is_dag(&g, &dag);
    if (!dag) {
        return 1;
    }
    igraph_destroy(&g);

    /* Simple weighted graph */
    igraph_small(&g, 0, IGRAPH_DIRECTED, 0, 1, 1, 2, 2, 0, 2, 3, 2, 4, 0, 4, 4, 3, 5, 0, 6, 5, -1);
    igraph_vector_init_int_end(&weights, -1, 1, 1, 3, 1, 1, 1, 1, 1, 1, -1);
    igraph_feedback_arc_set(&g, &result, &weights, IGRAPH_FAS_APPROX_EADES);
    igraph_vector_int_print(&result);
    igraph_delete_edges(&g, igraph_ess_vector(&result));
    igraph_is_dag(&g, &dag);
    if (!dag) {
        return 2;
    }
    igraph_vector_destroy(&weights);
    igraph_destroy(&g);

    /* Simple unweighted graph with loops */
    igraph_small(&g, 0, IGRAPH_DIRECTED, 0, 1, 1, 2, 2, 0, 2, 3, 2, 4, 0, 4, 4, 3, 5, 0, 6, 5, 1, 1, 4, 4, -1);
    igraph_feedback_arc_set(&g, &result, 0, IGRAPH_FAS_APPROX_EADES);
    igraph_vector_int_print(&result);
    igraph_delete_edges(&g, igraph_ess_vector(&result));
    igraph_is_dag(&g, &dag);
    if (!dag) {
        return 3;
    }
    igraph_destroy(&g);

    /* Null graph */
    igraph_empty(&g, 0, IGRAPH_DIRECTED);
    igraph_feedback_arc_set(&g, &result, NULL, IGRAPH_FAS_APPROX_EADES);
    if (igraph_vector_int_size(&result) != 0) {
        return 4;
    }
    igraph_destroy(&g);

    /* Singleton graph */
    igraph_empty(&g, 1, IGRAPH_DIRECTED);
    igraph_feedback_arc_set(&g, &result, NULL, IGRAPH_FAS_APPROX_EADES);
    if (igraph_vector_int_size(&result) != 0) {
        return 5;
    }
    igraph_destroy(&g);

    igraph_vector_int_destroy(&result);

    return 0;
}


示例 13.48. 文件 examples/simple/igraph_feedback_arc_set_ip.c

#include <igraph.h>
#include <string.h>

int main(void) {
    igraph_t g;
    igraph_vector_t weights;
    igraph_vector_int_t result;
    igraph_bool_t dag;
    igraph_error_t retval;

    igraph_vector_int_init(&result, 0);

    igraph_set_error_handler(&igraph_error_handler_printignore);

    /***********************************************************************/
    /* Exact solution with integer programming                             */
    /***********************************************************************/

    /* Simple unweighted graph */
    igraph_small(&g, 0, IGRAPH_DIRECTED, 0, 1, 1, 2, 2, 0, 2, 3, 2, 4, 0, 4, 4, 3, 5, 0, 6, 5, -1);
    retval = igraph_feedback_arc_set(&g, &result, 0, IGRAPH_FAS_EXACT_IP);
    if (retval == IGRAPH_UNIMPLEMENTED) {
        return 77;
    }
    igraph_vector_int_print(&result);
    igraph_delete_edges(&g, igraph_ess_vector(&result));
    igraph_is_dag(&g, &dag);
    if (!dag) {
        return 1;
    }
    igraph_destroy(&g);

    /* Simple weighted graph */
    igraph_small(&g, 0, IGRAPH_DIRECTED, 0, 1, 1, 2, 2, 0, 2, 3, 2, 4, 0, 4, 4, 3, 5, 0, 6, 5, -1);
    igraph_vector_init_int_end(&weights, -1, 1, 1, 3, 1, 1, 1, 1, 1, 1, -1);
    igraph_feedback_arc_set(&g, &result, &weights, IGRAPH_FAS_EXACT_IP);
    igraph_vector_int_print(&result);
    igraph_delete_edges(&g, igraph_ess_vector(&result));
    igraph_is_dag(&g, &dag);
    if (!dag) {
        return 2;
    }
    igraph_vector_destroy(&weights);
    igraph_destroy(&g);

    /* Simple unweighted graph with loops */
    igraph_small(&g, 0, IGRAPH_DIRECTED, 0, 1, 1, 2, 2, 0, 2, 3, 2, 4, 0, 4, 4, 3, 5, 0, 6, 5, 1, 1, 4, 4, -1);
    igraph_feedback_arc_set(&g, &result, 0, IGRAPH_FAS_EXACT_IP);
    igraph_vector_int_print(&result);
    igraph_delete_edges(&g, igraph_ess_vector(&result));
    igraph_is_dag(&g, &dag);
    if (!dag) {
        return 3;
    }
    igraph_destroy(&g);

    /* Disjoint union of two almost identical graphs */
    igraph_small(&g, 0, IGRAPH_DIRECTED,
                 0, 1, 1, 2, 2, 0, 2, 3,  2, 4,  0, 4,  4, 3,    5, 0,  6, 5, 1, 1, 4, 4,
                 7, 8, 8, 9, 9, 7, 9, 10, 9, 11, 7, 11, 11, 10, 12, 7, 13, 12,
                 -1);
    igraph_feedback_arc_set(&g, &result, 0, IGRAPH_FAS_EXACT_IP);
    igraph_vector_int_print(&result);
    igraph_delete_edges(&g, igraph_ess_vector(&result));
    igraph_is_dag(&g, &dag);
    if (!dag) {
        return 4;
    }
    igraph_destroy(&g);

    /* Graph with lots of isolated vertices */
    igraph_small(&g, 10000, IGRAPH_DIRECTED, 0, 1, -1);
    igraph_feedback_arc_set(&g, &result, 0, IGRAPH_FAS_EXACT_IP);
    igraph_vector_int_print(&result);
    igraph_delete_edges(&g, igraph_ess_vector(&result));
    igraph_is_dag(&g, &dag);
    if (!dag) {
        return 5;
    }
    igraph_destroy(&g);

    /* Null graph */
    igraph_empty(&g, 0, IGRAPH_DIRECTED);
    igraph_feedback_arc_set(&g, &result, NULL, IGRAPH_FAS_EXACT_IP);
    if (igraph_vector_int_size(&result) != 0) {
        return 6;
    }
    igraph_destroy(&g);

    /* Singleton graph */
    igraph_empty(&g, 1, IGRAPH_DIRECTED);
    igraph_feedback_arc_set(&g, &result, NULL, IGRAPH_FAS_EXACT_IP);
    if (igraph_vector_int_size(&result) != 0) {
        return 7;
    }
    igraph_destroy(&g);

    igraph_vector_int_destroy(&result);

    return 0;
}


时间复杂度:取决于 algo,请参见那里的时间复杂度。

22.4. igraph_feedback_vertex_set — 图的反馈顶点集。

igraph_error_t igraph_feedback_vertex_set(
    const igraph_t *graph, igraph_vector_int_t *result,
    const igraph_vector_t *vertex_weights, igraph_fvs_algorithm_t algo);

警告

此函数是实验性的,其签名尚未被视为最终签名。我们保留更改函数签名的权利,而无需更改 igraph 的主要版本。使用它需要您自担风险。

反馈顶点集是一组删除后使图无环的顶点。在有向图和无向图上查找最小反馈顶点集都是 NP 完全问题。

参数: 

:

图。

result:

已初始化的向量,结果将写入此处。

vertex_weights:

顶点权重向量,如果未指定权重,则为 NULL

algo:

要使用的算法。可能的值

IGRAPH_FVS_EXACT_IP

使用整数规划 (IP) 查找最小反馈顶点集。当然,复杂度至少是指数级的。目前,此方法使用类似于 igraph_feedback_arc_set()IGRAPH_FAS_EXACT_IP_CG 算法的方法。

返回值: 

错误代码。

时间复杂度:取决于 algo,请参见那里的时间复杂度。

23. 最大基数搜索和弦图

23.1. igraph_maximum_cardinality_search — 最大基数搜索。

igraph_error_t igraph_maximum_cardinality_search(const igraph_t *graph,
                                      igraph_vector_int_t *alpha,
                                      igraph_vector_int_t *alpham1);

此函数实现了最大基数搜索算法。它计算每个顶点的秩 alpha,使得按秩降序访问顶点对应于始终选择具有最多已访问邻居的顶点作为下一个访问的顶点。

最大基数搜索对于确定图的弦性很有用。一个图是弦图当且仅当一个顶点中任意两个秩比它高的邻居都相互连接。

参考

Robert E Tarjan and Mihalis Yannakakis: Simple linear-time algorithms to test chordality of graphs, test acyclicity of hypergraphs, and selectively reduce acyclic hypergraphs. SIAM Journal of Computation 13, 566--579, 1984. https://doi.org/10.1137/0213035

参数: 

:

输入图。边的方向将被忽略。

alpha:

指向已初始化向量的指针,结果存储在此处。它将根据需要调整大小。返回后,它包含每个顶点在 0 到 n - 1 范围内的秩,其中 n 是顶点的数量。

alpham1:

指向已初始化向量或 NULL 指针的指针。如果不是 NULL,则将 alpha 的逆存储在此处。换句话说,alpham1 的元素是反向最大基数搜索顺序的顶点 ID。

返回值: 

错误代码。

时间复杂度:O(|V|+|E|),相对于顶点和边的数量呈线性关系。

另请参阅: 

23.2. igraph_is_chordal — 确定图是否是弦图。

igraph_error_t igraph_is_chordal(const igraph_t *graph,
                      const igraph_vector_int_t *alpha,
                      const igraph_vector_int_t *alpham1,
                      igraph_bool_t *chordal,
                      igraph_vector_int_t *fill_in,
                      igraph_t *newgraph);

如果一个图的四个或更多节点的每个环都有一个弦,即一条连接两个不在环中相邻的节点的边,则该图是弦图。一个等效的定义是任何无弦的环最多有三个节点。如果给定了 alphaalpham1,则另一个通过简单地取逆来计算。如果两者都没有给定,则调用 igraph_maximum_cardinality_search() 来计算它们。

参数: 

:

输入图。边的方向将被忽略。

alpha:

igraph_maximum_cardinality_search()(在同一图上)获得的 alpha 向量,或 NULL 指针。

alpham1:

igraph_maximum_cardinality_search()(在同一图上)获得的逆 alpha 向量,或 NULL 指针。

chordal:

指向布尔值的指针。如果不是 NULL,则结果存储在此处。

fill_in:

指向已初始化向量的指针,或 NULL 指针。如果不是 NULL 指针,则填入,也称为图的弦补全,将存储在此处。弦补全是使图成为弦图所需的一组边。向量会根据需要调整大小。请注意,此函数返回的弦补全可能不是最小的,即可能不需要一些返回的填入边来使图成为弦图。

newgraph:

指向未初始化图的指针,或 NULL 指针。如果不是空指针,则将在此处创建一个新的三角图。这本质上意味着将填入边添加到原始图。

返回值: 

错误代码。

时间复杂度:O(n)。

另请参阅: 

24. 匹配

24.1. igraph_is_matching — 检查给定的匹配对于给定的图是否有效。

igraph_error_t igraph_is_matching(const igraph_t *graph,
                       const igraph_vector_bool_t *types, const igraph_vector_int_t *matching,
                       igraph_bool_t *result);

此函数检查匹配向量,并验证其长度是否与给定图中顶点的数量匹配,其值是否介于 -1(包括)和顶点数量(不包括)之间,以及对于每个匹配的顶点对,图中是否存在相应的边。对于二分图,它还会验证匹配的顶点是否位于图的不同部分。

参数: 

:

输入图。它可以是有向的,但边的方向将被忽略。

types:

如果图是二分图,并且您只对二分匹配感兴趣,请在此处传递顶点类型。如果图是非二分图,只需传递 NULL

matching:

匹配本身。它必须是一个向量,其中元素 i 包含与顶点 i 匹配的顶点的 ID,如果顶点 i 未匹配,则为 -1。

result:

指向布尔变量的指针,结果将返回到此处。

另请参阅: 

如果您还对匹配是否是最大匹配(即可扩展的)感兴趣,请使用 igraph_is_maximal_matching()

时间复杂度:O(|V|+|E|),其中 |V| 是顶点的数量,|E| 是边的数量。

示例 13.49. 文件 examples/simple/igraph_maximum_bipartite_matching.c

#include <igraph.h>
#include <stdio.h>

int main(void) {
    /* Test graph from the LEDA tutorial:
     * http://www.leda-tutorial.org/en/unofficial/ch05s03s05.html
     */
    igraph_t graph;
    igraph_vector_bool_t types;
    igraph_vector_int_t matching;
    igraph_integer_t matching_size;
    igraph_real_t matching_weight;
    igraph_bool_t is_matching;
    int i;

    igraph_small(&graph, 0, 0,
                 0, 8, 0, 12, 0, 14,
                 1, 9, 1, 10, 1, 13,
                 2, 8, 2, 9,
                 3, 10, 3, 11, 3, 13,
                 4, 9, 4, 14,
                 5, 14,
                 6, 9, 6, 14,
                 7, 8, 7, 12, 7, 14
                 , -1);
    igraph_vector_bool_init(&types, 15);
    for (i = 0; i < 15; i++) {
        VECTOR(types)[i] = (i >= 8);
    }
    igraph_vector_int_init(&matching, 0);

    igraph_maximum_bipartite_matching(&graph, &types, &matching_size,
                                      &matching_weight, &matching, 0, 0);
    if (matching_size != 6) {
        printf("matching_size is %" IGRAPH_PRId ", expected: 6\n", matching_size);
        return 1;
    }
    if (matching_weight != 6) {
        printf("matching_weight is %" IGRAPH_PRId ", expected: 6\n", (igraph_integer_t) matching_weight);
        return 2;
    }
    igraph_is_maximal_matching(&graph, &types, &matching, &is_matching);
    if (!is_matching) {
        printf("not a matching: ");
        igraph_vector_int_print(&matching);
        return 3;
    }

    igraph_vector_int_destroy(&matching);
    igraph_vector_bool_destroy(&types);
    igraph_destroy(&graph);

    return 0;
}


24.2. igraph_is_maximal_matching — 检查图中的匹配是否是最大匹配。

igraph_error_t igraph_is_maximal_matching(const igraph_t *graph,
                               const igraph_vector_bool_t *types, const igraph_vector_int_t *matching,
                               igraph_bool_t *result);

当且仅当图中不存在未匹配的顶点,使得其一个邻居也是未匹配的,则匹配是最大匹配。

参数: 

:

输入图。它可以是有向的,但边的方向将被忽略。

types:

如果图是二分图,并且您只对二分匹配感兴趣,请在此处传递顶点类型。如果图是非二分图,只需传递 NULL

matching:

匹配本身。它必须是一个向量,其中元素 i 包含与顶点 i 匹配的顶点的 ID,如果顶点 i 未匹配,则为 -1。

result:

指向布尔变量的指针,结果将返回到此处。

另请参阅: 

如果您只对匹配向量对于给定的图是否有效感兴趣,请使用 igraph_is_matching()

时间复杂度:O(|V|+|E|),其中 |V| 是顶点的数量,|E| 是边的数量。

示例 13.50. 文件 examples/simple/igraph_maximum_bipartite_matching.c

#include <igraph.h>
#include <stdio.h>

int main(void) {
    /* Test graph from the LEDA tutorial:
     * http://www.leda-tutorial.org/en/unofficial/ch05s03s05.html
     */
    igraph_t graph;
    igraph_vector_bool_t types;
    igraph_vector_int_t matching;
    igraph_integer_t matching_size;
    igraph_real_t matching_weight;
    igraph_bool_t is_matching;
    int i;

    igraph_small(&graph, 0, 0,
                 0, 8, 0, 12, 0, 14,
                 1, 9, 1, 10, 1, 13,
                 2, 8, 2, 9,
                 3, 10, 3, 11, 3, 13,
                 4, 9, 4, 14,
                 5, 14,
                 6, 9, 6, 14,
                 7, 8, 7, 12, 7, 14
                 , -1);
    igraph_vector_bool_init(&types, 15);
    for (i = 0; i < 15; i++) {
        VECTOR(types)[i] = (i >= 8);
    }
    igraph_vector_int_init(&matching, 0);

    igraph_maximum_bipartite_matching(&graph, &types, &matching_size,
                                      &matching_weight, &matching, 0, 0);
    if (matching_size != 6) {
        printf("matching_size is %" IGRAPH_PRId ", expected: 6\n", matching_size);
        return 1;
    }
    if (matching_weight != 6) {
        printf("matching_weight is %" IGRAPH_PRId ", expected: 6\n", (igraph_integer_t) matching_weight);
        return 2;
    }
    igraph_is_maximal_matching(&graph, &types, &matching, &is_matching);
    if (!is_matching) {
        printf("not a matching: ");
        igraph_vector_int_print(&matching);
        return 3;
    }

    igraph_vector_int_destroy(&matching);
    igraph_vector_bool_destroy(&types);
    igraph_destroy(&graph);

    return 0;
}


24.3. igraph_maximum_bipartite_matching — 计算二分图中的最大匹配。

igraph_error_t igraph_maximum_bipartite_matching(const igraph_t *graph,
                                      const igraph_vector_bool_t *types, igraph_integer_t *matching_size,
                                      igraph_real_t *matching_weight, igraph_vector_int_t *matching,
                                      const igraph_vector_t *weights, igraph_real_t eps);

二分图中的匹配是将第一种顶点的子集分配给第二种顶点的子集,使得第一种顶点的每个顶点最多与第二种顶点的一个顶点匹配,反之亦然,并且匹配的顶点必须通过图中的边连接。匹配的大小(或基数)是边的数量。如果不存在具有更大基数的其他匹配,则匹配是最大匹配。对于加权图,最大匹配是其边在所有可能的匹配中具有最大可能总权重的匹配。

二分图中的最大匹配是通过 push-relabel 算法找到的,该算法具有贪婪初始化,并在每 n/2 步后进行全局重新标记,其中 n 是图中顶点的数量。

参考文献:Cherkassky BV, Goldberg AV, Martin P, Setubal JC and Stolfi J: Augment or push: A computational study of bipartite matching and unit-capacity flow algorithms. ACM Journal of Experimental Algorithmics 3, 1998.

Kaya K, Langguth J, Manne F and Ucar B: Experiments on push-relabel-based maximum cardinality matching algorithms for bipartite graphs. Technical Report TR/PA/11/33 of the Centre Europeen de Recherche et de Formation Avancee en Calcul Scientifique, 2011.

参数: 

:

输入图。它可以是有向的,但边的方向将被忽略。

types:

给出图的顶点类型的布尔向量。

matching_size:

匹配的大小(即匹配的顶点对的数量将在此处返回)。如果不需要,它可以是 NULL

matching_weight:

如果边是加权的,则匹配的权重;如果边是未加权的,则再次是匹配的大小。如果不需要,它可以是 NULL

matching:

匹配本身。它必须是一个向量,其中元素 i 包含与顶点 i 匹配的顶点的 ID,如果顶点 i 未匹配,则为 -1。

weights:

空指针(=无边权重),或给出边权重的向量。请注意,该算法仅对整数权重稳定。

eps:

加权二分匹配算法中用于相等性测试的小实数。如果两个实数之差小于 eps,则认为它们在算法中相等。这是避免数值误差累积所必需的。建议在此处传递从 float.h 中的 DBL_EPSILON 常数派生的值。如果您在没有 weights 向量的情况下运行该算法,则此参数将被忽略。

返回值: 

错误代码。

时间复杂度:对于未加权图,为 O(sqrt(|V|) |E|(根据上面引用的技术报告),对于加权图,为 O(|V||E|)。

示例 13.51. 文件 examples/simple/igraph_maximum_bipartite_matching.c

#include <igraph.h>
#include <stdio.h>

int main(void) {
    /* Test graph from the LEDA tutorial:
     * http://www.leda-tutorial.org/en/unofficial/ch05s03s05.html
     */
    igraph_t graph;
    igraph_vector_bool_t types;
    igraph_vector_int_t matching;
    igraph_integer_t matching_size;
    igraph_real_t matching_weight;
    igraph_bool_t is_matching;
    int i;

    igraph_small(&graph, 0, 0,
                 0, 8, 0, 12, 0, 14,
                 1, 9, 1, 10, 1, 13,
                 2, 8, 2, 9,
                 3, 10, 3, 11, 3, 13,
                 4, 9, 4, 14,
                 5, 14,
                 6, 9, 6, 14,
                 7, 8, 7, 12, 7, 14
                 , -1);
    igraph_vector_bool_init(&types, 15);
    for (i = 0; i < 15; i++) {
        VECTOR(types)[i] = (i >= 8);
    }
    igraph_vector_int_init(&matching, 0);

    igraph_maximum_bipartite_matching(&graph, &types, &matching_size,
                                      &matching_weight, &matching, 0, 0);
    if (matching_size != 6) {
        printf("matching_size is %" IGRAPH_PRId ", expected: 6\n", matching_size);
        return 1;
    }
    if (matching_weight != 6) {
        printf("matching_weight is %" IGRAPH_PRId ", expected: 6\n", (igraph_integer_t) matching_weight);
        return 2;
    }
    igraph_is_maximal_matching(&graph, &types, &matching, &is_matching);
    if (!is_matching) {
        printf("not a matching: ");
        igraph_vector_int_print(&matching);
        return 3;
    }

    igraph_vector_int_destroy(&matching);
    igraph_vector_bool_destroy(&types);
    igraph_destroy(&graph);

    return 0;
}


25. 将图展开为树

25.1. igraph_unfold_tree — 通过可能地倍增顶点,将图展开为树。

igraph_error_t igraph_unfold_tree(const igraph_t *graph, igraph_t *tree,
                       igraph_neimode_t mode, const igraph_vector_int_t *roots,
                       igraph_vector_int_t *vertex_index);

通过在其上执行广度优先搜索,并将第二次、第三次等找到的顶点复制,将图转换为树(或森林,如果它是不连通的)。

参数: 

:

输入图,它可以是有向的也可以是无向的。

tree:

指向未初始化的图对象的指针,结果将存储在此处。

模式:

对于有向图; 是否沿边方向 (IGRAPH_OUT) 或相反方向 (IGRAPH_IN) 跟踪路径,或者完全忽略边方向 (IGRAPH_ALL)。 对于无向图,它将被忽略。

roots:

给出根顶点或顶点(如果图是不连通的)以开始的数值向量。

vertex_index:

指向已初始化向量的指针,或空指针。如果不是空指针,则在此处创建从新图中的顶点到原始图中顶点的映射。

返回值: 

错误代码。

时间复杂度:O(n+m),在顶点和边的数量上呈线性关系。

26. 其他操作

26.1. igraph_density — 计算图的密度。

igraph_error_t igraph_density(const igraph_t *graph, igraph_real_t *res,
                   igraph_bool_t loops);

图的密度只是其实际边数与其可能拥有的最大边数的比率。最大边数取决于解释:是否允许顶点与其自身连接?这由 loops 参数控制。

请注意,对于某些顶点对之间具有多条边的图,密度没有明确定义。考虑在这些图上调用 igraph_simplify()。此函数不检查图是否具有平行边。它为这些图返回的结果没有意义。

参数: 

:

输入图对象。它不能有平行边。

res:

指向实数的指针,结果将存储在此处。

循环:

布尔常量,是否在计算中包括自环。如果此常量为 true,则认为图中可能存在环边(这不一定意味着该图确实包含任何环)。如果这是 false,则仅当图不包含环时,结果才是正确的。

返回值: 

错误代码。

时间复杂度:O(1)。

26.2. igraph_mean_degree — 图的平均度数。

igraph_error_t igraph_mean_degree(const igraph_t *graph, igraph_real_t *res,
                                  igraph_bool_t loops);

警告

此函数是实验性的,其签名尚未被视为最终签名。我们保留更改函数签名的权利,而无需更改 igraph 的主要版本。使用它需要您自担风险。

这是一个方便函数,用于计算所有顶点度数的平均值。在有向图中,出度和入度的平均值是相同的;这是返回的数字。对于没有顶点的空图,将返回 NaN。

参数: 

:

输入图对象。

res:

指向实数的指针,结果将存储在此处。

循环:

计算过程中是否考虑自环。

返回值: 

错误代码。

时间复杂度:如果考虑自环则为 O(1),如果忽略自环则为 O(|E|),其中 |E| 是边的数量。

26.3. igraph_reciprocity — 计算有向图的互惠性。

igraph_error_t igraph_reciprocity(const igraph_t *graph, igraph_real_t *res,
                       igraph_bool_t ignore_loops,
                       igraph_reciprocity_t mode);

在有向图中,互惠性的度量定义了互连连接的比例。它最常见的定义是随机选择的有向边的相反对应方也包含在图中的概率。用邻接矩阵表示法:1 - (sum_ij |A_ij - A_ji|) / (2 sum_ij A_ij)。在多重图中,两个顶点之间的每条平行边必须有其自己单独的互惠边,与上述公式一致。如果 mode 参数为 IGRAPH_RECIPROCITY_DEFAULT,则计算此度量。

对于没有边的有向图,将返回 NaN。对于无向图,将无条件地返回 1。

在 igraph 0.6 版本之前,实现了另一种度量,定义为如果我们知道顶点对之间存在(可能非互惠)连接,则它们之间存在互连连接的概率。换句话说,(无序)顶点对被分为三组:(1)断开连接,(2)非互惠连接,(3)互惠连接。结果是组(3)的大小,除以组大小之和(2)+(3)。如果 modeIGRAPH_RECIPROCITY_RATIO,则计算此度量。

参数: 

:

图对象。

res:

指向 igraph_real_t 的指针,其中将包含结果。

ignore_loops:

计算边时是否忽略自环。自环被认为是互连连接。

模式:

要计算的互惠性类型,可能的值为 IGRAPH_RECIPROCITY_DEFAULTIGRAPH_RECIPROCITY_RATIO,请参见上面的描述。

返回值: 

错误代码:IGRAPH_EINVAL:图没有边 IGRAPH_ENOMEM:临时数据内存不足。

时间复杂度:O(|V|+|E|),|V| 是顶点数,|E| 是边数。

示例 13.52.  文件 examples/simple/igraph_reciprocity.c

#include <igraph.h>
#include <math.h>

int main(void) {

    igraph_t g;
    igraph_real_t res;

    /* Trivial cases */

    igraph_ring(&g, 100, IGRAPH_UNDIRECTED, 0, 0);
    igraph_reciprocity(&g, &res, 0, IGRAPH_RECIPROCITY_DEFAULT);
    igraph_destroy(&g);

    if (res != 1) {
        return 1;
    }

    /* Small test graph */

    igraph_small(&g, 0, IGRAPH_DIRECTED,
                 0,  1,  0,  2,  0,  3,  1,  0,  2,  3,  3,  2, -1);

    igraph_reciprocity(&g, &res, 0, IGRAPH_RECIPROCITY_RATIO);
    igraph_destroy(&g);

    if (res != 0.5) {
        fprintf(stderr, "%f != %f\n", res, 0.5);
        return 2;
    }

    igraph_small(&g, 0, IGRAPH_DIRECTED, 0, 1, 1, 2, 2, 1, -1);
    igraph_reciprocity(&g, &res, 0, IGRAPH_RECIPROCITY_DEFAULT);
    igraph_destroy(&g);

    if (fabs(res - 2.0 / 3.0) > 1e-15) {
        fprintf(stderr, "%f != %f\n", res, 2.0 / 3.0);
        return 3;
    }

    return 0;
}


26.4. igraph_diversity — 顶点的结构多样性指数。

igraph_error_t igraph_diversity(const igraph_t *graph, const igraph_vector_t *weights,
                     igraph_vector_t *res, const igraph_vs_t vids);

此度量是在 Nathan Eagle、Michael Macy 和 Rob Claxton 的《网络多样性和经济发展》(Science 328, 1029--1031, 2010) 中定义的。

它只是事件边的权重 (normalized) 香农熵。D(i) = H(i) / log(k[i]),并且 H(i) = -sum(p[i,j] log(p[i,j]), j=1..k[i]),其中 p[i,j] = w[i,j] / sum(w[i,l], l=1..k[i])k[i] 是顶点 i 的(总)度数,w[i,j] 是顶点 ij 之间的边的权重。孤立顶点的多样性将为 NaN(非数字),而具有单个连接的顶点的多样性将为零。

该度量仅在图是无向且没有多条边时才有效。如果图有多条边,请首先使用 igraph_simplify() 进行简化。如果图是有向图,请使用 igraph_to_undirected() 将其转换为无向图。

参数: 

:

无向输入图。

weights:

边权重,按边 ID 的顺序,必须具有适当的长度。权重必须为非负数。

res:

已初始化的向量,结果存储在此处。

vids:

顶点选择器,用于指定要计算度量的顶点。

返回值: 

错误代码。

时间复杂度:O(|V|+|E|),线性。

26.5. igraph_is_mutual — 检查有向图的某些边是否互惠。

igraph_error_t igraph_is_mutual(const igraph_t *graph, igraph_vector_bool_t *res,
                                igraph_es_t es, igraph_bool_t loops);

如果图也包含 (B,A) 边,则 (A,B) 非循环有向边是互惠的。有向自环是否被认为是互惠的由 loops 参数控制。

根据定义,无向图只有互惠边。

此处不考虑边重数,例如,如果有两条 (A,B) 边和一条 (B,A) 边,则所有三条边都被认为是互惠的。

参数: 

:

输入图。

res:

指向初始化向量的指针,结果存储在此处。

es:

要检查的边序列。提供 igraph_ess_all() 以检查所有边。

循环:

布尔值,是否将有向自环视为互惠。

返回值: 

错误代码。

时间复杂度:O(n log(d)),n 是提供的边数,d 是作为提供的边的目标的顶点的最大入度。时间复杂度的上限为 O(n log(|E|)),|E| 是图中的边数。

26.6. igraph_has_mutual — 检查有向图是否具有任何互惠边。

igraph_error_t igraph_has_mutual(const igraph_t *graph, igraph_bool_t *res,
                                 igraph_bool_t loops);

如果图也包含 (B,A) 边,则 (A,B) 非循环有向边是互惠的。有向自环是否被认为是互惠的由 loops 参数控制。

在无向图中,根据定义,所有边都被认为是互惠的。因此,对于无向图,此函数仅在没有边时返回 false。

要检查图是否为定向图,请将此函数与 igraph_is_directed() 一起使用。

参数: 

:

输入图。

res:

指向布尔值的指针,结果将存储在此处。

循环:

布尔值,是否将有向自环视为互惠。

返回值: 

错误代码。

时间复杂度:O(|E| log(d)),其中 d 是最大入度。

26.7. igraph_get_adjacency — 图的邻接矩阵。

igraph_error_t igraph_get_adjacency(
    const igraph_t *graph, igraph_matrix_t *res, igraph_get_adjacency_t type,
    const igraph_vector_t *weights, igraph_loops_t loops
);

结果是邻接矩阵。矩阵的条目 i, j 包含在未加权情况下连接顶点 i 到顶点 j 的边数,或在加权情况下连接顶点 i 到顶点 j 的边的总权重。

参数: 

:

指向要转换的图的指针

res:

指向初始化的矩阵对象的指针,如果需要,将调整其大小。

类型:

指定要为无向图创建的邻接矩阵类型的常量。对于有向图,它将被忽略。可能的值

IGRAPH_GET_ADJACENCY_UPPER

使用矩阵的右上三角形。

IGRAPH_GET_ADJACENCY_LOWER

使用矩阵的左下三角形。

IGRAPH_GET_ADJACENCY_BOTH

使用整个矩阵,如果图是无向的,则返回对称矩阵。

weights:

一个可选向量,包含图中每条边的权重。在此处提供一个空指针以使所有边具有相同的权重 1。

循环:

指定应如何处理循环边的常量。可能的值

IGRAPH_NO_LOOPS

循环边被忽略,并且矩阵的对角线将仅包含零

IGRAPH_LOOPS_ONCE

循环边被计数一次,即,具有单个未加权循环边的顶点将在相应的对角线条目中具有 1

IGRAPH_LOOPS_TWICE

循环边在 无向 图中被计数两次,即,无向图中具有单个未加权循环边的顶点将在相应的对角线条目中具有 2。有向图中的循环边仍然计为 1。本质上,这意味着该函数正在计数事件边 ,这在使用线性代数中的邻接矩阵时更有意义。

返回值: 

错误代码:IGRAPH_EINVAL 无效的类型参数。

另请参阅: 

如果您需要稀疏矩阵表示,请使用 igraph_get_adjacency_sparse()

时间复杂度:O(|V||V|),|V| 是图中的顶点数。

26.8. igraph_get_adjacency_sparse — 以稀疏矩阵格式返回图的邻接矩阵。

igraph_error_t igraph_get_adjacency_sparse(
    const igraph_t *graph, igraph_sparsemat_t *res, igraph_get_adjacency_t type,
    const igraph_vector_t *weights, igraph_loops_t loops
);

参数: 

:

输入图。

res:

指向 初始化 的稀疏矩阵的指针。结果将存储在此处。如果需要,将调整矩阵的大小。

类型:

指定要为无向图创建的邻接矩阵类型的常量。对于有向图,它将被忽略。可能的值

IGRAPH_GET_ADJACENCY_UPPER

使用矩阵的右上三角形。

IGRAPH_GET_ADJACENCY_LOWER

使用矩阵的左下三角形。

IGRAPH_GET_ADJACENCY_BOTH

使用整个矩阵,如果图是无向的,则返回对称矩阵。

返回值: 

错误代码:IGRAPH_EINVAL 无效的类型参数。

另请参阅: 

igraph_get_adjacency(),此函数的密集版本。

时间复杂度:待定。

26.9. igraph_get_stochastic — 图的随机邻接矩阵。

igraph_error_t igraph_get_stochastic(
    const igraph_t *graph, igraph_matrix_t *res, igraph_bool_t column_wise,
    const igraph_vector_t *weights
);

图的随机矩阵。图的随机矩阵是其邻接矩阵,按行或按列标准化,使得每行(或每列)的总和为 1。

参数: 

:

输入图。

res:

指向初始化矩阵的指针,结果存储在此处。如果需要,将调整其大小。

column_wise:

是否按列标准化。

返回值: 

错误代码。

时间复杂度:O(|V||V|),|V| 是图中的顶点数。

另请参阅: 

igraph_get_stochastic_sparse(),此函数的稀疏版本。

26.10. igraph_get_stochastic_sparse — 图的随机邻接矩阵。

igraph_error_t igraph_get_stochastic_sparse(
    const igraph_t *graph, igraph_sparsemat_t *res, igraph_bool_t column_wise,
    const igraph_vector_t *weights
);

图的随机矩阵。图的随机矩阵是其邻接矩阵,按行或按列标准化,使得每行(或每列)的总和为 1。

参数: 

:

输入图。

res:

指向 初始化 的稀疏矩阵的指针,结果存储在此处。如果需要,将调整矩阵的大小。

column_wise:

是否按列标准化。

返回值: 

错误代码。

时间复杂度:O(|V|+|E|),顶点数和边数的线性关系。

另请参阅: 

igraph_get_stochastic(),此函数的密集版本。

26.11. igraph_get_edgelist — 图中的边列表。

igraph_error_t igraph_get_edgelist(const igraph_t *graph, igraph_vector_int_t *res, igraph_bool_t bycol);

边的顺序由边 ID 给出。

参数: 

:

指向图对象的指针

res:

指向初始化向量对象的指针,将调整其大小。

bycol:

布尔常量。如果为 true,则将按列返回边,例如,第一条边为 res[0]->res[|E|],第二条边为 res[1]->res[|E|+1],依此类推。提供 false 以获得与 igraph_add_edges() 兼容格式的边列表。

返回值: 

错误代码。

另请参阅: 

igraph_edges() 仅返回某些边 ID 的结果。

时间复杂度:O(|E|),图中边的数量。

27. 已弃用的函数

27.1. igraph_are_connected — 确定两个顶点是否相邻(已弃用的别名)。

igraph_error_t igraph_are_connected(const igraph_t *graph,
                                   igraph_integer_t v1, igraph_integer_t v2,
                                   igraph_bool_t *res);

警告

自 0.10.10 版本起已弃用。请不要在新代码中使用此函数;请改用 igraph_are_adjacent()

确定是否存在以 v1v2 作为端点的边。 对于无向图,此函数当然是对称的。

参数: 

:

图对象。

v1:

第一个顶点。

v2:

第二个顶点。

res:

布尔值,如果存在从 v1v2 的边,则为 true,否则为 false

返回值: 

如果给出了无效的顶点 ID,则返回错误代码 IGRAPH_EINVVID

时间复杂度:O( min(log(d1), log(d2)) ),d1 是 v1 的(出)度,d2 是 v2 的(入)度。

27.2. igraph_shortest_paths — 顶点之间最短路径的长度。

igraph_error_t igraph_shortest_paths(const igraph_t *graph,
                                     igraph_matrix_t *res,
                                     const igraph_vs_t from,
                                     const igraph_vs_t to,
                                     igraph_neimode_t mode);

警告

自 0.10.0 版本起已弃用。请不要在新代码中使用此函数;请改用 igraph_distances()

27.3. igraph_shortest_paths_dijkstra — 顶点之间的加权最短路径长度(已弃用)。

igraph_error_t igraph_shortest_paths_dijkstra(const igraph_t *graph,
                                       igraph_matrix_t *res,
                                       const igraph_vs_t from,
                                       const igraph_vs_t to,
                                       const igraph_vector_t *weights,
                                       igraph_neimode_t mode);

警告

自 0.10.0 版本起已弃用。请不要在新代码中使用此函数;请改用 igraph_distances_dijkstra()

27.4. igraph_shortest_paths_bellman_ford — 顶点之间的加权最短路径长度,允许负权重(已弃用)。

igraph_error_t igraph_shortest_paths_bellman_ford(const igraph_t *graph,
                                       igraph_matrix_t *res,
                                       const igraph_vs_t from,
                                       const igraph_vs_t to,
                                       const igraph_vector_t *weights,
                                       igraph_neimode_t mode);

警告

自 0.10.0 版本起已弃用。请不要在新代码中使用此函数;请改用 igraph_distances_bellman_ford()

27.5. igraph_shortest_paths_johnson — 顶点之间的加权最短路径长度,使用 Johnson 算法(已弃用)。

igraph_error_t igraph_shortest_paths_johnson(const igraph_t *graph,
                                  igraph_matrix_t *res,
                                  const igraph_vs_t from,
                                  const igraph_vs_t to,
                                  const igraph_vector_t *weights);

警告

自 0.10.0 版本起已弃用。请不要在新代码中使用此函数;请改用 igraph_distances_johnson()

27.6. igraph_get_stochastic_sparsemat — 图的随机邻接矩阵(已弃用)。

igraph_error_t igraph_get_stochastic_sparsemat(const igraph_t *graph,
                                               igraph_sparsemat_t *res,
                                               igraph_bool_t column_wise);

此函数已被弃用,建议使用 igraph_get_stochastic_sparse(),但工作方式并不完全相同。此函数接受一个 未初始化igraph_sparsemat_t,而 igraph_get_stochastic_sparse() 接受一个已初始化的 igraph_sparsemat_t

参数: 

:

输入图。

res:

指向 未初始化 的稀疏矩阵的指针,结果存储在此处。如果需要,将调整矩阵的大小。

column_wise:

是否按列标准化。对于无向图,此参数没有任何影响。

返回值: 

错误代码。

警告

自 0.10.0 版本起已弃用。请不要在新代码中使用此函数;请改用 igraph_get_stochastic_sparse()

27.7. igraph_get_sparsemat — 将 igraph 图转换为稀疏矩阵(已弃用)。

igraph_error_t igraph_get_sparsemat(const igraph_t *graph, igraph_sparsemat_t *res);

如果图是无向的,则创建对称矩阵。

此函数已被弃用,建议使用 igraph_get_adjacency_sparse(),但工作方式并不完全相同。此函数接受一个 未初始化igraph_sparsemat_t,而 igraph_get_adjacency_sparse() 接受一个已初始化的 igraph_sparsemat_t

参数: 

:

输入图。

res:

指向 未初始化 的稀疏矩阵的指针。结果将存储在此处。

返回值: 

错误代码。

警告

自 0.10.0 版本起已弃用。请不要在新代码中使用此函数;请改用 igraph_get_adjacency_sparse()

27.8. igraph_laplacian — 返回图的拉普拉斯矩阵(已弃用)。

igraph_error_t igraph_laplacian(
    const igraph_t *graph, igraph_matrix_t *res, igraph_sparsemat_t *sparseres,
    igraph_bool_t normalized, const igraph_vector_t *weights
);

此函数以密集或稀疏格式生成图的拉普拉斯矩阵。当 normalized 设置为 true 时,使用的标准化类型取决于图的直接性:对称标准化用于无向图,左随机标准化用于有向图。

参数: 

:

指向要转换的图的指针。

res:

指向初始化矩阵对象或 NULL 的指针。密集矩阵结果将存储在此处。

sparseres:

指向初始化稀疏矩阵对象或 NULL 的指针。稀疏矩阵结果将存储在此处。

模式:

控制是否在有向图中使用出度或入度。如果设置为 IGRAPH_ALL,则将忽略边方向。

normalized:

布尔值,是否标准化结果。

weights:

一个可选向量,包含非负边权重,用于计算加权拉普拉斯矩阵。将其设置为空指针以计算未加权拉普拉斯算子。

返回值: 

错误代码。

警告

自 0.10.0 版本起已弃用。请不要在新代码中使用此函数;请改用 igraph_get_laplacian()

27.9. igraph_hub_score — Kleinberg 的 hub 分数。

igraph_error_t igraph_hub_score(const igraph_t *graph, igraph_vector_t *vector,
                     igraph_real_t *value, igraph_bool_t scale,
                     const igraph_vector_t *weights,
                     igraph_arpack_options_t *options);

警告

自 0.10.5 版本起已弃用。请不要在新代码中使用此函数;请改用 igraph_hub_and_authority_scores()

顶点的 hub 分数定义为 A A^T 的主特征向量,其中 A 是图的邻接矩阵,A^T 是其转置。

请参阅以下有关此分数含义的参考资料:J. Kleinberg。超链接环境中的权威来源。 Proc. 9th ACM-SIAM Symposium on Discrete Algorithms, 1998。扩展版本见 Journal of the ACM 46(1999)。也出现在 IBM 研究报告 RJ 10076 中,1997 年 5 月。

参数: 

:

输入图。可以是定向的也可以是非定向的。

vector:

指向初始化向量的指针,结果存储在此处。如果为空指针,则将其忽略。

value:

如果不是空指针,则与计算出的特征向量相对应的特征值将存储在此处。

scale:

如果不为零,则将缩放结果,使得最大中心性的绝对值为 1。

weights:

空指针(=无边权重),或提供边权重的向量。

选项:

ARPACK 的选项。有关详细信息,请参见 igraph_arpack_options_t。请注意,该函数会覆盖 n(顶点数)参数,并且始终从基于顶点度数计算的非随机向量开始计算。

返回值: 

错误代码。

时间复杂度:取决于输入图,通常为 O(|V|),顶点的数量。

另请参阅: 

igraph_hub_and_authority_scores() 可以同时有效地计算 hub 和 authority 分数,igraph_authority_score() 用于伴随度量,igraph_pagerank(), igraph_personalized_pagerank(), igraph_eigenvector_centrality() 用于类似的度量。

27.10. igraph_authority_score — Kleinberg 的 authority 分数。

igraph_error_t igraph_authority_score(const igraph_t *graph, igraph_vector_t *vector,
                           igraph_real_t *value, igraph_bool_t scale,
                           const igraph_vector_t *weights,
                           igraph_arpack_options_t *options);

警告

自 0.10.5 版本起已弃用。请不要在新代码中使用此函数;请改用 igraph_hub_and_authority_scores()

顶点的 authority 分数定义为 A^T A 的主特征向量,其中 A 是图的邻接矩阵,A^T 是其转置。

请参阅以下有关此分数含义的参考资料:J. Kleinberg。超链接环境中的权威来源。 Proc. 9th ACM-SIAM Symposium on Discrete Algorithms, 1998。扩展版本见 Journal of the ACM 46(1999)。也出现在 IBM 研究报告 RJ 10076 中,1997 年 5 月。

参数: 

:

输入图。可以是定向的也可以是非定向的。

vector:

指向初始化向量的指针,结果存储在此处。如果为空指针,则将其忽略。

value:

如果不是空指针,则与计算出的特征向量相对应的特征值将存储在此处。

scale:

如果不为零,则将缩放结果,使得最大中心性的绝对值为 1。

weights:

空指针(=无边权重),或提供边权重的向量。

选项:

ARPACK 的选项。有关详细信息,请参见 igraph_arpack_options_t。请注意,该函数会覆盖 n(顶点数)参数,并且始终从基于顶点度数计算的非随机向量开始计算。

返回值: 

错误代码。

时间复杂度:取决于输入图,通常为 O(|V|),顶点的数量。

另请参阅: 

igraph_hub_and_authority_scores() 可以同时有效地计算 hub 和 authority 分数,igraph_hub_score() 用于伴随度量,igraph_pagerank(), igraph_personalized_pagerank(), igraph_eigenvector_centrality() 用于类似的度量。