查找路径列表中两条相似度最低的路径,networkX内置方法无法满足需求
两条最低相似度路径筛选实现方案
1. 先定义路径相似度度量规则
你可以根据业务对节点/边重合的敏感程度,选择以下任意一种常用度量方式,相似度数值越低代表两条路径差异越大:
- 边Jaccard相似度(最常用,适合对路径走向重合敏感的场景):
公共边数量 / 两条路径去重后的总边数 - 节点Jaccard相似度(适合对经过的节点重合敏感的场景):
公共节点数量 / 两条路径去重后的总节点数 - 路径编辑距离(适合对路径序列顺序敏感的场景):将路径转为序列计算Levenshtein距离,数值越大差异越大
2. 实现方案(路径数量较少时直接暴力枚举,性能足够)
你通过nx.shortest_simple_paths获取的路径数量通常不会很大(默认返回按长度升序的路径,一般业务场景下取前几十条足够),直接枚举所有两两组合计算相似度,选出最低的一对即可,实现代码如下:
import itertools # 示例路径列表 path_list = [ ["T1", "E1B", "E2B", "ACD6B", "DE6", "T3"], ["T1", "E1B", "ACD3B", "ACD6B", "DE6", "T3"], ["T1", "E1B", "ACD3B", "DE2", "DE4", "DE6", "T3"], ["T1", "E1B", "E2B", "ACD6B", "ACD3B", "DE2", "DE4", "DE6", "T3"] ] # 辅助函数:将路径转为边集合 def path_to_edges(path): return set(zip(path[:-1], path[1:])) # 计算两条路径的边Jaccard相似度 def calc_edge_jaccard(path1, path2): edges1 = path_to_edges(path1) edges2 = path_to_edges(path2) intersect = len(edges1 & edges2) union = len(edges1 | edges2) return intersect / union if union != 0 else 0 # 枚举所有两两路径组合,找相似度最低的一对 min_similarity = float('inf') best_pair = None for (idx1, p1), (idx2, p2) in itertools.combinations(enumerate(path_list), 2): sim = calc_edge_jaccard(p1, p2) if sim < min_similarity: min_similarity = sim best_pair = (p1, p2) print("相似度最低的两条路径:") print(best_pair[0]) print(best_pair[1]) print("相似度值:", min_similarity)
运行结果说明
针对你给出的示例路径列表,最终会筛选出以下两条差异最大的路径:
['T1', 'E1B', 'E2B', 'ACD6B', 'DE6', 'T3'] ['T1', 'E1B', 'ACD3B', 'DE2', 'DE4', 'DE6', 'T3']
两者边Jaccard相似度仅为0.22,是所有组合中最低的。
3. 大路径量场景优化
如果你的路径列表超过100条,暴力枚举的时间复杂度为O(n²),可以改用局部敏感哈希(LSH)做近似查询,降低计算成本。
内容的提问来源于stack exchange,提问作者Umair Shahid
相关产品推荐
相关产品推荐

