01 / 看一轮计算改变什么
下图直接代表可用的不完整图 Gδ,有 6 个节点、5 条无向边。节点 5 是孤立节点。此页不生成完整图或传播快照。
已执行迭代
0
得分总和
1.000000
相邻向量 L1 差
尚未更新
初始分数均为 1/6。请先计算到收敛,再看正式的传感器选择。
02 / 改变预算,不重算得分
这是便于看清前缀的数量控件;正式实验按 m=ceil(ρn) 选择 5%/10%/15% 等预算。m 沿用 SDSI/SDSA 的传感器数量记号;本页并非正式实验预算网格。
优先顺序:
所选集合:
滑动 m 后,“已执行迭代”不会增加。改变的只是同一排序的前缀;中间迭代的排序仅作演示,实际代码先收敛再选点。
得分降序;精确同分时按整数节点 ID 升序。本页表格显示六位小数,显示相同不一定表示底层数值精确相同。
03 / 一轮更新:不是传播了一轮谣言
每个节点的新分数 = 0.85 ×(邻居分来的分数 + 孤立节点总分 / 6)+ 0.15 / 6
无向边两端都能传递排名分数:一个非孤立节点把旧分数平均分给它的邻居。孤立节点没有可沿用的边,其旧分数按均匀规则重新分配。最后每个节点都加上均匀跳转项。所有新分数都用同一份旧向量计算,不能更新一个节点后立刻拿它的新分数去算下一个节点。
这里没有感染状态、真实源、发送者或感染时间戳。迭代计算的是随机游走模型的稳定得分;本项目调用的数值求解没有实际抽样一批随机游走或 SI 级联。
数学记号固定 c=0.85,对应 NetworkX 参数 alpha=0.85;停止条件与本机 NetworkX 3.2.1 稀疏实现对应:相邻向量 L1 差 < n×10⁻⁶,最多 100 轮。浮点运算顺序可能与 SciPy 不同,因此本页用于解释,不作为正式结果复算程序。
04 / 代码中的三步
pr_sd/runner.py → _pagerank_sequence
scores = nx.pagerank(graph, alpha=PAGERANK_ALPHA)
ranked = sorted(scores,
key=lambda node_id: (-scores[node_id], node_id))
return [int(value) for value in ranked[:sensor_count]], ...
① nx.pagerank:构造稀疏转移关系并迭代算分,主要为 O(TPR(n+|Eδ|))。
② sorted:对 n 个节点完整比较排序,为 O(n log n)。一次排序也不是线性时间。
③ 前缀:切片、转换 m 个节点,为 O(m)。因为 m≤n,主复杂度式中可被其他项吸收。
总成本:O(TPR(n+|Eδ|) + n log n)
TPR 是实际迭代轮数;|Eδ| 是不完整图边数,m 专门表示传感器数。这里是算法工作量的量级,不能直接换算成秒。
05 / MC 为什么要随 m 重复?
core/parallel.py → _observer_parallel_impl 的教学简写:
while placed < sensor_count:
# 本轮一共 N_MC 次,不是每个候选各 N_MC 次
results = run_batches(total=N_MC)
counts = sum_node_coverage_counts(results)
new_sensor = argmax(counts among eligible nodes)
mark_sensor(new_sensor)
placed += 1
每一轮通过一批 SI 模拟汇总节点覆盖计数,只选一个新传感器。下一轮已选集合发生变化,再进行一批模拟。
若沿用 NMC=800,当前教学 m=2 需要 1600 次部署传播模拟。这里仅计算调用次数,不实际运行 MC,也不是正式网络实测耗时。
主要模拟工作量:O(m NMC (n+|Eδ|))
部署模拟在 Gδ 上运行;还包含计数汇总、选点、图准备和并行管理开销。workers 可以缩短墙钟时间,不会把总模拟次数变成 800。