如何用NetworkX将多关系图通过Levi变换转为二部图?
实现多关系图到二部图的Levi变换(NetworkX)
可以通过以下简洁高效的方式完成Levi变换,将带谓词标签的边转换为连接实体与谓词节点的无标签边:
核心思路
- 新建有向图(保留原图方向性)作为转换后的二部图载体
- 复制原图中所有实体节点及其属性
- 提取所有谓词标签作为新节点加入二部图
- 将每条原边
(s, o, p)拆解为两条无标签边(s, p)和(p, o)
代码实现
修正原图构建(多关系图建议用MultiDiGraph)
原代码使用DiGraph无法保留同一实体对间的多条不同关系边,改用MultiDiGraph才能正确存储多关系结构:
import networkx as nx # 构建多关系图 amr_graph = nx.MultiDiGraph() for node_id, node_string in amr.nodes.items(): amr_graph.add_node(node_id, name=node_string) for subj, pred, obj in amr.edges: amr_graph.add_edge(subj, obj, key=pred)
执行Levi变换
# 创建转换后的二部图 levi_graph = nx.DiGraph() # 批量复制所有实体节点及属性 levi_graph.add_nodes_from(amr_graph.nodes(data=True)) # 提取所有谓词并添加为新节点(标记类型便于区分实体与关系) all_predicates = {p for s, o, p in amr_graph.edges(keys=True)} levi_graph.add_nodes_from(all_predicates, type="predicate") # 批量生成并添加转换后的边 levi_graph.add_edges_from( pair for s, o, p in amr_graph.edges(keys=True) for pair in [(s, p), (p, o)] )
补充说明
- 转换后的图通过节点属性
type="predicate"区分谓词节点与实体节点,可直接使用NetworkX的二部图工具模块处理 - 批量操作(
add_nodes_from、add_edges_from)比循环单条添加更高效,代码也更简洁
内容的提问来源于stack exchange,提问作者GiacomoFrisoni
相关产品推荐
相关产品推荐

