igraph 参考手册

用于使用 igraph C 库

搜索手册

第 10 章。图上的博弈

1. 传染病模型

1.1. igraph_sir — 在图上执行多次 SIR 传染病模型运行。

igraph_error_t igraph_sir(const igraph_t *graph, igraph_real_t beta,
               igraph_real_t gamma, igraph_integer_t no_sim,
               igraph_vector_ptr_t *result);

SIR 模型是流行病学中的一个简单模型。人口中的个体可能处于三种状态:易感、感染和恢复。假定康复者对该疾病具有免疫力。易感者以取决于其感染邻居数量的速率被感染。感染者以恒定速率恢复。请参阅以下参数。

此函数运行多次模拟,所有模拟均从单个均匀随机选择的感染个体开始。当没有感染个体剩余时,模拟停止。

参数: 

:

要在其上执行模型的图。对于有向图,边缘方向将被忽略,并给出警告。

beta:

易感且具有单个感染邻居的个体的感染率。具有 n 个感染邻居的易感个体的感染率是 beta 的 n 倍。形式上,这是指数分布的速率参数。

gamma:

感染个体的恢复率。形式上,这是指数分布的速率参数。

no_sim:

要执行的模拟运行次数。

result:

模拟结果存储在此处,存储在 igraph_sir_t 对象的列表中。要释放内存,用户需要在销毁指针向量本身之前,对每个元素调用 igraph_sir_destroy,使用 igraph_vector_ptr_destroy_all()

返回值: 

错误代码。

时间复杂度:O(no_sim * (|V| + |E| log(|V|))).

1.2. igraph_sir_t — 一次 SIR 模型模拟的结果。

typedef struct igraph_sir_t {
    igraph_vector_t times;
    igraph_vector_int_t no_s, no_i, no_r;
} igraph_sir_t;

数据结构,用于存储图上 SIR(易感-感染-恢复)模型的一次模拟的结果。它具有以下成员。它们都是(实数或整数)向量,并且长度相同。

值: 

times:

向量,事件的时间存储在此处。

no_s:

整数向量,每个时间步中易感者的数量存储在此处。

no_i:

整数向量,每个时间步中感染个体的数量存储在此处。

no_r:

整数向量,每个时间步中恢复个体的数量存储在此处。

1.3. igraph_sir_destroy — 释放与 SIR 模拟运行相关的内存。

void igraph_sir_destroy(igraph_sir_t *sir);

参数: 

sir:

存储模拟的 igraph_sir_t 对象。

2. 弃用的函数

2.1. igraph_deterministic_optimal_imitation — 通过确定性最优模仿采用策略。

igraph_error_t igraph_deterministic_optimal_imitation(const igraph_t *graph,
        igraph_integer_t vid,
        igraph_optimal_t optimality,
        const igraph_vector_t *quantities,
        igraph_vector_int_t *strategies,
        igraph_neimode_t mode);

一种简单的确定性模仿策略,其中顶点将其策略修改为产生局部最优策略的策略。这里,“局部”是相对于顶点的直接邻居而言的。顶点保留其当前策略,其中此策略产生局部最优量。在这种情况下,该量可以是诸如适应度之类的度量。

参数: 

:

表示博弈网络的图对象。这不能是空图或平凡图,但必须至少具有两个顶点和一个边。如果 graph 具有一个顶点,则不会发生策略更新。此外,如果 graph 具有至少两个顶点但零个边,则也不会发生策略更新。

vid:

要更新其策略的顶点。假定 vid 表示 graph 中的顶点。不执行检查,您有责任确保 vid 确实是 graph 的顶点。如果提供了孤立顶点,即输入顶点的度为 0,则不会发生策略更新,并且 vid 将保留其当前策略。如果 vid 的局部邻域是其入邻居(分别是出邻居),但 vid 具有零个入邻居(分别是出邻居),则也不会发生策略更新。在计算 vid 的度(入度、出度、所有度)时,循环将被忽略。

optimality:

布尔值;控制要使用的最优性类型。支持的值为

IGRAPH_MAXIMUM

使用最大确定性模仿,其中将采用具有最大量(例如,适应度)的顶点的策略。我们将 vid 的策略更新为产生局部最大值的策略。

IGRAPH_MINIMUM

使用最小确定性模仿。也就是说,将模仿具有最小量的顶点的策略。换句话说,更新为产生局部最小值的策略。

quantities:

一个数量向量,提供 graph 中每个顶点的数量。将向量的每个条目都视为由诸如博弈的适应度函数之类的函数生成。因此,如果该向量表示适应度量,则每个向量条目都是某个顶点的适应度。此向量的长度必须与 graph 的顶点集中的顶点数相同。

strategies:

顶点群体的当前策略向量。 vid 的更新策略将存储在此处。每个策略都由一个非负整数标识,其解释取决于博弈的收益矩阵。通常,我们将策略 ID 用作收益矩阵的行或列索引。此向量的长度必须与 graph 的顶点集中的顶点数相同。

模式:

定义要为 vid 考虑的邻域类型。如果 graph 是无向图,则我们使用 vid 的所有直接邻居。因此,如果您知道 graph 是无向图,则在此处传递值 IGRAPH_ALL 是安全的。支持的值为

