【发布时间】:2022-01-29 03:56:07
【问题描述】:
有什么方法可以在 python 中获取 graphviz 中的边列表。在我的程序中,我想在有向图中添加边之前检查节点之间是否已经存在边。我在 python 的 grahviz 中找不到像 get_edge() 或 has_connected() 这样的函数。有没有其他方法可以完成上述任务?任何帮助将不胜感激。
【问题讨论】:
标签: python python-3.x python-2.7 graphviz
有什么方法可以在 python 中获取 graphviz 中的边列表。在我的程序中,我想在有向图中添加边之前检查节点之间是否已经存在边。我在 python 的 grahviz 中找不到像 get_edge() 或 has_connected() 这样的函数。有没有其他方法可以完成上述任务?任何帮助将不胜感激。
【问题讨论】:
标签: python python-3.x python-2.7 graphviz
如果您的目标是避免重复边缘,请使用 Digraph(strict=True) 或 Graph(strict=True)
【讨论】:
我刚刚遇到了这个问题。我在源代码中看不到任何表明检查边是否在图中的便捷方法的内容。
如果您正在处理一个非常简单的图表,那么这可能会有所帮助。
def has_edge(graph, v1, v2):
tail_name = graph._quote_edge(v1)
head_name = graph._quote_edge(v2)
return (graph._edge % (tail_name, head_name, '')) in graph.body
我从 graphviz/dot.py 中的 'edge()' 方法改编了这个。它不处理任何属性。
据我所知,graph.body 是代表节点和边的字符串列表。
【讨论】:
这里是get_edges,用于获取给定 graphviz 有向图(或图)的边列表。
该图可以表示为BaseGraph 或Source 对象,或者只是源字符串。但默认它会返回节点 ID 对(字符串),但你可以告诉 get_edges 给你任何东西(包括 pydot.Edge 对象本身,包含它的所有属性。
from typing import Tuple, List, Iterable
from pydot import Dot, graph_from_dot_data, Edge
from graphviz.graphs import BaseGraph
from graphviz import Source
def edge_to_node_ids(edge: Edge) -> Tuple[str, str]:
"""Returns the node id pair for the edge object"""
return (edge.get_source(), edge.get_destination())
def get_graph_dot_obj(graph_spec) -> List[Dot]:
"""Get a dot (graphs) object list from a variety of possible sources (postelizing inputs here)"""
_original_graph_spec = graph_spec
if isinstance(graph_spec, (BaseGraph, Source)):
# get the source (str) from a graph object
graph_spec = graph_spec.source
if isinstance(graph_spec, str):
# get a dot-graph from dot string data
graph_spec = graph_from_dot_data(graph_spec)
# make sure we have a list of Dot objects now
assert isinstance(graph_spec, list) and all(
isinstance(x, Dot) for x in graph_spec
), (
f"Couldn't get a proper dot object list from: {_original_graph_spec}. "
f"At this point, we should have a list of Dot objects, but was: {graph_spec}"
)
return graph_spec
def get_edges(graph_spec, postprocess_edges=edge_to_node_ids):
"""Get a list of edges for a given graph (or list of lists thereof).
If ``postprocess_edges`` is ``None`` the function will return ``pydot.Edge`` objects from
which you can extract any information you want.
By default though, it is set to extract the node pairs for the edges, and you can
replace with any function that takes ``pydot.Edge`` as an input.
"""
graphs = get_graph_dot_obj(graph_spec)
n_graphs = len(graphs)
if n_graphs > 1:
return [get_edges(graph, postprocess_edges) for graph in graphs]
elif n_graphs == 0:
raise ValueError(f"Your input had no graphs")
else:
graph = graphs[0]
edges = graph.get_edges()
if callable(postprocess_edges):
edges = list(map(postprocess_edges, edges))
return edges
测试:
digraph_dot_source = """
DIGRAPH{
rain -> traffic
rain -> wet
traffic, wet -> moody
}
"""
assert (
get_edges(digraph_dot_source)
== get_edges(Source(digraph_dot_source))
== [('rain', 'traffic'), ('rain', 'wet'), ('wet', 'moody')]
)
graph_dot_source = """
GRAPH{
rain -- traffic
rain -- wet
traffic, wet -- moody
}
"""
assert (
get_edges(graph_dot_source)
== get_edges(Source(graph_dot_source))
== [('rain', 'traffic'), ('rain', 'wet'), ('wet', 'moody')]
)
【讨论】: