邻接矩阵实现HITS算法时err_bound终止条件陷入死循环如何解决
HITS算法误差阈值终止条件死循环问题修复方案
以下是可直接排查解决问题的bug点和修复方案:
- bug1:done数组赋值错误
原代码中done[i] == true是相等比较操作,没有实际赋值效果,导致done数组所有元素永远保持初始的false,终止判断永远不满足,直接触发死循环。需要修改为赋值操作done[i] = true。 - bug2:hub历史值赋值错误
迭代收尾更新上一轮值的代码中,hub_t_1[i] = auth_t[i]错误地将当前轮的权威值赋值给了枢纽值的历史缓存,后续迭代的枢纽值计算完全错误,误差永远无法收敛到阈值内。需要修改为hub_t_1[i] = hub_t[i]。 - bug3:归一化系数未重置
auth_scale和hub_scale两个归一化系数没有在每轮迭代开始时重置为0,每轮迭代都会在上一轮的基础上累加数值,导致归一化逻辑完全失效,计算出的authority和hub值偏离正常值,无法收敛。需要在每轮while循环开始时将两个变量重置为0。 - bug4:done数组未每轮重置
done数组只在进入err分支时初始化了一次,后续迭代不会重置,只要某一轮某个节点满足误差要求,后续哪怕数值波动也会保持true状态,终止判断逻辑错误。需要在每轮while循环开始时重置done数组全为false。 - bug5:终止判断逻辑冗余混乱
goto和while嵌套的逻辑完全没必要,且t的计数位置错误,只有遇到不满足条件的节点才会计数,无法正确统计迭代次数。可以简化终止判断逻辑,去掉goto语句。
修复后代码片段
else if (err_bound == true){ int t = 0; std::fill (auth_t_1.begin(), auth_t_1.end(), iter0); std::fill (hub_t_1.begin(), hub_t_1.end(), iter0); stop = false; while (!stop){ // 每轮迭代重置变量 t++; auth_scale = 0; hub_scale = 0; // 计算本轮未归一化的auth和hub for (int i = 0; i < auth_t.size(); i++){ auth_t[i] = product(hub_t_1, transpose(this->node), i); hub_t[i] = product(auth_t, node, i); auth_scale += std::pow(auth_t[i],2); hub_scale += std::pow(hub_t[i],2); } // 归一化 for (int i = 0; i < auth_t.size(); i++){ auth_t[i] = auth_t[i]/std::sqrt(auth_scale); hub_t[i] = hub_t[i]/std::sqrt(hub_scale); } // 检查所有节点是否都满足误差要求 bool all_converged = true; for (int i = 0; i < auth_t.size(); i++){ double auth_diff = abs(auth_t[i] - auth_t_1[i]); double hub_diff = abs(hub_t[i] - hub_t_1[i]); if (auth_diff >= err || hub_diff >= err){ all_converged = false; break; } } // 所有节点收敛则终止,否则更新历史值继续迭代 if (all_converged) { stop = true; } else { for (int i = 0; i < auth_t.size(); i++){ auth_t_1[i] = auth_t[i]; hub_t_1[i] = hub_t[i]; } } } // 迭代结束输出结果 std::cout << "Iter : " << t << "\n"; for (int i = 0; i < N; i++){ std::cout << "A/H[" << i << "]=" << auth_t[i] << "/" << hub_t[i] << " " << "\n"; } }
内容的提问来源于stack exchange,提问作者CodingwithHieroglyphics
相关产品推荐
相关产品推荐

