复杂网络仿真入门到精通4: 社团结构分析

系列文章:

一、引言:社团结构的重要性

社团结构(Community Structure)是复杂网络研究中最具代表性的现象之一。
它描述了网络中节点之间形成紧密连接群体的现象,在社交网络、科研合作网络、生物网络中普遍存在。

  • 社交网络:社团对应朋友圈或兴趣群体;
  • 科研合作网络:社团对应研究方向或课题组;
  • 生物网络:社团对应功能模块(如基因调控模块)。

通过社团分析,我们可以理解网络的宏观组织形态、发现潜在的功能群体,并进一步优化传播、推荐或控制机制。
因此,社团检测已成为复杂网络分析中最核心的研究内容之一。

本文对应资源
github代码地址:复杂网络学习合集-step4
如访问不了可从下列地址保存:第一个文件夹 下面的 Step4
网盘地址


二、社团检测的基本思路

社团划分的目标是:

让社团内部的连接尽量密集,而社团之间的连接尽量稀疏。

目前主流方法大致可以分为三类:

方法类别 主要思想 常用算法
基于模块度优化(Modularity) 通过最大化模块度 (Q) 寻找最优划分 Louvain、Newman
基于谱聚类(Spectral) 对网络拉普拉斯矩阵进行特征分解 Spectral Clustering
基于概率模型 用随机块模型(SBM)建模节点连接概率 Stochastic Block Model

这些方法各有优势:

  • Louvain 方法高效、适用于大规模网络;
  • 谱聚类方法理论清晰、便于可解释;
  • 概率模型适合推断复杂多层网络。

三、MATLAB 实现:Louvain 社团检测

在 MATLAB 中,我们通常先构建网络(或载入上一节课程保存的邻接矩阵),然后执行社团检测。
最常见的是 Louvain 算法,它通过模块度 (Q) 的优化自动识别社团。

关键示例:

1
2
3
G = graph(A);
[community, Q] = community_louvain(full(adjacency(G)));
fprintf('模块度 Q = %.4f\n', Q);

得到的结果中:

  • community 表示每个节点所属社团编号;
  • Q 为模块度值,衡量社团划分质量。

随后可使用 force-directed 布局进行可视化:

1
2
3
4
5
p = plot(G, 'Layout', 'force');
colors = lines(max(community));
for i = 1:max(community)
highlight(p, find(community==i), 'NodeColor', colors(i,:));
end

若模块度 (Q > 0.3),说明网络具有明显的社团结构。

四、模块度与网络类型的关系

模块度 ( Q ) 的定义为:

$$Q = \frac{1}{2m} \sum_{ij} \left[ A_{ij} - \frac{k_i k_j}{2m} \right] \delta(c_i, c_j)$$

其中:

  • $(A_{ij})$:邻接矩阵;
  • $(k_i)$:节点 $(i)$ 的度;
  • $(m)$:边总数;
  • $(\delta(c_i, c_j))$:若节点 $(i,j) $属于同一社团则为 1,否则为 0。

根据经验:

  • (Q > 0.3):网络具有显著社团结构;
  • (Q < 0.1):社团结构不明显。

结合前几篇结果,我们可以对网络类型进行对比:

网络类型 主要特征
小世界网络 高聚类系数 + 短平均路径
无标度网络 度分布呈幂律
社团网络 模块度 (Q) 高,结构分层明显

这三类特性经常同时出现在现实系统中,例如社交网络既呈幂律分布,又具有小世界和社团特性。


五、社团结构的功能与桥节点分析

完成社团划分后,我们往往还需识别社团间的关键节点
这些节点在不同社团间起“桥梁作用”,对信息传播或控制极为关键。

在 MATLAB 中,可以使用介数中心性(Betweenness Centrality)来识别桥节点:

1
2
3
bet = centrality(G, 'betweenness');
[~, idx] = max(bet);
fprintf('桥节点编号:%d\n', idx);

随后进行可视化:

1
2
highlight(p, idx, 'NodeColor', 'k', 'Marker', 's', 'MarkerSize', 8);
title('桥节点高亮');

此外,还可以分析不同社团间的连接强度:

1
2
3
imagesc(commMatrix);
colorbar;
title('社团间连接强度矩阵');

从矩阵图中,我们能清晰看到哪些社团之间的交互更频繁。

六、科研视角的延伸与应用

社团检测不仅是可视化的结果,更是理解复杂系统组织规律的关键工具。
在科研与工程应用中,常见的拓展方向包括:

  1. 社团动态演化
    研究社团随时间变化的形成与合并过程,例如社交话题的生命周期。

  2. 多层网络社团检测
    当网络存在多种关系(如“合作”与“引用”),需要分析不同层的社团重叠与耦合。

  3. 基于社团的功能预测
    通过节点所属社团,预测其潜在属性或未来连接。

推荐阅读:

  • Newman, M. E. J. Networks: An Introduction. Oxford University Press, 2010.
  • Fortunato, S. Community Detection in Graphs. Physics Reports, 2010.

七、小结与下一步

本节我们完成了:

  • ✅ 理解社团结构的概念与意义;
  • ✅ 掌握 Louvain 算法的基本实现;
  • ✅ 通过模块度分析网络结构特性;
  • ✅ 识别关键桥节点并可视化社团分布。

最后:给大家推荐一个在线复杂计算平台, 欢迎大家进行体验

👉 复杂网络分析平台

支持:

  • AI 智能报告生成
  • 上传邻接矩阵文件
  • 自动构建网络, 指标一键计算与可视化
  • 网络鲁棒性分析(节点/边攻击)
  • 级联失效模型分析

复杂网络仿真入门到精通3: 网络可视化与指标仿真分析

本文为“复杂网络仿真入门到精通”系列的第三篇,前一篇我们学习了如何构建网络(包括随机网络、小世界网络与无标度网络),本篇将聚焦于网络的可视化与基础统计分析,并进一步探讨如何判断一个网络是否具有“小世界”或“无标度”特性。


一、引言

网络不仅仅是由节点与边组成的抽象结构,其拓扑特征往往蕴含了系统行为的重要信息。
从社交网络到神经网络,从交通系统到蛋白质相互作用网络,理解网络的统计特性是揭示系统规律的第一步。

本文将以 MATLAB 为主要工具,介绍:

  1. 网络可视化方法;
  2. 网络基本指标计算;
  3. 小世界与无标度性质的定量分析;
  4. 幂律分布拟合与验证。

github代码地址:复杂网络学习合集-step3
如访问不了可从下列地址保存:第一个文件夹 下面的 Step3
网盘地址


二、准备数据

