igraph 参考手册

用于使用 igraph C 库

搜索手册

第 32 章. 非图相关函数

1. igraph 版本号

1.1. igraph_version — igraph C 库的版本。

void igraph_version(const char **version_string,
                    int *major,
                    int *minor,
                    int *subminor);

参数: 

version_string:

指向字符串指针的指针。如果不是 null,则设置为 igraph 版本字符串,例如“0.9.11”或“0.10.0”。此字符串不得修改或释放。

major:

如果不是空指针,则设置为 igraph 主版本号。例如,对于版本“0.9.11”,此值为 0。

minor:

如果不是空指针,则设置为 igraph 次版本号。例如,对于版本“0.9.11”,此值为 11。

subminor:

如果不是空指针,则设置为 igraph 子版本号。例如,对于版本“0.9.11”,此值为 11。

示例 32.1.  文件 examples/simple/igraph_version.c

#include <igraph.h>
#include <string.h>

int main(void) {

    char tmp[100];
    const char *string;
    int major, minor, subminor;

    igraph_version(&string, &major, &minor, &subminor);
    snprintf(tmp, sizeof(tmp), "%i.%i.%i", major, minor, subminor);

    if (strncmp(string, tmp, strlen(tmp))) {
        return 1;
    }

    return 0;
}


2. 时间序列的移动平均

2.1. igraph_running_mean — 计算向量的移动平均值。

igraph_error_t igraph_running_mean(const igraph_vector_t *data, igraph_vector_t *res,
                        igraph_integer_t binwidth);

移动平均值由前一个 binwidth 值的平均值定义。

参数: 

数据:

包含数据的向量。

res:

包含结果的向量。应在调用此函数之前对其进行初始化,并将调整其大小。

binwidth:

整数,给出用于移动平均值计算的 bin 的宽度。

返回值: 

错误代码。

时间复杂度:O(n),其中 n 是数据向量的长度。

3. 从非常长的序列中随机抽样

3.1. igraph_random_sample — 生成递增的随机整数序列。

igraph_error_t igraph_random_sample(igraph_vector_int_t *res, igraph_integer_t l, igraph_integer_t h,
                         igraph_integer_t length);

此函数生成来自给定区间的递增的随机整数序列。该算法完全取自 (Vitter 1987)。此方法可用于从非常大的区间生成数字。它主要用于从大型图中可能的边的有时很大的集合中随机选择一些边。

参考

J. S. Vitter. An efficient algorithm for sequential random sampling. ACM Transactions on Mathematical Software, 13(1):58--67, 1987. https://doi.org/10.1145/23002.23003

参数: 

res:

指向已初始化向量的指针。这将保存结果。将调整其大小以适合。

l:

生成区间的下限(包括)。此值必须小于或等于上限,并且必须为整数。

h:

生成区间的上限(包括)。此值必须大于或等于下限,并且必须为整数。

length:

要生成的随机整数的数量。

返回值: 

在以下每种情况下,都会返回错误代码 IGRAPH_EINVAL:(1) 给定的下限大于给定的上限,即 l > h。(2) 假设 l < h 并且 N 是样本大小,如果 N > |h - l|,则返回上述错误代码,即样本大小超过候选池的大小。

时间复杂度:根据 (Vitter 1987),预期运行时间为 O(length)。

示例 32.2.  文件 examples/simple/igraph_random_sample.c

#include <igraph.h>

int main(void) {
    igraph_vector_int_t V;

    igraph_vector_int_init(&V, 0);

    igraph_random_sample(&V, 0, 100, 5);

    igraph_vector_int_print(&V);

    igraph_vector_int_destroy(&V);
}


4. 空间点的随机抽样

4.1. igraph_sample_sphere_surface — 从球面上均匀采样点。

igraph_error_t igraph_sample_sphere_surface(igraph_integer_t dim, igraph_integer_t n,
                                 igraph_real_t radius,
                                 igraph_bool_t positive,
                                 igraph_matrix_t *res);

球的中心位于原点。

参数: 

dim:

随机向量的维度。

n:

要采样的向量数。

radius:

球的半径,必须为正数。

positive:

是否将采样限制为正卦限。

res:

指向已初始化矩阵的指针,结果存储在此处,每一列将是一个采样的向量。必要时会调整矩阵大小。

返回值: 

错误代码。

时间复杂度:O(n*dim*g),其中 g 是生成标准正态随机数的时间复杂度。

