有没有办法在Python中获取Graphviz图中边的列表。在我的程序中,我想在向有向图添加边之前检查节点之间是否已经存在边。我在Python的Grahviz中找不到像
get_edge()
或has_connected()
函数这样的函数。有其他做上述任务的方法吗?感谢您的帮助。get_edge()
或has_connected()
函数这样的函数。有其他做上述任务的方法吗?感谢您的帮助。如果您的目标是避免重复的边,则使用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
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')]
)