IGRAPH_OUT

使用 vid 的出邻居。仅当 graph 是有向图时,此选项才相关。

IGRAPH_IN

使用 vid 的入邻居。同样,仅当 graph 是有向图时,此选项才相关。

IGRAPH_ALL

同时使用 vid 的入邻居和出邻居。仅当 graph 是有向图时,此选项才相关。如果 graph 是无向图,也请使用此值。

返回值: 

在以下每种情况下,都会返回错误代码 IGRAPH_EINVAL:(1)任何参数 graphquantitiesstrategies 都是空指针。(2)向量 quantitiesstrategies 的长度与 graph 中的顶点数不同。(3)参数 graph 是空图或零图,即具有零个顶点和边的图。

时间复杂度:O(2d),其中 d 是顶点 vid 的度。

示例 10.1.  文件 examples/simple/igraph_deterministic_optimal_imitation.c

#include <igraph.h>
#include <stdio.h>

/* test parameters structure */
typedef struct {
    igraph_t *graph;
    igraph_integer_t vertex;
    igraph_optimal_t optimality;
    igraph_vector_t *quantities;
    igraph_vector_int_t *strategies;
    igraph_neimode_t mode;
    igraph_error_t retval;
} strategy_test_t;

/* Updating the strategy of an isolated vertex. In this case, the strategies
 * vector should not change at all.
 */
igraph_error_t isolated_vertex_test(void) {
    igraph_t g;
    igraph_vector_t quant;
    igraph_vector_int_t strat, v;
    igraph_integer_t i;
    igraph_error_t ret;

    /* graph with one isolated vertex */
    igraph_small(&g, 0, IGRAPH_UNDIRECTED, 0, 1, 1, 2, 2, 0, -1);
    igraph_add_vertices(&g, 1, 0);  /* new vertex 3 is isolated */
    /* quantities vector: all vertices have the same fitness */
    igraph_vector_init_real(&quant, 4, 0.25, 0.25, 0.25, 0.25);
    /* strategies vector: 0 means aggressive strategy; 1 means passive */
    igraph_vector_int_init_int(&strat, 4, 1, 0, 1, 0);
    /* make a copy of the original strategies vector for comparison later on */
    igraph_vector_int_init_copy(&v, &strat);
    /* Now update strategy of vertex 3. Since this vertex is isolated, no */
    /* strategy update would take place. The resulting strategies vector */
    /* would be the same as it was originally. */
    ret = igraph_deterministic_optimal_imitation(/*graph*/ &g,
            /*vertex*/ 3,
            /*optimality*/ IGRAPH_MAXIMUM,
            /*quantities*/ &quant,
            /*strategies*/ &strat,
            /*mode*/ IGRAPH_ALL);
    if (ret) {
        printf("Isolated vertex test failed.\n");
        return IGRAPH_FAILURE;
    }
    for (i = 0; i < igraph_vector_int_size(&strat); i++) {
        if (VECTOR(strat)[i] != VECTOR(v)[i]) {
            printf("Isolated vertex test failed.\n");
            return IGRAPH_FAILURE;
        }
    }
    /* clean up */
    igraph_destroy(&g);
    igraph_vector_destroy(&quant);
    igraph_vector_int_destroy(&strat);
    igraph_vector_int_destroy(&v);

    return IGRAPH_SUCCESS;
}

/* A game on the Petersen graph. This graph has 10 vertices and 15 edges.
 * The Petersen graph is initialized with a default quantities vector and a
 * default strategies vector. For each vertex v in the graph, we update the
 * strategy of v via deterministic optimal imitation. The resulting updated
 * strategies vector is compared with the known result vector. A mismatch would
 * raise an error code. If the updated strategies vector matches the known
 * result vector, we reset the strategies vector to its default state and
 * repeat the game with another vertex.
 */
