用于使用 igraph C 库
igraph 中的一些算法,例如从随机图模型中采样,需要随机数生成器 (RNG)。 igraph 包括一个灵活的 RNG 框架,允许连接任意随机数生成器,并附带了几个即用型生成器。该框架用于 igraph 的高级接口中,以与宿主语言自己的 RNG 集成。
void igraph_rng_set_default(igraph_rng_t *rng);
该函数复制给定 igraph_rng_t 对象的内部结构到 igraph 的内部默认 RNG 结构中。该结构本身仅包含两个指针,一个指向 RNG 的“方法”,另一个指向保存 RNG 内部状态的内存缓冲区。这意味着,如果在将其设置为默认值后,您继续从 RNG 生成随机数,它也会影响默认 RNG 的状态,因为两者共享相同的状态指针。但是,不要期望 igraph_rng_default()
返回与您在此处传入的指针相同的指针 - 状态是共享的,但整个结构不是。
参数:
|
从现在起用作默认值的随机数生成器。在其仍用作默认值时调用 |
时间复杂度:O(1)。
igraph_error_t igraph_rng_init(igraph_rng_t *rng, const igraph_rng_type_t *type);
该函数为具有给定类型的随机数生成器分配内存,并将其种子设置为默认值。
参数:
|
指向未初始化 RNG 的指针。 |
|
RNG 的类型,例如 |
返回值:
错误代码。 |
void igraph_rng_destroy(igraph_rng_t *rng);
参数:
|
要销毁的 RNG。不要销毁用作默认 igraph RNG 的 RNG。 |
时间复杂度:O(1)。
igraph_error_t igraph_rng_seed(igraph_rng_t *rng, igraph_uint_t seed);
参数:
|
RNG。 |
|
新的种子。 |
返回值:
错误代码。 |
时间复杂度:通常为 O(1),但可能取决于 RNG 的类型。
igraph_integer_t igraph_rng_bits(const igraph_rng_t* rng);
参数:
|
RNG。 |
返回值:
可以使用 RNG 在单轮中生成的随机位数。 |
时间复杂度:O(1)。
igraph_uint_t igraph_rng_max(const igraph_rng_t *rng);
请注意,此数字仅用于提供信息;它返回可以通过 RNG 单次调用其内部函数生成的最大可能整数。它直接从 RNG 在单轮中可以生成的随机位数推导而来。当它小于其他 RNG 函数(如 igraph_rng_get_integer()
)所需的数量时,igraph 将多次调用 RNG 以生成更多随机位。
参数:
|
RNG。 |
返回值:
可以使用 RNG 在单轮中生成的最大可能整数。 |
时间复杂度:O(1)。
igraph_rng_get_bool
— 生成随机布尔值。igraph_rng_get_integer
— 从区间生成整数随机数。igraph_rng_get_unif01
— 从单位区间均匀采样。igraph_rng_get_unif
— 从给定区间采样实数。igraph_rng_get_normal
— 从正态分布采样。igraph_rng_get_exp
— 从指数分布采样。igraph_rng_get_gamma
— 从伽马分布采样。igraph_rng_get_binom
— 从二项分布采样。igraph_rng_get_geom
— 从几何分布采样。igraph_rng_get_pois
— 从泊松分布采样。
igraph_bool_t igraph_rng_get_bool(igraph_rng_t *rng);
仅当一次需要单个随机布尔值,即单个位时,才使用此函数。它对于生成多个位效率不高。
参数:
|
指向用于生成的 RNG 的指针。在此处使用 |
返回值:
生成的位,作为真值。 |
igraph_integer_t igraph_rng_get_integer( igraph_rng_t *rng, igraph_integer_t l, igraph_integer_t h );
从区间 [l, h]
生成均匀分布的整数。
参数:
|
指向用于生成的 RNG 的指针。在此处使用 |
|
下限,包括在内,也可以为负。 |
|
上限,包括在内,也可以为负,但必须至少为 |
返回值:
生成的随机整数。 |
时间复杂度:O(log2(h-l+1) / bits),其中 bits 是 igraph_rng_bits
(rng) 的值。
igraph_real_t igraph_rng_get_unif01(igraph_rng_t *rng);
从 [0, 1)
半开区间生成均匀分布的实数。
参数:
|
指向要使用的 RNG 的指针。在此处使用 |
返回值:
生成的均匀分布的随机数。 |
时间复杂度:取决于 RNG 的类型。
igraph_real_t igraph_rng_get_unif(igraph_rng_t *rng, igraph_real_t l, igraph_real_t h);
从 [l, h)
半开区间生成均匀分布的实数。
参数:
|
指向要使用的 RNG 的指针。在此处使用 |
|
下限,可以为负。 |
|
上限,可以为负,但必须大于下限。 |
返回值:
生成的均匀分布的随机数。 |
时间复杂度:取决于 RNG 的类型。
igraph_real_t igraph_rng_get_normal(igraph_rng_t *rng, igraph_real_t m, igraph_real_t s);
从具有概率密度的正态分布生成随机变量
exp( -(x - m)^2 / (2 s^2) )
.
参数:
|
指向要使用的 RNG 的指针。在此处使用 |
|
平均值。 |
|
标准差。 |
返回值:
生成的正态分布随机数。 |
时间复杂度:取决于 RNG 的类型。
igraph_real_t igraph_rng_get_exp(igraph_rng_t *rng, igraph_real_t rate);
从概率密度与以下成比例的指数分布生成随机变量
exp(-rate x)
.
参数:
|
指向要使用的 RNG 的指针。在此处使用 |
|
速率参数。 |
返回值:
生成的样本。 |
时间复杂度:取决于 RNG。
igraph_real_t igraph_rng_get_gamma(igraph_rng_t *rng, igraph_real_t shape, igraph_real_t scale);
从概率密度与以下成比例的伽马分布生成随机变量
x^(shape-1) exp(-x / scale)
.
参数:
|
指向要使用的 RNG 的指针。在此处使用 |
|
形状参数。 |
|
比例参数。 |
返回值:
生成的样本。 |
时间复杂度:取决于 RNG。
igraph_real_t igraph_rng_get_binom(igraph_rng_t *rng, igraph_integer_t n, igraph_real_t p);
从二项分布生成随机变量。数字 k
以概率生成
(n \choose k) p^k (1-p)^(n-k)
, k = 0, 1, ..., n
。
参数:
|
指向要使用的 RNG 的指针。在此处使用 |
|
观测次数。 |
|
事件的概率。 |
返回值:
生成的二项分布随机数。 |
时间复杂度:取决于 RNG。
igraph_real_t igraph_rng_get_geom(igraph_rng_t *rng, igraph_real_t p);
从几何分布生成随机变量。数字 k
以概率生成
(1 - p)^k p
, k = 0, 1, 2, ...
。
参数:
|
指向要使用的 RNG 的指针。在此处使用 |
|
每次试验中成功的概率。必须大于零且小于或等于 1。 |
返回值:
生成的几何分布随机数。 |
时间复杂度:取决于 RNG。
igraph_real_t igraph_rng_get_pois(igraph_rng_t *rng, igraph_real_t rate);
从泊松分布生成随机变量。数字 k
以概率生成
rate^k * exp(-rate) / k!
, k = 0, 1, 2, ...
。
参数:
|
指向要使用的 RNG 的指针。在此处使用 |
|
泊松分布的速率参数。不得为负。 |
返回值:
生成的几何分布随机数。 |
时间复杂度:取决于 RNG。
默认情况下,igraph 使用 MT19937 生成器。在 igraph 版本 0.6 之前,使用标准 C 库提供的生成器。这意味着 GNU libc 2 系统上的 GLIBC2 生成器,以及其他系统上的 BSD RAND 生成器。 RAND 生成器由于其较差的统计特性在版本 0.10 中被删除。 PCG32 生成器在版本 0.10 中添加。
const igraph_rng_type_t igraph_rngtype_mt19937 = { /* name= */ "MT19937", /* bits= */ 32, /* init= */ igraph_rng_mt19937_init, /* destroy= */ igraph_rng_mt19937_destroy, /* seed= */ igraph_rng_mt19937_seed, /* get= */ igraph_rng_mt19937_get, /* get_int= */ NULL, /* get_real= */ NULL, /* get_norm= */ NULL, /* get_geom= */ NULL, /* get_binom= */ NULL, /* get_exp= */ NULL, /* get_gamma= */ NULL, /* get_pois= */ NULL };
Makoto Matsumoto 和 Takuji Nishimura 的 MT19937 生成器是扭曲的广义反馈移位寄存器算法的变体,被称为“梅森旋转”生成器。它具有 2^19937 - 1(约 10^6000)的梅森素数周期,并且在 623 个维度上是等分布的。它已通过了 diehard 统计测试。它每个生成器使用 624 个字的状态,并且速度与其他生成器相当。原始生成器使用 4357 的默认种子,并且在 igraph_rng_mt19937_seed
() 中选择等于零的 s
会重现此结果。更高版本切换到 5489 作为默认种子,如果您需要,可以通过 igraph_rng_seed()
显式选择此种子。
有关更多信息,请参见 Makoto Matsumoto 和 Takuji Nishimura,“梅森旋转:一种 623 维等分布均匀伪随机数生成器”。 ACM Transactions on Modeling and Computer Simulation,第 8 卷,第 1 期(1998 年 1 月),第 3–30 页
生成器 igraph_rngtype_mt19937
使用上述两位作者于 2002 年发布的播种过程的第二次修订。原始播种过程可能会导致某些种子值的虚假伪像。
此生成器是从 GNU Scientific Library 移植的。
const igraph_rng_type_t igraph_rngtype_glibc2 = { /* name= */ "LIBC", /* bits= */ 31, /* init= */ igraph_rng_glibc2_init, /* destroy= */ igraph_rng_glibc2_destroy, /* seed= */ igraph_rng_glibc2_seed, /* get= */ igraph_rng_glibc2_get, /* get_int= */ NULL, /* get_real= */ NULL, /* get_norm= */ NULL, /* get_geom= */ NULL, /* get_binom= */ NULL, /* get_exp= */ NULL, /* get_gamma= */ NULL, /* get_pois= */ NULL };
这是一个具有 128 字节缓冲区的线性反馈移位寄存器生成器。在 igraph 版本 0.6 之前,该生成器是默认生成器,至少在依赖 GNU libc 的系统上是这样。该生成器是从 GNU Scientific Library 移植的。它是一个重新实现,不调用系统 glibc 生成器。
const igraph_rng_type_t igraph_rngtype_pcg32 = { /* name= */ "PCG32", /* bits= */ 32, /* init= */ igraph_rng_pcg32_init, /* destroy= */ igraph_rng_pcg32_destroy, /* seed= */ igraph_rng_pcg32_seed, /* get= */ igraph_rng_pcg32_get, /* get_int= */ NULL, /* get_real= */ NULL, /* get_norm= */ NULL, /* get_geom= */ NULL, /* get_binom= */ NULL, /* get_exp= */ NULL, /* get_gamma= */ NULL, /* get_pois= */ NULL };
这是 PCG 随机数生成器的实现;有关更多详细信息,请参见 https://www.pcg-random.org。此实现在单次迭代中返回 32 个随机位。
该生成器是从作者在 https://github.com/imneme/pcg-c 上发布的原始源代码移植的。
const igraph_rng_type_t igraph_rngtype_pcg64 = { /* name= */ "PCG64", /* bits= */ 64, /* init= */ igraph_rng_pcg64_init, /* destroy= */ igraph_rng_pcg64_destroy, /* seed= */ igraph_rng_pcg64_seed, /* get= */ igraph_rng_pcg64_get, /* get_int= */ NULL, /* get_real= */ NULL, /* get_norm= */ NULL, /* get_geom= */ NULL, /* get_binom= */ NULL, /* get_exp= */ NULL, /* get_gamma= */ NULL, /* get_pois= */ NULL };
这是 PCG 随机数生成器的实现;有关更多详细信息,请参见 https://www.pcg-random.org。此实现在单次迭代中返回 64 个随机位。它仅在具有提供 __uint128_t 类型的编译器的 64 位平台上可用。
PCG64 在采样浮点数或非常大的整数时通常提供比 PCG32 更好的性能,因为它可以在单次生成轮次中提供两倍的随机位数。
该生成器是从作者在 https://github.com/imneme/pcg-c 上发布的原始源代码移植的。
如果用户未显式使用任何 RNG 函数,而是调用一些随机 igraph 函数,则在 igraph 函数首次需要随机数时,将设置默认 RNG。此 RNG 的种子是 time(0)
函数调用的输出,使用标准 C 库中的 time
函数。这确保 igraph 每次调用 C 程序时都创建一个不同的随机图。
创建的默认生成器在内部存储,可以使用 igraph_rng_default()
函数查询。
如果需要可重现的结果,则用户应使用 igraph_rng_seed()
函数在默认生成器 igraph_rng_default()
上显式设置默认随机数生成器的种子。将种子设置为相同的数字时,igraph 会生成完全相同的随机图(或一系列随机图)。
默认情况下,igraph 使用 igraph_rng_default()
随机数生成器。可以通过使用已初始化的随机数生成器调用 igraph_rng_set_default()
随时更改此设置。请注意,旧的(替换的)生成器不会被销毁,因此不会释放任何内存。
igraph 还提供了使用 igraph_rng_init()
函数设置多个随机数生成器的函数,然后从它们生成随机数,例如使用 igraph_rng_get_integer()
和/或 igraph_rng_get_unif()
调用。
请注意,初始化新的随机数生成器与 igraph 函数本身使用的生成器无关。如果要替换该生成器,请使用 igraph_rng_set_default()
。
示例 8.1. 文件 examples/simple/random_seed.c
#include <igraph.h> int main(void) { igraph_t g1, g2; igraph_bool_t iso; /* Seed the default random number generator and create a random graph. */ igraph_rng_seed(igraph_rng_default(), 1122); igraph_erdos_renyi_game_gnp(&g1, 100, 3.0 / 100, /*directed=*/ 0, /*loops=*/ 0); /* Seed the generator with the same seed again, * and create a graph with the same method. */ igraph_rng_seed(igraph_rng_default(), 1122); igraph_erdos_renyi_game_gnp(&g2, 100, 3.0 / 100, /*directed=*/ 0, /*loops=*/ 0); /* The two graphs will be identical. */ igraph_is_same_graph(&g1, &g2, &iso); if (!iso) { return 1; } /* Destroy no longer needed data structures. */ igraph_destroy(&g2); igraph_destroy(&g1); return 0; }
← 第 7 章. 数据结构库:向量、矩阵、其他数据类型 | 第 9 章. 图生成器 → |