可以使用前一篇中的随机、小世界、无标度模型,或导入真实网络。
例如,若已有边列表文件 edge_list.csv

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
if isfile('edge_list.csv')
T = readtable('edge_list.csv');
G = graph(T.source, T.target);
else
% 若无文件,则生成一个小世界网络示例
N = 100;
K = 4;
beta = 0.2;
s = repelem((1:N)', K/2);
t = mod(s + repmat(1:K/2, N, 1), N) + 1;
G = graph(s(:), t(:));
end
````

---

## 三、网络可视化

MATLAB 提供了丰富的可视化布局方式,如 `force`, `subspace`, `circle` 等,下面给出一个简单的实现例子,可以根据这个例子进行一定的后续优化。

```matlab
figure;
plot(G, 'Layout', 'force');
title('网络可视化(Force Layout)');

为了更直观地展示结构特征,可以根据节点度调整节点大小或颜色:

1
2
3
4
5
6
7
deg = degree(G);
figure;
p = plot(G, 'Layout', 'force');
p.NodeCData = deg;
p.MarkerSize = 5 + deg;
colorbar;
title('网络可视化(节点颜色代表度)');

同理 Python R语言,都可以实现类似的可视化方案


四、网络基本统计指标

1. 节点与边

1
2
3
numNodes = numnodes(G);
numEdges = numedges(G);
fprintf('节点数: %d, 边数: %d\n', numNodes, numEdges);

2. 平均度与度分布

1
2
3
4
5
6
deg = degree(G);
avgDeg = mean(deg);
figure;
histogram(deg);
xlabel('Degree'); ylabel('Frequency');
title('节点度分布');

3. 聚类系数与平均最短路径长度

1
2
3
C = mean(clusteringCoefficient(G));
L = mean(distances(G), 'all', 'omitnan');
fprintf('平均聚类系数: %.4f\n平均最短路径长度: %.4f\n', C, L);

clusteringCoefficient(G) 可用自定义函数或基于邻接矩阵计算:

1
2
3
4
5
6
7
8
9
10
11
12
function C = clusteringCoefficient(G)
A = adjacency(G);
n = size(A,1);
C = zeros(n,1);
for i=1:n
ki = sum(A(i,:));
if ki > 1
subA = A(i,:) * A * A(:,i);
C(i) = subA / (ki*(ki-1));
end
end
end

五、小世界特性分析

小世界网络一般具有:

  • 高聚类系数;
  • 短平均路径长度。

为了验证网络是否具有小世界特征,我们需要把网络与同规模、同平均度的随机网络进行对比:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
N = numnodes(G);
E = numedges(G);
G_rand = randomReference(G); % 同规模随机网络

C_rand = mean(clusteringCoefficient(G_rand));
L_rand = mean(distances(G_rand), 'all', 'omitnan');

SWI = (C / C_rand) / (L / L_rand);
fprintf('小世界指数 SWI = %.3f\n', SWI);

if SWI > 1
disp('该网络表现出小世界特性');
else
disp('该网络不具备显著小世界特性');
end

六、无标度特性与幂律度分布

无标度网络的节点度分布通常服从幂律形式:

$$P(k) \sim k^{-\gamma}$$

在对数坐标下呈线性关系。

1
2
3
4
5
6
7
8
deg = degree(G);
[counts, bins] = histcounts(deg, 'BinMethod', 'integers');
bins_center = bins(1:end-1) + diff(bins)/2;

figure;
loglog(bins_center, counts/sum(counts), 'o');
xlabel('k'); ylabel('P(k)');
title('度分布(对数坐标)');

幂律拟合与参数估计

1
2
3
4
5
6
7
8
9
validIdx = deg > 0;
k = deg(validIdx);
[alpha, xmin, L] = plfit(k); % 使用 Clauset 等提出的最大似然估计方法

fprintf('幂律指数 α = %.3f, xmin = %d\n', alpha, xmin);

figure;
plplot(k, xmin, alpha);
title('幂律拟合结果');

若无 plfit 函数,可自行实现或使用简化线性拟合:

1
2
3
4
5
logk = log(bins_center(bins_center>0));
logP = log(counts(bins_center>0)/sum(counts));
coeffs = polyfit(logk, logP, 1);
gamma = -coeffs(1);
fprintf('拟合幂律指数 γ ≈ %.3f\n', gamma);

七、综合分析

特性 判断依据 结论示例
小世界 ( SWI > 1 )
无标度 度分布符合幂律 是(γ ≈ 2.5)

若网络同时满足以上两点,则说明其拓扑结构兼具局部聚集与全局稀疏的复杂性特征。


八、结论

本文从可视化入手,系统介绍了复杂网络的基础统计分析方法。
通过对聚类系数、路径长度、度分布及幂律拟合的分析,我们能够初步判断网络类型:

  • 小世界网络 → 局部紧密、全局高效;
  • 无标度网络 → 度分布长尾,存在“枢纽节点”;

这些特性不仅是理论研究的核心,也为后续的鲁棒性分析传播动力学仿真提供了基础。


九、下一篇预告

下一篇《复杂网络系列④:网络鲁棒性分析》
我们将深入探讨:

  • 网络在随机失效与攻击下的稳定性;
  • 节点介数、节点度、中心性等多种重要性指标。

敬请期待。

最后

我们开发了一个在线复杂网络计算平台:
👉 复杂网络分析平台

支持:

  • 上传邻接矩阵文件
  • 自动构建网络
  • 指标一键计算与可视化
  • AI 智能报告生成

复杂网络仿真入门到精通2: 构建网络(邻接矩阵)

系列文章:

  • 系列合集
  • 下一篇预告:网络可视化与基础统计分析

💡 引言

在复杂网络研究中,“网络构建” 是一切分析与建模的起点。
无论你要研究传播、鲁棒性还是社团结构,第一步都必须拥有一个可计算、可分析的网络结构。而且后续我们的研究,也是研究这个目标网络的特性。
本文以Matlab代码为实例,进行代码说明。

从研究角度看,网络的构建主要分为两类:

① 模拟网络(Synthetic Network) —— 基于模型算法生成;
② 实体网络(Empirical Network) —— 来自现实数据的网络。

两类方式各有侧重:

  • 模拟网络用于理论研究与算法验证;
  • 实体网络用于真实系统建模与特性分析。

而无论哪种方式,最终的核心数据结构都是:邻接矩阵(Adjacency Matrix),邻接表也是可以的。


🧩 一、邻接矩阵的基本形式

假设我们有 ( N ) 个节点,网络可以用一个 ( N \times N ) 的矩阵 ( A ) 表示:

$$
A_{ij} =
\begin{cases}
1, & \text{节点 } i \text{ 与 } j \text{ 有边相连} \
0, & \text{节点 } i \text{ 与 } j \text{ 无连接}
\end{cases}
$$

  • 对于无向网络:矩阵对称$A_{ij} = A_{ji}$;
  • 对于有向网络:矩阵一般不对称;
  • 对于加权网络:$A_{ij}$ 可取任意实数权重。

表达矩阵和后续计算 一般有两种方式:

  1. 使用二维矩阵(doublesparse)来存储邻接矩阵,并以矩阵形式进行后续计算。
  2. 使用邻接矩阵或者邻接表构建图对象(G),并使用这个对象进行后续计算。

🧠 二、构建网络的两条主线

(一)模拟网络(Synthetic Networks)

模拟网络通过算法或数学模型生成人工网络,用于验证理论或测试算法表现。
常见模型包括:

网络类型 特点 MATLAB 构建方式
随机网络(Erdős–Rényi, ER) 边以固定概率 p 随机生成 sprand(N, N, p)
小世界网络(Watts–Strogatz, WS) 高聚类 + 短路径 wattsStrogatz(N, K, p)
无标度网络(Barabási–Albert, BA) 幂律度分布,存在 Hub 节点 pref 或自编生长算法

✅ 示例:随机网络(ER)模型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
N = 10;      % 节点数
p = 0.3; % 边存在的概率
A = rand(N) < p; % 随机连接
A = triu(A,1); % 取上三角避免重复
A = A + A'; % 对称化成无向网络
G = graph(A);
plot(G, 'Layout', 'force');
title('Erdős–Rényi 随机网络');
````

#### ✅ 示例:小世界网络(WS)模型

```matlab
N = 20; K = 4; p = 0.1;
G = wattsStrogatz(N, K, p);
plot(G, 'Layout', 'force');
title('Watts–Strogatz 小世界网络');
A = adjacency(G);

✅ 示例:无标度网络(BA)模型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
N = 20; m = 2;
A = zeros(N);
for i = 1:(m+1)
for j = (i+1):(m+1)
A(i,j)=1; A(j,i)=1;
end
end

for i = (m+2):N
degree = sum(A);
prob = degree / sum(degree);
selected = randsample(1:i-1, m, true, prob);
A(i, selected) = 1; A(selected, i) = 1;
end

G = graph(A);
plot(G, 'Layout', 'force');
title('Barabási–Albert 无标度网络');

这些网络模型是复杂网络研究的基础模型,可用于:

  • 验证算法;
  • 分析理论特性;
  • 模拟不同网络拓扑下的行为。

(二)实体网络(Empirical Networks)

实体网络来源于真实世界的数据,是复杂系统的映射结果。

常见来源包括:

领域 示例 数据格式
社会网络 微信、微博、协作网络 .csv, .edge, .gml
生物网络 蛋白质相互作用网络 .graphml, .mat
技术网络 电网、交通网络、互联网 .txt, .json
科研网络 引文、合作、知识图谱 .csv, .gml

✅ 示例:从边列表构建实体网络

假设你有一个 edges.csv 文件:

Source Target
1 2
1 3
2 4
3 4

MATLAB 构建代码:

1
2
3
4
5
6
7
8
9
10
11
12
data = readtable('edges.csv');
edges = table2array(data(:,1:2));
N = max(edges(:));
A = zeros(N,N);
for k = 1:size(edges,1)
i = edges(k,1); j = edges(k,2);
A(i,j) = 1; A(j,i) = 1; % 无向图
end

G = graph(A);
plot(G, 'Layout', 'force');
title('实体网络示例');

✅ 示例:从 .gml 文件导入网络

1
2
3
G = importgraph('network.gml'); % MATLAB R2023a 起支持
A = adjacency(G);
plot(G);

✅ 示例:从实验或观测矩阵直接读取

1
2
3
4
A = load('brain_connectivity.mat');  % 神经连接矩阵
G = graph(A);
plot(G, 'Layout', 'circle');
title('大脑功能连接网络');

🔍 三、邻接矩阵的验证与操作

当你成功构建网络后,建议进行基本验证:

1
2
3
4
N = size(A,1);
M = nnz(triu(A)); % 边数
degree = sum(A,2); % 各节点度
fprintf('节点数: %d, 边数: %d\n', N, M);

如果矩阵非常稀疏(多数为 0),可转换为稀疏存储:

1
A = sparse(A);

🧭 四、延伸阅读:网络构建策略对分析结果的影响

不同的构建方式会显著影响分析结论:

  • 模拟网络适合研究拓扑理论与算法鲁棒性;
  • 实体网络则能反映真实系统特征与动力学规律。

研究者常在模拟网络上测试方法性能,再在实体网络上验证泛化能力。


⚙️ 五、在线构建与分析平台

我们在平台中提供了一个简易入口:
👉 复杂网络分析平台 - 构建与计算

支持:

  • 上传边表 / 邻接矩阵文件
  • 自动构建网络
  • 指标一键计算与可视化
  • AI 智能报告生成

📘 总结

构建网络是复杂网络研究的起点。
模拟网络实体网络,你可以:

  • 用 MATLAB 生成理想拓扑结构;
  • 从真实数据中提取结构信息;
  • 最终得到可分析、可以可视化的邻接矩阵。

下一篇预告:

  • 复杂网络入门到精通(三)—— 网络可视化与基础统计
  • 我们将使用 MATLAB 展示网络图形化与分布特征。

复杂网络仿真从入门到精通1:关键网络指标解析

引言

复杂网络作为描绘与分析现实世界复杂系统的有力工具,已渗透到自然科学与社会科学的众多领域。从生物网络、技术网络到社会网络,其普适性源于将系统实体抽象为“节点”(Nodes)、将实体间关系抽象为“边”(Edges)的强大能力。对网络拓扑结构的量化分析是理解系统行为、功能与演化规律的基础。

本文旨在系统性介绍复杂网络分析中的核心度量指标,并辅以相应的数学定义,为复杂网络研究扫清障碍。


1. 网络的基本拓扑属性

网络的基本属性是宏观上刻画其规模与连接紧密度的基础。

  • 节点数 (Node Count, N) :网络中节点的总数。
  • 边数 (Edge Count, M) :网络中边的总数。
  • 网络密度 (Density, D) :衡量网络中节点间连接的完备程度。对于一个无向无权网络,其定义为实际存在的边数与可能的最大边数之比。
    $$D = \frac{2M}{N(N-1)}$$
    密度值介于 0 和 1 之间。$D \to 1$ 表示网络趋近于一个完全图(Clique),节点间连接非常紧密;而 $D \to 0$ 则表示网络是一个稀疏网络。

2. 路径、距离与网络效率

路径相关指标主要用于衡量网络中信息或物质的传输效率与可达性。

  • 平均路径长度 (Average Path Length, L) :网络中所有节点对之间最短路径长度的算术平均值。它反映了网络的全局传输效率。
    $$L = \frac{1}{N(N-1)} \sum_{i \neq j} d(i, j)$$
    其中,$d(i, j)$ 是节点 $i$ 和 $j$ 之间的最短路径距离。较小的 $L$ 值通常意味着更高的网络通信效率。

  • 网络直径 (Diameter, D_max) :网络中所有节点对之间最短路径长度的最大值。它定义了网络中信息传输所需的最长时延。


3. 聚类效应与社区结构

这些指标用于量化网络中的局部聚集程度和中尺度结构。

  • 平均聚类系数 (Average Clustering Coefficient, C) :衡量网络中节点“抱团”或形成紧密邻域的平均趋势。一个节点 $i$ 的局部聚类系数 $C_i$ 定义为其邻居节点之间实际存在的边数与可能的最大边数之比。
    $$C_i = \frac{2E_i}{k_i(k_i-1)} $$
    其中,$k_i$是节点$i$的度(邻居数),$E_i$是其
    $k_i$个邻居之间实际存在的边数。网络的平均聚类系数即为所有节点$C_i$的平均值:
    $$C = \frac{1}{N} \sum_{i=1}^{N} C_i$$

  • 社区 (Community) :指网络中由一些连接紧密的节点组成的子图,这些子图内部的连接密度远高于其与网络其余部分的连接密度。

  • 模块度 (Modularity, Q) :衡量网络社区结构划分质量的常用指标。其核心思想是比较社区内部实际存在的边数与在相同节点度和社区划分下的随机期望边数。
    $$Q = \frac{1}{2M} \sum_{i,j} \left[ A_{ij} - \frac{k_i k_j}{2M} \right] \delta(c_i, c_j)$$
    其中,$A_{ij}$ 是邻接矩阵元素,$k_i$ 是节点 $i$ 的度,$\delta(c_i, c_j)$ 函数当节点 $i, j$ 属于同一社区时为 1,否则为 0。$Q$ 值越高(通常认为大于 0.3),表明社区划分越显著。


4. 节点中心性度量

中心性指标用于识别网络中最重要的节点,但“重要性”的定义因场景而异。

  • 度中心性 (Degree Centrality) :最直接的中心性度量,定义为节点的连接数(度)。对于有向图,分为入度和出度。标准化的度中心性为:
    $$C_D(i) = \frac{k_i}{N-1}$$

  • 介数中心性 (Betweenness Centrality) :衡量一个节点作为网络中其他节点对之间最短路径“桥梁”的程度。
    $$C_B(v) = \sum_{s \neq v \neq t}
    \frac{\sigma_{st}(v)}{\sigma_{st}}$$其中,$\sigma_{st}$ 是从节点$s$到$t$
    的最短路径总数,$$\sigma_{st}(v)$$
    是这些路径中经过节点 $v$的数量。高介数的节点是网络信息流的关键瓶颈。

  • 接近度中心性 (Closeness Centrality) :衡量一个节点到网络中所有其他节点的平均距离的倒数。它反映了节点作为信息传播中心的能力。
    $$C_C(v) = \frac{N-1}{\sum_{t \neq v} d(v, t)}$$

  • PageRank :一种衡量节点递归重要性的算法。一个节点的 PageRank 值不仅取决于指向它的链接数量,还取决于这些链接来源节点的重要性。


5. 常见网络拓扑模型

  • 无标度网络 (Scale-Free Network) :许多真实网络的度分布服从幂律分布(Power-law distribution),即 $$P(k) \sim k^{-\gamma}$$,其中 $P(k)$是度为 $k$ 的节点比例,$gamma$ 是幂律指数。这类网络具有少量度极高的“中心节点”(Hubs)和大量度很低的“末梢节点”,呈现“贫富分化”现象。无标度网络对随机故障具有鲁棒性,但对针对中心节点的蓄意攻击则表现出脆弱性。
  • 小世界网络 (Small-World Network) :这类网络同时具有高聚类系数(类似规则网络)和短平均路径长度(类似随机网络)的特征。该特性由 Watts 和 Strogatz 于 1998 年提出,广泛存在于社会、生物和技术网络中。

实践(Matlab代码版)

对上述指标的精确计算与综合分析,是揭示任何复杂系统内在机制的关键。然而,手动计算和分析过程繁琐且易错。
matlab 实现代码请访问:
https://github.com/XuXING0430/complex-network-study

为了促进学术研究与应用探索,我们开发了一个计算平台,该平台旨在提供一个高效、精准且用户友好的网络分析解决方案。可以直接进行体验:

复杂网络分析平台 -
体验地址

还包括以下的功能:

  • 便捷的数据导入 :支持多种标准网络数据格式。
  • 自动化的指标计算 :一键生成包括本文所述在内的数十种关键网络指标。
  • 深度 AI 分析报告 :结合计算结果,提供对网络结构与特性的智能化解读。
  • 图表可视化 :相关指标出图表

复杂网络仿真从入门到精通0:学习路线

一、为什么要学习复杂网络仿真?

在科研中,复杂网络模型 已经成为分析系统结构与动态的重要工具。无论是社交网络、交通网络,还是生物分子网络,其核心问题往往都离不开一个:

“系统中的节点是如何相互影响的?”

很多同学在读论文时,会看到“BA模型”“WS模型”“网络鲁棒性仿真”等名词,但真正动手实现的时候往往卡在第一步——
不知道该从哪里学起,更不知道怎么建模、怎么画图、怎么计算指标。


二、入门前的准备:看书先了解一些基础概念

复杂网络的基础是图论。建议初学者先从一本书开始,从头看起,了解一些基础概念,然后再进行后续研究。

📘 推荐入门教材:《复杂网络理论及其应用》汪小帆 李翔 陈关荣. 清华大学出版社 2006

当然不是整本书都需要看,一开始只需要了解基础概念,下面我会给出一个推荐:

没太多时间看前三章就行,第一章引论介绍,第二章 网络拓扑基本模型及其性质,第三章
Internet拓扑特性及建模。重点是了解基础概念,指标定义,网络特性。

后面的章节基本就是对应了具体的研究方向,有时间的可以快速过一下:

第4章 复杂网络上的传播机理与动力学分析

第5章 复杂网络上的相继故障

第6章 复杂网络中的搜索

第7章 复杂网络中的社团结构

第8章 复杂网络中的同步

了解了这些基础概念之后,可以看论文有哪些自己感兴趣的方向,然后再针对看,研究就可以了。


三、仿真入门路线图(Matlab方向)

如果你对matlab这门语言不熟悉的话,建议学一下matlab软件基础操作,学习matlab语言基础,矩阵操作,常见数学计算。这一步只是初步学习,为能看懂别人的仿真打好基础。

注意:matlab的功能极为强大,有太多的功能是我们一时用不上的,最好是先了解基础,然后后面根据需要再进行学习,节省精力。(其他的语言也是同理)

如果你是科研方向的学生或者开发者,可以按下面这条路线循序渐进:

阶段1:网络结构基础

  • 了解随机网络(Erdős–Rényi)、小世界网络(Watts–Strogatz)和无标度网络(Barabási–Albert)的生成机制;
  • 用 Matlab 自带函数或自己写脚本生成网络;
  • 学会可视化:plot(G)

示例:生成小世界网络

1
2
3
n = 100; k = 4; p = 0.1;
G = watts_strogatz(n, k, p);
plot(G)

阶段2:网络指标分析

  • 计算平均度、聚类系数、路径长度、介数中心性;

  • 掌握 Matlab 的 centrality(G, 'betweenness')clustering_coef_bu(A) 等函数;

  • 对比不同模型的特性差异。

阶段3:按方向进行后续仿真

因为后续的方向不同会导致仿真之间也有很大的不同。


四、建议

  • 看书和仿真可以一起做
    先把基础指标和模型原理搞透,然后可以尝试仿真进行实现,一步一个脚印。

举个例子:你今天看到了度这个指标,那么这个指标的定义是什么?如何实现呢?

matlab中计算很简单:然后就涉及到了两个问题,A是怎么得到的?sum函数的原理是什么?解决了一个指标,等于理解了三个概念。

1
2
% A为邻接矩阵
degree = sum(A);
  • 做本阶段该做的事情

看论文,或者是看博客,发现哪个复杂网络概念不了解,那就去了解概念。

看别人的代码发现matlab(或者其他语言)看不明白,那就去查语句,查函数,查实现。

入门的时候就不要想着后续的研究模型,时候到了再进行研究就可以。

五、最后

欢迎关注,我会持续更新:复杂网络仿真从入门到精通。我会持续更新每一步的代码、科研思路和实现细节,希望能让更多科研人少走弯路。

资料分享:
分享地址

本系列对应的github:工程地址

matlab实现简单级联失效模型

级联失效的定义如下:网络中,一个或少数几个节点或连线的失效会通过节点之间的耦合关系引发其他节点也发生失效,进而产生级联效应,最终导致相当一部分节点甚至整个网络的崩溃,这种现象就称为级联失效,有时也形象称之为“ 雪崩”。

级联失效的原理并不难懂,但是实现起来并不简单,也曾在网上寻找过代码,可以几无所得。有的实现代码确实有点复杂,但我觉得从逻辑上来讲,应该是不难的。

负载-容量模型是应用最为广泛的级联失效模型。该模型主要有三个部分组成,初始负载定义、节点容量设置、负载重分配策略。
一个简单的负荷容量模型流程图可如下图所示:

流程图
重分配策略一般是创新点集中存在的地方,因为这块可以做文章的地方比较多,我理解重这部分可以分三块:策略,节点状态和分配负载的比例。
策略:常见的负载重分配策略有随机分配,按某指标进行分配,剩余负载重分配等等。
节点状态:最简单的就是两种:正常和失效。所以有研究者又设置了一种叫做 过载 的状态,顾名思义就是介于正常和失效的中间状态。
分配负载的比例:最简单的就是当节点失效的时候,失效节点上的所有负载都参与重分配。那么如果有过载这个节点状态呢?那么此时就不是所有的负载都会被分配。
💥 级联失效动态演示
下图是失效过程的动态模拟,红色节点表示在各阶段中失效的节点,示例网络是100节点的侧视图。

根据实际攻击结果的动态图
🎯 模拟前后网络对比

对比图

上面的理论说的差不多,具体从哪里开始创新还是要靠个人自己的研究,本文从代码层面帮助大家实现一个最基础的级联失效模型,希望可以帮助到大家。
下面的示例代码:初始负载为度,节点容量设置为线性模型设置,负载重分配策略为按照度分配。

其中初始负载L0 定义和节点容量C 设置,这两部分相对比较简单:

1
2
3
L0 = sum(A);
C = (1 + a)*L0
重分配部分:

%% 重分配
pre_attack_list = [1];
% 初始节点状态 一开始都是正常所以都是0, 失效为1
status_list = zeros([1 node_num]);
% 失效节点列表
node_index_list{1,1} = pre_attack_list;
% 当前失效的列表
failure_list = node_index_list{1,1};

status_list(node_index_list{1,1}) = 1;
% 存储每个阶段的失效列表
failure_cell{1,1} = node_index_list{1,1};

% 1.从node_index_list拿出此次失效的节点
% 2.计算出相邻节点开始分配
for i = 1:length(indexs)
% 开始分配
f1(i) = Load_redistribution(indexs(i),indexs, L0, status_list(node_index(j)));
L( indexs(i) ) = L0( indexs(i) ) + f1(i)* L0( node_index(j));

% 3. 更新节点状态
% 4. 更新失效列表

if status_list(indexs(i)) == 1
    failure_list = [failure_list indexs(i)];
end

end
% 5. 根据失效列表求得当前网络的指标
A(failure_list,:) = 0;
A(:,failure_list) = 0;
AA = A;

% 记载失效集合
failure_cell{1,k+1} = failure_list;
node_index_list{1,k+1} = setdiff(failure_cell{1,k+1}, failure_cell{1,k});

% 判断级联失效是否停止
all_the_indexs = figure_NetEff( AA ,node_num);
NetEff = all_the_indexs.Eglob;
Max_sub_num = all_the_indexs.Max_sub_num;
实现算法不易,本文仅放置了部分代码,若想获取完整代码或者与我交流,可关注:公众号【三紫智造局】,或直接访问下方内测入口也可以。后续会一直更新相关复杂网络算法和内容,欢迎关注。

放在最后:
我们最近正在开发一个复杂网络平台,参与内测后续上线会赠送免费计算次数
平台入口(内测中)
www.threepurple.cn/

并且我准备建立一个复杂网络交流群,想进群可以联系我。

如何使用postman进行API测试

最近接触了Postman API测试,业务上是需要写出来Postman脚本。以前可以说是从来都没有听说过脚本的事情,虽说也其实这个工具有一点了解,但是在这回实践之后才有了更多的理解。首先推荐大家学习一个Pluralsight的视频Postman Fundamentals,我只是有针对性的看了前一部分,就感觉收获良多。一个好的入门课程其实也是很重要的。

这里我就举例说一个spring security的用户验证的测试,其他的测试过程也是很相似的。

认证测试:

  • step1 在地址栏中输入自己API的地址(例子中是用户登陆认证的一个form)
  • step2 选择请求的方式,这个postman里面有很多,我这里选择的是POST
  • step3 在headers我们可以把Content-Type设置出来
  • step4 在body中加入需要请求的key和对应的value(这个例子中就是username、password,因为spring secutity的登陆认证机制只有验证登陆后才可以进行后续操作,否则就会报401未认证)
  • step5 在Tests中可以编写一些测试语句,以检查得到的Response body是否是你需要的

这个例子的Tests如下:

编写好测试界面中的测试语句,然后点击send,可以在下面的Tests Results中查看测试是否通过,例子中的就是测试全部通过了,如果有错误,下面的提示中会告知你哪个测试出错,以及为什么出错。

下面说一下这几个简单测试语句:

我想在开始之前提醒大家一件事,postman测试语句是需要很精准的,也就是说你写的测试语句需要可以精准的、直观的测试出返回的response是否符合预期,你的测试需要着眼于关键点。

状态码测试:

1
2
3
pm.test("Status code is 200", function () {
pm.response.to.have.status(200);
});

第一行中的”Status code is 200”是可以自己修改的,这一行字符串会在下面的控制台输出(可参照上图),这里建议要取一些有意义的字符串,可以见名知义那种。

第二行中的 200,就是你期望得到的状态码。

是否得到认证的测试:

第二行就是定义jsonData接受response中json数据,然后就是进行判断返回的字段是否是预期的。

1
2
3
4
pm.test("Your test user is authenticated", function () {
var jsonData = pm.response.json();
pm.expect(jsonData.authenticated).to.eql(true);
});

那么对比验证一下认证失败的情况:

我随便的设置了登录的用户名和密码,可以看到下方的Test results中3条都fail了,并且还有返回值的对比说明。

希望以上能对大家有所帮助。

如何在spring security中对用户密码进行加密

最近在实践中接触了spring security密码加密的相关内容。

以前在数据库中存入用户密码的时侯,选择的都是明文密码,没有任何的安全性,这种方式其实非常的危险。所以我们需要在用户注册时就对用户键入的密码进行加密,然后存储到数据库中。之后在用户登录的时候再对数据中的加密密码和用户键入的密码进行一个对比的验证。

这里不推荐使用spring security自带的PasswordEncoder方法进行加密,因为这样很容易被破解掉。推荐编写自己的加密方法,可以选择SHA-1,SHA-256等算法,然后也可以在密码加密之前中加入盐值salt。然后写自己的MyPasswordEncoder方法然后重写PasswordEncoder,实现encode,matches方法。

spring security自带的PasswordEncoder方法如下所示:

1
2
3
4
5
public interface PasswordEncoder {

String encode(CharSequence rawPassword);

boolean matches(CharSequence rawPassword, String encodedPassword);

我们可以看到这个PasswordEncoder接口有两个方法,encode的方法是加密,matches方法是比较初始密码加密后是否等于加密后的密码。

下面展示一个小的例子:新建自己的MyPasswordEncoder方法实现PasswordEncoder接口中的两个方法,这里我就写了一个encode的方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class MyPasswordEncoder implements PasswordEncoder {

//加密算法
private static MyDigestAlgorithm myDigestAlgorithm;

String encodedPassword = "";
// add salt
String saltedPassword = Common.SALT + rawPassword.toString();
try {
//encrypt the password
encodedPassword = MyDigestAlgorithm.toHexString(MyAlgorithm.getSHA(saltedPassword));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}

return encodedPassword;
}
}
}