igraph_error_t petersen_game_test(void) {
    igraph_t g;
    igraph_vector_t quant;
    igraph_vector_int_t known_max_v, known_min_v, strat, stratcopy;
    igraph_integer_t i, nvert;

    /* the Petersen graph */
    igraph_small(&g, /*n=*/ 0, IGRAPH_UNDIRECTED,
                 0, 1, 0, 4, 0, 5, 1, 2, 1, 6, 2, 3, 2, 7, 3, 4, 3, 8, 4, 9,
                 5, 7, 5, 8, 6, 8, 6, 9, 7, 9, -1);
    nvert = igraph_vcount(&g);
    /* Strategies vector, one strategy for each vertex. Thus vec[i] is the */
    /* strategy of vertex i. The strategy space is: {0, 1, 2, 3}. */
    igraph_vector_int_init_int(&strat, nvert, 1, 1, 2, 2, 0, 0, 0, 1, 2, 3);
    /* Quantities vector, one quantity per vertex. Thus vec[i] is the */
    /* quantity for vertex i. */
    igraph_vector_init_real(&quant, nvert,
                            0.3, 1.1, 0.5, 1.0, 0.9,
                            0.8, 0.4, 0.1, 0.7, 0.7);
    /* Known strategies that would be adopted. Thus vec[i] means that in */
    /* game i where we revise the strategy of vertex i, the strategy */
    /* vec[i] would be adopted by i. */
    /*maximum deterministic imitation*/
    igraph_vector_int_init_int(&known_max_v, nvert, 1, 1, 1, 2, 2, 0, 1, 0, 2, 0);
    /*minimum deterministic imitation*/
    igraph_vector_int_init_int(&known_min_v, nvert, 1, 1, 1, 2, 1, 1, 0, 1, 0, 1);
    /* play game and compare resulting updated strategies */
    for (i = 0; i < nvert; i++) {
        /* maximum deterministic imitation */
        igraph_vector_int_init_copy(&stratcopy, &strat);
        igraph_deterministic_optimal_imitation(/*graph*/ &g,
                /*vertex*/ i,
                /*optimality*/ IGRAPH_MAXIMUM,
                /*quantities*/ &quant,
                /*strategies*/ &stratcopy,
                /*neighbours*/ IGRAPH_ALL);
        if (VECTOR(stratcopy)[i] != VECTOR(known_max_v)[i]) {
            printf("Maximum deterministic imitation failed for vertex %" IGRAPH_PRId ".\n", i);
            return IGRAPH_FAILURE;
        }
        igraph_vector_int_destroy(&stratcopy);
        /* minimum deterministic imitation */
        igraph_vector_int_init_copy(&stratcopy, &strat);
        igraph_deterministic_optimal_imitation(/*graph*/ &g,
                /*vertex*/ i,
                /*optimality*/ IGRAPH_MINIMUM,
                /*quantities*/ &quant,
                /*strategies*/ &stratcopy,
                /*neighbours*/ IGRAPH_ALL);
        if (VECTOR(stratcopy)[i] != VECTOR(known_min_v)[i]) {
            printf("Minimum deterministic imitation failed for vertex %" IGRAPH_PRId ".\n", i);
            return IGRAPH_FAILURE;
        }
        igraph_vector_int_destroy(&stratcopy);
    }
    /* clean up */
    igraph_destroy(&g);
    igraph_vector_int_destroy(&known_max_v);
    igraph_vector_int_destroy(&known_min_v);
    igraph_vector_destroy(&quant);
    igraph_vector_int_destroy(&strat);

    return IGRAPH_SUCCESS;
}

int main(void) {
    igraph_error_t ret;

    igraph_rng_seed(igraph_rng_default(), 648);

    ret = isolated_vertex_test();
    if (ret) {
        return ret;
    }
    ret = petersen_game_test();
    if (ret) {
        return ret;
    }

    return IGRAPH_SUCCESS;
}


2.2. igraph_moran_process — 网络设置中的 Moran 过程。

igraph_error_t igraph_moran_process(const igraph_t *graph,
                         const igraph_vector_t *weights,
                         igraph_vector_t *quantities,
                         igraph_vector_int_t *strategies,
                         igraph_neimode_t mode);

这是经典 Moran 过程到网络设置的扩展。Moran 过程是在具有固定大小的群体中进行单倍体(无性)繁殖的模型。在网络设置中,Moran 过程在加权图上运行。在每个时间步,选择顶点 a 进行繁殖,选择另一个顶点 b 进行死亡。顶点 a 产生一个相同的克隆 c,它取代 b。顶点 c 是 a 的克隆,因为 c 继承了 a 的当前数量(例如,适应度)和当前策略。

假设表示博弈网络的图 G 是简单的,即没有循环且没有多条边。另一方面,如果 G 在某个顶点 v 上具有循环,则当选择 v 进行繁殖时,它可能会放弃此机会。特别是,当选择 v 进行繁殖并且还选择 v 进行死亡时,v 的克隆将是 v 本身,并带有其当前的顶点 ID。实际上,v 放弃了它的繁殖机会。

参数: 

:

表示博弈网络的图对象。这不能是空图或平凡图,但必须至少具有两个顶点和一个边。在以下每种情况下,Moran 过程都不会发生:(1)如果 graph 具有一个顶点。(2)如果 graph 具有至少两个顶点但零个边。

weights:

所有边权重的向量 graph。因此,weights[i] 表示具有边 ID i 的边的权重。对于 Moran 过程,假定每个权重都是正数;您有责任确保此条件成立。此向量的长度必须与 graph 中的边数相同。

quantities:

一个数量向量,提供 graph 中每个顶点的数量。新克隆的数量将存储在此处。将向量的每个条目都视为由诸如博弈的适应度函数之类的函数生成。因此,如果该向量表示适应度量,则每个向量条目都是某个顶点的适应度。此向量的长度必须与 graph 的顶点集中的顶点数相同。对于 Moran 过程,假定每个向量条目都是非负数;不会对此进行检查。您有责任确保至少有一个条目为正数。此外,此向量不能是零向量;将检查此条件。

strategies:

顶点群体的当前策略向量。新克隆的策略将存储在此处。每个策略都由一个非负整数标识,其解释取决于博弈的收益矩阵。通常,我们将策略 ID 用作收益矩阵的行或列索引。此向量的长度必须与 graph 的顶点集中的顶点数相同。