另请参阅: 

igraph_sample_sphere_volume(), igraph_sample_dirichlet() 用于其他类似的采样器。

4.2. igraph_sample_sphere_volume — 从球的体积内均匀采样点。

igraph_error_t igraph_sample_sphere_volume(igraph_integer_t dim, igraph_integer_t n,
                                igraph_real_t radius,
                                igraph_bool_t positive,
                                igraph_matrix_t *res);

球的中心位于原点。

参数: 

dim:

随机向量的维度。

n:

要采样的向量数。

radius:

球的半径,必须为正数。

positive:

是否将采样限制为正卦限。

res:

指向已初始化矩阵的指针,结果存储在此处,每一列将是一个采样的向量。必要时会调整矩阵大小。

返回值: 

错误代码。

时间复杂度:O(n*dim*g),其中 g 是生成标准正态随机数的时间复杂度。

另请参阅: 

igraph_sample_sphere_surface(), igraph_sample_dirichlet() 用于其他类似的采样器。

4.3. igraph_sample_dirichlet — 从 Dirichlet 分布中采样点。

igraph_error_t igraph_sample_dirichlet(igraph_integer_t n, const igraph_vector_t *alpha,
                            igraph_matrix_t *res);

参数: 

n:

要采样的向量数。

alpha:

Dirichlet 分布的参数。它们必须是正数。此向量的长度给出生成的样本的维度。

res:

指向已初始化矩阵的指针,结果存储在此处,每个样本在一列中。必要时会调整其大小。

返回值: 

错误代码。

时间复杂度:O(n * dim * g),其中 dim 是样本向量的维度,由 alpha 的长度设置,g 是从 Gamma 分布中采样的时间复杂度。

另请参阅: 

igraph_sample_sphere_surface()igraph_sample_sphere_volume() 用于其他采样潜在向量的方法。

5. 平面上点集的凸包

5.1. igraph_convex_hull — 确定给定平面上点集的凸包。

igraph_error_t igraph_convex_hull(
    const igraph_matrix_t *data, igraph_vector_int_t *resverts,
    igraph_matrix_t *rescoords
);

凸包由 Graham 扫描算法确定。有关详细信息,请参阅以下参考资料

Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, and Clifford Stein. Introduction to Algorithms, Second Edition. MIT Press and McGraw-Hill, 2001. ISBN 0262032937. Pages 949-955 of section 33.3: Finding the convex hull.

参数: 

数据:

包含坐标的向量。向量的长度必须是偶数,因为它包含 X-Y 坐标对。

resverts:

包含结果的向量,例如,用作凸包角的顶点索引向量。如果您只对凸包角的坐标感兴趣,请在此处提供 NULL

rescoords:

包含所选角顶点的坐标的矩阵。如果您只对顶点索引感兴趣,请在此处提供 NULL

返回值: 

错误代码:IGRAPH_ENOMEM:内存不足

时间复杂度:O(n log(n)),其中 n 是顶点的数量。

6. 将幂律分布拟合到经验数据

6.1. igraph_plfit_result_t — 将幂律分布拟合到向量的结果。

typedef struct igraph_plfit_result_t {
    igraph_bool_t continuous;
    igraph_real_t alpha;
    igraph_real_t xmin;
    igraph_real_t L;
    igraph_real_t D;
    const igraph_vector_t* data;
} igraph_plfit_result_t;

此数据结构包含 igraph_power_law_fit() 的结果,它尝试将幂律分布拟合到数字向量。该结构包含以下成员

值: 

continuous:

拟合的幂律分布是连续的还是离散的。

alpha:

alpha

xmin:

从中拟合幂律分布的最小值。换句话说,输入向量中仅使用了大于 xmin 的值。

L:

拟合参数的对数似然;换句话说,观察给定参数的输入向量的概率。

D:

将拟合分布与输入向量进行比较的 Kolmogorov-Smirnov 检验的检验统计量。较小的分数表示更好的拟合。

p:

Kolmogorov-Smirnov 检验的 p 值;如果尚未计算,则为 NaN。较小的 p 值(小于 0.05)表示检验拒绝了原始数据可以从拟合幂律分布中提取的假设。

数据:

包含原始输入数据的向量。如果调用方已经销毁了该向量,则可能不再有效。

6.2. igraph_power_law_fit — 将幂律分布拟合到数字向量。

