5D Library › 社会网络拓扑、结构洞与复杂传染的数学模型 · English

第二章 结构洞:闭合与经纪

两种社会资本

上一章讨论的是连带:哪一条关系带来新信息。本章讨论位置:一个人的联系人彼此之间是怎样连接的。社会学里有两种看起来相反的观点。

第一种强调闭合。科尔曼认为,一个人的联系人彼此相识、相互连接时,网络就能产生信任、规范与约束:如果一个人违背承诺,所有人都会知道,因此人人都更守信用;家长彼此认识的学校里,孩子更难逃避管教。他把这种由闭合的网络带来的好处称为社会资本 (Coleman 1988)。

第二种强调经纪。伯特在 1992 年的专著《结构洞》中提出,网络中最有价值的往往不是紧密,而是空隙:如果你的两个联系人彼此不相识,他们之间就有一个「结构洞」,而你是唯一能把两边的信息、资源与机会连起来的人。圈子内部的意见与做法趋同,站在圈子之间的人能更早接触到不同的想法,也能决定把什么从一边带到另一边 (Burt 1992)。

网络约束与有效规模

伯特用一个量来衡量一个人的网络在多大程度上「被困」在彼此相连的联系人之中。设 pijp_{ij} 是 ii 投入在联系人 jj 上的时间与精力占全部的比例(对没有权重的无向网络,pij=1/kip_{ij} = 1/k_i),ii 与 jj 之间的二元约束为

cij=(pij+∑q≠i,jpiqpqj)2c_{ij} = \Big(p_{ij} + \sum_{q \neq i, j} p_{iq}\, p_{qj}\Big)^2

括号中第一项是 ii 对 jj 的直接投入,第二项是通过共同联系人 qq 的间接投入:如果 ii 的其他联系人也都和 jj 有很多往来,ii 就很难绕开 jj。ii 的网络约束是 Ci=∑jcijC_i = \sum_j c_{ij}。约束越高,结构洞越少 (Burt 1992)。

另一个指标是有效规模:联系人数减去冗余。对没有权重的无向网络,博加蒂证明伯特的定义可以化简为 n−2t/nn – 2t/n,其中 nn 是联系人数,tt 是这些联系人之间的连带数 (Borgatti 1997)。有效规模除以 nn 称为效率。

推导

在一个虚构的小网络上计算这几个量。a、b、c 三个四人小组,组内两两相识。安娜是 a 组的第五个成员,与 a1–a4 都相识;波与每个小组各有一位联系人(a1、b1、c1);赛与 b 组两人、c 组两人相识。

# Burt's network constraint and effective size on a small invented network.
# Three groups of four (a, b, c) are cliques. Ana is a fifth member of group a
# (tied to all of a1-a4). Bo is tied to one person in each group (a1, b1, c1).
# Cy is tied to two people in group b and two in group c (b2, b3, c2, c3).
# For binary undirected ties p_ij = 1/k_i (Burt 1992). Dyadic constraint
#   c_ij = (p_ij + sum over q != i, j of p_iq * p_qj) ** 2,  C_i = sum_j c_ij.
# Effective size = n - 2t/n (t = ties among the n contacts; Borgatti 1997).
from itertools import combinations
groups = {g: [f"{g}{i}" for i in range(1, 5)] for g in "abc"}
ties = set()
for members in groups.values():
    ties |= {tuple(sorted(e)) for e in combinations(members, 2)}
ties |= {("Ana", x) for x in groups["a"]}
ties |= {("Bo", x) for x in ("a1", "b1", "c1")}
ties |= {("Cy", x) for x in ("b2", "b3", "c2", "c3")}
nb = {}
for u, v in ties:
    nb.setdefault(u, set()).add(v); nb.setdefault(v, set()).add(u)

def p(i, j):
    return 1 / len(nb[i]) if j in nb[i] else 0.0

def dyadic(i, j):
    return (p(i, j) + sum(p(i, q) * p(q, j) for q in sorted(nb[i]) if q != j)) ** 2

def constraint(i):
    return sum(dyadic(i, j) for j in sorted(nb[i]))

def effective_size(i):
    n = len(nb[i])
    t = sum(1 for u, v in combinations(nb[i], 2) if v in nb[u])
    return n - 2 * t / n

print("node  contacts  effective size  efficiency  constraint  largest c_ij")
for i in ("Ana", "a2", "a1", "Cy", "Bo"):
    n, es = len(nb[i]), effective_size(i)
    j = max(sorted(nb[i]), key=lambda x: dyadic(i, x))
    print(f" {i:4s} {n:6d} {es:13.2f} {es / n:12.2f} {constraint(i):11.3f}"
          f"     {j} {dyadic(i, j):.3f}")