模式:

定义要为选择进行繁殖的顶点 a 考虑的邻域类型。仅当 graph 是有向图时,此选项才相关。如果 graph 是无向图,则在此处传递值 IGRAPH_ALL 是安全的。支持的值为

IGRAPH_OUT

使用 a 的出邻居。仅当 graph 是有向图时,此选项才相关。

IGRAPH_IN

使用 a 的入邻居。同样,仅当 graph 是有向图时,此选项才相关。

IGRAPH_ALL

同时使用 a 的入邻居和出邻居。仅当 graph 是有向图时,此选项才相关。如果 graph 是无向图,也请使用此值。

返回值: 

在以下每种情况下,都会返回错误代码 IGRAPH_EINVAL:(1)任何参数 graphweightsquantitiesstrategies 都是空指针。(2)向量 quantitiesstrategies 的长度与 graph 中的顶点数不同。(3)向量 weights 的长度与 graph 中的边数不同。(4)参数 graph 是空图或零图,即具有零个顶点和边的图。(5)向量 weights 或感兴趣的组合总和为零。(6)向量 quantities 或感兴趣的组合总和为零。

时间复杂度:取决于随机数生成器,但通常为 O(n),其中 n 是 graph 中的顶点数。

参考

(Lieberman 等人 2005)

E. Lieberman、C. Hauert 和 M. A. Nowak。图上的进化动力学。 Nature, 433(7023):312--316, 2005。

(Moran 1958)

P. A. P. Moran。遗传学中的随机过程。 Mathematical Proceedings of the Cambridge Philosophical Society, 54(1):60--71, 1958。

2.3. igraph_roulette_wheel_imitation — 通过轮盘赌选择采用策略。

igraph_error_t igraph_roulette_wheel_imitation(const igraph_t *graph,
                                    igraph_integer_t vid,
                                    igraph_bool_t islocal,
                                    const igraph_vector_t *quantities,
                                    igraph_vector_int_t *strategies,
                                    igraph_neimode_t mode);

一种简单的随机模仿策略,其中顶点将其策略修改为按 u 的数量(例如,适应度)成比例选择的顶点 u 的策略。这是随机模仿的特例,其中候选者不是均匀随机选择的,而是按其数量成比例选择的。

参数: 

:

表示博弈网络的图对象。这不能是空图或平凡图,但必须至少具有两个顶点和一个边。如果 graph 具有一个顶点,则不会发生策略更新。此外,如果 graph 具有至少两个顶点但零个边,则也不会发生策略更新。

vid:

要更新其策略的顶点。假定 vid 表示 graph 中的顶点。不执行检查,您有责任确保 vid 确实是 graph 的顶点。如果提供了孤立顶点,即输入顶点的度为 0,则不会发生策略更新,并且 vid 将保留其当前策略。如果 vid 的局部邻域是其入邻居(分别是出邻居),但 vid 具有零个入邻居(分别是出邻居),则也不会发生策略更新。在计算 vid 的度(入度、出度、所有度)时,循环将被忽略。

islocal:

布尔值;此标志控制在计算相对数量时使用哪个角度。如果为 true,则我们使用局部角度;否则,我们使用全局角度。 vid 的局部角度是 vid 的所有直接邻居的集合。相反, vid 的全局角度是 graph 的顶点集。

quantities:

一个数量向量,提供 graph 中每个顶点的数量。将向量的每个条目都视为由诸如博弈的适应度函数之类的函数生成。因此,如果该向量表示适应度量,则每个向量条目都是某个顶点的适应度。此向量的长度必须与 graph 的顶点集中的顶点数相同。对于轮盘赌选择,假定每个向量条目都是非负数;不会对此进行检查。您有责任确保至少有一个条目为非零。此外,此向量不能是零向量;将检查此条件。

strategies:

顶点群体的当前策略向量。 vid 的更新策略将存储在此处。每个策略都由一个非负整数标识,其解释取决于博弈的收益矩阵。通常,我们将策略 ID 用作收益矩阵的行或列索引。此向量的长度必须与 graph 的顶点集中的顶点数相同。

模式:

定义要为 vid 考虑的邻域类型。仅当我们考虑局部角度时,即如果 islocal 为 true,此选项才相关。如果我们考虑全局角度,则在此处传递值 IGRAPH_ALL 是安全的。如果 graph 是无向图,则我们使用 vid 的所有直接邻居。因此,如果您知道 graph 是无向图,则在此处传递值 IGRAPH_ALL 是安全的。支持的值为

IGRAPH_OUT

使用 vid 的出邻居。仅当 graph 是有向图并且我们正在考虑局部角度时,此选项才相关。

IGRAPH_IN

使用 vid 的入邻居。同样,仅当 graph 是有向图并且我们正在考虑局部角度时,此选项才相关。

IGRAPH_ALL

同时使用 vid 的入邻居和出邻居。仅当 graph 是有向图时,此选项才相关。如果 graph 是无向图或者我们正在考虑全局角度,也请使用此值。

返回值: 