igraph_error_t igraph_power_law_fit(
    const igraph_vector_t* data, igraph_plfit_result_t* result,
    igraph_real_t xmin, igraph_bool_t force_continuous
);

此函数将幂律分布拟合到包含分布样本的向量(假设遵循幂律)。在幂律分布中,通常假设 P(X=x) 与 x-alpha 成正比,其中 x 是正数,alpha 大于 1。在许多现实世界的案例中,幂律行为仅在阈值 xmin 以上开始。此函数的目标是确定给定 xminalpha,或者确定 xmin 以及 alpha 的相应值。

该函数使用最大似然原理来确定给定 xminalpha;换句话说,该函数将返回绘制给定样本的概率最高的 alpha 值。当没有提前给出 xmin 时,该算法将尝试找到最佳的 xmin 值,对于该值,拟合分布和原始样本之间的 Kolmogorov-Smirnov 检验的 p 值最大。该函数使用 Clauset、Shalizi 和 Newman 的方法来计算拟合分布的参数。有关详细信息,请参阅以下参考资料

Aaron Clauset, Cosma R. Shalizi and Mark E.J. Newman: Power-law distributions in empirical data. SIAM Review 51(4):661-703, 2009. https://doi.org/10.1137/070710111

参数: 

数据:

包含要拟合幂律分布的样本的向量。请注意,您必须提供 样本,而不是概率密度函数或累积分布函数。例如,如果您希望将幂律拟合到图的度数,则可以将 igraph_degree 的输出直接作为 igraph_power_law_fit 的输入参数。

result:

拟合算法的结果。有关更多详细信息,请参见 igraph_plfit_result_t。请注意,默认情况下计算拟合的 p 值,因为它很耗时;您需要调用 igraph_plfit_result_calculate_p_value() 来计算 p 值本身

xmin:

样本向量中预期幂律行为开始的最小值。小于 xmin 的样本将被该算法忽略。如果您想包括所有样本,请在此处传递零。如果 xmin 为负数,则该算法将尝试自动确定其最佳值。

force_continuous:

假设 data 参数中的样本来自连续分布,即使样本向量仅包含整数值(偶然)。如果此参数为 false,则 igraph 将假设至少有一个样本是非整数的连续分布,否则将假设离散分布。

返回值: 

错误代码:IGRAPH_ENOMEM:内存不足 IGRAPH_EINVAL:参数之一无效 IGRAPH_EOVERFLOW:拟合过程中溢出 IGRAPH_EUNDERFLOW:拟合过程中下溢 IGRAPH_FAILURE:底层算法发出失败信号,而没有返回更具体的错误代码

时间复杂度:在连续情况下,如果给定 xmin,则为 O(n log(n))。在离散情况下,时间复杂度由用于优化 alpha 的底层 L-BFGS 算法的复杂度决定。如果未给定 xmin,则时间复杂度乘以输入向量中唯一样本的数量(尽管在实践中应该更快)。

示例 32.3.  文件 examples/simple/igraph_power_law_fit.c

#include <igraph.h>

int main(void) {
    igraph_t g;
    igraph_vector_t degree;
    igraph_plfit_result_t model;

    /* Seed random number generator to ensure reproducibility. */
    igraph_rng_seed(igraph_rng_default(), 42);

    /* Generate a BA network; degree distribution is supposed to be a power-law
     * if the graph is large enough */
    igraph_barabasi_game(
        &g, 10000, /*power=*/ 1, /*m=*/ 2,
        /* outseq= */ 0, /* outpref= */ 0, /*A=*/ 1,
        IGRAPH_UNDIRECTED, IGRAPH_BARABASI_BAG,
        /*start_from=*/ 0
    );

    /* Get the vertex degrees. We use igraph_strength() because it stores its
     * result in an igraph_vector_t */
    igraph_vector_init(&degree, 0);
    igraph_strength(&g, &degree, igraph_vss_all(), IGRAPH_ALL, IGRAPH_NO_LOOPS, 0);

    /* Fit a power-law to the degrees */
    igraph_power_law_fit(
        &degree, &model, /* xmin = */ -1,
        /* force_continuous = */ 0
    );

    /* If you also need a p-value: */
    /* igraph_plfit_result_calculate_p_value(&model, &p, 0.001); */

    printf("alpha = %.5f\n", model.alpha);
    printf("xmin = %.5f\n", model.xmin);
    printf("log-likelihood = %.5f\n", model.L);

    igraph_vector_destroy(&degree);
    igraph_destroy(&g);

    return 0;
}


