<< 返回本书主页
<< Back to the afterword page

3 极化关系下网络结构的稳定平衡性

吕汶桧 Wenhui Lyu

Jan. 2022

codes

3.1 背景问题

本讲的主题是,社会网络在什么情况下是平衡的,什么情况下不是?

在一个社会中,两个人的关系可能是友善的,也可能是互相抱有敌意的。为了模拟这种现象,我们可以把社会网络中某两个节点之间的边,标注为正关系(友)或负关系(敌)。对于网络中的一个三角结构,我们就可以讨论它是否平衡。

balanced triangles

unbalanced triangles

在一个社会网络中,如果所有三角关系都是平衡的,那么这个网络就是平衡的;否则,总有力量改变其中的某个三角关系,从而影响网络结构的平衡性。这个定义可以进一步操作化——结构平衡定理:

一个边标注完全图是平衡的,当且仅当它的所有边都是“+”边或节点集能划分为两个子集,子集内部都是“+”边,子集之间都是“-”边。

也就是说,这一网络要么全部是正关系,要么可以表示为如下的结构:

结构平衡定理

简单的归谬法就可以证明这一定理。如果左边的关系中存在负关系,设节点B和节点C之间为“-”边,那么ABC就是“++-”的不稳定关系。如果右边的关系中存在正关系,设节点B和节点C之间为“+”边,那么ABC就是“++-”的不稳定关系。

可是,社会网络中并非所有节点之间都有边,不是所有边都身处一个或多个三角关系中,逐个考察三角关系的方法不再适用。对于不完全网络图,我们如此理解它的平衡状态:不会因为增加一条标注边,出现不可避免的不平衡三角子图。例如下图,当两个本无关系的人BD,处在两个潜在的三角关系ABDBCD中,ABD要求BD为“+”关系,BCD要求BD为“-”关系。不管加上的BD边是什么,这幅图都会出现不平衡三角子图。

不平衡的不完全网络图

也就是说,一个平衡的不完全网络图,可以通过补充缺失的边(带极性),成为一个平衡的完全网络。根据结构平衡定理,平衡的不完全网络图的定义也可以进一步操作化:

若已有边不全是“+”,则节点可以分成两组,组内边均为“+”,跨组边均为“-”。

3.2 计算实践:网络结构平衡性的判断

codes

3.2.1 作业描述与算法思路

接续上文,要判断不完全网络图是否平衡,我们已经有了一个操作化定理:

若已有边不全是“+”,则节点可以分成两组,组内边均为“+”,跨组边均为“-”。

但这距离算法化还有一定距离。为了算法化,我们还要进一步用到图论的知识:一个含有奇数个“-”的圈的节点不能被分成这样两组:每一组内部的关系都为“+”,跨组的边均为“-”。

也就是说,如果图中存在一个含有奇数个“-”的圈,就没有可能将其节点安排到两个对立阵营中;反过来,若没有那样的圈,则总是可以将所有节点做两个阵营的划分。根据上述操作化定理,如果图中存在一个含有奇数个“-”的圈,该图就不平衡;反之就平衡。

为了更方便地判定网络中是否存在含有奇数个“-”的圈,我们可以整体考虑内部边均为“+”的节点子集,因为它们并不会影响自己所在的圈有多少个“-”。把内部边均为“+”的节点集合为一个“连通分量”,从而把网络简化为“简约图”。这样,简约图里所有的边都是“-”边。例如,下图左侧的不完全社会网络(红边为“+”、黑边为“-”),就可以表示为右侧的简约图。

简约图

现在,我们只需要考虑简约图里有没有长度为奇数的圈。判定方式是“广度优先搜索”(Breadth First Search or BFS)。在下图的例子中,对左侧的图以节点G为起点做广度优先搜索,所有节点被归入到1–3层里。

广度优先搜索

从广度优先搜索的结果可以看到,圈的形成有两种方式:

这样,要判断不完全网络图是否平衡,我们只需要BFS结果中是否存在同层边。

3.2.2 编程实现与要点说明

首先,我们还是需要调用读取数据文件的函数,把邻接矩阵存储在一个numpy 2d-array array里。代码略,与1.2.1.2类似。一个数据文件的例子如下:

第一步,我们先要把网络简化为简约图。先写一个函数cluster,找出节点i所处的连通分量group,其中所有边都是“+”边。这个函数用到了递归,我先以i为起点,找到和它以“+”边相连的节点j,再以j为起点做同样的操作(这其实也是“广度优先搜索”),直到找不到更多以“+”边相连的节点。

循环调用cluster函数,每次的搜索起点是还未归入某一连通分量的节点,直到把网络中所有节点都归入某一连通分量。结果存储在groups中。

以下是一个输出结果的例子:

寻找连通分量的过程,并未一一检查内部的所有边。以特定次序找“+”得出的节点集合,在另一种找边的次序中可能存在“-”边。因此我们还需要重新检查一下连通分量内部是否有“-”边。如果有的话,我们可以直接确定这一网络不平衡,因为这一连通分量内部有“++-”的不稳定关系。

如果连通分量内部没有“-”边,我们就可以使用groups的信息生成简约图array2。我们检查连通分量之间是否有边(只可能是“-”边),从而确定表示简约图的矩阵在每一格应该填什么。有边就填1,无边就填0。

接着,我们对简约图做广度优先搜索:输入起点节点,输出搜索结果(每一层有哪些节点layers,节点之间的边有哪些layerCon)。这一过程依靠函数bfs完成。

搜索时,我用到了递归,搜索到下一层的节点j_list后,再以j_list里的节点为起点搜索再下一层,直到搜不到更多节点j_list == []

有了搜索结果,我们就可以两两检查每层内的节点,判断层间边是否存在。

存在层内边时,我们还可以用一个函数circleSpotter找出奇数圈:输入两个起点节点编码(初始为存在层内边的两个节点编码ij)、它们在哪一层layerI、已经找到的奇数圈节点oddCir(初始为[i,j])、广度优先搜索的结果layerslayerCon;返回所有奇数圈节点。

定义一个局部函数nodeAdder,它的作用是,当我们找到起点节点所在的层内边edge后(如ii2),我们把i2加入oddCir当中,并把i2确定为新的起点节点,以便进行下一轮搜索。

给定ij,分别调用nodeAdder函数,沿着ij所在的层间边,确定下一组起点节点(在更高层)i2j2

i2j2为新的起点节点继续搜索(递归),直到两条搜索线路汇集于同一点i2 == j2

对于每一条层间边,我们都可以调用circleSpotter函数,找出它所在的奇数圈。下述代码中自oddcnt += 1始。

<< 返回本书主页
<< Back to the afterword page