在以下每种情况下,都会返回错误代码 IGRAPH_EINVAL:(1)任何参数 graphquantitiesstrategies 都是空指针。(2)向量 quantitiesstrategies 的长度与 graph 中的顶点数不同。(3)参数 graph 是空图或零图,即具有零个顶点和边的图。(4)向量 quantities 的总和为零。

时间复杂度:O(n),其中 n 是要考虑的角度中的顶点数。如果我们考虑全局角度,则 n 是 graph 的顶点集中的顶点数。另一方面,对于局部角度,n 是 vid 的度,不包括循环。

参考

(Yu & Gen 2010)

X. Yu 和 M. Gen。 进化算法简介。 Springer, 2010, 第 18--20 页。

示例 10.2.  文件 examples/simple/igraph_roulette_wheel_imitation.c

#include <igraph.h>
#include <stdio.h>

#define R_INTEGER(a,b) (igraph_rng_get_integer(igraph_rng_default(), (a), (b)))

/* test parameters structure */
typedef struct {
    igraph_t *graph;
    igraph_integer_t vertex;
    igraph_bool_t islocal;
    igraph_vector_t *quantities;
    igraph_vector_int_t *strategies;
    igraph_vector_int_t *known_strats;
    igraph_neimode_t mode;
    igraph_error_t retval;
} strategy_test_t;

/* A game on a graph with 5 vertices and 7 edges. Use roulette wheel selection
 * to update strategies. This example also illustrates how a choice of
 * perspective (whether local or global) could affect the range of
 * possible strategies a vertex could adopt.
 */
igraph_error_t roulette_test(void) {
    igraph_t g;
    igraph_bool_t success;
    igraph_vector_t quant;
    igraph_vector_int_t *known, strat, stratcopy;
    igraph_vector_int_t known0, known1, known2, known3, known4, known5;
    igraph_integer_t i, k, n, nvert;
    igraph_error_t ret;
    strategy_test_t *test;

    /* the game network */
    igraph_small(&g, /*nvert=*/ 0, IGRAPH_UNDIRECTED,
                 0, 3, 0, 4, 1, 2, 1, 4, 1, 5, 2, 3, 2, 4, 3, 4, -1);
    nvert = igraph_vcount(&g);
    /* strategies vector; the strategy space is {0, 1, 2, 3} */
    /* V[i] is strategy of vertex i */
    igraph_vector_int_init_int(&strat, nvert, 1, 0, 1, 2, 0, 3);
    /* quantities vector; V[i] is quantity of vertex i */
    igraph_vector_init_real(&quant, nvert, 0.56, 0.13, 0.26, 0.73, 0.67, 0.82);
    /* possible strategies each vertex can adopt */
    igraph_vector_int_init_int(&known0, /*n=*/ 3, 0, 1, 2);       /* local */
    igraph_vector_int_init_int(&known1, /*n=*/ 3, 0, 1, 3);       /* local */
    igraph_vector_int_init_int(&known2, /*n=*/ 3, 0, 1, 2);       /* local */
    igraph_vector_int_init_int(&known3, /*n=*/ 3, 0, 1, 2);       /* local */
    igraph_vector_int_init_int(&known4, /*n=*/ 3, 0, 1, 2);       /* local */
    igraph_vector_int_init_int(&known5, /*n=*/ 4, 0, 1, 2, 3);    /* global */

    /* test parameters */
    /*graph--vert--islocal--quantities--strategies--known_strats--mode-retval*/
    strategy_test_t game0 = {&g, 0, 1, &quant, NULL, &known0, IGRAPH_ALL, IGRAPH_SUCCESS};
    strategy_test_t game1 = {&g, 1, 1, &quant, NULL, &known1, IGRAPH_ALL, IGRAPH_SUCCESS};
    strategy_test_t game2 = {&g, 2, 1, &quant, NULL, &known2, IGRAPH_ALL, IGRAPH_SUCCESS};
    strategy_test_t game3 = {&g, 3, 1, &quant, NULL, &known3, IGRAPH_ALL, IGRAPH_SUCCESS};
    strategy_test_t game4 = {&g, 4, 1, &quant, NULL, &known4, IGRAPH_ALL, IGRAPH_SUCCESS};
    strategy_test_t game5 = {&g, 5, 0, &quant, NULL, &known5, IGRAPH_ALL, IGRAPH_SUCCESS};
    strategy_test_t *all_checks[] = {/* 1 */ &game0,
                                             /* 2 */ &game1,
                                             /* 3 */ &game2,
                                             /* 4 */ &game3,
                                             /* 5 */ &game4,
                                             /* 6 */ &game5
                                    };

    /* play game */
    n = 6;
    i = 0;
    while (i < n) {
        test = all_checks[i];
        igraph_vector_int_init_copy(&stratcopy, &strat);
        ret = igraph_roulette_wheel_imitation(test->graph, test->vertex,
                                              test->islocal, test->quantities,
                                              &stratcopy, test->mode);
        if (ret != test->retval) {
            printf("Test no. %" IGRAPH_PRId " failed.\n", i + 1);
            return IGRAPH_FAILURE;
        }
        /* If the revised strategy s matches one of the candidate strategies, */
        /* then success. If s doesn't match any of the possible strategies, then */
        /* failure. Default to failure. */
        success = 0;
        known = test->known_strats;
        for (k = 0; k < igraph_vector_int_size(known); k++) {
            if (VECTOR(*known)[k] == VECTOR(stratcopy)[test->vertex]) {
                success = 1;
                break;
            }
        }
        if (!success) {
            printf("Roulette wheel imitation failed for vertex %" IGRAPH_PRId ".\n", test->vertex);
            return IGRAPH_FAILURE;
        }
        igraph_vector_int_destroy(&stratcopy);
        i++;
    }
    /* game finished; pack up */
    igraph_destroy(&g);
    igraph_vector_int_destroy(&known0);
    igraph_vector_int_destroy(&known1);
    igraph_vector_int_destroy(&known2);
    igraph_vector_int_destroy(&known3);
    igraph_vector_int_destroy(&known4);
    igraph_vector_int_destroy(&known5);
    igraph_vector_destroy(&quant);
    igraph_vector_int_destroy(&strat);

    return IGRAPH_SUCCESS;
}