6.3. igraph_plfit_result_calculate_p_value — 计算拟合幂律模型的 p 值。

igraph_error_t igraph_plfit_result_calculate_p_value(
    const igraph_plfit_result_t* model, igraph_real_t* result, igraph_real_t precision
);

p 值的计算方法是,以一种方式对输入数据进行多次重新采样,即低于拟合的 x_min 阈值的部分从输入数据本身重新采样,而高于拟合的 x_min 阈值的部分从拟合的幂律函数中提取。然后对每个重新采样的数据集执行 Kolmogorov-Smirnov 检验,并将其检验统计量与原始数据集中的观测检验统计量进行比较。具有更高检验统计量的重新采样数据集的分数是返回的 p 值。

请注意,返回的 p 值的精度取决于重新采样的尝试次数。重新采样试验的次数由 0.25 除以所需精度的平方确定。例如,所需的精度为 0.01 意味着将绘制 2500 个样本。

如果 igraph 是使用 OpenMP 支持编译的,则此函数将使用并行 OpenMP 线程进行重新采样。每个 OpenMP 线程都获得其自己的随机数生成器实例。但是,由于 OpenMP 线程的调度不在我们的控制范围内,因此我们无法保证线程被要求执行多少个重新采样实例,因此可能会发生随机数生成器在运行之间使用不同的情况。如果您想获得可重现的结果,请适当地播种 igraph 的主 RNG,并强制 OpenMP 线程的数量为 1,在程序中早期,可以通过调用 omp_set_num_threads(1) 或将 OMP_NUM_THREADS 环境变量的值设置为 1。

参数: 

model:

来自 igraph_power_law_fit() 函数的拟合幂律模型

result:

计算出的 p 值在此处返回

precision:

p 值的所需精度。较高的值对应于更长的计算时间。@return igraph_error_t

7. 在容差范围内比较浮点数

7.1. igraph_cmp_epsilon — 在容差范围内比较两个双精度浮点数。

int igraph_cmp_epsilon(double a, double b, double eps);

确定两个双精度浮点数是否在给定的相对误差容差范围内“几乎相等”。

该函数支持无穷大和 NaN 值。NaN 值被认为不等于任何其他值(甚至是另一个 NaN),但排序是任意的;换句话说,我们仅保证将 NaN 与任何其他值进行比较不会返回零。正无穷大被认为大于任何容差内的任何有限值。负无穷大被认为小于任何容差内的任何有限值。正无穷大被认为等于任何容差内的另一个正无穷大。负无穷大被认为等于任何容差内的另一个负无穷大。

参数: 

a:

第一个浮点数。

b:

第二个浮点数。

eps:

相对误差的容差级别。相对误差定义为 abs(a-b) / (abs(a) + abs(b))。如果小于 eps,则认为这两个数字相等。不允许使用负 epsilon 值;在这种情况下,返回值将是未定义的。零意味着进行精确比较,而没有容差。

返回值: 

如果两个浮点数在给定的容差级别内几乎彼此相等,则为零;如果第一个浮点数较大,则为正数;如果第二个浮点数较大,则为负数。

7.2. igraph_almost_equals — 在容差范围内比较两个双精度浮点数。

igraph_bool_t igraph_almost_equals(double a, double b, double eps);

确定两个双精度浮点数是否在给定的相对误差容差范围内“几乎相等”。

参数: 

a:

第一个浮点数。

b:

第二个浮点数。

eps:

相对误差的容差级别。相对误差定义为 abs(a-b) / (abs(a) + abs(b))。如果小于 eps,则认为这两个数字相等。

返回值: 

如果两个浮点数在给定的容差级别内几乎彼此相等,则为 True,否则为 False。

7.3. igraph_complex_almost_equals — 在容差范围内比较两个复数。

igraph_bool_t igraph_complex_almost_equals(igraph_complex_t a,
                                           igraph_complex_t b,
                                           igraph_real_t eps);

确定两个复数是否在给定的相对误差容差范围内“几乎相等”。

参数: 

a:

第一个复数。

b:

第二个复数。

eps:

相对误差的容差级别。相对误差定义为 abs(a-b) / (abs(a) + abs(b))。如果小于 eps,则认为这两个数字相等。

返回值: 

如果两个复数在给定的容差级别内几乎彼此相等,则为 True,否则为 False。