print("benchmarks: n unconnected contacts give C = 1/n;"
      f" a clique of 5 gives C = {4 * (0.25 + 3 / 16) ** 2:.3f}")
# node  contacts  effective size  efficiency  constraint  largest c_ij
#  Ana       4          1.00         0.25       0.733     a1 0.191
#  a2        4          1.00         0.25       0.733     a1 0.191
#  a1        5          2.60         0.52       0.530     Ana 0.123
#  Cy        4          3.00         0.75       0.391     b2 0.098
#  Bo        3          3.00         1.00       0.333     a1 0.111
# benchmarks: n unconnected contacts give C = 1/n; a clique of 5 gives C = 0.766

安娜与 a2 的四个联系人彼此全都相识,有效规模只有 1,约束为 0.733(如果 a1 没有与波相连,这个五人小团体中每个人的约束都是 0.766)。波只有三个联系人,但他们分属三个互不相识的小组,有效规模为 3、效率为 1、约束为 1/3,是这个网络中最低的。赛的四个联系人分成两对,有效规模为 3,约束为 0.391。a1 因为同时属于 a 组又与波相连,约束降到 0.530。这几个数字说明,约束与联系人的多少关系不大,与联系人之间是否相连关系很大:联系人更多的安娜比联系人更少的波受到的约束高得多。

介数中心性与布兰德斯算法

衡量「站在中间」的另一个常用指标是弗里曼的介数中心性:在所有人两两之间的最短路径中,有多大比例经过某个人 (Freeman 1977)。直接计算需要枚举所有的路径。布兰德斯在 2001 年给出了一个快得多的算法:从每个起点做一次广度优先搜索,记下到达每个人的最短路径条数,再从最远处往回累加每个人「承担」的路径比例,对没有权重的网络,总的计算量与人数乘以连带数成正比 (Brandes 2001)。

推导

用标准库实现布兰德斯算法。第一部分用上面的虚构网络;第二部分用一个合成网络(12 个 15 人小组,组内连带概率 0.35,组间另有 40 条随机连带),看介数中心性与网络约束是否一致。介数已归一化到 0–1。

# Betweenness centrality with Brandes' (2001) algorithm, standard library only:
# one breadth-first search per source, then dependencies accumulated backwards,
# O(n m) for unweighted graphs instead of O(n^3).
# Part 1: the invented network of the constraint program (p03).
# Part 2: a synthetic network of 12 groups of 15 (tie probability 0.35 inside,
# 40 random ties between groups): do betweenness and low constraint agree?
import random
from collections import deque
from itertools import combinations

def brandes(nb):
    bc = {v: 0.0 for v in nb}
    for s in nb:
        stack, pred = [], {v: [] for v in nb}
        sigma = dict.fromkeys(nb, 0); sigma[s] = 1
        dist = dict.fromkeys(nb, -1); dist[s] = 0
        q = deque([s])
        while q:
            v = q.popleft(); stack.append(v)
            for w in sorted(nb[v]):
                if dist[w] < 0:
                    dist[w] = dist[v] + 1; q.append(w)
                if dist[w] == dist[v] + 1:
                    sigma[w] += sigma[v]; pred[w].append(v)
        delta = dict.fromkeys(nb, 0.0)
        while stack:
            w = stack.pop()
            for v in pred[w]:
                delta[v] += sigma[v] / sigma[w] * (1 + delta[w])
            if w != s:
                bc[w] += delta[w]
    n = len(nb)
    return {v: bc[v] / 2 / ((n - 1) * (n - 2) / 2) for v in nb}   # undirected, 0..1

def constraint(nb, i):
    p = lambda a, b: 1 / len(nb[a]) if b in nb[a] else 0.0
    return sum((p(i, j) + sum(p(i, q) * p(q, j) for q in sorted(nb[i])
                              if q != j)) ** 2 for j in sorted(nb[i]))

def add(nb, u, v):
    nb.setdefault(u, set()).add(v); nb.setdefault(v, set()).add(u)

nb = {}
for g in "abc":
    for u, v in combinations([f"{g}{i}" for i in range(1, 5)], 2):
        add(nb, u, v)
for x in ("a1", "a2", "a3", "a4"): add(nb, "Ana", x)
for x in ("a1", "b1", "c1"): add(nb, "Bo", x)
for x in ("b2", "b3", "c2", "c3"): add(nb, "Cy", x)
bc = brandes(nb)
print("part 1 (normalised betweenness, 0-1):")
top6 = sorted(nb, key=lambda v: -bc[v])[:6]
print("  " + ", ".join(f"{v} {bc[v]:.3f}" for v in top6))
print(f"  Ana {bc['Ana']:.3f}, a2 {bc['a2']:.3f}")