有了加密方法之后,就可以在service编写业务代码:简单来说就是,存入数据库之前把用户键入的密码加密,然后再存入数据库。例子如下所示:

1
2
3
4
5
6
public void addAccounts(Account account) {

account.setPassword(myPasswordEncoder.encode(account.getPassword()));
accountMapper.addAccounts(account);

}

因为我们是自己重写的PasswordEncoder方法,所以在spring security的config中,需要注入我们的加密类,否则登陆的时候就会认证失败。例子如下:

1
2
3
4
5
@Bean
public MyPasswordEncoder myPasswordEncoder(){

return new MyPasswordEncoder();
}

希望能对您有所帮助。

matlab运行速度优化

当我们需要处理较大数据量,或者程序中有一些较为复杂的逻辑。这个时候就需要对程序进行一定的优化,以下是一些小技巧与例子的展示。

硬件方面

1.提升电脑的配置

2.在Matlab软件中设置,分配更多的运行内存

代码方面:

  1. 数据格式double转成single

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    A_length = length(A);
    numbers = 50;
    for k = 1:numbers
    for i = 1:A_length
    for j = 1:A_length
    A(i,j) = A(i,j)*rand;
    end
    end
    end


    矩阵维度:1000*1000
    double:时间已过 1.700172 秒
    single:时间已过 1.546184 秒。

    矩阵维度:5000*5000
    double:时间已过 50.057981 秒。
    single:时间已过 45.139951 秒。
  1. 避免for循环

    code1:

    1
    2
    3
    4
    5
    6
    7
    y =[];
    number = 100000;
    for i =1:number
    y = [y sin(i)];
    end

    % 时间已过 2.749184 秒。

    code2:

    1
    2
    3
    4
    y =[];
    number = 100000;
    y = sin([1:1:number]);
    时间已过 0.001548 秒。
  1. 预先声明变量长度

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    number = 1000; %5000
    %%新建一个矩阵
    %这一句就是原先声明变量的长度
    A = zeros([number number]);

    for i =1:number
    for j =1:number
    if rand >0.5
    A(i,j) = 1;
    end
    end
    end


    1000*1000
    未声明:时间已过 0.237895 秒。
    已声明:时间已过 0.041581 秒。

    5000*5000
    未声明:时间已过 41.466290 秒。
    已声明:时间已过 0.962321 秒。