/* It is possible for a vertex to retain its current strategy. This can
 * happen both in the local and global perspectives.
 */
igraph_error_t retain_strategy_test(void) {
    igraph_t g;
    igraph_integer_t max, min, v;
    igraph_vector_t quant;
    igraph_vector_int_t strat, stratcp;
    igraph_integer_t i, ntry, nvert;

    /* the game network */
    igraph_small(&g, /*nvert=*/ 0, IGRAPH_UNDIRECTED,
                 0, 3, 0, 4, 1, 2, 1, 4, 1, 5, 2, 3, 2, 4, 3, 4, -1);
    nvert = igraph_vcount(&g);
    /* strategies vector; the strategy space is {0, 1, 2, 3} */
    /* V[i] is strategy of vertex i */
    igraph_vector_int_init_int(&strat, nvert, 1, 0, 1, 2, 0, 3);
    /* quantities vector; V[i] is quantity of vertex i */
    igraph_vector_init_real(&quant, nvert, 0.56, 0.13, 0.26, 0.73, 0.67, 0.82);

    /* random vertex */
    min = 0;
    max = 5;
    igraph_rng_seed(igraph_rng_default(), 42); /* make tests deterministic */
    v = R_INTEGER(min, max);  /* min <= v <= max */
    /* Ensure that it is possible for v to retain its current strategy. We */
    /* will try to do this at most ntry times. As there are at most 6 vertices */
    /* to choose from, it shouldn't take long before we encounter a strategy */
    /* revision round where v retains its current strategy. */
    /* With local perspective. */
    i = 0;
    ntry = 100;
    igraph_vector_int_init(&stratcp, 0);
    do {
        i++;
        if (i > ntry) {
            return IGRAPH_FAILURE;    /* ideally this should never happen */
        }
        igraph_vector_int_destroy(&stratcp);
        igraph_vector_int_init_copy(&stratcp, &strat);
        igraph_roulette_wheel_imitation(&g, v, /*is local?*/ 1, &quant, &stratcp,
                                        IGRAPH_ALL);
    } while (VECTOR(stratcp)[v] != VECTOR(strat)[v]);
    /* If we get to this point, we know that there was an update round */
    /* i <= ntry as a result of which v retains its current strategy. */
    /* Now try again, but this time with the global perspective. */
    i = 0;
    do {
        i++;
        if (i > ntry) {
            return IGRAPH_FAILURE;    /* ideally this should never happen */
        }
        igraph_vector_int_destroy(&stratcp);
        igraph_vector_int_init_copy(&stratcp, &strat);
        igraph_roulette_wheel_imitation(&g, v, /*is local?*/ 0, &quant, &stratcp,
                                        IGRAPH_ALL);
    } while (VECTOR(stratcp)[v] != VECTOR(strat)[v]);
    /* nothing further to do, but housekeeping */
    igraph_destroy(&g);
    igraph_vector_destroy(&quant);
    igraph_vector_int_destroy(&strat);
    igraph_vector_int_destroy(&stratcp);

    return IGRAPH_SUCCESS;
}

int main(void) {
    igraph_error_t ret;

    igraph_rng_seed(igraph_rng_default(), 3241);

    ret = roulette_test();
    if (ret) {
        return IGRAPH_FAILURE;
    }
    ret = retain_strategy_test();
    if (ret) {
        return IGRAPH_FAILURE;
    }

    return IGRAPH_SUCCESS;
}


2.4. igraph_stochastic_imitation — 通过具有均匀选择的随机模仿采用策略。

igraph_error_t igraph_stochastic_imitation(const igraph_t *graph,
                                igraph_integer_t vid,
                                igraph_imitate_algorithm_t algo,
                                const igraph_vector_t *quantities,
                                igraph_vector_int_t *strategies,
                                igraph_neimode_t mode);

一种简单的随机模仿策略,其中顶点将其策略修改为从其局部邻域中均匀随机选择的顶点的策略。这称为通过均匀选择进行随机模仿,其中模仿的策略是通过某种随机过程选择的。对于此函数,我们使用来自候选者池的均匀选择。

参数: 

:

表示博弈网络的图对象。这不能是空图或平凡图,但必须至少具有两个顶点和一个边。如果 graph 具有一个顶点,则不会发生策略更新。此外,如果 graph 具有至少两个顶点但零个边,则也不会发生策略更新。

vid:

要更新其策略的顶点。假定 vid 表示 graph 中的顶点。不执行检查,您有责任确保 vid 确实是 graph 的顶点。如果提供了孤立顶点,即输入顶点的度为 0,则不会发生策略更新,并且 vid 将保留其当前策略。如果 vid 的局部邻域是其入邻居(分别是出邻居),但 vid 具有零个入邻居(分别是出邻居),则也不会发生策略更新。在计算 vid 的度(入度、出度、所有度)时,循环将被忽略。

algo:

此标志控制在随机模仿中使用哪种算法。支持的值为

IGRAPH_IMITATE_AUGMENTED

增强模仿。顶点 vid 模仿所选顶点 u 的策略,前提是这样做会增加 vid 的数量(例如,适应度)。增强模仿可以认为是“如果更好则模仿”。

IGRAPH_IMITATE_BLIND

盲目模仿。顶点 vid 盲目模仿所选顶点 u 的策略,无论这样做是否会增加或减少 vid 的数量。

IGRAPH_IMITATE_CONTRACTED

收缩模仿。这里,顶点 vid 模仿所选顶点 u 的策略,如果这样做会减少 vid 的数量。将收缩模仿视为“如果更糟则模仿”。

quantities:

一个数量向量,提供 graph 中每个顶点的数量。将向量的每个条目都视为由诸如博弈的适应度函数之类的函数生成。因此,如果该向量表示适应度量,则每个向量条目都是某个顶点的适应度。此向量的长度必须与 graph 的顶点集中的顶点数相同。

strategies:

顶点群体的当前策略向量。 vid 的更新策略将存储在此处。每个策略都由一个非负整数标识,其解释取决于博弈的收益矩阵。通常,我们将策略 ID 用作收益矩阵的行或列索引。此向量的长度必须与 graph 的顶点集中的顶点数相同。

模式:

定义要为 vid 考虑的邻域类型。如果 graph 是无向图,则我们使用 vid 的所有直接邻居。因此,如果您知道 graph 是无向图,则在此处传递值 IGRAPH_ALL 是安全的。支持的值为

IGRAPH_OUT

使用 vid 的出邻居。仅当 graph 是有向图时,此选项才相关。

IGRAPH_IN

使用 vid 的入邻居。同样,仅当 graph 是有向图时,此选项才相关。

IGRAPH_ALL

同时使用 vid 的入邻居和出邻居。仅当 graph 是有向图时,此选项才相关。如果 graph 是无向图,也请使用此值。

返回值: 

在以下每种情况下,都会返回错误代码 IGRAPH_EINVAL:(1)任何参数 graphquantitiesstrategies 都是空指针。(2)向量 quantitiesstrategies 的长度与 graph 中的顶点数不同。(3)参数 graph 是空图或零图,即具有零个顶点和边的图。(4)参数 algo 指的是不支持的随机模仿算法。

时间复杂度:取决于均匀随机数生成器,但通常应为 O(1)。

示例 10.3.  文件 examples/simple/igraph_stochastic_imitation.c

#include <igraph.h>
#include <stdio.h>

/* test parameters structure */
typedef struct {
    igraph_t *graph;
    igraph_integer_t vertex;
    igraph_imitate_algorithm_t algo;
    igraph_vector_t *quantities;
    igraph_vector_int_t *strategies;
    igraph_vector_int_t *known_strats;
    igraph_neimode_t mode;
    igraph_integer_t retval;
} strategy_test_t;

/* Updating the strategy of an isolated vertex. In this case, the strategies
 * vector should not change at all.
 */
igraph_error_t isolated_vertex_test(void) {
    igraph_t g;
    igraph_vector_t quant;
    igraph_vector_int_t strat, v;
    igraph_integer_t i;
    igraph_error_t ret;

    /* graph with one isolated vertex */
    igraph_small(&g, /*n vertices*/ 0, IGRAPH_UNDIRECTED, 0, 1, 1, 2, 2, 0, -1);
    igraph_add_vertices(&g, 1, 0);  /* new vertex 3 is isolated */
    /* quantities vector: all vertices have the same fitness */
    igraph_vector_init_real(&quant, 4, 0.25, 0.25, 0.25, 0.25);
    /* strategies vector: 0 means aggressive strategy; 1 means passive */
    igraph_vector_int_init_int(&strat, 4, 1, 0, 1, 0);
    /* make a copy of the original strategies vector for comparison later on */
    igraph_vector_int_init_copy(&v, &strat);
    /* Now update strategy of vertex 3. Since this vertex is isolated, no */
    /* strategy update would take place. The resulting strategies vector */
    /* would be the same as it was originally. */
    ret = igraph_stochastic_imitation(/*graph*/ &g,
            /*vertex*/ 3,
            /*algorithm*/ IGRAPH_IMITATE_BLIND,
            /*quantities*/ &quant,
            /*strategies*/ &strat,
            /*mode*/ IGRAPH_ALL);
    if (ret) {
        printf("Isolated vertex test failed.\n");
        return IGRAPH_FAILURE;
    }
    for (i = 0; i < igraph_vector_int_size(&strat); i++) {
        if (VECTOR(strat)[i] != VECTOR(v)[i]) {
            printf("Isolated vertex test failed.\n");
            return IGRAPH_FAILURE;
        }
    }
    /* clean up */
    igraph_destroy(&g);
    igraph_vector_destroy(&quant);
    igraph_vector_int_destroy(&strat);
    igraph_vector_int_destroy(&v);

    return IGRAPH_SUCCESS;
}