rng = random.Random(4)
G, S = 12, 15
big = {i: set() for i in range(G * S)}
for g in range(G):
    for a, b in combinations(range(g * S, (g + 1) * S), 2):
        if rng.random() < 0.35: add(big, a, b)
k = 0
while k < 40:
    a, b = rng.randrange(G * S), rng.randrange(G * S)
    if a // S != b // S and b not in big[a]:
        add(big, a, b); k += 1
bc = brandes(big)
con = {v: constraint(big, v) for v in big}

def ranks(d):                     # average ranks, so tied values share a rank
    order = sorted(d, key=lambda v: d[v]); r = {}; i = 0
    while i < len(order):
        j = i
        while j + 1 < len(order) and abs(d[order[j + 1]] - d[order[i]]) < 1e-12:
            j += 1
        for v in order[i:j + 1]: r[v] = (i + j) / 2
        i = j + 1
    return r

def pearson(x, y):
    mx, my = sum(x) / len(x), sum(y) / len(y)
    sxy = sum((a - mx) * (b - my) for a, b in zip(x, y))
    sxx = sum((a - mx) ** 2 for a in x); syy = sum((b - my) ** 2 for b in y)
    return sxy / (sxx * syy) ** 0.5

rb, rc = ranks(bc), ranks(con)
n = len(big)
rho = pearson([rb[v] for v in big], [rc[v] for v in big])   # Spearman
print(f"part 2: {n} people; Spearman correlation of betweenness with constraint"
      f" = {rho:+.2f}")
