diff --git a/go/internal/governance/graph_sqlite.go b/go/internal/governance/graph_sqlite.go index f667710..4d44609 100644 --- a/go/internal/governance/graph_sqlite.go +++ b/go/internal/governance/graph_sqlite.go @@ -941,21 +941,26 @@ func (gs *SQLiteGraphStore) PageRank(damping float64, iterations int) map[string } for iter := 0; iter < iterations; iter++ { - newRanks := make(map[string]float64) - for _, node := range nodes { - rank := base - for src, edges := range outEdges { - totalWt := 0.0 - for _, e := range edges { - totalWt += e.weight - } - for _, e := range edges { - if e.target == node && totalWt > 0 { - rank += damping * ranks[src] * e.weight / totalWt - } - } + // 正确 PageRank 实现 O(V+E):先归一化每个源节点总权重, + // 再沿出边把贡献直接累加到目标节点(旧实现每目标遍历全源 O(V²), + // 17628 节点 × 20 迭代 = 6.2 亿次 → 3 分钟;现在亚秒级) + contrib := make(map[string]float64, len(outEdges)) + for src, edges := range outEdges { + totalWt := 0.0 + for _, e := range edges { + totalWt += e.weight } - newRanks[node] = rank + if totalWt <= 0 { + continue + } + share := damping * ranks[src] / totalWt + for _, e := range edges { + contrib[e.target] += share * e.weight + } + } + newRanks := make(map[string]float64, len(nodes)) + for _, node := range nodes { + newRanks[node] = base + contrib[node] } ranks = newRanks }