/* A game on the Petersen graph. This graph has 10 vertices and 15 edges. The
 * Petersen graph is initialized with a default quantities vector and a
 * default strategies vector. Some vertices are chosen for strategy revision,
 * each one via a different stochastic imitation rule.
 */
igraph_error_t petersen_game_test(void) {
    igraph_t g;
    igraph_bool_t success;
    igraph_vector_t quant;
    igraph_vector_int_t strat, stratcopy, *knownstrats;
    igraph_vector_int_t known0, known2, known4;
    igraph_integer_t i, k, n;
    igraph_error_t ret;
    int nvert;
    strategy_test_t *test;

    /* the Petersen graph */
    igraph_small(&g, /*n vertices*/ 0, IGRAPH_UNDIRECTED,
                 0, 1, 0, 4, 0, 5, 1, 2, 1, 6, 2, 3, 2, 7, 3, 4, 3, 8, 4, 9,
                 5, 7, 5, 8, 6, 8, 6, 9, 7, 9, -1);
    nvert = igraph_vcount(&g);
    /* Strategies vector, one strategy for each vertex. Thus vec[i] is the */
    /* strategy of vertex i. The strategy space is: {0, 1, 2, 3}. */
    /* Each strategy should be an integer. */
    igraph_vector_int_init_int(&strat, nvert, 1, 1, 2, 2, 0, 0, 0, 1, 2, 3);
    /* Quantities vector, one quantity per vertex. Thus vec[i] is the */
    /* quantity for vertex i. */
    igraph_vector_init_real(&quant, nvert,
                            0.3, 1.1, 0.5, 1.0, 0.9,
                            0.8, 0.4, 0.1, 0.7, 0.7);
    /* parameter settings and known results */
    igraph_vector_int_init_int(&known0, 2, 0, 1);
    igraph_vector_int_init_int(&known2, 2, 1, 2);
    igraph_vector_int_init_int(&known4, 2, 0, 2);
    /*graph--vertex--algo--quantities--strategies--known_strats--mode--retval*/
    strategy_test_t blind0 = {&g, 0, IGRAPH_IMITATE_BLIND, &quant, NULL, &known0, IGRAPH_ALL, IGRAPH_SUCCESS};
    strategy_test_t augmented4 = {&g, 4, IGRAPH_IMITATE_AUGMENTED, &quant, NULL, &known4, IGRAPH_ALL, IGRAPH_SUCCESS};
    strategy_test_t contracted2 = {&g, 2, IGRAPH_IMITATE_CONTRACTED, &quant, NULL, &known2, IGRAPH_ALL, IGRAPH_SUCCESS};
    strategy_test_t *all_checks[] = {/* 1 */ &blind0,
                                             /* 2 */ &augmented4,
                                             /* 3 */ &contracted2
                                    };
    /* run the tests */
    n = 3;
    i = 0;
    while (i < n) {
        test = all_checks[i];
        igraph_vector_int_init_copy(&stratcopy, &strat);
        ret = igraph_stochastic_imitation(test->graph, test->vertex, test->algo,
                                          test->quantities, &stratcopy,
                                          test->mode);
        if (ret) {
            printf("Stochastic imitation failed for vertex %" IGRAPH_PRId ".\n", test->vertex);
            return IGRAPH_FAILURE;
        }
        /* If the updated strategy for the vertex matches one of the known */
        /* strategies, then success. Default to failure. */
        success = 0;
        knownstrats = test->known_strats;
        for (k = 0; k < igraph_vector_int_size(knownstrats); k++) {
            if (VECTOR(*knownstrats)[k] == VECTOR(stratcopy)[test->vertex]) {
                success = 1;
                break;
            }
        }
        if (!success) {
            printf("Stochastic imitation failed for vertex %" IGRAPH_PRId ".\n", test->vertex);
            return IGRAPH_FAILURE;
        }
        igraph_vector_int_destroy(&stratcopy);
        i++;
    }
    /* clean up */
    igraph_destroy(&g);
    igraph_vector_int_destroy(&known0);
    igraph_vector_int_destroy(&known2);
    igraph_vector_int_destroy(&known4);
    igraph_vector_destroy(&quant);
    igraph_vector_int_destroy(&strat);

    return IGRAPH_SUCCESS;
}

int main(void) {
    igraph_error_t ret;

    igraph_rng_seed(igraph_rng_default(), 547612);

    ret = isolated_vertex_test();
    if (ret) {
        return ret;
    }
    ret = petersen_game_test();
    if (ret) {
        return ret;
    }

    return IGRAPH_SUCCESS;
}