top = sorted(big, key=lambda v: -bc[v])[:5]
print("  top 5 by betweenness  (bc, constraint C, ties outside own group):")
for v in top:
    out = sum(1 for w in big[v] if w // S != v // S)
    print(f"    person {v:3d}: bc {bc[v]:.3f}, C {con[v]:.2f}, {out} outside")
print(f"  median person: bc {sorted(bc.values())[n // 2]:.3f},"
      f" C {sorted(con.values())[n // 2]:.2f}")
# part 1 (normalised betweenness, 0-1):
#   Bo 0.544, a1 0.440, b1 0.251, c1 0.251, Cy 0.126, b2 0.050
#   Ana 0.000, a2 0.000
# part 2: 180 people; Spearman correlation of betweenness with constraint = -0.78
#   top 5 by betweenness  (bc, constraint C, ties outside own group):
#     person 133: bc 0.129, C 0.19, 2 outside
#     person  32: bc 0.127, C 0.19, 2 outside
#     person 100: bc 0.114, C 0.19, 2 outside
#     person   6: bc 0.111, C 0.18, 2 outside
#     person 116: bc 0.102, C 0.31, 2 outside
#   median person: bc 0.009, C 0.28

在虚构网络中,波的介数最高(0.544),因为三个小组之间的最短路径都要经过他;a1 次之(0.440),因为 a 组与外界的联系都经过他;安娜与 a2 的介数为 0:任何两人之间都有不经过他们的同样短的路径。在 180 人的合成网络中,介数与约束的等级相关为 −0.78:站在中间的人,网络约束通常较低。介数最高的五个人都各有两条通往其他小组的连带,约束在 0.18–0.31 之间,而中位数的人介数只有 0.009、约束为 0.28。两者并不完全一致:介数衡量的是整个网络的路径,约束只看一个人周围的局部结构;一个人可以约束不高,却站在一个偏僻的角落里。

经纪的证据

证据

结构洞与好主意。 伯特研究了美国一家大型电子公司 2001 年负责供应链的 673 名经理,其中 455 人(68%)完成了网络调查。每位经理被要求提出一项能改进供应链管理的建议,两位负责公司最大供应链业务的高层经理在不知道作者是谁的情况下为这些建议打分(「如果执行得好,这个想法能创造多少价值?」,1–5 分),也可以拒绝评分。结果,网络约束较低、跨越结构洞的经理更可能提出建议,他们的建议更少被拒绝评分,也更可能被评为有价值。网络约束还与较低的相对薪酬、较差的绩效评价和较低的晋升机会相关 (Burt 2004)。

这项研究是结构洞理论最常被引用的证据,但有几点需要注意。第一,它是一家公司在一个时点上的相关研究,不能排除反向的因果:更有能力的经理可能更容易建立跨部门的关系,而不是跨部门的关系使人更有能力。第二,「好主意」由两位高层评判,他们自己的位置与偏好会影响评分。第三,样本是一家美国公司的管理者,经纪的收益在其他情境下是否存在,需要另外检验。

证据

经纪不一定有用。 肖知兴与徐淑英在中国四家高科技企业中研究了结构洞与员工职业结果的关系,使用网络调查与访谈数据。他们认为,在强调集体主义价值的中国文化中,「经纪人」不一定被认可:组织的高承诺文化越强,结构洞对员工的薪酬、奖金等职业成就越有害,而把彼此不相识的人连在一起、「填补」结构洞的整合者获得了更多的职业收益 (Xiao and Tsui 2007)。

这项研究提示,「结构洞带来收益」不是一条普遍的定律,而取决于组织如何看待站在中间的人:是把他看作带来新信息的桥梁,还是看作可能利用信息差谋取私利的人。在一个高度依赖信任与长期承诺的环境里,后一种看法可能占上风。科尔曼的闭合与伯特的经纪,因此更像是一对需要按情境权衡的选择,而不是谁对谁错。

注

经纪的两种做法。 伯特在《结构洞》中讨论过「渔翁得利」(tertius gaudens)式的经纪:利用两方彼此不相识而从中获益,例如让两个供应商互相压价。这种做法在交易中合法,但在团队与社群中容易损害信任,也正是肖与徐所描述的那种被排斥的经纪。本书讨论结构洞,是为了理解信息如何在群体之间流动,以及群体为什么会因为封闭而看不到别的做法;第八章的核查表关心的是把彼此隔绝的人连接起来,而不是利用隔绝。本书不提供任何操纵他人关系的方法。

假说 · 尚未验证

经纪与信任的代价(尚未确立)。在同一家组织中,跨越结构洞较多的成员提出的方案会被盲评为更新颖,但当同事认为他们「控制」了组间信息时,对他们的信任评分会下降,方案被采纳的比例反而降低。可以检验的预测:在控制方案的盲评质量之后,「被认为控制信息」的评分与方案的采纳率负相关。如果这一负相关不存在,或者跨越结构洞的成员在信任评分上与他人没有差别,这一假说就被削弱。

本章小结

科尔曼的闭合强调紧密的网络带来信任与约束,伯特的结构洞强调站在圈子之间带来信息与机会。网络约束衡量一个人被困在彼此相连的联系人中的程度,它取决于联系人之间是否相连,而不是联系人的多少;网络约束与介数中心性从不同角度衡量同一种「位置」,在合成网络中两者高度(负)相关但并不相同。伯特对 673 名经理的研究显示,跨越结构洞的人更可能提出被认为有价值的建议,也获得更好的薪酬与晋升;但在中国高科技企业中,在高承诺的组织文化里结构洞反而有害。下一章讨论,当传播的东西不是一条消息而是一种需要多人强化的行为时,桥还够不够。

参考文献

Borgatti, Stephen P. 1997. “Structural Holes: Unpacking Burt’s Redundancy Measures.” Connections 20 (1): 35–38.
Brandes, Ulrik. 2001. “A Faster Algorithm for Betweenness Centrality.” Journal of Mathematical Sociology 25 (2): 163–77. https://doi.org/10.1080/0022250X.2001.9990249.
Burt, Ronald S. 1992. Structural Holes: The Social Structure of Competition. Cambridge, MA: Harvard University Press.
———. 2004. “Structural Holes and Good Ideas.” American Journal of Sociology 110 (2): 349–99. https://doi.org/10.1086/421787.
Coleman, James S. 1988. “Social Capital in the Creation of Human Capital.” American Journal of Sociology 94: S95–120. https://doi.org/10.1086/228943.
Freeman, Linton C. 1977. “A Set of Measures of Centrality Based on Betweenness.” Sociometry 40 (1): 35–41. https://doi.org/10.2307/3033543.
Xiao, Zhixing, and Anne S. Tsui. 2007. “When Brokers May Not Work: The Cultural Contingency of Social Capital in Chinese High-Tech Firms.” Administrative Science Quarterly 52 (1): 1–31. https://doi.org/10.2189/asqu.52.1.1.

Fan, Y. (2026). Social Network Topology, Structural Holes and Complex Contagion: From the Strength of Weak Ties and Preferential Attachment to Information Cascades, Read Beside Classical Chinese Diplomacy [社会网络拓扑、结构洞与复杂传染的数学模型] (Version 1.0.0). 5D Library. https://doi.org/10.5281/zenodo.23764990 · Licensed under Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International (CC BY-NC-ND 4.0).