经过测试,可以看到预先分配数组的大小和避免使用for循环对运行速度的提升效果是非常好的,特别是当数据量越大的时候,效果也就越好。

希望对大家有所帮助。

解决centos7下报错:net/http: TLS handshake timeout

最近在使用CentOS 7按照官方网站的文档安装docker时遇到了一个问题:

当我运行这一句时

1
sudo docker run hello-world

出现了bug:

1
net/http: TLS handshake timeout

解决方案:

配置镜像,修改 /etc/docker/daemon.json 文件,如果没有可以新建一个文件,然后加入以下的docker镜像地址:

1
2
3
4
5
6
{
"registry-mirrors": [
"https://dockerhub.azk8s.cn",
"https://hub-mirror.c.163.com"
]
}

保存退出
然后重启docker

1
sudo systemctl restart docker

这里可以检查一下配置的镜像是否生效:

1
docker info

如果显示的配置信息的末尾部分出现如下字样,说明配置完成:

镜像字样示例

再次运行:

1
sudo docker run hello-world

出现以下的信息,证明问题已经解决了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/

For more examples and ideas, visit:
https://docs.docker.com/get-started/
© 2025 Three purple's blog All Rights Reserved. 本站总访客数 加载中... 人 | 本站总访问量 加载中...
Theme by hiero